|
@@ -32,8 +32,7 @@ public:
|
|
constexpr float cFreeAngle = DegreesToRadians(179.5f);
|
|
constexpr float cFreeAngle = DegreesToRadians(179.5f);
|
|
|
|
|
|
// Assume sane input
|
|
// Assume sane input
|
|
- JPH_ASSERT(inTwistMinAngle <= 0.0f && inTwistMinAngle >= -JPH_PI);
|
|
|
|
- JPH_ASSERT(inTwistMaxAngle >= 0.0f && inTwistMaxAngle <= JPH_PI);
|
|
|
|
|
|
+ JPH_ASSERT(inTwistMinAngle <= inTwistMinAngle);
|
|
JPH_ASSERT(inSwingYHalfAngle >= 0.0f && inSwingYHalfAngle <= JPH_PI);
|
|
JPH_ASSERT(inSwingYHalfAngle >= 0.0f && inSwingYHalfAngle <= JPH_PI);
|
|
JPH_ASSERT(inSwingZHalfAngle >= 0.0f && inSwingZHalfAngle <= JPH_PI);
|
|
JPH_ASSERT(inSwingZHalfAngle >= 0.0f && inSwingZHalfAngle <= JPH_PI);
|
|
|
|
|
|
@@ -99,10 +98,11 @@ public:
|
|
}
|
|
}
|
|
|
|
|
|
/// Clamp twist and swing against the constraint limits, returns which parts were clamped (everything assumed in constraint space)
|
|
/// Clamp twist and swing against the constraint limits, returns which parts were clamped (everything assumed in constraint space)
|
|
- inline void ClampSwingTwist(Quat &ioSwing, bool &outSwingYClamped, bool &outSwingZClamped, Quat &ioTwist, bool &outTwistClamped) const
|
|
|
|
|
|
+ inline void ClampSwingTwist(Quat &ioSwing, bool &outSwingYClamped, bool &outSwingZClamped, Quat &ioTwist, bool &outTwistClampedToMin, bool &outTwistClampedToMax) const
|
|
{
|
|
{
|
|
// Start with not clamped
|
|
// Start with not clamped
|
|
- outTwistClamped = false;
|
|
|
|
|
|
+ outTwistClampedToMin = false;
|
|
|
|
+ outTwistClampedToMax = false;
|
|
outSwingYClamped = false;
|
|
outSwingYClamped = false;
|
|
outSwingZClamped = false;
|
|
outSwingZClamped = false;
|
|
|
|
|
|
@@ -125,7 +125,7 @@ public:
|
|
if (ioTwist.GetX() != 0.0f)
|
|
if (ioTwist.GetX() != 0.0f)
|
|
{
|
|
{
|
|
ioTwist = Quat::sIdentity();
|
|
ioTwist = Quat::sIdentity();
|
|
- outTwistClamped = true;
|
|
|
|
|
|
+ outTwistClampedToMin = outTwistClampedToMax = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ((mRotationFlags & TwistXFree) == 0)
|
|
else if ((mRotationFlags & TwistXFree) == 0)
|
|
@@ -147,10 +147,15 @@ public:
|
|
|
|
|
|
// Pick the twist that corresponds to the smallest delta
|
|
// Pick the twist that corresponds to the smallest delta
|
|
if (delta_min < delta_max)
|
|
if (delta_min < delta_max)
|
|
|
|
+ {
|
|
ioTwist = Quat(mSinTwistHalfMinAngle, 0, 0, mCosTwistHalfMinAngle);
|
|
ioTwist = Quat(mSinTwistHalfMinAngle, 0, 0, mCosTwistHalfMinAngle);
|
|
|
|
+ outTwistClampedToMin = true;
|
|
|
|
+ }
|
|
else
|
|
else
|
|
|
|
+ {
|
|
ioTwist = Quat(mSinTwistHalfMaxAngle, 0, 0, mCosTwistHalfMaxAngle);
|
|
ioTwist = Quat(mSinTwistHalfMaxAngle, 0, 0, mCosTwistHalfMaxAngle);
|
|
- outTwistClamped = true;
|
|
|
|
|
|
+ outTwistClampedToMax = true;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -221,8 +226,8 @@ public:
|
|
|
|
|
|
// Clamp against joint limits
|
|
// Clamp against joint limits
|
|
Quat q_clamped_swing = q_swing, q_clamped_twist = q_twist;
|
|
Quat q_clamped_swing = q_swing, q_clamped_twist = q_twist;
|
|
- bool swing_y_clamped, swing_z_clamped, twist_clamped;
|
|
|
|
- ClampSwingTwist(q_clamped_swing, swing_y_clamped, swing_z_clamped, q_clamped_twist, twist_clamped);
|
|
|
|
|
|
+ bool swing_y_clamped, swing_z_clamped, twist_clamped_to_min, twist_clamped_to_max;
|
|
|
|
+ ClampSwingTwist(q_clamped_swing, swing_y_clamped, swing_z_clamped, q_clamped_twist, twist_clamped_to_min, twist_clamped_to_max);
|
|
|
|
|
|
if (mRotationFlags & SwingYLocked)
|
|
if (mRotationFlags & SwingYLocked)
|
|
{
|
|
{
|
|
@@ -305,11 +310,11 @@ public:
|
|
else if ((mRotationFlags & TwistXFree) == 0)
|
|
else if ((mRotationFlags & TwistXFree) == 0)
|
|
{
|
|
{
|
|
// Twist has limits
|
|
// Twist has limits
|
|
- if (twist_clamped)
|
|
|
|
|
|
+ if (twist_clamped_to_min || twist_clamped_to_max)
|
|
{
|
|
{
|
|
mWorldSpaceTwistLimitRotationAxis = (inConstraintToWorld * q_swing).RotateAxisX();
|
|
mWorldSpaceTwistLimitRotationAxis = (inConstraintToWorld * q_swing).RotateAxisX();
|
|
- if (Sign(q_twist.GetW()) * q_twist.GetX() < 0.0f)
|
|
|
|
- mWorldSpaceTwistLimitRotationAxis = -mWorldSpaceTwistLimitRotationAxis; // Flip axis if angle is negative because the impulse limit is going to be between [-FLT_MAX, 0]
|
|
|
|
|
|
+ if (twist_clamped_to_min)
|
|
|
|
+ mWorldSpaceTwistLimitRotationAxis = -mWorldSpaceTwistLimitRotationAxis; // Flip axis if hittin min limit because the impulse limit is going to be between [-FLT_MAX, 0]
|
|
mTwistLimitConstraintPart.CalculateConstraintProperties(inBody1, inBody2, mWorldSpaceTwistLimitRotationAxis);
|
|
mTwistLimitConstraintPart.CalculateConstraintProperties(inBody1, inBody2, mWorldSpaceTwistLimitRotationAxis);
|
|
}
|
|
}
|
|
else
|
|
else
|
|
@@ -374,11 +379,11 @@ public:
|
|
Quat q_swing, q_twist;
|
|
Quat q_swing, q_twist;
|
|
inConstraintRotation.GetSwingTwist(q_swing, q_twist);
|
|
inConstraintRotation.GetSwingTwist(q_swing, q_twist);
|
|
|
|
|
|
- bool swing_y_clamped, swing_z_clamped, twist_clamped;
|
|
|
|
- ClampSwingTwist(q_swing, swing_y_clamped, swing_z_clamped, q_twist, twist_clamped);
|
|
|
|
|
|
+ bool swing_y_clamped, swing_z_clamped, twist_clamped_to_min, twist_clamped_to_max;
|
|
|
|
+ ClampSwingTwist(q_swing, swing_y_clamped, swing_z_clamped, q_twist, twist_clamped_to_min, twist_clamped_to_max);
|
|
|
|
|
|
// Solve rotation violations
|
|
// Solve rotation violations
|
|
- if (swing_y_clamped || swing_z_clamped || twist_clamped)
|
|
|
|
|
|
+ if (swing_y_clamped || swing_z_clamped || twist_clamped_to_min || twist_clamped_to_max)
|
|
{
|
|
{
|
|
RotationEulerConstraintPart part;
|
|
RotationEulerConstraintPart part;
|
|
Quat inv_initial_orientation = inConstraintToBody2 * (inConstraintToBody1 * q_swing * q_twist).Conjugated();
|
|
Quat inv_initial_orientation = inConstraintToBody2 * (inConstraintToBody1 * q_swing * q_twist).Conjugated();
|