29 void SetLimits(
float inTwistMinAngle,
float inTwistMaxAngle,
float inSwingYHalfAngle,
float inSwingZHalfAngle)
35 JPH_ASSERT(inTwistMinAngle <= 0.0f && inTwistMinAngle >= -JPH_PI);
36 JPH_ASSERT(inTwistMaxAngle >= 0.0f && inTwistMaxAngle <= JPH_PI);
37 JPH_ASSERT(inSwingYHalfAngle >= 0.0f && inSwingYHalfAngle <= JPH_PI);
38 JPH_ASSERT(inSwingZHalfAngle >= 0.0f && inSwingZHalfAngle <= JPH_PI);
42 (0.5f *
Vec4(inTwistMinAngle, inTwistMaxAngle, inSwingYHalfAngle, inSwingZHalfAngle)).SinCos(s, c);
46 if (inTwistMinAngle > -cLockedAngle && inTwistMaxAngle < cLockedAngle)
48 mRotationFlags |= TwistXLocked;
49 mSinTwistHalfMinAngle = 0.0f;
50 mSinTwistHalfMaxAngle = 0.0f;
51 mCosTwistHalfMinAngle = 1.0f;
52 mCosTwistHalfMaxAngle = 1.0f;
54 else if (inTwistMinAngle < -cFreeAngle && inTwistMaxAngle > cFreeAngle)
56 mRotationFlags |= TwistXFree;
57 mSinTwistHalfMinAngle = -1.0f;
58 mSinTwistHalfMaxAngle = 1.0f;
59 mCosTwistHalfMinAngle = 0.0f;
60 mCosTwistHalfMaxAngle = 0.0f;
64 mSinTwistHalfMinAngle = s.
GetX();
65 mSinTwistHalfMaxAngle = s.
GetY();
66 mCosTwistHalfMinAngle = c.
GetX();
67 mCosTwistHalfMaxAngle = c.
GetY();
70 if (inSwingYHalfAngle < cLockedAngle)
72 mRotationFlags |= SwingYLocked;
73 mSinSwingYQuarterAngle = 0.0f;
75 else if (inSwingYHalfAngle > cFreeAngle)
77 mRotationFlags |= SwingYFree;
78 mSinSwingYQuarterAngle = 1.0f;
82 mSinSwingYQuarterAngle = s.
GetZ();
85 if (inSwingZHalfAngle < cLockedAngle)
87 mRotationFlags |= SwingZLocked;
88 mSinSwingZQuarterAngle = 0.0f;
90 else if (inSwingZHalfAngle > cFreeAngle)
92 mRotationFlags |= SwingZFree;
93 mSinSwingZQuarterAngle = 1.0f;
97 mSinSwingZQuarterAngle = s.
GetW();
102 inline void ClampSwingTwist(
Quat &ioSwing,
bool &outSwingYClamped,
bool &outSwingZClamped,
Quat &ioTwist,
bool &outTwistClamped)
const
105 outTwistClamped =
false;
106 outSwingYClamped =
false;
107 outSwingZClamped =
false;
115 bool negate_swing = ioSwing.
GetW() < 0.0f;
118 bool negate_twist = ioTwist.
GetW() < 0.0f;
122 if (mRotationFlags & TwistXLocked)
125 if (ioTwist.
GetX() != 0.0f)
128 outTwistClamped =
true;
131 else if ((mRotationFlags & TwistXFree) == 0)
134 float delta_min = mSinTwistHalfMinAngle - ioTwist.
GetX();
135 float delta_max = ioTwist.
GetX() - mSinTwistHalfMaxAngle;
136 if (delta_min > 0.0f || delta_max > 0.0f)
143 delta_min = abs(delta_min);
144 if (delta_min > 1.0f) delta_min = 2.0f - delta_min;
145 delta_max = abs(delta_max);
146 if (delta_max > 1.0f) delta_max = 2.0f - delta_max;
149 if (delta_min < delta_max)
150 ioTwist =
Quat(mSinTwistHalfMinAngle, 0, 0, mCosTwistHalfMinAngle);
152 ioTwist =
Quat(mSinTwistHalfMaxAngle, 0, 0, mCosTwistHalfMaxAngle);
153 outTwistClamped =
true;
158 if (mRotationFlags & SwingYLocked)
160 if (mRotationFlags & SwingZLocked)
163 outSwingYClamped = ioSwing.
GetY() != 0.0f;
164 outSwingZClamped = ioSwing.
GetZ() != 0.0f;
165 if (outSwingYClamped || outSwingZClamped)
171 float z =
Clamp(ioSwing.
GetZ(), -mSinSwingZQuarterAngle, mSinSwingZQuarterAngle);
172 outSwingYClamped = ioSwing.
GetY() != 0.0f;
173 outSwingZClamped = z != ioSwing.
GetZ();
174 if (outSwingYClamped || outSwingZClamped)
175 ioSwing =
Quat(0, 0, z, sqrt(1.0f -
Square(z)));
178 else if (mRotationFlags & SwingZLocked)
181 float y =
Clamp(ioSwing.
GetY(), -mSinSwingYQuarterAngle, mSinSwingYQuarterAngle);
182 outSwingYClamped = y != ioSwing.
GetY();
183 outSwingZClamped = ioSwing.
GetZ() != 0.0f;
184 if (outSwingYClamped || outSwingZClamped)
185 ioSwing =
Quat(0, y, 0, sqrt(1.0f -
Square(y)));
190 Ellipse ellipse(mSinSwingYQuarterAngle, mSinSwingZQuarterAngle);
195 ioSwing =
Quat(0, closest.
x, closest.
y, sqrt(max(0.0f, 1.0f -
Square(closest.
x) -
Square(closest.
y))));
196 outSwingYClamped =
true;
197 outSwingZClamped =
true;
220 Quat q_swing, q_twist;
224 Quat q_clamped_swing = q_swing, q_clamped_twist = q_twist;
225 bool swing_y_clamped, swing_z_clamped, twist_clamped;
226 ClampSwingTwist(q_clamped_swing, swing_y_clamped, swing_z_clamped, q_clamped_twist, twist_clamped);
228 if (mRotationFlags & SwingYLocked)
230 Quat twist_to_world = inConstraintToWorld * q_swing;
231 mWorldSpaceSwingLimitYRotationAxis = twist_to_world.
RotateAxisY();
232 mWorldSpaceSwingLimitZRotationAxis = twist_to_world.
RotateAxisZ();
234 if (mRotationFlags & SwingZLocked)
246 if (
Sign(q_swing.GetW()) * q_swing.GetZ() < 0.0f)
247 mWorldSpaceSwingLimitZRotationAxis = -mWorldSpaceSwingLimitZRotationAxis;
254 else if (mRotationFlags & SwingZLocked)
257 Quat twist_to_world = inConstraintToWorld * q_swing;
258 mWorldSpaceSwingLimitYRotationAxis = twist_to_world.
RotateAxisY();
259 mWorldSpaceSwingLimitZRotationAxis = twist_to_world.
RotateAxisZ();
263 if (
Sign(q_swing.GetW()) * q_swing.GetY() < 0.0f)
264 mWorldSpaceSwingLimitYRotationAxis = -mWorldSpaceSwingLimitYRotationAxis;
271 else if ((mRotationFlags & SwingYZFree) != SwingYZFree)
274 if (swing_y_clamped || swing_z_clamped)
277 Vec3 current = (inConstraintToWorld * q_swing).RotateAxisX();
278 Vec3 desired = (inConstraintToWorld * q_clamped_swing).RotateAxisX();
279 mWorldSpaceSwingLimitYRotationAxis = desired.
Cross(current);
280 float len = mWorldSpaceSwingLimitYRotationAxis.
Length();
283 mWorldSpaceSwingLimitYRotationAxis /= len;
300 if (mRotationFlags & TwistXLocked)
303 mWorldSpaceTwistLimitRotationAxis = (inConstraintToWorld * q_swing).RotateAxisX();
306 else if ((mRotationFlags & TwistXFree) == 0)
311 mWorldSpaceTwistLimitRotationAxis = (inConstraintToWorld * q_swing).RotateAxisX();
313 mWorldSpaceTwistLimitRotationAxis = -mWorldSpaceTwistLimitRotationAxis;
337 return mSwingLimitYConstraintPart.
IsActive() || mSwingLimitZConstraintPart.
IsActive() || mTwistLimitConstraintPart.
IsActive();
343 mSwingLimitYConstraintPart.
WarmStart(ioBody1, ioBody2, inWarmStartImpulseRatio);
344 mSwingLimitZConstraintPart.
WarmStart(ioBody1, ioBody2, inWarmStartImpulseRatio);
345 mTwistLimitConstraintPart.
WarmStart(ioBody1, ioBody2, inWarmStartImpulseRatio);
351 bool impulse =
false;
354 if (mSwingLimitYConstraintPart.
IsActive())
355 impulse |= mSwingLimitYConstraintPart.
SolveVelocityConstraint(ioBody1, ioBody2, mWorldSpaceSwingLimitYRotationAxis, -FLT_MAX, (mRotationFlags & SwingYLocked)? FLT_MAX : 0.0f);
357 if (mSwingLimitZConstraintPart.
IsActive())
358 impulse |= mSwingLimitZConstraintPart.
SolveVelocityConstraint(ioBody1, ioBody2, mWorldSpaceSwingLimitZRotationAxis, -FLT_MAX, (mRotationFlags & SwingZLocked)? FLT_MAX : 0.0f);
361 if (mTwistLimitConstraintPart.
IsActive())
362 impulse |= mTwistLimitConstraintPart.
SolveVelocityConstraint(ioBody1, ioBody2, mWorldSpaceTwistLimitRotationAxis, -FLT_MAX, (mRotationFlags & TwistXLocked)? FLT_MAX : 0.0f);
375 Quat q_swing, q_twist;
378 bool swing_y_clamped, swing_z_clamped, twist_clamped;
379 ClampSwingTwist(q_swing, swing_y_clamped, swing_z_clamped, q_twist, twist_clamped);
382 if (swing_y_clamped || swing_z_clamped || twist_clamped)
385 Quat inv_initial_orientation = inConstraintToBody2 * (inConstraintToBody1 * q_swing * q_twist).Conjugated();
413 mSwingLimitYConstraintPart.
SaveState(inStream);
414 mSwingLimitZConstraintPart.
SaveState(inStream);
415 mTwistLimitConstraintPart.
SaveState(inStream);
432 TwistXLocked = 1 << 0,
433 SwingYLocked = 1 << 1,
434 SwingZLocked = 1 << 2,
440 SwingYZFree = SwingYFree | SwingZFree
443 uint8 mRotationFlags;
446 float mSinTwistHalfMinAngle;
447 float mSinTwistHalfMaxAngle;
448 float mCosTwistHalfMinAngle;
449 float mCosTwistHalfMaxAngle;
450 float mSinSwingYQuarterAngle;
451 float mSinSwingZQuarterAngle;
456 Vec3 mWorldSpaceSwingLimitYRotationAxis;
457 Vec3 mWorldSpaceSwingLimitZRotationAxis;
458 Vec3 mWorldSpaceTwistLimitRotationAxis;
#define JPH_NAMESPACE_END
Definition Core.h:240
uint8_t uint8
Definition Core.h:310
#define JPH_NAMESPACE_BEGIN
Definition Core.h:234
#define JPH_ASSERT(...)
Definition IssueReporting.h:33
constexpr T Clamp(T inV, T inMin, T inMax)
Clamp a value between two values.
Definition Math.h:45
constexpr T Square(T inV)
Square a value.
Definition Math.h:52
constexpr T Sign(T inV)
Get the sign of a value.
Definition Math.h:66
constexpr float DegreesToRadians(float inV)
Convert a value from degrees to radians.
Definition Math.h:13
Definition AngleConstraintPart.h:36
void Deactivate()
Deactivate this constraint.
Definition AngleConstraintPart.h:87
bool IsActive() const
Check if constraint is active.
Definition AngleConstraintPart.h:94
void CalculateConstraintProperties(float inDeltaTime, const Body &inBody1, const Body &inBody2, Vec3Arg inWorldSpaceAxis, float inBias=0.0f, float inC=0.0f, float inFrequency=0.0f, float inDamping=0.0f)
Definition AngleConstraintPart.h:71
void RestoreState(StateRecorder &inStream)
Restore state of this constraint part.
Definition AngleConstraintPart.h:183
void WarmStart(Body &ioBody1, Body &ioBody2, float inWarmStartImpulseRatio)
Definition AngleConstraintPart.h:103
bool SolveVelocityConstraint(Body &ioBody1, Body &ioBody2, Vec3Arg inWorldSpaceAxis, float inMinLambda, float inMaxLambda)
Definition AngleConstraintPart.h:115
void SaveState(StateRecorder &inStream) const
Save state of this constraint part.
Definition AngleConstraintPart.h:177
float GetTotalLambda() const
Return lagrange multiplier.
Definition AngleConstraintPart.h:129
Quat GetRotation() const
World space rotation of the body.
Definition Body.h:187
Float2 GetClosestPoint(const Float2 &inPoint) const
Definition Ellipse.h:30
bool IsInside(const Float2 &inPoint) const
Check if inPoint is inside the ellipsse.
Definition Ellipse.h:22
Class that holds 2 floats, used as a storage class mainly.
Definition Float2.h:11
float y
Definition Float2.h:30
float x
Definition Float2.h:29
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:77
JPH_INLINE float GetY() const
Get Y component (imaginary part j)
Definition Quat.h:71
JPH_INLINE float GetZ() const
Get Z component (imaginary part k)
Definition Quat.h:74
JPH_INLINE float GetX() const
Get X component (imaginary part i)
Definition Quat.h:68
static JPH_INLINE Quat sIdentity()
Definition Quat.h:93
JPH_INLINE void GetSwingTwist(Quat &outSwing, Quat &outTwist) const
Definition Quat.inl:215
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:58
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:181
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:15
Definition SwingTwistConstraintPart.h:26
float GetTotalSwingYLambda() const
Return lagrange multiplier for swing.
Definition SwingTwistConstraintPart.h:394
void ClampSwingTwist(Quat &ioSwing, bool &outSwingYClamped, bool &outSwingZClamped, Quat &ioTwist, bool &outTwistClamped) const
Clamp twist and swing against the constraint limits, returns which parts were clamped (everything ass...
Definition SwingTwistConstraintPart.h:102
void RestoreState(StateRecorder &inStream)
Restore state of this constraint part.
Definition SwingTwistConstraintPart.h:419
float GetTotalSwingZLambda() const
Definition SwingTwistConstraintPart.h:399
float GetTotalTwistLambda() const
Return lagrange multiplier for twist.
Definition SwingTwistConstraintPart.h:405
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:341
void SaveState(StateRecorder &inStream) const
Save state of this constraint part.
Definition SwingTwistConstraintPart.h:411
void SetLimits(float inTwistMinAngle, float inTwistMaxAngle, float inSwingYHalfAngle, float inSwingZHalfAngle)
Set limits for this constraint (see description above for parameters)
Definition SwingTwistConstraintPart.h:29
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:349
void Deactivate()
Deactivate this constraint.
Definition SwingTwistConstraintPart.h:327
bool SolvePositionConstraint(Body &ioBody1, Body &ioBody2, QuatArg inConstraintRotation, QuatArg inConstraintToBody1, QuatArg inConstraintToBody2, float inBaumgarte) const
Definition SwingTwistConstraintPart.h:373
void CalculateConstraintProperties(float inDeltaTime, const Body &inBody1, const Body &inBody2, QuatArg inConstraintRotation, QuatArg inConstraintToWorld)
Definition SwingTwistConstraintPart.h:217
bool IsActive() const
Check if constraint is active.
Definition SwingTwistConstraintPart.h:335
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
JPH_INLINE float GetW() const
Definition Vec4.h:115
JPH_INLINE float GetX() const
Get individual components.
Definition Vec4.h:112
JPH_INLINE float GetZ() const
Definition Vec4.h:114
JPH_INLINE float GetY() const
Definition Vec4.h:113