PathConstraint.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #pragma once
  4. #include <Physics/Constraints/TwoBodyConstraint.h>
  5. #include <Physics/Constraints/PathConstraintPath.h>
  6. #include <Physics/Constraints/MotorSettings.h>
  7. #include <Physics/Constraints/ConstraintPart/AxisConstraintPart.h>
  8. #include <Physics/Constraints/ConstraintPart/DualAxisConstraintPart.h>
  9. #include <Physics/Constraints/ConstraintPart/HingeRotationConstraintPart.h>
  10. #include <Physics/Constraints/ConstraintPart/RotationQuatConstraintPart.h>
  11. namespace JPH {
  12. /// How to constrain the rotation of the body to a PathConstraint
  13. enum class EPathRotationConstraintType
  14. {
  15. Free, ///< Do not constrain the rotation of the body at all
  16. ConstrainAroundTangent, ///< Only allow rotation around the tangent vector (following the path)
  17. ConstrainAroundNormal, ///< Only allow rotation around the normal vector (perpendicular to the path)
  18. ConstrainAroundBinormal, ///< Only allow rotation around the binormal vector (perpendicular to the path)
  19. ConstaintToPath, ///< Fully constrain the rotation of body 2 to the path (follwing the tangent and normal of the path)
  20. FullyConstrained, ///< Fully constrain the rotation of the body 2 to the rotation of body 1
  21. };
  22. /// Point constraint settings, used to create a point constraint
  23. class PathConstraintSettings final : public TwoBodyConstraintSettings
  24. {
  25. public:
  26. JPH_DECLARE_SERIALIZABLE_VIRTUAL(PathConstraintSettings)
  27. // See: ConstraintSettings::SaveBinaryState
  28. virtual void SaveBinaryState(StreamOut &inStream) const override;
  29. /// Create an an instance of this constraint
  30. virtual TwoBodyConstraint * Create(Body &inBody1, Body &inBody2) const override;
  31. /// The path that constrains the two bodies
  32. RefConst<PathConstraintPath> mPath;
  33. /// The position of the path start relative to world transform of body 1
  34. Vec3 mPathPosition = Vec3::sZero();
  35. /// The rotation of the path start relative to world transform of body 1
  36. Quat mPathRotation = Quat::sIdentity();
  37. /// The fraction along the path that corresponds to the initial position of body 2. Usually this is 0, the beginning of the path. But if you want to start an object halfway the path you can calculate this with mPath->GetClosestPoint(point on path to attach body to).
  38. float mPathFraction = 0.0f;
  39. /// Maximum amount of friction force to apply (N) when not driven by a motor.
  40. float mMaxFrictionForce = 0.0f;
  41. /// In case the constraint is powered, this determines the motor settings along the path
  42. MotorSettings mPositionMotorSettings;
  43. /// How to constrain the rotation of the body to the path
  44. EPathRotationConstraintType mRotationConstraintType = EPathRotationConstraintType::Free;
  45. protected:
  46. // See: ConstraintSettings::RestoreBinaryState
  47. virtual void RestoreBinaryState(StreamIn &inStream) override;
  48. };
  49. /// A point constraint constrains 2 bodies on a single point (removing 3 degrees of freedom)
  50. class PathConstraint final : public TwoBodyConstraint
  51. {
  52. public:
  53. /// Construct point constraint
  54. PathConstraint(Body &inBody1, Body &inBody2, const PathConstraintSettings &inSettings);
  55. // Generic interface of a constraint
  56. virtual EConstraintType GetType() const override { return EConstraintType::Path; }
  57. virtual void SetupVelocityConstraint(float inDeltaTime) override;
  58. virtual void WarmStartVelocityConstraint(float inWarmStartImpulseRatio) override;
  59. virtual bool SolveVelocityConstraint(float inDeltaTime) override;
  60. virtual bool SolvePositionConstraint(float inDeltaTime, float inBaumgarte) override;
  61. #ifdef JPH_DEBUG_RENDERER
  62. virtual void DrawConstraint(DebugRenderer *inRenderer) const override;
  63. #endif // JPH_DEBUG_RENDERER
  64. virtual void SaveState(StateRecorder &inStream) const override;
  65. virtual void RestoreState(StateRecorder &inStream) override;
  66. virtual bool IsActive() const override { return TwoBodyConstraint::IsActive() && mPath != nullptr; }
  67. // See: TwoBodyConstraint
  68. virtual Mat44 GetConstraintToBody1Matrix() const override { return mPathToBody1; }
  69. virtual Mat44 GetConstraintToBody2Matrix() const override { return mPathToBody2; }
  70. /// Update the path for this constraint
  71. void SetPath(const PathConstraintPath *inPath, float inPathFraction);
  72. /// Access to the current path
  73. const PathConstraintPath * GetPath() const { return mPath; }
  74. /// Access to the current fraction along the path e [0, GetPath()->GetMaxPathFraction()]
  75. float GetPathFraction() const { return mPathFraction; }
  76. /// Friction control
  77. void SetMaxFrictionForce(float inFrictionForce) { mMaxFrictionForce = inFrictionForce; }
  78. float GetMaxFrictionForce() const { return mMaxFrictionForce; }
  79. /// Position motor settings
  80. MotorSettings & GetPositionMotorSettings() { return mPositionMotorSettings; }
  81. const MotorSettings & GetPositionMotorSettings() const { return mPositionMotorSettings; }
  82. // Position motor controls (drives body 2 along the path)
  83. void SetPositionMotorState(EMotorState inState) { JPH_ASSERT(inState == EMotorState::Off || mPositionMotorSettings.IsValid()); mPositionMotorState = inState; }
  84. EMotorState GetPositionMotorState() const { return mPositionMotorState; }
  85. void SetTargetVelocity(float inVelocity) { mTargetVelocity = inVelocity; }
  86. float GetTargetVelocity() const { return mTargetVelocity; }
  87. void SetTargetPathFraction(float inFraction) { JPH_ASSERT(mPath->IsLooping() || (inFraction >= 0.0f && inFraction <= mPath->GetPathMaxFraction())); mTargetPathFraction = inFraction; }
  88. float GetTargetPathFraction() const { return mTargetPathFraction; }
  89. private:
  90. // Internal helper function to calculate the values below
  91. void CalculateConstraintProperties(float inDeltaTime);
  92. // CONFIGURATION PROPERTIES FOLLOW
  93. RefConst<PathConstraintPath> mPath; ///< The path that attaches the two bodies
  94. Mat44 mPathToBody1; ///< Transform that takes a quantity from path space to body 1 center of mass space
  95. Mat44 mPathToBody2; ///< Transform that takes a quantity from path space to body 2 center of mass space
  96. EPathRotationConstraintType mRotationConstraintType; ///< How to constrain the rotation of the path
  97. // Friction
  98. float mMaxFrictionForce;
  99. // Motor controls
  100. MotorSettings mPositionMotorSettings;
  101. EMotorState mPositionMotorState = EMotorState::Off;
  102. float mTargetVelocity = 0.0f;
  103. float mTargetPathFraction = 0.0f;
  104. // RUN TIME PROPERTIES FOLLOW
  105. // Positions where the point constraint acts on in world space
  106. Vec3 mR1;
  107. Vec3 mR2;
  108. // X2 + R2 - X1 - R1
  109. Vec3 mU;
  110. // World space path tangent
  111. Vec3 mPathTangent;
  112. // Normals to the path tangent
  113. Vec3 mPathNormal;
  114. Vec3 mPathBinormal;
  115. // Inverse of initial rotation from body 1 to body 2 in body 1 space (only used when rotation constraint type is FullyConstrained)
  116. Quat mInvInitialOrientation;
  117. // Current fraction along the path where body 2 is attached
  118. float mPathFraction = 0.0f;
  119. // Translation constraint parts
  120. DualAxisConstraintPart mPositionConstraintPart; ///< Constraint part that keeps the movement along the tangent of the path
  121. AxisConstraintPart mPositionLimitsConstraintPart; ///< Constraint part that prevents movement beyond the beginning and end of the path
  122. AxisConstraintPart mPositionMotorConstraintPart; ///< Constraint to drive the object along the path or to apply friction
  123. // Rotation constraint parts
  124. HingeRotationConstraintPart mHingeConstraintPart; ///< Constraint part that removes 2 degrees of rotation freedom
  125. RotationQuatConstraintPart mRotationConstraintPart; ///< Constraint part that removes all rotational freedom
  126. };
  127. } // JPH