SixDOFConstraint.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #pragma once
  4. #include <Physics/Constraints/TwoBodyConstraint.h>
  5. #include <Physics/Constraints/MotorSettings.h>
  6. #include <Physics/Constraints/ConstraintPart/PointConstraintPart.h>
  7. #include <Physics/Constraints/ConstraintPart/AxisConstraintPart.h>
  8. #include <Physics/Constraints/ConstraintPart/AngleConstraintPart.h>
  9. #include <Physics/Constraints/ConstraintPart/RotationEulerConstraintPart.h>
  10. #include <Physics/Constraints/ConstraintPart/SwingTwistConstraintPart.h>
  11. namespace JPH {
  12. /// 6 Degree Of Freedom Constraint setup structure. Allows control over each of the 6 degrees of freedom.
  13. class SixDOFConstraintSettings final : public TwoBodyConstraintSettings
  14. {
  15. public:
  16. JPH_DECLARE_SERIALIZABLE_VIRTUAL(SixDOFConstraintSettings)
  17. /// Constraint is split up into translation/rotation around X, Y and Z axis.
  18. enum EAxis
  19. {
  20. TranslationX,
  21. TranslationY,
  22. TranslationZ,
  23. RotationX, ///< When limited: MinLimit needs to be [-PI, 0], MaxLimit needs to be [0, PI]
  24. RotationY, ///< When limited: MaxLimit between [0, PI]. MinLimit = -MaxLimit. Forms a cone shaped limit with Z.
  25. RotationZ, ///< When limited: MaxLimit between [0, PI]. MinLimit = -MaxLimit. Forms a cone shaped limit with Y.
  26. Num,
  27. };
  28. // See: ConstraintSettings::SaveBinaryState
  29. virtual void SaveBinaryState(StreamOut &inStream) const override;
  30. /// Create an an instance of this constraint
  31. virtual TwoBodyConstraint * Create(Body &inBody1, Body &inBody2) const override;
  32. /// Body 1 constraint reference frame (in world space)
  33. Vec3 mPosition1 = Vec3::sZero();
  34. Vec3 mAxisX1 = Vec3::sAxisX();
  35. Vec3 mAxisY1 = Vec3::sAxisY();
  36. /// Body 2 constraint reference frame (in world space)
  37. Vec3 mPosition2 = Vec3::sZero();
  38. Vec3 mAxisX2 = Vec3::sAxisX();
  39. Vec3 mAxisY2 = Vec3::sAxisY();
  40. /// Friction settings.
  41. /// For translation: Max friction force in N. 0 = no friction.
  42. /// For rotation: Max friction torque in Nm. 0 = no friction.
  43. float mMaxFriction[EAxis::Num] = { 0, 0, 0, 0, 0, 0 };
  44. /// Limits.
  45. /// For translation: Min and max linear limits in m (0 is frame of body 1 and 2 coincide).
  46. /// For rotation: Min and max angular limits in rad (0 is frame of body 1 and 2 coincide). See comments at Axis enum for limit ranges.
  47. ///
  48. /// Remove degree of freedom by setting min = FLT_MAX and max = -FLT_MAX. The constraint will be driven to 0 for this axis.
  49. ///
  50. /// Free movement over an axis is allowed when min = -FLT_MAX and max = FLT_MAX.
  51. float mLimitMin[EAxis::Num] = { -FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX };
  52. float mLimitMax[EAxis::Num] = { FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX };
  53. /// Make axis free (unconstrained)
  54. void MakeFreeAxis(EAxis inAxis) { mLimitMin[inAxis] = -FLT_MAX; mLimitMax[inAxis] = FLT_MAX; }
  55. bool IsFreeAxis(EAxis inAxis) const { return mLimitMin[inAxis] == -FLT_MAX && mLimitMax[inAxis] == FLT_MAX; }
  56. /// Make axis fixed (fixed at value 0)
  57. void MakeFixedAxis(EAxis inAxis) { mLimitMin[inAxis] = FLT_MAX; mLimitMax[inAxis] = -FLT_MAX; }
  58. bool IsFixedAxis(EAxis inAxis) const { return mLimitMin[inAxis] >= mLimitMax[inAxis]; }
  59. /// Set a valid range for the constraint
  60. void SetLimitedAxis(EAxis inAxis, float inMin, float inMax) { JPH_ASSERT(inMin < inMax); JPH_ASSERT(inMin <= 0.0f); JPH_ASSERT(inMax >= 0.0f); mLimitMin[inAxis] = inMin; mLimitMax[inAxis] = inMax; }
  61. /// Motor settings for each axis
  62. MotorSettings mMotorSettings[EAxis::Num];
  63. protected:
  64. // See: ConstraintSettings::RestoreBinaryState
  65. virtual void RestoreBinaryState(StreamIn &inStream) override;
  66. };
  67. /// 6 Degree Of Freedom Constraint. Allows control over each of the 6 degrees of freedom.
  68. class SixDOFConstraint final : public TwoBodyConstraint
  69. {
  70. public:
  71. /// Get Axis from settings class
  72. using EAxis = SixDOFConstraintSettings::EAxis;
  73. /// Construct six DOF constraint
  74. SixDOFConstraint(Body &inBody1, Body &inBody2, const SixDOFConstraintSettings &inSettings);
  75. /// Generic interface of a constraint
  76. virtual EConstraintType GetType() const override { return EConstraintType::SixDOF; }
  77. virtual void SetupVelocityConstraint(float inDeltaTime) override;
  78. virtual void WarmStartVelocityConstraint(float inWarmStartImpulseRatio) override;
  79. virtual bool SolveVelocityConstraint(float inDeltaTime) override;
  80. virtual bool SolvePositionConstraint(float inDeltaTime, float inBaumgarte) override;
  81. #ifdef JPH_DEBUG_RENDERER
  82. virtual void DrawConstraint(DebugRenderer *inRenderer) const override;
  83. virtual void DrawConstraintLimits(DebugRenderer *inRenderer) const override;
  84. #endif // JPH_DEBUG_RENDERER
  85. virtual void SaveState(StateRecorder &inStream) const override;
  86. virtual void RestoreState(StateRecorder &inStream) override;
  87. // See: TwoBodyConstraint
  88. virtual Mat44 GetConstraintToBody1Matrix() const override { return Mat44::sRotationTranslation(mConstraintToBody1, mLocalSpacePosition1); }
  89. virtual Mat44 GetConstraintToBody2Matrix() const override { return Mat44::sRotationTranslation(mConstraintToBody2, mLocalSpacePosition2); }
  90. /// Update the translation limits for this constraint, note that this won't change if axis are free or not.
  91. void SetTranslationLimits(Vec3Arg inLimitMin, Vec3Arg inLimitMax);
  92. /// Update the rotational limits for this constraint, note that this won't change if axis are free or not.
  93. void SetRotationLimits(Vec3Arg inLimitMin, Vec3Arg inLimitMax);
  94. /// Get rotation of constraint in constraint space
  95. inline Quat GetRotationInConstraintSpace() const;
  96. /// Motor settings
  97. MotorSettings & GetMotorSettings(EAxis inAxis) { return mMotorSettings[inAxis]; }
  98. const MotorSettings & GetMotorSettings(EAxis inAxis) const { return mMotorSettings[inAxis]; }
  99. /// Motor controls.
  100. /// Translation motors work in constraint space of body 1.
  101. /// Rotation motors work in constraint space of body 2 (!).
  102. void SetMotorState(EAxis inAxis, EMotorState inState);
  103. EMotorState GetMotorState(EAxis inAxis) const { return mMotorState[inAxis]; }
  104. /// Set the target velocity in body 1 constraint space
  105. Vec3 GetTargetVelocityCS() const { return mTargetVelocity; }
  106. void SetTargetVelocityCS(Vec3Arg inVelocity) { mTargetVelocity = inVelocity; }
  107. /// Set the target angular velocity in body 2 constraint space (!)
  108. void SetTargetAngularVelocityCS(Vec3Arg inAngularVelocity) { mTargetAngularVelocity = inAngularVelocity; }
  109. Vec3 GetTargetAngularVelocityCS() const { return mTargetAngularVelocity; }
  110. /// Set the target position in body 1 constraint space
  111. Vec3 GetTargetPositionCS() const { return mTargetPosition; }
  112. void SetTargetPositionCS(Vec3Arg inPosition) { mTargetPosition = inPosition; }
  113. /// Set the target orientation in body 1 constraint space
  114. void SetTargetOrientationCS(QuatArg inOrientation);
  115. Quat GetTargetOrientationCS() const { return mTargetOrientation; }
  116. /// Set the target orientation in body space (R2 = R1 * inOrientation, where R1 and R2 are the world space rotations for body 1 and 2).
  117. /// Solve: R2 * ConstraintToBody2 = R1 * ConstraintToBody1 * q (see SwingTwistConstraint::GetSwingTwist) and R2 = R1 * inOrientation for q.
  118. void SetTargetOrientationBS(QuatArg inOrientation) { SetTargetOrientationCS(mConstraintToBody1.Conjugated() * inOrientation * mConstraintToBody2); }
  119. private:
  120. // Calculate properties needed for the position constraint
  121. inline void GetPositionConstraintProperties(Vec3 &outR1PlusU, Vec3 &outR2, Vec3 &outU) const;
  122. // Propagate the rotation limits to the constraint part
  123. inline void UpdateRotationLimits();
  124. // Constraint settings helper functions
  125. inline bool IsAxisFixed(EAxis inAxis) const { return (mFixedAxis & (1 << inAxis)) != 0; }
  126. inline bool IsAxisFree(EAxis inAxis) const { return (mFreeAxis & (1 << inAxis)) != 0; }
  127. inline bool IsTranslationConstrained() const { return (mFreeAxis & 0b111) != 0b111; }
  128. inline bool IsTranslationFullyConstrained() const { return (mFixedAxis & 0b111) == 0b111; }
  129. inline bool IsRotationConstrained() const { return (mFreeAxis & 0b111000) != 0b111000; }
  130. inline bool IsRotationFullyConstrained() const { return (mFixedAxis & 0b111000) == 0b111000; }
  131. // CONFIGURATION PROPERTIES FOLLOW
  132. // Local space constraint positions
  133. Vec3 mLocalSpacePosition1;
  134. Vec3 mLocalSpacePosition2;
  135. // Transforms from constraint space to body space
  136. Quat mConstraintToBody1;
  137. Quat mConstraintToBody2;
  138. // Limits
  139. uint8 mFreeAxis; // Bitmask of free axis (bit 0 = TranslationX)
  140. uint8 mFixedAxis; // Bitmask of fixed axis (bit 0 = TranslationX)
  141. bool mTranslationMotorActive = false; // If any of the translational frictions / motors are active
  142. bool mRotationMotorActive = false; // If any of the rotational frictions / motors are active
  143. uint8 mRotationPositionMotorActive = 0; // Bitmask of axis that have position motor active (bit 0 = RotationX)
  144. float mLimitMin[EAxis::Num];
  145. float mLimitMax[EAxis::Num];
  146. // Motor settings for each axis
  147. MotorSettings mMotorSettings[EAxis::Num];
  148. // Friction settings for each axis
  149. float mMaxFriction[EAxis::Num];
  150. // Motor controls
  151. EMotorState mMotorState[EAxis::Num] = { EMotorState::Off, EMotorState::Off, EMotorState::Off, EMotorState::Off, EMotorState::Off, EMotorState::Off };
  152. Vec3 mTargetVelocity = Vec3::sZero();
  153. Vec3 mTargetAngularVelocity = Vec3::sZero();
  154. Vec3 mTargetPosition = Vec3::sZero();
  155. Quat mTargetOrientation = Quat::sIdentity();
  156. // RUN TIME PROPERTIES FOLLOW
  157. // Constraint space axis in world space
  158. Vec3 mTranslationAxis[3];
  159. Vec3 mRotationAxis[3];
  160. // Translation displacement (valid when translation axis has a range limit)
  161. float mDisplacement[3];
  162. // Individual constraint parts for translation, or a combined point constraint part if all axis are fixed
  163. AxisConstraintPart mTranslationConstraintPart[3];
  164. PointConstraintPart mPointConstraintPart;
  165. // Individual constraint parts for rotation or a combined constraint part if rotation is fixed
  166. SwingTwistConstraintPart mSwingTwistConstraintPart;
  167. RotationEulerConstraintPart mRotationConstraintPart;
  168. // Motor or friction constraints
  169. AxisConstraintPart mMotorTranslationConstraintPart[3];
  170. AngleConstraintPart mMotorRotationConstraintPart[3];
  171. };
  172. } // JPH