BodyInterface.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #pragma once
  4. #include <Jolt/Physics/Body/BodyID.h>
  5. #include <Jolt/Physics/EActivation.h>
  6. #include <Jolt/Physics/Collision/ObjectLayer.h>
  7. #include <Jolt/Physics/Body/MotionType.h>
  8. #include <Jolt/Core/Reference.h>
  9. JPH_NAMESPACE_BEGIN
  10. class Body;
  11. class BodyCreationSettings;
  12. class BodyLockInterface;
  13. class BroadPhase;
  14. class BodyManager;
  15. class TransformedShape;
  16. class PhysicsMaterial;
  17. class SubShapeID;
  18. class Shape;
  19. class TwoBodyConstraintSettings;
  20. class TwoBodyConstraint;
  21. /// Class that provides operations on bodies using a body ID. Note that if you need to do multiple operations on a single body, it is more efficient to lock the body once and combine the operations.
  22. /// All quantities are in world space unless otherwise specified.
  23. class BodyInterface : public NonCopyable
  24. {
  25. public:
  26. /// Initialize the interface (should only be called by PhysicsSystem)
  27. void Init(BodyLockInterface &inBodyLockInterface, BodyManager &inBodyManager, BroadPhase &inBroadPhase) { mBodyLockInterface = &inBodyLockInterface; mBodyManager = &inBodyManager; mBroadPhase = &inBroadPhase; }
  28. /// Create a body
  29. /// @return Created body or null when out of bodies
  30. Body * CreateBody(const BodyCreationSettings &inSettings);
  31. /// Create a body with specified ID. This function can be used if a simulation is to run in sync between clients or if a simulation needs to be restored exactly.
  32. /// The ID created on the server can be replicated to the client and used to create a deterministic simulation.
  33. /// @return Created body or null when the body ID is invalid or a body of the same ID already exists.
  34. Body * CreateBodyWithID(const BodyID &inBodyID, const BodyCreationSettings &inSettings);
  35. /// Destroy a body
  36. void DestroyBody(const BodyID &inBodyID);
  37. /// Destroy multiple bodies
  38. void DestroyBodies(const BodyID *inBodyIDs, int inNumber);
  39. /// Add body to the world.
  40. /// Note that if you need to add multiple bodies, use the AddBodiesPrepare/AddBodiesFinalize function.
  41. /// Adding many bodies, one at a time, results in a really inefficient broadphase until PhysicsSystem::OptimizeBroadPhase is called or when PhysicsSystem::Update rebuilds the tree!
  42. /// After adding, to get a body by ID use the BodyLockRead or BodyLockWrite interface!
  43. void AddBody(const BodyID &inBodyID, EActivation inActivationMode);
  44. /// Remove body from the world.
  45. void RemoveBody(const BodyID &inBodyID);
  46. /// Check if a body has been added to the world.
  47. bool IsAdded(const BodyID &inBodyID) const;
  48. /// Combines CreateBody and AddBody
  49. /// @return Created body ID or an invalid ID when out of bodies
  50. BodyID CreateAndAddBody(const BodyCreationSettings &inSettings, EActivation inActivationMode);
  51. /// Broadphase add state handle, used to keep track of a batch while ading to the broadphase.
  52. using AddState = void *;
  53. ///@name Batch adding interface, see Broadphase for further documentation.
  54. /// Note that ioBodies array must be kept constant while the add is in progress.
  55. ///@{
  56. AddState AddBodiesPrepare(BodyID *ioBodies, int inNumber);
  57. void AddBodiesFinalize(BodyID *ioBodies, int inNumber, AddState inAddState, EActivation inActivationMode);
  58. void AddBodiesAbort(BodyID *ioBodies, int inNumber, AddState inAddState);
  59. void RemoveBodies(BodyID *ioBodies, int inNumber);
  60. ///@}
  61. ///@name Activate / deactivate a body
  62. ///@{
  63. void ActivateBody(const BodyID &inBodyID);
  64. void ActivateBodies(const BodyID *inBodyIDs, int inNumber);
  65. void DeactivateBody(const BodyID &inBodyID);
  66. void DeactivateBodies(const BodyID *inBodyIDs, int inNumber);
  67. bool IsActive(const BodyID &inBodyID) const;
  68. ///@}
  69. /// Create a two body constraint
  70. TwoBodyConstraint * CreateConstraint(const TwoBodyConstraintSettings *inSettings, const BodyID &inBodyID1, const BodyID &inBodyID2);
  71. /// Activate non-static bodies attached to a constraint
  72. void ActivateConstraint(const TwoBodyConstraint *inConstraint);
  73. ///@name Access to the shape of a body
  74. ///@{
  75. /// Get the current shape
  76. RefConst<Shape> GetShape(const BodyID &inBodyID) const;
  77. /// Set a new shape on the body
  78. /// @param inBodyID Body ID of body that had its shape changed
  79. /// @param inShape The new shape
  80. /// @param inUpdateMassProperties When true, the mass and inertia tensor is recalculated
  81. /// @param inActivationMode Weather or not to activate the body
  82. void SetShape(const BodyID &inBodyID, const Shape *inShape, bool inUpdateMassProperties, EActivation inActivationMode) const;
  83. /// Notify all systems to indicate that a shape has changed (usable for MutableCompoundShapes)
  84. /// @param inBodyID Body ID of body that had its shape changed
  85. /// @param inPreviousCenterOfMass Center of mass of the shape before the alterations
  86. /// @param inUpdateMassProperties When true, the mass and inertia tensor is recalculated
  87. /// @param inActivationMode Weather or not to activate the body
  88. void NotifyShapeChanged(const BodyID &inBodyID, Vec3Arg inPreviousCenterOfMass, bool inUpdateMassProperties, EActivation inActivationMode) const;
  89. ///@}
  90. ///@name Object layer of a body
  91. ///@{
  92. void SetObjectLayer(const BodyID &inBodyID, ObjectLayer inLayer);
  93. ObjectLayer GetObjectLayer(const BodyID &inBodyID) const;
  94. ///@}
  95. ///@name Position and rotation of a body
  96. ///@{
  97. void SetPositionAndRotation(const BodyID &inBodyID, Vec3Arg inPosition, QuatArg inRotation, EActivation inActivationMode);
  98. void SetPositionAndRotationWhenChanged(const BodyID &inBodyID, Vec3Arg inPosition, QuatArg inRotation, EActivation inActivationMode); ///< Will only update the position/rotation and activate the body when the difference is larger than a very small number. This avoids updating the broadphase/waking up a body when the resulting position/orientation doesn't really change.
  99. void GetPositionAndRotation(const BodyID &inBodyID, Vec3 &outPosition, Quat &outRotation) const;
  100. void SetPosition(const BodyID &inBodyID, Vec3Arg inPosition, EActivation inActivationMode);
  101. Vec3 GetPosition(const BodyID &inBodyID) const;
  102. Vec3 GetCenterOfMassPosition(const BodyID &inBodyID) const;
  103. void SetRotation(const BodyID &inBodyID, QuatArg inRotation, EActivation inActivationMode);
  104. Quat GetRotation(const BodyID &inBodyID) const;
  105. Mat44 GetWorldTransform(const BodyID &inBodyID) const;
  106. Mat44 GetCenterOfMassTransform(const BodyID &inBodyID) const;
  107. ///@}
  108. /// Set velocity of body such that it will be positioned at inTargetPosition/Rotation in inDeltaTime seconds (will activate body if needed)
  109. void MoveKinematic(const BodyID &inBodyID, Vec3Arg inTargetPosition, QuatArg inTargetRotation, float inDeltaTime);
  110. /// Linear or angular velocity (functions will activate body if needed).
  111. /// Note that the linear velocity is the velocity of the center of mass, which may not coincide with the position of your object, to correct for this: \f$VelocityCOM = Velocity - AngularVelocity \times ShapeCOM\f$
  112. void SetLinearAndAngularVelocity(const BodyID &inBodyID, Vec3Arg inLinearVelocity, Vec3Arg inAngularVelocity);
  113. void GetLinearAndAngularVelocity(const BodyID &inBodyID, Vec3 &outLinearVelocity, Vec3 &outAngularVelocity) const;
  114. void SetLinearVelocity(const BodyID &inBodyID, Vec3Arg inLinearVelocity);
  115. Vec3 GetLinearVelocity(const BodyID &inBodyID) const;
  116. void AddLinearVelocity(const BodyID &inBodyID, Vec3Arg inLinearVelocity); ///< Add velocity to current velocity
  117. void AddLinearAndAngularVelocity(const BodyID &inBodyID, Vec3Arg inLinearVelocity, Vec3Arg inAngularVelocity); ///< Add linear and angular to current velocities
  118. void SetAngularVelocity(const BodyID &inBodyID, Vec3Arg inAngularVelocity);
  119. Vec3 GetAngularVelocity(const BodyID &inBodyID) const;
  120. Vec3 GetPointVelocity(const BodyID &inBodyID, Vec3Arg inPoint) const; ///< Velocity of point inPoint (in world space, e.g. on the surface of the body) of the body
  121. /// Set the complete motion state of a body.
  122. /// Note that the linear velocity is the velocity of the center of mass, which may not coincide with the position of your object, to correct for this: \f$VelocityCOM = Velocity - AngularVelocity \times ShapeCOM\f$
  123. void SetPositionRotationAndVelocity(const BodyID &inBodyID, Vec3Arg inPosition, QuatArg inRotation, Vec3Arg inLinearVelocity, Vec3Arg inAngularVelocity);
  124. ///@name Add forces to the body
  125. ///@{
  126. void AddForce(const BodyID &inBodyID, Vec3Arg inForce); ///< See Body::AddForce
  127. void AddForce(const BodyID &inBodyID, Vec3Arg inForce, Vec3Arg inPoint); ///< Applied at inPoint
  128. void AddTorque(const BodyID &inBodyID, Vec3Arg inTorque); ///< See Body::AddTorque
  129. void AddForceAndTorque(const BodyID &inBodyID, Vec3Arg inForce, Vec3Arg inTorque); ///< A combination of Body::AddForce and Body::AddTorque
  130. ///@}
  131. ///@name Add an impulse to the body
  132. ///@{
  133. void AddImpulse(const BodyID &inBodyID, Vec3Arg inImpulse); ///< Applied at center of mass
  134. void AddImpulse(const BodyID &inBodyID, Vec3Arg inImpulse, Vec3Arg inPoint); ///< Applied at inPoint
  135. void AddAngularImpulse(const BodyID &inBodyID, Vec3Arg inAngularImpulse);
  136. ///@}
  137. ///@name Body motion type
  138. ///@{
  139. void SetMotionType(const BodyID &inBodyID, EMotionType inMotionType, EActivation inActivationMode);
  140. EMotionType GetMotionType(const BodyID &inBodyID) const;
  141. ///@}
  142. /// Get inverse inertia tensor in world space
  143. Mat44 GetInverseInertia(const BodyID &inBodyID) const;
  144. ///@name Restitution
  145. ///@{
  146. void SetRestitution(const BodyID &inBodyID, float inRestitution);
  147. float GetRestitution(const BodyID &inBodyID) const;
  148. ///@}
  149. ///@name Friction
  150. ///@{
  151. void SetFriction(const BodyID &inBodyID, float inFriction);
  152. float GetFriction(const BodyID &inBodyID) const;
  153. ///@}
  154. ///@name Gravity factor
  155. ///@{
  156. void SetGravityFactor(const BodyID &inBodyID, float inGravityFactor);
  157. float GetGravityFactor(const BodyID &inBodyID) const;
  158. ///@}
  159. /// Get transform and shape for this body, used to perform collision detection
  160. TransformedShape GetTransformedShape(const BodyID &inBodyID) const;
  161. /// Get the user data for a body
  162. uint64 GetUserData(const BodyID &inBodyID) const;
  163. /// Get the material for a particular sub shape
  164. const PhysicsMaterial * GetMaterial(const BodyID &inBodyID, const SubShapeID &inSubShapeID) const;
  165. /// Set the Body::EFlags::InvalidateContactCache flag for the specified body. This means that the collision cache is invalid for any body pair involving that body until the next physics step.
  166. void InvalidateContactCache(const BodyID &inBodyID);
  167. private:
  168. BodyLockInterface * mBodyLockInterface = nullptr;
  169. BodyManager * mBodyManager = nullptr;
  170. BroadPhase * mBroadPhase = nullptr;
  171. };
  172. JPH_NAMESPACE_END