BsJoint.h 13 KB

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