UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
XPBDWeakConstraints.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2#pragma once
3
5#include "ChaosStats.h"
8#include "Chaos/MPMTransfer.h"
10#include "Misc/FileHelper.h"
12#include "HAL/IConsoleManager.h"
13#include "Misc/Paths.h"
14#include "Chaos/GraphColoring.h"
16
17//DECLARE_CYCLE_STAT(TEXT("Chaos XPBD Corotated Constraint"), STAT_ChaosXPBDCorotated, STATGROUP_Chaos);
18//DECLARE_CYCLE_STAT(TEXT("Chaos XPBD Corotated Constraint Polar Compute"), STAT_ChaosXPBDCorotatedPolar, STATGROUP_Chaos);
19//DECLARE_CYCLE_STAT(TEXT("Chaos XPBD Corotated Constraint Det Compute"), STAT_ChaosXPBDCorotatedDet, STATGROUP_Chaos);
20
21namespace Chaos::Softs
22{
23
30
31 using Chaos::TVec3;
32
33 template <typename T, typename ParticleType>
35 {
36
37 public:
38 //this one only accepts tetmesh input and mesh
40 const ParticleType& InParticles,
44 )
46 {
49 InitColor(InParticles);
50 LambdaArray.Init((T)0., Indices.Num() * 3);
51 }
52
54 const ParticleType& InParticles,
61 )
63 {
64 ensureMsgf(Indices.Num() == SecondIndices.Num(), TEXT("Input Double Bindings have wrong size"));
65
66 for (int32 i = 0; i < Indices.Num(); i++)
67 {
69 for (int32 j = 0; j < SecondIndices[i].Num(); j++)
70 {
71 ensureMsgf(!IndicesSet.Contains(SecondIndices[i][j]), TEXT("Indices and Second Indices overlaps. Currently not supported"));
72 }
73 }
74 InitColor(InParticles);
75 LambdaArray.Init((T)0., Indices.Num() * 3);
76 }
77
78
80
81 void ApplyInParallel(ParticleType& Particles, const T Dt) const
82 {
84
85 if ((ConstraintsPerColor.Num() > 0))
86 {
87 if (SecondIndices.Num() == 0)
88 {
90 {
92 {
93 const int32 ConstraintIndex = ConstraintsPerColor[Color][Index];
94 ApplySingleConstraintWithoutSelfTarget(Particles, Dt, ConstraintIndex);
95 });
96 }
97 }
98 else
99 {
100 for (int32 Color = 0; Color < ConstraintsPerColor.Num(); Color++)
101 {
103 {
104 const int32 ConstraintIndex = ConstraintsPerColor[Color][Index];
105 ApplySingleConstraintWithSelfTarget(Particles, Dt, ConstraintIndex);
106 });
107 }
108 }
109 }
110 }
111
112
114 {
115 return Indices;
116 }
117
118 void Init(const FSolverParticles& InParticles, const T Dt) const
119 {
120 for (T& Lambdas : LambdaArray) { Lambdas = (T)0.; }
122 {
123 VisualizeAllBindings(InParticles, Dt);
124 }
125 }
126
131
132
133 private:
134
135 void InitColor(const ParticleType& Particles)
136 {
138 }
139
140 void ApplySingleConstraintWithoutSelfTarget(ParticleType& Particles, const T Dt, const int32 ConstraintIndex, const T Tol = UE_KINDA_SMALL_NUMBER) const
141 {
142 if (Stiffness[ConstraintIndex] < Tol)
143 {
144 return;
145 }
146
147 T AlphaTilde = T(2) / (Stiffness[ConstraintIndex] * Dt * Dt);
148
149 if (Stiffness[ConstraintIndex] > 1e14)
150 {
151 AlphaTilde = T(0);
152 }
153
154 TVec3<T> SpringEdge((T)0.);
155 for (int32 j = 0; j < Indices[ConstraintIndex].Num(); j++) {
156 for (int32 alpha = 0; alpha < 3; alpha++) {
157 SpringEdge[alpha] += Weights[ConstraintIndex][j] * Particles.P(Indices[ConstraintIndex][j])[alpha];
158 }
159 }
160
161 SpringEdge -= Constraints[ConstraintIndex];
162
163 T Denom = AlphaTilde;
164 for (int32 j = 0; j < Indices[ConstraintIndex].Num(); j++) {
165 Denom += Weights[ConstraintIndex][j] * Weights[ConstraintIndex][j] * Particles.InvM(Indices[ConstraintIndex][j]);
166
167 }
168
169 for (int32 Beta = 0; Beta < 3; Beta++)
170 {
171 T Cj = SpringEdge[Beta];
172 T DLambda = -Cj - AlphaTilde * LambdaArray[ConstraintIndex * 3 + Beta];
173
174 DLambda /= Denom;
175 LambdaArray[ConstraintIndex * 3 + Beta] += DLambda;
176 for (int32 j = 0; j < Indices[ConstraintIndex].Num(); j++) {
177 Particles.P(Indices[ConstraintIndex][j])[Beta] += DLambda * Weights[ConstraintIndex][j] * Particles.InvM(Indices[ConstraintIndex][j]);
178 }
179 }
180 }
181
182 void ApplySingleConstraintWithSelfTarget(ParticleType& Particles, const T Dt, const int32 ConstraintIndex, const T Tol = UE_KINDA_SMALL_NUMBER) const
183 {
184 if (Stiffness[ConstraintIndex] < Tol)
185 {
186 return;
187 }
188
189 ensure(SecondIndices.Num() > 0);
190
191 T AlphaTilde = T(2) / (Stiffness[ConstraintIndex] * Dt * Dt);
192
193 if (Stiffness[ConstraintIndex] > 1e14)
194 {
195 AlphaTilde = T(0);
196 }
197
198 TVec3<T> SpringEdge((T)0.);
199 for (int32 j = 0; j < Indices[ConstraintIndex].Num(); j++) {
200 for (int32 alpha = 0; alpha < 3; alpha++) {
201 SpringEdge[alpha] += Weights[ConstraintIndex][j] * Particles.P(Indices[ConstraintIndex][j])[alpha];
202 }
203 }
204
205 for (int32 j = 0; j < SecondIndices[ConstraintIndex].Num(); j++) {
206
207 SpringEdge -= SecondWeights[ConstraintIndex][j] * Particles.P(SecondIndices[ConstraintIndex][j]);
208
209 }
210
211 T Denom = AlphaTilde;
212 for (int32 j = 0; j < Indices[ConstraintIndex].Num(); j++) {
213 Denom += Weights[ConstraintIndex][j] * Weights[ConstraintIndex][j] * Particles.InvM(Indices[ConstraintIndex][j]);
214 }
215
216 for (int32 j = 0; j < SecondIndices[ConstraintIndex].Num(); j++) {
217 Denom += SecondWeights[ConstraintIndex][j] * SecondWeights[ConstraintIndex][j] * Particles.InvM(SecondIndices[ConstraintIndex][j]);
218 }
219
220
221 for (int32 Beta = 0; Beta < 3; Beta++)
222 {
223 T Cj = SpringEdge[Beta];
224 T DLambda = -Cj - AlphaTilde * LambdaArray[ConstraintIndex * 3 + Beta];
225
226 DLambda /= Denom;
227 LambdaArray[ConstraintIndex * 3 + Beta] += DLambda;
228 for (int32 j = 0; j < Indices[ConstraintIndex].Num(); j++) {
229 Particles.P(Indices[ConstraintIndex][j])[Beta] += DLambda * Weights[ConstraintIndex][j] * Particles.InvM(Indices[ConstraintIndex][j]);
230 }
231
232 for (int32 j = 0; j < SecondIndices[ConstraintIndex].Num(); j++) {
233 Particles.P(SecondIndices[ConstraintIndex][j])[Beta] -= DLambda * SecondWeights[ConstraintIndex][j] * Particles.InvM(SecondIndices[ConstraintIndex][j]);
234 }
235 }
236 }
237
238 void VisualizeAllBindings(const FSolverParticles& InParticles, const T Dt) const
239 {
240#if WITH_EDITOR
241 auto DoubleVert = [](Chaos::TVec3<T> V) { return FVector3d(V.X, V.Y, V.Z); };
242 for (int32 i = 0; i < Indices.Num(); i++)
243 {
244 Chaos::TVec3<T> SourcePos((T)0.), TargetPos((T)0.);
245 for (int32 j = 0; j < Indices[i].Num(); j++)
246 {
247 SourcePos += Weights[i][j] * InParticles.P(Indices[i][j]);
248 }
249 for (int32 j = 0; j < SecondIndices[i].Num(); j++)
250 {
252 }
253
256
257 if (Indices[i].Num() == 1)
258 {
259 Chaos::FDebugDrawQueue::GetInstance().DrawDebugPoint(DoubleVert(SourcePos), FColor::Red, false, Dt, 0, ParticleThickness);
260 for (int32 j = 0; j < SecondIndices[i].Num(); j++)
261 {
262 Chaos::FDebugDrawQueue::GetInstance().DrawDebugPoint(DoubleVert(InParticles.P(SecondIndices[i][j])), FColor::Green, false, Dt, 0, ParticleThickness);
263 Chaos::FDebugDrawQueue::GetInstance().DrawDebugLine(DoubleVert(InParticles.P(SecondIndices[i][j])), DoubleVert(InParticles.P(SecondIndices[i][(j+1) % SecondIndices[i].Num()])), FColor::Green, false, Dt, 0, LineThickness);
264 }
265
266 }
267
268 if (SecondIndices[i].Num() == 1)
269 {
270 Chaos::FDebugDrawQueue::GetInstance().DrawDebugPoint(DoubleVert(TargetPos), FColor::Red, false, Dt, 0, ParticleThickness);
271 for (int32 j = 0; j < Indices[i].Num(); j++)
272 {
273 Chaos::FDebugDrawQueue::GetInstance().DrawDebugPoint(DoubleVert(InParticles.P(Indices[i][j])), FColor::Green, false, Dt, 0, ParticleThickness);
274 Chaos::FDebugDrawQueue::GetInstance().DrawDebugLine(DoubleVert(InParticles.P(Indices[i][j])), DoubleVert(InParticles.P(Indices[i][(j + 1) % SecondIndices[i].Num()])), FColor::Green, false, Dt, 0, LineThickness);
275 }
276 }
277
278 Chaos::FDebugDrawQueue::GetInstance().DrawDebugLine(DoubleVert(SourcePos), DoubleVert(TargetPos), FColor::Yellow, false, Dt, 0, LineThickness);
279 }
280#endif
281 }
282
283
284 protected:
293 bool VisualizeBindings = false;
295 };
296
297
298
299} // End namespace Chaos::Softs
300
#define ensureMsgf( InExpression, InFormat,...)
Definition AssertionMacros.h:465
#define ensure( InExpression)
Definition AssertionMacros.h:464
#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
#define UE_KINDA_SMALL_NUMBER
Definition UnrealMathUtility.h:131
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
Definition PBDSoftsSolverParticles.h:20
Definition XPBDWeakConstraints.h:35
TArray< T > LambdaArray
Definition XPBDWeakConstraints.h:292
TArray< TVector< T, 3 > > Constraints
Definition XPBDWeakConstraints.h:287
TArray< T > Stiffness
Definition XPBDWeakConstraints.h:290
FDeformableXPBDWeakConstraintParams DebugDrawParams
Definition XPBDWeakConstraints.h:294
void UpdateTargets(TArray< TVector< T, 3 > > &&InTargets)
Definition XPBDWeakConstraints.h:127
bool VisualizeBindings
Definition XPBDWeakConstraints.h:293
void Init(const FSolverParticles &InParticles, const T Dt) const
Definition XPBDWeakConstraints.h:118
TArray< TArray< T > > SecondWeights
Definition XPBDWeakConstraints.h:289
FXPBDWeakConstraints(const ParticleType &InParticles, 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 XPBDWeakConstraints.h:53
TArray< TArray< int32 > > SecondIndices
Definition XPBDWeakConstraints.h:288
TArray< TArray< int32 > > ConstraintsPerColor
Definition XPBDWeakConstraints.h:291
virtual ~FXPBDWeakConstraints()
Definition XPBDWeakConstraints.h:79
TArray< TArray< int32 > > Indices
Definition XPBDWeakConstraints.h:285
const TArray< TArray< int32 > > & GetIndices()
Definition XPBDWeakConstraints.h:113
FXPBDWeakConstraints(const ParticleType &InParticles, const TArray< TArray< int32 > > &InIndices, const TArray< TArray< T > > &InWeights, const TArray< T > &InStiffness)
Definition XPBDWeakConstraints.h:39
void ApplyInParallel(ParticleType &Particles, const T Dt) const
Definition XPBDWeakConstraints.h:81
TArray< TArray< T > > Weights
Definition XPBDWeakConstraints.h:286
Definition Vector.h:1000
Definition Vector.h:41
Definition Constraints.Build.cs:6
Definition Array.h:670
UE_REWRITE SizeType Num() const
Definition Array.h:1144
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
Definition CollectionEmbeddedSpringConstraintFacade.cpp:6
void CHAOS_API PhysicsParallelFor(int32 InNum, TFunctionRef< void(int32)> InCallable, bool bForceSingleThreaded=false)
Definition Parallel.cpp:55
CHAOS_API void ComputeWeakConstraintsColoring(const TArray< TArray< int32 > > &Indices, const TArray< TArray< int32 > > &SecondIndices, const Chaos::TDynamicParticles< T, 3 > &InParticles, TArray< TArray< int32 > > &ConstraintsPerColor)
const float LineThickness
Definition CrowdManager.cpp:100
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
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