Cry_Matrix34.h 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. // Description : Common matrix class
  9. #pragma once
  10. ///////////////////////////////////////////////////////////////////////////////
  11. ///////////////////////////////////////////////////////////////////////////////
  12. ///////////////////////////////////////////////////////////////////////////////
  13. // struct Matrix34_tpl
  14. ///////////////////////////////////////////////////////////////////////////////
  15. ///////////////////////////////////////////////////////////////////////////////
  16. ///////////////////////////////////////////////////////////////////////////////
  17. template <typename F>
  18. struct Matrix34_tpl
  19. {
  20. F m00, m01, m02, m03;
  21. F m10, m11, m12, m13;
  22. F m20, m21, m22, m23;
  23. //default constructor
  24. #if defined(_DEBUG)
  25. ILINE Matrix34_tpl()
  26. {
  27. if constexpr (sizeof(F) == 4)
  28. {
  29. uint32* p = (uint32*)&m00;
  30. p[ 0] = F32NAN;
  31. p[ 1] = F32NAN;
  32. p[ 2] = F32NAN;
  33. p[ 3] = F32NAN;
  34. p[ 4] = F32NAN;
  35. p[ 5] = F32NAN;
  36. p[ 6] = F32NAN;
  37. p[ 7] = F32NAN;
  38. p[ 8] = F32NAN;
  39. p[ 9] = F32NAN;
  40. p[10] = F32NAN;
  41. p[11] = F32NAN;
  42. }
  43. if constexpr (sizeof(F) == 8)
  44. {
  45. uint64* p = (uint64*)&m00;
  46. p[ 0] = F64NAN;
  47. p[ 1] = F64NAN;
  48. p[ 2] = F64NAN;
  49. p[ 3] = F64NAN;
  50. p[ 4] = F64NAN;
  51. p[ 5] = F64NAN;
  52. p[ 6] = F64NAN;
  53. p[ 7] = F64NAN;
  54. p[ 8] = F64NAN;
  55. p[ 9] = F64NAN;
  56. p[10] = F64NAN;
  57. p[11] = F64NAN;
  58. }
  59. }
  60. #else
  61. ILINE Matrix34_tpl(){};
  62. #endif
  63. //set matrix to Identity
  64. ILINE Matrix34_tpl(type_identity)
  65. {
  66. m00 = 1;
  67. m01 = 0;
  68. m02 = 0;
  69. m03 = 0;
  70. m10 = 0;
  71. m11 = 1;
  72. m12 = 0;
  73. m13 = 0;
  74. m20 = 0;
  75. m21 = 0;
  76. m22 = 1;
  77. m23 = 0;
  78. }
  79. //set matrix to Zero
  80. ILINE Matrix34_tpl(type_zero)
  81. {
  82. m00 = 0;
  83. m01 = 0;
  84. m02 = 0;
  85. m03 = 0;
  86. m10 = 0;
  87. m11 = 0;
  88. m12 = 0;
  89. m13 = 0;
  90. m20 = 0;
  91. m21 = 0;
  92. m22 = 0;
  93. m23 = 0;
  94. }
  95. //ASSIGNMENT OPERATOR of identical Matrix33 types.
  96. //The assignment operator has precedence over assignment constructor
  97. //Matrix34 m; m=m34;
  98. ILINE Matrix34_tpl<F>& operator = (const Matrix34_tpl<F>& m)
  99. {
  100. assert(m.IsValid());
  101. m00 = m.m00;
  102. m01 = m.m01;
  103. m02 = m.m02;
  104. m03 = m.m03;
  105. m10 = m.m10;
  106. m11 = m.m11;
  107. m12 = m.m12;
  108. m13 = m.m13;
  109. m20 = m.m20;
  110. m21 = m.m21;
  111. m22 = m.m22;
  112. m23 = m.m23;
  113. return *this;
  114. }
  115. //--------------------------------------------------------------------
  116. //---- implementation of the constructors ---
  117. //--------------------------------------------------------------------
  118. //CONSTRUCTOR for identical float-types. It initialises a matrix34 with 12 floats.
  119. ILINE Matrix34_tpl<F>(F v00, F v01, F v02, F v03, F v10, F v11, F v12, F v13, F v20, F v21, F v22, F v23)
  120. {
  121. m00 = v00;
  122. m01 = v01;
  123. m02 = v02;
  124. m03 = v03;
  125. m10 = v10;
  126. m11 = v11;
  127. m12 = v12;
  128. m13 = v13;
  129. m20 = v20;
  130. m21 = v21;
  131. m22 = v22;
  132. m23 = v23;
  133. }
  134. //CONSTRUCTOR for different float-types. It initialises a matrix34 with 12 floats.
  135. template<class F1>
  136. ILINE Matrix34_tpl<F>(F1 v00, F1 v01, F1 v02, F1 v03, F1 v10, F1 v11, F1 v12, F1 v13, F1 v20, F1 v21, F1 v22, F1 v23)
  137. {
  138. m00 = F(v00);
  139. m01 = F(v01);
  140. m02 = F(v02);
  141. m03 = F(v03);
  142. m10 = F(v10);
  143. m11 = F(v11);
  144. m12 = F(v12);
  145. m13 = F(v13);
  146. m20 = F(v20);
  147. m21 = F(v21);
  148. m22 = F(v22);
  149. m23 = F(v23);
  150. }
  151. //CONSTRUCTOR for identical float-types. It converts a Matrix33 into a Matrix34.
  152. //Matrix34(m33);
  153. ILINE Matrix34_tpl<F>(const Matrix33_tpl<F>&m)
  154. {
  155. assert(m.IsValid());
  156. m00 = m.m00;
  157. m01 = m.m01;
  158. m02 = m.m02;
  159. m03 = 0;
  160. m10 = m.m10;
  161. m11 = m.m11;
  162. m12 = m.m12;
  163. m13 = 0;
  164. m20 = m.m20;
  165. m21 = m.m21;
  166. m22 = m.m22;
  167. m23 = 0;
  168. }
  169. //CONSTRUCTOR for different float-types. It converts a Matrix33 into a Matrix34 and also converts between double/float.
  170. //Matrix34(Matrix33);
  171. template<class F1>
  172. ILINE Matrix34_tpl<F>(const Matrix33_tpl<F1>&m)
  173. {
  174. assert(m.IsValid());
  175. m00 = F(m.m00);
  176. m01 = F(m.m01);
  177. m02 = F(m.m02);
  178. m03 = 0;
  179. m10 = F(m.m10);
  180. m11 = F(m.m11);
  181. m12 = F(m.m12);
  182. m13 = 0;
  183. m20 = F(m.m20);
  184. m21 = F(m.m21);
  185. m22 = F(m.m22);
  186. m23 = 0;
  187. }
  188. //CONSTRUCTOR for identical float-types. It converts a Matrix33 with a translation-vector into a Matrix34.
  189. //Matrix34(m33,Vec3(1,2,3));
  190. ILINE Matrix34_tpl<F>(const Matrix33_tpl<F>&m, const Vec3_tpl<F>&t)
  191. {
  192. assert(m.IsValid());
  193. assert(t.IsValid());
  194. m00 = m.m00;
  195. m01 = m.m01;
  196. m02 = m.m02;
  197. m03 = t.x;
  198. m10 = m.m10;
  199. m11 = m.m11;
  200. m12 = m.m12;
  201. m13 = t.y;
  202. m20 = m.m20;
  203. m21 = m.m21;
  204. m22 = m.m22;
  205. m23 = t.z;
  206. }
  207. //CONSTRUCTOR for different float-types. It converts a Matrix33 with a translation-vector into a Matrix34 and also converts between double/float.
  208. //Matrix34(Matrix33r,Vec3d(1,2,3));
  209. template<class F1>
  210. ILINE Matrix34_tpl<F>(const Matrix33_tpl<F1>&m, const Vec3_tpl<F1>&t)
  211. {
  212. assert(m.IsValid());
  213. assert(t.IsValid());
  214. m00 = F(m.m00);
  215. m01 = F(m.m01);
  216. m02 = F(m.m02);
  217. m03 = F(t.x);
  218. m10 = F(m.m10);
  219. m11 = F(m.m11);
  220. m12 = F(m.m12);
  221. m13 = F(t.y);
  222. m20 = F(m.m20);
  223. m21 = F(m.m21);
  224. m22 = F(m.m22);
  225. m23 = F(t.z);
  226. }
  227. //CONSTRUCTOR for identical float types
  228. //Matrix34 m=m34;
  229. ILINE Matrix34_tpl<F>(const Matrix34_tpl<F>&m)
  230. {
  231. assert(m.IsValid());
  232. m00 = m.m00;
  233. m01 = m.m01;
  234. m02 = m.m02;
  235. m03 = m.m03;
  236. m10 = m.m10;
  237. m11 = m.m11;
  238. m12 = m.m12;
  239. m13 = m.m13;
  240. m20 = m.m20;
  241. m21 = m.m21;
  242. m22 = m.m22;
  243. m23 = m.m23;
  244. }
  245. //CONSTRUCTOR for different float-types.
  246. //Matrix34 m=m34d;
  247. template<class F1>
  248. ILINE Matrix34_tpl<F>(const Matrix34_tpl<F1>&m)
  249. {
  250. assert(m.IsValid());
  251. m00 = F(m.m00);
  252. m01 = F(m.m01);
  253. m02 = F(m.m02);
  254. m03 = F(m.m03);
  255. m10 = F(m.m10);
  256. m11 = F(m.m11);
  257. m12 = F(m.m12);
  258. m13 = F(m.m13);
  259. m20 = F(m.m20);
  260. m21 = F(m.m21);
  261. m22 = F(m.m22);
  262. m23 = F(m.m23);
  263. }
  264. //CONSTRUCTOR for identical float-types. It converts a Matrix44 into a Matrix34.
  265. //Needs to be 'explicit' because we loose the translation vector in the conversion process
  266. //Matrix34(m44);
  267. ILINE explicit Matrix34_tpl<F>(const Matrix44_tpl<F>&m)
  268. {
  269. assert(m.IsValid());
  270. m00 = m.m00;
  271. m01 = m.m01;
  272. m02 = m.m02;
  273. m03 = m.m03;
  274. m10 = m.m10;
  275. m11 = m.m11;
  276. m12 = m.m12;
  277. m13 = m.m13;
  278. m20 = m.m20;
  279. m21 = m.m21;
  280. m22 = m.m22;
  281. m23 = m.m23;
  282. }
  283. //CONSTRUCTOR for different float types. It converts a Matrix44 into a Matrix34 and converts between double/float.
  284. //Needs to be 'explicit' because we loose the translation vector in the conversion process
  285. //Matrix34(m44r);
  286. template<class F1>
  287. ILINE explicit Matrix34_tpl<F>(const Matrix44_tpl<F1>&m)
  288. {
  289. assert(m.IsValid());
  290. m00 = F(m.m00);
  291. m01 = F(m.m01);
  292. m02 = F(m.m02);
  293. m03 = F(m.m03);
  294. m10 = F(m.m10);
  295. m11 = F(m.m11);
  296. m12 = F(m.m12);
  297. m13 = F(m.m13);
  298. m20 = F(m.m20);
  299. m21 = F(m.m21);
  300. m22 = F(m.m22);
  301. m23 = F(m.m23);
  302. }
  303. //CONSTRUCTOR for identical float-types. It converts a Quat into a Matrix34.
  304. //Needs to be 'explicit' because we loose float-precision in the conversion process
  305. //Matrix34(QuatT);
  306. explicit ILINE Matrix34_tpl<F>(const Quat_tpl<F>&q)
  307. {
  308. *this = Matrix33_tpl<F>(q);
  309. }
  310. //CONSTRUCTOR for different float-types. It converts a Quat into a Matrix34.
  311. //Needs to be 'explicit' because we loose float-precision in the conversion process
  312. //Matrix34(QuatTd);
  313. template<class F1>
  314. explicit ILINE Matrix34_tpl<F>(const Quat_tpl<F1>&q)
  315. {
  316. *this = Matrix33_tpl<F>(q);
  317. }
  318. //apply scaling to the columns of the matrix.
  319. ILINE void ScaleColumn(const Vec3_tpl<F>& s)
  320. {
  321. m00 *= s.x;
  322. m01 *= s.y;
  323. m02 *= s.z;
  324. m10 *= s.x;
  325. m11 *= s.y;
  326. m12 *= s.z;
  327. m20 *= s.x;
  328. m21 *= s.y;
  329. m22 *= s.z;
  330. }
  331. /*!
  332. *
  333. * Initializes the Matrix34 with the identity.
  334. *
  335. */
  336. void SetIdentity()
  337. {
  338. m00 = 1.0f;
  339. m01 = 0.0f;
  340. m02 = 0.0f;
  341. m03 = 0.0f;
  342. m10 = 0.0f;
  343. m11 = 1.0f;
  344. m12 = 0.0f;
  345. m13 = 0.0f;
  346. m20 = 0.0f;
  347. m21 = 0.0f;
  348. m22 = 1.0f;
  349. m23 = 0.0f;
  350. }
  351. ILINE static Matrix34_tpl<F> CreateIdentity()
  352. {
  353. Matrix34_tpl<F> m;
  354. m.SetIdentity();
  355. return m;
  356. }
  357. /*!
  358. * Create rotation-matrix about X axis using an angle.
  359. * The angle is assumed to be in radians.
  360. * The translation-vector is set to zero.
  361. *
  362. * Example:
  363. * Matrix34 m34;
  364. * m34.SetRotationX(0.5f);
  365. */
  366. ILINE void SetRotationX(const f32 rad, const Vec3_tpl<F>& t = Vec3(ZERO))
  367. {
  368. *this = Matrix33_tpl<F>::CreateRotationX(rad);
  369. this->SetTranslation(t);
  370. }
  371. ILINE static Matrix34_tpl<F> CreateRotationX(const f32 rad, const Vec3_tpl<F>& t = Vec3(ZERO))
  372. {
  373. Matrix34_tpl<F> m34;
  374. m34.SetRotationX(rad, t);
  375. return m34;
  376. }
  377. /*!
  378. * Create rotation-matrix about Y axis using an angle.
  379. * The angle is assumed to be in radians.
  380. * The translation-vector is set to zero.
  381. *
  382. * Example:
  383. * Matrix34 m34;
  384. * m34.SetRotationY(0.5f);
  385. */
  386. ILINE void SetRotationY(const f32 rad, const Vec3_tpl<F>& t = Vec3(ZERO))
  387. {
  388. *this = Matrix33_tpl<F>::CreateRotationY(rad);
  389. this->SetTranslation(t);
  390. }
  391. ILINE static Matrix34_tpl<F> CreateRotationY(const f32 rad, const Vec3_tpl<F>& t = Vec3(ZERO))
  392. {
  393. Matrix34_tpl<F> m34;
  394. m34.SetRotationY(rad, t);
  395. return m34;
  396. }
  397. /*!
  398. *
  399. * Convert three Euler angle to mat33 (rotation order:XYZ)
  400. * The Euler angles are assumed to be in radians.
  401. * The translation-vector is set to zero.
  402. *
  403. * Example 1:
  404. * Matrix34 m34;
  405. * m34.SetRotationXYZ( Ang3(0.5f,0.2f,0.9f), translation );
  406. *
  407. * Example 2:
  408. * Matrix34 m34=Matrix34::CreateRotationXYZ( Ang3(0.5f,0.2f,0.9f), translation );
  409. */
  410. ILINE void SetRotationXYZ(const Ang3_tpl<F>& rad, const Vec3_tpl<F>& t = Vec3(ZERO))
  411. {
  412. assert(rad.IsValid());
  413. assert(t.IsValid());
  414. *this = Matrix33_tpl<F>::CreateRotationXYZ(rad);
  415. this->SetTranslation(t);
  416. }
  417. ILINE static Matrix34_tpl<F> CreateRotationXYZ(const Ang3_tpl<F>& rad, const Vec3_tpl<F>& t = Vec3(ZERO))
  418. {
  419. assert(rad.IsValid());
  420. assert(t.IsValid());
  421. Matrix34_tpl<F> m34;
  422. m34.SetRotationXYZ(rad, t);
  423. return m34;
  424. }
  425. ILINE void SetTranslationMat(const Vec3_tpl<F>& v)
  426. {
  427. m00 = 1.0f;
  428. m01 = 0.0f;
  429. m02 = 0.0f;
  430. m03 = v.x;
  431. m10 = 0.0f;
  432. m11 = 1.0f;
  433. m12 = 0.0f;
  434. m13 = v.y;
  435. m20 = 0.0f;
  436. m21 = 0.0f;
  437. m22 = 1.0f;
  438. m23 = v.z;
  439. }
  440. ILINE static Matrix34_tpl<F> CreateTranslationMat(const Vec3_tpl<F>& v)
  441. {
  442. Matrix34_tpl<F> m34;
  443. m34.SetTranslationMat(v);
  444. return m34;
  445. }
  446. //NOTE: all vectors are stored in columns
  447. ILINE void SetFromVectors(const Vec3& vx, const Vec3& vy, const Vec3& vz, const Vec3& pos)
  448. {
  449. m00 = vx.x;
  450. m01 = vy.x;
  451. m02 = vz.x;
  452. m03 = pos.x;
  453. m10 = vx.y;
  454. m11 = vy.y;
  455. m12 = vz.y;
  456. m13 = pos.y;
  457. m20 = vx.z;
  458. m21 = vy.z;
  459. m22 = vz.z;
  460. m23 = pos.z;
  461. }
  462. ILINE static Matrix34_tpl<F> CreateFromVectors(const Vec3_tpl<F>& vx, const Vec3_tpl<F>& vy, const Vec3_tpl<F>& vz, const Vec3_tpl<F>& pos)
  463. {
  464. Matrix34_tpl<F> m;
  465. m.SetFromVectors(vx, vy, vz, pos);
  466. return m;
  467. }
  468. Matrix34_tpl<F> GetInvertedFast() const
  469. {
  470. assert(IsOrthonormal());
  471. Matrix34_tpl<F> dst;
  472. dst.m00 = m00;
  473. dst.m01 = m10;
  474. dst.m02 = m20;
  475. dst.m03 = -m03 * m00 - m13 * m10 - m23 * m20;
  476. dst.m10 = m01;
  477. dst.m11 = m11;
  478. dst.m12 = m21;
  479. dst.m13 = -m03 * m01 - m13 * m11 - m23 * m21;
  480. dst.m20 = m02;
  481. dst.m21 = m12;
  482. dst.m22 = m22;
  483. dst.m23 = -m03 * m02 - m13 * m12 - m23 * m22;
  484. return dst;
  485. }
  486. //! transforms a vector. the translation is not beeing considered
  487. ILINE Vec3_tpl<F> TransformVector(const Vec3_tpl<F>& v) const
  488. {
  489. assert(v.IsValid());
  490. return Vec3_tpl<F>(m00 * v.x + m01 * v.y + m02 * v.z, m10 * v.x + m11 * v.y + m12 * v.z, m20 * v.x + m21 * v.y + m22 * v.z);
  491. }
  492. //! transforms a point and add translation vector
  493. ILINE Vec3_tpl<F> TransformPoint(const Vec3_tpl<F>& p) const
  494. {
  495. assert(p.IsValid());
  496. return Vec3_tpl<F>(m00 * p.x + m01 * p.y + m02 * p.z + m03, m10 * p.x + m11 * p.y + m12 * p.z + m13, m20 * p.x + m21 * p.y + m22 * p.z + m23);
  497. }
  498. //! Remove scale from matrix.
  499. void OrthonormalizeFast()
  500. {
  501. Vec3_tpl<F> x(m00, m10, m20);
  502. Vec3_tpl<F> y(m01, m11, m21);
  503. Vec3_tpl<F> z;
  504. x = x.GetNormalized();
  505. z = (x % y).GetNormalized();
  506. y = (z % x).GetNormalized();
  507. m00 = x.x;
  508. m10 = x.y;
  509. m20 = x.z;
  510. m01 = y.x;
  511. m11 = y.y;
  512. m21 = y.z;
  513. m02 = z.x;
  514. m12 = z.y;
  515. m22 = z.z;
  516. }
  517. //--------------------------------------------------------------------------------
  518. //---- helper functions to access matrix-members ------------
  519. //--------------------------------------------------------------------------------
  520. F* GetData() { return &m00; }
  521. const F* GetData() const { return &m00; }
  522. ILINE F operator () (uint32 i, uint32 j) const { assert ((i < 3) && (j < 4)); F* p_data = (F*)(&m00); return p_data[i * 4 + j]; }
  523. ILINE F& operator () (uint32 i, uint32 j) { assert ((i < 3) && (j < 4)); F* p_data = (F*)(&m00); return p_data[i * 4 + j]; }
  524. ILINE void SetRow(int i, const Vec3_tpl<F>& v) { assert(i < 3); F* p = (F*)(&m00); p[0 + 4 * i] = v.x; p[1 + 4 * i] = v.y; p[2 + 4 * i] = v.z; }
  525. ILINE const Vec3_tpl<F>& GetRow(int i) const { assert(i < 3); return *(const Vec3_tpl<F>*)(&m00 + 4 * i); }
  526. ILINE const Vec4& GetRow4(int i) const { assert(i < 3); return *(const Vec4*)(&m00 + 4 * i); }
  527. ILINE Vec3_tpl<F> GetColumn0() const { return Vec3_tpl<F>(m00, m10, m20); }
  528. ILINE Vec3_tpl<F> GetColumn1() const { return Vec3_tpl<F>(m01, m11, m21); }
  529. ILINE Vec3_tpl<F> GetColumn2() const { return Vec3_tpl<F>(m02, m12, m22); }
  530. ILINE Vec3_tpl<F> GetColumn3() const { return Vec3_tpl<F>(m03, m13, m23); }
  531. ILINE void SetTranslation(const Vec3_tpl<F>& t) { m03 = t.x; m13 = t.y; m23 = t.z; }
  532. ILINE Vec3_tpl<F> GetTranslation() const { return Vec3_tpl<F>(m03, m13, m23); }
  533. ILINE void SetRotation33(const Matrix33_tpl<F>& m33)
  534. {
  535. m00 = m33.m00;
  536. m01 = m33.m01;
  537. m02 = m33.m02;
  538. m10 = m33.m10;
  539. m11 = m33.m11;
  540. m12 = m33.m12;
  541. m20 = m33.m20;
  542. m21 = m33.m21;
  543. m22 = m33.m22;
  544. }
  545. //check if we have an orthonormal-base (general case, works even with reflection matrices)
  546. int IsOrthonormal(F threshold = 0.001) const
  547. {
  548. f32 d0 = fabs_tpl(GetColumn0() | GetColumn1());
  549. if (d0 > threshold)
  550. {
  551. return 0;
  552. }
  553. f32 d1 = fabs_tpl(GetColumn0() | GetColumn2());
  554. if (d1 > threshold)
  555. {
  556. return 0;
  557. }
  558. f32 d2 = fabs_tpl(GetColumn1() | GetColumn2());
  559. if (d2 > threshold)
  560. {
  561. return 0;
  562. }
  563. int a = (fabs_tpl(1 - (GetColumn0() | GetColumn0()))) < threshold;
  564. int b = (fabs_tpl(1 - (GetColumn1() | GetColumn1()))) < threshold;
  565. int c = (fabs_tpl(1 - (GetColumn2() | GetColumn2()))) < threshold;
  566. return a & b & c;
  567. }
  568. //check if we have an orthonormal-base (assuming we are using a right-handed coordinate system)
  569. int IsOrthonormalRH(F threshold = 0.001) const
  570. {
  571. int a = Vec3_tpl<F>::IsEquivalent(GetColumn0(), GetColumn1() % GetColumn2(), threshold);
  572. int b = Vec3_tpl<F>::IsEquivalent(GetColumn1(), GetColumn2() % GetColumn0(), threshold);
  573. int c = Vec3_tpl<F>::IsEquivalent(GetColumn2(), GetColumn0() % GetColumn1(), threshold);
  574. return a & b & c;
  575. }
  576. bool static IsEquivalent(const Matrix34_tpl<F>& m0, const Matrix34_tpl<F>& m1, F e = VEC_EPSILON)
  577. {
  578. return (
  579. (fabs_tpl(m0.m00 - m1.m00) <= e) && (fabs_tpl(m0.m01 - m1.m01) <= e) && (fabs_tpl(m0.m02 - m1.m02) <= e) && (fabs_tpl(m0.m03 - m1.m03) <= e) &&
  580. (fabs_tpl(m0.m10 - m1.m10) <= e) && (fabs_tpl(m0.m11 - m1.m11) <= e) && (fabs_tpl(m0.m12 - m1.m12) <= e) && (fabs_tpl(m0.m13 - m1.m13) <= e) &&
  581. (fabs_tpl(m0.m20 - m1.m20) <= e) && (fabs_tpl(m0.m21 - m1.m21) <= e) && (fabs_tpl(m0.m22 - m1.m22) <= e) && (fabs_tpl(m0.m23 - m1.m23) <= e)
  582. );
  583. }
  584. bool IsValid() const
  585. {
  586. if (!NumberValid(m00))
  587. {
  588. return false;
  589. }
  590. if (!NumberValid(m01))
  591. {
  592. return false;
  593. }
  594. if (!NumberValid(m02))
  595. {
  596. return false;
  597. }
  598. if (!NumberValid(m03))
  599. {
  600. return false;
  601. }
  602. if (!NumberValid(m10))
  603. {
  604. return false;
  605. }
  606. if (!NumberValid(m11))
  607. {
  608. return false;
  609. }
  610. if (!NumberValid(m12))
  611. {
  612. return false;
  613. }
  614. if (!NumberValid(m13))
  615. {
  616. return false;
  617. }
  618. if (!NumberValid(m20))
  619. {
  620. return false;
  621. }
  622. if (!NumberValid(m21))
  623. {
  624. return false;
  625. }
  626. if (!NumberValid(m22))
  627. {
  628. return false;
  629. }
  630. if (!NumberValid(m23))
  631. {
  632. return false;
  633. }
  634. return true;
  635. }
  636. /*!
  637. * Create a matrix with SCALING, ROTATION and TRANSLATION (in this order).
  638. *
  639. * Example 1:
  640. * Matrix m34;
  641. * m34.SetMatrix( Vec3(1,2,3), quat, Vec3(11,22,33) );
  642. */
  643. ILINE void Set(const Vec3_tpl<F>& s, const Quat_tpl<F>& q, const Vec3_tpl<F>& t = Vec3(ZERO))
  644. {
  645. assert(s.IsValid());
  646. assert(q.IsUnit(0.1f));
  647. assert(t.IsValid());
  648. F vxvx = q.v.x * q.v.x;
  649. F vzvz = q.v.z * q.v.z;
  650. F vyvy = q.v.y * q.v.y;
  651. F vxvy = q.v.x * q.v.y;
  652. F vxvz = q.v.x * q.v.z;
  653. F vyvz = q.v.y * q.v.z;
  654. F svx = q.w * q.v.x;
  655. F svy = q.w * q.v.y;
  656. F svz = q.w * q.v.z;
  657. m00 = (1 - (vyvy + vzvz) * 2) * s.x;
  658. m01 = (vxvy - svz) * 2 * s.y;
  659. m02 = (vxvz + svy) * 2 * s.z;
  660. m03 = t.x;
  661. m10 = (vxvy + svz) * 2 * s.x;
  662. m11 = (1 - (vxvx + vzvz) * 2) * s.y;
  663. m12 = (vyvz - svx) * 2 * s.z;
  664. m13 = t.y;
  665. m20 = (vxvz - svy) * 2 * s.x;
  666. m21 = (vyvz + svx) * 2 * s.y;
  667. m22 = (1 - (vxvx + vyvy) * 2) * s.z;
  668. m23 = t.z;
  669. }
  670. ILINE static Matrix34_tpl<F> Create(const Vec3_tpl<F>& s, const Quat_tpl<F>& q, const Vec3_tpl<F>& t = Vec3(ZERO))
  671. {
  672. Matrix34_tpl<F> m34;
  673. m34.Set(s, q, t);
  674. return m34;
  675. }
  676. Matrix34_tpl(const Vec3_tpl<F>& s, const Quat_tpl<F>& q, const Vec3_tpl<F>& t = Vec3(ZERO))
  677. {
  678. Set(s, q, t);
  679. }
  680. /*!
  681. * Create scaling-matrix.
  682. * The translation-vector is set to zero.
  683. *
  684. * Example 1:
  685. * Matrix m34;
  686. * m34.SetScale( Vec3(0.5f, 1.0f, 2.0f) );
  687. */
  688. ILINE void SetScale(const Vec3_tpl<F>& s, const Vec3_tpl<F>& t = Vec3(ZERO))
  689. {
  690. *this = Matrix33::CreateScale(s);
  691. this->SetTranslation(t);
  692. }
  693. /*!
  694. * calculate a real inversion of a Matrix34
  695. * an inverse-matrix is an UnDo-matrix for all kind of transformations
  696. *
  697. * Example 1:
  698. * Matrix34 im34; im34.Invert();
  699. *
  700. * Example 2:
  701. * Matrix34 im34 = m34.GetInverted();
  702. */
  703. void Invert()
  704. {
  705. //rescue members
  706. Matrix34_tpl<F> m = *this;
  707. // calculate 12 cofactors
  708. m00 = m.m22 * m.m11 - m.m12 * m.m21;
  709. m10 = m.m12 * m.m20 - m.m22 * m.m10;
  710. m20 = m.m10 * m.m21 - m.m20 * m.m11;
  711. m01 = m.m02 * m.m21 - m.m22 * m.m01;
  712. m11 = m.m22 * m.m00 - m.m02 * m.m20;
  713. m21 = m.m20 * m.m01 - m.m00 * m.m21;
  714. m02 = m.m12 * m.m01 - m.m02 * m.m11;
  715. m12 = m.m02 * m.m10 - m.m12 * m.m00;
  716. m22 = m.m00 * m.m11 - m.m10 * m.m01;
  717. m03 = (m.m22 * m.m13 * m.m01 + m.m02 * m.m23 * m.m11 + m.m12 * m.m03 * m.m21) - (m.m12 * m.m23 * m.m01 + m.m22 * m.m03 * m.m11 + m.m02 * m.m13 * m.m21);
  718. m13 = (m.m12 * m.m23 * m.m00 + m.m22 * m.m03 * m.m10 + m.m02 * m.m13 * m.m20) - (m.m22 * m.m13 * m.m00 + m.m02 * m.m23 * m.m10 + m.m12 * m.m03 * m.m20);
  719. m23 = (m.m20 * m.m11 * m.m03 + m.m00 * m.m21 * m.m13 + m.m10 * m.m01 * m.m23) - (m.m10 * m.m21 * m.m03 + m.m20 * m.m01 * m.m13 + m.m00 * m.m11 * m.m23);
  720. // calculate determinant
  721. F det = m.m00 * m00 + m.m10 * m01 + m.m20 * m02;
  722. assert(fabs_tpl(det) > (F)0.00000001);
  723. F rcpDet = 1.0f / det;
  724. // calculate matrix inverse/
  725. m00 *= rcpDet;
  726. m01 *= rcpDet;
  727. m02 *= rcpDet;
  728. m03 *= rcpDet;
  729. m10 *= rcpDet;
  730. m11 *= rcpDet;
  731. m12 *= rcpDet;
  732. m13 *= rcpDet;
  733. m20 *= rcpDet;
  734. m21 *= rcpDet;
  735. m22 *= rcpDet;
  736. m23 *= rcpDet;
  737. }
  738. ILINE Matrix34_tpl<F> GetInverted() const
  739. {
  740. Matrix34_tpl<F> dst = *this;
  741. dst.Invert();
  742. return dst;
  743. }
  744. };
  745. ///////////////////////////////////////////////////////////////////////////////
  746. // Typedefs //
  747. ///////////////////////////////////////////////////////////////////////////////
  748. typedef Matrix34_tpl<f32> Matrix34; //always 32 bit
  749. //----------------------------------------------------------------------------------
  750. //----------------------------------------------------------------------------------
  751. //----------------------------------------------------------------------------------
  752. //------------- implementation of Matrix34 ------------------------------
  753. //----------------------------------------------------------------------------------
  754. //----------------------------------------------------------------------------------
  755. //----------------------------------------------------------------------------------
  756. //! multiply all matrix's values by f and return the matrix
  757. template<class F>
  758. ILINE Matrix34_tpl<F> operator * (const Matrix34_tpl<F>& m, const f32 f)
  759. {
  760. assert(m.IsValid());
  761. Matrix34_tpl<F> r;
  762. r.m00 = m.m00 * f;
  763. r.m01 = m.m01 * f;
  764. r.m02 = m.m02 * f;
  765. r.m03 = m.m03 * f;
  766. r.m10 = m.m10 * f;
  767. r.m11 = m.m11 * f;
  768. r.m12 = m.m12 * f;
  769. r.m13 = m.m13 * f;
  770. r.m20 = m.m20 * f;
  771. r.m21 = m.m21 * f;
  772. r.m22 = m.m22 * f;
  773. r.m23 = m.m23 * f;
  774. return r;
  775. }
  776. /*!
  777. * multiplication of Matrix34 by a (column) Vec3.
  778. * This function transforms the given input Vec3
  779. * into the coordinate system defined by this matrix.
  780. *
  781. * Example:
  782. * Matrix34 m34;
  783. * Vec3 vector(44,55,66);
  784. * Vec3 result = m34*vector;
  785. */
  786. template<class F>
  787. ILINE Vec3_tpl<F> operator * (const Matrix34_tpl<F>& m, const Vec3_tpl<F>& p)
  788. {
  789. assert(m.IsValid());
  790. assert(p.IsValid());
  791. Vec3_tpl<F> tp;
  792. tp.x = m.m00 * p.x + m.m01 * p.y + m.m02 * p.z + m.m03;
  793. tp.y = m.m10 * p.x + m.m11 * p.y + m.m12 * p.z + m.m13;
  794. tp.z = m.m20 * p.x + m.m21 * p.y + m.m22 * p.z + m.m23;
  795. return tp;
  796. }
  797. template<class F1, class F2>
  798. ILINE Matrix34_tpl<F1> operator + (const Matrix34_tpl<F1>& l, const Matrix34_tpl<F2>& r)
  799. {
  800. assert(l.IsValid());
  801. assert(r.IsValid());
  802. Matrix34_tpl<F1> m;
  803. m.m00 = l.m00 + r.m00;
  804. m.m01 = l.m01 + r.m01;
  805. m.m02 = l.m02 + r.m02;
  806. m.m03 = l.m03 + r.m03;
  807. m.m10 = l.m10 + r.m10;
  808. m.m11 = l.m11 + r.m11;
  809. m.m12 = l.m12 + r.m12;
  810. m.m13 = l.m13 + r.m13;
  811. m.m20 = l.m20 + r.m20;
  812. m.m21 = l.m21 + r.m21;
  813. m.m22 = l.m22 + r.m22;
  814. m.m23 = l.m23 + r.m23;
  815. return m;
  816. }
  817. template<class F1, class F2>
  818. ILINE Matrix34_tpl<F1>& operator += (Matrix34_tpl<F1>& l, const Matrix34_tpl<F2>& r)
  819. {
  820. assert(l.IsValid());
  821. assert(r.IsValid());
  822. l.m00 += r.m00;
  823. l.m01 += r.m01;
  824. l.m02 += r.m02;
  825. l.m03 += r.m03;
  826. l.m10 += r.m10;
  827. l.m11 += r.m11;
  828. l.m12 += r.m12;
  829. l.m13 += r.m13;
  830. l.m20 += r.m20;
  831. l.m21 += r.m21;
  832. l.m22 += r.m22;
  833. l.m23 += r.m23;
  834. return l;
  835. }
  836. /*!
  837. * Implements the multiplication operator: Matrix34=Matrix34*Matrix33
  838. *
  839. * Matrix33 and Matrix44 are specified in collumn order for a right-handed coordinate-system.
  840. * AxB = operation B followed by operation A.
  841. * A multiplication takes 27 muls and 24 adds.
  842. *
  843. * Example:
  844. * Matrix34 m34=Matrix33::CreateRotationX(1.94192f);;
  845. * Matrix33 m33=Matrix34::CreateRotationZ(3.14192f);
  846. * Matrix34 result=m34*m33;
  847. */
  848. template<class F>
  849. ILINE Matrix34_tpl<F> operator * (const Matrix34_tpl<F>& l, const Matrix33_tpl<F>& r)
  850. {
  851. assert(l.IsValid());
  852. assert(r.IsValid());
  853. Matrix34_tpl<F> m;
  854. m.m00 = l.m00 * r.m00 + l.m01 * r.m10 + l.m02 * r.m20;
  855. m.m10 = l.m10 * r.m00 + l.m11 * r.m10 + l.m12 * r.m20;
  856. m.m20 = l.m20 * r.m00 + l.m21 * r.m10 + l.m22 * r.m20;
  857. m.m01 = l.m00 * r.m01 + l.m01 * r.m11 + l.m02 * r.m21;
  858. m.m11 = l.m10 * r.m01 + l.m11 * r.m11 + l.m12 * r.m21;
  859. m.m21 = l.m20 * r.m01 + l.m21 * r.m11 + l.m22 * r.m21;
  860. m.m02 = l.m00 * r.m02 + l.m01 * r.m12 + l.m02 * r.m22;
  861. m.m12 = l.m10 * r.m02 + l.m11 * r.m12 + l.m12 * r.m22;
  862. m.m22 = l.m20 * r.m02 + l.m21 * r.m12 + l.m22 * r.m22;
  863. m.m03 = l.m03;
  864. m.m13 = l.m13;
  865. m.m23 = l.m23;
  866. return m;
  867. }
  868. /*!
  869. * Implements the multiplication operator: Matrix34=Matrix34*Matrix34
  870. *
  871. * Matrix34 is specified in collumn order.
  872. * AxB = rotation B followed by rotation A.
  873. * This operation takes 36 mults and 27 adds.
  874. *
  875. * Example:
  876. * Matrix34 m34=Matrix34::CreateRotationX(1.94192f, Vec3(11,22,33));;
  877. * Matrix34 m34=Matrix33::CreateRotationZ(3.14192f);
  878. * Matrix34 result=m34*m34;
  879. */
  880. template<class F>
  881. ILINE Matrix34_tpl<F> operator * (const Matrix34_tpl<F>& l, const Matrix34_tpl<F>& r)
  882. {
  883. assert(l.IsValid());
  884. assert(r.IsValid());
  885. Matrix34_tpl<F> m;
  886. m.m00 = l.m00 * r.m00 + l.m01 * r.m10 + l.m02 * r.m20;
  887. m.m10 = l.m10 * r.m00 + l.m11 * r.m10 + l.m12 * r.m20;
  888. m.m20 = l.m20 * r.m00 + l.m21 * r.m10 + l.m22 * r.m20;
  889. m.m01 = l.m00 * r.m01 + l.m01 * r.m11 + l.m02 * r.m21;
  890. m.m11 = l.m10 * r.m01 + l.m11 * r.m11 + l.m12 * r.m21;
  891. m.m21 = l.m20 * r.m01 + l.m21 * r.m11 + l.m22 * r.m21;
  892. m.m02 = l.m00 * r.m02 + l.m01 * r.m12 + l.m02 * r.m22;
  893. m.m12 = l.m10 * r.m02 + l.m11 * r.m12 + l.m12 * r.m22;
  894. m.m22 = l.m20 * r.m02 + l.m21 * r.m12 + l.m22 * r.m22;
  895. m.m03 = l.m00 * r.m03 + l.m01 * r.m13 + l.m02 * r.m23 + l.m03;
  896. m.m13 = l.m10 * r.m03 + l.m11 * r.m13 + l.m12 * r.m23 + l.m13;
  897. m.m23 = l.m20 * r.m03 + l.m21 * r.m13 + l.m22 * r.m23 + l.m23;
  898. return m;
  899. }
  900. /*!
  901. * Implements the multiplication operator: Matrix44=Matrix34*Matrix44
  902. *
  903. * Matrix44 and Matrix34 are specified in collumn order.
  904. * AxB = rotation B followed by rotation A.
  905. * This operation takes 48 mults and 36 adds.
  906. *
  907. * Example:
  908. * Matrix34 m34=Matrix33::CreateRotationX(1.94192f);;
  909. * Matrix44 m44=Matrix33::CreateRotationZ(3.14192f);
  910. * Matrix44 result=m34*m44;
  911. */
  912. template<class F>
  913. ILINE Matrix44_tpl<F> operator * (const Matrix34_tpl<F>& l, const Matrix44_tpl<F>& r)
  914. {
  915. assert(l.IsValid());
  916. assert(r.IsValid());
  917. Matrix44_tpl<F> m;
  918. m.m00 = l.m00 * r.m00 + l.m01 * r.m10 + l.m02 * r.m20 + l.m03 * r.m30;
  919. m.m10 = l.m10 * r.m00 + l.m11 * r.m10 + l.m12 * r.m20 + l.m13 * r.m30;
  920. m.m20 = l.m20 * r.m00 + l.m21 * r.m10 + l.m22 * r.m20 + l.m23 * r.m30;
  921. m.m30 = r.m30;
  922. m.m01 = l.m00 * r.m01 + l.m01 * r.m11 + l.m02 * r.m21 + l.m03 * r.m31;
  923. m.m11 = l.m10 * r.m01 + l.m11 * r.m11 + l.m12 * r.m21 + l.m13 * r.m31;
  924. m.m21 = l.m20 * r.m01 + l.m21 * r.m11 + l.m22 * r.m21 + l.m23 * r.m31;
  925. m.m31 = r.m31;
  926. m.m02 = l.m00 * r.m02 + l.m01 * r.m12 + l.m02 * r.m22 + l.m03 * r.m32;
  927. m.m12 = l.m10 * r.m02 + l.m11 * r.m12 + l.m12 * r.m22 + l.m13 * r.m32;
  928. m.m22 = l.m20 * r.m02 + l.m21 * r.m12 + l.m22 * r.m22 + l.m23 * r.m32;
  929. m.m32 = r.m32;
  930. m.m03 = l.m00 * r.m03 + l.m01 * r.m13 + l.m02 * r.m23 + l.m03 * r.m33;
  931. m.m13 = l.m10 * r.m03 + l.m11 * r.m13 + l.m12 * r.m23 + l.m13 * r.m33;
  932. m.m23 = l.m20 * r.m03 + l.m21 * r.m13 + l.m22 * r.m23 + l.m23 * r.m33;
  933. m.m33 = r.m33;
  934. return m;
  935. }