MotionProperties.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #pragma once
  5. #include <Jolt/Geometry/Sphere.h>
  6. #include <Jolt/Physics/Body/AllowedDOFs.h>
  7. #include <Jolt/Physics/Body/MotionQuality.h>
  8. #include <Jolt/Physics/Body/BodyAccess.h>
  9. #include <Jolt/Physics/Body/MotionType.h>
  10. #include <Jolt/Physics/Body/BodyType.h>
  11. #include <Jolt/Physics/Body/MassProperties.h>
  12. #include <Jolt/Physics/DeterminismLog.h>
  13. JPH_NAMESPACE_BEGIN
  14. class StateRecorder;
  15. /// Enum that determines if an object can go to sleep
  16. enum class ECanSleep
  17. {
  18. CannotSleep = 0, ///< Object cannot go to sleep
  19. CanSleep = 1, ///< Object can go to sleep
  20. };
  21. /// The Body class only keeps track of state for static bodies, the MotionProperties class keeps the additional state needed for a moving Body. It has a 1-on-1 relationship with the body.
  22. class JPH_EXPORT MotionProperties
  23. {
  24. public:
  25. JPH_OVERRIDE_NEW_DELETE
  26. /// Motion quality, or how well it detects collisions when it has a high velocity
  27. EMotionQuality GetMotionQuality() const { return mMotionQuality; }
  28. /// Get the allowed degrees of freedom that this body has (this can be changed by calling SetMassProperties)
  29. inline EAllowedDOFs GetAllowedDOFs() const { return mAllowedDOFs; }
  30. /// If this body can go to sleep.
  31. inline bool GetAllowSleeping() const { return mAllowSleeping; }
  32. /// Get world space linear velocity of the center of mass
  33. inline Vec3 GetLinearVelocity() const { JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess, BodyAccess::EAccess::Read)); return mLinearVelocity; }
  34. /// Set world space linear velocity of the center of mass
  35. void SetLinearVelocity(Vec3Arg inLinearVelocity) { JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess, BodyAccess::EAccess::ReadWrite)); JPH_ASSERT(inLinearVelocity.Length() <= mMaxLinearVelocity); mLinearVelocity = inLinearVelocity; }
  36. /// Set world space linear velocity of the center of mass, will make sure the value is clamped against the maximum linear velocity
  37. void SetLinearVelocityClamped(Vec3Arg inLinearVelocity) { mLinearVelocity = inLinearVelocity; ClampLinearVelocity(); }
  38. /// Get world space angular velocity of the center of mass
  39. inline Vec3 GetAngularVelocity() const { JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess, BodyAccess::EAccess::Read)); return mAngularVelocity; }
  40. /// Set world space angular velocity of the center of mass
  41. void SetAngularVelocity(Vec3Arg inAngularVelocity) { JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess, BodyAccess::EAccess::ReadWrite)); JPH_ASSERT(inAngularVelocity.Length() <= mMaxAngularVelocity); mAngularVelocity = inAngularVelocity; }
  42. /// Set world space angular velocity of the center of mass, will make sure the value is clamped against the maximum angular velocity
  43. void SetAngularVelocityClamped(Vec3Arg inAngularVelocity) { mAngularVelocity = inAngularVelocity; ClampAngularVelocity(); }
  44. /// Set velocity of body such that it will be rotate/translate by inDeltaPosition/Rotation in inDeltaTime seconds.
  45. inline void MoveKinematic(Vec3Arg inDeltaPosition, QuatArg inDeltaRotation, float inDeltaTime);
  46. ///@name Velocity limits
  47. ///@{
  48. /// Maximum linear velocity that a body can achieve. Used to prevent the system from exploding.
  49. inline float GetMaxLinearVelocity() const { return mMaxLinearVelocity; }
  50. inline void SetMaxLinearVelocity(float inLinearVelocity) { JPH_ASSERT(inLinearVelocity >= 0.0f); mMaxLinearVelocity = inLinearVelocity; }
  51. /// Maximum angular velocity that a body can achieve. Used to prevent the system from exploding.
  52. inline float GetMaxAngularVelocity() const { return mMaxAngularVelocity; }
  53. inline void SetMaxAngularVelocity(float inAngularVelocity) { JPH_ASSERT(inAngularVelocity >= 0.0f); mMaxAngularVelocity = inAngularVelocity; }
  54. ///@}
  55. /// Clamp velocity according to limit
  56. inline void ClampLinearVelocity();
  57. inline void ClampAngularVelocity();
  58. /// Get linear damping: dv/dt = -c * v. c must be between 0 and 1 but is usually close to 0.
  59. inline float GetLinearDamping() const { return mLinearDamping; }
  60. void SetLinearDamping(float inLinearDamping) { JPH_ASSERT(inLinearDamping >= 0.0f); mLinearDamping = inLinearDamping; }
  61. /// Get angular damping: dw/dt = -c * w. c must be between 0 and 1 but is usually close to 0.
  62. inline float GetAngularDamping() const { return mAngularDamping; }
  63. void SetAngularDamping(float inAngularDamping) { JPH_ASSERT(inAngularDamping >= 0.0f); mAngularDamping = inAngularDamping; }
  64. /// Get gravity factor (1 = normal gravity, 0 = no gravity)
  65. inline float GetGravityFactor() const { return mGravityFactor; }
  66. void SetGravityFactor(float inGravityFactor) { mGravityFactor = inGravityFactor; }
  67. /// Set the mass and inertia tensor
  68. void SetMassProperties(EAllowedDOFs inAllowedDOFs, const MassProperties &inMassProperties);
  69. /// Get inverse mass (1 / mass). Should only be called on a dynamic object (static or kinematic bodies have infinite mass so should be treated as 1 / mass = 0)
  70. inline float GetInverseMass() const { JPH_ASSERT(mCachedMotionType == EMotionType::Dynamic); return mInvMass; }
  71. inline float GetInverseMassUnchecked() const { return mInvMass; }
  72. /// Set the inverse mass (1 / mass).
  73. /// Note that mass and inertia are linearly related (e.g. inertia of a sphere with mass m and radius r is \f$2/5 \: m \: r^2\f$).
  74. /// If you change mass, inertia should probably change as well. See MassProperties::ScaleToMass.
  75. /// If all your translation degrees of freedom are restricted, make sure this is zero (see EAllowedDOFs).
  76. void SetInverseMass(float inInverseMass) { mInvMass = inInverseMass; }
  77. /// Diagonal of inverse inertia matrix: D. Should only be called on a dynamic object (static or kinematic bodies have infinite mass so should be treated as D = 0)
  78. inline Vec3 GetInverseInertiaDiagonal() const { JPH_ASSERT(mCachedMotionType == EMotionType::Dynamic); return mInvInertiaDiagonal; }
  79. /// Rotation (R) that takes inverse inertia diagonal to local space: \f$I_{body}^{-1} = R \: D \: R^{-1}\f$
  80. inline Quat GetInertiaRotation() const { return mInertiaRotation; }
  81. /// Set the inverse inertia tensor in local space by setting the diagonal and the rotation: \f$I_{body}^{-1} = R \: D \: R^{-1}\f$.
  82. /// Note that mass and inertia are linearly related (e.g. inertia of a sphere with mass m and radius r is \f$2/5 \: m \: r^2\f$).
  83. /// If you change inertia, mass should probably change as well. See MassProperties::ScaleToMass.
  84. /// If you don't allow all rotational degrees of freedom, make sure that the corresponding diagonal elements are zero (see EAllowedDOFs).
  85. void SetInverseInertia(Vec3Arg inDiagonal, QuatArg inRot) { mInvInertiaDiagonal = inDiagonal; mInertiaRotation = inRot; }
  86. /// Get inverse inertia matrix (\f$I_{body}^{-1}\f$). Will be a matrix of zeros for a static or kinematic object.
  87. inline Mat44 GetLocalSpaceInverseInertia() const;
  88. /// Same as GetLocalSpaceInverseInertia() but doesn't check if the body is dynamic
  89. inline Mat44 GetLocalSpaceInverseInertiaUnchecked() const;
  90. /// Get inverse inertia matrix (\f$I^{-1}\f$) for a given object rotation (translation will be ignored). Zero if object is static or kinematic.
  91. inline Mat44 GetInverseInertiaForRotation(Mat44Arg inRotation) const;
  92. /// Multiply a vector with the inverse world space inertia tensor (\f$I_{world}^{-1}\f$). Zero if object is static or kinematic.
  93. JPH_INLINE Vec3 MultiplyWorldSpaceInverseInertiaByVector(QuatArg inBodyRotation, Vec3Arg inV) const;
  94. /// Velocity of point inPoint (in center of mass space, e.g. on the surface of the body) of the body (unit: m/s)
  95. JPH_INLINE Vec3 GetPointVelocityCOM(Vec3Arg inPointRelativeToCOM) const { return mLinearVelocity + mAngularVelocity.Cross(inPointRelativeToCOM); }
  96. // Get the total amount of force applied to the center of mass this time step (through Body::AddForce calls). Note that it will reset to zero after PhysicsSimulation::Update.
  97. JPH_INLINE Vec3 GetAccumulatedForce() const { return Vec3::sLoadFloat3Unsafe(mForce); }
  98. // Get the total amount of torque applied to the center of mass this time step (through Body::AddForce/Body::AddTorque calls). Note that it will reset to zero after PhysicsSimulation::Update.
  99. JPH_INLINE Vec3 GetAccumulatedTorque() const { return Vec3::sLoadFloat3Unsafe(mTorque); }
  100. // Reset the total accumulated force, not that this will be done automatically after every time step.
  101. JPH_INLINE void ResetForce() { mForce = Float3(0, 0, 0); }
  102. // Reset the total accumulated torque, not that this will be done automatically after every time step.
  103. JPH_INLINE void ResetTorque() { mTorque = Float3(0, 0, 0); }
  104. /// Takes a translation vector inV and returns a vector where the components that are not allowed by mAllowedDOFs are set to 0
  105. JPH_INLINE Vec3 LockTranslation(Vec3Arg inV)
  106. {
  107. uint32 allowed_dofs = uint32(mAllowedDOFs);
  108. UVec4 allowed_dofs_mask = UVec4(allowed_dofs << 31, allowed_dofs << 30, allowed_dofs << 29, 0).ArithmeticShiftRight<31>();
  109. return Vec3::sAnd(inV, Vec3(allowed_dofs_mask.ReinterpretAsFloat()));
  110. }
  111. ////////////////////////////////////////////////////////////
  112. // FUNCTIONS BELOW THIS LINE ARE FOR INTERNAL USE ONLY
  113. ////////////////////////////////////////////////////////////
  114. ///@name Update linear and angular velocity (used during constraint solving)
  115. ///@{
  116. inline void AddLinearVelocityStep(Vec3Arg inLinearVelocityChange) { JPH_DET_LOG("AddLinearVelocityStep: " << inLinearVelocityChange); JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess, BodyAccess::EAccess::ReadWrite)); mLinearVelocity = LockTranslation(mLinearVelocity + inLinearVelocityChange); JPH_ASSERT(!mLinearVelocity.IsNaN()); }
  117. inline void SubLinearVelocityStep(Vec3Arg inLinearVelocityChange) { JPH_DET_LOG("SubLinearVelocityStep: " << inLinearVelocityChange); JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess, BodyAccess::EAccess::ReadWrite)); mLinearVelocity = LockTranslation(mLinearVelocity - inLinearVelocityChange); JPH_ASSERT(!mLinearVelocity.IsNaN()); }
  118. inline void AddAngularVelocityStep(Vec3Arg inAngularVelocityChange) { JPH_DET_LOG("AddAngularVelocityStep: " << inAngularVelocityChange); JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess, BodyAccess::EAccess::ReadWrite)); mAngularVelocity += inAngularVelocityChange; JPH_ASSERT(!mAngularVelocity.IsNaN()); }
  119. inline void SubAngularVelocityStep(Vec3Arg inAngularVelocityChange) { JPH_DET_LOG("SubAngularVelocityStep: " << inAngularVelocityChange); JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess, BodyAccess::EAccess::ReadWrite)); mAngularVelocity -= inAngularVelocityChange; JPH_ASSERT(!mAngularVelocity.IsNaN()); }
  120. ///@}
  121. /// Apply all accumulated forces, torques and drag (should only be called by the PhysicsSystem)
  122. inline void ApplyForceTorqueAndDragInternal(QuatArg inBodyRotation, Vec3Arg inGravity, float inDeltaTime);
  123. /// Access to the island index
  124. uint32 GetIslandIndexInternal() const { return mIslandIndex; }
  125. void SetIslandIndexInternal(uint32 inIndex) { mIslandIndex = inIndex; }
  126. /// Access to the index in the active bodies array
  127. uint32 GetIndexInActiveBodiesInternal() const { return mIndexInActiveBodies; }
  128. #ifdef JPH_DOUBLE_PRECISION
  129. inline DVec3 GetSleepTestOffset() const { return DVec3::sLoadDouble3Unsafe(mSleepTestOffset); }
  130. #endif // JPH_DOUBLE_PRECISION
  131. /// Reset spheres to center around inPoints with radius 0
  132. inline void ResetSleepTestSpheres(const RVec3 *inPoints);
  133. /// Reset the sleep test timer without resetting the sleep test spheres
  134. inline void ResetSleepTestTimer() { mSleepTestTimer = 0.0f; }
  135. /// Accumulate sleep time and return if a body can go to sleep
  136. inline ECanSleep AccumulateSleepTime(float inDeltaTime, float inTimeBeforeSleep);
  137. /// Saving state for replay
  138. void SaveState(StateRecorder &inStream) const;
  139. /// Restoring state for replay
  140. void RestoreState(StateRecorder &inStream);
  141. static constexpr uint32 cInactiveIndex = uint32(-1); ///< Constant indicating that body is not active
  142. private:
  143. friend class BodyManager;
  144. friend class Body;
  145. // 1st cache line
  146. // 16 byte aligned
  147. Vec3 mLinearVelocity { Vec3::sZero() }; ///< World space linear velocity of the center of mass (m/s)
  148. Vec3 mAngularVelocity { Vec3::sZero() }; ///< World space angular velocity (rad/s)
  149. Vec3 mInvInertiaDiagonal; ///< Diagonal of inverse inertia matrix: D
  150. Quat mInertiaRotation; ///< Rotation (R) that takes inverse inertia diagonal to local space: Ibody^-1 = R * D * R^-1
  151. // 2nd cache line
  152. // 4 byte aligned
  153. Float3 mForce { 0, 0, 0 }; ///< Accumulated world space force (N). Note loaded through intrinsics so ensure that the 4 bytes after this are readable!
  154. Float3 mTorque { 0, 0, 0 }; ///< Accumulated world space torque (N m). Note loaded through intrinsics so ensure that the 4 bytes after this are readable!
  155. float mInvMass; ///< Inverse mass of the object (1/kg)
  156. float mLinearDamping; ///< Linear damping: dv/dt = -c * v. c must be between 0 and 1 but is usually close to 0.
  157. float mAngularDamping; ///< Angular damping: dw/dt = -c * w. c must be between 0 and 1 but is usually close to 0.
  158. float mMaxLinearVelocity; ///< Maximum linear velocity that this body can reach (m/s)
  159. float mMaxAngularVelocity; ///< Maximum angular velocity that this body can reach (rad/s)
  160. float mGravityFactor; ///< Factor to multiply gravity with
  161. uint32 mIndexInActiveBodies = cInactiveIndex; ///< If the body is active, this is the index in the active body list or cInactiveIndex if it is not active (note that there are 2 lists, one for rigid and one for soft bodies)
  162. uint32 mIslandIndex = cInactiveIndex; ///< Index of the island that this body is part of, when the body has not yet been updated or is not active this is cInactiveIndex
  163. // 1 byte aligned
  164. EMotionQuality mMotionQuality; ///< Motion quality, or how well it detects collisions when it has a high velocity
  165. bool mAllowSleeping; ///< If this body can go to sleep
  166. EAllowedDOFs mAllowedDOFs = EAllowedDOFs::All; ///< Allowed degrees of freedom for this body
  167. // 3rd cache line (least frequently used)
  168. // 4 byte aligned (or 8 byte if running in double precision)
  169. #ifdef JPH_DOUBLE_PRECISION
  170. Double3 mSleepTestOffset; ///< mSleepTestSpheres are relative to this offset to prevent floating point inaccuracies. Warning: Loaded using sLoadDouble3Unsafe which will read 8 extra bytes.
  171. #endif // JPH_DOUBLE_PRECISION
  172. Sphere mSleepTestSpheres[3]; ///< Measure motion for 3 points on the body to see if it is resting: COM, COM + largest bounding box axis, COM + second largest bounding box axis
  173. float mSleepTestTimer; ///< How long this body has been within the movement tolerance
  174. #ifdef JPH_ENABLE_ASSERTS
  175. EBodyType mCachedBodyType; ///< Copied from Body::mBodyType and cached for asserting purposes
  176. EMotionType mCachedMotionType; ///< Copied from Body::mMotionType and cached for asserting purposes
  177. #endif
  178. };
  179. JPH_NAMESPACE_END
  180. #include "MotionProperties.inl"