// Copyright Epic Games, Inc. All Rights Reserved. #include "Dataflow/GeometryCollectionClusteringNodes.h" #include "Dataflow/DataflowCore.h" #include "Engine/StaticMesh.h" #include "GeometryCollection/GeometryCollectionObject.h" #include "GeometryCollection/ManagedArrayCollection.h" #include "GeometryCollection/GeometryCollection.h" #include "GeometryCollection/GeometryCollectionEngineUtility.h" #include "GeometryCollection/GeometryCollectionEngineConversion.h" #include "Logging/LogMacros.h" #include "Templates/SharedPointer.h" #include "UObject/UnrealTypePrivate.h" #include "DynamicMeshToMeshDescription.h" #include "MeshDescriptionToDynamicMesh.h" #include "StaticMeshAttributes.h" #include "DynamicMeshEditor.h" #include "Operations/MeshBoolean.h" #include "EngineGlobals.h" #include "GeometryCollection/GeometryCollectionAlgo.h" #include "GeometryCollection/GeometryCollectionClusteringUtility.h" #include "GeometryCollection/GeometryCollectionConvexUtility.h" #include "Voronoi/Voronoi.h" #include "PlanarCut.h" #include "GeometryCollection/GeometryCollectionProximityUtility.h" #include "FractureEngineClustering.h" #include "FractureEngineSelection.h" #include UE_INLINE_GENERATED_CPP_BY_NAME(GeometryCollectionClusteringNodes) namespace Dataflow { void GeometryCollectionClusteringNodes() { static const FLinearColor CDefaultNodeBodyTintColor = FLinearColor(0.f, 0.f, 0.f, 0.5f); DATAFLOW_NODE_REGISTER_CREATION_FACTORY(FAutoClusterDataflowNode); DATAFLOW_NODE_REGISTER_CREATION_FACTORY(FClusterFlattenDataflowNode); // GeometryCollection|Cluster DATAFLOW_NODE_REGISTER_CREATION_FACTORY_NODE_COLORS_BY_CATEGORY("GeometryCollection|Cluster", FLinearColor(.25f, 0.45f, 0.8f), CDefaultNodeBodyTintColor); } } void FAutoClusterDataflowNode::Evaluate(Dataflow::FContext& Context, const FDataflowOutput* Out) const { if (Out->IsA(&Collection)) { const FManagedArrayCollection& InCollection = GetValue(Context, &Collection); const FDataflowTransformSelection& InTransformSelection = GetValue(Context, &TransformSelection); if (TUniquePtr GeomCollection = TUniquePtr(InCollection.NewCopy())) { EClusterSizeMethodEnum InClusterSizeMethod = ClusterSizeMethod; int32 InClusterSites = GetValue(Context, &ClusterSites); float InClusterFraction = GetValue(Context, &ClusterFraction); float InSiteSize = GetValue(Context, &SiteSize); bool InAutoCluster = AutoCluster; bool InAvoidIsolated = AvoidIsolated; TArray SelectedBones; InTransformSelection.AsArray(SelectedBones); FFractureEngineClustering::AutoCluster(*GeomCollection, SelectedBones, (EFractureEngineClusterSizeMethod)InClusterSizeMethod, InClusterSites, InClusterFraction, InSiteSize, InAutoCluster, InAvoidIsolated); SetValue(Context, (const FManagedArrayCollection&)(*GeomCollection), &Collection); } } } void FClusterFlattenDataflowNode::Evaluate(Dataflow::FContext& Context, const FDataflowOutput* Out) const { if (Out->IsA(&Collection)) { const FManagedArrayCollection& InCollection = GetValue(Context, &Collection); if (TUniquePtr GeomCollection = TUniquePtr(InCollection.NewCopy())) { FGeometryCollectionClusteringUtility::UpdateHierarchyLevelOfChildren(GeomCollection.Get(), -1); const TManagedArray& Levels = GeomCollection->GetAttribute("Level", FGeometryCollection::TransformGroup); // Populate Selected Bones in an Array // @todo(harsha) Implement with Selection // For every bone in selected array: [ClusterIndex] int32 ClusterIndex = 0; TArray LeafBones; FGeometryCollectionClusteringUtility::GetLeafBones(GeomCollection.Get(), ClusterIndex, true, LeafBones); FGeometryCollectionClusteringUtility::ClusterBonesUnderExistingNode(GeomCollection.Get(), ClusterIndex, LeafBones); FGeometryCollectionClusteringUtility::RemoveDanglingClusters(GeomCollection.Get()); // End for FGeometryCollectionClusteringUtility::UpdateHierarchyLevelOfChildren(GeomCollection.Get(), -1); SetValue(Context, (const FManagedArrayCollection&)(*GeomCollection), &Collection); } } }