UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
JointSolverConstraints.inl
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3namespace Chaos
4{
6 const FPBDJointSolverSettings& SolverSettings,
7 const FPBDJointSettings& JointSettings,
8 const FVec3& PrevP0,
9 const FRotation3& PrevQ0,
10 const FVec3& PrevP1,
11 const FRotation3& PrevQ1,
12 const FReal InvM0,
13 const FVec3& InvIL0,
14 const FReal InvM1,
15 const FVec3& InvIL1,
16 const FRigidTransform3& XL0,
17 const FRigidTransform3& XL1)
18 {
19 XLs[0] = XL0;
20 XLs[1] = XL1;
21
22 InvILs[0] = JointSettings.ParentInvMassScale * InvIL0;
23 InvILs[1] = InvIL1;
24 InvMs[0] = JointSettings.ParentInvMassScale * InvM0;
25 InvMs[1] = InvM1;
26
28
29 PrevPs[0] = PrevP0;
30 PrevPs[1] = PrevP1;
31 PrevQs[0] = PrevQ0;
32 PrevQs[1] = PrevQ1;
33 PrevXs[0] = PrevP0 + PrevQ0 * XL0.GetTranslation();
34 PrevXs[1] = PrevP1 + PrevQ1 * XL1.GetTranslation();
35
36 PositionTolerance = SolverSettings.PositionTolerance;
37 AngleTolerance = SolverSettings.AngleTolerance;
38
40 }
41
43 const FVec3& P0,
44 const FRotation3& Q0,
45 const FVec3& P1,
46 const FRotation3& Q1)
47 {
48 Ps[0] = P0;
49 Ps[1] = P1;
50 Qs[0] = Q0;
51 Qs[1] = Q1;
52 Qs[1].EnforceShortestArcWith(Qs[0]);
53 }
54
56 {
57 // Really we should need to do this for Kinematics since Dynamics are updated each iteration
58 Xs[0] = PrevPs[0] + PrevQs[0] * XLs[0].GetTranslation();
59 Rs[0] = PrevQs[0] * XLs[0].GetRotation();
60 InvIs[0] = (InvMs[0] > 0.0f) ? Utilities::ComputeWorldSpaceInertia(PrevQs[0], InvILs[0]) : FMatrix33(0, 0, 0);
61
62 Xs[1] = PrevPs[1] + PrevQs[1] * XLs[1].GetTranslation();
63 Rs[1] = PrevQs[1] * XLs[1].GetRotation();
64 InvIs[1] = (InvMs[1] > 0.0f) ? Utilities::ComputeWorldSpaceInertia(PrevQs[1], InvILs[1]) : FMatrix33(0, 0, 0);
65
66 Rs[1].EnforceShortestArcWith(Rs[0]);
67
68 PrevXs[0] = Xs[0];
69 PrevXs[1] = Xs[1];
70
71 DPs[0] = FVec3(0);
72 DRs[0] = FVec3(0);
73 DPs[1] = FVec3(0);
74 DRs[1] = FVec3(0);
75 }
76
78 {
79 if (InvMs[0] > 0.0f)
80 {
81 Xs[0] = Ps[0] + Qs[0] * XLs[0].GetTranslation();
82 Rs[0] = Qs[0] * XLs[0].GetRotation();
84 DPs[0] = FVec3(0);
85 DRs[0] = FVec3(0);
86 }
87 if (InvMs[1] > 0.0f)
88 {
89 Xs[1] = Ps[1] + Qs[1] * XLs[1].GetTranslation();
90 Rs[1] = Qs[1] * XLs[1].GetRotation();
92 DPs[1] = FVec3(0);
93 DRs[1] = FVec3(0);
94 }
95 Rs[1].EnforceShortestArcWith(Rs[0]);
96 }
97
99 const FVec3& DP0,
100 const FVec3& DR0,
101 const FVec3& DP1,
102 const FVec3& DR1)
103 {
104 if (InvMs[0] > 0.0f)
105 {
106 //UE_LOG(LogChaosJoint, VeryVerbose, TEXT(" Apply DP%d %f %f %f"), 0, DP0.X, DP0.Y, DP0.Z);
107 //UE_LOG(LogChaosJoint, VeryVerbose, TEXT(" Apply DR%d %f %f %f"), 0, DR0.X, DR0.Y, DR0.Z);
108
109 Ps[0] += DP0;
110 const FRotation3 DQ0 = (FRotation3::FromElements(DR0, 0) * Qs[0]) * (FReal)0.5;
111 Qs[0] = (Qs[0] + DQ0).GetNormalized();
112 }
113 if (InvMs[1] > 0.0f)
114 {
115 //UE_LOG(LogChaosJoint, VeryVerbose, TEXT(" Apply DP%d %f %f %f"), 1, DP1.X, DP1.Y, DP1.Z);
116 //UE_LOG(LogChaosJoint, VeryVerbose, TEXT(" Apply DR%d %f %f %f"), 1, DR1.X, DR1.Y, DR1.Z);
117
118 Ps[1] += DP1;
119 const FRotation3 DQ1 = (FRotation3::FromElements(DR1, 0) * Qs[1]) * (FReal)0.5;
120 Qs[1] = (Qs[1] + DQ1).GetNormalized();
121 }
122 Qs[1].EnforceShortestArcWith(Qs[0]);
123 }
124
126 const FVec3& DR0,
127 const FVec3& DR1)
128 {
129 if (InvMs[0] > 0.0f)
130 {
131 //UE_LOG(LogChaosJoint, VeryVerbose, TEXT(" Apply DR%d %f %f %f"), 0, DR0.X, DR0.Y, DR0.Z);
132
133 const FRotation3 DQ0 = (FRotation3::FromElements(DR0, 0) * Qs[0]) * (FReal)0.5;
134 Qs[0] = (Qs[0] + DQ0).GetNormalized();
135 }
136 if (InvMs[1] > 0.0f)
137 {
138 //UE_LOG(LogChaosJoint, VeryVerbose, TEXT(" Apply DR%d %f %f %f"), 1, DR1.X, DR1.Y, DR1.Z);
139
140 const FRotation3 DQ1 = (FRotation3::FromElements(DR1, 0) * Qs[1]) * (FReal)0.5;
141 Qs[1] = (Qs[1] + DQ1).GetNormalized();
142 }
143 Qs[1].EnforceShortestArcWith(Qs[0]);
144 }
145
146 //
148 //
149
154
155 // Reset calculated values ready for next iteration. Note: Lambda is not reset here,
156 // it accumulates over the whole timestep.
158 {
159 DPs[0] = FVec3(0);
160 DPs[1] = FVec3(0);
161 DRs[0] = FVec3(0);
162 DRs[1] = FVec3(0);
163 Axis = FVec3(0);
164 Error = 0.0f;
165 // Do not reset Lambda
166 }
167
169 {
170 Error = 0.0f;
171 if (Position >= Limit)
172 {
173 Error = Position - Limit;
174 }
175 else if (Position <= -Limit)
176 {
177 Error = Position + Limit;
178 }
179 }
180
181 //
183 //
184
185
186 FORCEINLINE int32 FJointSolverConstraints::UpdatePointPositionConstraint(
190 const FPBDJointSettings& JointSettings,
191 const FVec3& X0,
192 const FVec3& X1)
193 {
194 const FVec3 CX = X1 - X0;
195 for (int32 AxisIndex = 0; AxisIndex < 3; ++AxisIndex)
196 {
197 FVec3 Axis = FVec3(0.0f);
198 Axis[AxisIndex] = 1.0f;
199 RowStates[RowIndexBegin + AxisIndex].Axis = Axis;
200 RowStates[RowIndexBegin + AxisIndex].CalculateError(CX[AxisIndex], RowDatas[RowIndexBegin + AxisIndex].Limit);
201 }
202
203 return 3;
204 }
205
206 FORCEINLINE int32 FJointSolverConstraints::UpdateSphericalPositionConstraint(
210 const FPBDJointSettings& JointSettings,
211 const FVec3& X0,
212 const FVec3& X1)
213 {
214 const FVec3 CX = X1 - X0;
215 const FReal CXLen = CX.Size();
217 {
219 RowStates[RowIndexBegin].CalculateError(CXLen, RowDatas[RowIndexBegin].Limit);
220 }
221
222 return 1;
223 }
224
225 FORCEINLINE int32 FJointSolverConstraints::UpdateCylindricalPositionConstraint(
229 const FPBDJointSettings& JointSettings,
230 const FRotation3& R0,
231 const FVec3& X0,
232 const FVec3& X1)
233 {
234 const FJointSolverConstraintRowData& AxisData = RowDatas[RowIndexBegin + 0];
235 const FJointSolverConstraintRowData& RadialData = RowDatas[RowIndexBegin + 1];
237
241
242 FJointSolverConstraintRowState& AxisState = RowStates[RowIndexBegin + 0];
243 AxisState.Axis = Axis;
244 AxisState.CalculateError(AxialDelta, AxisData.Limit);
245
246 FJointSolverConstraintRowState& RadialState = RowStates[RowIndexBegin + 1];
247 RadialState.Axis = RadialAxis;
248 RadialState.CalculateError(RadialDelta, RadialData.Limit);
249
250 return 2;
251 }
252
253 FORCEINLINE int32 FJointSolverConstraints::UpdatePlanarPositionConstraint(
257 const FPBDJointSettings& JointSettings,
258 const FRotation3& R0,
259 const FVec3& X0,
260 const FVec3& X1)
261 {
262 const FJointSolverConstraintRowData& RowData = RowDatas[RowIndexBegin];
263
264 FVec3 Axis;
265 FReal Delta;
266 FPBDJointUtilities::GetPlanarAxisDelta(R0, X0, X1, RowData.ConstraintIndex, Axis, Delta);
267
268 FJointSolverConstraintRowState& RowState = RowStates[RowIndexBegin];
269 RowState.Axis = Axis;
270 RowState.CalculateError(Delta, RowData.Limit);
271
272 return 1;
273 }
274
275 FORCEINLINE int32 FJointSolverConstraints::UpdateSphericalPositionDrive(
276 int32 RowIndex,
279 const FPBDJointSettings& JointSettings,
280 const FRotation3& R0,
281 const FVec3& X0,
282 const FVec3& X1)
283 {
284 const FJointSolverConstraintRowData& RowData = RowDatas[RowIndex];
285 FJointSolverConstraintRowState& RowState = RowStates[RowIndex];
286
287 const FVec3 XTarget = X0 + R0 * JointSettings.LinearDrivePositionTarget;
288 FVec3 Axis;
289 FReal Delta;
291
292 RowState.Axis = Axis;
293 RowState.CalculateError(Delta, RowData.Limit);
294
295 return 1;
296 }
297
298 FORCEINLINE int32 FJointSolverConstraints::UpdateCircularPositionDrive(
299 int32 RowIndex,
302 const FPBDJointSettings& JointSettings,
303 const FRotation3& R0,
304 const FVec3& X0,
305 const FVec3& X1)
306 {
307 const FJointSolverConstraintRowData& RowData = RowDatas[RowIndex];
308 FJointSolverConstraintRowState& RowState = RowStates[RowIndex];
309
310 const FVec3 XTarget = X0 + R0 * JointSettings.LinearDrivePositionTarget;
314
315 RowState.Axis = RadialAxis;
316 RowState.CalculateError(RadialDelta, RowData.Limit);
317
318 return 1;
319 }
320
321 FORCEINLINE int32 FJointSolverConstraints::UpdateAxialPositionDrive(
322 int32 RowIndex,
325 const FPBDJointSettings& JointSettings,
326 const FRotation3& R0,
327 const FVec3& X0,
328 const FVec3& X1)
329 {
330 const FJointSolverConstraintRowData& RowData = RowDatas[RowIndex];
331 FJointSolverConstraintRowState& RowState = RowStates[RowIndex];
332
333 const FVec3 XTarget = X0 + R0 * JointSettings.LinearDrivePositionTarget;
334 FVec3 Axis;
335 FReal Delta;
337
338 RowState.Axis = Axis;
339 RowState.CalculateError(Delta, RowData.Limit);
340
341 return 1;
342 }
343
344 //
346 //
347
348 FORCEINLINE void FJointSolverConstraints::UpdateTwistConstraint(
349 const FJointSolverConstraintRowData& RowData,
350 FJointSolverConstraintRowState& RowState,
351 const FPBDJointSettings& JointSettings,
352 const FRotation3& R1,
353 const FRotation3& RTwist)
354 {
357 }
358
359 FORCEINLINE void FJointSolverConstraints::UpdateConeSwingConstraint(
360 const FJointSolverConstraintRowData& RowData,
361 FJointSolverConstraintRowState& RowState,
362 const FPBDJointSettings& JointSettings,
363 const FRotation3& R0,
364 const FRotation3& RSwing)
365 {
368 RSwing.ToAxisAndAngleSafe(SwingAxisLocal, SwingAngle, FJointConstants::Swing1Axis(), 1.e-6f);
369 if (SwingAngle > UE_PI)
370 {
372 }
373
374 RowState.Axis = R0 * SwingAxisLocal;
376 }
377
378 FORCEINLINE void FJointSolverConstraints::UpdateSingleLockedSwingConstraint(
379 const FJointSolverConstraintRowData& RowData,
380 FJointSolverConstraintRowState& RowState,
381 const FPBDJointSettings& JointSettings,
382 const FRotation3& R0,
383 const FRotation3& R1)
384 {
387
388 RowState.Axis = FVec3::CrossProduct(Swing0, Twist1);
389 RowState.CalculateError(-FVec3::DotProduct(Swing0, Twist1), RowData.Limit);
390 }
391
392 FORCEINLINE void FJointSolverConstraints::UpdateSingleLimitedSwingConstraint(
393 const FJointSolverConstraintRowData& RowData,
394 FJointSolverConstraintRowState& RowState,
395 const FPBDJointSettings& JointSettings,
396 const FRotation3& R0,
397 const FRotation3& RSwing)
398 {
399 const FReal R01SwingYorZ = (FJointConstants::AxisIndex((EJointAngularConstraintIndex)RowData.ConstraintIndex) == 2) ? RSwing.Z : RSwing.Y; // Can't index a quat :(
400 const FReal Angle = (FReal)4. * FMath::Atan2(R01SwingYorZ, (FReal)(1. + RSwing.W));
401 const FVec3& AxisLocal = (RowData.ConstraintIndex == (int32)EJointAngularConstraintIndex::Swing1) ? FJointConstants::Swing1Axis() : FJointConstants::Swing2Axis();
402
403 RowState.Axis = R0 * AxisLocal;
404 RowState.CalculateError(Angle, RowData.Limit);
405 }
406
407 FORCEINLINE void FJointSolverConstraints::UpdateDualConeSwingConstraint(
408 const FJointSolverConstraintRowData& RowData,
409 FJointSolverConstraintRowState& RowState,
410 const FPBDJointSettings& JointSettings,
411 const FRotation3& R0,
412 const FRotation3& R1)
413 {
416
417 FVec3 Axis = FVec3::CrossProduct(Swing0, Twist1);
419 {
420 FReal SwingTwistDot = FVec3::DotProduct(Swing0, Twist1);
421 FReal Position = FMath::Asin(FMath::Clamp(-SwingTwistDot, FReal(-1), FReal(1)));
422 RowState.Axis = Axis;
423 RowState.CalculateError(Position, RowData.Limit);
424 }
425 }
426
427 FORCEINLINE void FJointSolverConstraints::UpdateTwistDrive(
428 const FJointSolverConstraintRowData& RowData,
429 FJointSolverConstraintRowState& RowState,
430 const FPBDJointSettings& JointSettings,
431 const FRotation3& R1,
432 const FRotation3& RTwist)
433 {
434 // @todo(ccaulfield): Reimplement with AngularDriveTarget
435 //const FVec3 Axis = R1 * FJointConstants::TwistAxis();
436 //const FReal Angle = FPBDJointUtilities::GetTwistAngle(RTwist);
437 //const FReal TwistAngleTarget = JointSettings.AngularDriveTargetAngles[(int32)EJointAngularConstraintIndex::Twist];
438 //const FReal DTwistAngle = Angle - TwistAngleTarget;
439
440 //RowState.Axis = Axis;
441 //RowState.CalculateError(DTwistAngle, RowData.Limit);
442 }
443
444 FORCEINLINE void FJointSolverConstraints::UpdateConeSwingDrive(
445 const FJointSolverConstraintRowData& RowData,
446 FJointSolverConstraintRowState& RowState,
447 const FPBDJointSettings& JointSettings,
448 const FRotation3& R0,
449 const FRotation3& RSwing)
450 {
451 // @todo(ccaulfield): Reimplement with AngularDriveTarget
452 //FReal SwingAngle;
453 //FVec3 SwingAxisLocal;
454 //RSwing.ToAxisAndAngleSafe(SwingAxisLocal, SwingAngle, FJointConstants::Swing1Axis(), AngleTolerance);
455 //if (SwingAngle > PI)
456 //{
457 // SwingAngle = SwingAngle - (FReal)2 * PI;
458 //}
459
462 //const FReal Swing1Target = JointSettings.AngularDriveTargetAngles[(int32)EJointAngularConstraintIndex::Swing1];
463 //const FReal Swing2Target = JointSettings.AngularDriveTargetAngles[(int32)EJointAngularConstraintIndex::Swing2];
464 //const FReal SwingAngleTarget = FMath::Max(Swing1Target, Swing2Target);
465 //const FReal DSwingAngle = SwingAngle - SwingAngleTarget;
466
467 //RowState.Axis = R0 * SwingAxisLocal;
468 //RowState.CalculateError(DSwingAngle, RowData.Limit);
469 }
470
471 FORCEINLINE void FJointSolverConstraints::UpdateSwingDrive(
472 const FJointSolverConstraintRowData& RowData,
473 FJointSolverConstraintRowState& RowState,
474 const FPBDJointSettings& JointSettings,
475 const FRotation3& R0,
476 const FRotation3& RSwing)
477 {
478 // @todo(ccaulfield): Reimplement with AngularDriveTarget
479 //const FReal R01SwingYorZ = (FJointConstants::AxisIndex((EJointAngularConstraintIndex)RowData.ConstraintIndex) == 2) ? RSwing.Z : RSwing.Y; // Can't index a quat :(
480 //const FReal SwingAngle = 4.0f * FMath::Atan2(R01SwingYorZ, 1.0f + RSwing.W);
481 //const FReal SwingAngleTarget = JointSettings.AngularDriveTargetAngles[(int32)RowData.ConstraintIndex];
482 //const FReal DSwingAngle = SwingAngle - SwingAngleTarget;
483 //const FVec3& AxisLocal = ((EJointAngularConstraintIndex)RowData.ConstraintIndex == EJointAngularConstraintIndex::Swing1) ? FJointConstants::Swing1Axis() : FJointConstants::Swing2Axis();
484
485 //RowState.Axis = R0 * AxisLocal;
486 //RowState.CalculateError(DSwingAngle, RowData.Limit);
487 }
488
489 FORCEINLINE void FJointSolverConstraints::UpdateSLerpDrive(
490 const FJointSolverConstraintRowData& RowData,
491 FJointSolverConstraintRowState& RowState,
492 const FPBDJointSettings& JointSettings,
493 const FRotation3& R0,
494 const FRotation3& R1)
495 {
496 const FRotation3 TargetR1 = R0 * JointSettings.AngularDrivePositionTarget;
497 const FRotation3 DR = TargetR1 * R1.Inverse();
498
501 if (DR.ToAxisAndAngleSafe(SLerpAxis, SLerpAngle, FVec3(1, 0, 0)))
502 {
503 if (SLerpAngle > (FReal)UE_PI)
504 {
506 }
507
508 //UE_LOG(LogChaosJoint, VeryVerbose, TEXT(" SLerpDrive Pos: %f Axis: %f %f %f"), -SLerpAngle, SLerpAxis.X, SLerpAxis.Y, SLerpAxis.Z);
509
510 RowState.Axis = SLerpAxis;
511 RowState.CalculateError(-SLerpAngle, RowData.Limit);
512 }
513 }
514
515 //
517 //
518
519 FORCEINLINE void FJointSolver::ApplyPositionConstraint1(
520 const FReal Dt,
521 const FJointSolverJointState& JointState,
522 const FJointSolverConstraintRowData& RowData,
523 FJointSolverConstraintRowState& RowState)
524 {
525 //UE_LOG(LogChaosJoint, VeryVerbose, TEXT(" Position Error %f"), RowState.Error);
526
527 FReal II = 0.0f;
530
531 if (JointState.InvMs[0] > 0.0f)
532 {
533 AngularAxis0 = FVec3::CrossProduct(JointState.Xs[0] - JointState.Ps[0], RowState.Axis);
535 const FReal II0 = FVec3::DotProduct(AngularAxis0, IA0);
536 II += JointState.InvMs[0] + II0;
537 }
538 if (JointState.InvMs[1] > 0.0f)
539 {
540 AngularAxis1 = FVec3::CrossProduct(JointState.Xs[1] - JointState.Ps[1], RowState.Axis);
542 const FReal II1 = FVec3::DotProduct(AngularAxis1, IA1);
543 II += JointState.InvMs[1] + II1;
544 }
545
546 if (RowData.bIsSoft)
547 {
548 FReal VelDt = 0;
549 if (RowData.Damping > UE_KINDA_SMALL_NUMBER)
550 {
551 const FVec3 V0 = FVec3::CalculateVelocity(JointState.PrevXs[0], JointState.Xs[0], 1.0f);
552 const FVec3 V1 = FVec3::CalculateVelocity(JointState.PrevXs[1], JointState.Xs[1], 1.0f);
553 VelDt = FVec3::DotProduct(V0 - V1, RowState.Axis);
554 }
555
556 const FReal SpringMassScale = (RowData.bIsAccelerationMode) ? 1.0f / (JointState.InvMs[0] + JointState.InvMs[1]) : 1.0f;
557 const FReal S = SpringMassScale * RowData.Stiffness * Dt * Dt;
558 const FReal D = SpringMassScale * RowData.Damping * Dt;
559 const FReal Multiplier = (FReal)1 / ((S + D) * II + (FReal)1);
560 const FReal DLambda = Multiplier * (S * RowState.Error - D * VelDt - RowState.Lambda);
561
562 RowState.DPs[0] = (JointState.InvMs[0] * DLambda) * RowState.Axis;
563 RowState.DPs[1] = (-JointState.InvMs[1] * DLambda) * RowState.Axis;
566 RowState.Lambda += DLambda;
567 }
568 else
569 {
570 const FVec3 DX = RowState.Axis * (RowData.Stiffness * RowState.Error / II);
571
572 // Apply constraint correction
573 RowState.DPs[0] = JointState.InvMs[0] * DX;
574 RowState.DPs[1] = -JointState.InvMs[1] * DX;
575 RowState.DRs[0] = Utilities::Multiply(JointState.InvIs[0], FVec3::CrossProduct(JointState.Xs[0] - JointState.Ps[0], DX));
576 RowState.DRs[1] = Utilities::Multiply(JointState.InvIs[1], FVec3::CrossProduct(JointState.Xs[1] - JointState.Ps[1], -DX));
577 }
578 }
579
580 // NOTE: Currently assumes row axes are unit axes
581 FORCEINLINE void FJointSolver::ApplyPositionConstraint3(
582 const FReal Dt,
583 const FJointSolverJointState& JointState,
584 const FJointSolverConstraintRowData& RowData,
585 FJointSolverConstraintRowState& RowState0,
586 FJointSolverConstraintRowState& RowState1,
587 FJointSolverConstraintRowState& RowState2)
588 {
589 FVec3 CX = FVec3(RowState0.Error, RowState1.Error, RowState2.Error);
590
591 //UE_LOG(LogChaosJoint, VeryVerbose, TEXT(" Position Error %f"), CX.Size());
592
593 FMatrix33 M = FMatrix33(0, 0, 0);
594 if (JointState.InvMs[0] > 0)
595 {
597 M += M0;
598 }
599 if (JointState.InvMs[1] > 0)
600 {
602 M += M1;
603 }
604 FMatrix33 MI = M.Inverse();
605 const FVec3 DX = RowData.Stiffness * Utilities::Multiply(MI, CX);
606
607 // Apply constraint correction
608 RowState0.DPs[0] = JointState.InvMs[0] * DX;
609 RowState0.DPs[1] = -JointState.InvMs[1] * DX;
610 RowState0.DRs[0] = Utilities::Multiply(JointState.InvIs[0], FVec3::CrossProduct(JointState.Xs[0] - JointState.Ps[0], DX));
611 RowState0.DRs[1] = Utilities::Multiply(JointState.InvIs[1], FVec3::CrossProduct(JointState.Xs[1] - JointState.Ps[1], -DX));
612 }
613
614 FORCEINLINE void FJointSolver::ApplyRotationConstraint(
615 const FReal Dt,
616 const FJointSolverJointState& JointState,
617 const FJointSolverConstraintRowData& RowData,
618 FJointSolverConstraintRowState& RowState)
619 {
620 // Joint-space inverse mass
621 FVec3 IA0 = FVec3(0);
622 FVec3 IA1 = FVec3(0);
623 FReal II0 = 0.0f;
624 FReal II1 = 0.0f;
625 if (JointState.InvMs[0] > 0)
626 {
627 IA0 = Utilities::Multiply(JointState.InvIs[0], RowState.Axis);
628 II0 = FVec3::DotProduct(RowState.Axis, IA0);
629 }
630 if (JointState.InvMs[1] > 0)
631 {
632 IA1 = Utilities::Multiply(JointState.InvIs[1], RowState.Axis);
633 II1 = FVec3::DotProduct(RowState.Axis, IA1);
634 }
635 const FReal II = (II0 + II1);
636
637 if (RowData.bIsSoft)
638 {
639 // Damping angular velocity
640 FReal AngVelDt = 0;
641 if (RowData.Damping > 0.0f)
642 {
643 const FVec3 W0 = FRotation3::CalculateAngularVelocity(JointState.PrevQs[0], JointState.Qs[0], 1.0f);
644 const FVec3 W1 = FRotation3::CalculateAngularVelocity(JointState.PrevQs[1], JointState.Qs[1], 1.0f);
645 AngVelDt = FVec3::DotProduct(RowState.Axis, W0) - FVec3::DotProduct(RowState.Axis, W1);
646 }
647
648 const FReal SpringMassScale = (RowData.bIsAccelerationMode) ? 1.0f / II : 1.0f;
649 const FReal S = SpringMassScale * RowData.Stiffness * Dt * Dt;
650 const FReal D = SpringMassScale * RowData.Damping * Dt;
651 const FReal Multiplier = (FReal)1 / ((S + D) * II + (FReal)1);
652 const FReal DLambda = Multiplier * (S * RowState.Error - D * AngVelDt - RowState.Lambda);
653
654 //const FVec3 DR0 = IA0 * DLambda;
655 //const FVec3 DR1 = IA1 * -DLambda;
656 RowState.DRs[0] = RowState.Axis * (DLambda * II0);
657 RowState.DRs[1] = RowState.Axis * -(DLambda * II1);
658 RowState.Lambda += DLambda;
659 }
660 else
661 {
662 RowState.DRs[0] = IA0 * (RowData.Stiffness * RowState.Error / II);
663 RowState.DRs[1] = IA1 * -(RowData.Stiffness * RowState.Error / II);
664 }
665 }
666
667}
#define FORCEINLINE
Definition AndroidPlatform.h:140
#define check(expr)
Definition AssertionMacros.h:314
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 W1
@ Multiplier
#define UE_PI
Definition UnrealMathUtility.h:129
#define UE_KINDA_SMALL_NUMBER
Definition UnrealMathUtility.h:131
FVec3 Axis
Definition JointSolverConstraints.h:138
FVec3 DRs[MaxConstrainedBodies]
Definition JointSolverConstraints.h:137
FVec3 DPs[MaxConstrainedBodies]
Definition JointSolverConstraints.h:136
FReal Error
Definition JointSolverConstraints.h:139
FORCEINLINE void IterationReset()
Definition JointSolverConstraints.inl:157
FORCEINLINE void CalculateError(FReal Position, FReal Limit)
Definition JointSolverConstraints.inl:168
FORCEINLINE void TickReset()
Definition JointSolverConstraints.inl:150
FReal Lambda
Definition JointSolverConstraints.h:142
FVec3 PrevPs[MaxConstrainedBodies]
Definition JointSolverConstraints.h:97
FVec3 PrevXs[MaxConstrainedBodies]
Definition JointSolverConstraints.h:99
FVec3 Ps[MaxConstrainedBodies]
Definition JointSolverConstraints.h:92
FRotation3 Rs[MaxConstrainedBodies]
Definition JointSolverConstraints.h:89
FORCEINLINE void UpdateDerivedState()
Definition JointSolverConstraints.inl:77
FORCEINLINE void InitDerivedState()
Definition JointSolverConstraints.inl:55
FORCEINLINE void Update(const FVec3 &P0, const FRotation3 &Q0, const FVec3 &P1, const FRotation3 &Q1)
Definition JointSolverConstraints.inl:42
FVec3 DPs[MaxConstrainedBodies]
Definition JointSolverConstraints.h:101
FVec3 Xs[MaxConstrainedBodies]
Definition JointSolverConstraints.h:88
FVec3 DRs[MaxConstrainedBodies]
Definition JointSolverConstraints.h:102
FRotation3 PrevQs[MaxConstrainedBodies]
Definition JointSolverConstraints.h:98
FORCEINLINE void ApplyDelta(const FVec3 &DP0, const FVec3 &DR0, const FVec3 &DP1, const FVec3 &DR1)
Definition JointSolverConstraints.inl:98
FReal PositionTolerance
Definition JointSolverConstraints.h:104
FMatrix33 InvIs[MaxConstrainedBodies]
Definition JointSolverConstraints.h:94
FReal AngleTolerance
Definition JointSolverConstraints.h:105
FRotation3 Qs[MaxConstrainedBodies]
Definition JointSolverConstraints.h:93
FORCEINLINE void ApplyRotationDelta(const FVec3 &DR0, const FVec3 &DR1)
Definition JointSolverConstraints.inl:125
void Init(const FPBDJointSolverSettings &SolverSettings, const FPBDJointSettings &JointSettings, const FVec3 &PrevP0, const FRotation3 &PrevQ0, const FVec3 &PrevP1, const FRotation3 &PrevQ1, const FReal InvM0, const FVec3 &InvIL0, const FReal InvM1, const FVec3 &InvIL1, const FRigidTransform3 &XL0, const FRigidTransform3 &XL1)
Definition JointSolverConstraints.inl:5
FRigidTransform3 XLs[MaxConstrainedBodies]
Definition JointSolverConstraints.h:83
FReal InvMs[MaxConstrainedBodies]
Definition JointSolverConstraints.h:85
FVec3 InvILs[MaxConstrainedBodies]
Definition JointSolverConstraints.h:84
Definition PBDJointConstraintTypes.h:114
FReal ParentInvMassScale
Definition PBDJointConstraintTypes.h:141
Definition PBDJointConstraintTypes.h:219
FReal PositionTolerance
Definition PBDJointConstraintTypes.h:229
FReal MaxInertiaRatio
Definition PBDJointConstraintTypes.h:234
FReal MinParentMassRatio
Definition PBDJointConstraintTypes.h:233
FReal AngleTolerance
Definition PBDJointConstraintTypes.h:230
static CHAOS_API void GetPlanarAxisDelta(const FRotation3 &R0, const FVec3 &X0, const FVec3 &X1, const int32 PlaneAxisIndex, FVec3 &Axis, FReal &Delta)
Definition PBDJointConstraintUtilities.cpp:150
static CHAOS_API void ConditionInverseMassAndInertia(const FReal &InInvMParent, const FReal &InInvMChild, const FVec3 &InInvIParent, const FVec3 &InInvIChild, const FReal MinParentMassRatio, const FReal MaxInertiaRatio, FReal &OutInvMParent, FReal &OutInvMChild, FVec3 &OutInvIParent, FVec3 &OutInvIChild)
Definition PBDJointConstraintUtilities.cpp:701
static CHAOS_API void GetCylindricalAxesDeltas(const FRotation3 &R0, const FVec3 &X0, const FVec3 &X1, const int32 CylinderAxisIndex, FVec3 &CylinderAxis, FReal &CylinderDelta, FVec3 &RadialAxis, FReal &RadialDelta)
Definition PBDJointConstraintUtilities.cpp:119
static CHAOS_API void GetSphericalAxisDelta(const FVec3 &X0, const FVec3 &X1, FVec3 &Axis, FReal &Delta)
Definition PBDJointConstraintUtilities.cpp:100
static CHAOS_API FReal GetTwistAngle(const FRotation3 &InTwist)
Definition PBDJointConstraintUtilities.cpp:179
static CHAOS_API FReal GetConeAngleLimit(const FPBDJointSettings &JointSettings, const FVec3 &SwingAxisLocal, const FReal SwingAngle)
Definition PBDJointConstraintUtilities.cpp:373
Definition Array.h:670
bool NormalizeSafe(FVec3 &V, FReal EpsilonSq=UE_SMALL_NUMBER)
Definition Utilities.h:492
FMatrix33 Multiply(const FMatrix33 &L, const FMatrix33 &R)
Definition Utilities.h:154
FMatrix33 ComputeWorldSpaceInertia(const FRotation3 &CoMRotation, const FMatrix33 &I)
Definition Utilities.h:327
PMatrix< T, 3, 3 > ComputeJointFactorMatrix(const TVec3< T > &V, const PMatrix< T, 3, 3 > &M, const T &Im)
Definition Utilities.h:349
Definition SkeletalMeshComponent.h:307
@ Y
Definition SimulationModuleBase.h:153
FRealDouble FReal
Definition Real.h:22
TRotation< FReal, 3 > FRotation3
Definition Core.h:19
EJointAngularConstraintIndex
Definition PBDJointConstraintTypes.h:48
PMatrix< FReal, 3, 3 > FMatrix33
Definition Core.h:20
TVector< FReal, 3 > FVec3
Definition Core.h:17
@ V1
Definition NNEModelData.cpp:17
@ V0
Definition NNEModelData.cpp:16
static const FVec3 OtherSwingAxis(const EJointAngularConstraintIndex ConstraintIndex)
Definition PBDJointConstraintTypes.h:90
static const FVec3 Swing1Axis()
Definition PBDJointConstraintTypes.h:66
static const int32 AxisIndex(const EJointAngularConstraintIndex ConstraintIndex)
Definition PBDJointConstraintTypes.h:96
static const FVec3 TwistAxis()
Definition PBDJointConstraintTypes.h:63
static constexpr UE_FORCEINLINE_HINT T Clamp(const T X, const T MinValue, const T MaxValue)
Definition UnrealMathUtility.h:592