DistanceConstraint.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #pragma once
  4. #include <Physics/Constraints/TwoBodyConstraint.h>
  5. #include <Physics/Constraints/ConstraintPart/AxisConstraintPart.h>
  6. namespace JPH {
  7. /// Distance constraint settings, used to create a distance constraint
  8. class DistanceConstraintSettings final : public TwoBodyConstraintSettings
  9. {
  10. public:
  11. JPH_DECLARE_SERIALIZABLE_VIRTUAL(DistanceConstraintSettings)
  12. // See: ConstraintSettings::SaveBinaryState
  13. virtual void SaveBinaryState(StreamOut &inStream) const override;
  14. /// Create an an instance of this constraint
  15. virtual TwoBodyConstraint * Create(Body &inBody1, Body &inBody2) const override;
  16. /// Body 1 constraint reference frame (in world space).
  17. /// Constraint will keep mPoint1 (a point on body 1, world space) and mPoint2 (a point on body 2, world space) at the same distance.
  18. /// Note that this constraint can be used as a cheap PointConstraint by setting mPoint1 = mPoint2 (but this removes only 1 degree of freedom instead of 3).
  19. Vec3 mPoint1 = Vec3::sZero();
  20. /// Body 2 constraint reference frame (in world space)
  21. Vec3 mPoint2 = Vec3::sZero();
  22. /// Ability to override the distance range at which the two points are kept apart. If the value is negative, it will be replaced by the distance between mPoint1 and mPoint2.
  23. float mMinDistance = -1.0f;
  24. float mMaxDistance = -1.0f;
  25. /// If mFrequency != 0 the constraint will be soft and mFrequency specifies the oscillation frequency in Hz and mDamping the damping ratio (0 = no damping, 1 = critical damping).
  26. /// Note that due to the way the damping is implemented, it is impossible to get an undamped oscillation. See comment in AxisConstraintPart::CalculateConstraintProperties.
  27. float mFrequency = 0.0f;
  28. float mDamping = 0.0f;
  29. protected:
  30. // See: ConstraintSettings::RestoreBinaryState
  31. virtual void RestoreBinaryState(StreamIn &inStream) override;
  32. };
  33. /// This constraint is a stiff spring that holds 2 points at a fixed distance from each other
  34. class DistanceConstraint final : public TwoBodyConstraint
  35. {
  36. public:
  37. /// Construct distance constraint
  38. DistanceConstraint(Body &inBody1, Body &inBody2, const DistanceConstraintSettings &inSettings);
  39. // Generic interface of a constraint
  40. virtual EConstraintType GetType() const override { return EConstraintType::Distance; }
  41. virtual void SetupVelocityConstraint(float inDeltaTime) override;
  42. virtual void WarmStartVelocityConstraint(float inWarmStartImpulseRatio) override;
  43. virtual bool SolveVelocityConstraint(float inDeltaTime) override;
  44. virtual bool SolvePositionConstraint(float inDeltaTime, float inBaumgarte) override;
  45. #ifdef JPH_DEBUG_RENDERER
  46. virtual void DrawConstraint(DebugRenderer *inRenderer) const override;
  47. #endif // JPH_DEBUG_RENDERER
  48. virtual void SaveState(StateRecorder &inStream) const override;
  49. virtual void RestoreState(StateRecorder &inStream) override;
  50. // See: TwoBodyConstraint
  51. virtual Mat44 GetConstraintToBody1Matrix() const override { return Mat44::sTranslation(mLocalSpacePosition1); }
  52. virtual Mat44 GetConstraintToBody2Matrix() const override { return Mat44::sTranslation(mLocalSpacePosition2); } // Note: Incorrect rotation as we don't track the original rotation difference, should not matter though as the constraint is not limiting rotation.
  53. /// Update the minimum and maximum distance for the constraint
  54. void SetDistance(float inMinDistance, float inMaxDistance) { JPH_ASSERT(inMinDistance <= inMaxDistance); mMinDistance = inMinDistance; mMaxDistance = inMaxDistance; }
  55. float GetMinDistance() const { return mMinDistance; }
  56. float GetMaxDistance() const { return mMaxDistance; }
  57. /// Update the spring frequency for the constraint
  58. void SetFrequency(float inFrequency) { JPH_ASSERT(inFrequency >= 0.0f); mFrequency = inFrequency; }
  59. float GetFrequency() const { return mFrequency; }
  60. /// Update the spring damping for the constraint
  61. void SetDamping(float inDamping) { JPH_ASSERT(inDamping >= 0.0f); mDamping = inDamping; }
  62. float GetDamping() const { return mDamping; }
  63. ///@name Get Lagrange multiplier from last physics update (relates to how much force/torque was applied to satisfy the constraint)
  64. inline float GetTotalLambdaPosition() const { return mAxisConstraint.GetTotalLambda(); }
  65. private:
  66. // Internal helper function to calculate the values below
  67. void CalculateConstraintProperties(float inDeltaTime);
  68. // CONFIGURATION PROPERTIES FOLLOW
  69. // Local space constraint positions
  70. Vec3 mLocalSpacePosition1;
  71. Vec3 mLocalSpacePosition2;
  72. // Min/max distance that must be kept between the world space points
  73. float mMinDistance;
  74. float mMaxDistance;
  75. // Soft constraint properties (see DistanceConstraintSettings)
  76. float mFrequency;
  77. float mDamping;
  78. // RUN TIME PROPERTIES FOLLOW
  79. // World space positions and normal
  80. Vec3 mWorldSpacePosition1;
  81. Vec3 mWorldSpacePosition2;
  82. Vec3 mWorldSpaceNormal;
  83. // Depending on if the distance < min or distance > max we can apply forces to prevent further violations
  84. float mMinLambda;
  85. float mMaxLambda;
  86. // The constraint part
  87. AxisConstraintPart mAxisConstraint;
  88. };
  89. } // JPH