BsJoint.h 13 KB

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