UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
PBDAltitudeSpringConstraints.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
9
10namespace Chaos::Softs
11{
12
14 {
15 public:
18 {
19
20 RestLength.Init((FSolverReal)0., 4 * Constraints.Num());
21 Volumes.Init((FSolverReal)0., Constraints.Num());
22 for (int32 ElementIndex = 0; ElementIndex < Constraints.Num(); ElementIndex++)
23 {
24 TVec4<int32> Constraint = Constraints[ElementIndex];
25 for (int32 i = 0; i < 4; i++)
26 {
27 const FSolverVec3& P1 = InParticles.GetX(Constraint[i]);
28 const FSolverVec3& P2 = InParticles.GetX(Constraint[(i + 1) % 4]);
29 const FSolverVec3& P3 = InParticles.GetX(Constraint[(i + 2) % 4]);
30 const FSolverVec3& P4 = InParticles.GetX(Constraint[(i + 3) % 4]);
31 RestLength[4* ElementIndex +i] = FSolverVec3::DotProduct(FSolverVec3::CrossProduct(P3 - P2, P4 - P2), P1 - P2) / FSolverVec3::CrossProduct(P3 - P2, P4 - P2).Size();
32
33 }
34 const FSolverVec3& P1 = InParticles.GetX(Constraint[0]);
35 const FSolverVec3& P2 = InParticles.GetX(Constraint[1]);
36 const FSolverVec3& P3 = InParticles.GetX(Constraint[2]);
37 const FSolverVec3& P4 = InParticles.GetX(Constraint[3]);
38 Volumes[ElementIndex] = FSolverVec3::DotProduct(FSolverVec3::CrossProduct(P2 - P1, P3 - P1), P4 - P1) / (FSolverReal)6.;
39 }
40
41 InitColor(InParticles);
42 }
44
45 TVec4<FSolverVec3> GetGradients(const FSolverParticles& InParticles, const int32 ElementIndex, const int32 ie) const
46 {
48 const TVec4<int32>& Constraint = Constraints[ElementIndex];
49 const int32 i1 = Constraint[ie];
50 const int32 i2 = Constraint[(ie + 1) % 4];
51 const int32 i3 = Constraint[(ie + 2) % 4];
52 const int32 i4 = Constraint[(ie + 3) % 4];
53 const FSolverVec3& P1 = InParticles.P(i1);
54 const FSolverVec3& P2 = InParticles.P(i2);
55 const FSolverVec3& P3 = InParticles.P(i3);
56 const FSolverVec3& P4 = InParticles.P(i4);
57 const FSolverVec3 P1P2 = P1 - P2;
58 const FSolverVec3 P3P2 = P3 - P2;
59 const FSolverVec3 P4P2 = P4 - P2;
60
61 FSolverVec3 ScaledBottomNormal = FSolverVec3::CrossProduct(P3 - P2, P4 - P2);
62 FSolverReal ScaledVolume = FSolverVec3::DotProduct(ScaledBottomNormal, P1 - P2);
75 dAdX[1] = -dAdX[2] - dAdX[3];
76
78 dVdX[0] = FSolverVec3::CrossProduct(P3P2, P4P2);
79 dVdX[2] = FSolverVec3::CrossProduct(P4P2, P1P2);
80 dVdX[3] = FSolverVec3::CrossProduct(P1P2, P3P2);
81 dVdX[1] = -(dVdX[0] + dVdX[2] + dVdX[3]);
82 for (int32 je = 0; je < 4; je++)
83 {
85 }
86
87
88 return Grads;
89 }
90
92 {
93 const TVec4<int32>& Constraint = Constraints[ElementIndex];
94 const int32 i1 = Constraint[ie];
95 const int32 i2 = Constraint[(ie + 1) % 4];
96 const int32 i3 = Constraint[(ie + 2) % 4];
97 const int32 i4 = Constraint[(ie + 3) % 4];
98 const FSolverVec3& P1 = InParticles.P(i1);
99 const FSolverVec3& P2 = InParticles.P(i2);
100 const FSolverVec3& P3 = InParticles.P(i3);
101 const FSolverVec3& P4 = InParticles.P(i4);
102 FSolverVec3 ScaledBottomNormal = FSolverVec3::CrossProduct(P3 - P2, P4 - P2);
103 FSolverReal ScaledVolume = FSolverVec3::DotProduct(ScaledBottomNormal, P1 - P2);
104 FSolverReal CurrentLength = ScaledVolume / ScaledBottomNormal.Size();
105 const FSolverReal S = (CurrentLength - RestLength[4*ElementIndex+ie]) / (
106 InParticles.InvM(i1) * Grads[0].SizeSquared() +
107 InParticles.InvM(i2) * Grads[1].SizeSquared() +
108 InParticles.InvM(i3) * Grads[2].SizeSquared() +
109 InParticles.InvM(i4) * Grads[3].SizeSquared());
110 return Stiffness * S;
111 }
112
113 virtual void ApplySingleElement(FSolverParticles& Particles, const FSolverReal Dt, const int32 ElementIndex) const
114 {
116 const TVec4<int32>& Constraint = Constraints[ElementIndex];
117 for (int ie = 0; ie < 4; ++ie)
118 {
119
120 const int32 i1 = Constraint[ie];
121 const int32 i2 = Constraint[(ie + 1) % 4];
122 const int32 i3 = Constraint[(ie + 2) % 4];
123 const int32 i4 = Constraint[(ie + 3) % 4];
124 const TVec4<FSolverVec3> Grads = GetGradients(Particles, ElementIndex, ie);
125 const FSolverReal S = GetScalingFactor(Particles, ElementIndex, ie, Grads);
126 Particles.P(i1) -= S * Particles.InvM(i1) * Grads[0];
127 Particles.P(i2) -= S * Particles.InvM(i2) * Grads[1];
128 Particles.P(i3) -= S * Particles.InvM(i3) * Grads[2];
129 Particles.P(i4) -= S * Particles.InvM(i4) * Grads[3];
130 }
131 }
132
133 virtual void ApplySingleElementAllInOne(FSolverParticles& Particles, const FSolverReal Dt, const int32 ElementIndex) const
134 {
136 const TVec4<int32>& Constraint = Constraints[ElementIndex];
137 for (int ie = 0; ie < 4; ++ie)
138 {
140 const int32 i1 = Constraint[ie];
141 const int32 i2 = Constraint[(ie + 1) % 4];
142 const int32 i3 = Constraint[(ie + 2) % 4];
143 const int32 i4 = Constraint[(ie + 3) % 4];
144 const FSolverVec3& P1 = Particles.P(i1);
145 const FSolverVec3& P2 = Particles.P(i2);
146 const FSolverVec3& P3 = Particles.P(i3);
147 const FSolverVec3& P4 = Particles.P(i4);
148 const FSolverVec3 P1P2 = P1 - P2;
149 const FSolverVec3 P3P2 = P3 - P2;
150 const FSolverVec3 P4P2 = P4 - P2;
151
152 FSolverVec3 ScaledBottomNormal = FSolverVec3::CrossProduct(P3 - P2, P4 - P2);
153 FSolverReal ScaledVolume = FSolverVec3::DotProduct(ScaledBottomNormal, P1 - P2);
166 dAdX[1] = -dAdX[2] - dAdX[3];
167
169 dVdX[0] = FSolverVec3::CrossProduct(P3P2, P4P2);
170 dVdX[2] = FSolverVec3::CrossProduct(P4P2, P1P2);
171 dVdX[3] = FSolverVec3::CrossProduct(P1P2, P3P2);
172 dVdX[1] = -(dVdX[0] + dVdX[2] + dVdX[3]);
173 for (int32 je = 0; je < 4; je++)
174 {
176 }
177 FSolverReal CurrentLength = ScaledVolume / ScaledBottomNormal.Size();
178 const FSolverReal S = Stiffness * (CurrentLength - RestLength[4 * ElementIndex + ie]) / (
179 Particles.InvM(i1) * Grads[0].SizeSquared() +
180 Particles.InvM(i2) * Grads[1].SizeSquared() +
181 Particles.InvM(i3) * Grads[2].SizeSquared() +
182 Particles.InvM(i4) * Grads[3].SizeSquared());
183 Particles.P(i1) -= S * Particles.InvM(i1) * Grads[0];
184 Particles.P(i2) -= S * Particles.InvM(i2) * Grads[1];
185 Particles.P(i3) -= S * Particles.InvM(i3) * Grads[2];
186 Particles.P(i4) -= S * Particles.InvM(i4) * Grads[3];
187 }
188 }
189
190 virtual void ApplySingleElementVolumeAllInOne(FSolverParticles& Particles, const FSolverReal Dt, const int32 ElementIndex) const
191 {
193 const TVec4<int32>& Constraint = Constraints[ElementIndex];
194 const FSolverVec3& P1 = Particles.P(Constraint[0]);
195 const FSolverVec3& P2 = Particles.P(Constraint[1]);
196 const FSolverVec3& P3 = Particles.P(Constraint[2]);
197 const FSolverVec3& P4 = Particles.P(Constraint[3]);
198 const FSolverVec3 P2P1 = P2 - P1;
199 const FSolverVec3 P4P1 = P4 - P1;
200 const FSolverVec3 P3P1 = P3 - P1;
201 Grads[1] = FSolverVec3::CrossProduct(P3P1, P4P1) / (FSolverReal)6.;
202 Grads[2] = FSolverVec3::CrossProduct(P4P1, P2P1) / (FSolverReal)6.;
203 Grads[3] = FSolverVec3::CrossProduct(P2P1, P3P1) / (FSolverReal)6.;
204 Grads[0] = -(Grads[1] + Grads[2] + Grads[3]);
205 const int32 i1 = Constraint[0];
206 const int32 i2 = Constraint[1];
207 const int32 i3 = Constraint[2];
208 const int32 i4 = Constraint[3];
209
210 const FSolverReal Volume = FSolverVec3::DotProduct(FSolverVec3::CrossProduct(P2 - P1, P3 - P1), P4 - P1) / (FSolverReal)6.;
211 const FSolverReal S = Stiffness*(Volume - Volumes[ElementIndex]) / (
212 Particles.InvM(i1) * Grads[0].SizeSquared() +
213 Particles.InvM(i2) * Grads[1].SizeSquared() +
214 Particles.InvM(i3) * Grads[2].SizeSquared() +
215 Particles.InvM(i4) * Grads[3].SizeSquared());
216
217 Particles.P(i1) -= S * Particles.InvM(i1) * Grads[0];
218 Particles.P(i2) -= S * Particles.InvM(i2) * Grads[1];
219 Particles.P(i3) -= S * Particles.InvM(i3) * Grads[2];
220 Particles.P(i4) -= S * Particles.InvM(i4) * Grads[3];
221 }
222
223 virtual void ApplySingleElementShortest(FSolverParticles& Particles, const FSolverReal Dt, const int32 ElementIndex) const
224 {
226 const TVec4<int32>& Constraint = Constraints[ElementIndex];
227 int32 ie = GetSingleElementShortestLength(Particles, Dt, ElementIndex);
228
229 const int32 i1 = Constraint[ie];
230 const int32 i2 = Constraint[(ie + 1) % 4];
231 const int32 i3 = Constraint[(ie + 2) % 4];
232 const int32 i4 = Constraint[(ie + 3) % 4];
233 const TVec4<FSolverVec3> Grads = GetGradients(Particles, ElementIndex, ie);
234 const FSolverReal S = GetScalingFactor(Particles, ElementIndex, ie, Grads);
235 Particles.P(i1) -= S * Particles.InvM(i1) * Grads[0];
236 Particles.P(i2) -= S * Particles.InvM(i2) * Grads[1];
237 Particles.P(i3) -= S * Particles.InvM(i3) * Grads[2];
238 Particles.P(i4) -= S * Particles.InvM(i4) * Grads[3];
239
240 }
241
242 int32 GetSingleElementShortestLength(FSolverParticles& Particles, const FSolverReal Dt, const int32 ElementIndex) const
243 {
244 int32 ReturnIndex = -1;
246 const TVec4<int32>& Constraint = Constraints[ElementIndex];
247 for (int ie = 0; ie < 4; ++ie)
248 {
249 const int32 i1 = Constraint[ie];
250 const int32 i2 = Constraint[(ie + 1) % 4];
251 const int32 i3 = Constraint[(ie + 2) % 4];
252 const int32 i4 = Constraint[(ie + 3) % 4];
253 const FSolverVec3& P1 = Particles.P(i1);
254 const FSolverVec3& P2 = Particles.P(i2);
255 const FSolverVec3& P3 = Particles.P(i3);
256 const FSolverVec3& P4 = Particles.P(i4);
257 FSolverVec3 ScaledBottomNormal = FSolverVec3::CrossProduct(P3 - P2, P4 - P2);
258 FSolverReal ScaledVolume = FSolverVec3::DotProduct(ScaledBottomNormal, P1 - P2);
259 FSolverReal CurrentLength = ScaledVolume / ScaledBottomNormal.Size();
260 FSolverReal CurrentConstraint = CurrentLength - RestLength[4 * ElementIndex + ie];
262 {
263 ReturnIndex = ie;
265 }
266 }
267
268 //another stratey: find the face with largest area
269 /*FSolverReal MaxConstraint = (FSolverReal)-1.;
270 for (int ie = 0; ie < 4; ++ie)
271 {
272 const int32 i1 = Constraint[ie];
273 const int32 i2 = Constraint[(ie + 1) % 4];
274 const int32 i3 = Constraint[(ie + 2) % 4];
275 const int32 i4 = Constraint[(ie + 3) % 4];
276 const FSolverVec3& P1 = Particles.P(i1);
277 const FSolverVec3& P2 = Particles.P(i2);
278 const FSolverVec3& P3 = Particles.P(i3);
279 const FSolverVec3& P4 = Particles.P(i4);
280 FSolverReal ScaledBottomNormalArea = FSolverVec3::CrossProduct(P3 - P2, P4 - P2).Size();
281 if (ScaledBottomNormalArea > MaxConstraint)
282 {
283 ReturnIndex = ie;
284 MaxConstraint = ScaledBottomNormalArea;
285 }
286 }*/
287
288 ensure(ReturnIndex != -1);
289 return ReturnIndex;
290
291 }
292
293 void ApplyInSerial(FSolverParticles& Particles, const FSolverReal Dt) const
294 {
295 //SCOPE_CYCLE_COUNTER(STAT_ChaosXPBDCorotated);
297 for (int32 ElementIndex = 0; ElementIndex < Constraints.Num(); ++ElementIndex)
298 {
299 ApplySingleElement(Particles, Dt, ElementIndex);
300 //ApplySingleElementShortest(Particles, Dt, ElementIndex);
301 //ApplySingleElementVolumeAllInOne(Particles, Dt, ElementIndex);
302 }
303 }
304
305 void ApplyInParallel(FSolverParticles& Particles, const FSolverReal Dt) const
306 {
307 {
309 if ((ConstraintsPerColorStartIndex.Num() > 1))//&& (MeshConstraints.Num() > Chaos_Spring_ParallelConstraintCount))
310 {
311 const int32 ConstraintColorNum = ConstraintsPerColorStartIndex.Num() - 1;
312
314 {
315 const int32 ColorStart = ConstraintsPerColorStartIndex[ConstraintColorIndex];
316 const int32 ColorSize = ConstraintsPerColorStartIndex[ConstraintColorIndex + 1] - ColorStart;
318 {
319 const int32 ConstraintIndex = ColorStart + Index;
320 ApplySingleElement(Particles, Dt, ConstraintIndex);
321 //ApplySingleElementShortest(Particles, Dt, ConstraintIndex);
322 //ApplySingleElementVolumeAllInOne(Particles, Dt, ConstraintIndex);
323 //ApplySingleElementAllInOne(Particles, Dt, ConstraintIndex);
324 });
325 }
326 }
327 }
328 }
329
330 protected:
332
333 protected:
334
335
336 private:
337 void InitColor(const FSolverParticles& Particles)
338 {
339
340 {
341 const TArray<TArray<int32>> ConstraintsPerColor = FGraphColoring::ComputeGraphColoring(Constraints, Particles);
342
343 // Reorder constraints based on color so each array in ConstraintsPerColor contains contiguous elements.
347 TArray<int32> OrigToReorderedIndices; // used to reorder stiffness indices
349 ReorderedRestLength.SetNumUninitialized(RestLength.Num());
350 ReorderedVolumes.SetNumUninitialized(Volumes.Num());
351 OrigToReorderedIndices.SetNumUninitialized(Constraints.Num());
352
353 ConstraintsPerColorStartIndex.Reset(ConstraintsPerColor.Num() + 1);
354
356 for (const TArray<int32>& ConstraintsBatch : ConstraintsPerColor)
357 {
358 ConstraintsPerColorStartIndex.Add(ReorderedIndex);
360 {
363 //ReorderedMeasure[ReorderedIndex] = Measure[OrigIndex];
364 for (int32 kk = 0; kk < 4; kk++)
365 {
366 ReorderedRestLength[4 * ReorderedIndex + kk] = RestLength[4 * OrigIndex + kk];
367 }
370
372 }
373 }
374 ConstraintsPerColorStartIndex.Add(ReorderedIndex);
375
377 RestLength = MoveTemp(ReorderedRestLength);
378 Volumes = MoveTemp(ReorderedVolumes);
379 }
380 }
381
382 TArray<FSolverReal> RestLength;
383 TArray<FSolverReal> Volumes;
384 FSolverReal Stiffness;
385 TArray<int32> ConstraintsPerColorStartIndex;
386 };
387
388} // End namespace Chaos::Softs
int Volume
Definition AndroidPlatformMisc.cpp:380
#define ensure( InExpression)
Definition AssertionMacros.h:464
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_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
static TArray< TArray< int32 > > ComputeGraphColoring(const TArray< TVector< int32, N > > &Graph, const TDynamicParticles< T, 3 > &InParticles, const int32 GraphParticlesStart, const int32 GraphParticlesEnd)
Definition GraphColoring.h:24
Definition PBDAltitudeSpringConstraints.h:14
virtual void ApplySingleElement(FSolverParticles &Particles, const FSolverReal Dt, const int32 ElementIndex) const
Definition PBDAltitudeSpringConstraints.h:113
FPBDAltitudeSpringConstraints(const FSolverParticles &InParticles, TArray< TVec4< int32 > > &&InConstraints, const FSolverReal InStiffness=(FSolverReal) 1.)
Definition PBDAltitudeSpringConstraints.h:16
void ApplyInParallel(FSolverParticles &Particles, const FSolverReal Dt) const
Definition PBDAltitudeSpringConstraints.h:305
virtual void ApplySingleElementAllInOne(FSolverParticles &Particles, const FSolverReal Dt, const int32 ElementIndex) const
Definition PBDAltitudeSpringConstraints.h:133
virtual ~FPBDAltitudeSpringConstraints()
Definition PBDAltitudeSpringConstraints.h:43
void ApplyInSerial(FSolverParticles &Particles, const FSolverReal Dt) const
Definition PBDAltitudeSpringConstraints.h:293
TVec4< FSolverVec3 > GetGradients(const FSolverParticles &InParticles, const int32 ElementIndex, const int32 ie) const
Definition PBDAltitudeSpringConstraints.h:45
FSolverReal GetScalingFactor(const FSolverParticles &InParticles, const int32 ElementIndex, const int32 ie, const TVec4< FSolverVec3 > &Grads) const
Definition PBDAltitudeSpringConstraints.h:91
virtual void ApplySingleElementVolumeAllInOne(FSolverParticles &Particles, const FSolverReal Dt, const int32 ElementIndex) const
Definition PBDAltitudeSpringConstraints.h:190
TArray< TVec4< int32 > > Constraints
Definition PBDAltitudeSpringConstraints.h:331
int32 GetSingleElementShortestLength(FSolverParticles &Particles, const FSolverReal Dt, const int32 ElementIndex) const
Definition PBDAltitudeSpringConstraints.h:242
virtual void ApplySingleElementShortest(FSolverParticles &Particles, const FSolverReal Dt, const int32 ElementIndex) const
Definition PBDAltitudeSpringConstraints.h:223
Definition PBDSoftsSolverParticles.h:20
const FSolverVec3 & P(const int32 index) const
Definition PBDSoftsSolverParticles.h:36
const T InvM(const int32 Index) const
Definition DynamicParticles.h:48
Definition Vector.h:41
Definition Constraints.Build.cs:6
Definition Array.h:670
UE_REWRITE SizeType Num() const
Definition Array.h:1144
void Reset(SizeType NewSize=0)
Definition Array.h:2246
UE_NODEBUG UE_FORCEINLINE_HINT SizeType Add(ElementType &&Item)
Definition Array.h:2696
void Init(const ElementType &Element, SizeType Number)
Definition Array.h:3043
void SetNumUninitialized(SizeType NewNum, EAllowShrinking AllowShrinking=UE::Core::Private::AllowShrinkingByDefault< AllocatorType >())
Definition Array.h:2369
Definition CollectionEmbeddedSpringConstraintFacade.cpp:6
FRealSingle FSolverReal
Definition PBDSoftsEvolutionFwd.h:31
TVector< FSolverReal, 3 > FSolverVec3
Definition PBDSoftsEvolutionFwd.h:33
void CHAOS_API PhysicsParallelFor(int32 InNum, TFunctionRef< void(int32)> InCallable, bool bForceSingleThreaded=false)
Definition Parallel.cpp:55
U16 Index
Definition radfft.cpp:71
Definition NumericLimits.h:41