2
0

BsJoint.h 13 KB

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