BsRigidbody.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsCorePrerequisites.h"
  5. #include "BsPhysicsCommon.h"
  6. namespace BansheeEngine
  7. {
  8. /** @addtogroup Physics
  9. * @{
  10. */
  11. /** Type of force or torque that can be applied to a rigidbody. */
  12. enum class ForceMode
  13. {
  14. Force, /**< Value applied is a force. */
  15. Impulse, /**< Value applied is an impulse (a direct change in its linear or angular momentum). */
  16. Velocity, /**< Value applied is velocity. */
  17. Acceleration /**< Value applied is accelearation. */
  18. };
  19. /** Type of force that can be applied to a rigidbody at an arbitrary point. */
  20. enum class PointForceMode
  21. {
  22. Force, /**< Value applied is a force. */
  23. Impulse, /**< Value applied is an impulse (a direct change in its linear or angular momentum). */
  24. };
  25. /**
  26. * Rigidbody is a dynamic physics object that can be moved using forces (or directly). It will interact with other
  27. * static and dynamic physics objects in the scene accordingly (it will push other non-kinematic rigidbodies,
  28. * and collide with static objects).
  29. *
  30. * The shape and mass of a rigidbody is governed by its colliders. You must attach at least one collider for the
  31. * rigidbody to be valid.
  32. */
  33. class BS_CORE_EXPORT Rigidbody
  34. {
  35. public:
  36. /** Flags that control options of a Rigidbody object. */
  37. enum class Flag
  38. {
  39. /** No options. */
  40. None = 0x00,
  41. /** Automatically calculate center of mass transform and inertia tensors from child shapes (colliders). */
  42. AutoTensors = 0x01,
  43. /** Calculate mass distribution from child shapes (colliders). Only relevant when auto-tensors is on. */
  44. AutoMass = 0x02,
  45. /**
  46. * Enables continous collision detection. This can prevent fast moving bodies from tunneling through each other.
  47. * This must also be enabled globally in Physics otherwise the flag will be ignored.
  48. */
  49. CCD = 0x04
  50. };
  51. /**
  52. * Constructs a new rigidbody.
  53. *
  54. * @param[in] linkedSO Scene object that owns this rigidbody. All physics updates applied to this object
  55. * will be transfered to this scene object (the movement/rotation resulting from
  56. * those updates).
  57. */
  58. Rigidbody(const HSceneObject& linkedSO);
  59. virtual ~Rigidbody();
  60. /**
  61. * Moves the rigidbody to a specific position. This method will ensure physically correct movement, meaning the body
  62. * will collide with other objects along the way.
  63. */
  64. virtual void move(const Vector3& position) = 0;
  65. /**
  66. * Rotates the rigidbody. This method will ensure physically correct rotation, meaning the body will collide with
  67. * other objects along the way.
  68. */
  69. virtual void rotate(const Quaternion& rotation) = 0;
  70. /** Returns the current position of the rigidbody. */
  71. virtual Vector3 getPosition() const = 0;
  72. /** Returns the current rotation of the rigidbody. */
  73. virtual Quaternion getRotation() const = 0;
  74. /**
  75. * Moves and rotates the rigidbody to a specific position. Unlike move() and rotate() this will not transform the
  76. * body in a physically correct manner, but will instead "teleport" it immediately to the specified position and
  77. * rotation.
  78. */
  79. virtual void setTransform(const Vector3& pos, const Quaternion& rot) = 0;
  80. /**
  81. * Sets the mass of the object and all of its collider shapes. Only relevant if Flag::AutoMass or Flag::AutoTensors
  82. * is turned off. Value of zero means the object is immovable (but can be rotated).
  83. */
  84. virtual void setMass(float mass) = 0;
  85. /**
  86. * Returns the mass of the object. This may be mass manually set by setMass(), or the mass of all child colliders,
  87. * depending if the mass is calculated automatically or not.
  88. */
  89. virtual float getMass() const = 0;
  90. /**
  91. * Sets if the body is kinematic. Kinematic body will not move in response to external forces (for example gravity,
  92. * or another object pushing it), essentially behaving like collider. Unlike a collider though, you can still move
  93. * the object and have other dynamic objects respond correctly (meaning it will push other objects).
  94. */
  95. virtual void setIsKinematic(bool kinematic) = 0;
  96. /** Checks if the body is kinematic. */
  97. virtual bool getIsKinematic() const = 0;
  98. /**
  99. * Checks if the body is sleeping. Objects that aren't moved/rotated for a while are put to sleep to reduce load
  100. * on the physics system.
  101. */
  102. virtual bool isSleeping() const = 0;
  103. /** Forces the object to sleep. Useful if you know the object will not move in any significant way for a while. */
  104. virtual void sleep() = 0;
  105. /**
  106. * Wakes an object up. Useful if you modified properties of this object, and potentially surrounding objects which
  107. * might result in the object being moved by physics (although the physics system will automatically wake the
  108. * object up for majority of such cases).
  109. */
  110. virtual void wakeUp() = 0;
  111. /** Sets a threshold of force and torque under which the object will be considered to be put to sleep. */
  112. virtual void setSleepThreshold(float threshold) = 0;
  113. /** Gets a threshold of force and torque under which the object will be considered to be put to sleep. */
  114. virtual float getSleepThreshold() const = 0;
  115. /** Sets whether or not the rigidbody will have the global gravity force applied to it. */
  116. virtual void setUseGravity(bool gravity) = 0;
  117. /** Gets whether or not the rigidbody will have the global gravity force applied to it. */
  118. virtual bool getUseGravity() const = 0;
  119. /** Sets the linear velocity of the body. */
  120. virtual void setVelocity(const Vector3& velocity) = 0;
  121. /** Returns the current linear velocity of the body. */
  122. virtual Vector3 getVelocity() const = 0;
  123. /** Sets the angular velocity of the body. */
  124. virtual void setAngularVelocity(const Vector3& velocity) = 0;
  125. /** Returns the current angular velocity of the body. */
  126. virtual Vector3 getAngularVelocity() const = 0;
  127. /** Sets the linear drag of the body. Higher drag values means the object resists linear movement more. */
  128. virtual void setDrag(float drag) = 0;
  129. /** Gets the linear drag of the body. Higher drag values means the object resists linear movement more. */
  130. virtual float getDrag() const = 0;
  131. /** Sets the angular drag of the body. Higher drag values means the object resists angular movement more. */
  132. virtual void setAngularDrag(float drag) = 0;
  133. /** Gets the angular drag of the body. Higher drag values means the object resists angular movement more. */
  134. virtual float getAngularDrag() const = 0;
  135. /**
  136. * Sets the inertia tensor in local mass space. Inertia tensor determines how difficult is to rotate the object.
  137. * Values of zero in the inertia tensor mean the object will be unable to rotate around a specific axis. Only
  138. * relevant if Flag::AutoTensors is turned off.
  139. */
  140. virtual void setInertiaTensor(const Vector3& tensor) = 0;
  141. /** Gets the inertia tensor in local mass space. */
  142. virtual Vector3 getInertiaTensor() const = 0;
  143. /** Returns the maximum angular velocity of the rigidbody. Velocity will be clamped to this value. */
  144. virtual void setMaxAngularVelocity(float maxVelocity) = 0;
  145. /** Gets the maximum angular velocity of the rigidbody. */
  146. virtual float getMaxAngularVelocity() const = 0;
  147. /**
  148. * Sets the rigidbody's center of mass transform. Only relevant if Flag::AutoTensors is turned off.
  149. *
  150. * @param[in] position Position of the center of mass.
  151. * @param[in] rotation Rotation that determines orientation of the inertia tensor (rotation of the center of
  152. * mass frame).
  153. */
  154. virtual void setCenterOfMass(const Vector3& position, const Quaternion& rotation) = 0;
  155. /** Returns the position of the center of mass. */
  156. virtual Vector3 getCenterOfMassPosition() const = 0;
  157. /** Returns the rotation of the inertia tensor. */
  158. virtual Quaternion getCenterOfMassRotation() const = 0;
  159. /**
  160. * Sets the number of iterations to use when solving for position. Higher values can improve precision and
  161. * numerical stability of the simulation.
  162. */
  163. virtual void setPositionSolverCount(UINT32 count) = 0;
  164. /** Gets the number of iterations to use when solving for position. */
  165. virtual UINT32 getPositionSolverCount() const = 0;
  166. /**
  167. * Sets the number of iterations to use when solving for velocity. Higher values can improve precision and
  168. * numerical stability of the simulation.
  169. */
  170. virtual void setVelocitySolverCount(UINT32 count) = 0;
  171. /** Gets the number of iterations to use when solving for velocity. */
  172. virtual UINT32 getVelocitySolverCount() const = 0;
  173. /** Sets flags that control the behaviour of the rigidbody. */
  174. virtual void setFlags(Flag flags) { mFlags = flags; }
  175. /** Gets flags that control the behaviour of the rigidbody. */
  176. virtual Flag getFlags() const { return mFlags; }
  177. /**
  178. * Applies a force to the center of the mass of the rigidbody. This will produce linear momentum.
  179. *
  180. * @param[in] force Force to apply.
  181. * @param[in] mode Determines what is the type of @p force.
  182. */
  183. virtual void addForce(const Vector3& force, ForceMode mode = ForceMode::Force) = 0;
  184. /**
  185. * Applies a torque to the rigidbody. This will produce angular momentum.
  186. *
  187. * @param[in] torque Torque to apply.
  188. * @param[in] mode Determines what is the type of @p torque.
  189. */
  190. virtual void addTorque(const Vector3& torque, ForceMode mode = ForceMode::Force) = 0;
  191. /**
  192. * Applies a force to a specific point on the rigidbody. This will in most cases produce both linear and angular
  193. * momentum.
  194. *
  195. * @param[in] force Force to apply.
  196. * @param[in] position World position to apply the force at.
  197. * @param[in] mode Determines what is the type of @p force.
  198. */
  199. virtual void addForceAtPoint(const Vector3& force, const Vector3& position,
  200. PointForceMode mode = PointForceMode::Force) = 0;
  201. /**
  202. * Returns the total (linear + angular) velocity at a specific point.
  203. *
  204. * @param[in] point Point in world space.
  205. * @return Total velocity of the point.
  206. */
  207. virtual Vector3 getVelocityAtPoint(const Vector3& point) const = 0;
  208. /** Registers a new collider as a child of this rigidbody. */
  209. virtual void addCollider(FCollider* collider) = 0;
  210. /** Removes a collider from the child list of this rigidbody. */
  211. virtual void removeCollider(FCollider* collider) = 0;
  212. /** Removes all colliders from the child list of this rigidbody. */
  213. virtual void removeColliders() = 0;
  214. /**
  215. * Recalculates rigidbody's mass, inertia tensors and center of mass depending on the currently set child colliders.
  216. * This should be called whenever relevant child collider properties change (like mass or shape).
  217. *
  218. * If automatic tensor calculation is turned off then this will do nothing. If automatic mass calculation is turned
  219. * off then this will use the mass set directly on the body using setMass().
  220. */
  221. virtual void updateMassDistribution() { }
  222. /**
  223. * Creates a new rigidbody.
  224. *
  225. * @param[in] linkedSO Scene object that owns this rigidbody. All physics updates applied to this object
  226. * will be transfered to this scene object (the movement/rotation resulting from
  227. * those updates).
  228. */
  229. static SPtr<Rigidbody> create(const HSceneObject& linkedSO);
  230. /** Triggered when one of the colliders owned by the rigidbody starts colliding with another object. */
  231. Event<void(const CollisionData&)> onCollisionBegin;
  232. /** Triggered when a previously colliding collider stays in collision. Triggered once per frame. */
  233. Event<void(const CollisionData&)> onCollisionStay;
  234. /** Triggered when one of the colliders owned by the rigidbody stops colliding with another object. */
  235. Event<void(const CollisionData&)> onCollisionEnd;
  236. /** @name Internal
  237. * @{
  238. */
  239. /**
  240. * Sets the priority of the physics update. Bodies with a higher priority will be updated before the bodies with
  241. * lower priority. This allows you to control the order of updated in case rigidbodies are in some way dependant.
  242. */
  243. void _setPriority(UINT32 priority);
  244. /** Sets a unique ID of the rigidbody, so it can be recognized by the physics system. */
  245. void _setPhysicsId(UINT32 id) { mPhysicsId = id; }
  246. /**
  247. * Applies new transform values retrieved from the most recent physics update (values resulting from physics
  248. * simulation).
  249. */
  250. void _setTransform(const Vector3& position, const Quaternion& rotation);
  251. /**
  252. * Sets the object that owns this physics object, if any. Used for high level systems so they can easily map their
  253. * high level physics objects from the low level ones returned by various queries and events.
  254. */
  255. void _setOwner(PhysicsOwnerType type, void* owner) { mOwner.type = type; mOwner.ownerData = owner; }
  256. /**
  257. * Gets the object that owns this physics object, if any. Used for high level systems so they can easily map their
  258. * high level physics objects from the low level ones returned by various queries and events.
  259. */
  260. void* _getOwner(PhysicsOwnerType type) const { return mOwner.type == type ? mOwner.ownerData : nullptr; }
  261. /** @} */
  262. protected:
  263. friend class FCollider;
  264. Flag mFlags = Flag::None;
  265. PhysicsObjectOwner mOwner;
  266. UINT32 mPhysicsId = 0;
  267. HSceneObject mLinkedSO;
  268. };
  269. /** @} */
  270. }