BodyInterface.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  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/Physics/Body/BodyID.h>
  6. #include <Jolt/Physics/EActivation.h>
  7. #include <Jolt/Physics/Collision/ObjectLayer.h>
  8. #include <Jolt/Physics/Body/MotionType.h>
  9. #include <Jolt/Physics/Body/MotionQuality.h>
  10. #include <Jolt/Physics/Body/BodyType.h>
  11. #include <Jolt/Core/Reference.h>
  12. JPH_NAMESPACE_BEGIN
  13. class Body;
  14. class BodyCreationSettings;
  15. class SoftBodyCreationSettings;
  16. class BodyLockInterface;
  17. class BroadPhase;
  18. class BodyManager;
  19. class TransformedShape;
  20. class PhysicsMaterial;
  21. class SubShapeID;
  22. class Shape;
  23. class TwoBodyConstraintSettings;
  24. class TwoBodyConstraint;
  25. class BroadPhaseLayerFilter;
  26. class AABox;
  27. class CollisionGroup;
  28. /// 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.
  29. /// All quantities are in world space unless otherwise specified.
  30. class JPH_EXPORT BodyInterface : public NonCopyable
  31. {
  32. public:
  33. /// Initialize the interface (should only be called by PhysicsSystem)
  34. void Init(BodyLockInterface &inBodyLockInterface, BodyManager &inBodyManager, BroadPhase &inBroadPhase) { mBodyLockInterface = &inBodyLockInterface; mBodyManager = &inBodyManager; mBroadPhase = &inBroadPhase; }
  35. /// Create a rigid body
  36. /// @return Created body or null when out of bodies
  37. Body * CreateBody(const BodyCreationSettings &inSettings);
  38. /// Create a soft body
  39. /// @return Created body or null when out of bodies
  40. Body * CreateSoftBody(const SoftBodyCreationSettings &inSettings);
  41. /// Create a rigid 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.
  42. /// The ID created on the server can be replicated to the client and used to create a deterministic simulation.
  43. /// @return Created body or null when the body ID is invalid or a body of the same ID already exists.
  44. Body * CreateBodyWithID(const BodyID &inBodyID, const BodyCreationSettings &inSettings);
  45. /// Create a soft body with specified ID. See comments at CreateBodyWithID.
  46. Body * CreateSoftBodyWithID(const BodyID &inBodyID, const SoftBodyCreationSettings &inSettings);
  47. /// Advanced use only. Creates a rigid body without specifying an ID. This body cannot be added to the physics system until it has been assigned a body ID.
  48. /// This can be used to decouple allocation from registering the body. A call to CreateBodyWithoutID followed by AssignBodyID is equivalent to calling CreateBodyWithID.
  49. /// @return Created body
  50. Body * CreateBodyWithoutID(const BodyCreationSettings &inSettings) const;
  51. /// Advanced use only. Creates a body without specifying an ID. See comments at CreateBodyWithoutID.
  52. Body * CreateSoftBodyWithoutID(const SoftBodyCreationSettings &inSettings) const;
  53. /// Advanced use only. Destroy a body previously created with CreateBodyWithoutID that hasn't gotten an ID yet through the AssignBodyID function,
  54. /// or a body that has had its body ID unassigned through UnassignBodyIDs. Bodies that have an ID should be destroyed through DestroyBody.
  55. void DestroyBodyWithoutID(Body *inBody) const;
  56. /// Advanced use only. Assigns the next available body ID to a body that was created using CreateBodyWithoutID. After this call, the body can be added to the physics system.
  57. /// @return false if the body already has an ID or out of body ids.
  58. bool AssignBodyID(Body *ioBody);
  59. /// Advanced use only. Assigns a body ID to a body that was created using CreateBodyWithoutID. After this call, the body can be added to the physics system.
  60. /// @return false if the body already has an ID or if the ID is not valid.
  61. bool AssignBodyID(Body *ioBody, const BodyID &inBodyID);
  62. /// Advanced use only. See UnassignBodyIDs. Unassigns the ID of a single body.
  63. Body * UnassignBodyID(const BodyID &inBodyID);
  64. /// Advanced use only. Removes a number of body IDs from their bodies and returns the body pointers. Before calling this, the body should have been removed from the physics system.
  65. /// The body can be destroyed through DestroyBodyWithoutID. This can be used to decouple deallocation. A call to UnassignBodyIDs followed by calls to DestroyBodyWithoutID is equivalent to calling DestroyBodies.
  66. /// @param inBodyIDs A list of body IDs
  67. /// @param inNumber Number of bodies in the list
  68. /// @param outBodies If not null on input, this will contain a list of body pointers corresponding to inBodyIDs that can be destroyed afterwards (caller assumes ownership over these).
  69. void UnassignBodyIDs(const BodyID *inBodyIDs, int inNumber, Body **outBodies);
  70. /// Destroy a body.
  71. /// Make sure that you remove the body from the physics system using BodyInterface::RemoveBody before calling this function.
  72. void DestroyBody(const BodyID &inBodyID);
  73. /// Destroy multiple bodies
  74. /// Make sure that you remove the bodies from the physics system using BodyInterface::RemoveBody before calling this function.
  75. void DestroyBodies(const BodyID *inBodyIDs, int inNumber);
  76. /// Add body to the physics system.
  77. /// Note that if you need to add multiple bodies, use the AddBodiesPrepare/AddBodiesFinalize function.
  78. /// 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!
  79. /// After adding, to get a body by ID use the BodyLockRead or BodyLockWrite interface!
  80. void AddBody(const BodyID &inBodyID, EActivation inActivationMode);
  81. /// Remove body from the physics system. Note that you need to add a body to the physics system before you can remove it.
  82. void RemoveBody(const BodyID &inBodyID);
  83. /// Check if a body has been added to the physics system.
  84. bool IsAdded(const BodyID &inBodyID) const;
  85. /// Combines CreateBody and AddBody
  86. /// @return Created body ID or an invalid ID when out of bodies
  87. BodyID CreateAndAddBody(const BodyCreationSettings &inSettings, EActivation inActivationMode);
  88. /// Combines CreateSoftBody and AddBody
  89. /// @return Created body ID or an invalid ID when out of bodies
  90. BodyID CreateAndAddSoftBody(const SoftBodyCreationSettings &inSettings, EActivation inActivationMode);
  91. /// Add state handle, used to keep track of a batch of bodies while adding them to the PhysicsSystem.
  92. using AddState = void *;
  93. ///@name Batch adding interface
  94. ///@{
  95. /// Prepare adding inNumber bodies at ioBodies to the PhysicsSystem, returns a handle that should be used in AddBodiesFinalize/Abort.
  96. /// This can be done on a background thread without influencing the PhysicsSystem.
  97. /// ioBodies may be shuffled around by this function and should be kept that way until AddBodiesFinalize/Abort is called.
  98. AddState AddBodiesPrepare(BodyID *ioBodies, int inNumber);
  99. /// Finalize adding bodies to the PhysicsSystem, supply the return value of AddBodiesPrepare in inAddState.
  100. /// Please ensure that the ioBodies array passed to AddBodiesPrepare is unmodified and passed again to this function.
  101. void AddBodiesFinalize(BodyID *ioBodies, int inNumber, AddState inAddState, EActivation inActivationMode);
  102. /// Abort adding bodies to the PhysicsSystem, supply the return value of AddBodiesPrepare in inAddState.
  103. /// This can be done on a background thread without influencing the PhysicsSystem.
  104. /// Please ensure that the ioBodies array passed to AddBodiesPrepare is unmodified and passed again to this function.
  105. void AddBodiesAbort(BodyID *ioBodies, int inNumber, AddState inAddState);
  106. /// Remove inNumber bodies in ioBodies from the PhysicsSystem. Note that bodies need to be added to the physics system before they can be removed.
  107. /// ioBodies may be shuffled around by this function.
  108. void RemoveBodies(BodyID *ioBodies, int inNumber);
  109. ///@}
  110. ///@name Activate / deactivate a body. Note that you need to add a body to the physics system before you can activate it.
  111. ///@{
  112. void ActivateBody(const BodyID &inBodyID);
  113. void ActivateBodies(const BodyID *inBodyIDs, int inNumber);
  114. void ActivateBodiesInAABox(const AABox &inBox, const BroadPhaseLayerFilter &inBroadPhaseLayerFilter, const ObjectLayerFilter &inObjectLayerFilter);
  115. void DeactivateBody(const BodyID &inBodyID);
  116. void DeactivateBodies(const BodyID *inBodyIDs, int inNumber);
  117. bool IsActive(const BodyID &inBodyID) const; ///< Checks if a body is currently actively simulating
  118. void ResetSleepTimer(const BodyID &inBodyID); ///< @see Body::ResetSleepTimer
  119. ///@}
  120. /// Create a two body constraint
  121. TwoBodyConstraint * CreateConstraint(const TwoBodyConstraintSettings *inSettings, const BodyID &inBodyID1, const BodyID &inBodyID2);
  122. /// Activate non-static bodies attached to a constraint.
  123. /// Note that the bodies involved in the constraint should be added to the physics system before activating a constraint.
  124. void ActivateConstraint(const TwoBodyConstraint *inConstraint);
  125. ///@name Access to the shape of a body
  126. ///@{
  127. /// Get the current shape
  128. RefConst<Shape> GetShape(const BodyID &inBodyID) const;
  129. /// Set a new shape on the body
  130. /// @param inBodyID Body ID of body that had its shape changed
  131. /// @param inShape The new shape
  132. /// @param inUpdateMassProperties When true, the mass and inertia tensor is recalculated
  133. /// @param inActivationMode Whether or not to activate the body
  134. void SetShape(const BodyID &inBodyID, const Shape *inShape, bool inUpdateMassProperties, EActivation inActivationMode) const;
  135. /// Notify all systems to indicate that a shape has changed (usable for MutableCompoundShapes)
  136. /// @param inBodyID Body ID of body that had its shape changed
  137. /// @param inPreviousCenterOfMass Center of mass of the shape before the alterations
  138. /// @param inUpdateMassProperties When true, the mass and inertia tensor is recalculated
  139. /// @param inActivationMode Whether or not to activate the body
  140. void NotifyShapeChanged(const BodyID &inBodyID, Vec3Arg inPreviousCenterOfMass, bool inUpdateMassProperties, EActivation inActivationMode) const;
  141. ///@}
  142. ///@name Object layer of a body
  143. ///@{
  144. void SetObjectLayer(const BodyID &inBodyID, ObjectLayer inLayer); ///< The collision layer this body belongs to (determines if two objects can collide)
  145. ObjectLayer GetObjectLayer(const BodyID &inBodyID) const; ///< @see Body::GetObjectLayer
  146. ///@}
  147. ///@name Position and rotation of a body
  148. ///@{
  149. void SetPositionAndRotation(const BodyID &inBodyID, RVec3Arg inPosition, QuatArg inRotation, EActivation inActivationMode);
  150. void SetPositionAndRotationWhenChanged(const BodyID &inBodyID, RVec3Arg 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.
  151. void GetPositionAndRotation(const BodyID &inBodyID, RVec3 &outPosition, Quat &outRotation) const;
  152. void SetPosition(const BodyID &inBodyID, RVec3Arg inPosition, EActivation inActivationMode);
  153. RVec3 GetPosition(const BodyID &inBodyID) const;
  154. RVec3 GetCenterOfMassPosition(const BodyID &inBodyID) const; ///< @see Body::GetCenterOfMassPosition
  155. void SetRotation(const BodyID &inBodyID, QuatArg inRotation, EActivation inActivationMode);
  156. Quat GetRotation(const BodyID &inBodyID) const;
  157. RMat44 GetWorldTransform(const BodyID &inBodyID) const; ///< @see Body::GetWorldTransform
  158. RMat44 GetCenterOfMassTransform(const BodyID &inBodyID) const; ///< @see Body::GetCenterOfMassTransform
  159. ///@}
  160. /// Set velocity of body such that it will be positioned at inTargetPosition/Rotation in inDeltaTime seconds (will activate body if needed)
  161. void MoveKinematic(const BodyID &inBodyID, RVec3Arg inTargetPosition, QuatArg inTargetRotation, float inDeltaTime);
  162. /// Linear or angular velocity (functions will activate body if needed).
  163. /// 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$
  164. void SetLinearAndAngularVelocity(const BodyID &inBodyID, Vec3Arg inLinearVelocity, Vec3Arg inAngularVelocity);
  165. void GetLinearAndAngularVelocity(const BodyID &inBodyID, Vec3 &outLinearVelocity, Vec3 &outAngularVelocity) const;
  166. void SetLinearVelocity(const BodyID &inBodyID, Vec3Arg inLinearVelocity); ///< @see Body::SetLinearVelocity
  167. Vec3 GetLinearVelocity(const BodyID &inBodyID) const; ///< @see Body::GetLinearVelocity
  168. void AddLinearVelocity(const BodyID &inBodyID, Vec3Arg inLinearVelocity); ///< Add velocity to current velocity
  169. void AddLinearAndAngularVelocity(const BodyID &inBodyID, Vec3Arg inLinearVelocity, Vec3Arg inAngularVelocity); ///< Add linear and angular to current velocities
  170. void SetAngularVelocity(const BodyID &inBodyID, Vec3Arg inAngularVelocity); ///< @see Body::SetAngularVelocity
  171. Vec3 GetAngularVelocity(const BodyID &inBodyID) const; ///< @see Body::GetAngularVelocity
  172. Vec3 GetPointVelocity(const BodyID &inBodyID, RVec3Arg inPoint) const; ///< Velocity of point inPoint (in world space, e.g. on the surface of the body) of the body. @see Body::GetPointVelocity
  173. /// Set the complete motion state of a body.
  174. /// 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$
  175. void SetPositionRotationAndVelocity(const BodyID &inBodyID, RVec3Arg inPosition, QuatArg inRotation, Vec3Arg inLinearVelocity, Vec3Arg inAngularVelocity);
  176. ///@name Add forces to the body. Note that you should add a body to the physics system before applying forces or torques.
  177. ///@{
  178. void AddForce(const BodyID &inBodyID, Vec3Arg inForce, EActivation inActivationMode = EActivation::Activate); ///< @see Body::AddForce
  179. void AddForce(const BodyID &inBodyID, Vec3Arg inForce, RVec3Arg inPoint, EActivation inActivationMode = EActivation::Activate); ///< Applied at world space position inPoint. @see Body::AddForce
  180. void AddTorque(const BodyID &inBodyID, Vec3Arg inTorque, EActivation inActivationMode = EActivation::Activate); ///< @see Body::AddTorque
  181. void AddForceAndTorque(const BodyID &inBodyID, Vec3Arg inForce, Vec3Arg inTorque, EActivation inActivationMode = EActivation::Activate); ///< A combination of Body::AddForce and Body::AddTorque
  182. ///@}
  183. ///@name Add an impulse to the body. Note that you should add a body to the physics system before applying impulses.
  184. ///@{
  185. void AddImpulse(const BodyID &inBodyID, Vec3Arg inImpulse); ///< Applied at center of mass. @see Body::AddImpulse
  186. void AddImpulse(const BodyID &inBodyID, Vec3Arg inImpulse, RVec3Arg inPoint); ///< Applied at world space position inPoint. @see Body::AddImpulse
  187. void AddAngularImpulse(const BodyID &inBodyID, Vec3Arg inAngularImpulse); ///< @see Body::AddAngularImpulse
  188. bool ApplyBuoyancyImpulse(const BodyID &inBodyID, RVec3Arg inSurfacePosition, Vec3Arg inSurfaceNormal, float inBuoyancy, float inLinearDrag, float inAngularDrag, Vec3Arg inFluidVelocity, Vec3Arg inGravity, float inDeltaTime); ///< @see Body::ApplyBuoyancyImpulse
  189. ///@}
  190. ///@name Body type
  191. ///@{
  192. EBodyType GetBodyType(const BodyID &inBodyID) const; ///< @see Body::GetBodyType
  193. ///@}
  194. ///@name Body motion type
  195. ///@{
  196. void SetMotionType(const BodyID &inBodyID, EMotionType inMotionType, EActivation inActivationMode); ///< @see Body::SetMotionType
  197. EMotionType GetMotionType(const BodyID &inBodyID) const; ///< @see Body::GetMotionType
  198. ///@}
  199. ///@name Body motion quality
  200. ///@{
  201. void SetMotionQuality(const BodyID &inBodyID, EMotionQuality inMotionQuality); ///< How well it detects collisions when it has a high velocity
  202. EMotionQuality GetMotionQuality(const BodyID &inBodyID) const; ///< @see MotionProperties::GetMotionQuality
  203. ///@}
  204. /// Get inverse inertia tensor in world space
  205. Mat44 GetInverseInertia(const BodyID &inBodyID) const; ///< @see Body::GetInverseInertia
  206. ///@name Restitution
  207. ///@{
  208. void SetRestitution(const BodyID &inBodyID, float inRestitution); ///< @see Body::SetRestitution
  209. float GetRestitution(const BodyID &inBodyID) const; ///< @see Body::GetRestitution
  210. ///@}
  211. ///@name Friction
  212. ///@{
  213. void SetFriction(const BodyID &inBodyID, float inFriction); ///< @see Body::SetFriction
  214. float GetFriction(const BodyID &inBodyID) const; ///< @see Body::GetFriction
  215. ///@}
  216. ///@name Gravity factor
  217. ///@{
  218. void SetGravityFactor(const BodyID &inBodyID, float inGravityFactor); ///< @see MotionProperties::SetGravityFactor
  219. float GetGravityFactor(const BodyID &inBodyID) const; ///< @see MotionProperties::GetGravityFactor
  220. ///@}
  221. ///@name Max linear velocity
  222. ///@{
  223. void SetMaxLinearVelocity(const BodyID &inBodyID, float inLinearVelocity); ///< @see MotionProperties::SetMaxLinearVelocity
  224. float GetMaxLinearVelocity(const BodyID &inBodyID) const; ///< @see MotionProperties::GetMaxLinearVelocity
  225. ///@}
  226. ///@name Max angular velocity
  227. ///@{
  228. void SetMaxAngularVelocity(const BodyID &inBodyID, float inAngularVelocity); ///< @see MotionProperties::SetMaxAngularVelocity
  229. float GetMaxAngularVelocity(const BodyID &inBodyID) const; ///< @see MotionProperties::GetMaxAngularVelocity
  230. ///@}
  231. ///@name Manifold reduction
  232. ///@{
  233. void SetUseManifoldReduction(const BodyID &inBodyID, bool inUseReduction); ///< @see Body::SetUseManifoldReduction
  234. bool GetUseManifoldReduction(const BodyID &inBodyID) const; ///< @see Body::GetUseManifoldReduction
  235. ///@}
  236. ///@name Sensor
  237. ///@{
  238. void SetIsSensor(const BodyID &inBodyID, bool inIsSensor); ///< @see Body::SetIsSensor
  239. bool IsSensor(const BodyID &inBodyID) const; ///< @see Body::IsSensor
  240. ///@}
  241. ///@name Collision group
  242. ///@{
  243. void SetCollisionGroup(const BodyID &inBodyID, const CollisionGroup &inCollisionGroup); ///< @see Body::SetCollisionGroup
  244. const CollisionGroup & GetCollisionGroup(const BodyID &inBodyID) const; ///< @see Body::GetCollisionGroup
  245. ///@}
  246. /// Get transform and shape for this body, used to perform collision detection
  247. TransformedShape GetTransformedShape(const BodyID &inBodyID) const;
  248. /// Get the user data for a body
  249. uint64 GetUserData(const BodyID &inBodyID) const;
  250. void SetUserData(const BodyID &inBodyID, uint64 inUserData) const;
  251. /// Get the material for a particular sub shape
  252. const PhysicsMaterial * GetMaterial(const BodyID &inBodyID, const SubShapeID &inSubShapeID) const;
  253. /// 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.
  254. void InvalidateContactCache(const BodyID &inBodyID);
  255. private:
  256. /// Helper function to activate a single body
  257. JPH_INLINE void ActivateBodyInternal(Body &ioBody) const;
  258. BodyLockInterface * mBodyLockInterface = nullptr;
  259. BodyManager * mBodyManager = nullptr;
  260. BroadPhase * mBroadPhase = nullptr;
  261. };
  262. JPH_NAMESPACE_END