// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "LidarPointCloud.h" #include "Components/MeshComponent.h" #include "LidarPointCloudComponent.generated.h" class UBodySetup; class FViewportClient; UENUM(BlueprintType) enum class ELidarPointCloudSpriteOrientation : uint8 { /** The sprites will face camera, even if Normals are available. */ PreferFacingCamera, /** The sprites will attempt to face Normals, if available, or fall back to facing camera otherwise. */ PreferFacingNormal, }; /** Component that allows you to render specified point cloud section */ UCLASS(ClassGroup=Rendering, ShowCategories = (Rendering), HideCategories = (Object, LOD, Physics, Activation, Materials, Cooking, Input, HLOD, Mobile), meta = (BlueprintSpawnableComponent)) class LIDARPOINTCLOUDRUNTIME_API ULidarPointCloudComponent : public UMeshComponent { GENERATED_BODY() private: UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Lidar Point Cloud", meta = (AllowPrivateAccess = "true")) TObjectPtr PointCloud; /** * Allows using custom-built material for the point cloud. * Set to None to use the default one instead. */ UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Material", meta = (AllowPrivateAccess = "true")) TObjectPtr CustomMaterial; public: /** * Use to tweak the size of the points. * Set to 0 to switch to 1 pixel points. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Appearance", meta = (ClampMin = "0.0")) float PointSize; /** Determines how the points will be scaled */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Appearance") ELidarPointCloudScalingMethod ScalingMethod; /** * If set to > 0, it attempts to close gaps between points. * Setting this too high may cause visual artifacts. * This setting may interfere with AO */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Appearance", meta = (ClampMin = "0.0")) float GapFillingStrength; /** Specifies which source to use for point colors. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Appearance") ELidarPointCloudColorationMode ColorSource; private: /** Affects the shape of points. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Appearance", BlueprintSetter = SetPointShape, meta = (AllowPrivateAccess = "true", DeprecatedProperty, DeprecationMessage="Use GetPointShape() / SetPointShape() instead.")) ELidarPointCloudSpriteShape PointShape; public: /** Affects the orientation of points. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Appearance") ELidarPointCloudSpriteOrientation PointOrientation; /** * Used with the Classification source. * Maps the given classification ID to a color. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Appearance") TMap ClassificationColors; /** Specifies the bottom color of the elevation-based gradient. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Appearance") FLinearColor ElevationColorBottom; /** Specifies the top color of the elevation-based gradient. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Appearance") FLinearColor ElevationColorTop; /** * Larger values will help mask LOD transition areas, but too large values will lead to loss of detail. * Values in range 0.035 - 0.05 seem to produce best overall results. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Appearance", meta = (ClampMin = "0.0", ClampMax = "0.15")) float PointSizeBias; UPROPERTY(interp, EditAnywhere, BlueprintReadWrite, Category = "Color Adjustment", meta = (UIMin = "0.0", UIMax = "2.0", Delta = "0.01", ColorGradingMode = "saturation")) FVector4 Saturation; UPROPERTY(interp, EditAnywhere, BlueprintReadWrite, Category = "Color Adjustment", meta = (UIMin = "0.0", UIMax = "2.0", Delta = "0.01", ColorGradingMode = "contrast")) FVector4 Contrast; UPROPERTY(interp, EditAnywhere, BlueprintReadWrite, Category = "Color Adjustment", meta = (UIMin = "0.0", UIMax = "2.0", Delta = "0.01", ColorGradingMode = "gamma")) FVector4 Gamma; /** Affects the emissive strength of the color. Useful to create Bloom and light bleed effects. */ UPROPERTY(interp, EditAnywhere, BlueprintReadWrite, Category = "Color Adjustment", meta = (UIMin = "0.0", UIMax = "1.0", Delta = "0.01", ColorGradingMode = "gain")) FVector4 Gain; /** Applied additively, 0 being neutral. */ UPROPERTY(interp, EditAnywhere, BlueprintReadWrite, Category = "Color Adjustment", meta = (UIMin = "-1.0", UIMax = "1.0", Delta = "0.001", ColorGradingMode = "offset", SupportDynamicSliderMaxValue = "true", SupportDynamicSliderMinValue = "true")) FVector4 Offset; /** Specifies the tint to apply to the points. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Color Adjustment") FLinearColor ColorTint; /** Specifies the influence of Intensity data, if available, on the overall color. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Color Adjustment", meta = (ClampMin = "0", ClampMax = "1")) float IntensityInfluence; /** * If enabled, points outside of the visible frustum will not be rendered. * While most project should leave this enabled, disabling it may help * with the data streaming lag when shooting cinematics. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Rendering") bool bUseFrustumCulling; /** * Minimum Depth from which the nodes should be rendered. * 0 to disable. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Rendering", meta = (ClampMin = "0")) int32 MinDepth; /** * Maximum Depth to which the nodes should be rendered. * -1 to disable. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Rendering") int32 MaxDepth; /** Enabling this will cause the visible nodes to render their bounds. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Rendering") bool bDrawNodeBounds; private: UPROPERTY(Transient) TObjectPtr Material; UPROPERTY(Transient) TObjectPtr BaseMaterial; UPROPERTY(Transient) TObjectPtr BaseMaterialMasked; /** Pointer to the viewport client of the owning editor, or null, if this is a game object. */ TWeakPtr OwningViewportClient; public: ULidarPointCloudComponent(); UFUNCTION(BlueprintPure, Category = "Components|LidarPointCloud") ULidarPointCloud* GetPointCloud() const { return PointCloud; } FORCEINLINE TWeakPtr GetOwningViewportClient() const { return OwningViewportClient; } FORCEINLINE bool IsOwnedByEditor() const { return OwningViewportClient.IsValid(); } /** Returns true if there are any points within the given sphere. */ UFUNCTION(BlueprintPure, Category = "Lidar Point Cloud") bool HasPointsInSphere(FVector Center, float Radius, bool bVisibleOnly) const { return HasPointsInSphere(FSphere(Center, Radius), bVisibleOnly); } bool HasPointsInSphere(const FSphere& Sphere, bool bVisibleOnly) const { return PointCloud && PointCloud->HasPointsInSphere(Sphere.TransformBy(GetComponentTransform().Inverse()), bVisibleOnly); } /** Returns true if there are any points within the given box. */ UFUNCTION(BlueprintPure, Category = "Lidar Point Cloud") bool HasPointsInBox(FVector Center, FVector Extent, bool bVisibleOnly) const { return HasPointsInBox(FBox(Center - Extent, Center + Extent), bVisibleOnly); } bool HasPointsInBox(const FBox& Box, bool bVisibleOnly) const { return PointCloud && PointCloud->HasPointsInBox(Box.TransformBy(GetComponentTransform().Inverse()), bVisibleOnly); } /** Returns true if there are any points hit by the given ray. */ UFUNCTION(BlueprintPure, Category = "Lidar Point Cloud") bool HasPointsByRay(FVector Origin, FVector Direction, float Radius, bool bVisibleOnly) const { return HasPointsByRay(FLidarPointCloudRay((FVector3f)Origin, (FVector3f)Direction), Radius, bVisibleOnly); } bool HasPointsByRay(const FLidarPointCloudRay& Ray, float Radius, bool bVisibleOnly) const { return PointCloud && PointCloud->HasPointsByRay(Ray.TransformBy(GetComponentTransform().Inverse()), Radius, bVisibleOnly); } /** Populates the array with the list of points within the given sphere. */ void GetPointsInSphere(TArray& SelectedPoints, const FVector& Center, const float& Radius, const bool& bVisibleOnly) { GetPointsInSphere(SelectedPoints, FSphere(Center, Radius), bVisibleOnly); } void GetPointsInSphere(TArray64& SelectedPoints, const FVector& Center, const float& Radius, const bool& bVisibleOnly) { GetPointsInSphere(SelectedPoints, FSphere(Center, Radius), bVisibleOnly); } void GetPointsInSphere(TArray& SelectedPoints, const FSphere& Sphere, const bool& bVisibleOnly) { if (PointCloud) { PointCloud->GetPointsInSphere(SelectedPoints, Sphere.TransformBy(GetComponentTransform().Inverse()), bVisibleOnly); } } void GetPointsInSphere(TArray64& SelectedPoints, const FSphere& Sphere, const bool& bVisibleOnly) { if (PointCloud) { PointCloud->GetPointsInSphere(SelectedPoints, Sphere.TransformBy(GetComponentTransform().Inverse()), bVisibleOnly); } } /** Populates the array with the list of points within the given box. */ void GetPointsInBox(TArray& SelectedPoints, const FVector& Center, const FVector& Extent, const bool& bVisibleOnly) { GetPointsInBox(SelectedPoints, FBox(Center - Extent, Center + Extent), bVisibleOnly); } void GetPointsInBox(TArray64& SelectedPoints, const FVector& Center, const FVector& Extent, const bool& bVisibleOnly) { GetPointsInBox(SelectedPoints, FBox(Center - Extent, Center + Extent), bVisibleOnly); } void GetPointsInBox(TArray& SelectedPoints, const FBox& Box, const bool& bVisibleOnly) { if (PointCloud) { PointCloud->GetPointsInBox(SelectedPoints, Box.TransformBy(GetComponentTransform().Inverse()), bVisibleOnly); } } void GetPointsInBox(TArray64& SelectedPoints, const FBox& Box, const bool& bVisibleOnly) { if (PointCloud) { PointCloud->GetPointsInBox(SelectedPoints, Box.TransformBy(GetComponentTransform().Inverse()), bVisibleOnly); } } /** * Populates the array with copies of points within the given sphere. * If ReturnWorldSpace is selected, the points' locations will be converted into absolute value, otherwise they will be relative to the center of the cloud. */ UFUNCTION(BlueprintCallable, Category = "Lidar Point Cloud") TArray GetPointsInSphereAsCopies(FVector Center, float Radius, bool bVisibleOnly, bool bReturnWorldSpace) { TArray Points; GetPointsInSphereAsCopies(Points, FSphere(Center, Radius), bVisibleOnly, bReturnWorldSpace); return Points; } void GetPointsInSphereAsCopies(TArray& SelectedPoints, const FSphere& Sphere, const bool& bVisibleOnly, const bool& bReturnWorldSpace) { if (PointCloud) { FTransform LocalToWorld = GetLocalToWorld(); PointCloud->Octree.GetPointsInSphereAsCopies(SelectedPoints, Sphere.TransformBy(LocalToWorld.Inverse()), bVisibleOnly, bReturnWorldSpace ? &LocalToWorld : nullptr); } } void GetPointsInSphereAsCopies(TArray64& SelectedPoints, const FSphere& Sphere, const bool& bVisibleOnly, const bool& bReturnWorldSpace) { if (PointCloud) { FTransform LocalToWorld = GetLocalToWorld(); PointCloud->Octree.GetPointsInSphereAsCopies(SelectedPoints, Sphere.TransformBy(LocalToWorld.Inverse()), bVisibleOnly, bReturnWorldSpace ? &LocalToWorld : nullptr); } } /** * Populates the array with copies of points within the given box. * If ReturnWorldSpace is selected, the points' locations will be converted into absolute value, otherwise they will be relative to the center of the cloud. */ UFUNCTION(BlueprintCallable, Category = "Lidar Point Cloud") TArray GetPointsInBoxAsCopies(FVector Center, FVector Extent, bool bVisibleOnly, bool bReturnWorldSpace) { TArray Points; GetPointsInBoxAsCopies(Points, FBox(Center - Extent, Center + Extent), bVisibleOnly, bReturnWorldSpace); return Points; } void GetPointsInBoxAsCopies(TArray& SelectedPoints, const FBox& Box, const bool& bVisibleOnly, const bool& bReturnWorldSpace) { if (PointCloud) { FTransform LocalToWorld = GetLocalToWorld(); PointCloud->Octree.GetPointsInBoxAsCopies(SelectedPoints, Box.TransformBy(LocalToWorld.Inverse()), bVisibleOnly, bReturnWorldSpace ? &LocalToWorld : nullptr); } } void GetPointsInBoxAsCopies(TArray64& SelectedPoints, const FBox& Box, const bool& bVisibleOnly, const bool& bReturnWorldSpace) { if (PointCloud) { FTransform LocalToWorld = GetLocalToWorld(); PointCloud->Octree.GetPointsInBoxAsCopies(SelectedPoints, Box.TransformBy(LocalToWorld.Inverse()), bVisibleOnly, bReturnWorldSpace ? &LocalToWorld : nullptr); } } /** Performs a raycast test against the point cloud. Returns the pointer if hit or nullptr otherwise. */ UFUNCTION(BlueprintPure, Category = "Lidar Point Cloud", meta = (Keywords = "raycast")) bool LineTraceSingle(FVector Origin, FVector Direction, float Radius, bool bVisibleOnly, FLidarPointCloudPoint& PointHit) { FLidarPointCloudPoint* Point = LineTraceSingle(FLidarPointCloudRay((FVector3f)Origin, (FVector3f)Direction), Radius, bVisibleOnly); if (Point) { PointHit = *Point; return true; } return false; } FLidarPointCloudPoint* LineTraceSingle(FLidarPointCloudRay Ray, float Radius, bool bVisibleOnly) { return PointCloud ? PointCloud->LineTraceSingle(Ray.TransformBy(GetComponentTransform().Inverse()), Radius, bVisibleOnly) : nullptr; } /** * Performs a raycast test against the point cloud. * Populates OutHits array with the results. * If ReturnWorldSpace is selected, the points' locations will be converted into absolute value, otherwise they will be relative to the center of the cloud. * Returns true it anything has been hit. */ UFUNCTION(BlueprintPure, Category = "Lidar Point Cloud", meta = (Keywords = "raycast")) bool LineTraceMulti(FVector Origin, FVector Direction, float Radius, bool bVisibleOnly, bool bReturnWorldSpace, TArray& OutHits) { return LineTraceMulti(FLidarPointCloudRay((FVector3f)Origin, (FVector3f)Direction).TransformBy(GetComponentTransform().Inverse()), Radius, bVisibleOnly, bReturnWorldSpace, OutHits); } bool LineTraceMulti(FLidarPointCloudRay Ray, float Radius, bool bVisibleOnly, bool bReturnWorldSpace, TArray& OutHits) { if (PointCloud) { FTransform LocalToWorld = GetLocalToWorld(); return PointCloud->Octree.RaycastMulti(Ray.TransformBy(LocalToWorld.Inverse()), Radius, bVisibleOnly, bReturnWorldSpace ? &LocalToWorld : nullptr, OutHits); } return false; } bool LineTraceMulti(FLidarPointCloudRay Ray, float Radius, bool bVisibleOnly, TArray& OutHits) { return PointCloud ? PointCloud->LineTraceMulti(Ray.TransformBy(GetComponentTransform().Inverse()), Radius, bVisibleOnly, OutHits) : false; } /** Sets visibility of points within the given sphere. */ UFUNCTION(BlueprintCallable, Category = "Lidar Point Cloud") void SetVisibilityOfPointsInSphere(bool bNewVisibility, FVector Center, float Radius) { SetVisibilityOfPointsInSphere(bNewVisibility, FSphere(Center, Radius)); } void SetVisibilityOfPointsInSphere(const bool& bNewVisibility, const FSphere& Sphere) { if (PointCloud) { PointCloud->SetVisibilityOfPointsInSphere(bNewVisibility, Sphere.TransformBy(GetComponentTransform().Inverse())); } } /** Sets visibility of points within the given box. */ UFUNCTION(BlueprintCallable, Category = "Lidar Point Cloud") void SetVisibilityOfPointsInBox(bool bNewVisibility, FVector Center, FVector Extent) { SetVisibilityOfPointsInBox(bNewVisibility, FBox(Center - Extent, Center + Extent)); } void SetVisibilityOfPointsInBox(const bool& bNewVisibility, const FBox& Box) { if (PointCloud) { PointCloud->SetVisibilityOfPointsInBox(bNewVisibility, Box.TransformBy(GetComponentTransform().Inverse())); } } /** Sets visibility of the first point hit by the given ray. */ UFUNCTION(BlueprintCallable, Category = "Lidar Point Cloud") void SetVisibilityOfFirstPointByRay(bool bNewVisibility, FVector Origin, FVector Direction, float Radius) { SetVisibilityOfFirstPointByRay(bNewVisibility, FLidarPointCloudRay((FVector3f)Origin, (FVector3f)Direction), Radius); } void SetVisibilityOfFirstPointByRay(bool bNewVisibility, FLidarPointCloudRay Ray, float Radius) { if (PointCloud) { PointCloud->SetVisibilityOfFirstPointByRay(bNewVisibility, Ray.TransformBy(GetComponentTransform().Inverse()), Radius); } } /** Sets visibility of points hit by the given ray. */ UFUNCTION(BlueprintCallable, Category = "Lidar Point Cloud") void SetVisibilityOfPointsByRay(bool bNewVisibility, FVector Origin, FVector Direction, float Radius) { SetVisibilityOfPointsByRay(bNewVisibility, FLidarPointCloudRay((FVector3f)Origin, (FVector3f)Direction), Radius); } void SetVisibilityOfPointsByRay(bool bNewVisibility, FLidarPointCloudRay Ray, float Radius) { if (PointCloud) { PointCloud->SetVisibilityOfPointsByRay(bNewVisibility, Ray.TransformBy(GetComponentTransform().Inverse()), Radius); } } /** Executes the provided action on each of the points within the given sphere. */ void ExecuteActionOnPointsInSphere(TFunction Action, const FVector& Center, const float& Radius, const bool& bVisibleOnly) { ExecuteActionOnPointsInSphere(MoveTemp(Action), FSphere(Center, Radius), bVisibleOnly); } void ExecuteActionOnPointsInSphere(TFunction Action, const FSphere& Sphere, const bool& bVisibleOnly) { if (PointCloud) { PointCloud->ExecuteActionOnPointsInSphere(MoveTemp(Action), Sphere.TransformBy(GetComponentTransform().Inverse()), bVisibleOnly); } } /** Executes the provided action on each of the points within the given box. */ void ExecuteActionOnPointsInBox(TFunction Action, const FVector& Center, const FVector& Extent, const bool& bVisibleOnly) { ExecuteActionOnPointsInBox(MoveTemp(Action), FBox(Center - Extent, Center + Extent), bVisibleOnly); } void ExecuteActionOnPointsInBox(TFunction Action, const FBox& Box, const bool& bVisibleOnly) { if (PointCloud) { PointCloud->ExecuteActionOnPointsInBox(MoveTemp(Action), Box.TransformBy(GetComponentTransform().Inverse()), bVisibleOnly); } } /** Executes the provided action on the first point hit by the given ray. */ void ExecuteActionOnFirstPointByRay(TFunction Action, FLidarPointCloudRay Ray, float Radius, bool bVisibleOnly) { if (PointCloud) { PointCloud->ExecuteActionOnFirstPointByRay(MoveTemp(Action), Ray.TransformBy(GetComponentTransform().Inverse()), Radius, bVisibleOnly); } } /** Executes the provided action on each of the points hit by the given ray. */ void ExecuteActionOnPointsByRay(TFunction Action, FLidarPointCloudRay Ray, float Radius, bool bVisibleOnly) { if (PointCloud) { PointCloud->ExecuteActionOnPointsByRay(MoveTemp(Action), Ray.TransformBy(GetComponentTransform().Inverse()), Radius, bVisibleOnly); } } /** Applies the given color to all points within the sphere */ UFUNCTION(BlueprintCallable, Category = "Lidar Point Cloud") void ApplyColorToPointsInSphere(FColor NewColor, FVector Center, float Radius, bool bVisibleOnly) { ApplyColorToPointsInSphere(NewColor, FSphere(Center, Radius), bVisibleOnly); } void ApplyColorToPointsInSphere(const FColor& NewColor, const FSphere& Sphere, const bool& bVisibleOnly) { if (PointCloud) { PointCloud->ApplyColorToPointsInSphere(NewColor, Sphere.TransformBy(GetComponentTransform().Inverse()), bVisibleOnly); } } /** Applies the given color to all points within the box */ UFUNCTION(BlueprintCallable, Category = "Lidar Point Cloud") void ApplyColorToPointsInBox(FColor NewColor, FVector Center, FVector Extent, bool bVisibleOnly) { ApplyColorToPointsInBox(NewColor, FBox(Center - Extent, Center + Extent), bVisibleOnly); } void ApplyColorToPointsInBox(const FColor& NewColor, const FBox& Box, const bool& bVisibleOnly) { if (PointCloud) { PointCloud->ApplyColorToPointsInBox(NewColor, Box.TransformBy(GetComponentTransform().Inverse()), bVisibleOnly); } } /** Applies the given color to the first point hit by the given ray */ UFUNCTION(BlueprintCallable, Category = "Lidar Point Cloud") void ApplyColorToFirstPointByRay(FColor NewColor, FVector Origin, FVector Direction, float Radius, bool bVisibleOnly) { ApplyColorToFirstPointByRay(NewColor, FLidarPointCloudRay((FVector3f)Origin, (FVector3f)Direction), Radius, bVisibleOnly); } void ApplyColorToFirstPointByRay(const FColor& NewColor, FLidarPointCloudRay Ray, float Radius, bool bVisibleOnly) { if (PointCloud) { PointCloud->ApplyColorToFirstPointByRay(NewColor, Ray.TransformBy(GetComponentTransform().Inverse()), Radius, bVisibleOnly); } } /** Applies the given color to all points hit by the given ray */ UFUNCTION(BlueprintCallable, Category = "Lidar Point Cloud") void ApplyColorToPointsByRay(FColor NewColor, FVector Origin, FVector Direction, float Radius, bool bVisibleOnly) { ApplyColorToPointsByRay(NewColor, FLidarPointCloudRay((FVector3f)Origin, (FVector3f)Direction), Radius, bVisibleOnly); } void ApplyColorToPointsByRay(const FColor& NewColor, FLidarPointCloudRay Ray, float Radius, bool bVisibleOnly) { if (PointCloud) { PointCloud->ApplyColorToPointsByRay(NewColor, Ray.TransformBy(GetComponentTransform().Inverse()), Radius, bVisibleOnly); } } /** Removes all points within the given sphere */ UFUNCTION(BlueprintCallable, Category = "Lidar Point Cloud") void RemovePointsInSphere(FVector Center, float Radius, bool bVisibleOnly) { RemovePointsInSphere(FSphere(Center, Radius), bVisibleOnly); } void RemovePointsInSphere(const FSphere& Sphere, const bool& bVisibleOnly) { if (PointCloud) { PointCloud->RemovePointsInSphere(Sphere.TransformBy(GetComponentTransform().Inverse()), bVisibleOnly); } } /** Removes all points within the given box */ UFUNCTION(BlueprintCallable, Category = "Lidar Point Cloud") void RemovePointsInBox(FVector Center, FVector Extent, bool bVisibleOnly) { RemovePointsInBox(FBox(Center - Extent, Center + Extent), bVisibleOnly); } void RemovePointsInBox(const FBox& Box, const bool& bVisibleOnly) { if (PointCloud) { PointCloud->RemovePointsInBox(Box.TransformBy(GetComponentTransform().Inverse()), bVisibleOnly); } } /** Removes the first point hit by the given ray */ UFUNCTION(BlueprintCallable, Category = "Lidar Point Cloud") void RemoveFirstPointByRay(FVector Origin, FVector Direction, float Radius, bool bVisibleOnly) { RemoveFirstPointByRay(FLidarPointCloudRay((FVector3f)Origin, (FVector3f)Direction), Radius, bVisibleOnly); } void RemoveFirstPointByRay(const FLidarPointCloudRay& Ray, const float& Radius, bool bVisibleOnly) { if (PointCloud) { PointCloud->RemoveFirstPointByRay(Ray.TransformBy(GetComponentTransform().Inverse()), Radius, bVisibleOnly); } } /** Removes all points hit by the given ray */ UFUNCTION(BlueprintCallable, Category = "Lidar Point Cloud") void RemovePointsByRay(FVector Origin, FVector Direction, float Radius, bool bVisibleOnly) { RemovePointsByRay(FLidarPointCloudRay((FVector3f)Origin, (FVector3f)Direction), Radius, bVisibleOnly); } void RemovePointsByRay(FLidarPointCloudRay Ray, float Radius, const bool& bVisibleOnly) { if (PointCloud) { PointCloud->RemovePointsByRay(Ray.TransformBy(GetComponentTransform().Inverse()), Radius, bVisibleOnly); } } #if WITH_EDITOR void SelectByConvexVolume(FConvexVolume ConvexVolume, bool bAdditive, bool bVisibleOnly); void SelectBySphere(FSphere Sphere, bool bAdditive, bool bVisibleOnly); void HideSelected(); void DeleteSelected(); void InvertSelection(); int64 NumSelectedPoints(); void GetSelectedPointsAsCopies(TArray64& SelectedPoints); void ClearSelection(); #endif public: UFUNCTION(BlueprintCallable, Category = "Components|LidarPointCloud") void SetPointCloud(ULidarPointCloud *InPointCloud); /** Returns the current Point Shape */ UFUNCTION(BlueprintPure, Category = "Components|LidarPointCloud") FORCEINLINE ELidarPointCloudSpriteShape GetPointShape() const { return PointShape; } /** Sets new Point Shape */ UFUNCTION(BlueprintCallable, Category = "Components|LidarPointCloud") void SetPointShape(ELidarPointCloudSpriteShape NewPointShape); /** Applies specified rendering parameters (Brightness, Saturation, etc) to the selected material */ UFUNCTION(BlueprintCallable, Category = "Components|LidarPointCloud|Rendering") void ApplyRenderingParameters(); public: // Begin UObject Interface. static void AddReferencedObjects(UObject* InThis, FReferenceCollector& Collector); virtual void PostLoad() override; // End UObject Interface. // End UMeshComponent Interface virtual int32 GetNumMaterials() const override { return 1; } virtual UMaterialInterface* GetMaterial(int32 ElementIndex) const override { return Material; } virtual void SetMaterial(int32 ElementIndex, UMaterialInterface* InMaterial) override; // End UMeshComponent Interface #if WITH_EDITOR virtual void PreEditChange(FProperty* PropertyThatWillChange) override; virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; virtual void PostEditImport() override { Super::PostEditImport(); // Make sure to update the material after duplicating this component UpdateMaterial(); } #endif virtual UBodySetup* GetBodySetup() override; /** Returns true if the component should be rendered facing normals */ bool ShouldRenderFacingNormals() const { return PointOrientation == ELidarPointCloudSpriteOrientation::PreferFacingNormal && PointSize > 0; } private: // Begin UPrimitiveComponent Interface virtual FPrimitiveSceneProxy* CreateSceneProxy() override; // End UMeshComponent Interface // Begin USceneComponent Interface virtual FBoxSphereBounds CalcBounds(const FTransform& LocalToWorld) const override; // End USceneComponent Interface FTransform GetLocalToWorld() { FTransform LocalToWorld = GetComponentTransform(); if (PointCloud) { LocalToWorld.AddToTranslation(PointCloud->LocationOffset); } return LocalToWorld; } void UpdateMaterial(); void AttachPointCloudListener(); void RemovePointCloudListener(); void OnPointCloudRebuilt(); void OnPointCloudCollisionUpdated(); void OnPointCloudNormalsUpdated(); void PostPointCloudSet(); friend class FPointCloudSceneProxy; #if WITH_EDITOR friend class SLidarPointCloudEditorViewport; #endif };