UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
GaussSeidelWeakConstraints.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2#pragma once
3
7#include "ChaosStats.h"
12#include "Chaos/Utilities.h"
15#include "Chaos/Triangle.h"
17#include "Chaos/TriangleMesh.h"
18#include <unordered_map>
19namespace Chaos::Softs
20{
21 using Chaos::TVec3;
22
23 template <typename T>
36
37 template<class T>
39 {
40 public:
42 {
43 AddArray(&MIndices);
44 AddArray(&MSecondIndices);
45 AddArray(&MWeights);
46 AddArray(&MSecondWeights);
47 AddArray(&MStiffness);
48 AddArray(&MIsAnisotropic);
49 AddArray(&MNormals);
50 AddArray(&MIsZeroRestLength);
51 AddArray(&MRestLength);
52 }
55 : TArrayCollection(), MIndices(MoveTemp(Other.MIndices))
56 , MSecondIndices(MoveTemp(Other.MSecondIndices))
57 , MWeights(MoveTemp(Other.MWeights))
58 , MSecondWeights(MoveTemp(Other.MSecondWeights))
59 , MStiffness(MoveTemp(Other.MStiffness))
60 , MIsAnisotropic(MoveTemp(Other.MIsAnisotropic))
61 {
62 AddParticles(Other.Size());
63 AddArray(&MIndices);
64 AddArray(&MSecondIndices);
65 AddArray(&MWeights);
66 AddArray(&MSecondWeights);
67 AddArray(&MStiffness);
68 AddArray(&MIsAnisotropic);
69 AddArray(&MNormals);
70 AddArray(&MIsZeroRestLength);
71 AddArray(&MRestLength);
72 Other.MSize = 0;
73 }
74
77
79 {
81 }
82
83 void RemoveConstraint(const int32 Idx)
84 {
86 }
87
89 {
90 MIndices[ConstraintIndex] = SingleData.SingleIndices;
91 MSecondIndices[ConstraintIndex] = SingleData.SingleSecondIndices;
92 MStiffness[ConstraintIndex] = SingleData.SingleStiffness;
93 MWeights[ConstraintIndex] = SingleData.SingleWeights;
94 MSecondWeights[ConstraintIndex] = SingleData.SingleSecondWeights;
95 MNormals[ConstraintIndex] = SingleData.SingleNormal;
96 MIsAnisotropic[ConstraintIndex] = SingleData.bIsAnisotropic;
97 MIsZeroRestLength[ConstraintIndex] = SingleData.bIsZeroRestLength;
98 }
99
105
106 int32 Size() const
107 {
108 return static_cast<int32>(MSize);
109 }
110
111 void Resize(const int32 Num)
112 {
114 }
115
117 {
118 MIndices = MoveTemp(Other.MIndices);
119 MSecondIndices = MoveTemp(Other.MSecondIndices);
120 MWeights = MoveTemp(Other.MWeights);
121 MSecondWeights = MoveTemp(Other.MSecondWeights);
122 MStiffness = MoveTemp(Other.MStiffness);
123 MIsAnisotropic = MoveTemp(Other.MIsAnisotropic);
124 MNormals = MoveTemp(Other.MNormals);
125 MIsZeroRestLength = MoveTemp(Other.MIsZeroRestLength);
126 ResizeHelper(Other.Size());
127 Other.MSize = 0;
128 return *this;
129 }
130
132 {
133 return MIndices;
134 }
135
137 {
138 return MIndices[Index];
139 }
140
142 {
143 MIndices[Index] = InIndices;
144 }
145
147 {
148 return MSecondIndices;
149 }
150
152 {
153 return MSecondIndices[Index];
154 }
155
157 {
158 MSecondIndices[Index] = InIndices;
159 }
160
162 {
163 return MWeights;
164 }
165
166 const TArray<T>& GetWeights(const int32 Index) const
167 {
168 return MWeights[Index];
169 }
170
172 {
173 MWeights[Index] = InWeights;
174 }
175
177 {
178 return MSecondWeights;
179 }
180
182 {
183 return MSecondWeights[Index];
184 }
185
187 {
188 MSecondWeights[Index] = InWeights;
189 }
190
191 const bool GetIsAnisotropic(const int32 Index) const
192 {
193 return MIsAnisotropic[Index];
194 }
195
197 {
198 MIsAnisotropic[Index] = InIsAnisotropic;
199 }
200
202 {
203 return MNormals;
204 }
205
206 const TVec3<T>& GetNormal(const int32 Index) const
207 {
208 return MNormals[Index];
209 }
210
212 {
213 MNormals[Index] = InNormal;
214 }
215
217 {
218 return MStiffness;
219 }
220
221 T GetStiffness(const int32 Index) const
222 {
223 return MStiffness[Index];
224 }
225
226 void SetStiffness(const int32 Index, const T InStiffness)
227 {
228 MStiffness[Index] = InStiffness;
229 }
230
231 const bool GetIsZeroRestLength(const int32 Index) const
232 {
233 return MIsZeroRestLength[Index];
234 }
235
237 {
238 MIsZeroRestLength[Index] = InIsZeroRestLength;
239 }
240
242 {
243 MRestLength[Index] = InRestLength;
244 }
245
247 {
249 check(static_cast<uint32>(ConstraintIndex) < MSize);
250 if (ConstraintIndex > INDEX_NONE && static_cast<uint32>(ConstraintIndex) < MSize)
251 {
252 SingleConstraintData.SingleIndices = MIndices[ConstraintIndex];
253 SingleConstraintData.SingleSecondIndices = MSecondIndices[ConstraintIndex];
254 SingleConstraintData.SingleStiffness = MStiffness[ConstraintIndex];
255 SingleConstraintData.SingleWeights = MWeights[ConstraintIndex];
256 SingleConstraintData.SingleSecondWeights = MSecondWeights[ConstraintIndex];
257 SingleConstraintData.bIsAnisotropic = MIsAnisotropic[ConstraintIndex];
258 SingleConstraintData.SingleNormal = MNormals[ConstraintIndex];
259 SingleConstraintData.bIsZeroRestLength = MIsZeroRestLength[ConstraintIndex];
260 SingleConstraintData.RestLength = MRestLength[ConstraintIndex];
261 }
263 }
264
265 private:
269 TArrayCollectionArray<TArray<T>> MSecondWeights;
270 TArrayCollectionArray<T> MStiffness;
271 TArrayCollectionArray<bool> MIsAnisotropic;
273 TArrayCollectionArray<bool> MIsZeroRestLength;
274 TArrayCollectionArray<T> MRestLength;
275 };
276
277
278
279 template <typename T, typename ParticleType>
281 {
282 //TODO(Yizhou): Add unittest for Gauss Seidel Weak Constraints
285 const TArray<TArray<T>>& InWeights,
286 const TArray<T>& InStiffness,
291 {
292 ensureMsgf(InIndices.Num() == InSecondIndices.Num(), TEXT("Input Double Bindings have wrong size"));
293
294 ConstraintsData.Resize(0);
295
296 ConstraintsData.AddConstraints(InIndices.Num());
297
298 for (int32 i = 0; i < InIndices.Num(); i++)
299 {
302 SingleConstraintData.SingleSecondIndices = InSecondIndices[i];
303 SingleConstraintData.SingleWeights = InWeights[i];
304 SingleConstraintData.SingleSecondWeights = InSecondWeights[i];
305 SingleConstraintData.SingleStiffness = InStiffness[i];
306 ConstraintsData.SetSingleConstraint(SingleConstraintData, i);
307 }
308
309 for (int32 i = 0; i < ConstraintsData.Size(); i++)
310 {
311 const TArray<int32>& SingleIndices = ConstraintsData.GetIndices(i);
312 const TArray<int32>& SingleSecondIndices = ConstraintsData.GetSecondIndices(i);
313 for (int32 j = 0; j < SingleSecondIndices.Num(); j++)
314 {
315 ensureMsgf(!SingleIndices.Contains(SingleSecondIndices[j]), TEXT("Indices and Second Indices overlaps. Currently not supported"));
316 }
317 }
318 }
319
324
326
327 void ComputeInitialWCData(const ParticleType& InParticles)
328 {
331 for (int32 ConstraintIdx = 0; ConstraintIdx < ExtraConstraints.Num(); ++ConstraintIdx)
332 {
333 ExtraConstraints[ConstraintIdx].SetNum(ConstraintsData.GetIndices(ConstraintIdx).Num() + ConstraintsData.GetSecondIndices(ConstraintIdx).Num());
334 for (int32 LocalIdx = 0; LocalIdx < ConstraintsData.GetIndices(ConstraintIdx).Num(); ++LocalIdx)
335 {
336 ExtraConstraints[ConstraintIdx][LocalIdx] = ConstraintsData.GetIndices(ConstraintIdx)[LocalIdx];
337 }
338 for (int32 LocalSecondIdx = 0; LocalSecondIdx < ConstraintsData.GetSecondIndices(ConstraintIdx).Num(); ++LocalSecondIdx)
339 {
340 ExtraConstraints[ConstraintIdx][LocalSecondIdx+ConstraintsData.GetIndices(ConstraintIdx).Num()] = ConstraintsData.GetSecondIndices(ConstraintIdx)[LocalSecondIdx];
341 }
342 }
344
345 //Update rest state normal and nodal weights
346 UpdateTriangleNormalAndNodalWeight(InParticles, /*bUseParticleX = */true);
347
351
354
355 // Compute rest length
356 for (int32 ConstraintIdx = 0; ConstraintIdx < ConstraintsData.Size(); ++ConstraintIdx)
357 {
358 if (ConstraintsData.GetIsZeroRestLength(ConstraintIdx))
359 {
360 ConstraintsData.SetRestLength(ConstraintIdx, 0);
361 }
362 else
363 {
364 const TArray<int32>& Indices = ConstraintsData.GetIndices(ConstraintIdx);
365 const TArray<int32>& SecondIndices = ConstraintsData.GetSecondIndices(ConstraintIdx);
366 const TArray<T>& Weights = ConstraintsData.GetWeights(ConstraintIdx);
367 const TArray<T>& SecondWeights = ConstraintsData.GetSecondWeights(ConstraintIdx);
368 const TVec3<T> RestSpringEdge = ComputeSpringEdge(InParticles, Indices, SecondIndices, Weights, SecondWeights, /*bUseParticleX =*/true);
369 if (ConstraintsData.GetIsAnisotropic(ConstraintIdx))
370 {
371 //if the spring is anisotropic, rest length could be negative depending on the normal direction
372 ConstraintsData.SetRestLength(ConstraintIdx, TVec3<T>::DotProduct(ConstraintsData.GetNormal(ConstraintIdx), RestSpringEdge));
373 }
374 else
375 {
376 ConstraintsData.SetRestLength(ConstraintIdx, RestSpringEdge.Size());
377 }
378 }
379 }
380 }
381
384 {
385 TVec3<T> SpringEdge((T)0.);
386 if (ensure(LocalIndices.Num() == Weight.Num() && LocalSecondIndices.Num() == SecondWeight.Num()))
387 {
388 if (bUseParticleX)
389 {
390 for (int32 Idx = 0; Idx < LocalIndices.Num(); ++Idx)
391 {
392 for (int32 beta = 0; beta < 3; beta++)
393 {
395 }
396 }
398 {
399 for (int32 beta = 0; beta < 3; beta++)
400 {
402 }
403 }
404 }
405 else
406 {
407 for (int32 Idx = 0; Idx < LocalIndices.Num(); ++Idx)
408 {
409 for (int32 beta = 0; beta < 3; beta++)
410 {
412 }
413 }
415 {
416 for (int32 beta = 0; beta < 3; beta++)
417 {
419 }
420 }
421 }
422 }
423 return SpringEdge;
424 }
425
427 {
428 if (NodalWeights[p].Num() > 0)
429 {
430 for (int32 alpha = 0; alpha < 3; alpha++)
431 {
432 ParticleHessian.SetAt(alpha, alpha, ParticleHessian.GetAt(alpha, alpha) + Dt * Dt * NodalWeights[p][alpha]);
433 }
434
435 ParticleHessian.SetAt(0, 1, ParticleHessian.GetAt(0, 1) + Dt * Dt * NodalWeights[p][3]);
436 ParticleHessian.SetAt(0, 2, ParticleHessian.GetAt(0, 2) + Dt * Dt * NodalWeights[p][4]);
437 ParticleHessian.SetAt(1, 2, ParticleHessian.GetAt(1, 2) + Dt * Dt * NodalWeights[p][5]);
438 ParticleHessian.SetAt(1, 0, ParticleHessian.GetAt(1, 0) + Dt * Dt * NodalWeights[p][3]);
439 ParticleHessian.SetAt(2, 0, ParticleHessian.GetAt(2, 0) + Dt * Dt * NodalWeights[p][4]);
440 ParticleHessian.SetAt(2, 1, ParticleHessian.GetAt(2, 1) + Dt * Dt * NodalWeights[p][5]);
441 //TODO(Yizhou): Clean up the following after debugging:
442 //ParticleHessian.SetAt(0, 2) += Dt * Dt * NodalWeights[p][4];
443 //ParticleHessian.SetAt(1, 2) += Dt * Dt * NodalWeights[p][5];
444 //ParticleHessian.SetAt(1, 0) += Dt * Dt * NodalWeights[p][3];
445 //ParticleHessian.SetAt(2, 0) += Dt * Dt * NodalWeights[p][4];
446 //ParticleHessian.SetAt(2, 1) += Dt * Dt * NodalWeights[p][5];
447 }
448 }
449
451 const TArray<TArray<T>>& InWeights,
452 const TArray<T>& InStiffness,
457 {
458 const int32 Offset = ConstraintsData.Size();
459
460 ConstraintsData.AddConstraints(InIndices.Num());
461
462 for (int32 i = 0; i < InIndices.Num(); i++)
463 {
466 SingleConstraintData.SingleSecondIndices = InSecondIndices[i];
467 SingleConstraintData.SingleWeights = InWeights[i];
468 SingleConstraintData.SingleSecondWeights = InSecondWeights[i];
469 SingleConstraintData.SingleStiffness = InStiffness[i];
470 SingleConstraintData.bIsAnisotropic = InIsAnisotrpic[i];
471 SingleConstraintData.bIsZeroRestLength = InIsZeroRestLength[i];
472 ConstraintsData.SetSingleConstraint(SingleConstraintData, i + Offset);
473 }
474 }
475
477 {
478 ConstraintsData.Resize(Size);
479 }
480
482 {
484
486
487 for (int32 i = InitialWCSize; i < OriginalConstraintsData.Size(); i++)
488 {
490 const TArray<int32>& SecondIndicesTemp = OriginalConstraintsData.GetSecondIndices(i);
491 ensureMsgf(OriginalConstraintsData.GetIndices(i).Num() == 3, TEXT("Collision format is not point-triangle"));
492 ensureMsgf(OriginalConstraintsData.GetSecondIndices(i).Num() == 1, TEXT("Collision format is not point-triangle"));
493 Chaos::TVector<float, 3> TriPos0(Particles.P(IndicesTemp[0])), TriPos1(Particles.P(IndicesTemp[1])), TriPos2(Particles.P(IndicesTemp[2])), ParticlePos(Particles.P(SecondIndicesTemp[0]));
494 Chaos::TVector<T, 3> Normal = FVector3f::CrossProduct(TriPos2 - TriPos0, TriPos1 - TriPos0); //triangle normal convention (see FTriangleMesh::GetFaceNormals())
495 if (FVector3f::DotProduct(ParticlePos - TriPos0, Normal) < 0.f) //not resolved, keep the spring
496 {
497 ConstraintsData.AddConstraints(OriginalConstraintsData.GetSingleConstraintData(i));
498 }
499 }
500 }
501
502 void VisualizeAllBindings(const FSolverParticles& InParticles, const T Dt) const
503 {
504#if WITH_EDITOR
505 auto DoubleVert = [](Chaos::TVec3<T> V) { return FVector3d(V.X, V.Y, V.Z); };
506 for (int32 i = 0; i < ConstraintsData.Size(); i++)
507 {
509 Chaos::TVec3<T> SourcePos((T)0.), TargetPos((T)0.);
510 for (int32 j = 0; j < SingleConstraintData.SingleIndices.Num(); j++)
511 {
512 SourcePos += SingleConstraintData.SingleWeights[j] * InParticles.P(SingleConstraintData.SingleIndices[j]);
513 }
514 for (int32 j = 0; j < SingleConstraintData.SingleSecondIndices.Num(); j++)
515 {
516 TargetPos += SingleConstraintData.SingleSecondWeights[j] * InParticles.P(SingleConstraintData.SingleSecondIndices[j]);
517 }
518
520 float LineThickness = DebugDrawParams.DebugLineWidth;
521
522 if (SingleConstraintData.SingleIndices.Num() == 1)
523 {
524 Chaos::FDebugDrawQueue::GetInstance().DrawDebugPoint(DoubleVert(SourcePos), FColor::Red, false, Dt, 0, ParticleThickness);
525 for (int32 j = 0; j < SingleConstraintData.SingleSecondIndices.Num(); j++)
526 {
527 Chaos::FDebugDrawQueue::GetInstance().DrawDebugPoint(DoubleVert(InParticles.P(SingleConstraintData.SingleSecondIndices[j])), FColor::Green, false, Dt, 0, ParticleThickness);
528 Chaos::FDebugDrawQueue::GetInstance().DrawDebugLine(DoubleVert(InParticles.P(SingleConstraintData.SingleSecondIndices[j])), DoubleVert(InParticles.P(SingleConstraintData.SingleSecondIndices[(j + 1) % SingleConstraintData.SingleSecondIndices.Num()])), FColor::Green, false, Dt, 0, LineThickness);
529 }
530
531 }
532
533 if (SingleConstraintData.SingleSecondIndices.Num() == 1)
534 {
535 Chaos::FDebugDrawQueue::GetInstance().DrawDebugPoint(DoubleVert(TargetPos), FColor::Red, false, Dt, 0, ParticleThickness);
536 for (int32 j = 0; j < SingleConstraintData.SingleIndices.Num(); j++)
537 {
538 Chaos::FDebugDrawQueue::GetInstance().DrawDebugPoint(DoubleVert(InParticles.P(SingleConstraintData.SingleIndices[j])), FColor::Green, false, Dt, 0, ParticleThickness);
539 Chaos::FDebugDrawQueue::GetInstance().DrawDebugLine(DoubleVert(InParticles.P(SingleConstraintData.SingleIndices[j])), DoubleVert(InParticles.P(SingleConstraintData.SingleIndices[(j + 1) % SingleConstraintData.SingleIndices.Num()])), FColor::Green, false, Dt, 0, LineThickness);
540 }
541 }
542
543 Chaos::FDebugDrawQueue::GetInstance().DrawDebugLine(DoubleVert(SourcePos), DoubleVert(TargetPos), FColor::Yellow, false, Dt, 0, LineThickness);
544 }
545#endif
546 }
547
548 void Init(const FSolverParticles& InParticles, const T Dt)
549 {
550 UpdateTriangleNormalAndNodalWeight(InParticles, /*bUseParticleX =*/ false);
552 {
554 }
555 }
556
558 {
559 for (int32 i = 0; i < ConstraintsData.Size(); i++)
560 {
561 if (ConstraintsData.GetIsAnisotropic(i))
562 {
563 const TArray<int32>& IndicesTemp = ConstraintsData.GetIndices(i);
564 const TArray<int32>& SecondIndicesTemp = ConstraintsData.GetSecondIndices(i);
565 ensureMsgf(ConstraintsData.GetIndices(i).Num() == 3, TEXT("Collision format is not point-triangle"));
566 ensureMsgf(ConstraintsData.GetSecondIndices(i).Num() == 1, TEXT("Collision format is not point-triangle"));
568 if (bUseParticleX)
569 {
571 Normal = FVector3f::CrossProduct(TriPos2 - TriPos0, TriPos1 - TriPos0).GetSafeNormal(); //triangle normal convention (see FTriangleMesh::GetFaceNormals())
572 }
573 else
574 {
576 Normal = FVector3f::CrossProduct(TriPos2 - TriPos0, TriPos1 - TriPos0).GetSafeNormal(); //triangle normal convention (see FTriangleMesh::GetFaceNormals())
577 }
578 ConstraintsData.SetNormal(i, Normal);
579 }
580 }
581
582 NodalWeights.Init({}, InParticles.Size());
583 for (int32 p = 0; p < WCIncidentElements.Num(); ++p)
584 {
585 if (WCIncidentElements[p].Num() > 0)
586 {
587 NodalWeights[p].Init(T(0), 6);
588 for (int32 j = 0; j < WCIncidentElements[p].Num(); j++)
589 {
590 int32 ConstraintIndex = WCIncidentElements[p][j];
591 int32 LocalIndex = WCIncidentElementsLocal[p][j];
592
593 T Weight = T(0);
594 if (LocalIndex >= ConstraintsData.GetIndices(ConstraintIndex).Num())
595 {
596 Weight = ConstraintsData.GetSecondWeights(ConstraintIndex)[LocalIndex - ConstraintsData.GetIndices(ConstraintIndex).Num()];
597 }
598 else
599 {
600 Weight = ConstraintsData.GetWeights(ConstraintIndex)[LocalIndex];
601 }
602
603 if (ConstraintsData.GetIsAnisotropic(ConstraintIndex))
604 {
605 for (int32 alpha = 0; alpha < 3; alpha++)
606 {
607 NodalWeights[p][alpha] += ConstraintsData.GetNormal(ConstraintIndex)[alpha] * ConstraintsData.GetNormal(ConstraintIndex)[alpha] * Weight * Weight * ConstraintsData.GetStiffness(ConstraintIndex);
608 }
609
610 NodalWeights[p][3] += ConstraintsData.GetNormal(ConstraintIndex)[0] * ConstraintsData.GetNormal(ConstraintIndex)[1] * Weight * Weight * ConstraintsData.GetStiffness(ConstraintIndex);
611 NodalWeights[p][4] += ConstraintsData.GetNormal(ConstraintIndex)[0] * ConstraintsData.GetNormal(ConstraintIndex)[2] * Weight * Weight * ConstraintsData.GetStiffness(ConstraintIndex);
612 NodalWeights[p][5] += ConstraintsData.GetNormal(ConstraintIndex)[1] * ConstraintsData.GetNormal(ConstraintIndex)[2] * Weight * Weight * ConstraintsData.GetStiffness(ConstraintIndex);
613 }
614 else
615 {
616 for (int32 alpha = 0; alpha < 3; alpha++)
617 {
618 NodalWeights[p][alpha] += Weight * Weight * ConstraintsData.GetStiffness(ConstraintIndex);
619 }
620 }
621 }
622 }
623 }
624 }
625
626 //CollisionDetectionSpatialHash should be faster than CollisionDetectionBVH
627 void CollisionDetectionBVH(const FSolverParticles& Particles, const TArray<TVec3<int32>>& SurfaceElements, const TArray<int32>& ComponentIndex, float DetectRadius = 1.f, float PositionTargetStiffness = 10000.f, bool UseAnisotropicSpring = true)
628 {
631
633 for (int32 i = 0; i < SurfaceElements.Num(); i++)
634 {
636 for (int32 j = 0; j < 3; j++)
637 {
638 CurrentSurfaceElements[j] = SurfaceElements[i][j];
639 }
643 {
645 }
646 }
647 TArray<TArray<int32>> LocalIndex;
648 TArray<TArray<int32>>* LocalIndexPtr = &LocalIndex;
651 for (int32 l = 0; l < GlobalIndex.Num(); l++)
652 {
653 if (GlobalIndex[l].Num() > 0)
654 {
656 }
657 }
663 for (int32 i = 0; i < GlobalIndex.Num(); i++)
664 {
665 if (GlobalIndex[i].Num() > 0)
666 {
667 SurfaceElementsPositions[CurrentParticleIndex] = Particles.P(SurfaceElements[GlobalIndex[i][0]][LocalIndex[i][0]]);
668 SurfaceElementsMap[CurrentParticleIndex] = SurfaceElements[GlobalIndex[i][0]][LocalIndex[i][0]];
670 }
671 }
672
675
678
679 for (int32 i = 0; i < SurfaceElementsPositions.Num(); i++)
680 {
685 }
691
692 for (int32 i = 0; i < SurfaceElements.Num(); i++)
693 {
694 TArray<int32> TriangleIntersections0 = VertexBVH.FindAllIntersections(Particles.P(SurfaceElements[i][0]));
695 TArray<int32> TriangleIntersections1 = VertexBVH.FindAllIntersections(Particles.P(SurfaceElements[i][1]));
696 TArray<int32> TriangleIntersections2 = VertexBVH.FindAllIntersections(Particles.P(SurfaceElements[i][2]));
700
702 for (int32 k = 0; k < TriangleIntersections0.Num(); k++)
703 {
706 {
708 }
709 }
710
711 int32 TriangleIndex = ComponentIndex[SurfaceElements[i][0]];
712 int32 MinIndex = INDEX_NONE;
713 float MinDis = DetectRadius;
715 Chaos::TVector<float, 3> FaceNormal;
716 for (int32 j = 0; j < TriangleIntersections.Num(); j++)
717 {
718 if (ComponentIndex[SurfaceElementsMap[TriangleIntersections[j]]] >= 0 && TriangleIndex >= 0 && ComponentIndex[SurfaceElementsMap[TriangleIntersections[j]]] != TriangleIndex)
719 {
720 Chaos::TVector<float, 3> Bary, TriPos0(Particles.P(SurfaceElements[i][0])), TriPos1(Particles.P(SurfaceElements[i][1])), TriPos2(Particles.P(SurfaceElements[i][2])), ParticlePos(Particles.P(SurfaceElementsMap[TriangleIntersections[j]]));
724 {
725 Chaos::TVector<T, 3> Normal = FVector3f::CrossProduct(TriPos2 - TriPos0, TriPos1 - TriPos0); //The normal needs to point outwards of the geometry
727 {
728 Normal.SafeNormalize(1e-8f);
731 ClosestBary = Bary;
732 FaceNormal = Normal;
733 }
734 }
735
736 }
737 }
738 if (MinIndex != INDEX_NONE
739 && MinIndex != SurfaceElements[i][0]
740 && MinIndex != SurfaceElements[i][1]
741 && MinIndex != SurfaceElements[i][2])
742 {
744 SingleConstraintData.SingleIndices = {SurfaceElements[i][0], SurfaceElements[i][1], SurfaceElements[i][2]};
745 SingleConstraintData.SingleSecondIndices = {MinIndex};
747 SingleConstraintData.SecondWeights = {T(1.f)};
749 SingleConstraintData.SingleNormal = FaceNormal;
750 SingleConstraintData.bIsZeroRestLength = true; //Push-out type collision springs should be zero rest length
751
752 float SpringStiffness = 0.f;
753 for (int32 k = 0; k < 3; k++)
754 {
755 SpringStiffness += ClosestBary[k] * PositionTargetStiffness * Particles.M(SurfaceElements[i][k]);
756 }
757 SpringStiffness += PositionTargetStiffness * Particles.M(MinIndex);
758 SingleConstraintData.SingleStiffness = (T)SpringStiffness;
759 ConstraintsData.AddSingleConstraint(SingleConstraintData);
760 }
761 }
762 }
763
764 template<typename SpatialAccelerator>
765 void CollisionDetectionSpatialHash(const FSolverParticles& Particles, const TArray<int32>& SurfaceVertices, const FTriangleMesh& TriangleMesh, const TArray<int32>& ComponentIndex, const SpatialAccelerator& Spatial, float DetectRadius = 1.f, float PositionTargetStiffness = 10000.f, bool UseAnisotropicSpring = true)
766 {
768 Resize(InitialWCSize + Particles.Size());
769 std::atomic<int32> ConstraintIndex(InitialWCSize);
770 const TArray<TVec3<int32>>& Elements = TriangleMesh.GetSurfaceElements();
771 const float HalfRadius = DetectRadius / 2;
773 [this, &Spatial, &Particles, &SurfaceVertices, &ConstraintIndex, &TriangleMesh, &Elements, &HalfRadius, &ComponentIndex, &PositionTargetStiffness, &UseAnisotropicSpring](int32 i)
774 {
775 const int32 Index = SurfaceVertices[i];
776 TArray< TTriangleCollisionPoint<FSolverReal>> Result;
777 //PointProximityQuery
778 if (TriangleMesh.PointClosestTriangleQuery(Spatial, static_cast<const TArrayView<const FSolverVec3>&>(Particles.XArray()), Index, Particles.GetX(Index), HalfRadius, HalfRadius,
779 [this, &ComponentIndex, &Elements](const int32 PointIndex, const int32 TriangleIndex)->bool
780 {
781 //Skip particles that are bound in initial springs
782 return ComponentIndex[PointIndex] != ComponentIndex[Elements[TriangleIndex][0]] && (!NoCollisionWCIncidentElements.IsValidIndex(PointIndex) || NoCollisionWCIncidentElements[PointIndex].Num() == 0);
783 },
784 Result))
785 {
787 {
788 if (CollisionPoint.Phi < 0)
789 {
790 const TVector<int32, 3>& Elem = Elements[CollisionPoint.Indices[1]];
791 const int32 IndexToWrite = ConstraintIndex.fetch_add(1);
792
795 SingleConstraintData.SingleSecondIndices = { Index };
796 SingleConstraintData.SingleWeights = { CollisionPoint.Bary[1], CollisionPoint.Bary[2], CollisionPoint.Bary[3] };
797 SingleConstraintData.SingleSecondWeights = {T(1.f)};
799 SingleConstraintData.SingleNormal = CollisionPoint.Normal;
800 SingleConstraintData.bIsZeroRestLength = true; //Push-out type collision springs should be zero rest length
801
802 float SpringStiffness = 0.f;
803 for (int32 k = 0; k < 3; k++)
804 {
805 SpringStiffness += SingleConstraintData.SingleWeights[k] * PositionTargetStiffness * Particles.M(Elem[k]);
806 }
808 SingleConstraintData.SingleStiffness = (T)SpringStiffness;
810 }
811 }
812 }
813 }
814 );
815
816 // Shrink the arrays to the actual number of found constraints.
817 const int32 ConstraintNum = ConstraintIndex.load();
819 }
820
821 template<typename SpatialAccelerator>
823 {
825 Resize(InitialWCSize + Particles.Size());
826 std::atomic<int32> ConstraintIndex(InitialWCSize);
827 const TArray<TVec3<int32>>& Elements = TriangleMesh.GetSurfaceElements();
828 const float HalfRadius = DetectRadius/2;
830 [this, &Spatial, &Particles, &SurfaceVertices, &ConstraintIndex, &TriangleMesh, &ExcludeMap, &Elements, &HalfRadius, &PositionTargetStiffness, &UseAnisotropicSpring](int32 i)
831 {
832 const int32 Index = SurfaceVertices[i];
833 TArray< TTriangleCollisionPoint<FSolverReal>> Result;
834 //PointProximityQuery
835 if (TriangleMesh.PointClosestTriangleQuery(Spatial, static_cast<const TArrayView<const FSolverVec3>&>(Particles.XArray()), Index, Particles.GetX(Index), HalfRadius, HalfRadius,
836 [this, &Elements, &ExcludeMap](const int32 PointIndex, const int32 TriangleIndex)->bool
837 {
838 return !(ExcludeMap.Find(PointIndex) && ExcludeMap[PointIndex].Contains(TriangleIndex));
839 },
840 Result))
841 {
843 {
844 if (CollisionPoint.Phi < 0)
845 {
846 const TVector<int32, 3>& Elem = Elements[CollisionPoint.Indices[1]];
847 const int32 IndexToWrite = ConstraintIndex.fetch_add(1);
848
851 SingleConstraintData.SingleSecondIndices = { Index };
852 SingleConstraintData.SingleWeights = { CollisionPoint.Bary[1], CollisionPoint.Bary[2], CollisionPoint.Bary[3] };
853 SingleConstraintData.SingleSecondWeights = {T(1.f)};
855 SingleConstraintData.SingleNormal = CollisionPoint.Normal;
856 SingleConstraintData.bIsZeroRestLength = true; //Push-out type collision springs should be zero rest length
857
858 float SpringStiffness = 0.f;
859 for (int32 k = 0; k < 3; k++)
860 {
861 SpringStiffness += SingleConstraintData.SingleWeights[k] * PositionTargetStiffness * Particles.M(Elem[k]);
862 }
864 SingleConstraintData.SingleStiffness = (T)SpringStiffness;
865 ConstraintsData.SetSingleConstraint(SingleConstraintData, IndexToWrite);
866 }
867 }
868 }
869 }
870 );
871
872 // Shrink the arrays to the actual number of found constraints.
873 const int32 ConstraintNum = ConstraintIndex.load();
874 Resize(ConstraintNum);
875 }
876
878 {
879 ensureMsgf(ConstraintsData.Size() >= InitialWCSize, TEXT("The size of Indices is smaller than InitialWCSize"));
880
881 ExtraConstraints.Init(TArray<int32>(), ConstraintsData.Size() - InitialWCSize);
882 for (int32 i = InitialWCSize; i < static_cast<int32>(ConstraintsData.Size()); i++)
883 {
884 const TArray<int32>& LocalIndices = ConstraintsData.GetIndices(i);
885 const TArray<int32>& LocalSecondIndices = ConstraintsData.GetSecondIndices(i);
886
887 ExtraConstraints[i - InitialWCSize].SetNum(LocalIndices.Num() + LocalSecondIndices.Num());
888 for (int32 j = 0; j < LocalIndices.Num(); j++)
889 {
890 ExtraConstraints[i - InitialWCSize][j] = LocalIndices[j];
891 }
892 for (int32 j = 0; j < LocalSecondIndices.Num(); j++)
893 {
894 ExtraConstraints[i - InitialWCSize][j + LocalIndices.Num()] = LocalSecondIndices[j];
895 }
896 }
897
899
900 NodalWeights = NoCollisionNodalWeights;
901 for (int32 i = 0; i < ExtraWCIncidentElements.Num(); i++)
902 {
903 if (ExtraWCIncidentElements[i].Num() > 0)
904 {
906 if (NodalWeights[p].Num() == 0)
907 {
908 NodalWeights[p].Init(T(0), 6);
909 }
910 for (int32 j = 0; j < ExtraWCIncidentElements[i].Num(); j++)
911 {
912 int32 LocalIndex = ExtraWCIncidentElementsLocal[i][j];
913 int32 ConstraintIndex = ExtraWCIncidentElements[i][j] + InitialWCSize;
914
915 const FGaussSeidelWeakConstraintSingleData<T>& SingleData = ConstraintsData.GetSingleConstraintData(ConstraintIndex);
916
917 T weight = T(0);
918 if (LocalIndex >= SingleData.SingleIndices.Num())
919 {
920 weight = SingleData.SingleWeights[LocalIndex - SingleData.SingleIndices.Num()];
921 }
922 else
923 {
924 weight = SingleData.SingleWeights[LocalIndex];
925 }
926 if (SingleData.bIsAnisotropic)
927 {
928 for (int32 alpha = 0; alpha < 3; alpha++)
929 {
930 NodalWeights[p][alpha] += SingleData.SingleNormal[alpha] * SingleData.SingleNormal[alpha] * weight * weight * SingleData.SingleStiffness;
931 }
932
933 NodalWeights[p][3] += SingleData.SingleNormal[0] * SingleData.SingleNormal[1] * weight * weight * SingleData.SingleStiffness;
934 NodalWeights[p][4] += SingleData.SingleNormal[0] * SingleData.SingleNormal[2] * weight * weight * SingleData.SingleStiffness;
935 NodalWeights[p][5] += SingleData.SingleNormal[1] * SingleData.SingleNormal[2] * weight * weight * SingleData.SingleStiffness;
936 }
937 else
938 {
939 for (int32 alpha = 0; alpha < 3; alpha++)
940 {
941 NodalWeights[p][alpha] += weight * weight * SingleData.SingleStiffness;
942 }
943 }
944 }
945 }
946 }
947 }
948
949
950 const TArray<TArray<int32>>& GetStaticConstraintArrays(TArray<TArray<int32>>& IncidentElements, TArray<TArray<int32>>& IncidentElementsLocal) const
951 {
952 IncidentElements = NoCollisionWCIncidentElements;
953 IncidentElementsLocal = NoCollisionWCIncidentElementsLocal;
954 return NoCollisionConstraints;
955 }
956
958 {
960 ExtraConstraints.Init(TArray<int32>(), ConstraintsData.Size());
961 for (int32 i = InitialWCSize; i < ConstraintsData.Size(); i++)
962 {
963 const TArray<int32>& LocalIndices = ConstraintsData.GetIndices(i);
964 const TArray<int32>& LocalSecondIndices = ConstraintsData.GetSecondIndices(i);
965 ExtraConstraints[i - InitialWCSize].SetNum(LocalIndices.Num() + LocalSecondIndices.Num());
966 for (int32 j = 0; j < LocalIndices.Num(); j++)
967 {
968 ExtraConstraints[i - InitialWCSize][j] = LocalIndices[j];
969 }
970 for (int32 j = 0; j < LocalSecondIndices.Num(); j++)
971 {
972 ExtraConstraints[i - InitialWCSize][j + LocalIndices.Num()] = LocalSecondIndices[j];
973 }
974 }
975
976 IncidentElements = Chaos::Utilities::ComputeIncidentElements(ExtraConstraints, &IncidentElementsLocal);
977
978 return ExtraConstraints;
979 }
980
981 // Deprecated, now replaced with AddWCResidual for more general cases
982 void AddZeroRestLengthWCResidualAndHessian(const ParticleType& InParticles, const int32 ConstraintIndex, const int32 LocalIndex, const T Dt, TVec3<T>& ParticleResidual, Chaos::PMatrix<T, 3, 3>& ParticleHessian) const
983 {
984 const FGaussSeidelWeakConstraintSingleData<T>& SingleData = ConstraintsData.GetSingleConstraintData(ConstraintIndex);
985
986 const TVec3<T> SpringEdge = ComputeSpringEdge(InParticles, SingleData.SingleIndices, SingleData.SingleSecondIndices,
987 SingleData.SingleWeights, SingleData.SingleSecondWeights, /*bUseParticleX =*/false);
988 T weight = T(0);
989 if (LocalIndex >= SingleData.SingleIndices.Num())
990 {
991 weight = -SingleData.SingleSecondWeights[LocalIndex - SingleData.SingleIndices.Num()];
992 }
993 else
994 {
995 weight = SingleData.SingleWeights[LocalIndex];
996 }
997 if (SingleData.bIsAnisotropic)
998 {
999 T comp = TVec3<T>::DotProduct(SpringEdge, SingleData.SingleNormal);
1000 TVec3<T> proj = SingleData.SingleNormal * comp;
1001 for (int32 alpha = 0; alpha < 3; alpha++)
1002 {
1003 ParticleResidual[alpha] += Dt * Dt * SingleData.SingleStiffness * proj[alpha] * weight;
1004 }
1005 }
1006 else
1007 {
1008 for (int32 alpha = 0; alpha < 3; alpha++)
1009 {
1010 ParticleResidual[alpha] += Dt * Dt * SingleData.SingleStiffness * SpringEdge[alpha] * weight;
1011 }
1012 }
1013 }
1014
1015 void AddWCResidual(const ParticleType& InParticles, const int32 ConstraintIndex, const int32 LocalIndex, const T Dt, TVec3<T>& ParticleResidual, Chaos::PMatrix<T, 3, 3>& ParticleHessian) const
1016 {
1017 const FGaussSeidelWeakConstraintSingleData<T>& SingleData = ConstraintsData.GetSingleConstraintData(ConstraintIndex);
1018
1019 const TVec3<T> SpringEdge = ComputeSpringEdge(InParticles, SingleData.SingleIndices, SingleData.SingleSecondIndices,
1020 SingleData.SingleWeights, SingleData.SingleSecondWeights, /*bUseParticleX =*/false);
1021 T weight = T(0);
1022 if (LocalIndex >= SingleData.SingleIndices.Num())
1023 {
1024 weight = -SingleData.SingleSecondWeights[LocalIndex - SingleData.SingleIndices.Num()];
1025 }
1026 else
1027 {
1028 weight = SingleData.SingleWeights[LocalIndex];
1029 }
1031 if (SingleData.bIsAnisotropic)
1032 {
1033 T LengthDiff = TVec3<T>::DotProduct(SpringEdge, SingleData.SingleNormal) - SingleData.RestLength;
1034 Projection = SingleData.SingleNormal * LengthDiff;
1035 }
1036 else
1037 {
1039 if (!SingleData.bIsZeroRestLength) // if not zero rest-length, apply repulsion force
1040 {
1042 }
1043 }
1044 for (int32 alpha = 0; alpha < 3; ++alpha)
1045 {
1046 ParticleResidual[alpha] += Dt * Dt * SingleData.SingleStiffness * Projection[alpha] * weight;
1047 }
1048 }
1049
1051
1053
1056
1058
1064 };
1065
1066
1067}// End namespace Chaos::Softs
#define check(expr)
Definition AssertionMacros.h:314
#define ensureMsgf( InExpression, InFormat,...)
Definition AssertionMacros.h:465
#define ensure( InExpression)
Definition AssertionMacros.h:464
@ INDEX_NONE
Definition CoreMiscDefines.h:150
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
#define TRACE_CPUPROFILER_EVENT_SCOPE(Name)
Definition CpuProfilerTrace.h:528
UE::Math::TVector< double > FVector3d
Definition MathFwd.h:60
@ Num
Definition MetalRHIPrivate.h:234
AUTORTFM_INFER constexpr auto Projection(Invocable0Type &&Invocable0, InvocableTypes &&... Invocables)
Definition Projection.h:108
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
uint32 Offset
Definition VulkanMemory.cpp:4033
uint32 Size
Definition VulkanMemory.cpp:4034
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition TriangleMesh.h:24
Definition Matrix.h:21
Definition PBDSoftsSolverParticles.h:20
const FSolverVec3 & P(const int32 index) const
Definition PBDSoftsSolverParticles.h:36
Definition GaussSeidelWeakConstraints.h:39
void SetRestLength(const int32 Index, const T InRestLength)
Definition GaussSeidelWeakConstraints.h:241
void SetWeights(const int32 Index, const TArray< int32 > &InWeights)
Definition GaussSeidelWeakConstraints.h:171
TGaussSeidelWeakConstraintData()
Definition GaussSeidelWeakConstraints.h:41
const TArrayCollectionArray< TArray< T > > & Weights() const
Definition GaussSeidelWeakConstraints.h:161
virtual ~TGaussSeidelWeakConstraintData()
Definition GaussSeidelWeakConstraints.h:75
const TArrayCollectionArray< TArray< int32 > > & SecondIndices() const
Definition GaussSeidelWeakConstraints.h:146
void SetIsZeroRestLength(const int32 Index, const bool InIsZeroRestLength)
Definition GaussSeidelWeakConstraints.h:236
void SetIndices(const int32 Index, const TArray< int32 > &InIndices)
Definition GaussSeidelWeakConstraints.h:141
const TArrayCollectionArray< TArray< T > > & SecondWeights() const
Definition GaussSeidelWeakConstraints.h:176
const FGaussSeidelWeakConstraintSingleData< T > GetSingleConstraintData(const int32 ConstraintIndex) const
Definition GaussSeidelWeakConstraints.h:246
void RemoveConstraint(const int32 Idx)
Definition GaussSeidelWeakConstraints.h:83
void SetSingleConstraint(const FGaussSeidelWeakConstraintSingleData< T > &SingleData, const int32 ConstraintIndex)
Definition GaussSeidelWeakConstraints.h:88
const TArrayCollectionArray< TArray< int32 > > & Indices() const
Definition GaussSeidelWeakConstraints.h:131
TGaussSeidelWeakConstraintData & operator=(TGaussSeidelWeakConstraintData< T > &&Other)
Definition GaussSeidelWeakConstraints.h:116
const TArrayCollectionArray< T > & Stiffness() const
Definition GaussSeidelWeakConstraints.h:216
TGaussSeidelWeakConstraintData(TGaussSeidelWeakConstraintData< T > &&Other)
Definition GaussSeidelWeakConstraints.h:54
void Resize(const int32 Num)
Definition GaussSeidelWeakConstraints.h:111
TGaussSeidelWeakConstraintData(const TGaussSeidelWeakConstraintData< T > &Other)=delete
const TArray< int32 > & GetSecondIndices(const int32 Index) const
Definition GaussSeidelWeakConstraints.h:151
const TArray< int32 > & GetIndices(const int32 Index) const
Definition GaussSeidelWeakConstraints.h:136
void SetStiffness(const int32 Index, const T InStiffness)
Definition GaussSeidelWeakConstraints.h:226
const bool GetIsAnisotropic(const int32 Index) const
Definition GaussSeidelWeakConstraints.h:191
void SetIsAnisotropic(const int32 Index, const bool InIsAnisotropic)
Definition GaussSeidelWeakConstraints.h:196
void AddSingleConstraint(const FGaussSeidelWeakConstraintSingleData< T > &SingleData)
Definition GaussSeidelWeakConstraints.h:100
const bool GetIsZeroRestLength(const int32 Index) const
Definition GaussSeidelWeakConstraints.h:231
const TArrayCollectionArray< TVec3< T > > & Normals() const
Definition GaussSeidelWeakConstraints.h:201
int32 Size() const
Definition GaussSeidelWeakConstraints.h:106
const TVec3< T > & GetNormal(const int32 Index) const
Definition GaussSeidelWeakConstraints.h:206
void SetNormal(const int32 Index, const TVec3< T > &InNormal)
Definition GaussSeidelWeakConstraints.h:211
void AddConstraints(const int32 Num)
Definition GaussSeidelWeakConstraints.h:78
void SetSecondWeights(const int32 Index, const TArray< int32 > &InWeights)
Definition GaussSeidelWeakConstraints.h:186
const TArray< T > & GetSecondWeights(const int32 Index) const
Definition GaussSeidelWeakConstraints.h:181
void SetSecondIndices(const int32 Index, const TArray< int32 > &InIndices)
Definition GaussSeidelWeakConstraints.h:156
T GetStiffness(const int32 Index) const
Definition GaussSeidelWeakConstraints.h:221
const TArray< T > & GetWeights(const int32 Index) const
Definition GaussSeidelWeakConstraints.h:166
Definition ArrayCollectionArray.h:15
Definition ArrayCollection.h:10
uint32 MSize
Definition ArrayCollection.h:152
int32 AddArray(TArrayCollectionArrayBase *Array)
Definition ArrayCollection.h:36
uint32 Size() const
Definition ArrayCollection.h:66
void ResizeHelper(const int32 Num)
Definition ArrayCollection.h:93
void RemoveAtSwapHelper(const int32 Index)
Definition ArrayCollection.h:119
void AddElementsHelper(const int32 Num)
Definition ArrayCollection.h:84
Definition BoundingVolumeHierarchy.h:60
const T M(const int32 Index) const
Definition DynamicParticles.h:43
Definition Vector.h:1000
TVector< T, 3 > GetSafeNormal() const
Definition Vector.h:1079
Definition Vector.h:41
Definition Array.h:670
UE_REWRITE SizeType Num() const
Definition Array.h:1144
bool Contains(const ComparisonType &Item) const
Definition Array.h:1518
UE_FORCEINLINE_HINT SizeType Emplace(ArgsType &&... Args)
Definition Array.h:2561
void SetNum(SizeType NewNum, EAllowShrinking AllowShrinking=UE::Core::Private::AllowShrinkingByDefault< AllocatorType >())
Definition Array.h:2308
void Init(const ElementType &Element, SizeType Number)
Definition Array.h:3043
UE_NODEBUG void Sort()
Definition Array.h:3418
Definition UnrealString.h.inl:34
Definition CollectionEmbeddedSpringConstraintFacade.cpp:6
TArray< TArray< int > > ComputeIncidentElements(const TArray< TVector< int32, d > > &Mesh, TArray< TArray< int32 > > *LocalIndex=nullptr)
Definition Utilities.h:1013
TSphere< FReal, 3 > FSphere
Definition ImplicitObject.h:36
void CHAOS_API PhysicsParallelFor(int32 InNum, TFunctionRef< void(int32)> InCallable, bool bForceSingleThreaded=false)
Definition Parallel.cpp:55
FRealDouble FReal
Definition Real.h:22
TVector< T, d > FindClosestPointAndBaryOnTriangle(const TVector< T, d > &P0, const TVector< T, d > &P1, const TVector< T, d > &P2, const TVector< T, d > &P, TVector< T, 3 > &Bary)
Definition Plane.h:220
float FRealSingle
Definition Real.h:14
U16 Index
Definition radfft.cpp:71
Definition XPBDWeakConstraints.h:25
bool bVisualizeBindings
Definition XPBDWeakConstraints.h:28
float DebugLineWidth
Definition XPBDWeakConstraints.h:26
float DebugParticleWidth
Definition XPBDWeakConstraints.h:27
Definition GaussSeidelWeakConstraints.h:25
TArray< int32 > SingleIndices
Definition GaussSeidelWeakConstraints.h:26
TArray< T > SingleWeights
Definition GaussSeidelWeakConstraints.h:29
T RestLength
Definition GaussSeidelWeakConstraints.h:34
TArray< T > SingleSecondWeights
Definition GaussSeidelWeakConstraints.h:30
bool bIsAnisotropic
Definition GaussSeidelWeakConstraints.h:31
bool bIsZeroRestLength
Definition GaussSeidelWeakConstraints.h:33
T SingleStiffness
Definition GaussSeidelWeakConstraints.h:28
TVec3< T > SingleNormal
Definition GaussSeidelWeakConstraints.h:32
TArray< int32 > SingleSecondIndices
Definition GaussSeidelWeakConstraints.h:27
int32 ConstraintIndex
Definition GaussSeidelWeakConstraints.h:322
Definition GaussSeidelWeakConstraints.h:281
FGaussSeidelWeakConstraints(const TArray< TArray< int32 > > &InIndices, const TArray< TArray< T > > &InWeights, const TArray< T > &InStiffness, const TArray< TArray< int32 > > &InSecondIndices, const TArray< TArray< T > > &InSecondWeights, const FDeformableXPBDWeakConstraintParams &InParams)
Definition GaussSeidelWeakConstraints.h:283
TArray< TArray< int32 > > NoCollisionWCIncidentElementsLocal
Definition GaussSeidelWeakConstraints.h:1063
FDeformableXPBDWeakConstraintParams DebugDrawParams
Definition GaussSeidelWeakConstraints.h:1057
void AddWCResidual(const ParticleType &InParticles, const int32 ConstraintIndex, const int32 LocalIndex, const T Dt, TVec3< T > &ParticleResidual, Chaos::PMatrix< T, 3, 3 > &ParticleHessian) const
Definition GaussSeidelWeakConstraints.h:1015
TVec3< T > ComputeSpringEdge(const ParticleType &InParticles, const TArray< int32 > &LocalIndices, const TArray< int32 > &LocalSecondIndices, const TArray< T > &Weight, const TArray< T > &SecondWeight, bool bUseParticleX) const
Definition GaussSeidelWeakConstraints.h:382
virtual ~FGaussSeidelWeakConstraints()
Definition GaussSeidelWeakConstraints.h:325
void UpdatePointTriangleCollisionWCData(const FSolverParticles &Particles)
Definition GaussSeidelWeakConstraints.h:481
const TArray< TArray< int32 > > & GetStaticConstraintArrays(TArray< TArray< int32 > > &IncidentElements, TArray< TArray< int32 > > &IncidentElementsLocal) const
Definition GaussSeidelWeakConstraints.h:950
TArray< TArray< int32 > > WCIncidentElementsLocal
Definition GaussSeidelWeakConstraints.h:1055
TArray< TArray< T > > NoCollisionNodalWeights
Definition GaussSeidelWeakConstraints.h:1060
void Resize(int32 Size)
Definition GaussSeidelWeakConstraints.h:476
void CollisionDetectionSpatialHashInComponent(const FSolverParticles &Particles, const TArray< int32 > &SurfaceVertices, const FTriangleMesh &TriangleMesh, const TMap< int32, TSet< int32 > > &ExcludeMap, const SpatialAccelerator &Spatial, float DetectRadius=0.f, float PositionTargetStiffness=10000.f, bool UseAnisotropicSpring=true)
Definition GaussSeidelWeakConstraints.h:822
TGaussSeidelWeakConstraintData< T > ConstraintsData
Definition GaussSeidelWeakConstraints.h:1050
void AddZeroRestLengthWCResidualAndHessian(const ParticleType &InParticles, const int32 ConstraintIndex, const int32 LocalIndex, const T Dt, TVec3< T > &ParticleResidual, Chaos::PMatrix< T, 3, 3 > &ParticleHessian) const
Definition GaussSeidelWeakConstraints.h:982
void CollisionDetectionSpatialHash(const FSolverParticles &Particles, const TArray< int32 > &SurfaceVertices, const FTriangleMesh &TriangleMesh, const TArray< int32 > &ComponentIndex, const SpatialAccelerator &Spatial, float DetectRadius=1.f, float PositionTargetStiffness=10000.f, bool UseAnisotropicSpring=true)
Definition GaussSeidelWeakConstraints.h:765
void ComputeInitialWCData(const ParticleType &InParticles)
Definition GaussSeidelWeakConstraints.h:327
void AddWCHessian(const int32 p, const T Dt, Chaos::PMatrix< T, 3, 3 > &ParticleHessian) const
Definition GaussSeidelWeakConstraints.h:426
void UpdateTriangleNormalAndNodalWeight(const FSolverParticles &InParticles, bool bUseParticleX)
Definition GaussSeidelWeakConstraints.h:557
TArray< TArray< int32 > > WCIncidentElements
Definition GaussSeidelWeakConstraints.h:1054
TArray< TArray< int32 > > NoCollisionConstraints
Definition GaussSeidelWeakConstraints.h:1061
void Init(const FSolverParticles &InParticles, const T Dt)
Definition GaussSeidelWeakConstraints.h:548
TArray< TArray< T > > NodalWeights
Definition GaussSeidelWeakConstraints.h:1052
TArray< TArray< int32 > > NoCollisionWCIncidentElements
Definition GaussSeidelWeakConstraints.h:1062
void VisualizeAllBindings(const FSolverParticles &InParticles, const T Dt) const
Definition GaussSeidelWeakConstraints.h:502
void CollisionDetectionBVH(const FSolverParticles &Particles, const TArray< TVec3< int32 > > &SurfaceElements, const TArray< int32 > &ComponentIndex, float DetectRadius=1.f, float PositionTargetStiffness=10000.f, bool UseAnisotropicSpring=true)
Definition GaussSeidelWeakConstraints.h:627
TArray< TArray< int32 > > GetDynamicConstraintArrays(TArray< TArray< int32 > > &IncidentElements, TArray< TArray< int32 > > &IncidentElementsLocal) const
Definition GaussSeidelWeakConstraints.h:957
void ComputeCollisionWCDataSimplified(TArray< TArray< int32 > > &ExtraConstraints, TArray< TArray< int32 > > &ExtraWCIncidentElements, TArray< TArray< int32 > > &ExtraWCIncidentElementsLocal)
Definition GaussSeidelWeakConstraints.h:877
int32 InitialWCSize
Definition GaussSeidelWeakConstraints.h:1059
void AddExtraConstraints(const TArray< TArray< int32 > > &InIndices, const TArray< TArray< T > > &InWeights, const TArray< T > &InStiffness, const TArray< TArray< int32 > > &InSecondIndices, const TArray< TArray< T > > &InSecondWeights, const TArray< bool > &InIsAnisotrpic, const TArray< bool > &InIsZeroRestLength)
Definition GaussSeidelWeakConstraints.h:450
Data returned by TriangleMesh point-triangle and edge-edge queries.
Definition TriangleCollisionPoint.h:17
static CORE_API const FColor Red
Definition Color.h:752
static CORE_API const FColor Yellow
Definition Color.h:755
static CORE_API const FColor Green
Definition Color.h:753
static UE_FORCEINLINE_HINT float DotProduct(const TVector< float > &A, const TVector< float > &B)
Definition Vector.h:1559
TVector< T > GetSafeNormal(T Tolerance=UE_SMALL_NUMBER, const TVector< T > &ResultIfZero=ZeroVector) const
Definition Vector.h:2060
static UE_FORCEINLINE_HINT TVector< float > CrossProduct(const TVector< float > &A, const TVector< float > &B)
Definition Vector.h:1541