BsJoint.h 13 KB

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