Wheel.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #pragma once
  4. #include <Jolt/Physics/Body/Body.h>
  5. #include <Jolt/Physics/Constraints/ConstraintPart/AxisConstraintPart.h>
  6. #include <Jolt/ObjectStream/SerializableObject.h>
  7. #include <Jolt/Core/StreamIn.h>
  8. #include <Jolt/Core/StreamOut.h>
  9. JPH_NAMESPACE_BEGIN
  10. class VehicleConstraint;
  11. /// Base class for wheel settings, each VehicleController can implement a derived class of this
  12. class WheelSettings : public SerializableObject, public RefTarget<WheelSettings>, public NonCopyable
  13. {
  14. public:
  15. JPH_DECLARE_SERIALIZABLE_VIRTUAL(WheelSettings)
  16. /// Saves the contents in binary form to inStream.
  17. virtual void SaveBinaryState(StreamOut &inStream) const;
  18. /// Restores the contents in binary form to inStream.
  19. virtual void RestoreBinaryState(StreamIn &inStream);
  20. Vec3 mPosition { 0, 0, 0 }; ///< Attachment point of wheel suspension in local space of the body
  21. Vec3 mDirection { 0, -1, 0 }; ///< Direction of the suspension in local space of the body
  22. float mSuspensionMinLength = 0.3f; ///< How long the suspension is in max raised position relative to the attachment point (m)
  23. float mSuspensionMaxLength = 0.5f; ///< How long the suspension is in max droop position relative to the attachment point (m)
  24. float mSuspensionPreloadLength = 0.0f; ///< The natural length (m) of the suspension spring is defined as mSuspensionMaxLength + mSuspensionPreloadLength. Can be used to preload the suspension as the spring is compressed by mSuspensionPreloadLength when the suspension is in max droop position. Note that this means when the vehicle touches the ground there is a discontinuity so it will also make the vehicle more bouncy as we're updating with discrete time steps.
  25. float mSuspensionFrequency = 1.5f; ///< Natural frequency of the suspension spring (Hz)
  26. float mSuspensionDamping = 0.5f; ///< Damping factor of the suspension spring (0 = no damping, 1 = critical damping)
  27. float mRadius = 0.3f; ///< Radius of the wheel (m)
  28. float mWidth = 0.1f; ///< Width of the wheel (m)
  29. };
  30. /// Base class for runtime data for a wheel, each VehicleController can implement a derived class of this
  31. class Wheel
  32. {
  33. public:
  34. JPH_OVERRIDE_NEW_DELETE
  35. /// Constructor / destructor
  36. explicit Wheel(const WheelSettings &inSettings);
  37. virtual ~Wheel() = default;
  38. /// Get settings for the wheel
  39. const WheelSettings * GetSettings() const { return mSettings; }
  40. /// Get the angular velocity (rad/s) for this wheel, note that positive means the wheel is rotating such that the car moves forward
  41. float GetAngularVelocity() const { return mAngularVelocity; }
  42. /// Update the angular velocity (rad/s)
  43. void SetAngularVelocity(float inVel) { mAngularVelocity = inVel; }
  44. /// Get the current rotation angle of the wheel in radians [0, 2 pi]
  45. float GetRotationAngle() const { return mAngle; }
  46. /// Set the current rotation angle of the wheel in radians [0, 2 pi]
  47. void SetRotationAngle(float inAngle) { mAngle = inAngle; }
  48. /// Get the current steer angle of the wheel in radians [-pi, pi], positive is to the left
  49. float GetSteerAngle() const { return mSteerAngle; }
  50. /// Set the current steer angle of the wheel in radians [-pi, pi]
  51. void SetSteerAngle(float inAngle) { mSteerAngle = inAngle; }
  52. /// Returns true if the wheel is touching an object
  53. bool HasContact() const { return mContactBody != nullptr; }
  54. /// Returns the body ID of the body that this wheel is touching
  55. BodyID GetContactBodyID() const { return mContactBodyID; }
  56. /// Returns the sub shape ID where we're contacting the body
  57. SubShapeID GetContactSubShapeID() const { return mContactSubShapeID; }
  58. /// Returns the current contact position in world space (note by the time you call this the vehicle has moved)
  59. Vec3 GetContactPosition() const { JPH_ASSERT(mContactBody != nullptr); return mContactPosition; }
  60. /// Velocity of the contact point (m / s, not relative to the wheel but in world space)
  61. Vec3 GetContactPointVelocity() const { JPH_ASSERT(mContactBody != nullptr); return mContactPointVelocity; }
  62. /// Returns the current contact mormal in world space (note by the time you call this the vehicle has moved)
  63. Vec3 GetContactNormal() const { JPH_ASSERT(mContactBody != nullptr); return mContactNormal; }
  64. /// Returns longitudinal direction (direction along the wheel relative to floor) in world space (note by the time you call this the vehicle has moved)
  65. Vec3 GetContactLongitudinal() const { JPH_ASSERT(mContactBody != nullptr); return mContactLongitudinal; }
  66. /// Returns lateral direction (sideways direction) in world space (note by the time you call this the vehicle has moved)
  67. Vec3 GetContactLateral() const { JPH_ASSERT(mContactBody != nullptr); return mContactLateral; }
  68. /// Get the length of the suspension for a wheel (m) relative to the suspension attachment point (hard point)
  69. float GetSuspensionLength() const { return mContactLength - mSettings->mRadius; }
  70. /// Check if the suspension hit its upper limit
  71. bool HasHitHardPoint() const { return mSuspensionMaxUpPart.IsActive(); }
  72. /// Get the total impulse (N s) that was applied by the suspension
  73. float GetSuspensionLambda() const { return mSuspensionPart.GetTotalLambda() + mSuspensionMaxUpPart.GetTotalLambda(); }
  74. /// Get total impulse (N s) applied along the forward direction of the wheel
  75. float GetLongitudinalLambda() const { return mLongitudinalPart.GetTotalLambda(); }
  76. /// Get total impulse (N s) applied along the sideways direction of the wheel
  77. float GetLateralLambda() const { return mLateralPart.GetTotalLambda(); }
  78. /// Internal function that should only be called by the controller. Used to apply impulses in the forward direction of the vehicle.
  79. bool SolveLongitudinalConstraintPart(const VehicleConstraint &inConstraint, float inMinImpulse, float inMaxImpulse);
  80. /// Internal function that should only be called by the controller. Used to apply impulses in the sideways direction of the vehicle.
  81. bool SolveLateralConstraintPart(const VehicleConstraint &inConstraint, float inMinImpulse, float inMaxImpulse);
  82. protected:
  83. friend class VehicleConstraint;
  84. RefConst<WheelSettings> mSettings; ///< Configuration settings for this wheel
  85. BodyID mContactBodyID; ///< ID of body for ground
  86. SubShapeID mContactSubShapeID; ///< Sub shape ID for ground
  87. Body * mContactBody = nullptr; ///< Body for ground
  88. float mContactLength; ///< Length between attachment point and ground
  89. Vec3 mContactPosition; ///< Position of the contact point between wheel and ground
  90. Vec3 mContactPointVelocity; ///< Velocity of the contact point (m / s, not relative to the wheel but in world space)
  91. Vec3 mContactNormal; ///< Normal of the contact point between wheel and ground
  92. Vec3 mContactLongitudinal; ///< Vector perpendicular to normal in the forward direction
  93. Vec3 mContactLateral; ///< Vector perpendicular to normal and longitudinal direction in the right direction
  94. Vec3 mWSDirection; ///< Suspension spring direction in world space
  95. float mAntiRollBarImpulse = 0.0f; ///< Amount of impulse applied to the suspension from the anti-rollbars
  96. float mSteerAngle = 0.0f; ///< Rotation around the suspension direction, positive is to the left
  97. float mAngularVelocity = 0.0f; ///< Rotation speed of wheel, positive when the wheels cause the vehicle to move forwards (rad/s)
  98. float mAngle = 0.0f; ///< Current rotation of the wheel (rad, [0, 2 pi])
  99. AxisConstraintPart mSuspensionPart; ///< Controls movement up/down
  100. AxisConstraintPart mSuspensionMaxUpPart; ///< Adds a hard limit when reaching the minimal suspension length
  101. AxisConstraintPart mLongitudinalPart; ///< Controls movement forward/backward
  102. AxisConstraintPart mLateralPart; ///< Controls movement sideways (slip)
  103. };
  104. using Wheels = Array<Wheel *>;
  105. JPH_NAMESPACE_END