2020-09-01 14:07:48 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# pragma once
# include "CoreMinimal.h"
2021-11-23 09:42:40 -05:00
# include "BaseTools/MultiSelectionMeshEditingTool.h"
2020-09-01 14:07:48 -04:00
# include "InteractiveToolBuilder.h"
2021-06-13 00:36:02 -04:00
# include "DynamicMesh/DynamicMesh3.h"
2020-09-01 14:07:48 -04:00
# include "SphereTypes.h"
# include "OrientedBoxTypes.h"
# include "CapsuleTypes.h"
# include "Physics/CollisionPropertySets.h"
2022-04-19 15:48:15 -04:00
# include "Physics/PhysicsDataCollection.h"
2021-06-20 17:01:49 -04:00
# include "PropertySets/PolygroupLayersProperties.h"
# include "Polygroups/PolygroupSet.h"
2022-04-19 15:48:15 -04:00
# include "ModelingOperators.h"
# include "MeshOpPreviewHelpers.h"
2020-09-01 14:07:48 -04:00
# include "SetCollisionGeometryTool.generated.h"
class UPreviewGeometry ;
2021-03-09 19:33:56 -04:00
PREDECLARE_GEOMETRY ( class FMeshSimpleShapeApproximation )
PREDECLARE_USE_GEOMETRY_CLASS ( FDynamicMesh3 ) ;
2020-09-01 14:07:48 -04:00
UCLASS ( )
2021-11-23 09:42:40 -05:00
class MESHMODELINGTOOLSEXP_API USetCollisionGeometryToolBuilder : public UMultiSelectionMeshEditingToolBuilder
2020-09-01 14:07:48 -04:00
{
GENERATED_BODY ( )
public :
virtual bool CanBuildTool ( const FToolBuilderState & SceneState ) const override ;
2021-11-23 09:42:40 -05:00
virtual UMultiSelectionMeshEditingTool * CreateNewTool ( const FToolBuilderState & SceneState ) const override ;
2021-03-11 11:40:03 -04:00
protected :
2021-11-23 09:42:40 -05:00
virtual const FToolTargetTypeRequirements & GetTargetRequirements ( ) const override ;
2020-09-01 14:07:48 -04:00
} ;
UENUM ( )
enum class ESetCollisionGeometryInputMode
{
CombineAll = 0 ,
PerInputObject = 1 ,
PerMeshComponent = 2 ,
PerMeshGroup = 3
} ;
UENUM ( )
enum class ECollisionGeometryType
{
KeepExisting = 0 ,
AlignedBoxes = 1 ,
OrientedBoxes = 2 ,
MinimalSpheres = 3 ,
Capsules = 4 ,
ConvexHulls = 5 ,
SweptHulls = 6 ,
2022-05-30 16:48:48 -04:00
LevelSets = 7 ,
2020-09-01 14:07:48 -04:00
MinVolume = 10 ,
None = 11
} ;
UENUM ( )
enum class EProjectedHullAxis
{
X = 0 ,
Y = 1 ,
Z = 2 ,
SmallestBoxDimension = 3 ,
SmallestVolume = 4
} ;
UCLASS ( )
2021-07-29 20:08:48 -04:00
class MESHMODELINGTOOLSEXP_API USetCollisionGeometryToolProperties : public UInteractiveToolPropertySet
2020-09-01 14:07:48 -04:00
{
GENERATED_BODY ( )
public :
UPROPERTY ( EditAnywhere , Category = Options )
ECollisionGeometryType GeometryType = ECollisionGeometryType : : AlignedBoxes ;
UPROPERTY ( EditAnywhere , Category = Options )
ESetCollisionGeometryInputMode InputMode = ESetCollisionGeometryInputMode : : PerInputObject ;
UPROPERTY ( EditAnywhere , Category = Options )
bool bUseWorldSpace = false ;
UPROPERTY ( EditAnywhere , Category = Options )
bool bRemoveContained = true ;
UPROPERTY ( EditAnywhere , Category = Options )
bool bEnableMaxCount = true ;
2021-05-09 18:24:46 -04:00
UPROPERTY ( EditAnywhere , Category = Options , meta = ( UIMin = " 1 " , UIMax = " 100 " , ClampMin = " 1 " , ClampMax = " 9999999 " , EditCondition = " bEnableMaxCount " ) )
2020-09-01 14:07:48 -04:00
int32 MaxCount = 50 ;
UPROPERTY ( EditAnywhere , Category = Options , AdvancedDisplay )
float MinThickness = 0.01 ;
UPROPERTY ( EditAnywhere , Category = AutoDetect )
bool bDetectBoxes = true ;
UPROPERTY ( EditAnywhere , Category = AutoDetect )
bool bDetectSpheres = true ;
UPROPERTY ( EditAnywhere , Category = AutoDetect )
bool bDetectCapsules = true ;
UPROPERTY ( EditAnywhere , Category = ConvexHulls , meta = ( EditConditionHides , EditCondition = " GeometryType == ECollisionGeometryType::ConvexHulls " ) )
bool bSimplifyHulls = true ;
UPROPERTY ( EditAnywhere , Category = ConvexHulls , meta = ( UIMin = " 4 " , UIMax = " 100 " , ClampMin = " 4 " , ClampMax = " 9999999 " ,
EditConditionHides , EditCondition = " GeometryType == ECollisionGeometryType::ConvexHulls " ) )
int32 HullTargetFaceCount = 20 ;
2022-04-01 16:04:37 -04:00
/** How many convex hulls can be used to approximate each mesh */
UPROPERTY ( EditAnywhere , Category = ConvexHulls , meta = ( UIMin = " 1 " , UIMax = " 100 " , ClampMin = " 1 " ,
EditConditionHides , EditCondition = " GeometryType == ECollisionGeometryType::ConvexHulls " ) )
int32 MaxHullsPerMesh = 1 ;
/** How much to search the space of possible decompositions beyond MaxHullsPerMesh; for larger values, will do additional work to try to better approximate mesh features (but resulting hulls may overlap more) */
UPROPERTY ( EditAnywhere , Category = ConvexHulls , meta = ( UIMin = " 0 " , UIMax = " 2 " , ClampMin = " 0 " ,
EditConditionHides , EditCondition = " GeometryType == ECollisionGeometryType::ConvexHulls && MaxHullsPerMesh > 1 " ) )
float ConvexDecompositionSearchFactor = .5 ;
/** Error tolerance for adding more convex hulls, in cm. For volumetric errors, the value will be cubed (so a value of 10 indicates a 10x10x10 volume worth of error is acceptable). */
UPROPERTY ( EditAnywhere , Category = ConvexHulls , meta = ( UIMin = " 0 " , UIMax = " 1000 " , ClampMin = " 0 " ,
EditConditionHides , EditCondition = " GeometryType == ECollisionGeometryType::ConvexHulls && MaxHullsPerMesh > 1 " ) )
float AddHullsErrorTolerance = 0 ;
2022-05-09 16:41:33 -04:00
/** Minimum part thickness for convex decomposition (in cm); hulls thinner than this will be merged into adjacent hulls, if possible. */
UPROPERTY ( EditAnywhere , Category = ConvexHulls , meta = ( UIMin = " 0 " , UIMax = " 1 " , ClampMin = " 0 " ,
EditConditionHides , EditCondition = " GeometryType == ECollisionGeometryType::ConvexHulls && MaxHullsPerMesh > 1 " ) )
float MinPartThickness = 0.1 ;
2020-09-01 14:07:48 -04:00
UPROPERTY ( EditAnywhere , Category = SweptHulls , meta = ( EditConditionHides , EditCondition = " GeometryType == ECollisionGeometryType::SweptHulls " ) )
bool bSimplifyPolygons = true ;
UPROPERTY ( EditAnywhere , Category = SweptHulls , meta = ( UIMin = " 0 " , UIMax = " 10 " , ClampMin = " 0 " , ClampMax = " 100000 " ,
EditConditionHides , EditCondition = " GeometryType == ECollisionGeometryType::SweptHulls " ) )
float HullTolerance = 0.1 ;
UPROPERTY ( EditAnywhere , Category = SweptHulls , meta = ( UIMin = " 0 " , UIMax = " 10 " , ClampMin = " 0 " , ClampMax = " 100000 " ,
EditConditionHides , EditCondition = " GeometryType == ECollisionGeometryType::SweptHulls " ) )
EProjectedHullAxis SweepAxis = EProjectedHullAxis : : SmallestVolume ;
2022-05-30 16:48:48 -04:00
// Level Set settings
/** Level set grid resolution along longest grid axis */
UPROPERTY ( EditAnywhere , Category = LevelSets , meta = ( UIMin = " 3 " , UIMax = " 100 " , ClampMin = " 3 " , ClampMax = " 1000 " ,
EditConditionHides , EditCondition = " GeometryType == ECollisionGeometryType::LevelSets " ) )
int32 LevelSetResolution = 10 ;
2020-09-01 14:07:48 -04:00
UPROPERTY ( EditAnywhere , Category = OutputOptions )
bool bAppendToExisting = false ;
UPROPERTY ( EditAnywhere , Category = OutputOptions )
ECollisionGeometryMode SetCollisionType = ECollisionGeometryMode : : SimpleAndComplex ;
} ;
/**
* Mesh Inspector Tool for visualizing mesh information
*/
UCLASS ( )
2022-04-19 15:48:15 -04:00
class MESHMODELINGTOOLSEXP_API USetCollisionGeometryTool : public UMultiSelectionMeshEditingTool , public UE : : Geometry : : IGenericDataOperatorFactory < FPhysicsDataCollection >
2020-09-01 14:07:48 -04:00
{
GENERATED_BODY ( )
public :
virtual void Setup ( ) override ;
2022-01-28 18:40:54 -05:00
virtual void OnShutdown ( EToolShutdownType ShutdownType ) override ;
2020-09-01 14:07:48 -04:00
virtual void OnTick ( float DeltaTime ) override ;
virtual bool HasCancel ( ) const override { return true ; }
virtual bool HasAccept ( ) const override { return true ; }
2022-04-19 15:48:15 -04:00
virtual bool CanAccept ( ) const override
{
// allow accept when we're showing the current, valid result
return Super : : CanAccept ( ) & & bInputMeshesValid & & Compute & & Compute - > HaveValidResult ( ) & & ! bVisualizationDirty ;
}
// Begin IGenericDataOperatorFactory interface
virtual TUniquePtr < UE : : Geometry : : TGenericDataOperator < FPhysicsDataCollection > > MakeNewOperator ( ) override ;
// End IGenericDataOperatorFactory interface
2020-09-01 14:07:48 -04:00
protected :
UPROPERTY ( )
2021-07-20 00:24:38 -04:00
TObjectPtr < USetCollisionGeometryToolProperties > Settings = nullptr ;
2020-09-01 14:07:48 -04:00
2021-06-20 17:01:49 -04:00
UPROPERTY ( )
2021-07-20 00:24:38 -04:00
TObjectPtr < UPolygroupLayersProperties > PolygroupLayerProperties = nullptr ;
2020-09-01 14:07:48 -04:00
UPROPERTY ( )
2021-07-20 00:24:38 -04:00
TObjectPtr < UCollisionGeometryVisualizationProperties > VizSettings = nullptr ;
2020-09-01 14:07:48 -04:00
UPROPERTY ( )
2021-07-20 00:24:38 -04:00
TObjectPtr < UPhysicsObjectToolPropertySet > CollisionProps ;
2020-09-01 14:07:48 -04:00
2020-10-29 13:38:15 -04:00
UPROPERTY ( )
2021-07-20 00:24:38 -04:00
TObjectPtr < UMaterialInterface > LineMaterial = nullptr ;
2020-10-29 13:38:15 -04:00
2022-04-19 15:48:15 -04:00
//
// Background compute
//
TUniquePtr < TGenericDataBackgroundCompute < FPhysicsDataCollection > > Compute = nullptr ;
2020-09-01 14:07:48 -04:00
protected :
UPROPERTY ( )
2021-07-20 00:24:38 -04:00
TObjectPtr < UPreviewGeometry > PreviewGeom ;
2020-09-01 14:07:48 -04:00
TArray < int32 > SourceObjectIndices ;
bool bSourcesHidden = false ;
2021-06-20 17:01:49 -04:00
TArray < FDynamicMesh3 > InitialSourceMeshes ;
void OnInputModeChanged ( ) ;
2022-04-19 15:48:15 -04:00
/**
* Invalidates the background compute operator .
*/
void InvalidateCompute ( ) ;
2020-09-01 14:07:48 -04:00
enum class EDetectedCollisionGeometry
{
None ,
Sphere = 2 ,
Box = 4 ,
Capsule = 8 ,
Convex = 16
} ;
struct FSourceMesh
{
FDynamicMesh3 Mesh ;
EDetectedCollisionGeometry DetectedType = EDetectedCollisionGeometry : : None ;
2021-03-09 19:33:56 -04:00
UE : : Geometry : : FSphere3d DetectedSphere ;
UE : : Geometry : : FOrientedBox3d DetectedBox ;
UE : : Geometry : : FCapsule3d DetectedCapsule ;
2020-09-01 14:07:48 -04:00
} ;
bool bInputMeshesValid = false ;
2021-02-17 11:50:23 -04:00
TArray < TSharedPtr < FDynamicMesh3 , ESPMode : : ThreadSafe > > InputMeshes ;
TArray < TSharedPtr < FDynamicMesh3 , ESPMode : : ThreadSafe > > CombinedInputMeshes ;
TArray < TSharedPtr < FDynamicMesh3 , ESPMode : : ThreadSafe > > SeparatedInputMeshes ;
TArray < TSharedPtr < FDynamicMesh3 , ESPMode : : ThreadSafe > > PerGroupInputMeshes ;
2020-09-01 14:07:48 -04:00
2021-03-09 19:33:56 -04:00
TSharedPtr < UE : : Geometry : : FMeshSimpleShapeApproximation , ESPMode : : ThreadSafe > InputMeshesApproximator ;
TSharedPtr < UE : : Geometry : : FMeshSimpleShapeApproximation , ESPMode : : ThreadSafe > CombinedInputMeshesApproximator ;
TSharedPtr < UE : : Geometry : : FMeshSimpleShapeApproximation , ESPMode : : ThreadSafe > SeparatedMeshesApproximator ;
TSharedPtr < UE : : Geometry : : FMeshSimpleShapeApproximation , ESPMode : : ThreadSafe > PerGroupMeshesApproximator ;
2020-09-01 14:07:48 -04:00
void PrecomputeInputMeshes ( ) ;
void InitializeDerivedMeshSet (
2021-02-17 11:50:23 -04:00
const TArray < TSharedPtr < FDynamicMesh3 , ESPMode : : ThreadSafe > > & FromInputMeshes ,
TArray < TSharedPtr < FDynamicMesh3 , ESPMode : : ThreadSafe > > & ToMeshes ,
2020-09-01 14:07:48 -04:00
TFunctionRef < bool ( const FDynamicMesh3 * , int32 , int32 ) > TrisConnectedPredicate ) ;
2021-06-20 17:01:49 -04:00
TUniquePtr < UE : : Geometry : : FPolygroupSet > ActiveGroupSet ;
void OnSelectedGroupLayerChanged ( ) ;
void UpdateActiveGroupLayer ( ) ;
2020-09-01 14:07:48 -04:00
FTransform OrigTargetTransform ;
FVector TargetScale3D ;
2021-02-17 11:50:23 -04:00
TSharedPtr < FPhysicsDataCollection , ESPMode : : ThreadSafe > InitialCollision ;
TSharedPtr < FPhysicsDataCollection , ESPMode : : ThreadSafe > GeneratedCollision ;
2020-09-01 14:07:48 -04:00
bool bVisualizationDirty = false ;
void UpdateVisualization ( ) ;
} ;