38 mSwingType = inSwingType;
48 void SetLimits(
float inTwistMinAngle,
float inTwistMaxAngle,
float inSwingYMinAngle,
float inSwingYMaxAngle,
float inSwingZMinAngle,
float inSwingZMaxAngle)
54 JPH_ASSERT(inTwistMinAngle <= inTwistMaxAngle);
55 JPH_ASSERT(inSwingYMinAngle <= inSwingYMaxAngle);
56 JPH_ASSERT(inSwingZMinAngle <= inSwingZMaxAngle);
57 JPH_ASSERT(inSwingYMinAngle >= -JPH_PI && inSwingYMaxAngle <= JPH_PI);
58 JPH_ASSERT(inSwingZMinAngle >= -JPH_PI && inSwingZMaxAngle <= JPH_PI);
61 Vec4 half_twist = 0.5f *
Vec4(inTwistMinAngle, inTwistMaxAngle, 0, 0);
62 Vec4 twist_s, twist_c;
63 half_twist.
SinCos(twist_s, twist_c);
64 Vec4 half_swing = 0.5f *
Vec4(inSwingYMinAngle, inSwingYMaxAngle, inSwingZMinAngle, inSwingZMaxAngle);
65 Vec4 swing_s, swing_c;
66 half_swing.
SinCos(swing_s, swing_c);
69 mSwingYHalfMinAngle = half_swing.
GetX();
70 mSwingYHalfMaxAngle = half_swing.
GetY();
71 mSwingZHalfMinAngle = half_swing.
GetZ();
72 mSwingZHalfMaxAngle = half_swing.
GetW();
76 if (inTwistMinAngle > -cLockedAngle && inTwistMaxAngle < cLockedAngle)
78 mRotationFlags |= TwistXLocked;
79 mSinTwistHalfMinAngle = 0.0f;
80 mSinTwistHalfMaxAngle = 0.0f;
81 mCosTwistHalfMinAngle = 1.0f;
82 mCosTwistHalfMaxAngle = 1.0f;
84 else if (inTwistMinAngle < -cFreeAngle && inTwistMaxAngle > cFreeAngle)
86 mRotationFlags |= TwistXFree;
87 mSinTwistHalfMinAngle = -1.0f;
88 mSinTwistHalfMaxAngle = 1.0f;
89 mCosTwistHalfMinAngle = 0.0f;
90 mCosTwistHalfMaxAngle = 0.0f;
94 mSinTwistHalfMinAngle = twist_s.
GetX();
95 mSinTwistHalfMaxAngle = twist_s.
GetY();
96 mCosTwistHalfMinAngle = twist_c.
GetX();
97 mCosTwistHalfMaxAngle = twist_c.
GetY();
100 if (inSwingYMinAngle > -cLockedAngle && inSwingYMaxAngle < cLockedAngle)
102 mRotationFlags |= SwingYLocked;
103 mSinSwingYHalfMinAngle = 0.0f;
104 mSinSwingYHalfMaxAngle = 0.0f;
105 mCosSwingYHalfMinAngle = 1.0f;
106 mCosSwingYHalfMaxAngle = 1.0f;
108 else if (inSwingYMinAngle < -cFreeAngle && inSwingYMaxAngle > cFreeAngle)
110 mRotationFlags |= SwingYFree;
111 mSinSwingYHalfMinAngle = -1.0f;
112 mSinSwingYHalfMaxAngle = 1.0f;
113 mCosSwingYHalfMinAngle = 0.0f;
114 mCosSwingYHalfMaxAngle = 0.0f;
118 mSinSwingYHalfMinAngle = swing_s.
GetX();
119 mSinSwingYHalfMaxAngle = swing_s.
GetY();
120 mCosSwingYHalfMinAngle = swing_c.
GetX();
121 mCosSwingYHalfMaxAngle = swing_c.
GetY();
122 JPH_ASSERT(mSinSwingYHalfMinAngle <= mSinSwingYHalfMaxAngle);
125 if (inSwingZMinAngle > -cLockedAngle && inSwingZMaxAngle < cLockedAngle)
127 mRotationFlags |= SwingZLocked;
128 mSinSwingZHalfMinAngle = 0.0f;
129 mSinSwingZHalfMaxAngle = 0.0f;
130 mCosSwingZHalfMinAngle = 1.0f;
131 mCosSwingZHalfMaxAngle = 1.0f;
133 else if (inSwingZMinAngle < -cFreeAngle && inSwingZMaxAngle > cFreeAngle)
135 mRotationFlags |= SwingZFree;
136 mSinSwingZHalfMinAngle = -1.0f;
137 mSinSwingZHalfMaxAngle = 1.0f;
138 mCosSwingZHalfMinAngle = 0.0f;
139 mCosSwingZHalfMaxAngle = 0.0f;
143 mSinSwingZHalfMinAngle = swing_s.
GetZ();
144 mSinSwingZHalfMaxAngle = swing_s.
GetW();
145 mCosSwingZHalfMinAngle = swing_c.
GetZ();
146 mCosSwingZHalfMaxAngle = swing_c.
GetW();
147 JPH_ASSERT(mSinSwingZHalfMinAngle <= mSinSwingZHalfMaxAngle);
167 inDeltaMin = abs(inDeltaMin);
168 if (inDeltaMin > 1.0f) inDeltaMin = 2.0f - inDeltaMin;
169 inDeltaMax = abs(inDeltaMax);
170 if (inDeltaMax > 1.0f) inDeltaMax = 2.0f - inDeltaMax;
171 return inDeltaMin < inDeltaMax;
186 bool negate_swing = ioSwing.
GetW() < 0.0f;
189 bool negate_twist = ioTwist.
GetW() < 0.0f;
193 if (mRotationFlags & TwistXLocked)
199 else if ((mRotationFlags & TwistXFree) == 0)
202 float delta_min = mSinTwistHalfMinAngle - ioTwist.
GetX();
203 float delta_max = ioTwist.
GetX() - mSinTwistHalfMaxAngle;
204 if (delta_min > 0.0f || delta_max > 0.0f)
209 ioTwist =
Quat(mSinTwistHalfMinAngle, 0, 0, mCosTwistHalfMinAngle);
214 ioTwist =
Quat(mSinTwistHalfMaxAngle, 0, 0, mCosTwistHalfMaxAngle);
221 if (mRotationFlags & SwingYLocked)
223 if (mRotationFlags & SwingZLocked)
234 float delta_min = mSinSwingZHalfMinAngle - ioSwing.
GetZ();
235 float delta_max = ioSwing.
GetZ() - mSinSwingZHalfMaxAngle;
236 if (delta_min > 0.0f || delta_max > 0.0f)
241 ioSwing =
Quat(0, 0, mSinSwingZHalfMinAngle, mCosSwingZHalfMinAngle);
246 ioSwing =
Quat(0, 0, mSinSwingZHalfMaxAngle, mCosSwingZHalfMaxAngle);
252 float z = ioSwing.
GetZ();
253 ioSwing =
Quat(0, 0, z, sqrt(1.0f -
Square(z)));
257 else if (mRotationFlags & SwingZLocked)
261 float delta_min = mSinSwingYHalfMinAngle - ioSwing.
GetY();
262 float delta_max = ioSwing.
GetY() - mSinSwingYHalfMaxAngle;
263 if (delta_min > 0.0f || delta_max > 0.0f)
268 ioSwing =
Quat(0, mSinSwingYHalfMinAngle, 0, mCosSwingYHalfMinAngle);
273 ioSwing =
Quat(0, mSinSwingYHalfMaxAngle, 0, mCosSwingYHalfMaxAngle);
279 float y = ioSwing.
GetY();
280 ioSwing =
Quat(0, y, 0, sqrt(1.0f -
Square(y)));
286 if (mSwingType == ESwingType::Cone)
289 Ellipse ellipse(mSinSwingYHalfMaxAngle, mSinSwingZHalfMaxAngle);
294 ioSwing =
Quat(0, closest.
x, closest.
y, sqrt(max(0.0f, 1.0f -
Square(closest.
x) -
Square(closest.
y))));
306 Vec4 min_half_angle(mSwingYHalfMinAngle, mSwingYHalfMinAngle, mSwingZHalfMinAngle, mSwingZHalfMinAngle);
307 Vec4 max_half_angle(mSwingYHalfMaxAngle, mSwingYHalfMaxAngle, mSwingZHalfMaxAngle, mSwingZHalfMaxAngle);
315 clamped_half_angle.
SinCos(s, c);
340 Quat q_swing, q_twist;
344 Quat q_clamped_swing = q_swing, q_clamped_twist = q_twist;
348 if (mRotationFlags & SwingYLocked)
350 Quat twist_to_world = inConstraintToWorld * q_swing;
351 mWorldSpaceSwingLimitYRotationAxis = twist_to_world.
RotateAxisY();
352 mWorldSpaceSwingLimitZRotationAxis = twist_to_world.
RotateAxisZ();
354 if (mRotationFlags & SwingZLocked)
367 mWorldSpaceSwingLimitZRotationAxis = -mWorldSpaceSwingLimitZRotationAxis;
374 else if (mRotationFlags & SwingZLocked)
377 Quat twist_to_world = inConstraintToWorld * q_swing;
378 mWorldSpaceSwingLimitYRotationAxis = twist_to_world.
RotateAxisY();
379 mWorldSpaceSwingLimitZRotationAxis = twist_to_world.
RotateAxisZ();
384 mWorldSpaceSwingLimitYRotationAxis = -mWorldSpaceSwingLimitYRotationAxis;
391 else if ((mRotationFlags & SwingYZFree) != SwingYZFree)
397 Vec3 current = (inConstraintToWorld * q_swing).RotateAxisX();
398 Vec3 desired = (inConstraintToWorld * q_clamped_swing).RotateAxisX();
399 mWorldSpaceSwingLimitYRotationAxis = desired.
Cross(current);
400 float len = mWorldSpaceSwingLimitYRotationAxis.
Length();
403 mWorldSpaceSwingLimitYRotationAxis /= len;
420 if (mRotationFlags & TwistXLocked)
423 mWorldSpaceTwistLimitRotationAxis = (inConstraintToWorld * q_swing).RotateAxisX();
426 else if ((mRotationFlags & TwistXFree) == 0)
431 mWorldSpaceTwistLimitRotationAxis = (inConstraintToWorld * q_swing).RotateAxisX();
433 mWorldSpaceTwistLimitRotationAxis = -mWorldSpaceTwistLimitRotationAxis;
457 return mSwingLimitYConstraintPart.
IsActive() || mSwingLimitZConstraintPart.
IsActive() || mTwistLimitConstraintPart.
IsActive();
463 mSwingLimitYConstraintPart.
WarmStart(ioBody1, ioBody2, inWarmStartImpulseRatio);
464 mSwingLimitZConstraintPart.
WarmStart(ioBody1, ioBody2, inWarmStartImpulseRatio);
465 mTwistLimitConstraintPart.
WarmStart(ioBody1, ioBody2, inWarmStartImpulseRatio);
471 bool impulse =
false;
474 if (mSwingLimitYConstraintPart.
IsActive())
475 impulse |= mSwingLimitYConstraintPart.
SolveVelocityConstraint(ioBody1, ioBody2, mWorldSpaceSwingLimitYRotationAxis, -FLT_MAX, mSinSwingYHalfMinAngle == mSinSwingYHalfMaxAngle? FLT_MAX : 0.0f);
477 if (mSwingLimitZConstraintPart.
IsActive())
478 impulse |= mSwingLimitZConstraintPart.
SolveVelocityConstraint(ioBody1, ioBody2, mWorldSpaceSwingLimitZRotationAxis, -FLT_MAX, mSinSwingZHalfMinAngle == mSinSwingZHalfMaxAngle? FLT_MAX : 0.0f);
481 if (mTwistLimitConstraintPart.
IsActive())
482 impulse |= mTwistLimitConstraintPart.
SolveVelocityConstraint(ioBody1, ioBody2, mWorldSpaceTwistLimitRotationAxis, -FLT_MAX, mSinTwistHalfMinAngle == mSinTwistHalfMaxAngle? FLT_MAX : 0.0f);
495 Quat q_swing, q_twist;
502 if (clamped_axis != 0)
505 Quat inv_initial_orientation = inConstraintToBody2 * (inConstraintToBody1 * q_swing * q_twist).Conjugated();
533 mSwingLimitYConstraintPart.
SaveState(inStream);
534 mSwingLimitZConstraintPart.
SaveState(inStream);
535 mTwistLimitConstraintPart.
SaveState(inStream);
552 TwistXLocked = 1 << 0,
553 SwingYLocked = 1 << 1,
554 SwingZLocked = 1 << 2,
560 SwingYZFree = SwingYFree | SwingZFree
563 uint8 mRotationFlags;
567 float mSinTwistHalfMinAngle;
568 float mSinTwistHalfMaxAngle;
569 float mCosTwistHalfMinAngle;
570 float mCosTwistHalfMaxAngle;
571 float mSwingYHalfMinAngle;
572 float mSwingYHalfMaxAngle;
573 float mSwingZHalfMinAngle;
574 float mSwingZHalfMaxAngle;
575 float mSinSwingYHalfMinAngle;
576 float mSinSwingYHalfMaxAngle;
577 float mSinSwingZHalfMinAngle;
578 float mSinSwingZHalfMaxAngle;
579 float mCosSwingYHalfMinAngle;
580 float mCosSwingYHalfMaxAngle;
581 float mCosSwingZHalfMinAngle;
582 float mCosSwingZHalfMaxAngle;
587 Vec3 mWorldSpaceSwingLimitYRotationAxis;
588 Vec3 mWorldSpaceSwingLimitZRotationAxis;
589 Vec3 mWorldSpaceTwistLimitRotationAxis;
std::uint8_t uint8
Definition: Core.h:440
unsigned int uint
Definition: Core.h:439
#define JPH_NAMESPACE_END
Definition: Core.h:367
#define JPH_NAMESPACE_BEGIN
Definition: Core.h:361
#define JPH_ASSERT(...)
Definition: IssueReporting.h:33
constexpr T Square(T inV)
Square a value.
Definition: Math.h:52
constexpr float DegreesToRadians(float inV)
Convert a value from degrees to radians.
Definition: Math.h:13
ESwingType
How the swing limit behaves.
Definition: SwingTwistConstraintPart.h:15
@ Pyramid
Swing is limited by a pyramid shape, note that this pyramid starts to deform for larger swing angles.
@ Cone
Swing is limited by a cone shape, note that this cone starts to deform for larger swing angles....
@ SWIZZLE_Z
Use the Z component.
Definition: Swizzle.h:14
@ SWIZZLE_Y
Use the Y component.
Definition: Swizzle.h:13
Definition: AngleConstraintPart.h:37
void Deactivate()
Deactivate this constraint.
Definition: AngleConstraintPart.h:148
bool IsActive() const
Check if constraint is active.
Definition: AngleConstraintPart.h:155
void CalculateConstraintProperties(const Body &inBody1, const Body &inBody2, Vec3Arg inWorldSpaceAxis, float inBias=0.0f)
Definition: AngleConstraintPart.h:81
void RestoreState(StateRecorder &inStream)
Restore state of this constraint part.
Definition: AngleConstraintPart.h:244
void WarmStart(Body &ioBody1, Body &ioBody2, float inWarmStartImpulseRatio)
Definition: AngleConstraintPart.h:164
bool SolveVelocityConstraint(Body &ioBody1, Body &ioBody2, Vec3Arg inWorldSpaceAxis, float inMinLambda, float inMaxLambda)
Definition: AngleConstraintPart.h:176
void SaveState(StateRecorder &inStream) const
Save state of this constraint part.
Definition: AngleConstraintPart.h:238
float GetTotalLambda() const
Return lagrange multiplier.
Definition: AngleConstraintPart.h:190
Quat GetRotation() const
World space rotation of the body.
Definition: Body.h:237
Float2 GetClosestPoint(const Float2 &inPoint) const
Definition: Ellipse.h:30
bool IsInside(const Float2 &inPoint) const
Check if inPoint is inside the ellipse.
Definition: Ellipse.h:22
Class that holds 2 floats, used as a storage class mainly.
Definition: Float2.h:11
float y
Definition: Float2.h:31
float x
Definition: Float2.h:30
static JPH_INLINE Mat44 sRotation(Vec3Arg inAxis, float inAngle)
Rotate around arbitrary axis.
Definition: Mat44.inl:139
JPH_INLINE float GetW() const
Get W component (real part)
Definition: Quat.h:78
JPH_INLINE float GetY() const
Get Y component (imaginary part j)
Definition: Quat.h:72
JPH_INLINE float GetZ() const
Get Z component (imaginary part k)
Definition: Quat.h:75
JPH_INLINE float GetX() const
Get X component (imaginary part i)
Definition: Quat.h:69
static JPH_INLINE Quat sIdentity()
Definition: Quat.h:103
JPH_INLINE Vec4 GetXYZW() const
Get the quaternion as a Vec4.
Definition: Quat.h:84
JPH_INLINE void GetSwingTwist(Quat &outSwing, Quat &outTwist) const
Definition: Quat.inl:215
JPH_INLINE Quat Normalized() const
Normalize the quaternion (make it length 1)
Definition: Quat.h:139
JPH_INLINE Vec3 RotateAxisZ() const
Rotate a the vector (0, 0, 1) with this quaternion.
Definition: Quat.inl:306
JPH_INLINE Vec3 RotateAxisY() const
Rotate a the vector (0, 1, 0) with this quaternion.
Definition: Quat.inl:297
bool IsNormalized(float inTolerance=1.0e-5f) const
If the length of this quaternion is 1 +/- inTolerance.
Definition: Quat.h:59
Definition: RotationEulerConstraintPart.h:36
bool SolvePositionConstraint(Body &ioBody1, Body &ioBody2, QuatArg inInvInitialOrientation, float inBaumgarte) const
Iteratively update the position constraint. Makes sure C(...) = 0.
Definition: RotationEulerConstraintPart.h:182
void CalculateConstraintProperties(const Body &inBody1, Mat44Arg inRotation1, const Body &inBody2, Mat44Arg inRotation2)
Calculate properties used during the functions below.
Definition: RotationEulerConstraintPart.h:139
Definition: StateRecorder.h:48
Definition: SwingTwistConstraintPart.h:33
float GetTotalSwingYLambda() const
Return lagrange multiplier for swing.
Definition: SwingTwistConstraintPart.h:514
ESwingType GetSwingType() const
Get the swing type for this part.
Definition: SwingTwistConstraintPart.h:42
void RestoreState(StateRecorder &inStream)
Restore state of this constraint part.
Definition: SwingTwistConstraintPart.h:539
float GetTotalSwingZLambda() const
Definition: SwingTwistConstraintPart.h:519
float GetTotalTwistLambda() const
Return lagrange multiplier for twist.
Definition: SwingTwistConstraintPart.h:525
static constexpr uint cClampedSwingYMax
Definition: SwingTwistConstraintPart.h:155
void WarmStart(Body &ioBody1, Body &ioBody2, float inWarmStartImpulseRatio)
Must be called from the WarmStartVelocityConstraint call to apply the previous frame's impulses.
Definition: SwingTwistConstraintPart.h:461
static constexpr uint cClampedTwistMin
Flags to indicate which axis got clamped by ClampSwingTwist.
Definition: SwingTwistConstraintPart.h:152
void ClampSwingTwist(Quat &ioSwing, Quat &ioTwist, uint &outClampedAxis) const
Clamp twist and swing against the constraint limits, returns which parts were clamped (everything ass...
Definition: SwingTwistConstraintPart.h:175
static JPH_INLINE bool sDistanceToMinShorter(float inDeltaMin, float inDeltaMax)
Helper function to determine if we're clamped against the min or max limit.
Definition: SwingTwistConstraintPart.h:160
static constexpr uint cClampedTwistMax
Definition: SwingTwistConstraintPart.h:153
static constexpr uint cClampedSwingZMin
Definition: SwingTwistConstraintPart.h:156
void SetSwingType(ESwingType inSwingType)
Override the swing type.
Definition: SwingTwistConstraintPart.h:36
void SaveState(StateRecorder &inStream) const
Save state of this constraint part.
Definition: SwingTwistConstraintPart.h:531
static constexpr uint cClampedSwingYMin
Definition: SwingTwistConstraintPart.h:154
void SetLimits(float inTwistMinAngle, float inTwistMaxAngle, float inSwingYMinAngle, float inSwingYMaxAngle, float inSwingZMinAngle, float inSwingZMaxAngle)
Set limits for this constraint (see description above for parameters)
Definition: SwingTwistConstraintPart.h:48
void CalculateConstraintProperties(const Body &inBody1, const Body &inBody2, QuatArg inConstraintRotation, QuatArg inConstraintToWorld)
Definition: SwingTwistConstraintPart.h:337
static constexpr uint cClampedSwingZMax
Definition: SwingTwistConstraintPart.h:157
bool SolveVelocityConstraint(Body &ioBody1, Body &ioBody2)
Iteratively update the velocity constraint. Makes sure d/dt C(...) = 0, where C is the constraint equ...
Definition: SwingTwistConstraintPart.h:469
void Deactivate()
Deactivate this constraint.
Definition: SwingTwistConstraintPart.h:447
bool SolvePositionConstraint(Body &ioBody1, Body &ioBody2, QuatArg inConstraintRotation, QuatArg inConstraintToBody1, QuatArg inConstraintToBody2, float inBaumgarte) const
Definition: SwingTwistConstraintPart.h:493
bool IsActive() const
Check if constraint is active.
Definition: SwingTwistConstraintPart.h:455
JPH_INLINE bool TestAllTrue() const
Test if all components are true (true is when highest bit of component is set)
Definition: UVec4.inl:400
JPH_INLINE Vec3 Cross(Vec3Arg inV2) const
Cross product.
Definition: Vec3.inl:582
JPH_INLINE float Length() const
Length of vector.
Definition: Vec3.inl:669
static Vec4 sATan2(Vec4Arg inY, Vec4Arg inX)
Calculate the arc tangent of y / x using the signs of the arguments to determine the correct quadrant...
Definition: Vec4.inl:937
JPH_INLINE float GetW() const
Definition: Vec4.h:116
static JPH_INLINE UVec4 sEquals(Vec4Arg inV1, Vec4Arg inV2)
Equals (component wise)
Definition: Vec4.inl:166
static JPH_INLINE Vec4 sMin(Vec4Arg inV1, Vec4Arg inV2)
Return the minimum value of each of the components.
Definition: Vec4.inl:138
JPH_INLINE Vec4 SplatW() const
Replicate the W component to all components.
Definition: Vec4.inl:580
JPH_INLINE float GetX() const
Get individual components.
Definition: Vec4.h:113
JPH_INLINE Vec4 Swizzle() const
Swizzle the elements in inV.
static JPH_INLINE Vec4 sMax(Vec4Arg inV1, Vec4Arg inV2)
Return the maximum of each of the components.
Definition: Vec4.inl:152
JPH_INLINE float GetZ() const
Definition: Vec4.h:115
JPH_INLINE float GetY() const
Definition: Vec4.h:114
void SinCos(Vec4 &outSin, Vec4 &outCos) const
Calculate the sine and cosine for each element of this vector (input in radians)
Definition: Vec4.inl:767