Cry_Matrix33.h 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230
  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 Matrix33_tpl
  14. ///////////////////////////////////////////////////////////////////////////////
  15. ///////////////////////////////////////////////////////////////////////////////
  16. ///////////////////////////////////////////////////////////////////////////////
  17. template<typename F>
  18. struct Matrix33_tpl
  19. {
  20. F m00, m01, m02;
  21. F m10, m11, m12;
  22. F m20, m21, m22;
  23. //---------------------------------------------------------------------------------
  24. #ifdef _DEBUG
  25. ILINE Matrix33_tpl()
  26. {
  27. if constexpr (sizeof(F) == 4)
  28. {
  29. uint32* p = alias_cast<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. }
  40. if constexpr (sizeof(F) == 8)
  41. {
  42. uint64* p = alias_cast<uint64*>(&m00);
  43. p[0] = F64NAN;
  44. p[1] = F64NAN;
  45. p[2] = F64NAN;
  46. p[3] = F64NAN;
  47. p[4] = F64NAN;
  48. p[5] = F64NAN;
  49. p[6] = F64NAN;
  50. p[7] = F64NAN;
  51. p[8] = F64NAN;
  52. }
  53. }
  54. #else
  55. ILINE Matrix33_tpl(){};
  56. #endif
  57. //set matrix to Identity
  58. ILINE Matrix33_tpl(type_identity)
  59. {
  60. m00 = 1;
  61. m01 = 0;
  62. m02 = 0;
  63. m10 = 0;
  64. m11 = 1;
  65. m12 = 0;
  66. m20 = 0;
  67. m21 = 0;
  68. m22 = 1;
  69. }
  70. //ASSIGNMENT OPERATOR of identical Matrix33 types.
  71. //The assignment operator has precedence over assignment constructor
  72. //Matrix33 m; m=m33;
  73. ILINE Matrix33_tpl<F>& operator = (const Matrix33_tpl<F>& m)
  74. {
  75. assert(m.IsValid());
  76. m00 = m.m00;
  77. m01 = m.m01;
  78. m02 = m.m02;
  79. m10 = m.m10;
  80. m11 = m.m11;
  81. m12 = m.m12;
  82. m20 = m.m20;
  83. m21 = m.m21;
  84. m22 = m.m22;
  85. return *this;
  86. }
  87. //--------------------------------------------------------------------
  88. //---- implementation of the constructors ---
  89. //--------------------------------------------------------------------
  90. //CONSTRUCTOR for identical float-types. It initializes a Matrix33 with 9 floats.
  91. //Matrix33(0,1,2, 3,4,5, 6,7,8);
  92. explicit ILINE Matrix33_tpl(F x00, F x01, F x02, F x10, F x11, F x12, F x20, F x21, F x22)
  93. {
  94. m00 = x00;
  95. m01 = x01;
  96. m02 = x02;
  97. m10 = x10;
  98. m11 = x11;
  99. m12 = x12;
  100. m20 = x20;
  101. m21 = x21;
  102. m22 = x22;
  103. }
  104. //CONSTRUCTOR for identical float-types. It initializes a Matrix33 with 3 vectors stored in the columns.
  105. //Matrix33(v0,v1,v2);
  106. explicit ILINE Matrix33_tpl(const Vec3_tpl<F>&vx, const Vec3_tpl<F>&vy, const Vec3_tpl<F>&vz)
  107. {
  108. m00 = vx.x;
  109. m01 = vy.x;
  110. m02 = vz.x;
  111. m10 = vx.y;
  112. m11 = vy.y;
  113. m12 = vz.y;
  114. m20 = vx.z;
  115. m21 = vy.z;
  116. m22 = vz.z;
  117. }
  118. //CONSTRUCTOR for different float-types. It initializes a Matrix33 with 3 vectors stored in the columns and converts between floats/doubles.
  119. //Matrix33r(v0,v1,v2);
  120. template<class F1>
  121. explicit ILINE Matrix33_tpl(const Vec3_tpl<F1>&vx, const Vec3_tpl<F1>&vy, const Vec3_tpl<F1>&vz)
  122. {
  123. m00 = F(vx.x);
  124. m01 = F(vy.x);
  125. m02 = F(vz.x);
  126. m10 = F(vx.y);
  127. m11 = F(vy.y);
  128. m12 = F(vz.y);
  129. m20 = F(vx.z);
  130. m21 = F(vy.z);
  131. m22 = F(vz.z);
  132. }
  133. //CONSTRUCTOR for identical float-types
  134. //Matrix33 m=m33;
  135. ILINE Matrix33_tpl<F>(const Matrix33_tpl<F>&m)
  136. {
  137. assert(m.IsValid());
  138. m00 = m.m00;
  139. m01 = m.m01;
  140. m02 = m.m02;
  141. m10 = m.m10;
  142. m11 = m.m11;
  143. m12 = m.m12;
  144. m20 = m.m20;
  145. m21 = m.m21;
  146. m22 = m.m22;
  147. }
  148. //CONSTRUCTOR for different float-types which converts between double/float
  149. //Matrix33 m=m33r;
  150. template<class F1>
  151. ILINE Matrix33_tpl<F>(const Matrix33_tpl<F1>&m)
  152. {
  153. assert(m.IsValid());
  154. m00 = F(m.m00);
  155. m01 = F(m.m01);
  156. m02 = F(m.m02);
  157. m10 = F(m.m10);
  158. m11 = F(m.m11);
  159. m12 = F(m.m12);
  160. m20 = F(m.m20);
  161. m21 = F(m.m21);
  162. m22 = F(m.m22);
  163. }
  164. //CONSTRUCTOR for identical float-types. It converts a Matrix34 into a Matrix33.
  165. //Needs to be 'explicit' because we loose the translation vector in the conversion process
  166. //Matrix33(m34);
  167. explicit ILINE Matrix33_tpl<F>(const Matrix34_tpl<F>&m)
  168. {
  169. assert(m.IsValid());
  170. m00 = m.m00;
  171. m01 = m.m01;
  172. m02 = m.m02;
  173. m10 = m.m10;
  174. m11 = m.m11;
  175. m12 = m.m12;
  176. m20 = m.m20;
  177. m21 = m.m21;
  178. m22 = m.m22;
  179. }
  180. //CONSTRUCTOR for different float-types. It converts a Matrix34 into a Matrix33 and converts between double/float.
  181. //Needs to be 'explicit' because we loose the translation vector in the conversion process
  182. //Matrix33(m34r);
  183. template<class F1>
  184. explicit ILINE Matrix33_tpl<F>(const Matrix34_tpl<F1>&m)
  185. {
  186. assert(m.IsValid());
  187. m00 = F(m.m00);
  188. m01 = F(m.m01);
  189. m02 = F(m.m02);
  190. m10 = F(m.m10);
  191. m11 = F(m.m11);
  192. m12 = F(m.m12);
  193. m20 = F(m.m20);
  194. m21 = F(m.m21);
  195. m22 = F(m.m22);
  196. }
  197. //CONSTRUCTOR for identical float-types. It converts a Matrix44 into a Matrix33.
  198. //Needs to be 'explicit' because we loose the translation vector and the 3rd row in the conversion process
  199. //Matrix33(m44);
  200. explicit ILINE Matrix33_tpl<F>(const Matrix44_tpl<F>&m)
  201. {
  202. assert(m.IsValid());
  203. m00 = m.m00;
  204. m01 = m.m01;
  205. m02 = m.m02;
  206. m10 = m.m10;
  207. m11 = m.m11;
  208. m12 = m.m12;
  209. m20 = m.m20;
  210. m21 = m.m21;
  211. m22 = m.m22;
  212. }
  213. //CONSTRUCTOR for different float-types. It converts a Matrix44 into a Matrix33 and converts between double/float.
  214. //Needs to be 'explicit' because we loose the translation vector and the 3rd row in the conversion process
  215. //Matrix33(m44r);
  216. template<class F1>
  217. explicit ILINE Matrix33_tpl<F>(const Matrix44_tpl<F1>&m)
  218. {
  219. assert(m.IsValid());
  220. m00 = F(m.m00);
  221. m01 = F(m.m01);
  222. m02 = F(m.m02);
  223. m10 = F(m.m10);
  224. m11 = F(m.m11);
  225. m12 = F(m.m12);
  226. m20 = F(m.m20);
  227. m21 = F(m.m21);
  228. m22 = F(m.m22);
  229. }
  230. //CONSTRUCTOR for identical float-types. It converts a Quat into a Matrix33.
  231. //Needs to be 'explicit' because we loose fp-precision in the conversion process
  232. //Matrix33(quat);
  233. explicit ILINE Matrix33_tpl<F>(const Quat_tpl<F>&q)
  234. {
  235. assert(q.IsValid(0.05f));
  236. Vec3_tpl<F> v2 = q.v + q.v;
  237. F xx = 1 - v2.x * q.v.x;
  238. F yy = v2.y * q.v.y;
  239. F xw = v2.x * q.w;
  240. F xy = v2.y * q.v.x;
  241. F yz = v2.z * q.v.y;
  242. F yw = v2.y * q.w;
  243. F xz = v2.z * q.v.x;
  244. F zz = v2.z * q.v.z;
  245. F zw = v2.z * q.w;
  246. m00 = 1 - yy - zz;
  247. m01 = xy - zw;
  248. m02 = xz + yw;
  249. m10 = xy + zw;
  250. m11 = xx - zz;
  251. m12 = yz - xw;
  252. m20 = xz - yw;
  253. m21 = yz + xw;
  254. m22 = xx - yy;
  255. }
  256. //CONSTRUCTOR for different float-types. It converts a Quat into a Matrix33 and converts between double/float.
  257. //Needs to be 'explicit' because we loose fp-precision in the conversion process
  258. //Matrix33(quatr);
  259. template<class F1>
  260. explicit ILINE Matrix33_tpl<F>(const Quat_tpl<F1>&q)
  261. {
  262. assert(q.IsValid(0.05f));
  263. Vec3_tpl<F1> v2 = q.v + q.v;
  264. F1 xx = 1 - v2.x * q.v.x;
  265. F1 yy = v2.y * q.v.y;
  266. F1 xw = v2.x * q.w;
  267. F1 xy = v2.y * q.v.x;
  268. F1 yz = v2.z * q.v.y;
  269. F1 yw = v2.y * q.w;
  270. F1 xz = v2.z * q.v.x;
  271. F1 zz = v2.z * q.v.z;
  272. F1 zw = v2.z * q.w;
  273. m00 = F(1 - yy - zz);
  274. m01 = F(xy - zw);
  275. m02 = F(xz + yw);
  276. m10 = F(xy + zw);
  277. m11 = F(xx - zz);
  278. m12 = F(yz - xw);
  279. m20 = F(xz - yw);
  280. m21 = F(yz + xw);
  281. m22 = F(xx - yy);
  282. }
  283. //CONSTRUCTOR for identical float-types. It converts a Euler Angle into a Matrix33.
  284. //Needs to be 'explicit' because we loose fp-precision in the conversion process
  285. //Matrix33(Ang3(1,2,3));
  286. explicit ILINE Matrix33_tpl<F>(const Ang3_tpl<F>&ang)
  287. {
  288. assert(ang.IsValid());
  289. SetRotationXYZ(ang);
  290. }
  291. //CONSTRUCTOR for different float-types. It converts a Euler Angle into a Matrix33 and converts between double/float. .
  292. //Needs to be 'explicit' because we loose fp-precision in the conversion process
  293. //Matrix33(Ang3r(1,2,3));
  294. template<class F1>
  295. explicit ILINE Matrix33_tpl<F>(const Ang3_tpl<F1>&ang)
  296. {
  297. assert(ang.IsValid());
  298. SetRotationXYZ(Ang3_tpl<F>(F(ang.x), F(ang.y), F(ang.z)));
  299. }
  300. //---------------------------------------------------------------------------------------
  301. ILINE void SetIdentity(void)
  302. {
  303. m00 = 1;
  304. m01 = 0;
  305. m02 = 0;
  306. m10 = 0;
  307. m11 = 1;
  308. m12 = 0;
  309. m20 = 0;
  310. m21 = 0;
  311. m22 = 1;
  312. }
  313. /*!
  314. * Create a rotation matrix around an arbitrary axis (Eulers Theorem).
  315. * The axis is specified as a normalized Vec3. The angle is assumed to be in radians.
  316. *
  317. * Example:
  318. * Matrix34 m34;
  319. * Vec3 axis=GetNormalized( Vec3(-1.0f,-0.3f,0.0f) );
  320. * m34.SetRotationAA( rad, axis );
  321. */
  322. ILINE void SetRotationAA(F angle, const Vec3_tpl<F> axis)
  323. {
  324. F s, c;
  325. sincos_tpl(angle, &s, &c);
  326. SetRotationAA(c, s, axis);
  327. }
  328. ILINE static Matrix33_tpl<F> CreateRotationAA(const F rad, const Vec3_tpl<F>& axis)
  329. {
  330. Matrix33_tpl<F> m33;
  331. m33.SetRotationAA(rad, axis);
  332. return m33;
  333. }
  334. ILINE void SetRotationAA(F c, F s, const Vec3_tpl<F>& axis)
  335. {
  336. assert(axis.IsUnit(0.001f));
  337. F mc = 1 - c;
  338. m00 = mc * axis.x * axis.x + c;
  339. m01 = mc * axis.x * axis.y - axis.z * s;
  340. m02 = mc * axis.x * axis.z + axis.y * s;
  341. m10 = mc * axis.y * axis.x + axis.z * s;
  342. m11 = mc * axis.y * axis.y + c;
  343. m12 = mc * axis.y * axis.z - axis.x * s;
  344. m20 = mc * axis.z * axis.x - axis.y * s;
  345. m21 = mc * axis.z * axis.y + axis.x * s;
  346. m22 = mc * axis.z * axis.z + c;
  347. }
  348. ILINE static Matrix33_tpl<F> CreateRotationAA(F c, F s, const Vec3_tpl<F>& axis)
  349. {
  350. Matrix33_tpl<F> m33;
  351. m33.SetRotationAA(c, s, axis);
  352. return m33;
  353. }
  354. ILINE void SetRotationAA(const Vec3_tpl<F> axis)
  355. {
  356. F angle = axis.GetLength();
  357. if (angle == F(0))
  358. {
  359. SetIdentity();
  360. }
  361. else
  362. {
  363. SetRotationAA(angle, axis / angle);
  364. }
  365. }
  366. ILINE static Matrix33_tpl<F> CreateRotationAA(const Vec3_tpl<F>& axis)
  367. {
  368. Matrix33_tpl<F> m33;
  369. m33.SetRotationAA(axis);
  370. return m33;
  371. }
  372. /*!
  373. *
  374. * Create rotation-matrix about X axis using an angle.
  375. * The angle is assumed to be in radians.
  376. *
  377. * Example:
  378. * Matrix m33;
  379. * m33.SetRotationX(0.5f);
  380. */
  381. ILINE void SetRotationX(const f32 rad)
  382. {
  383. F s, c;
  384. sincos_tpl(rad, &s, &c);
  385. m00 = 1.0f;
  386. m01 = 0.0f;
  387. m02 = 0.0f;
  388. m10 = 0.0f;
  389. m11 = c;
  390. m12 = -s;
  391. m20 = 0.0f;
  392. m21 = s;
  393. m22 = c;
  394. }
  395. ILINE static Matrix33_tpl<F> CreateRotationX(const f32 rad)
  396. {
  397. Matrix33_tpl<F> m33;
  398. m33.SetRotationX(rad);
  399. return m33;
  400. }
  401. ILINE void SetRotationY(const f32 rad)
  402. {
  403. F s, c;
  404. sincos_tpl(rad, &s, &c);
  405. m00 = c;
  406. m01 = 0;
  407. m02 = s;
  408. m10 = 0;
  409. m11 = 1;
  410. m12 = 0;
  411. m20 = -s;
  412. m21 = 0;
  413. m22 = c;
  414. }
  415. ILINE static Matrix33_tpl<F> CreateRotationY(const f32 rad)
  416. {
  417. Matrix33_tpl<F> m33;
  418. m33.SetRotationY(rad);
  419. return m33;
  420. }
  421. ILINE void SetRotationZ(const f32 rad)
  422. {
  423. F s, c;
  424. sincos_tpl(rad, &s, &c);
  425. m00 = c;
  426. m01 = -s;
  427. m02 = 0.0f;
  428. m10 = s;
  429. m11 = c;
  430. m12 = 0.0f;
  431. m20 = 0.0f;
  432. m21 = 0.0f;
  433. m22 = 1.0f;
  434. }
  435. ILINE static Matrix33_tpl<F> CreateRotationZ(const f32 rad)
  436. {
  437. Matrix33_tpl<F> m33;
  438. m33.SetRotationZ(rad);
  439. return m33;
  440. }
  441. ILINE void SetRotationXYZ(const Ang3_tpl<F>& rad)
  442. {
  443. assert(rad.IsValid());
  444. F sx, cx;
  445. sincos_tpl(rad.x, &sx, &cx);
  446. F sy, cy;
  447. sincos_tpl(rad.y, &sy, &cy);
  448. F sz, cz;
  449. sincos_tpl(rad.z, &sz, &cz);
  450. F sycz = (sy * cz), sysz = (sy * sz);
  451. m00 = cy * cz;
  452. m01 = sycz * sx - cx * sz;
  453. m02 = sycz * cx + sx * sz;
  454. m10 = cy * sz;
  455. m11 = sysz * sx + cx * cz;
  456. m12 = sysz * cx - sx * cz;
  457. m20 = -sy;
  458. m21 = cy * sx;
  459. m22 = cy * cx;
  460. }
  461. ILINE static Matrix33_tpl<F> CreateRotationXYZ(const Ang3_tpl<F>& rad)
  462. {
  463. assert(rad.IsValid());
  464. Matrix33_tpl<F> m33;
  465. m33.SetRotationXYZ(rad);
  466. return m33;
  467. }
  468. /*!
  469. * Creates a rotation matrix that rotates the vector "v0" into "v1".
  470. *
  471. * a) If both vectors are exactly parallel it returns an identity-matrix
  472. * b) CAUTION: If both vectors are exactly diametrical it returns a matrix that rotates
  473. * pi-radians about a "random" axis that is orthogonal to v0.
  474. * c) CAUTION: If both vectors are almost diametrical we have to normalize
  475. * a very small vector and the result is inaccurate. It is recommended to use this
  476. * function with 64-bit precision.
  477. */
  478. ILINE void SetRotationV0V1(const Vec3_tpl<F>& v0, const Vec3_tpl<F>& v1)
  479. {
  480. assert((fabs_tpl(1 - (v0 | v0))) < 0.01); //check if unit-vector
  481. assert((fabs_tpl(1 - (v1 | v1))) < 0.01); //check if unit-vector
  482. F dot = v0 | v1;
  483. if (dot < F(-0.9999f))
  484. {
  485. Vec3_tpl<F> axis = v0.GetOrthogonal().GetNormalized();
  486. m00 = F(2 * axis.x * axis.x - 1);
  487. m01 = F(2 * axis.x * axis.y);
  488. m02 = F(2 * axis.x * axis.z);
  489. m10 = F(2 * axis.y * axis.x);
  490. m11 = F(2 * axis.y * axis.y - 1);
  491. m12 = F(2 * axis.y * axis.z);
  492. m20 = F(2 * axis.z * axis.x);
  493. m21 = F(2 * axis.z * axis.y);
  494. m22 = F(2 * axis.z * axis.z - 1);
  495. }
  496. else
  497. {
  498. Vec3_tpl<F> v = v0 % v1;
  499. F h = 1 / (1 + dot);
  500. m00 = F(dot + h * v.x * v.x);
  501. m01 = F(h * v.x * v.y - v.z);
  502. m02 = F(h * v.x * v.z + v.y);
  503. m10 = F(h * v.x * v.y + v.z);
  504. m11 = F(dot + h * v.y * v.y);
  505. m12 = F(h * v.y * v.z - v.x);
  506. m20 = F(h * v.x * v.z - v.y);
  507. m21 = F(h * v.y * v.z + v.x);
  508. m22 = F(dot + h * v.z * v.z);
  509. }
  510. }
  511. ILINE static Matrix33_tpl<F> CreateRotationV0V1(const Vec3_tpl<F>& v0, const Vec3_tpl<F>& v1)
  512. {
  513. Matrix33_tpl<F> m33;
  514. m33.SetRotationV0V1(v0, v1);
  515. return m33;
  516. }
  517. /*!
  518. *
  519. * \param vdir normalized view direction.
  520. * \param roll radiant to rotate about Y-axis.
  521. *
  522. * Given a view-direction and a radiant to rotate about Y-axis, this function builds a 3x3 look-at matrix
  523. * using only simple vector arithmetic. This function is always using the implicit up-vector Vec3(0,0,1).
  524. * The view-direction is always stored in column(1).
  525. * IMPORTANT: The view-vector is assumed to be normalized, because all trig-values for the orientation are being
  526. * extracted directly out of the vector. This function must NOT be called with a view-direction
  527. * that is close to Vec3(0,0,1) or Vec3(0,0,-1). If one of these rules is broken, the function returns a matrix
  528. * with an undefined rotation about the Z-axis.
  529. *
  530. * Rotation order for the look-at-matrix is Z-X-Y. (Zaxis=YAW / Xaxis=PITCH / Yaxis=ROLL)
  531. *
  532. * COORDINATE-SYSTEM
  533. *
  534. * z-axis
  535. * ^
  536. * |
  537. * | y-axis
  538. * | /
  539. * | /
  540. * |/
  541. * +---------------> x-axis
  542. *
  543. * Example:
  544. * Matrix33 orientation=Matrix33::CreateRotationVDir( Vec3(0,1,0), 0 );
  545. */
  546. ILINE void SetRotationVDir(const Vec3_tpl<F>& vdir)
  547. {
  548. assert((fabs_tpl(1 - (vdir | vdir))) < 0.01); //check if unit-vector
  549. //set default initialisation for up-vector
  550. m00 = 1;
  551. m01 = 0;
  552. m02 = 0;
  553. m10 = 0;
  554. m11 = 0;
  555. m12 = -vdir.z;
  556. m20 = 0;
  557. m21 = vdir.z;
  558. m22 = 0;
  559. //calculate look-at matrix
  560. F l = sqrt(vdir.x * vdir.x + vdir.y * vdir.y);
  561. if (l > F(0.00001))
  562. {
  563. F xl = -vdir.x / l;
  564. F yl = vdir.y / l;
  565. m00 = F(yl);
  566. m01 = F(vdir.x);
  567. m02 = F(xl * vdir.z);
  568. m10 = F(xl);
  569. m11 = F(vdir.y);
  570. m12 = F(-vdir.z * yl);
  571. m20 = 0;
  572. m21 = F(vdir.z);
  573. m22 = F(l);
  574. }
  575. }
  576. ILINE static Matrix33_tpl<F> CreateRotationVDir(const Vec3_tpl<F> vdir)
  577. {
  578. Matrix33_tpl<F> m33;
  579. m33.SetRotationVDir(vdir);
  580. return m33;
  581. }
  582. //look-at matrix with roll
  583. ILINE void SetRotationVDir(const Vec3_tpl<F>& vdir, F roll)
  584. {
  585. SetRotationVDir(vdir);
  586. F s, c;
  587. sincos_tpl(roll, &s, &c);
  588. F x00 = m00, x10 = m10;
  589. m00 = m00 * c - m02 * s;
  590. m02 = x00 * s + m02 * c;
  591. m10 = m10 * c - m12 * s;
  592. m12 = x10 * s + m12 * c;
  593. m20 = -m22 * s;
  594. m22 = m22 * c;
  595. }
  596. ILINE static Matrix33_tpl<F> CreateRotationVDir(const Vec3_tpl<F>& vdir, F roll)
  597. {
  598. Matrix33_tpl<F> m33;
  599. m33.SetRotationVDir(vdir, roll);
  600. return m33;
  601. }
  602. //////////////////////////////////////////////////////////////////////////
  603. ILINE static Matrix33_tpl<F> CreateOrientation(const Vec3_tpl<F>& dir, const Vec3_tpl<F>& up, float rollAngle)
  604. {
  605. // LookAt transform.
  606. Vec3 xAxis, yAxis, zAxis;
  607. Vec3 upVector = up;
  608. if (dir.IsZeroFast())
  609. {
  610. Matrix33_tpl<F> tm;
  611. tm.SetIdentity();
  612. return tm;
  613. }
  614. yAxis = dir.GetNormalized();
  615. if (yAxis.x == 0 && yAxis.y == 0 && up.IsEquivalent(Vec3_tpl<F>(0, 0, 1.0f)))
  616. {
  617. upVector.Set(-yAxis.z, 0, 0);
  618. }
  619. xAxis = (upVector % yAxis).GetNormalized();
  620. zAxis = (xAxis % yAxis).GetNormalized();
  621. Matrix33_tpl<F> tm;
  622. tm.SetFromVectors(xAxis, yAxis, zAxis);
  623. if (rollAngle != 0)
  624. {
  625. Matrix33_tpl<F> RollMtx;
  626. RollMtx.SetRotationY(rollAngle);
  627. tm = tm * RollMtx;
  628. }
  629. return tm;
  630. }
  631. ILINE void SetScale(const Vec3_tpl<F>& s)
  632. {
  633. m00 = s.x;
  634. m01 = 0;
  635. m02 = 0;
  636. m10 = 0;
  637. m11 = s.y;
  638. m12 = 0;
  639. m20 = 0;
  640. m21 = 0;
  641. m22 = s.z;
  642. }
  643. ILINE static Matrix33_tpl<F> CreateScale(const Vec3_tpl<F>& s) { Matrix33_tpl<F> m; m.SetScale(s); return m; }
  644. //NOTE: all vectors are stored in columns
  645. ILINE void SetFromVectors(const Vec3_tpl<F>& vx, const Vec3_tpl<F>& vy, const Vec3_tpl<F>& vz)
  646. {
  647. m00 = vx.x;
  648. m01 = vy.x;
  649. m02 = vz.x;
  650. m10 = vx.y;
  651. m11 = vy.y;
  652. m12 = vz.y;
  653. m20 = vx.z;
  654. m21 = vy.z;
  655. m22 = vz.z;
  656. }
  657. ILINE static Matrix33_tpl<F> CreateFromVectors(const Vec3_tpl<F>& vx, const Vec3_tpl<F>& vy, const Vec3_tpl<F>& vz) { Matrix33_tpl<F> dst; dst.SetFromVectors(vx, vy, vz); return dst; }
  658. ILINE void Transpose() // in-place transposition
  659. {
  660. F t;
  661. t = m01;
  662. m01 = m10;
  663. m10 = t;
  664. t = m02;
  665. m02 = m20;
  666. m20 = t;
  667. t = m12;
  668. m12 = m21;
  669. m21 = t;
  670. }
  671. /*!
  672. *
  673. * calculate a real inversion of a Matrix33.
  674. * an inverse-matrix is an UnDo-matrix for all kind of transformations
  675. * NOTE: if the return value of Invert33() is zero, then the inversion failed!
  676. *
  677. * Example 1:
  678. * Matrix33 im33;
  679. * bool st=i33.Invert();
  680. * assert(st);
  681. *
  682. * Example 2:
  683. * matrix33 im33=Matrix33::GetInverted(m33);
  684. */
  685. ILINE bool Invert(void)
  686. {
  687. //rescue members
  688. Matrix33_tpl<F> m = *this;
  689. //calculate the cofactor-matrix (=transposed adjoint-matrix)
  690. m00 = m.m22 * m.m11 - m.m12 * m.m21;
  691. m01 = m.m02 * m.m21 - m.m22 * m.m01;
  692. m02 = m.m12 * m.m01 - m.m02 * m.m11;
  693. m10 = m.m12 * m.m20 - m.m22 * m.m10;
  694. m11 = m.m22 * m.m00 - m.m02 * m.m20;
  695. m12 = m.m02 * m.m10 - m.m12 * m.m00;
  696. m20 = m.m10 * m.m21 - m.m20 * m.m11;
  697. m21 = m.m20 * m.m01 - m.m00 * m.m21;
  698. m22 = m.m00 * m.m11 - m.m10 * m.m01;
  699. // calculate determinant
  700. F det = (m.m00 * m00 + m.m10 * m01 + m.m20 * m02);
  701. if (fabs_tpl(det) < 1E-20f)
  702. {
  703. return 0;
  704. }
  705. //divide the cofactor-matrix by the determinant
  706. F idet = (F)1.0 / det;
  707. m00 *= idet;
  708. m01 *= idet;
  709. m02 *= idet;
  710. m10 *= idet;
  711. m11 *= idet;
  712. m12 *= idet;
  713. m20 *= idet;
  714. m21 *= idet;
  715. m22 *= idet;
  716. return 1;
  717. }
  718. ILINE Matrix33_tpl<F> GetInverted() const
  719. {
  720. Matrix33_tpl<F> dst = *this;
  721. dst.Invert();
  722. return dst;
  723. }
  724. ILINE Vec3_tpl<F> TransformVector(const Vec3_tpl<F>& v) const
  725. {
  726. 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);
  727. }
  728. //! make a right-handed orthonormal matrix.
  729. ILINE void OrthonormalizeFast()
  730. {
  731. Vec3 x = Vec3(m00, m10, m20).GetNormalized();
  732. Vec3 y = (Vec3(m02, m12, m22) % x).GetNormalized();
  733. Vec3 z = (x % y);
  734. m00 = x.x;
  735. m01 = y.x;
  736. m02 = z.x;
  737. m10 = x.y;
  738. m11 = y.y;
  739. m12 = z.y;
  740. m20 = x.z;
  741. m21 = y.z;
  742. m22 = z.z;
  743. }
  744. ILINE f32 Determinant() const
  745. {
  746. return (m00 * m11 * m22) + (m01 * m12 * m20) + (m02 * m10 * m21) - (m02 * m11 * m20) - (m00 * m12 * m21) - (m01 * m10 * m22);
  747. }
  748. //--------------------------------------------------------------------------------
  749. //---- helper functions to access matrix-members ------------
  750. //--------------------------------------------------------------------------------
  751. F* GetData() { return &m00; }
  752. const F* GetData() const { return &m00; }
  753. ILINE F operator () (uint32 i, uint32 j) const { assert ((i < 3) && (j < 3)); const F* const p_data = (const F*)(&m00); return p_data[i * 3 + j]; }
  754. ILINE F& operator () (uint32 i, uint32 j) { assert ((i < 3) && (j < 3)); F* p_data = (F*)(&m00); return p_data[i * 3 + j]; }
  755. ILINE void SetRow(int i, const Vec3_tpl<F>& v) { assert(i < 3); F* p = (F*)(&m00); p[0 + 3 * i] = v.x; p[1 + 3 * i] = v.y; p[2 + 3 * i] = v.z; }
  756. ILINE Vec3_tpl<F> GetRow(int i) const { assert(i < 3); const F* const p = (const F*)(&m00); return Vec3_tpl<F>(p[0 + 3 * i], p[1 + 3 * i], p[2 + 3 * i]); }
  757. ILINE void SetColumn(int i, const Vec3_tpl<F>& v) { assert(i < 3); F* p = (F*)(&m00); p[i + 3 * 0] = v.x; p[i + 3 * 1] = v.y; p[i + 3 * 2] = v.z; }
  758. ILINE Vec3_tpl<F> GetColumn(int i) const { assert(i < 3); const F* const p = (const F*)(&m00); return Vec3_tpl<F>(p[i + 3 * 0], p[i + 3 * 1], p[i + 3 * 2]); }
  759. ILINE Vec3_tpl<F> GetColumn0() const { return Vec3_tpl<F> (m00, m10, m20); }
  760. ILINE Vec3_tpl<F> GetColumn1() const { return Vec3_tpl<F> (m01, m11, m21); }
  761. ILINE Vec3_tpl<F> GetColumn2() const { return Vec3_tpl<F> (m02, m12, m22); }
  762. ILINE void SetColumn0(const Vec3_tpl<F>& v) { m00 = v.x; m10 = v.y; m20 = v.z; }
  763. ILINE void SetColumn1(const Vec3_tpl<F>& v) { m01 = v.x; m11 = v.y; m21 = v.z; }
  764. ILINE void SetColumn2(const Vec3_tpl<F>& v) { m02 = v.x; m12 = v.y; m22 = v.z; }
  765. ILINE Matrix33_tpl<F>& operator *= (F op)
  766. {
  767. m00 *= op;
  768. m01 *= op;
  769. m02 *= op;
  770. m10 *= op;
  771. m11 *= op;
  772. m12 *= op;
  773. m20 *= op;
  774. m21 *= op;
  775. m22 *= op;
  776. return *this;
  777. }
  778. ILINE Matrix33_tpl<F>& operator /= (F op)
  779. {
  780. F iop = (F)1.0 / op;
  781. m00 *= iop;
  782. m01 *= iop;
  783. m02 *= iop;
  784. m10 *= iop;
  785. m11 *= iop;
  786. m12 *= iop;
  787. m20 *= iop;
  788. m21 *= iop;
  789. m22 *= iop;
  790. return *this;
  791. }
  792. ILINE static bool IsEquivalent(const Matrix33_tpl<F>& m0, const Matrix33_tpl<F>& m1, F e = VEC_EPSILON)
  793. {
  794. return (
  795. (fabs_tpl(m0.m00 - m1.m00) <= e) && (fabs_tpl(m0.m01 - m1.m01) <= e) && (fabs_tpl(m0.m02 - m1.m02) <= e) &&
  796. (fabs_tpl(m0.m10 - m1.m10) <= e) && (fabs_tpl(m0.m11 - m1.m11) <= e) && (fabs_tpl(m0.m12 - m1.m12) <= e) &&
  797. (fabs_tpl(m0.m20 - m1.m20) <= e) && (fabs_tpl(m0.m21 - m1.m21) <= e) && (fabs_tpl(m0.m22 - m1.m22) <= e)
  798. );
  799. }
  800. ILINE bool IsIdentity(F e) const
  801. {
  802. return (
  803. (fabs_tpl((F)1 - m00) <= e) && (fabs_tpl(m01) <= e) && (fabs_tpl(m02) <= e) &&
  804. (fabs_tpl(m10) <= e) && (fabs_tpl((F)1 - m11) <= e) && (fabs_tpl(m12) <= e) &&
  805. (fabs_tpl(m20) <= e) && (fabs_tpl(m21) <= e) && (fabs_tpl((F)1 - m22) <= e)
  806. );
  807. }
  808. ILINE bool IsIdentity() const
  809. {
  810. return 0 == (fabs_tpl((F)1 - m00) + fabs_tpl(m01) + fabs_tpl(m02) + fabs_tpl(m10) + fabs_tpl((F)1 - m11) + fabs_tpl(m12) + fabs_tpl(m20) + fabs_tpl(m21) + fabs_tpl((F)1 - m22));
  811. }
  812. ILINE int IsZero() const
  813. {
  814. return 0 == (fabs_tpl(m00) + fabs_tpl(m01) + fabs_tpl(m02) + fabs_tpl(m10) + fabs_tpl(m11) + fabs_tpl(m12) + fabs_tpl(m20) + fabs_tpl(m21) + fabs_tpl(m22));
  815. }
  816. //check if we have an orthonormal-base (general case, works even with reflection matrices)
  817. ILINE int IsOrthonormal(F threshold = 0.001) const
  818. {
  819. f32 d0 = fabs_tpl(GetColumn0() | GetColumn1());
  820. if (d0 > threshold)
  821. {
  822. return 0;
  823. }
  824. f32 d1 = fabs_tpl(GetColumn0() | GetColumn2());
  825. if (d1 > threshold)
  826. {
  827. return 0;
  828. }
  829. f32 d2 = fabs_tpl(GetColumn1() | GetColumn2());
  830. if (d2 > threshold)
  831. {
  832. return 0;
  833. }
  834. int a = (fabs_tpl(1 - (GetColumn0() | GetColumn0()))) < threshold;
  835. int b = (fabs_tpl(1 - (GetColumn1() | GetColumn1()))) < threshold;
  836. int c = (fabs_tpl(1 - (GetColumn2() | GetColumn2()))) < threshold;
  837. return a & b & c;
  838. }
  839. //check if we have an orthonormal-base (assuming we are using a right-handed coordinate system)
  840. ILINE int IsOrthonormalRH(F threshold = 0.002) const
  841. {
  842. Vec3_tpl<F> x = GetColumn0();
  843. Vec3_tpl<F> y = GetColumn1();
  844. Vec3_tpl<F> z = GetColumn2();
  845. bool a = x.IsEquivalent(y % z, threshold);
  846. bool b = y.IsEquivalent(z % x, threshold);
  847. bool c = z.IsEquivalent(x % y, threshold);
  848. a &= x.IsUnit(0.01f);
  849. b &= y.IsUnit(0.01f);
  850. c &= z.IsUnit(0.01f);
  851. return a & b & c;
  852. }
  853. //////////////////////////////////////////////////////////////////////////
  854. // Remove uniform scale from matrix.
  855. ILINE void NoScale()
  856. {
  857. *this /= GetColumn(0).GetLength();
  858. }
  859. ILINE bool IsValid() const
  860. {
  861. if (!NumberValid(m00))
  862. {
  863. return false;
  864. }
  865. if (!NumberValid(m01))
  866. {
  867. return false;
  868. }
  869. if (!NumberValid(m02))
  870. {
  871. return false;
  872. }
  873. if (!NumberValid(m10))
  874. {
  875. return false;
  876. }
  877. if (!NumberValid(m11))
  878. {
  879. return false;
  880. }
  881. if (!NumberValid(m12))
  882. {
  883. return false;
  884. }
  885. if (!NumberValid(m20))
  886. {
  887. return false;
  888. }
  889. if (!NumberValid(m21))
  890. {
  891. return false;
  892. }
  893. if (!NumberValid(m22))
  894. {
  895. return false;
  896. }
  897. return true;
  898. }
  899. };
  900. ///////////////////////////////////////////////////////////////////////////////
  901. // Typedefs //
  902. ///////////////////////////////////////////////////////////////////////////////
  903. typedef Matrix33_tpl<f32> Matrix33; //always 32 bit
  904. //----------------------------------------------------------------------------------
  905. //----------------------------------------------------------------------------------
  906. //----------------------------------------------------------------------------------
  907. //------------- implementation of Matrix33 ------------------------------
  908. //----------------------------------------------------------------------------------
  909. //----------------------------------------------------------------------------------
  910. //----------------------------------------------------------------------------------
  911. //Matrix33 operations with another Matrix33
  912. template<class F1, class F2>
  913. ILINE Matrix33_tpl<F1> operator * (const Matrix33_tpl<F1>& l, const Matrix33_tpl<F2>& r)
  914. {
  915. assert(l.IsValid());
  916. assert(r.IsValid());
  917. Matrix33_tpl<F1> m;
  918. m.m00 = l.m00 * r.m00 + l.m01 * r.m10 + l.m02 * r.m20;
  919. m.m01 = l.m00 * r.m01 + l.m01 * r.m11 + l.m02 * r.m21;
  920. m.m02 = l.m00 * r.m02 + l.m01 * r.m12 + l.m02 * r.m22;
  921. m.m10 = l.m10 * r.m00 + l.m11 * r.m10 + l.m12 * r.m20;
  922. m.m11 = l.m10 * r.m01 + l.m11 * r.m11 + l.m12 * r.m21;
  923. m.m12 = l.m10 * r.m02 + l.m11 * r.m12 + l.m12 * r.m22;
  924. m.m20 = l.m20 * r.m00 + l.m21 * r.m10 + l.m22 * r.m20;
  925. m.m21 = l.m20 * r.m01 + l.m21 * r.m11 + l.m22 * r.m21;
  926. m.m22 = l.m20 * r.m02 + l.m21 * r.m12 + l.m22 * r.m22;
  927. return m;
  928. }
  929. /*!
  930. *
  931. * Implements the multiplication operator: Matrix34=Matrix33*Matrix34
  932. *
  933. * Matrix33 and Matrix34 are specified in collumn order for a right-handed coordinate-system.
  934. * AxB = operation B followed by operation A.
  935. * A multiplication takes 36 muls and 24 adds.
  936. *
  937. * Example:
  938. * Matrix33 m33=Matrix33::CreateRotationX(1.94192f);;
  939. * Matrix34 m34=Matrix34::CreateRotationZ(3.14192f);
  940. * Matrix34 result=m33*m34;
  941. *
  942. */
  943. template<class F1, class F2>
  944. ILINE Matrix34_tpl<F2> operator * (const Matrix33_tpl<F1>& l, const Matrix34_tpl<F2>& r)
  945. {
  946. assert(l.IsValid());
  947. assert(r.IsValid());
  948. Matrix34_tpl<F2> m;
  949. m.m00 = l.m00 * r.m00 + l.m01 * r.m10 + l.m02 * r.m20;
  950. m.m10 = l.m10 * r.m00 + l.m11 * r.m10 + l.m12 * r.m20;
  951. m.m20 = l.m20 * r.m00 + l.m21 * r.m10 + l.m22 * r.m20;
  952. m.m01 = l.m00 * r.m01 + l.m01 * r.m11 + l.m02 * r.m21;
  953. m.m11 = l.m10 * r.m01 + l.m11 * r.m11 + l.m12 * r.m21;
  954. m.m21 = l.m20 * r.m01 + l.m21 * r.m11 + l.m22 * r.m21;
  955. m.m02 = l.m00 * r.m02 + l.m01 * r.m12 + l.m02 * r.m22;
  956. m.m12 = l.m10 * r.m02 + l.m11 * r.m12 + l.m12 * r.m22;
  957. m.m22 = l.m20 * r.m02 + l.m21 * r.m12 + l.m22 * r.m22;
  958. m.m03 = l.m00 * r.m03 + l.m01 * r.m13 + l.m02 * r.m23;
  959. m.m13 = l.m10 * r.m03 + l.m11 * r.m13 + l.m12 * r.m23;
  960. m.m23 = l.m20 * r.m03 + l.m21 * r.m13 + l.m22 * r.m23;
  961. return m;
  962. }
  963. /*!
  964. *
  965. * Implements the multiplication operator: Matrix44=Matrix33*Matrix44
  966. *
  967. * Matrix33 and Matrix44 are specified in collumn order for a right-handed coordinate-system.
  968. * AxB = operation B followed by operation A.
  969. * A multiplication takes 36 muls and 24 adds.
  970. *
  971. * Example:
  972. * Matrix33 m33=Matrix33::CreateRotationX(1.94192f);;
  973. * Matrix44 m44=Matrix33::CreateRotationZ(3.14192f);
  974. * Matrix44 result=m33*m44;
  975. *
  976. */
  977. template<class F1, class F2>
  978. ILINE Matrix44_tpl<F2> operator * (const Matrix33_tpl<F1>& l, const Matrix44_tpl<F2>& r)
  979. {
  980. assert(l.IsValid());
  981. assert(r.IsValid());
  982. Matrix44_tpl<F2> m;
  983. m.m00 = l.m00 * r.m00 + l.m01 * r.m10 + l.m02 * r.m20;
  984. m.m10 = l.m10 * r.m00 + l.m11 * r.m10 + l.m12 * r.m20;
  985. m.m20 = l.m20 * r.m00 + l.m21 * r.m10 + l.m22 * r.m20;
  986. m.m30 = r.m30;
  987. m.m01 = l.m00 * r.m01 + l.m01 * r.m11 + l.m02 * r.m21;
  988. m.m11 = l.m10 * r.m01 + l.m11 * r.m11 + l.m12 * r.m21;
  989. m.m21 = l.m20 * r.m01 + l.m21 * r.m11 + l.m22 * r.m21;
  990. m.m31 = r.m31;
  991. m.m02 = l.m00 * r.m02 + l.m01 * r.m12 + l.m02 * r.m22;
  992. m.m12 = l.m10 * r.m02 + l.m11 * r.m12 + l.m12 * r.m22;
  993. m.m22 = l.m20 * r.m02 + l.m21 * r.m12 + l.m22 * r.m22;
  994. m.m32 = r.m32;
  995. m.m03 = l.m00 * r.m03 + l.m01 * r.m13 + l.m02 * r.m23;
  996. m.m13 = l.m10 * r.m03 + l.m11 * r.m13 + l.m12 * r.m23;
  997. m.m23 = l.m20 * r.m03 + l.m21 * r.m13 + l.m22 * r.m23;
  998. m.m33 = r.m33;
  999. return m;
  1000. }
  1001. template<class F1, class F2>
  1002. ILINE Matrix33_tpl<F1>& operator *= (Matrix33_tpl<F1>& l, const Matrix33_tpl<F2>& r)
  1003. {
  1004. assert(l.IsValid());
  1005. assert(r.IsValid());
  1006. Matrix33_tpl<F1> tmp;
  1007. tmp.m00 = l.m00 * r.m00 + l.m01 * r.m10 + l.m02 * r.m20;
  1008. tmp.m01 = l.m00 * r.m01 + l.m01 * r.m11 + l.m02 * r.m21;
  1009. tmp.m02 = l.m00 * r.m02 + l.m01 * r.m12 + l.m02 * r.m22;
  1010. tmp.m10 = l.m10 * r.m00 + l.m11 * r.m10 + l.m12 * r.m20;
  1011. tmp.m11 = l.m10 * r.m01 + l.m11 * r.m11 + l.m12 * r.m21;
  1012. tmp.m12 = l.m10 * r.m02 + l.m11 * r.m12 + l.m12 * r.m22;
  1013. tmp.m20 = l.m20 * r.m00 + l.m21 * r.m10 + l.m22 * r.m20;
  1014. tmp.m21 = l.m20 * r.m01 + l.m21 * r.m11 + l.m22 * r.m21;
  1015. tmp.m22 = l.m20 * r.m02 + l.m21 * r.m12 + l.m22 * r.m22;
  1016. l = tmp;
  1017. return l;
  1018. }
  1019. template<class F1, class F2>
  1020. ILINE Matrix33_tpl<F1> operator+(const Matrix33_tpl<F1>& l, const Matrix33_tpl<F2>& r)
  1021. {
  1022. assert(l.IsValid());
  1023. assert(r.IsValid());
  1024. Matrix33_tpl<F1> res;
  1025. res.m00 = l.m00 + r.m00;
  1026. res.m01 = l.m01 + r.m01;
  1027. res.m02 = l.m02 + r.m02;
  1028. res.m10 = l.m10 + r.m10;
  1029. res.m11 = l.m11 + r.m11;
  1030. res.m12 = l.m12 + r.m12;
  1031. res.m20 = l.m20 + r.m20;
  1032. res.m21 = l.m21 + r.m21;
  1033. res.m22 = l.m22 + r.m22;
  1034. return res;
  1035. }
  1036. template<class F1, class F2>
  1037. ILINE Matrix33_tpl<F1>& operator+=(Matrix33_tpl<F1>& l, const Matrix33_tpl<F2>& r)
  1038. {
  1039. assert(l.IsValid());
  1040. assert(r.IsValid());
  1041. l.m00 += r.m00;
  1042. l.m01 += r.m01;
  1043. l.m02 += r.m02;
  1044. l.m10 += r.m10;
  1045. l.m11 += r.m11;
  1046. l.m12 += r.m12;
  1047. l.m20 += r.m20;
  1048. l.m21 += r.m21;
  1049. l.m22 += r.m22;
  1050. return l;
  1051. }
  1052. template<class F1, class F2>
  1053. ILINE Matrix33_tpl<F1> operator - (const Matrix33_tpl<F1>& l, const Matrix33_tpl<F2>& r)
  1054. {
  1055. assert(l.IsValid());
  1056. assert(r.IsValid());
  1057. Matrix33_tpl<F1> res;
  1058. res.m00 = l.m00 - r.m00;
  1059. res.m01 = l.m01 - r.m01;
  1060. res.m02 = l.m02 - r.m02;
  1061. res.m10 = l.m10 - r.m10;
  1062. res.m11 = l.m11 - r.m11;
  1063. res.m12 = l.m12 - r.m12;
  1064. res.m20 = l.m20 - r.m20;
  1065. res.m21 = l.m21 - r.m21;
  1066. res.m22 = l.m22 - r.m22;
  1067. return res;
  1068. }
  1069. template<class F1, class F2>
  1070. ILINE Matrix33_tpl<F1>& operator-=(Matrix33_tpl<F1>& l, const Matrix33_tpl<F2>& r)
  1071. {
  1072. assert(l.IsValid());
  1073. assert(r.IsValid());
  1074. l.m00 -= r.m00;
  1075. l.m01 -= r.m01;
  1076. l.m02 -= r.m02;
  1077. l.m10 -= r.m10;
  1078. l.m11 -= r.m11;
  1079. l.m12 -= r.m12;
  1080. l.m20 -= r.m20;
  1081. l.m21 -= r.m21;
  1082. l.m22 -= r.m22;
  1083. return l;
  1084. }
  1085. template<class F>
  1086. ILINE Matrix33_tpl<F> operator*(const Matrix33_tpl<F>& m, F op)
  1087. {
  1088. assert(m.IsValid());
  1089. Matrix33_tpl<F> res;
  1090. res.m00 = m.m00 * op;
  1091. res.m01 = m.m01 * op;
  1092. res.m02 = m.m02 * op;
  1093. res.m10 = m.m10 * op;
  1094. res.m11 = m.m11 * op;
  1095. res.m12 = m.m12 * op;
  1096. res.m20 = m.m20 * op;
  1097. res.m21 = m.m21 * op;
  1098. res.m22 = m.m22 * op;
  1099. return res;
  1100. }
  1101. template<class F>
  1102. ILINE Matrix33_tpl<F> operator/(const Matrix33_tpl<F>& src, F op) { return src * ((F)1.0 / op); }
  1103. //post-multiply
  1104. template<class F1, class F2>
  1105. ILINE Vec3_tpl<F1> operator*(const Matrix33_tpl<F2>& m, const Vec3_tpl<F1>& p)
  1106. {
  1107. assert(m.IsValid());
  1108. assert(p.IsValid());
  1109. Vec3_tpl<F1> tp;
  1110. tp.x = F1(m.m00 * p.x + m.m01 * p.y + m.m02 * p.z);
  1111. tp.y = F1(m.m10 * p.x + m.m11 * p.y + m.m12 * p.z);
  1112. tp.z = F1(m.m20 * p.x + m.m21 * p.y + m.m22 * p.z);
  1113. return tp;
  1114. }
  1115. //pre-multiply
  1116. template<class F1, class F2>
  1117. ILINE Vec3_tpl<F1> operator*(const Vec3_tpl<F1>& p, const Matrix33_tpl<F2>& m)
  1118. {
  1119. assert(m.IsValid());
  1120. assert(p.IsValid());
  1121. Vec3_tpl<F1> tp;
  1122. tp.x = F1(p.x * m.m00 + p.y * m.m10 + p.z * m.m20);
  1123. tp.y = F1(p.x * m.m01 + p.y * m.m11 + p.z * m.m21);
  1124. tp.z = F1(p.x * m.m02 + p.y * m.m12 + p.z * m.m22);
  1125. return tp;
  1126. }
  1127. //post-multiply
  1128. template<class F1, class F2>
  1129. ILINE Vec2_tpl<F1> operator*(const Matrix33_tpl<F2>& m, const Vec2_tpl<F1>& v)
  1130. {
  1131. assert(m.IsValid());
  1132. assert(v.IsValid());
  1133. return Vec2_tpl<F1>(v.x * m.m00 + v.y * m.m01, v.x * m.m10 + v.y * m.m11);
  1134. }
  1135. //pre-multiply
  1136. template<class F1, class F2>
  1137. ILINE Vec2_tpl<F1> operator*(const Vec2_tpl<F1>& v, const Matrix33_tpl<F2>& m)
  1138. {
  1139. assert(m.IsValid());
  1140. assert(v.IsValid());
  1141. return Vec2_tpl<F1>(v.x * m.m00 + v.y * m.m10, v.x * m.m01 + v.y * m.m11);
  1142. }