BsJoint.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  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. #include "BsFJoint.h"
  7. namespace BansheeEngine
  8. {
  9. /** @addtogroup Physics
  10. * @{
  11. */
  12. /**
  13. * Base class for all Joint types. Joints constrain how two rigidbodies move relative to one another (for example a door
  14. * hinge). One of the bodies in the joint must always be movable (non-kinematic).
  15. */
  16. class BS_CORE_EXPORT Joint
  17. {
  18. public:
  19. virtual ~Joint() { }
  20. /** @copydoc FJoint::getBody */
  21. inline Rigidbody* getBody(JointBody body) const;
  22. /** @copydoc FJoint::setBody */
  23. inline void setBody(JointBody body, Rigidbody* value);
  24. /** @copydoc FJoint::getPosition */
  25. inline Vector3 getPosition(JointBody body) const;
  26. /** @copydoc FJoint::getRotation */
  27. inline Quaternion getRotation(JointBody body) const;
  28. /** @copydoc FJoint::setTransform */
  29. inline void setTransform(JointBody body, const Vector3& position, const Quaternion& rotation);
  30. /** @copydoc FJoint::getBreakForce */
  31. inline float getBreakForce() const;
  32. /** @copydoc FJoint::setBreakForce */
  33. inline void setBreakForce(float force);
  34. /** @copydoc FJoint::getBreakTorque */
  35. inline float getBreakTorque() const;
  36. /** @copydoc FJoint::setBreakTorque */
  37. inline void setBreakTorque(float torque);
  38. /** @copydoc FJoint::getEnableCollision */
  39. inline bool getEnableCollision() const;
  40. /** @copydoc FJoint::setEnableCollision */
  41. inline void setEnableCollision(bool value);
  42. /** Triggered when the joint's break force or torque is exceeded. */
  43. Event<void()> onJointBreak;
  44. /** @name Internal
  45. * @{
  46. */
  47. /**
  48. * Sets the object that owns this physics object, if any. Used for high level systems so they can easily map their
  49. * high level physics objects from the low level ones returned by various queries and events.
  50. */
  51. void _setOwner(PhysicsOwnerType type, void* owner) { mOwner.type = type; mOwner.ownerData = owner; }
  52. /**
  53. * Gets the object that owns this physics object, if any. Used for high level systems so they can easily map their
  54. * high level physics objects from the low level ones returned by various queries and events.
  55. */
  56. void* _getOwner(PhysicsOwnerType type) const { return mOwner.type == type ? mOwner.ownerData : nullptr; }
  57. /** @} */
  58. protected:
  59. PhysicsObjectOwner mOwner;
  60. FJoint* mInternal = nullptr;
  61. };
  62. /**
  63. * Controls spring parameters for a physics joint limits. If a limit is soft (body bounces back due to restition when
  64. * the limit is reached) the spring will pull the body back towards the limit using the specified parameters.
  65. */
  66. struct Spring
  67. {
  68. /** Constructs a spring with no force. */
  69. Spring() { }
  70. /**
  71. * Constructs a spring.
  72. *
  73. * @param stiffness Spring strength. Force proportional to the position error.
  74. * @param damping Damping strength. Force propertional to the velocity error.
  75. */
  76. Spring(float stiffness, float damping)
  77. :stiffness(stiffness), damping(damping)
  78. { }
  79. bool operator==(const Spring& other) const
  80. {
  81. return stiffness == other.stiffness && damping == other.damping;
  82. }
  83. /** Spring strength. Force proportional to the position error. */
  84. float stiffness = 0.0f;
  85. /** Damping strength. Force propertional to the velocity error. */
  86. float damping = 0.0f;
  87. };
  88. /** Contains common values used by all Joint limit types. */
  89. struct LimitCommon
  90. {
  91. LimitCommon(float contactDist = -1.0f)
  92. :contactDist(contactDist)
  93. { }
  94. LimitCommon(const Spring& spring, float restitution = 0.0f)
  95. :spring(spring), restitution(restitution)
  96. { }
  97. /**
  98. * Distance from the limit at which it becomes active. Allows the solver to activate earlier than the limit is
  99. * reached to avoid breaking the limit.
  100. */
  101. float contactDist = -1.0f;
  102. /**
  103. * Controls how do objects react when the limit is reached, values closer to zero specify non-ellastic collision,
  104. * while those closer to one specify more ellastic (i.e bouncy) collision. Must be in [0, 1] range.
  105. */
  106. float restitution = 0.0f;
  107. /** Spring that controls how are the bodies pulled back towards the limit when they breach it. */
  108. Spring spring;
  109. };
  110. /** Represents a joint limit between two distance values. Lower value must be less than the upper value. */
  111. struct LimitLinearRange : LimitCommon
  112. {
  113. /** Constructs an empty limit. */
  114. LimitLinearRange()
  115. { }
  116. /**
  117. * Constructs a hard limit. Once the limit is reached the movement of the attached bodies will come to a stop.
  118. *
  119. * @param lower Lower distance of the limit. Must be less than @p upper.
  120. * @param upper Upper distance of the limit. Must be more than @p lower.
  121. * @param contactDist Distance from the limit at which it becomes active. Allows the solver to activate earlier
  122. * than the limit is reached to avoid breaking the limit. Specify -1 for the default.
  123. */
  124. LimitLinearRange(float lower, float upper, float contactDist = -1.0f)
  125. :LimitCommon(contactDist), lower(lower), upper(upper)
  126. { }
  127. /**
  128. * Constructs a soft limit. Once the limit is reached the bodies will bounce back according to the resitution
  129. * parameter and will be pulled back towards the limit by the provided spring.
  130. *
  131. * @param lower Lower distance of the limit. Must be less than @p upper.
  132. * @param upper Upper distance of the limit. Must be more than @p lower.
  133. * @param spring Spring that controls how are the bodies pulled back towards the limit when they breach it.
  134. * @param resitution Controls how do objects react when the limit is reached, values closer to zero specify
  135. * non-ellastic collision, while those closer to one specify more ellastic (i.e bouncy)
  136. * collision. Must be in [0, 1] range.
  137. */
  138. LimitLinearRange(float lower, float upper, const Spring& spring, float restitution = 0.0f)
  139. :LimitCommon(spring, restitution), lower(lower), upper(upper)
  140. { }
  141. bool operator==(const LimitLinearRange& other) const
  142. {
  143. return lower == other.lower && upper == other.upper && contactDist == other.contactDist &&
  144. restitution == other.restitution && spring == other.spring;
  145. }
  146. /** Lower distance of the limit. Must be less than #upper. */
  147. float lower = 0.0f;
  148. /** Upper distance of the limit. Must be more than #lower. */
  149. float upper = 0.0f;
  150. };
  151. /** Represents a joint limit between zero a single distance value. */
  152. struct LimitLinear : LimitCommon
  153. {
  154. /** Constructs an empty limit. */
  155. LimitLinear()
  156. { }
  157. /**
  158. * Constructs a hard limit. Once the limit is reached the movement of the attached bodies will come to a stop.
  159. *
  160. * @param extent Distance at which the limit becomes active.
  161. * @param contactDist Distance from the limit at which it becomes active. Allows the solver to activate earlier
  162. * than the limit is reached to avoid breaking the limit. Specify -1 for the default.
  163. */
  164. LimitLinear(float extent, float contactDist = -1.0f)
  165. :LimitCommon(contactDist), extent(extent)
  166. { }
  167. /**
  168. * Constructs a soft limit. Once the limit is reached the bodies will bounce back according to the resitution
  169. * parameter and will be pulled back towards the limit by the provided spring.
  170. *
  171. * @param extent Distance at which the limit becomes active.
  172. * @param spring Spring that controls how are the bodies pulled back towards the limit when they breach it.
  173. * @param resitution Controls how do objects react when the limit is reached, values closer to zero specify
  174. * non-ellastic collision, while those closer to one specify more ellastic (i.e bouncy)
  175. * collision. Must be in [0, 1] range.
  176. */
  177. LimitLinear(float extent, const Spring& spring, float restitution = 0.0f)
  178. :LimitCommon(spring, restitution), extent(extent)
  179. { }
  180. bool operator==(const LimitLinear& other) const
  181. {
  182. return extent == other.extent && contactDist == other.contactDist && restitution == other.restitution &&
  183. spring == other.spring;
  184. }
  185. /** Distance at which the limit becomes active. */
  186. float extent = 0.0f;
  187. };
  188. /** Represents a joint limit between two angles. */
  189. struct LimitAngularRange : LimitCommon
  190. {
  191. /** Constructs an empty limit. */
  192. LimitAngularRange()
  193. { }
  194. /**
  195. * Constructs a hard limit. Once the limit is reached the movement of the attached bodies will come to a stop.
  196. *
  197. * @param lower Lower angle of the limit. Must be less than @p upper.
  198. * @param upper Upper angle of the limit. Must be more than @p lower.
  199. * @param contactDist Distance from the limit at which it becomes active. Allows the solver to activate earlier
  200. * than the limit is reached to avoid breaking the limit. Specify -1 for the default.
  201. */
  202. LimitAngularRange(Radian lower, Radian upper, float contactDist = -1.0f)
  203. :LimitCommon(contactDist), lower(lower), upper(upper)
  204. { }
  205. /**
  206. * Constructs a soft limit. Once the limit is reached the bodies will bounce back according to the resitution
  207. * parameter and will be pulled back towards the limit by the provided spring.
  208. *
  209. * @param lower Lower angle of the limit. Must be less than @p upper.
  210. * @param upper Upper angle of the limit. Must be more than @p lower.
  211. * @param spring Spring that controls how are the bodies pulled back towards the limit when they breach it.
  212. * @param resitution Controls how do objects react when the limit is reached, values closer to zero specify
  213. * non-ellastic collision, while those closer to one specify more ellastic (i.e bouncy)
  214. * collision. Must be in [0, 1] range.
  215. */
  216. LimitAngularRange(Radian lower, Radian upper, const Spring& spring, float restitution = 0.0f)
  217. :LimitCommon(spring, restitution), lower(lower), upper(upper)
  218. { }
  219. bool operator==(const LimitAngularRange& other) const
  220. {
  221. return lower == other.lower && upper == other.upper && contactDist == other.contactDist &&
  222. restitution == other.restitution && spring == other.spring;
  223. }
  224. /** Lower angle of the limit. Must be less than #upper. */
  225. Radian lower = Radian(0.0f);
  226. /** Upper angle of the limit. Must be less than #lower. */
  227. Radian upper = Radian(0.0f);
  228. };
  229. /** Represents a joint limit that contraints movement to within an elliptical cone. */
  230. struct LimitConeRange : LimitCommon
  231. {
  232. /** Constructs a limit with a 45 degree cone. */
  233. LimitConeRange()
  234. { }
  235. /**
  236. * Constructs a hard limit. Once the limit is reached the movement of the attached bodies will come to a stop.
  237. *
  238. * @param yLimitAngle Y angle of the cone. Movement is constrainted between 0 and this angle on the Y axis.
  239. * @param zLimitAngle Z angle of the cone. Movement is constrainted between 0 and this angle on the Z axis.
  240. * @param contactDist Distance from the limit at which it becomes active. Allows the solver to activate
  241. * earlier than the limit is reached to avoid breaking the limit. Specify -1 for the
  242. * default.
  243. */
  244. LimitConeRange(Radian yLimitAngle, Radian zLimitAngle, float contactDist = -1.0f)
  245. :LimitCommon(contactDist), yLimitAngle(yLimitAngle), zLimitAngle(zLimitAngle)
  246. { }
  247. /**
  248. * Constructs a soft limit. Once the limit is reached the bodies will bounce back according to the resitution
  249. * parameter and will be pulled back towards the limit by the provided spring.
  250. *
  251. * @param yLimitAngle Y angle of the cone. Movement is constrainted between 0 and this angle on the Y axis.
  252. * @param zLimitAngle Z angle of the cone. Movement is constrainted between 0 and this angle on the Z axis.
  253. * @param spring Spring that controls how are the bodies pulled back towards the limit when they breach it.
  254. * @param resitution Controls how do objects react when the limit is reached, values closer to zero specify
  255. * non-ellastic collision, while those closer to one specify more ellastic (i.e bouncy)
  256. * collision. Must be in [0, 1] range.
  257. */
  258. LimitConeRange(Radian yLimitAngle, Radian zLimitAngle, const Spring& spring, float restitution = 0.0f)
  259. :LimitCommon(spring, restitution), yLimitAngle(yLimitAngle), zLimitAngle(zLimitAngle)
  260. { }
  261. bool operator==(const LimitConeRange& other) const
  262. {
  263. return yLimitAngle == other.yLimitAngle && zLimitAngle == other.zLimitAngle &&
  264. contactDist == other.contactDist && restitution == other.restitution && spring == other.spring;
  265. }
  266. /** Y angle of the cone. Movement is constrainted between 0 and this angle on the Y axis. */
  267. Radian yLimitAngle = Radian(Math::PI * 0.5f);
  268. /** Z angle of the cone. Movement is constrainted between 0 and this angle on the Z axis. */
  269. Radian zLimitAngle = Radian(Math::PI * 0.5f);
  270. };
  271. /** @} */
  272. }