Transform.h 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824
  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.2020.01.10
  7. #pragma once
  8. #include <Mathematics/Logger.h>
  9. #include <Mathematics/Matrix3x3.h>
  10. #include <Mathematics/Matrix4x4.h>
  11. #include <Mathematics/Rotation.h>
  12. // Transforms when GTE_USE_MAT_VEC is defined in the preprocessor symbols.
  13. //
  14. // The transform is Y = M*X+T, where M is a 3-by-3 matrix and T is a 3x1
  15. // translation. In most cases, M = R, a rotation matrix, or M = R*S,
  16. // where R is a rotation matrix and S is a diagonal matrix whose diagonal
  17. // entries are positive scales. To support modeling packages that allow
  18. // general affine transforms, M can be any invertible 3x3 matrix. The vector
  19. // X is transformed in the "forward" direction to Y. The "inverse" direction
  20. // transforms Y to X, namely X = M^{-1}*(Y-T) in the general case. In the
  21. // special case of M = R*S, the inverse direction is X = S^{-1}*R^t*(Y-T),
  22. // where S^{-1} is the diagonal matrix whose diagonal entries are the
  23. // reciprocoals of those of S and where R^t is the transpose of R. For SIMD
  24. // support of matrix-vector and matrix-matrix multiplications, a homogeneous
  25. // matrix H = {{M,T},{0,1}} is stored by this class. The forward transform is
  26. // {Y,1} = H*{X,1} and the inverse transform is {X,1} = H^{-1}*{Y,1}.
  27. // Transforms when GTE_USE_MAT_VEC is NOT defined in the preprocessor symbols.
  28. //
  29. // The transform is Y = T + X*M, where M is a 3-by-3 matrix and T is a 1x3
  30. // translation. In most cases, M = R, a rotation matrix, or M = S*R,
  31. // where R is a rotation matrix and S is a diagonal matrix whose diagonal
  32. // entries are positive scales. To support modeling packages that allow
  33. // general affine transforms, M can be any invertible 3x3 matrix. The vector
  34. // X is transformed in the "forward" direction to Y. The "inverse" direction
  35. // transforms Y to X, namely X = (Y-T)*M^{-1} in the general case. In the
  36. // special case of M = S*R, the inverse direction is X = (Y-T)*R^t*S^{-1},
  37. // where S^{-1} is the diagonal matrix whose diagonal entries are the
  38. // reciprocoals of those of S and where R^t is the transpose of R. For SIMD
  39. // support of matrix-vector and matrix-matrix multiplications, a homogeneous
  40. // matrix H = {{M,0},{T,1}} is stored by this class. The forward transform is
  41. // {Y,1} = {X,1}*H and the inverse transform is {X,1} = {Y,1}*H^{-1}.
  42. // With either multiplication convention, a matrix M = R*S (GTE_USE_MAT_VEC)
  43. // or a matrix M = S*R (!GTE_USE_VEC_MAT) is referred to as an "RS-matrix".
  44. // The class does not provide a member function to compute the inverse of a
  45. // transform: 'Transform GetInverse() const'. If one were to add this,
  46. // be aware that the inverse of an RS-matrix is not generally an RS-matrix;
  47. // that is, the inverse of R*S is S^{-1}*R^t which cannot always be factored
  48. // as S^{-1} * R^t = R' * S'. You would need to SetMatrix using S^{-1}*R^t
  49. // as the input.
  50. namespace WwiseGTE
  51. {
  52. template <typename Real>
  53. class Transform
  54. {
  55. public:
  56. // The default constructor produces the identity transformation. The
  57. // default copy constructor and assignment operator are generated by
  58. // the compiler.
  59. Transform()
  60. :
  61. mTranslate{ (Real)0, (Real)0, (Real)0, (Real)1 },
  62. mScale{ (Real)1, (Real)1, (Real)1, (Real)1 },
  63. mIsIdentity(true),
  64. mIsRSMatrix(true),
  65. mIsUniformScale(true),
  66. mInverseNeedsUpdate(false)
  67. {
  68. mHMatrix.MakeIdentity();
  69. mInvHMatrix.MakeIdentity();
  70. mMatrix.MakeIdentity();
  71. }
  72. // Implicit conversion.
  73. inline operator Matrix4x4<Real> const& () const
  74. {
  75. return GetHMatrix();
  76. }
  77. // Set the transformation to the identity matrix.
  78. void MakeIdentity()
  79. {
  80. mMatrix.MakeIdentity();
  81. mTranslate = { (Real)0, (Real)0, (Real)0, (Real)1 };
  82. mScale = { (Real)1, (Real)1, (Real)1, (Real)1 };
  83. mIsIdentity = true;
  84. mIsRSMatrix = true;
  85. mIsUniformScale = true;
  86. UpdateHMatrix();
  87. }
  88. // Set the transformation to have scales of 1.
  89. void MakeUnitScale()
  90. {
  91. LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
  92. mScale = { (Real)1, (Real)1, (Real)1, (Real)1 };
  93. mIsUniformScale = true;
  94. UpdateHMatrix();
  95. }
  96. // Hints about the structure of the transformation.
  97. // M = I
  98. inline bool IsIdentity() const
  99. {
  100. return mIsIdentity;
  101. }
  102. // R*S (GTE_USE_MAT_VEC defined) or S*R (GTE_USE_MAT_VEC not defined)
  103. inline bool IsRSMatrix() const
  104. {
  105. return mIsRSMatrix;
  106. }
  107. // RS-matrix with S = c*I
  108. inline bool IsUniformScale() const
  109. {
  110. return mIsRSMatrix && mIsUniformScale;
  111. }
  112. // Member access.
  113. // (1) The Set* functions set the is-identity hint to false.
  114. // (2) The SetRotate function sets the is-rsmatrix hint to true. If this
  115. // hint is false, GetRotate triggers an assertion in debug mode.
  116. // (3) The SetMatrix function sets the is-rsmatrix and is-uniform-scale
  117. // hints to false.
  118. // (4) The SetScale function sets the is-uniform-scale hint to false.
  119. // The SetUniformScale function sets the is-uniform-scale hint to
  120. // true. If this hint is false, GetUniformScale triggers an assertion
  121. // in debug mode.
  122. // (5) All Set* functions set the inverse-needs-update to true. When
  123. // GetHInverse is called, the inverse must be computed in this case
  124. // and the inverse-needs-update is reset to false.
  125. // {{R,0},{0,1}}
  126. void SetRotation(Matrix4x4<Real> const& rotate)
  127. {
  128. mMatrix = rotate;
  129. mIsIdentity = false;
  130. mIsRSMatrix = true;
  131. UpdateHMatrix();
  132. }
  133. // {{M,0},{0,1}}
  134. void SetMatrix(Matrix4x4<Real> const& matrix)
  135. {
  136. mMatrix = matrix;
  137. mIsIdentity = false;
  138. mIsRSMatrix = false;
  139. mIsUniformScale = false;
  140. UpdateHMatrix();
  141. }
  142. void SetTranslation(Real x0, Real x1, Real x2)
  143. {
  144. mTranslate = Vector4<Real>{ x0, x1, x2, (Real)1 };
  145. mIsIdentity = false;
  146. UpdateHMatrix();
  147. }
  148. inline void SetTranslation(Vector3<Real> const& translate)
  149. {
  150. SetTranslation(translate[0], translate[1], translate[2]);
  151. }
  152. inline void SetTranslation(Vector4<Real> const& translate)
  153. {
  154. SetTranslation(translate[0], translate[1], translate[2]);
  155. }
  156. void SetScale(Real s0, Real s1, Real s2)
  157. {
  158. LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
  159. LogAssert(s0 != (Real)0 && s1 != (Real)0 && s2 != (Real)0, "Scales must be nonzero.");
  160. mScale = { s0, s1, s2, (Real)1 };
  161. mIsIdentity = false;
  162. mIsUniformScale = false;
  163. UpdateHMatrix();
  164. }
  165. inline void SetScale(Vector3<Real> const& scale)
  166. {
  167. SetScale(scale[0], scale[1], scale[2]);
  168. }
  169. inline void SetScale(Vector4<Real> const& scale)
  170. {
  171. SetScale(scale[0], scale[1], scale[2]);
  172. }
  173. void SetUniformScale(Real scale)
  174. {
  175. LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
  176. LogAssert(scale != (Real)0, "Scale must be nonzero.");
  177. mScale = { scale, scale, scale, (Real)1 };
  178. mIsIdentity = false;
  179. mIsUniformScale = true;
  180. UpdateHMatrix();
  181. }
  182. // {{R,0},{0,1}}
  183. Matrix4x4<Real> const& GetRotation() const
  184. {
  185. LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
  186. return mMatrix;
  187. }
  188. // {{M,0},{0,1}}
  189. inline Matrix4x4<Real> const& GetMatrix() const
  190. {
  191. return mMatrix;
  192. }
  193. // (x,y,z)
  194. inline Vector3<Real> GetTranslation() const
  195. {
  196. return Vector3<Real>{ mTranslate[0], mTranslate[1], mTranslate[2] };
  197. }
  198. // (x,y,z,0)
  199. inline Vector4<Real> GetTranslationW0() const
  200. {
  201. return Vector4<Real>{ mTranslate[0], mTranslate[1], mTranslate[2], (Real)0 };
  202. }
  203. // (x,y,z,1)
  204. inline Vector4<Real> GetTranslationW1() const
  205. {
  206. return Vector4<Real>{ mTranslate[0], mTranslate[1], mTranslate[2], (Real)1 };
  207. }
  208. // (s0,s1,s2)
  209. Vector3<Real> GetScale() const
  210. {
  211. LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
  212. return Vector3<Real>{ mScale[0], mScale[1], mScale[2] };
  213. }
  214. // (s0,s1,s2,1)
  215. Vector4<Real> GetScaleW1() const
  216. {
  217. LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
  218. return Vector4<Real>{ mScale[0], mScale[1], mScale[2], (Real)1 };
  219. }
  220. Real GetUniformScale() const
  221. {
  222. LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
  223. LogAssert(mIsUniformScale, "Transform is not uniform scale.");
  224. return mScale[0];
  225. }
  226. // Alternate representations to set/get the rotation.
  227. // Set/get from 3x3 matrices.
  228. void SetRotation(Matrix3x3<Real> const& rotate)
  229. {
  230. mMatrix.MakeIdentity();
  231. for (int r = 0; r < 3; ++r)
  232. {
  233. for (int c = 0; c < 3; ++c)
  234. {
  235. mMatrix(r, c) = rotate(r, c);
  236. }
  237. }
  238. mIsIdentity = false;
  239. mIsRSMatrix = true;
  240. UpdateHMatrix();
  241. }
  242. void GetRotation(Matrix3x3<Real>& rotate) const
  243. {
  244. LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
  245. for (int r = 0; r < 3; ++r)
  246. {
  247. for (int c = 0; c < 3; ++c)
  248. {
  249. rotate(r, c) = mMatrix(r, c);
  250. }
  251. }
  252. }
  253. // The quaternion is unit length.
  254. void SetRotation(Quaternion<Real> const& q)
  255. {
  256. mMatrix = Rotation<4, Real>(q);
  257. mIsIdentity = false;
  258. mIsRSMatrix = true;
  259. UpdateHMatrix();
  260. }
  261. void GetRotation(Quaternion<Real>& q) const
  262. {
  263. LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
  264. q = Rotation<4, Real>(mMatrix);
  265. }
  266. // The axis is unit length and the angle is in radians.
  267. void SetRotation(AxisAngle<3, Real> const& axisAngle)
  268. {
  269. AxisAngle<4, Real> aa4(HLift(axisAngle.axis, (Real)1), axisAngle.angle);
  270. mMatrix = Rotation<4, Real>(aa4);
  271. mIsIdentity = false;
  272. mIsRSMatrix = true;
  273. UpdateHMatrix();
  274. }
  275. void GetRotation(AxisAngle<3, Real>& axisAngle) const
  276. {
  277. LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
  278. AxisAngle<4, Real> aa4 = Rotation<4, Real>(mMatrix);
  279. axisAngle.axis = HProject(aa4.axis);
  280. axisAngle.angle = aa4.angle;
  281. }
  282. void SetRotation(AxisAngle<4, Real> const& axisAngle)
  283. {
  284. mMatrix = Rotation<4, Real>(axisAngle);
  285. mIsIdentity = false;
  286. mIsRSMatrix = true;
  287. UpdateHMatrix();
  288. }
  289. void GetRotation(AxisAngle<4, Real>& axisAngle) const
  290. {
  291. LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
  292. axisAngle = Rotation<4, Real>(mMatrix);
  293. }
  294. // The Euler angles are in radians. The GetEulerAngles function
  295. // expects the eulerAngles.axis[] values to be set to the axis order
  296. // you want.
  297. void SetRotation(EulerAngles<Real> const& eulerAngles)
  298. {
  299. mMatrix = Rotation<4, Real>(eulerAngles);
  300. mIsIdentity = false;
  301. mIsRSMatrix = true;
  302. UpdateHMatrix();
  303. }
  304. void GetRotation(EulerAngles<Real>& eulerAngles) const
  305. {
  306. LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
  307. eulerAngles = Rotation<4, Real>(mMatrix)(eulerAngles.axis[0],
  308. eulerAngles.axis[1], eulerAngles.axis[2]);
  309. }
  310. // For M = R*S or M = S*R, the largest value of S in absolute value is
  311. // returned. For general M, the max-row-sum norm is returned when
  312. // GTE_USE_MAT_VEC is defined or the max-col-sum norm is returned when
  313. // the GTE_USE_MAT_VEC is not defined, which is a reasonable measure
  314. // of maximum scale of the transformation.
  315. Real GetNorm() const
  316. {
  317. Real sum0, sum1, sum2;
  318. if (mIsRSMatrix)
  319. {
  320. // A RS matrix (GTE_USE_MAT_VEC defined) or an SR matrix
  321. // (GTE_USE_MAT_VEC is not defined).
  322. sum0 = std::fabs(mScale[0]);
  323. sum1 = std::fabs(mScale[1]);
  324. sum2 = std::fabs(mScale[2]);
  325. }
  326. else
  327. {
  328. // The spectral norm (the maximum absolute value of the
  329. // eigenvalues) is smaller or equal to this norm. Therefore,
  330. // this function returns an approximation to the maximum
  331. // scale.
  332. #if defined(GTE_USE_MAT_VEC)
  333. // Use the max-row-sum matrix norm.
  334. sum0 = std::fabs(mMatrix(0, 0)) + std::fabs(mMatrix(0, 1)) + std::fabs(mMatrix(0, 2));
  335. sum1 = std::fabs(mMatrix(1, 0)) + std::fabs(mMatrix(1, 1)) + std::fabs(mMatrix(1, 2));
  336. sum2 = std::fabs(mMatrix(2, 0)) + std::fabs(mMatrix(2, 1)) + std::fabs(mMatrix(2, 2));
  337. #else
  338. // Use the max-col-sum matrix norm.
  339. sum0 = std::fabs(mMatrix(0, 0)) + std::fabs(mMatrix(1, 0)) + std::fabs(mMatrix(2, 0));
  340. sum1 = std::fabs(mMatrix(0, 1)) + std::fabs(mMatrix(1, 1)) + std::fabs(mMatrix(2, 1));
  341. sum2 = std::fabs(mMatrix(0, 2)) + std::fabs(mMatrix(1, 2)) + std::fabs(mMatrix(2, 2));
  342. #endif
  343. }
  344. return std::max(std::max(sum0, sum1), sum2);
  345. }
  346. // Get the homogeneous matrix (composite of all channels).
  347. inline Matrix4x4<Real> const& GetHMatrix() const
  348. {
  349. return mHMatrix;
  350. }
  351. // Get the inverse homogeneous matrix, recomputing it when necessary.
  352. // GTE_USE_MAT_VEC
  353. // H = {{M,T},{0,1}}, then H^{-1} = {{M^{-1},-M^{-1}*T},{0,1}}
  354. // GTE_USE_VEC_MAT
  355. // H = {{M,0},{T,1}}, then H^{-1} = {{M^{-1},0},{-M^{-1}*T,1}}
  356. Matrix4x4<Real> const& GetHInverse() const
  357. {
  358. if (mInverseNeedsUpdate)
  359. {
  360. if (mIsIdentity)
  361. {
  362. mInvHMatrix.MakeIdentity();
  363. }
  364. else
  365. {
  366. if (mIsRSMatrix)
  367. {
  368. if (mIsUniformScale)
  369. {
  370. Real invScale = (Real)1 / mScale[0];
  371. #if defined(GTE_USE_MAT_VEC)
  372. mInvHMatrix(0, 0) = invScale * mMatrix(0, 0);
  373. mInvHMatrix(0, 1) = invScale * mMatrix(1, 0);
  374. mInvHMatrix(0, 2) = invScale * mMatrix(2, 0);
  375. mInvHMatrix(1, 0) = invScale * mMatrix(0, 1);
  376. mInvHMatrix(1, 1) = invScale * mMatrix(1, 1);
  377. mInvHMatrix(1, 2) = invScale * mMatrix(2, 1);
  378. mInvHMatrix(2, 0) = invScale * mMatrix(0, 2);
  379. mInvHMatrix(2, 1) = invScale * mMatrix(1, 2);
  380. mInvHMatrix(2, 2) = invScale * mMatrix(2, 2);
  381. #else
  382. mInvHMatrix(0, 0) = mMatrix(0, 0) * invScale;
  383. mInvHMatrix(0, 1) = mMatrix(1, 0) * invScale;
  384. mInvHMatrix(0, 2) = mMatrix(2, 0) * invScale;
  385. mInvHMatrix(1, 0) = mMatrix(0, 1) * invScale;
  386. mInvHMatrix(1, 1) = mMatrix(1, 1) * invScale;
  387. mInvHMatrix(1, 2) = mMatrix(2, 1) * invScale;
  388. mInvHMatrix(2, 0) = mMatrix(0, 2) * invScale;
  389. mInvHMatrix(2, 1) = mMatrix(1, 2) * invScale;
  390. mInvHMatrix(2, 2) = mMatrix(2, 2) * invScale;
  391. #endif
  392. }
  393. else
  394. {
  395. // Replace 3 reciprocals by 6 multiplies and
  396. // 1 reciprocal.
  397. Real s01 = mScale[0] * mScale[1];
  398. Real s02 = mScale[0] * mScale[2];
  399. Real s12 = mScale[1] * mScale[2];
  400. Real invs012 = (Real)1 / (s01 * mScale[2]);
  401. Real invS0 = s12 * invs012;
  402. Real invS1 = s02 * invs012;
  403. Real invS2 = s01 * invs012;
  404. #if defined(GTE_USE_MAT_VEC)
  405. mInvHMatrix(0, 0) = invS0 * mMatrix(0, 0);
  406. mInvHMatrix(0, 1) = invS0 * mMatrix(1, 0);
  407. mInvHMatrix(0, 2) = invS0 * mMatrix(2, 0);
  408. mInvHMatrix(1, 0) = invS1 * mMatrix(0, 1);
  409. mInvHMatrix(1, 1) = invS1 * mMatrix(1, 1);
  410. mInvHMatrix(1, 2) = invS1 * mMatrix(2, 1);
  411. mInvHMatrix(2, 0) = invS2 * mMatrix(0, 2);
  412. mInvHMatrix(2, 1) = invS2 * mMatrix(1, 2);
  413. mInvHMatrix(2, 2) = invS2 * mMatrix(2, 2);
  414. #else
  415. mInvHMatrix(0, 0) = mMatrix(0, 0) * invS0;
  416. mInvHMatrix(0, 1) = mMatrix(1, 0) * invS1;
  417. mInvHMatrix(0, 2) = mMatrix(2, 0) * invS2;
  418. mInvHMatrix(1, 0) = mMatrix(0, 1) * invS0;
  419. mInvHMatrix(1, 1) = mMatrix(1, 1) * invS1;
  420. mInvHMatrix(1, 2) = mMatrix(2, 1) * invS2;
  421. mInvHMatrix(2, 0) = mMatrix(0, 2) * invS0;
  422. mInvHMatrix(2, 1) = mMatrix(1, 2) * invS1;
  423. mInvHMatrix(2, 2) = mMatrix(2, 2) * invS2;
  424. #endif
  425. }
  426. }
  427. else
  428. {
  429. Invert3x3(mHMatrix, mInvHMatrix);
  430. }
  431. #if defined(GTE_USE_MAT_VEC)
  432. mInvHMatrix(0, 3) = -(
  433. mInvHMatrix(0, 0) * mTranslate[0] +
  434. mInvHMatrix(0, 1) * mTranslate[1] +
  435. mInvHMatrix(0, 2) * mTranslate[2]
  436. );
  437. mInvHMatrix(1, 3) = -(
  438. mInvHMatrix(1, 0) * mTranslate[0] +
  439. mInvHMatrix(1, 1) * mTranslate[1] +
  440. mInvHMatrix(1, 2) * mTranslate[2]
  441. );
  442. mInvHMatrix(2, 3) = -(
  443. mInvHMatrix(2, 0) * mTranslate[0] +
  444. mInvHMatrix(2, 1) * mTranslate[1] +
  445. mInvHMatrix(2, 2) * mTranslate[2]
  446. );
  447. // The last row of mHMatrix is always (0,0,0,1) for an
  448. // affine transformation, so it is set once in the
  449. // constructor. It is not necessary to reset it here.
  450. #else
  451. mInvHMatrix(3, 0) = -(
  452. mInvHMatrix(0, 0) * mTranslate[0] +
  453. mInvHMatrix(1, 0) * mTranslate[1] +
  454. mInvHMatrix(2, 0) * mTranslate[2]
  455. );
  456. mInvHMatrix(3, 1) = -(
  457. mInvHMatrix(0, 1) * mTranslate[0] +
  458. mInvHMatrix(1, 1) * mTranslate[1] +
  459. mInvHMatrix(2, 1) * mTranslate[2]
  460. );
  461. mInvHMatrix(3, 2) = -(
  462. mInvHMatrix(0, 2) * mTranslate[0] +
  463. mInvHMatrix(1, 2) * mTranslate[1] +
  464. mInvHMatrix(2, 2) * mTranslate[2]
  465. );
  466. // The last column of mHMatrix is always (0,0,0,1) for an
  467. // affine transformation, so it is set once in the
  468. // constructor. It is not necessary to reset it here.
  469. #endif
  470. }
  471. mInverseNeedsUpdate = false;
  472. }
  473. return mInvHMatrix;
  474. }
  475. // Invert the transform. If possible, the channels are properly
  476. // assigned. For example, if the input has mIsRSMatrix equal to
  477. // 'true', then the inverse also has mIsRSMatrix equal to 'true'
  478. // and the inverse's mMatrix is a rotation matrix and mScale is
  479. // set accordingly.
  480. Transform Inverse() const
  481. {
  482. Transform inverse;
  483. if (mIsIdentity)
  484. {
  485. inverse.MakeIdentity();
  486. }
  487. else
  488. {
  489. if (mIsRSMatrix && mIsUniformScale)
  490. {
  491. inverse.SetRotation(Transpose(GetRotation()));
  492. inverse.SetUniformScale(1.0f / GetUniformScale());
  493. }
  494. else
  495. {
  496. Matrix4x4<Real> invUpper;
  497. Invert3x3(GetMatrix(), invUpper);
  498. inverse.SetMatrix(invUpper);
  499. }
  500. Vector4<Real> trn = -GetTranslationW0();
  501. inverse.SetTranslation(inverse.GetMatrix() * trn);
  502. }
  503. mInverseNeedsUpdate = true;
  504. return inverse;
  505. }
  506. // The identity transformation.
  507. static Transform Identity()
  508. {
  509. static Transform identity;
  510. return identity;
  511. }
  512. private:
  513. // Fill in the entries of mHMatrix whenever one of the components
  514. // mMatrix, mTranslate, or mScale changes.
  515. void UpdateHMatrix()
  516. {
  517. if (mIsIdentity)
  518. {
  519. mHMatrix.MakeIdentity();
  520. }
  521. else
  522. {
  523. if (mIsRSMatrix)
  524. {
  525. #if defined(GTE_USE_MAT_VEC)
  526. mHMatrix(0, 0) = mMatrix(0, 0) * mScale[0];
  527. mHMatrix(0, 1) = mMatrix(0, 1) * mScale[1];
  528. mHMatrix(0, 2) = mMatrix(0, 2) * mScale[2];
  529. mHMatrix(1, 0) = mMatrix(1, 0) * mScale[0];
  530. mHMatrix(1, 1) = mMatrix(1, 1) * mScale[1];
  531. mHMatrix(1, 2) = mMatrix(1, 2) * mScale[2];
  532. mHMatrix(2, 0) = mMatrix(2, 0) * mScale[0];
  533. mHMatrix(2, 1) = mMatrix(2, 1) * mScale[1];
  534. mHMatrix(2, 2) = mMatrix(2, 2) * mScale[2];
  535. #else
  536. mHMatrix(0, 0) = mScale[0] * mMatrix(0, 0);
  537. mHMatrix(0, 1) = mScale[0] * mMatrix(0, 1);
  538. mHMatrix(0, 2) = mScale[0] * mMatrix(0, 2);
  539. mHMatrix(1, 0) = mScale[1] * mMatrix(1, 0);
  540. mHMatrix(1, 1) = mScale[1] * mMatrix(1, 1);
  541. mHMatrix(1, 2) = mScale[1] * mMatrix(1, 2);
  542. mHMatrix(2, 0) = mScale[2] * mMatrix(2, 0);
  543. mHMatrix(2, 1) = mScale[2] * mMatrix(2, 1);
  544. mHMatrix(2, 2) = mScale[2] * mMatrix(2, 2);
  545. #endif
  546. }
  547. else
  548. {
  549. mHMatrix(0, 0) = mMatrix(0, 0);
  550. mHMatrix(0, 1) = mMatrix(0, 1);
  551. mHMatrix(0, 2) = mMatrix(0, 2);
  552. mHMatrix(1, 0) = mMatrix(1, 0);
  553. mHMatrix(1, 1) = mMatrix(1, 1);
  554. mHMatrix(1, 2) = mMatrix(1, 2);
  555. mHMatrix(2, 0) = mMatrix(2, 0);
  556. mHMatrix(2, 1) = mMatrix(2, 1);
  557. mHMatrix(2, 2) = mMatrix(2, 2);
  558. }
  559. #if defined(GTE_USE_MAT_VEC)
  560. mHMatrix(0, 3) = mTranslate[0];
  561. mHMatrix(1, 3) = mTranslate[1];
  562. mHMatrix(2, 3) = mTranslate[2];
  563. // The last row of mHMatrix is always (0,0,0,1) for an affine
  564. // transformation, so it is set once in the constructor. It
  565. // is not necessary to reset it here.
  566. #else
  567. mHMatrix(3, 0) = mTranslate[0];
  568. mHMatrix(3, 1) = mTranslate[1];
  569. mHMatrix(3, 2) = mTranslate[2];
  570. // The last column of mHMatrix is always (0,0,0,1) for an
  571. // affine transformation, so it is set once in the
  572. // constructor. It is not necessary to reset it here.
  573. #endif
  574. }
  575. mInverseNeedsUpdate = true;
  576. }
  577. // Invert the 3x3 upper-left block of the input matrix.
  578. static void Invert3x3(Matrix4x4<Real> const& mat, Matrix4x4<Real>& invMat)
  579. {
  580. // Compute the adjoint of M (3x3).
  581. invMat(0, 0) = mat(1, 1) * mat(2, 2) - mat(1, 2) * mat(2, 1);
  582. invMat(0, 1) = mat(0, 2) * mat(2, 1) - mat(0, 1) * mat(2, 2);
  583. invMat(0, 2) = mat(0, 1) * mat(1, 2) - mat(0, 2) * mat(1, 1);
  584. invMat(0, 3) = 0.0f;
  585. invMat(1, 0) = mat(1, 2) * mat(2, 0) - mat(1, 0) * mat(2, 2);
  586. invMat(1, 1) = mat(0, 0) * mat(2, 2) - mat(0, 2) * mat(2, 0);
  587. invMat(1, 2) = mat(0, 2) * mat(1, 0) - mat(0, 0) * mat(1, 2);
  588. invMat(1, 3) = 0.0f;
  589. invMat(2, 0) = mat(1, 0) * mat(2, 1) - mat(1, 1) * mat(2, 0);
  590. invMat(2, 1) = mat(0, 1) * mat(2, 0) - mat(0, 0) * mat(2, 1);
  591. invMat(2, 2) = mat(0, 0) * mat(1, 1) - mat(0, 1) * mat(1, 0);
  592. invMat(2, 3) = 0.0f;
  593. invMat(3, 0) = 0.0f;
  594. invMat(3, 1) = 0.0f;
  595. invMat(3, 2) = 0.0f;
  596. invMat(3, 3) = 1.0f;
  597. // Compute the reciprocal of the determinant of M.
  598. Real invDet = (Real)1 / (
  599. mat(0, 0) * invMat(0, 0) +
  600. mat(0, 1) * invMat(1, 0) +
  601. mat(0, 2) * invMat(2, 0)
  602. );
  603. // inverse(M) = adjoint(M)/determinant(M).
  604. invMat(0, 0) *= invDet;
  605. invMat(0, 1) *= invDet;
  606. invMat(0, 2) *= invDet;
  607. invMat(1, 0) *= invDet;
  608. invMat(1, 1) *= invDet;
  609. invMat(1, 2) *= invDet;
  610. invMat(2, 0) *= invDet;
  611. invMat(2, 1) *= invDet;
  612. invMat(2, 2) *= invDet;
  613. }
  614. // The full 4x4 homogeneous matrix H and its inverse H^{-1}, stored
  615. // according to the conventions (see GetHInverse description). The
  616. // inverse is computed only on demand.
  617. Matrix4x4<Real> mHMatrix;
  618. mutable Matrix4x4<Real> mInvHMatrix;
  619. Matrix4x4<Real> mMatrix; // M (general) or R (rotation)
  620. Vector4<Real> mTranslate; // T
  621. Vector4<Real> mScale; // S
  622. bool mIsIdentity, mIsRSMatrix, mIsUniformScale;
  623. mutable bool mInverseNeedsUpdate;
  624. };
  625. // Compute M*V.
  626. template <typename Real>
  627. Vector4<Real> operator*(Transform<Real> const& M, Vector4<Real> const& V)
  628. {
  629. return M.GetHMatrix() * V;
  630. }
  631. // Compute V^T*M.
  632. template <typename Real>
  633. Vector4<Real> operator*(Vector4<Real> const& V, Transform<Real> const& M)
  634. {
  635. return V * M.GetHMatrix();
  636. }
  637. // Compute A*B.
  638. template <typename Real>
  639. Transform<Real> operator*(Transform<Real> const& A, Transform<Real> const& B)
  640. {
  641. if (A.IsIdentity())
  642. {
  643. return B;
  644. }
  645. if (B.IsIdentity())
  646. {
  647. return A;
  648. }
  649. Transform<Real> product;
  650. if (A.IsRSMatrix() && B.IsRSMatrix())
  651. {
  652. #if defined(GTE_USE_MAT_VEC)
  653. if (A.IsUniformScale())
  654. {
  655. product.SetRotation(A.GetRotation() * B.GetRotation());
  656. product.SetTranslation(A.GetUniformScale() * (
  657. A.GetRotation() * B.GetTranslationW0()) +
  658. A.GetTranslationW1());
  659. if (B.IsUniformScale())
  660. {
  661. product.SetUniformScale(A.GetUniformScale() * B.GetUniformScale());
  662. }
  663. else
  664. {
  665. product.SetScale(A.GetUniformScale() * B.GetScale());
  666. }
  667. return product;
  668. }
  669. #else
  670. if (B.IsUniformScale())
  671. {
  672. product.SetRotation(A.GetRotation() * B.GetRotation());
  673. product.SetTranslation(B.GetUniformScale() * (
  674. A.GetTranslationW0() * B.GetRotation()) +
  675. B.GetTranslationW1());
  676. if (A.IsUniformScale())
  677. {
  678. product.SetUniformScale(A.GetUniformScale() * B.GetUniformScale());
  679. }
  680. else
  681. {
  682. product.SetScale(A.GetScale() * B.GetUniformScale());
  683. }
  684. return product;
  685. }
  686. #endif
  687. }
  688. // In all remaining cases, the matrix cannot be written as R*S*X+T.
  689. Matrix4x4<Real> matMA;
  690. if (A.IsRSMatrix())
  691. {
  692. #if defined(GTE_USE_MAT_VEC)
  693. matMA = MultiplyMD(A.GetRotation(), A.GetScaleW1());
  694. #else
  695. matMA = MultiplyDM(A.GetScaleW1(), A.GetRotation());
  696. #endif
  697. }
  698. else
  699. {
  700. matMA = A.GetMatrix();
  701. }
  702. Matrix4x4<Real> matMB;
  703. if (B.IsRSMatrix())
  704. {
  705. #if defined(GTE_USE_MAT_VEC)
  706. matMB = MultiplyMD(B.GetRotation(), B.GetScaleW1());
  707. #else
  708. matMB = MultiplyDM(B.GetScaleW1(), B.GetRotation());
  709. #endif
  710. }
  711. else
  712. {
  713. matMB = B.GetMatrix();
  714. }
  715. product.SetMatrix(matMA * matMB);
  716. #if defined(GTE_USE_MAT_VEC)
  717. product.SetTranslation(matMA * B.GetTranslationW0() +
  718. A.GetTranslationW1());
  719. #else
  720. product.SetTranslation(A.GetTranslationW0() * matMB +
  721. B.GetTranslationW1());
  722. #endif
  723. return product;
  724. }
  725. template <typename Real>
  726. inline Matrix4x4<Real> operator*(Matrix4x4<Real> const& A, Transform<Real> const& B)
  727. {
  728. return A * B.GetHMatrix();
  729. }
  730. template <typename Real>
  731. inline Matrix4x4<Real> operator*(Transform<Real> const& A, Matrix4x4<Real> const& B)
  732. {
  733. return A.GetHMatrix()* B;
  734. }
  735. }