// Copyright Epic Games, Inc. All Rights Reserved. #include "Dataflow/ChaosFleshSetVertexTetrahedraPositionTargetBindingNode.h" #include "Chaos/BoundingVolumeHierarchy.h" #include "GeometryCollection/Facades/CollectionPositionTargetFacade.h" #include "Chaos/Tetrahedron.h" #include "ChaosFlesh/TetrahedralCollection.h" #include UE_INLINE_GENERATED_CPP_BY_NAME(ChaosFleshSetVertexTetrahedraPositionTargetBindingNode) //DEFINE_LOG_CATEGORY_STATIC(ChaosFleshSetVertexTetrahedraPositionTargetBindingNodeLog, Log, All); void FSetVertexTetrahedraPositionTargetBindingDataflowNode::Evaluate(UE::Dataflow::FContext& Context, const FDataflowOutput* Out) const { if (Out->IsA(&Collection)) { DataType InCollection = GetValue(Context, &Collection); if (FindInput(&TargetIndicesIn) && FindInput(&TargetIndicesIn)->GetConnection()) { if (TManagedArray* Vertices = InCollection.FindAttribute("Vertex", FGeometryCollection::VerticesGroup)) { if (TManagedArray* Tetrahedron = InCollection.FindAttribute(FTetrahedralCollection::TetrahedronAttribute, FTetrahedralCollection::TetrahedralGroup)) { TManagedArray* TetrahedronStart = InCollection.FindAttribute(FTetrahedralCollection::TetrahedronStartAttribute, FGeometryCollection::GeometryGroup); TManagedArray* TetrahedronCount = InCollection.FindAttribute(FTetrahedralCollection::TetrahedronCountAttribute, FGeometryCollection::GeometryGroup); if (TetrahedronStart && TetrahedronCount) { TArray GeometryGroupGuidsLocal; if (FindInput(&GeometryGroupGuidsIn) && FindInput(&GeometryGroupGuidsIn)->GetConnection()) { GeometryGroupGuidsLocal = GetValue>(Context, &GeometryGroupGuidsIn); } TManagedArray* Guids = InCollection.FindAttribute("Guid", FGeometryCollection::GeometryGroup); for (int32 TetMeshIdx = 0; TetMeshIdx < TetrahedronStart->Num(); TetMeshIdx++) { if (GeometryGroupGuidsLocal.Num() && Guids) { if (!GeometryGroupGuidsLocal.Contains((*Guids)[TetMeshIdx])) { continue; } } const int32 TetMeshStart = (*TetrahedronStart)[TetMeshIdx]; const int32 TetMeshCount = (*TetrahedronCount)[TetMeshIdx]; // Build Tetrahedra TArray> Tets; // Index 0 == TetMeshStart TArray*> BVHTetPtrs; Tets.SetNumUninitialized(TetMeshCount); BVHTetPtrs.SetNumUninitialized(TetMeshCount); for (int32 i = 0; i < TetMeshCount; i++) { const int32 Idx = TetMeshStart + i; const FIntVector4& Tet = (*Tetrahedron)[Idx]; Tets[i] = Chaos::TTetrahedron( (*Vertices)[Tet[0]], (*Vertices)[Tet[1]], (*Vertices)[Tet[2]], (*Vertices)[Tet[3]]); BVHTetPtrs[i] = &Tets[i]; } Chaos::TBoundingVolumeHierarchy< TArray*>, TArray, Chaos::FReal, 3> TetBVH(BVHTetPtrs); TArray TargetIndicesLocal = GetValue>(Context, &TargetIndicesIn); TArray SourceIndices; SourceIndices.Init(-1, TargetIndicesLocal.Num()); GeometryCollection::Facades::FPositionTargetFacade PositionTargets(InCollection); PositionTargets.DefineSchema(); for (int32 i = 0; i < TargetIndicesLocal.Num(); i++) { if (TargetIndicesLocal[i] > -1 && TargetIndicesLocal[i] < Vertices->Num()) { FVector3f ParticlePos = (*Vertices)[TargetIndicesLocal[i]]; TArray TetIntersections = TetBVH.FindAllIntersections(ParticlePos); for (int32 j = 0; j < TetIntersections.Num(); j++) { const int32 TetIdx = TetIntersections[j]; if (!Tets[TetIdx].Outside(ParticlePos, 0)) { Chaos::TVector WeightsD = Tets[TetIdx].GetBarycentricCoordinates(ParticlePos); GeometryCollection::Facades::FPositionTargetsData DataPackage; DataPackage.TargetIndex.Init(TargetIndicesLocal[i], 1); DataPackage.TargetWeights.Init(1.f, 1); DataPackage.SourceWeights.Init(1.f, 4); DataPackage.SourceIndex.Init(-1, 4); DataPackage.SourceIndex[0] = (*Tetrahedron)[TetIdx][0]; DataPackage.SourceIndex[1] = (*Tetrahedron)[TetIdx][1]; DataPackage.SourceIndex[2] = (*Tetrahedron)[TetIdx][2]; DataPackage.SourceIndex[3] = (*Tetrahedron)[TetIdx][3]; DataPackage.SourceWeights[0] = WeightsD[0]; DataPackage.SourceWeights[1] = WeightsD[1]; DataPackage.SourceWeights[2] = WeightsD[2]; DataPackage.SourceWeights[3] = WeightsD[3]; if (TManagedArray* Mass = InCollection.FindAttribute("Mass", FGeometryCollection::VerticesGroup)) { DataPackage.Stiffness = 0.f; for (int32 k = 0; k < 4; k++) { DataPackage.Stiffness += DataPackage.SourceWeights[k] * PositionTargetStiffness * (*Mass)[DataPackage.SourceIndex[0]]; } } else { DataPackage.Stiffness = PositionTargetStiffness; } PositionTargets.AddPositionTarget(DataPackage); break; } } } } } } } } } SetValue(Context, MoveTemp(InCollection), &Collection); } }