RigidBody.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. // David Eberly, Geometric Tools, Redmond WA 98052
  2. // Copyright (c) 1998-2020
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // https://www.boost.org/LICENSE_1_0.txt
  5. // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
  6. // Version: 4.0.2019.08.13
  7. #pragma once
  8. #include <Mathematics/Matrix3x3.h>
  9. #include <Mathematics/Rotation.h>
  10. #include <functional>
  11. namespace WwiseGTE
  12. {
  13. template <typename Real>
  14. class RigidBody
  15. {
  16. public:
  17. // Construction and destruction. The rigid body state is
  18. // uninitialized. Use the set functions to initialize the state
  19. // before starting the simulation.
  20. virtual ~RigidBody() = default;
  21. RigidBody()
  22. :
  23. mMass(std::numeric_limits<Real>::max()),
  24. mInvMass((Real)0),
  25. mInertia(Matrix3x3<Real>::Identity()),
  26. mInvInertia(Matrix3x3<Real>::Zero()),
  27. mPosition(Vector3<Real>::Zero()),
  28. mQuatOrient(Quaternion<Real>::Identity()),
  29. mLinearMomentum(Vector3<Real>::Zero()),
  30. mAngularMomentum(Vector3<Real>::Zero()),
  31. mRotOrient(Matrix3x3<Real>::Identity()),
  32. mLinearVelocity(Vector3<Real>::Zero()),
  33. mAngularVelocity(Vector3<Real>::Zero())
  34. {
  35. // The default body is immovable.
  36. }
  37. // Set rigid body state.
  38. void SetMass(float mass)
  39. {
  40. if ((Real)0 < mass && mass < std::numeric_limits<Real>::max())
  41. {
  42. mMass = mass;
  43. mInvMass = (Real)1 / mass;
  44. }
  45. else
  46. {
  47. // Assume the body as immovable.
  48. mMass = std::numeric_limits<Real>::max();
  49. mInvMass = (Real)0;
  50. mInertia = Matrix3x3<Real>::Identity();
  51. mInvInertia = Matrix3x3<Real>::Zero();
  52. mQuatOrient = Quaternion<Real>::Identity();
  53. mLinearMomentum = Vector3<Real>::Zero();
  54. mAngularMomentum = Vector3<Real>::Zero();
  55. mRotOrient = Matrix3x3<Real>::Identity();
  56. mLinearVelocity = Vector3<Real>::Zero();
  57. mAngularVelocity = Vector3<Real>::Zero();
  58. }
  59. }
  60. void SetBodyInertia(Matrix3x3<Real> const& inertia)
  61. {
  62. mInertia = inertia;
  63. mInvInertia = Inverse(mInertia);
  64. }
  65. inline void SetPosition(Vector3<Real> const& position)
  66. {
  67. mPosition = position;
  68. }
  69. void SetQOrientation(Quaternion<Real> const& quatOrient)
  70. {
  71. mQuatOrient = quatOrient;
  72. mRotOrient = Rotation<3, Real>(mQuatOrient);
  73. }
  74. void SetLinearMomentum(Vector3<Real> const& linearMomentum)
  75. {
  76. mLinearMomentum = linearMomentum;
  77. mLinearVelocity = mInvMass * mLinearMomentum;
  78. }
  79. void SetAngularMomentum(Vector3<Real> const& angularMomentum)
  80. {
  81. mAngularMomentum = angularMomentum;
  82. // V = R^T*M
  83. mAngularVelocity = mAngularMomentum * mRotOrient;
  84. // V = J^{-1}*R^T*M
  85. mAngularVelocity = mInvInertia * mAngularVelocity;
  86. // V = R*J^{-1}*R^T*M
  87. mAngularVelocity = mRotOrient * mAngularVelocity;
  88. }
  89. void SetROrientation(Matrix3x3<Real> const& rotOrient)
  90. {
  91. mRotOrient = rotOrient;
  92. mQuatOrient = Rotation<3, Real>(mRotOrient);
  93. }
  94. void SetLinearVelocity(Vector3<Real> const& linearVelocity)
  95. {
  96. mLinearVelocity = linearVelocity;
  97. mLinearMomentum = mMass * mLinearVelocity;
  98. }
  99. void SetAngularVelocity(Vector3<Real> const& angularVelocity)
  100. {
  101. mAngularVelocity = angularVelocity;
  102. // M = R^T*V
  103. mAngularMomentum = mAngularVelocity * mRotOrient;
  104. // M = J*R^T*V
  105. mAngularMomentum = mInertia * mAngularMomentum;
  106. // M = R*J*R^T*V
  107. mAngularMomentum = mRotOrient * mAngularMomentum;
  108. }
  109. // Get rigid body state.
  110. inline Real GetMass() const
  111. {
  112. return mMass;
  113. }
  114. inline Real GetInverseMass() const
  115. {
  116. return mInvMass;
  117. }
  118. inline Matrix3x3<Real> const& GetBodyInertia() const
  119. {
  120. return mInertia;
  121. }
  122. inline Matrix3x3<Real> const& GetBodyInverseInertia() const
  123. {
  124. return mInvInertia;
  125. }
  126. Matrix3x3<Real> GetWorldInertia() const
  127. {
  128. return MultiplyABT(mRotOrient * mInertia, mRotOrient); // R*J*R^T
  129. }
  130. Matrix3x3<Real> GetWorldInverseInertia() const
  131. {
  132. // R*J^{-1}*R^T
  133. return MultiplyABT(mRotOrient * mInvInertia, mRotOrient);
  134. }
  135. inline Vector3<Real> const& GetPosition() const
  136. {
  137. return mPosition;
  138. }
  139. Quaternion<Real> const& GetQOrientation() const
  140. {
  141. return mQuatOrient;
  142. }
  143. inline Vector3<Real> const& GetLinearMomentum() const
  144. {
  145. return mLinearMomentum;
  146. }
  147. inline Vector3<Real> const& GetAngularMomentum() const
  148. {
  149. return mAngularMomentum;
  150. }
  151. inline Matrix3x3<Real> const& GetROrientation() const
  152. {
  153. return mRotOrient;
  154. }
  155. inline Vector3<Real> const& GetLinearVelocity() const
  156. {
  157. return mLinearVelocity;
  158. }
  159. inline Vector3<Real> const& GetAngularVelocity() const
  160. {
  161. return mAngularVelocity;
  162. }
  163. // Force/torque function format.
  164. typedef std::function
  165. <
  166. Vector3<Real>
  167. (
  168. Real, // time of application
  169. Real, // mass
  170. Vector3<Real> const&, // position
  171. Quaternion<Real> const&, // orientation
  172. Vector3<Real> const&, // linear momentum
  173. Vector3<Real> const&, // angular momentum
  174. Matrix3x3<Real> const&, // orientation
  175. Vector3<Real> const&, // linear velocity
  176. Vector3<Real> const& // angular velocity
  177. )
  178. >
  179. Function;
  180. // Force and torque functions.
  181. Function mForce;
  182. Function mTorque;
  183. // Runge-Kutta fourth-order differential equation solver
  184. void Update(Real t, Real dt)
  185. {
  186. // TODO: When GTE_MAT_VEC is not defined (i.e. use vec-mat),
  187. // test to see whether dq/dt = 0.5 * w * q (mat-vec convention)
  188. // needs to become a different equation.
  189. Real halfDT = (Real)0.5 * dt;
  190. Real sixthDT = dt / (Real)6;
  191. Real TpHalfDT = t + halfDT;
  192. Real TpDT = t + dt;
  193. Vector3<Real> newPosition, newLinearMomentum, newAngularMomentum;
  194. Vector3<Real> newLinearVelocity, newAngularVelocity;
  195. Quaternion<Real> newQuatOrient;
  196. Matrix3x3<Real> newRotOrient;
  197. // A1 = G(T,S0), B1 = S0 + (DT/2)*A1
  198. Vector3<Real> A1DXDT = mLinearVelocity;
  199. Quaternion<Real> W = Quaternion<Real>(mAngularVelocity[0],
  200. mAngularVelocity[1], mAngularVelocity[2], (Real)0);
  201. Quaternion<Real> A1DQDT = (Real)0.5 * W * mQuatOrient;
  202. Vector3<Real> A1DPDT = mForce(t, mMass, mPosition, mQuatOrient,
  203. mLinearMomentum, mAngularMomentum, mRotOrient, mLinearVelocity,
  204. mAngularVelocity);
  205. Vector3<Real> A1DLDT = mTorque(t, mMass, mPosition, mQuatOrient,
  206. mLinearMomentum, mAngularMomentum, mRotOrient, mLinearVelocity,
  207. mAngularVelocity);
  208. newPosition = mPosition + halfDT * A1DXDT;
  209. newQuatOrient = mQuatOrient + halfDT * A1DQDT;
  210. newLinearMomentum = mLinearMomentum + halfDT * A1DPDT;
  211. newAngularMomentum = mAngularMomentum + halfDT * A1DLDT;
  212. newRotOrient = Rotation<3, Real>(newQuatOrient);
  213. newLinearVelocity = mInvMass * newLinearMomentum;
  214. newAngularVelocity = newAngularMomentum * newRotOrient;
  215. newAngularVelocity = mInvInertia * newAngularVelocity;
  216. newAngularVelocity = newRotOrient * newAngularVelocity;
  217. // A2 = G(T+DT/2,B1), B2 = S0 + (DT/2)*A2
  218. Vector3<Real> A2DXDT = newLinearVelocity;
  219. W = Quaternion<Real>(newAngularVelocity[0], newAngularVelocity[1],
  220. newAngularVelocity[2], (Real)0);
  221. Quaternion<Real> A2DQDT = (Real)0.5 * W * newQuatOrient;
  222. Vector3<Real> A2DPDT = mForce(TpHalfDT, mMass, newPosition,
  223. newQuatOrient, newLinearMomentum, newAngularMomentum, newRotOrient,
  224. newLinearVelocity, newAngularVelocity);
  225. Vector3<Real> A2DLDT = mTorque(TpHalfDT, mMass, newPosition,
  226. newQuatOrient, newLinearMomentum, newAngularMomentum, newRotOrient,
  227. newLinearVelocity, newAngularVelocity);
  228. newPosition = mPosition + halfDT * A2DXDT;
  229. newQuatOrient = mQuatOrient + halfDT * A2DQDT;
  230. newLinearMomentum = mLinearMomentum + halfDT * A2DPDT;
  231. newAngularMomentum = mAngularMomentum + halfDT * A2DLDT;
  232. newRotOrient = Rotation<3, Real>(newQuatOrient);
  233. newLinearVelocity = mInvMass * newLinearMomentum;
  234. newAngularVelocity = newAngularMomentum * newRotOrient;
  235. newAngularVelocity = mInvInertia * newAngularVelocity;
  236. newAngularVelocity = newRotOrient * newAngularVelocity;
  237. // A3 = G(T+DT/2,B2), B3 = S0 + DT*A3
  238. Vector3<Real> A3DXDT = newLinearVelocity;
  239. W = Quaternion<Real>(newAngularVelocity[0], newAngularVelocity[1],
  240. newAngularVelocity[2], (Real)0);
  241. Quaternion<Real> A3DQDT = (Real)0.5 * W * newQuatOrient;
  242. Vector3<Real> A3DPDT = mForce(TpHalfDT, mMass, newPosition,
  243. newQuatOrient, newLinearMomentum, newAngularMomentum, newRotOrient,
  244. newLinearVelocity, newAngularVelocity);
  245. Vector3<Real> A3DLDT = mTorque(TpHalfDT, mMass, newPosition,
  246. newQuatOrient, newLinearMomentum, newAngularMomentum, newRotOrient,
  247. newLinearVelocity, newAngularVelocity);
  248. newPosition = mPosition + dt * A3DXDT;
  249. newQuatOrient = mQuatOrient + dt * A3DQDT;
  250. newLinearMomentum = mLinearMomentum + dt * A3DPDT;
  251. newAngularMomentum = mAngularMomentum + dt * A3DLDT;
  252. newRotOrient = Rotation<3, Real>(newQuatOrient);
  253. newLinearVelocity = mInvMass * newLinearMomentum;
  254. newAngularVelocity = newAngularMomentum * newRotOrient;
  255. newAngularVelocity = mInvInertia * newAngularVelocity;
  256. newAngularVelocity = newRotOrient * newAngularVelocity;
  257. // A4 = G(T+DT,B3), S1 = S0 + (DT/6)*(A1+2*(A2+A3)+A4)
  258. Vector3<Real> A4DXDT = newLinearVelocity;
  259. W = Quaternion<Real>(newAngularVelocity[0], newAngularVelocity[1],
  260. newAngularVelocity[2], (Real)0);
  261. Quaternion<Real> A4DQDT = (Real)0.5 * W * newQuatOrient;
  262. Vector3<Real> A4DPDT = mForce(TpDT, mMass, newPosition,
  263. newQuatOrient, newLinearMomentum, newAngularMomentum, newRotOrient,
  264. newLinearVelocity, newAngularVelocity);
  265. Vector3<Real> A4DLDT = mTorque(TpDT, mMass, newPosition, newQuatOrient,
  266. newLinearMomentum, newAngularMomentum, newRotOrient,
  267. newLinearVelocity, newAngularVelocity);
  268. mPosition += sixthDT * (A1DXDT + (Real)2 * (A2DXDT + A3DXDT) + A4DXDT);
  269. mQuatOrient += sixthDT * (A1DQDT + (Real)2 * (A2DQDT + A3DQDT) + A4DQDT);
  270. mLinearMomentum += sixthDT * (A1DPDT + (Real)2 * (A2DPDT + A3DPDT) + A4DPDT);
  271. mAngularMomentum += sixthDT * (A1DLDT + (Real)2 * (A2DLDT + A3DLDT) + A4DLDT);
  272. mRotOrient = Rotation<3, Real>(mQuatOrient);
  273. mLinearVelocity = mInvMass * mLinearMomentum;
  274. mAngularVelocity = mAngularMomentum * mRotOrient;
  275. mAngularVelocity = mInvInertia * mAngularVelocity;
  276. mAngularVelocity = mRotOrient * mAngularVelocity;
  277. }
  278. protected:
  279. // Constant quantities (matrices in body coordinates).
  280. Real mMass, mInvMass;
  281. Matrix3x3<Real> mInertia, mInvInertia;
  282. // State variables.
  283. Vector3<Real> mPosition;
  284. Quaternion<Real> mQuatOrient;
  285. Vector3<Real> mLinearMomentum;
  286. Vector3<Real> mAngularMomentum;
  287. // Derived state variables.
  288. Matrix3x3<Real> mRotOrient;
  289. Vector3<Real> mLinearVelocity;
  290. Vector3<Real> mAngularVelocity;
  291. };
  292. }