// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "Dataflow/DataflowEngine.h" #include "GeometryCollection/ManagedArrayCollection.h" #include "Engine/StaticMesh.h" #include "Engine/SkeletalMesh.h" #include "Dataflow/DataflowSelection.h" #include "ChaosFleshGenerateSurfaceBindingsNode.generated.h" class UStaticMesh; class USkeletalMesh; class UDynamicMesh; DECLARE_LOG_CATEGORY_EXTERN(LogMeshBindings, Verbose, All); /* Generate barycentric bindings (used by the FleshDeformer deformer graph and Geometry Cache generation) of a render surface to a tetrahedral mesh. * If a point is outside of the tetrahedral mesh, find surface embedding within SurfaceProjectionSearchRadius. Embeddings are color coded in the render view: green: embedded on in a tetrahedron blue: embedded on a surface triangle red: orphan (cannot be embedded) yellow: orphan reparented to a tetrahedron from a node neighbor */ USTRUCT(meta = (DataflowFlesh)) struct FGenerateSurfaceBindings : public FDataflowNode { GENERATED_USTRUCT_BODY() DATAFLOW_NODE_DEFINE_INTERNAL(FGenerateSurfaceBindings, "GenerateSurfaceBindings", "Flesh", "") DATAFLOW_NODE_RENDER_TYPE("SurfaceRender", FName("FDynamicMesh3"), "SKMDynamicMesh") public: FGenerateSurfaceBindings(const UE::Dataflow::FNodeParameters& InParam, FGuid InGuid = FGuid::NewGuid()) : FDataflowNode(InParam, InGuid) { RegisterInputConnection(&Collection); RegisterOutputConnection(&Collection, &Collection); RegisterInputConnection(&StaticMeshIn); RegisterInputConnection(&SkeletalMeshIn); RegisterInputConnection(&TransformSelection) .SetCanHidePin(true) .SetPinIsHidden(true); RegisterInputConnection(&GeometryGroupGuidsIn) .SetCanHidePin(true) .SetPinIsHidden(true); RegisterOutputConnection(&SKMDynamicMesh) .SetCanHidePin(true) .SetPinIsHidden(true); } private: /** Passthrough geometry collection. Bindings are stored as standalone groups in the \p Collection, keyed by the name of the input render mesh and all available LOD's. */ UPROPERTY(meta = (DataflowInput, DataflowOutput, DataflowPassthrough = "Collection", DisplayName = "Collection")) FManagedArrayCollection Collection; /** The input mesh, whose render surface is used to generate bindings. */ UPROPERTY(EditAnywhere, Category = "Dataflow", DisplayName = "Static Mesh", meta = (DataflowInput, EditCondition = "SkeletalMeshIn == nullptr")) TObjectPtr StaticMeshIn = nullptr; /** The input mesh, whose render surface is used to generate bindings. */ UPROPERTY(EditAnywhere, Category = "Dataflow", DisplayName = "Skeletal Mesh", meta = (DataflowInput, EditCondition = "StaticMeshIn == nullptr")) TObjectPtr SkeletalMeshIn = nullptr; /** Only meshes with transforms in TransformSelection will be bound. */ UPROPERTY(meta = (DataflowInput, DisplayName = "(Optional) TransformSelection")) FDataflowTransformSelection TransformSelection; /** Only meshes with transforms in TransformSelection will be bound. */ UPROPERTY(meta = (DataflowInput, DisplayName = "(Optional) GeometryGroupGuids")) TArray GeometryGroupGuidsIn; /** Use the import geometry of the skeletal mesh. */ UPROPERTY(EditAnywhere, Category = "Dataflow", meta = (DisplayName = "UseSkeletalMeshImportModel", EditCondition = "SkeletalMeshIn != nullptr")) bool bUseSkeletalMeshImportModel = false; /** Enable binding to the exterior hull of the tetrahedron mesh. */ UPROPERTY(EditAnywhere, Category = "Dataflow", meta = (DisplayName = "DoSurfaceProjection")) bool bDoSurfaceProjection = true; /** The search radius when looking for surface triangles to bind to. */ UPROPERTY(EditAnywhere, Category = "Dataflow", meta = (DisplayName = "SurfaceProjectionSearchRadius", EditCondition = "bDoSurfaceProjection == true")) float SurfaceProjectionSearchRadius = 1.f; /** When nodes aren't contained in tetrahedra and surface projection fails, try to find suitable bindings by looking to neighboring parents. */ UPROPERTY(EditAnywhere, Category = "Dataflow", meta = (DisplayName = "DoOrphanReparenting")) bool bDoOrphanReparenting = true; /** Converted from embedded skeletal/static mesh */ UPROPERTY(meta = (DataflowOutput)) TObjectPtr SKMDynamicMesh; virtual void Evaluate(UE::Dataflow::FContext& Context, const FDataflowOutput* Out) const override; };