// Copyright Epic Games, Inc. All Rights Reserved. #include "Dataflow/ChaosFleshAddKinematicParticlesNode.h" #include "Dataflow/DataflowEngineUtil.h" #include "Engine/SkeletalMesh.h" #include "GeometryCollection/Facades/CollectionKinematicBindingFacade.h" #include "GeometryCollection/Facades/CollectionVertexBoneWeightsFacade.h" #include "GeometryCollection/GeometryCollection.h" #include "BoneWeights.h" #include UE_INLINE_GENERATED_CPP_BY_NAME(ChaosFleshAddKinematicParticlesNode) //DEFINE_LOG_CATEGORY_STATIC(ChaosFleshAddKinematicParticlesDataflowNodeLog, Log, All); void FAddKinematicParticlesDataflowNode::Evaluate(UE::Dataflow::FContext& Context, const FDataflowOutput* Out) const { if (Out->IsA(&Collection) || Out->IsA>(&TargetIndicesOut)) { DataType InCollection = GetValue(Context, &Collection); TArray TargetIndices; if (TManagedArray* Vertices = InCollection.FindAttribute("Vertex", FGeometryCollection::VerticesGroup)) { if (FindInput(&VertexIndicesIn) && FindInput(&VertexIndicesIn)->GetConnection()) { TArray BoundVerts; TArray BoundWeights; for (int32 SelectionIndex : GetValue>(Context, &VertexIndicesIn)) { if (0 <= SelectionIndex && SelectionIndex < Vertices->Num()) { BoundVerts.Add(SelectionIndex); } } if (BoundVerts.Num()) { BoundWeights.Init(1.0, BoundVerts.Num()); GeometryCollection::Facades::FKinematicBindingFacade Kinematics(InCollection); Kinematics.AddKinematicBinding(Kinematics.SetBoneBindings(INDEX_NONE, BoundVerts, BoundWeights)); } } else if (TObjectPtr SkeletalMesh = GetValue>(Context, &SkeletalMeshIn)) { int32 IndexValue = GetValue(Context, &BoneIndexIn); if (IndexValue != INDEX_NONE) { TArray ComponentPose; UE::Dataflow::Animation::GlobalTransforms(SkeletalMesh->GetRefSkeleton(), ComponentPose); TArray BranchIndices; if (SkeletalSelectionMode == ESkeletalSeletionMode::Dataflow_SkeletalSelection_Branch) { TArray ToProcess; int32 CurrentIndex = IndexValue; while (SkeletalMesh->GetRefSkeleton().IsValidIndex(CurrentIndex)) { TArray Buffer; SkeletalMesh->GetRefSkeleton().GetDirectChildBones(CurrentIndex, Buffer); if (Buffer.Num()) { ToProcess.Append(Buffer); } BranchIndices.Add(CurrentIndex); CurrentIndex = INDEX_NONE; if (ToProcess.Num()) { CurrentIndex = ToProcess.Pop(); } } } else // ESkeletalSeletionMode::Dataflow_SkeletalSelection_Single { BranchIndices.Add(IndexValue); } // Add standalone particles, not bound to a transform group - so for these particles BoneMap = INDEX_NONE. int32 ParticleIndex = InCollection.AddElements(BranchIndices.Num(), FGeometryCollection::VerticesGroup); TManagedArray& CurrentVertices = InCollection.ModifyAttribute("Vertex", FGeometryCollection::VerticesGroup); for (int32 Index = 0; Index < BranchIndices.Num(); Index++) { const int32 BoneIndex = BranchIndices[Index]; FVector3f BonePosition(ComponentPose[BoneIndex].GetTranslation()); CurrentVertices[ParticleIndex+Index] = BonePosition; TArray BoundVerts; TArray BoundWeights; BoundVerts.Add(ParticleIndex + Index); BoundWeights.Add(1.0); TargetIndices.Emplace(ParticleIndex + Index); if (BoundVerts.Num()) { GeometryCollection::Facades::FKinematicBindingFacade Kinematics(InCollection); Kinematics.AddKinematicBinding(Kinematics.SetBoneBindings(BoneIndex, BoundVerts, BoundWeights)); } } //debugging code for tet binding: //int32 ParticleIndex1 = InCollection.AddElements(1, FGeometryCollection::VerticesGroup); //TManagedArray& CurrentVertices1 = InCollection.ModifyAttribute("Vertex", FGeometryCollection::VerticesGroup); //CurrentVertices1[ParticleIndex1][0] = -40.f; //CurrentVertices1[ParticleIndex1][1] = -50.f; //CurrentVertices1[ParticleIndex1][2] = -10.f; //GeometryCollection::Facades::FKinematicBindingFacade Kinematics(InCollection); //TArray BoundVerts; //TArray BoundWeights; //BoundVerts.Add(ParticleIndex1); //BoundWeights.Add(1.0); //Kinematics.AddKinematicBinding(Kinematics.SetBoneBindings(BranchIndices[0], BoundVerts, BoundWeights)); //TargetIndices.Emplace(ParticleIndex1); GeometryCollection::Facades::FVertexBoneWeightsFacade(InCollection).AddBoneWeightsFromKinematicBindings(); } } } SetValue(Context, MoveTemp(InCollection), &Collection); SetValue(Context, MoveTemp(TargetIndices), &TargetIndicesOut); } }