BsJoint.h 12 KB

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