Mat.h 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <AnKi/Math/Common.h>
  7. #include <AnKi/Math/Vec.h>
  8. namespace anki
  9. {
  10. /// @addtogroup math
  11. /// @{
  12. /// Matrix type.
  13. /// @tparam T The scalar type. Eg float.
  14. /// @tparam J The number of rows.
  15. /// @tparam I The number of columns.
  16. template<typename T, U J, U I>
  17. class alignas(MathSimd<T, I>::ALIGNMENT) TMat
  18. {
  19. public:
  20. using Scalar = T;
  21. using Simd = typename MathSimd<T, I>::Type;
  22. using SimdArray = Array<Simd, J>;
  23. using RowVec = TVec<T, I>;
  24. using ColumnVec = TVec<T, J>;
  25. static constexpr U ROW_SIZE = J; ///< Number of rows
  26. static constexpr U COLUMN_SIZE = I; ///< Number of columns
  27. static constexpr U SIZE = J * I; ///< Number of total elements
  28. static constexpr Bool HAS_SIMD = I == 4 && std::is_same<T, F32>::value && ANKI_SIMD_SSE;
  29. static constexpr Bool HAS_MAT4_SIMD = J == 4 && I == 4 && std::is_same<T, F32>::value && ANKI_SIMD_SSE;
  30. static constexpr Bool HAS_MAT3X4_SIMD = J == 3 && I == 4 && std::is_same<T, F32>::value && ANKI_SIMD_SSE;
  31. /// @name Constructors
  32. /// @{
  33. TMat()
  34. {
  35. }
  36. /// Copy.
  37. TMat(ANKI_ENABLE_ARG(const TMat&, !HAS_SIMD) b)
  38. {
  39. for(U i = 0; i < N; i++)
  40. {
  41. m_arr1[i] = b.m_arr1[i];
  42. }
  43. }
  44. /// Copy.
  45. TMat(ANKI_ENABLE_ARG(const TMat&, HAS_SIMD) b)
  46. {
  47. for(U i = 0; i < J; i++)
  48. {
  49. m_simd[i] = b.m_simd[i];
  50. }
  51. }
  52. ANKI_ENABLE_METHOD(!HAS_SIMD)
  53. explicit TMat(const T f)
  54. {
  55. for(T& x : m_arr1)
  56. {
  57. x = f;
  58. }
  59. }
  60. ANKI_ENABLE_METHOD(HAS_SIMD)
  61. explicit TMat(const T f)
  62. {
  63. for(U i = 0; i < J; i++)
  64. {
  65. m_simd[i] = _mm_set1_ps(f);
  66. }
  67. }
  68. explicit TMat(const T arr[])
  69. {
  70. for(U i = 0; i < N; i++)
  71. {
  72. m_arr1[i] = arr[i];
  73. }
  74. }
  75. // 3x3 specific constructors
  76. ANKI_ENABLE_METHOD(J == 3 && I == 3)
  77. TMat(T m00, T m01, T m02, T m10, T m11, T m12, T m20, T m21, T m22)
  78. {
  79. auto& m = *this;
  80. m(0, 0) = m00;
  81. m(0, 1) = m01;
  82. m(0, 2) = m02;
  83. m(1, 0) = m10;
  84. m(1, 1) = m11;
  85. m(1, 2) = m12;
  86. m(2, 0) = m20;
  87. m(2, 1) = m21;
  88. m(2, 2) = m22;
  89. }
  90. ANKI_ENABLE_METHOD(J == 3 && I == 3)
  91. explicit TMat(const TQuat<T>& q)
  92. {
  93. setRotationPart(q);
  94. }
  95. ANKI_ENABLE_METHOD(J == 3 && I == 3)
  96. explicit TMat(const TEuler<T>& e)
  97. {
  98. setRotationPart(e);
  99. }
  100. ANKI_ENABLE_METHOD(J == 3 && I == 3)
  101. explicit TMat(const TAxisang<T>& axisang)
  102. {
  103. setRotationPart(axisang);
  104. }
  105. // 4x4 specific constructors
  106. ANKI_ENABLE_METHOD(J == 4 && I == 4)
  107. TMat(T m00, T m01, T m02, T m03, T m10, T m11, T m12, T m13, T m20, T m21, T m22, T m23, T m30, T m31, T m32, T m33)
  108. {
  109. auto& m = *this;
  110. m(0, 0) = m00;
  111. m(0, 1) = m01;
  112. m(0, 2) = m02;
  113. m(0, 3) = m03;
  114. m(1, 0) = m10;
  115. m(1, 1) = m11;
  116. m(1, 2) = m12;
  117. m(1, 3) = m13;
  118. m(2, 0) = m20;
  119. m(2, 1) = m21;
  120. m(2, 2) = m22;
  121. m(2, 3) = m23;
  122. m(3, 0) = m30;
  123. m(3, 1) = m31;
  124. m(3, 2) = m32;
  125. m(3, 3) = m33;
  126. }
  127. ANKI_ENABLE_METHOD(J == 4 && I == 4)
  128. TMat(const TVec<T, 4>& translation, const TMat<T, 3, 3>& rotation, const T scale = T(1))
  129. {
  130. if(isZero<T>(scale - T(1)))
  131. {
  132. setRotationPart(rotation);
  133. }
  134. else
  135. {
  136. setRotationPart(rotation * scale);
  137. }
  138. setTranslationPart(translation);
  139. auto& m = *this;
  140. m(3, 0) = m(3, 1) = m(3, 2) = T(0);
  141. }
  142. ANKI_ENABLE_METHOD(J == 4 && I == 4)
  143. explicit TMat(const TTransform<T>& t)
  144. : TMat(t.getOrigin().xyz1(), t.getRotation().getRotationPart(), t.getScale())
  145. {
  146. }
  147. // 3x4 specific constructors
  148. ANKI_ENABLE_METHOD(J == 3 && I == 4)
  149. TMat(T m00, T m01, T m02, T m03, T m10, T m11, T m12, T m13, T m20, T m21, T m22, T m23)
  150. {
  151. auto& m = *this;
  152. m(0, 0) = m00;
  153. m(0, 1) = m01;
  154. m(0, 2) = m02;
  155. m(0, 3) = m03;
  156. m(1, 0) = m10;
  157. m(1, 1) = m11;
  158. m(1, 2) = m12;
  159. m(1, 3) = m13;
  160. m(2, 0) = m20;
  161. m(2, 1) = m21;
  162. m(2, 2) = m22;
  163. m(2, 3) = m23;
  164. }
  165. ANKI_ENABLE_METHOD(J == 3 && I == 4)
  166. explicit TMat(const TMat<T, 4, 4>& m4)
  167. {
  168. auto& m = *this;
  169. m(0, 0) = m4(0, 0);
  170. m(0, 1) = m4(0, 1);
  171. m(0, 2) = m4(0, 2);
  172. m(0, 3) = m4(0, 3);
  173. m(1, 0) = m4(1, 0);
  174. m(1, 1) = m4(1, 1);
  175. m(1, 2) = m4(1, 2);
  176. m(1, 3) = m4(1, 3);
  177. m(2, 0) = m4(2, 0);
  178. m(2, 1) = m4(2, 1);
  179. m(2, 2) = m4(2, 2);
  180. m(2, 3) = m4(2, 3);
  181. }
  182. ANKI_ENABLE_METHOD(J == 3 && I == 4)
  183. explicit TMat(const TVec<T, 3>& translation, const TMat<T, 3, 3>& rotation, const T scale = T(1))
  184. {
  185. if(isZero<T>(scale - T(1)))
  186. {
  187. setRotationPart(rotation);
  188. }
  189. else
  190. {
  191. setRotationPart(rotation * scale);
  192. }
  193. setTranslationPart(translation);
  194. }
  195. ANKI_ENABLE_METHOD(J == 3 && I == 4)
  196. explicit TMat(const TVec<T, 3>& translation, const TQuat<T>& q, const T scale = T(1))
  197. : TMat(translation, TMat<T, 3, 3>(q), scale)
  198. {
  199. }
  200. ANKI_ENABLE_METHOD(J == 3 && I == 4)
  201. explicit TMat(const TVec<T, 3>& translation, const TEuler<T>& b, const T scale = T(1))
  202. : TMat(translation, TMat<T, 3, 3>(b), scale)
  203. {
  204. }
  205. ANKI_ENABLE_METHOD(J == 3 && I == 4)
  206. explicit TMat(const TVec<T, 3>& translation, const TAxisang<T>& b, const T scale = T(1))
  207. : TMat(translation, TMat<T, 3, 3>(b), scale)
  208. {
  209. }
  210. ANKI_ENABLE_METHOD(J == 3 && I == 4)
  211. explicit TMat(const TTransform<T>& t)
  212. : TMat(t.getOrigin().xyz(), t.getRotation().getRotationPart(), t.getScale())
  213. {
  214. }
  215. /// @}
  216. /// @name Accessors
  217. /// @{
  218. T& operator()(const U j, const U i)
  219. {
  220. return m_arr2[j][i];
  221. }
  222. T operator()(const U j, const U i) const
  223. {
  224. return m_arr2[j][i];
  225. }
  226. T& operator[](const U n)
  227. {
  228. return m_arr1[n];
  229. }
  230. T operator[](const U n) const
  231. {
  232. return m_arr1[n];
  233. }
  234. /// @}
  235. /// @name Operators with same type
  236. /// @{
  237. /// Copy.
  238. TMat& operator=(ANKI_ENABLE_ARG(const TMat&, !HAS_SIMD) b)
  239. {
  240. for(U n = 0; n < N; n++)
  241. {
  242. m_arr1[n] = b.m_arr1[n];
  243. }
  244. return *this;
  245. }
  246. /// Copy.
  247. TMat& operator=(ANKI_ENABLE_ARG(const TMat&, HAS_SIMD) b)
  248. {
  249. for(U i = 0; i < J; i++)
  250. {
  251. m_simd[i] = b.m_simd[i];
  252. }
  253. return *this;
  254. }
  255. ANKI_ENABLE_METHOD(!HAS_SIMD)
  256. TMat operator+(const TMat& b) const
  257. {
  258. TMat c;
  259. for(U n = 0; n < N; n++)
  260. {
  261. c.m_arr1[n] = m_arr1[n] + b.m_arr1[n];
  262. }
  263. return c;
  264. }
  265. ANKI_ENABLE_METHOD(HAS_SIMD)
  266. TMat operator+(const TMat& b) const
  267. {
  268. TMat c;
  269. for(U i = 0; i < J; i++)
  270. {
  271. c.m_simd[i] = _mm_add_ps(m_simd[i], b.m_simd[i]);
  272. }
  273. return c;
  274. }
  275. ANKI_ENABLE_METHOD(!HAS_SIMD)
  276. TMat& operator+=(const TMat& b)
  277. {
  278. for(U n = 0; n < N; n++)
  279. {
  280. m_arr1[n] += b.m_arr1[n];
  281. }
  282. return *this;
  283. }
  284. ANKI_ENABLE_METHOD(HAS_SIMD)
  285. TMat& operator+=(const TMat& b)
  286. {
  287. for(U i = 0; i < J; i++)
  288. {
  289. m_simd[i] = _mm_add_ps(m_simd[i], b.m_simd[i]);
  290. }
  291. return *this;
  292. }
  293. ANKI_ENABLE_METHOD(!HAS_SIMD)
  294. TMat operator-(const TMat& b) const
  295. {
  296. TMat c;
  297. for(U n = 0; n < N; n++)
  298. {
  299. c.m_arr1[n] = m_arr1[n] - b.m_arr1[n];
  300. }
  301. return c;
  302. }
  303. ANKI_ENABLE_METHOD(HAS_SIMD)
  304. TMat operator-(const TMat& b) const
  305. {
  306. TMat c;
  307. for(U i = 0; i < J; i++)
  308. {
  309. c.m_simd[i] = _mm_sub_ps(m_simd[i], b.m_simd[i]);
  310. }
  311. return c;
  312. }
  313. ANKI_ENABLE_METHOD(!HAS_SIMD)
  314. TMat& operator-=(const TMat& b)
  315. {
  316. for(U n = 0; n < N; n++)
  317. {
  318. m_arr1[n] -= b.m_arr1[n];
  319. }
  320. return *this;
  321. }
  322. ANKI_ENABLE_METHOD(HAS_SIMD)
  323. TMat& operator-=(const TMat& b)
  324. {
  325. for(U i = 0; i < J; i++)
  326. {
  327. m_simd[i] = _mm_sub_ps(m_simd[i], b.m_simd[i]);
  328. }
  329. return *this;
  330. }
  331. ANKI_ENABLE_METHOD(J == I && !HAS_MAT4_SIMD)
  332. TMat operator*(const TMat& b) const
  333. {
  334. TMat out;
  335. const TMat& a = *this;
  336. for(U j = 0; j < J; j++)
  337. {
  338. for(U i = 0; i < I; i++)
  339. {
  340. out(j, i) = T(0);
  341. for(U k = 0; k < I; k++)
  342. {
  343. out(j, i) += a(j, k) * b(k, i);
  344. }
  345. }
  346. }
  347. return out;
  348. }
  349. ANKI_ENABLE_METHOD(HAS_MAT4_SIMD)
  350. TMat operator*(const TMat& b) const
  351. {
  352. TMat out;
  353. const auto& m = *this;
  354. for(U i = 0; i < 4; i++)
  355. {
  356. __m128 t1, t2;
  357. t1 = _mm_set1_ps(m(i, 0));
  358. t2 = _mm_mul_ps(b.m_simd[0], t1);
  359. t1 = _mm_set1_ps(m(i, 1));
  360. t2 = _mm_add_ps(_mm_mul_ps(b.m_simd[1], t1), t2);
  361. t1 = _mm_set1_ps(m(i, 2));
  362. t2 = _mm_add_ps(_mm_mul_ps(b.m_simd[2], t1), t2);
  363. t1 = _mm_set1_ps(m(i, 3));
  364. t2 = _mm_add_ps(_mm_mul_ps(b.m_simd[3], t1), t2);
  365. out.m_simd[i] = t2;
  366. }
  367. return out;
  368. }
  369. TMat& operator*=(const TMat& b)
  370. {
  371. (*this) = (*this) * b;
  372. return *this;
  373. }
  374. Bool operator==(const TMat& b) const
  375. {
  376. for(U i = 0; i < N; i++)
  377. {
  378. if(!isZero<T>(m_arr1[i] - b.m_arr1[i]))
  379. {
  380. return false;
  381. }
  382. }
  383. return true;
  384. }
  385. Bool operator!=(const TMat& b) const
  386. {
  387. for(U i = 0; i < N; i++)
  388. {
  389. if(!isZero<T>(m_arr1[i] - b.m_arr1[i]))
  390. {
  391. return true;
  392. }
  393. }
  394. return false;
  395. }
  396. /// @}
  397. /// @name Operators with T
  398. /// @{
  399. TMat operator+(const T f) const
  400. {
  401. TMat out;
  402. for(U i = 0; i < N; i++)
  403. {
  404. out.m_arr1[i] = m_arr1[i] + f;
  405. }
  406. return out;
  407. }
  408. TMat& operator+=(const T f)
  409. {
  410. for(U i = 0; i < N; i++)
  411. {
  412. m_arr1[i] += f;
  413. }
  414. return *this;
  415. }
  416. TMat operator-(const T f) const
  417. {
  418. TMat out;
  419. for(U i = 0; i < N; i++)
  420. {
  421. out.m_arr1[i] = m_arr1[i] - f;
  422. }
  423. return out;
  424. }
  425. TMat& operator-=(const T f)
  426. {
  427. for(U i = 0; i < N; i++)
  428. {
  429. m_arr1[i] -= f;
  430. }
  431. return *this;
  432. }
  433. TMat operator*(const T f) const
  434. {
  435. TMat out;
  436. for(U i = 0; i < N; i++)
  437. {
  438. out.m_arr1[i] = m_arr1[i] * f;
  439. }
  440. return out;
  441. }
  442. TMat& operator*=(const T f)
  443. {
  444. for(U i = 0; i < N; i++)
  445. {
  446. m_arr1[i] *= f;
  447. }
  448. return *this;
  449. }
  450. TMat operator/(const T f) const
  451. {
  452. ANKI_ASSERT(f != T(0));
  453. TMat out;
  454. for(U i = 0; i < N; i++)
  455. {
  456. out.m_arr1[i] = m_arr1[i] / f;
  457. }
  458. return out;
  459. }
  460. TMat& operator/=(const T f)
  461. {
  462. ANKI_ASSERT(f != T(0));
  463. for(U i = 0; i < N; i++)
  464. {
  465. m_arr1[i] /= f;
  466. }
  467. return *this;
  468. }
  469. /// @}
  470. /// @name Operators with other types
  471. /// @{
  472. ANKI_ENABLE_METHOD(!HAS_SIMD)
  473. ColumnVec operator*(const RowVec& v) const
  474. {
  475. const TMat& m = *this;
  476. ColumnVec out;
  477. for(U j = 0; j < J; j++)
  478. {
  479. T sum = 0.0;
  480. for(U i = 0; i < I; i++)
  481. {
  482. sum += m(j, i) * v[i];
  483. }
  484. out[j] = sum;
  485. }
  486. return out;
  487. }
  488. ANKI_ENABLE_METHOD(HAS_SIMD)
  489. ColumnVec operator*(const RowVec& v) const
  490. {
  491. ColumnVec out;
  492. for(U i = 0; i < J; i++)
  493. {
  494. _mm_store_ss(&out[i], _mm_dp_ps(m_simd[i], v.getSimd(), 0xF1));
  495. }
  496. return out;
  497. }
  498. /// @}
  499. /// @name Other
  500. /// @{
  501. ANKI_ENABLE_METHOD(!HAS_SIMD)
  502. void setRow(const U j, const RowVec& v)
  503. {
  504. for(U i = 0; i < I; i++)
  505. {
  506. m_arr2[j][i] = v[i];
  507. }
  508. }
  509. ANKI_ENABLE_METHOD(HAS_SIMD)
  510. void setRow(const U j, const RowVec& v)
  511. {
  512. m_simd[j] = v.getSimd();
  513. }
  514. void setRows(const RowVec& a, const RowVec& b, const RowVec& c)
  515. {
  516. setRow(0, a);
  517. setRow(1, b);
  518. setRow(2, c);
  519. }
  520. ANKI_ENABLE_METHOD(J > 3)
  521. void setRows(const RowVec& a, const RowVec& b, const RowVec& c, const RowVec& d)
  522. {
  523. setRows(a, b, c);
  524. setRow(3, d);
  525. }
  526. RowVec getRow(const U j) const
  527. {
  528. RowVec out;
  529. for(U i = 0; i < I; i++)
  530. {
  531. out[i] = m_arr2[j][i];
  532. }
  533. return out;
  534. }
  535. void getRows(RowVec& a, RowVec& b, RowVec& c) const
  536. {
  537. a = getRow(0);
  538. b = getRow(1);
  539. c = getRow(2);
  540. }
  541. void getRows(RowVec& a, RowVec& b, RowVec& c, RowVec& d) const
  542. {
  543. static_assert(J > 3, "Wrong matrix");
  544. getRows(a, b, c);
  545. d = getRow(3);
  546. }
  547. void setColumn(const U i, const ColumnVec& v)
  548. {
  549. for(U j = 0; j < J; j++)
  550. {
  551. m_arr2[j][i] = v[j];
  552. }
  553. }
  554. void setColumns(const ColumnVec& a, const ColumnVec& b, const ColumnVec& c)
  555. {
  556. setColumn(0, a);
  557. setColumn(1, b);
  558. setColumn(2, c);
  559. }
  560. void setColumns(const ColumnVec& a, const ColumnVec& b, const ColumnVec& c, const ColumnVec& d)
  561. {
  562. static_assert(I > 3, "Check column number");
  563. setColumns(a, b, c);
  564. setColumn(3, d);
  565. }
  566. ColumnVec getColumn(const U i) const
  567. {
  568. ColumnVec out;
  569. for(U j = 0; j < J; j++)
  570. {
  571. out[j] = m_arr2[j][i];
  572. }
  573. return out;
  574. }
  575. void getColumns(ColumnVec& a, ColumnVec& b, ColumnVec& c) const
  576. {
  577. a = getColumn(0);
  578. b = getColumn(1);
  579. c = getColumn(2);
  580. }
  581. void getColumns(ColumnVec& a, ColumnVec& b, ColumnVec& c, ColumnVec& d) const
  582. {
  583. static_assert(I > 3, "Check column number");
  584. getColumns(a, b, c);
  585. d = getColumn(3);
  586. }
  587. /// Get 1st column
  588. ColumnVec getXAxis() const
  589. {
  590. return getColumn(0);
  591. }
  592. /// Get 2nd column
  593. ColumnVec getYAxis() const
  594. {
  595. return getColumn(1);
  596. }
  597. /// Get 3rd column
  598. ColumnVec getZAxis() const
  599. {
  600. return getColumn(2);
  601. }
  602. /// Set 1st column
  603. void setXAxis(const ColumnVec& v)
  604. {
  605. setColumn(0, v);
  606. }
  607. /// Set 2nd column
  608. void setYAxis(const ColumnVec& v)
  609. {
  610. setColumn(1, v);
  611. }
  612. /// Set 3rd column
  613. void setZAxis(const ColumnVec& v)
  614. {
  615. setColumn(2, v);
  616. }
  617. void setRotationX(const T rad)
  618. {
  619. TMat& m = *this;
  620. T sintheta, costheta;
  621. sinCos(rad, sintheta, costheta);
  622. m(0, 0) = 1.0;
  623. m(0, 1) = 0.0;
  624. m(0, 2) = 0.0;
  625. m(1, 0) = 0.0;
  626. m(1, 1) = costheta;
  627. m(1, 2) = -sintheta;
  628. m(2, 0) = 0.0;
  629. m(2, 1) = sintheta;
  630. m(2, 2) = costheta;
  631. }
  632. void setRotationY(const T rad)
  633. {
  634. TMat& m = *this;
  635. T sintheta, costheta;
  636. sinCos(rad, sintheta, costheta);
  637. m(0, 0) = costheta;
  638. m(0, 1) = 0.0;
  639. m(0, 2) = sintheta;
  640. m(1, 0) = 0.0;
  641. m(1, 1) = 1.0;
  642. m(1, 2) = 0.0;
  643. m(2, 0) = -sintheta;
  644. m(2, 1) = 0.0;
  645. m(2, 2) = costheta;
  646. }
  647. void setRotationZ(const T rad)
  648. {
  649. TMat& m = *this;
  650. T sintheta, costheta;
  651. sinCos(rad, sintheta, costheta);
  652. m(0, 0) = costheta;
  653. m(0, 1) = -sintheta;
  654. m(0, 2) = 0.0;
  655. m(1, 0) = sintheta;
  656. m(1, 1) = costheta;
  657. m(1, 2) = 0.0;
  658. m(2, 0) = 0.0;
  659. m(2, 1) = 0.0;
  660. m(2, 2) = 1.0;
  661. }
  662. /// It rotates "this" in the axis defined by the rotation AND not the
  663. /// world axis
  664. void rotateXAxis(const T rad)
  665. {
  666. TMat& m = *this;
  667. // If we analize the mat3 we can extract the 3 unit vectors rotated by the mat3. The 3 rotated vectors are in
  668. // mat's columns. This means that: mat3.colomn[0] == i * mat3. rotateXAxis() rotates rad angle not from i
  669. // vector (aka x axis) but from the vector from colomn 0
  670. // NOTE: See the clean code from < r664
  671. T sina, cosa;
  672. sinCos(rad, sina, cosa);
  673. // zAxis = zAxis*cosa - yAxis*sina;
  674. m(0, 2) = m(0, 2) * cosa - m(0, 1) * sina;
  675. m(1, 2) = m(1, 2) * cosa - m(1, 1) * sina;
  676. m(2, 2) = m(2, 2) * cosa - m(2, 1) * sina;
  677. // zAxis.normalize();
  678. T len = sqrt(m(0, 2) * m(0, 2) + m(1, 2) * m(1, 2) + m(2, 2) * m(2, 2));
  679. m(0, 2) /= len;
  680. m(1, 2) /= len;
  681. m(2, 2) /= len;
  682. // yAxis = zAxis * xAxis;
  683. m(0, 1) = m(1, 2) * m(2, 0) - m(2, 2) * m(1, 0);
  684. m(1, 1) = m(2, 2) * m(0, 0) - m(0, 2) * m(2, 0);
  685. m(2, 1) = m(0, 2) * m(1, 0) - m(1, 2) * m(0, 0);
  686. // yAxis.normalize();
  687. }
  688. /// @copybrief rotateXAxis
  689. void rotateYAxis(const T rad)
  690. {
  691. TMat& m = *this;
  692. // NOTE: See the clean code from < r664
  693. T sina, cosa;
  694. sinCos(rad, sina, cosa);
  695. // zAxis = zAxis*cosa + xAxis*sina;
  696. m(0, 2) = m(0, 2) * cosa + m(0, 0) * sina;
  697. m(1, 2) = m(1, 2) * cosa + m(1, 0) * sina;
  698. m(2, 2) = m(2, 2) * cosa + m(2, 0) * sina;
  699. // zAxis.normalize();
  700. T len = sqrt(m(0, 2) * m(0, 2) + m(1, 2) * m(1, 2) + m(2, 2) * m(2, 2));
  701. m(0, 2) /= len;
  702. m(1, 2) /= len;
  703. m(2, 2) /= len;
  704. // xAxis = (zAxis*yAxis) * -1.0f;
  705. m(0, 0) = m(2, 2) * m(1, 1) - m(1, 2) * m(2, 1);
  706. m(1, 0) = m(0, 2) * m(2, 1) - m(2, 2) * m(0, 1);
  707. m(2, 0) = m(1, 2) * m(0, 1) - m(0, 2) * m(1, 1);
  708. }
  709. /// @copybrief rotateXAxis
  710. void rotateZAxis(const T rad)
  711. {
  712. TMat& m = *this;
  713. // NOTE: See the clean code from < r664
  714. T sina, cosa;
  715. sinCos(rad, sina, cosa);
  716. // xAxis = xAxis*cosa + yAxis*sina;
  717. m(0, 0) = m(0, 0) * cosa + m(0, 1) * sina;
  718. m(1, 0) = m(1, 0) * cosa + m(1, 1) * sina;
  719. m(2, 0) = m(2, 0) * cosa + m(2, 1) * sina;
  720. // xAxis.normalize();
  721. T len = sqrt(m(0, 0) * m(0, 0) + m(1, 0) * m(1, 0) + m(2, 0) * m(2, 0));
  722. m(0, 0) /= len;
  723. m(1, 0) /= len;
  724. m(2, 0) /= len;
  725. // yAxis = zAxis*xAxis;
  726. m(0, 1) = m(1, 2) * m(2, 0) - m(2, 2) * m(1, 0);
  727. m(1, 1) = m(2, 2) * m(0, 0) - m(0, 2) * m(2, 0);
  728. m(2, 1) = m(0, 2) * m(1, 0) - m(1, 2) * m(0, 0);
  729. }
  730. void setRotationPart(const TMat<T, 3, 3>& m3)
  731. {
  732. TMat& m = *this;
  733. for(U j = 0; j < 3; j++)
  734. {
  735. for(U i = 0; i < 3; i++)
  736. {
  737. m(j, i) = m3(j, i);
  738. }
  739. }
  740. }
  741. void setRotationPart(const TQuat<T>& q)
  742. {
  743. TMat& m = *this;
  744. // If length is > 1 + 0.002 or < 1 - 0.002 then not normalized quat
  745. ANKI_ASSERT(absolute(1.0 - q.getLength()) <= 0.002);
  746. T xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz;
  747. xs = q.x() + q.x();
  748. ys = q.y() + q.y();
  749. zs = q.z() + q.z();
  750. wx = q.w() * xs;
  751. wy = q.w() * ys;
  752. wz = q.w() * zs;
  753. xx = q.x() * xs;
  754. xy = q.x() * ys;
  755. xz = q.x() * zs;
  756. yy = q.y() * ys;
  757. yz = q.y() * zs;
  758. zz = q.z() * zs;
  759. m(0, 0) = T(1) - (yy + zz);
  760. m(0, 1) = xy - wz;
  761. m(0, 2) = xz + wy;
  762. m(1, 0) = xy + wz;
  763. m(1, 1) = T(1) - (xx + zz);
  764. m(1, 2) = yz - wx;
  765. m(2, 0) = xz - wy;
  766. m(2, 1) = yz + wx;
  767. m(2, 2) = T(1) - (xx + yy);
  768. }
  769. void setRotationPart(const TEuler<T>& e)
  770. {
  771. TMat& m = *this;
  772. T ch, sh, ca, sa, cb, sb;
  773. sinCos(e.y(), sh, ch);
  774. sinCos(e.z(), sa, ca);
  775. sinCos(e.x(), sb, cb);
  776. m(0, 0) = ch * ca;
  777. m(0, 1) = sh * sb - ch * sa * cb;
  778. m(0, 2) = ch * sa * sb + sh * cb;
  779. m(1, 0) = sa;
  780. m(1, 1) = ca * cb;
  781. m(1, 2) = -ca * sb;
  782. m(2, 0) = -sh * ca;
  783. m(2, 1) = sh * sa * cb + ch * sb;
  784. m(2, 2) = -sh * sa * sb + ch * cb;
  785. }
  786. void setRotationPart(const TAxisang<T>& axisang)
  787. {
  788. TMat& m = *this;
  789. // Not normalized axis
  790. ANKI_ASSERT(isZero<T>(T(1) - axisang.getAxis().getLength()));
  791. T c, s;
  792. sinCos(axisang.getAngle(), s, c);
  793. T t = T(1) - c;
  794. const TVec<T, 3>& axis = axisang.getAxis();
  795. m(0, 0) = c + axis.x() * axis.x() * t;
  796. m(1, 1) = c + axis.y() * axis.y() * t;
  797. m(2, 2) = c + axis.z() * axis.z() * t;
  798. T tmp1 = axis.x() * axis.y() * t;
  799. T tmp2 = axis.z() * s;
  800. m(1, 0) = tmp1 + tmp2;
  801. m(0, 1) = tmp1 - tmp2;
  802. tmp1 = axis.x() * axis.z() * t;
  803. tmp2 = axis.y() * s;
  804. m(2, 0) = tmp1 - tmp2;
  805. m(0, 2) = tmp1 + tmp2;
  806. tmp1 = axis.y() * axis.z() * t;
  807. tmp2 = axis.x() * s;
  808. m(2, 1) = tmp1 + tmp2;
  809. m(1, 2) = tmp1 - tmp2;
  810. }
  811. TMat<T, 3, 3> getRotationPart() const
  812. {
  813. const TMat& m = *this;
  814. TMat<T, 3, 3> m3;
  815. m3(0, 0) = m(0, 0);
  816. m3(0, 1) = m(0, 1);
  817. m3(0, 2) = m(0, 2);
  818. m3(1, 0) = m(1, 0);
  819. m3(1, 1) = m(1, 1);
  820. m3(1, 2) = m(1, 2);
  821. m3(2, 0) = m(2, 0);
  822. m3(2, 1) = m(2, 1);
  823. m3(2, 2) = m(2, 2);
  824. return m3;
  825. }
  826. void setTranslationPart(const ColumnVec& v)
  827. {
  828. if(ROW_SIZE == 4)
  829. {
  830. ANKI_ASSERT(isZero<T>(v[3] - T(1)) && "w should be 1");
  831. }
  832. setColumn(3, v);
  833. }
  834. ColumnVec getTranslationPart() const
  835. {
  836. return getColumn(3);
  837. }
  838. void reorthogonalize()
  839. {
  840. // There are 2 methods, the standard and the Gram-Schmidt method with a twist for zAxis. This uses the 2nd. For
  841. // the first see < r664
  842. ColumnVec xAxis, yAxis, zAxis;
  843. getColumns(xAxis, yAxis, zAxis);
  844. xAxis.normalize();
  845. yAxis = yAxis - (xAxis * xAxis.dot(yAxis));
  846. yAxis.normalize();
  847. zAxis = xAxis.cross(yAxis);
  848. setColumns(xAxis, yAxis, zAxis);
  849. }
  850. ANKI_ENABLE_METHOD(J == I && !HAS_SIMD)
  851. void transpose()
  852. {
  853. for(U j = 0; j < J; j++)
  854. {
  855. for(U i = j + 1; i < I; i++)
  856. {
  857. T tmp = m_arr2[j][i];
  858. m_arr2[j][i] = m_arr2[i][j];
  859. m_arr2[i][j] = tmp;
  860. }
  861. }
  862. }
  863. ANKI_ENABLE_METHOD(J == I && HAS_SIMD)
  864. void transpose()
  865. {
  866. _MM_TRANSPOSE4_PS(m_simd[0], m_simd[1], m_simd[2], m_simd[3]);
  867. }
  868. void transposeRotationPart()
  869. {
  870. for(U j = 0; j < 3; j++)
  871. {
  872. for(U i = j + 1; i < 3; i++)
  873. {
  874. T tmp = m_arr2[j][i];
  875. m_arr2[j][i] = m_arr2[i][j];
  876. m_arr2[i][j] = tmp;
  877. }
  878. }
  879. }
  880. ANKI_ENABLE_METHOD(I == J)
  881. TMat getTransposed() const
  882. {
  883. TMat out;
  884. for(U j = 0; j < J; j++)
  885. {
  886. for(U i = 0; i < I; i++)
  887. {
  888. out.m_arr2[i][j] = m_arr2[j][i];
  889. }
  890. }
  891. return out;
  892. }
  893. ANKI_ENABLE_METHOD(I == 3 && J == 3)
  894. T getDet() const
  895. {
  896. const auto& m = *this;
  897. // For the accurate method see < r664
  898. return m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) - m(0, 1) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0))
  899. + m(0, 2) * (m(0, 1) * m(2, 1) - m(1, 1) * m(2, 0));
  900. }
  901. ANKI_ENABLE_METHOD(I == 4 && J == 4)
  902. T getDet() const
  903. {
  904. const auto& t = *this;
  905. return t(0, 3) * t(1, 2) * t(2, 1) * t(3, 0) - t(0, 2) * t(1, 3) * t(2, 1) * t(3, 0)
  906. - t(0, 3) * t(1, 1) * t(2, 2) * t(3, 0) + t(0, 1) * t(1, 3) * t(2, 2) * t(3, 0)
  907. + t(0, 2) * t(1, 1) * t(2, 3) * t(3, 0) - t(0, 1) * t(1, 2) * t(2, 3) * t(3, 0)
  908. - t(0, 3) * t(1, 2) * t(2, 0) * t(3, 1) + t(0, 2) * t(1, 3) * t(2, 0) * t(3, 1)
  909. + t(0, 3) * t(1, 0) * t(2, 2) * t(3, 1) - t(0, 0) * t(1, 3) * t(2, 2) * t(3, 1)
  910. - t(0, 2) * t(1, 0) * t(2, 3) * t(3, 1) + t(0, 0) * t(1, 2) * t(2, 3) * t(3, 1)
  911. + t(0, 3) * t(1, 1) * t(2, 0) * t(3, 2) - t(0, 1) * t(1, 3) * t(2, 0) * t(3, 2)
  912. - t(0, 3) * t(1, 0) * t(2, 1) * t(3, 2) + t(0, 0) * t(1, 3) * t(2, 1) * t(3, 2)
  913. + t(0, 1) * t(1, 0) * t(2, 3) * t(3, 2) - t(0, 0) * t(1, 1) * t(2, 3) * t(3, 2)
  914. - t(0, 2) * t(1, 1) * t(2, 0) * t(3, 3) + t(0, 1) * t(1, 2) * t(2, 0) * t(3, 3)
  915. + t(0, 2) * t(1, 0) * t(2, 1) * t(3, 3) - t(0, 0) * t(1, 2) * t(2, 1) * t(3, 3)
  916. - t(0, 1) * t(1, 0) * t(2, 2) * t(3, 3) + t(0, 0) * t(1, 1) * t(2, 2) * t(3, 3);
  917. }
  918. ANKI_ENABLE_METHOD(I == 3 && J == 3)
  919. TMat getInverse() const
  920. {
  921. // Using Gramer's method Inv(A) = (1 / getDet(A)) * Adj(A)
  922. const TMat& m = *this;
  923. TMat r;
  924. // compute determinant
  925. const T cofactor0 = m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1);
  926. const T cofactor3 = m(0, 2) * m(2, 1) - m(0, 1) * m(2, 2);
  927. const T cofactor6 = m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1);
  928. const T det = m(0, 0) * cofactor0 + m(1, 0) * cofactor3 + m(2, 0) * cofactor6;
  929. ANKI_ASSERT(!isZero<T>(det)); // Cannot invert det == 0
  930. // create adjoint matrix and multiply by 1/det to get inverse
  931. const T invDet = 1.0 / det;
  932. r(0, 0) = invDet * cofactor0;
  933. r(0, 1) = invDet * cofactor3;
  934. r(0, 2) = invDet * cofactor6;
  935. r(1, 0) = invDet * (m(1, 2) * m(2, 0) - m(1, 0) * m(2, 2));
  936. r(1, 1) = invDet * (m(0, 0) * m(2, 2) - m(0, 2) * m(2, 0));
  937. r(1, 2) = invDet * (m(0, 2) * m(1, 0) - m(0, 0) * m(1, 2));
  938. r(2, 0) = invDet * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0));
  939. r(2, 1) = invDet * (m(0, 1) * m(2, 0) - m(0, 0) * m(2, 1));
  940. r(2, 2) = invDet * (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0));
  941. return r;
  942. }
  943. /// Invert using Cramer's rule
  944. ANKI_ENABLE_METHOD(I == 4 && J == 4)
  945. TMat getInverse() const
  946. {
  947. Array<T, 12> tmp;
  948. const auto& in = (*this);
  949. TMat m4;
  950. tmp[0] = in(2, 2) * in(3, 3);
  951. tmp[1] = in(3, 2) * in(2, 3);
  952. tmp[2] = in(1, 2) * in(3, 3);
  953. tmp[3] = in(3, 2) * in(1, 3);
  954. tmp[4] = in(1, 2) * in(2, 3);
  955. tmp[5] = in(2, 2) * in(1, 3);
  956. tmp[6] = in(0, 2) * in(3, 3);
  957. tmp[7] = in(3, 2) * in(0, 3);
  958. tmp[8] = in(0, 2) * in(2, 3);
  959. tmp[9] = in(2, 2) * in(0, 3);
  960. tmp[10] = in(0, 2) * in(1, 3);
  961. tmp[11] = in(1, 2) * in(0, 3);
  962. m4(0, 0) = tmp[0] * in(1, 1) + tmp[3] * in(2, 1) + tmp[4] * in(3, 1);
  963. m4(0, 0) -= tmp[1] * in(1, 1) + tmp[2] * in(2, 1) + tmp[5] * in(3, 1);
  964. m4(0, 1) = tmp[1] * in(0, 1) + tmp[6] * in(2, 1) + tmp[9] * in(3, 1);
  965. m4(0, 1) -= tmp[0] * in(0, 1) + tmp[7] * in(2, 1) + tmp[8] * in(3, 1);
  966. m4(0, 2) = tmp[2] * in(0, 1) + tmp[7] * in(1, 1) + tmp[10] * in(3, 1);
  967. m4(0, 2) -= tmp[3] * in(0, 1) + tmp[6] * in(1, 1) + tmp[11] * in(3, 1);
  968. m4(0, 3) = tmp[5] * in(0, 1) + tmp[8] * in(1, 1) + tmp[11] * in(2, 1);
  969. m4(0, 3) -= tmp[4] * in(0, 1) + tmp[9] * in(1, 1) + tmp[10] * in(2, 1);
  970. m4(1, 0) = tmp[1] * in(1, 0) + tmp[2] * in(2, 0) + tmp[5] * in(3, 0);
  971. m4(1, 0) -= tmp[0] * in(1, 0) + tmp[3] * in(2, 0) + tmp[4] * in(3, 0);
  972. m4(1, 1) = tmp[0] * in(0, 0) + tmp[7] * in(2, 0) + tmp[8] * in(3, 0);
  973. m4(1, 1) -= tmp[1] * in(0, 0) + tmp[6] * in(2, 0) + tmp[9] * in(3, 0);
  974. m4(1, 2) = tmp[3] * in(0, 0) + tmp[6] * in(1, 0) + tmp[11] * in(3, 0);
  975. m4(1, 2) -= tmp[2] * in(0, 0) + tmp[7] * in(1, 0) + tmp[10] * in(3, 0);
  976. m4(1, 3) = tmp[4] * in(0, 0) + tmp[9] * in(1, 0) + tmp[10] * in(2, 0);
  977. m4(1, 3) -= tmp[5] * in(0, 0) + tmp[8] * in(1, 0) + tmp[11] * in(2, 0);
  978. tmp[0] = in(2, 0) * in(3, 1);
  979. tmp[1] = in(3, 0) * in(2, 1);
  980. tmp[2] = in(1, 0) * in(3, 1);
  981. tmp[3] = in(3, 0) * in(1, 1);
  982. tmp[4] = in(1, 0) * in(2, 1);
  983. tmp[5] = in(2, 0) * in(1, 1);
  984. tmp[6] = in(0, 0) * in(3, 1);
  985. tmp[7] = in(3, 0) * in(0, 1);
  986. tmp[8] = in(0, 0) * in(2, 1);
  987. tmp[9] = in(2, 0) * in(0, 1);
  988. tmp[10] = in(0, 0) * in(1, 1);
  989. tmp[11] = in(1, 0) * in(0, 1);
  990. m4(2, 0) = tmp[0] * in(1, 3) + tmp[3] * in(2, 3) + tmp[4] * in(3, 3);
  991. m4(2, 0) -= tmp[1] * in(1, 3) + tmp[2] * in(2, 3) + tmp[5] * in(3, 3);
  992. m4(2, 1) = tmp[1] * in(0, 3) + tmp[6] * in(2, 3) + tmp[9] * in(3, 3);
  993. m4(2, 1) -= tmp[0] * in(0, 3) + tmp[7] * in(2, 3) + tmp[8] * in(3, 3);
  994. m4(2, 2) = tmp[2] * in(0, 3) + tmp[7] * in(1, 3) + tmp[10] * in(3, 3);
  995. m4(2, 2) -= tmp[3] * in(0, 3) + tmp[6] * in(1, 3) + tmp[11] * in(3, 3);
  996. m4(2, 3) = tmp[5] * in(0, 3) + tmp[8] * in(1, 3) + tmp[11] * in(2, 3);
  997. m4(2, 3) -= tmp[4] * in(0, 3) + tmp[9] * in(1, 3) + tmp[10] * in(2, 3);
  998. m4(3, 0) = tmp[2] * in(2, 2) + tmp[5] * in(3, 2) + tmp[1] * in(1, 2);
  999. m4(3, 0) -= tmp[4] * in(3, 2) + tmp[0] * in(1, 2) + tmp[3] * in(2, 2);
  1000. m4(3, 1) = tmp[8] * in(3, 2) + tmp[0] * in(0, 2) + tmp[7] * in(2, 2);
  1001. m4(3, 1) -= tmp[6] * in(2, 2) + tmp[9] * in(3, 2) + tmp[1] * in(0, 2);
  1002. m4(3, 2) = tmp[6] * in(1, 2) + tmp[11] * in(3, 2) + tmp[3] * in(0, 2);
  1003. m4(3, 2) -= tmp[10] * in(3, 2) + tmp[2] * in(0, 2) + tmp[7] * in(1, 2);
  1004. m4(3, 3) = tmp[10] * in(2, 2) + tmp[4] * in(0, 2) + tmp[9] * in(1, 2);
  1005. m4(3, 3) -= tmp[8] * in(1, 2) + tmp[11] * in(2, 2) + tmp[5] * in(0, 2);
  1006. T det = in(0, 0) * m4(0, 0) + in(1, 0) * m4(0, 1) + in(2, 0) * m4(0, 2) + in(3, 0) * m4(0, 3);
  1007. ANKI_ASSERT(!isZero<T>(det)); // Cannot invert, det == 0
  1008. det = T(1) / det;
  1009. m4 *= det;
  1010. return m4;
  1011. }
  1012. /// See getInverse
  1013. ANKI_ENABLE_METHOD((I == 4 && J == 4) || (I == 3 && J == 3))
  1014. void invert()
  1015. {
  1016. (*this) = getInverse();
  1017. }
  1018. /// 12 muls, 27 adds. Something like m4 = m0 * m1 but without touching the 4rth row and allot faster
  1019. ANKI_ENABLE_METHOD(I == 4 && J == 4)
  1020. static TMat combineTransformations(const TMat& m0, const TMat& m1)
  1021. {
  1022. // See the clean code in < r664
  1023. // one of the 2 mat4 doesnt represent transformation
  1024. ANKI_ASSERT(isZero<T>(m0(3, 0) + m0(3, 1) + m0(3, 2) + m0(3, 3) - 1.0)
  1025. && isZero<T>(m1(3, 0) + m1(3, 1) + m1(3, 2) + m1(3, 3) - 1.0));
  1026. TMat m4;
  1027. m4(0, 0) = m0(0, 0) * m1(0, 0) + m0(0, 1) * m1(1, 0) + m0(0, 2) * m1(2, 0);
  1028. m4(0, 1) = m0(0, 0) * m1(0, 1) + m0(0, 1) * m1(1, 1) + m0(0, 2) * m1(2, 1);
  1029. m4(0, 2) = m0(0, 0) * m1(0, 2) + m0(0, 1) * m1(1, 2) + m0(0, 2) * m1(2, 2);
  1030. m4(1, 0) = m0(1, 0) * m1(0, 0) + m0(1, 1) * m1(1, 0) + m0(1, 2) * m1(2, 0);
  1031. m4(1, 1) = m0(1, 0) * m1(0, 1) + m0(1, 1) * m1(1, 1) + m0(1, 2) * m1(2, 1);
  1032. m4(1, 2) = m0(1, 0) * m1(0, 2) + m0(1, 1) * m1(1, 2) + m0(1, 2) * m1(2, 2);
  1033. m4(2, 0) = m0(2, 0) * m1(0, 0) + m0(2, 1) * m1(1, 0) + m0(2, 2) * m1(2, 0);
  1034. m4(2, 1) = m0(2, 0) * m1(0, 1) + m0(2, 1) * m1(1, 1) + m0(2, 2) * m1(2, 1);
  1035. m4(2, 2) = m0(2, 0) * m1(0, 2) + m0(2, 1) * m1(1, 2) + m0(2, 2) * m1(2, 2);
  1036. m4(0, 3) = m0(0, 0) * m1(0, 3) + m0(0, 1) * m1(1, 3) + m0(0, 2) * m1(2, 3) + m0(0, 3);
  1037. m4(1, 3) = m0(1, 0) * m1(0, 3) + m0(1, 1) * m1(1, 3) + m0(1, 2) * m1(2, 3) + m0(1, 3);
  1038. m4(2, 3) = m0(2, 0) * m1(0, 3) + m0(2, 1) * m1(1, 3) + m0(2, 2) * m1(2, 3) + m0(2, 3);
  1039. m4(3, 0) = m4(3, 1) = m4(3, 2) = 0.0;
  1040. m4(3, 3) = 1.0;
  1041. return m4;
  1042. }
  1043. /// Create a new matrix that is equivalent to Mat4(this)*Mat4(b)
  1044. ANKI_ENABLE_METHOD(J == 3 && I == 4 && !HAS_SIMD)
  1045. TMat combineTransformations(const TMat& b) const
  1046. {
  1047. const auto& a = *this;
  1048. TMat c;
  1049. c(0, 0) = a(0, 0) * b(0, 0) + a(0, 1) * b(1, 0) + a(0, 2) * b(2, 0);
  1050. c(0, 1) = a(0, 0) * b(0, 1) + a(0, 1) * b(1, 1) + a(0, 2) * b(2, 1);
  1051. c(0, 2) = a(0, 0) * b(0, 2) + a(0, 1) * b(1, 2) + a(0, 2) * b(2, 2);
  1052. c(1, 0) = a(1, 0) * b(0, 0) + a(1, 1) * b(1, 0) + a(1, 2) * b(2, 0);
  1053. c(1, 1) = a(1, 0) * b(0, 1) + a(1, 1) * b(1, 1) + a(1, 2) * b(2, 1);
  1054. c(1, 2) = a(1, 0) * b(0, 2) + a(1, 1) * b(1, 2) + a(1, 2) * b(2, 2);
  1055. c(2, 0) = a(2, 0) * b(0, 0) + a(2, 1) * b(1, 0) + a(2, 2) * b(2, 0);
  1056. c(2, 1) = a(2, 0) * b(0, 1) + a(2, 1) * b(1, 1) + a(2, 2) * b(2, 1);
  1057. c(2, 2) = a(2, 0) * b(0, 2) + a(2, 1) * b(1, 2) + a(2, 2) * b(2, 2);
  1058. c(0, 3) = a(0, 0) * b(0, 3) + a(0, 1) * b(1, 3) + a(0, 2) * b(2, 3) + a(0, 3);
  1059. c(1, 3) = a(1, 0) * b(0, 3) + a(1, 1) * b(1, 3) + a(1, 2) * b(2, 3) + a(1, 3);
  1060. c(2, 3) = a(2, 0) * b(0, 3) + a(2, 1) * b(1, 3) + a(2, 2) * b(2, 3) + a(2, 3);
  1061. return c;
  1062. }
  1063. ANKI_ENABLE_METHOD(J == 3 && I == 4 && HAS_SIMD)
  1064. TMat combineTransformations(const TMat& b) const
  1065. {
  1066. TMat c;
  1067. const auto& a = *this;
  1068. for(U i = 0; i < 3; i++)
  1069. {
  1070. __m128 t1, t2;
  1071. t1 = _mm_set1_ps(a(i, 0));
  1072. t2 = _mm_mul_ps(b.m_simd[0], t1);
  1073. t1 = _mm_set1_ps(a(i, 1));
  1074. t2 = _mm_add_ps(_mm_mul_ps(b.m_simd[1], t1), t2);
  1075. t1 = _mm_set1_ps(a(i, 2));
  1076. t2 = _mm_add_ps(_mm_mul_ps(b.m_simd[2], t1), t2);
  1077. TVec<T, 4> v4(0.0, 0.0, 0.0, a(i, 3));
  1078. t2 = _mm_add_ps(v4.getSimd(), t2);
  1079. c.m_simd[i] = t2;
  1080. }
  1081. return c;
  1082. }
  1083. /// Calculate a perspective projection matrix. The z is mapped in [0, 1] range just like DX and Vulkan.
  1084. ANKI_ENABLE_METHOD(I == 4 && J == 4)
  1085. static ANKI_USE_RESULT TMat calculatePerspectiveProjectionMatrix(T fovX, T fovY, T near, T far)
  1086. {
  1087. ANKI_ASSERT(fovX > T(0) && fovY > T(0) && near > T(0) && far > T(0));
  1088. const T g = near - far;
  1089. const T f = T(1) / tan(fovY / T(2)); // f = cot(fovY/2)
  1090. TMat proj;
  1091. proj(0, 0) = f * (fovY / fovX); // = f/aspectRatio;
  1092. proj(0, 1) = T(0);
  1093. proj(0, 2) = T(0);
  1094. proj(0, 3) = T(0);
  1095. proj(1, 0) = T(0);
  1096. proj(1, 1) = f;
  1097. proj(1, 2) = T(0);
  1098. proj(1, 3) = T(0);
  1099. proj(2, 0) = T(0);
  1100. proj(2, 1) = T(0);
  1101. proj(2, 2) = far / g;
  1102. proj(2, 3) = (far * near) / g;
  1103. proj(3, 0) = T(0);
  1104. proj(3, 1) = T(0);
  1105. proj(3, 2) = T(-1);
  1106. proj(3, 3) = T(0);
  1107. return proj;
  1108. }
  1109. /// Calculate an orthographic projection matrix. The z is mapped in [0, 1] range just like DX and Vulkan.
  1110. ANKI_ENABLE_METHOD(I == 4 && J == 4)
  1111. static ANKI_USE_RESULT TMat calculateOrthographicProjectionMatrix(T right, T left, T top, T bottom, T near, T far)
  1112. {
  1113. ANKI_ASSERT(right != T(0) && left != T(0) && top != T(0) && bottom != T(0) && near != T(0) && far != T(0));
  1114. const T difx = right - left;
  1115. const T dify = top - bottom;
  1116. const T difz = far - near;
  1117. const T tx = -(right + left) / difx;
  1118. const T ty = -(top + bottom) / dify;
  1119. const T tz = -near / difz;
  1120. TMat m;
  1121. m(0, 0) = T(2) / difx;
  1122. m(0, 1) = T(0);
  1123. m(0, 2) = T(0);
  1124. m(0, 3) = tx;
  1125. m(1, 0) = T(0);
  1126. m(1, 1) = T(2) / dify;
  1127. m(1, 2) = T(0);
  1128. m(1, 3) = ty;
  1129. m(2, 0) = T(0);
  1130. m(2, 1) = T(0);
  1131. m(2, 2) = T(-1) / difz;
  1132. m(2, 3) = tz;
  1133. m(3, 0) = T(0);
  1134. m(3, 1) = T(0);
  1135. m(3, 2) = T(0);
  1136. m(3, 3) = T(1);
  1137. return m;
  1138. }
  1139. /// Given the parameters that construct a projection matrix extract 4 values that can be used to unproject a point
  1140. /// from NDC to view space.
  1141. /// @code
  1142. /// Vec4 unprojParams = calculatePerspectiveUnprojectionParams(...);
  1143. /// F32 z = unprojParams.z() / (unprojParams.w() + depth);
  1144. /// Vec2 xy = ndc.xy() * unprojParams.xy() * z;
  1145. /// Vec3 posViewSpace(xy, z);
  1146. /// @endcode
  1147. ANKI_ENABLE_METHOD(I == 4 && J == 4)
  1148. static TVec<T, 4> calculatePerspectiveUnprojectionParams(T fovX, T fovY, T near, T far)
  1149. {
  1150. TVec<T, 4> out;
  1151. const T g = near - far;
  1152. const T f = T(1) / tan(fovY / T(2)); // f = cot(fovY/2)
  1153. const T m00 = f * (fovY / fovX);
  1154. const T m11 = f;
  1155. const T m22 = far / g;
  1156. const T m23 = (far * near) / g;
  1157. // First, clip = (m * Pv) where Pv is the view space position.
  1158. // ndc.z = clip.z / clip.w = (m22 * Pv.z + m23) / -Pv.z. Note that ndc.z == depth in zero_to_one projection.
  1159. // Solving that for Pv.z we get
  1160. // Pv.z = A / (depth + B)
  1161. // where A = -m23 and B = m22
  1162. // so we save the A and B in the projection params vector
  1163. out.z() = -m23;
  1164. out.w() = m22;
  1165. // Using the same logic the Pv.x = x' * w / m00
  1166. // so Pv.x = x' * Pv.z * (-1 / m00)
  1167. out.x() = -T(1.0) / m00;
  1168. // Same for y
  1169. out.y() = -T(1.0) / m11;
  1170. return out;
  1171. }
  1172. /// Assuming this is a projection matrix extract the unprojection parameters. See
  1173. /// calculatePerspectiveUnprojectionParams for more info.
  1174. ANKI_ENABLE_METHOD(I == 4 && J == 4)
  1175. TVec<T, 4> extractPerspectiveUnprojectionParams() const
  1176. {
  1177. TVec<T, 4> out;
  1178. const auto& m = *this;
  1179. out.z() = -m(2, 3);
  1180. out.w() = m(2, 2);
  1181. out.x() = -T(1.0) / m(0, 0);
  1182. out.y() = -T(1.0) / m(1, 1);
  1183. return out;
  1184. }
  1185. /// If we suppose this matrix represents a transformation, return the inverted transformation
  1186. ANKI_ENABLE_METHOD(I == 4 && J == 4)
  1187. TMat getInverseTransformation() const
  1188. {
  1189. const TMat<T, 3, 3> invertedRot = getRotationPart().getTransposed();
  1190. TVec<T, 3> invertedTsl = getTranslationPart().xyz();
  1191. invertedTsl = -(invertedRot * invertedTsl);
  1192. return TMat(invertedTsl.xyz0(), invertedRot);
  1193. }
  1194. /// @note 9 muls, 9 adds
  1195. ANKI_ENABLE_METHOD(I == 4 && J == 4)
  1196. TVec<T, 3> transform(const TVec<T, 3>& v) const
  1197. {
  1198. const auto& m = *this;
  1199. return TVec<T, 3>(m(0, 0) * v.x() + m(0, 1) * v.y() + m(0, 2) * v.z() + m(0, 3),
  1200. m(1, 0) * v.x() + m(1, 1) * v.y() + m(1, 2) * v.z() + m(1, 3),
  1201. m(2, 0) * v.x() + m(2, 1) * v.y() + m(2, 2) * v.z() + m(2, 3));
  1202. }
  1203. /// Create a new transform matrix position at eye and looking at refPoint.
  1204. template<U VEC_DIMS, ANKI_ENABLE(J == 3 && I == 4 && VEC_DIMS >= 3)>
  1205. static TMat lookAt(const TVec<T, VEC_DIMS>& eye, const TVec<T, VEC_DIMS>& refPoint, const TVec<T, VEC_DIMS>& up)
  1206. {
  1207. const TVec<T, 3> vdir = (refPoint.xyz() - eye.xyz()).getNormalized();
  1208. const TVec<T, 3> vup = (up.xyz() - vdir * up.xyz().dot(vdir)).getNormalized();
  1209. const TVec<T, 3> vside = vdir.cross(vup);
  1210. TMat out;
  1211. out.setColumns(vside, vup, -vdir, eye.xyz());
  1212. return out;
  1213. }
  1214. /// Create a new transform matrix position at eye and looking at refPoint.
  1215. template<U VEC_DIMS, ANKI_ENABLE(J == 4 && I == 4 && VEC_DIMS >= 3)>
  1216. static TMat lookAt(const TVec<T, VEC_DIMS>& eye, const TVec<T, VEC_DIMS>& refPoint, const TVec<T, VEC_DIMS>& up)
  1217. {
  1218. const TVec<T, 4> vdir = (refPoint.xyz0() - eye.xyz0()).getNormalized();
  1219. const TVec<T, 4> vup = (up.xyz0() - vdir * up.xyz0().dot(vdir)).getNormalized();
  1220. const TVec<T, 4> vside = vdir.cross(vup);
  1221. TMat out;
  1222. out.setColumns(vside, vup, -vdir, eye.xyz1());
  1223. return out;
  1224. }
  1225. TMat lerp(const TMat& b, T t) const
  1226. {
  1227. return ((*this) * (1.0 - t)) + (b * t);
  1228. }
  1229. static TMat getZero()
  1230. {
  1231. return TMat(0.0);
  1232. }
  1233. void setZero()
  1234. {
  1235. *this = getZero();
  1236. }
  1237. ANKI_ENABLE_METHOD(I == 3 && J == 3)
  1238. static TMat getIdentity()
  1239. {
  1240. return TMat(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0);
  1241. }
  1242. ANKI_ENABLE_METHOD(I == 4 && J == 4)
  1243. static TMat getIdentity()
  1244. {
  1245. return TMat(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0);
  1246. }
  1247. ANKI_ENABLE_METHOD(I == 4 && J == 3)
  1248. static TMat getIdentity()
  1249. {
  1250. return TMat(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
  1251. }
  1252. void setIdentity()
  1253. {
  1254. (*this) = getIdentity();
  1255. }
  1256. static constexpr U8 getSize()
  1257. {
  1258. return U8(I * J);
  1259. }
  1260. ANKI_ENABLE_METHOD(std::is_floating_point<T>::value)
  1261. void toString(StringAuto& str) const
  1262. {
  1263. for(U j = 0; j < J; ++j)
  1264. {
  1265. for(U i = 0; i < I; ++i)
  1266. {
  1267. CString fmt;
  1268. if(i == I - 1 && j == J - 1)
  1269. {
  1270. fmt = "%f";
  1271. }
  1272. else if(i == I - 1)
  1273. {
  1274. fmt = "%f\n";
  1275. }
  1276. else
  1277. {
  1278. fmt = "%f ";
  1279. }
  1280. str.append(StringAuto(str.getAllocator()).sprintf(fmt, m_arr2[j][i]));
  1281. }
  1282. }
  1283. }
  1284. /// @}
  1285. protected:
  1286. static constexpr U N = I * J;
  1287. /// @name Data members
  1288. /// @{
  1289. union
  1290. {
  1291. Array<T, N> m_arr1;
  1292. Array2d<T, J, I> m_arr2;
  1293. T m_carr1[N]; ///< For easier debugging with gdb
  1294. T m_carr2[J][I]; ///< For easier debugging with gdb
  1295. SimdArray m_simd;
  1296. };
  1297. /// @}
  1298. };
  1299. /// @memberof TMat
  1300. template<typename T, U J, U I>
  1301. TMat<T, J, I> operator+(const T f, const TMat<T, J, I>& m)
  1302. {
  1303. return m + f;
  1304. }
  1305. /// @memberof TMat
  1306. template<typename T, U J, U I>
  1307. TMat<T, J, I> operator-(const T f, const TMat<T, J, I>& m)
  1308. {
  1309. TMat<T, J, I> out;
  1310. for(U i = 0; i < J * I; i++)
  1311. {
  1312. out[i] = f - m[i];
  1313. }
  1314. return out;
  1315. }
  1316. /// @memberof TMat
  1317. template<typename T, U J, U I>
  1318. TMat<T, J, I> operator*(const T f, const TMat<T, J, I>& m)
  1319. {
  1320. return m * f;
  1321. }
  1322. /// @memberof TMat
  1323. template<typename T, U J, U I>
  1324. TMat<T, J, I> operator/(const T f, const TMat<T, 3, 3>& m3)
  1325. {
  1326. TMat<T, J, I> out;
  1327. for(U i = 0; i < J * I; i++)
  1328. {
  1329. ANKI_ASSERT(m3[i] != T(0));
  1330. out[i] = f / m3[i];
  1331. }
  1332. return out;
  1333. }
  1334. /// F32 3x3 matrix
  1335. using Mat3 = TMat<F32, 3, 3>;
  1336. static_assert(sizeof(Mat3) == sizeof(F32) * 3 * 3, "Incorrect size");
  1337. /// F64 3x3 matrix
  1338. using DMat3 = TMat<F64, 3, 3>;
  1339. static_assert(sizeof(DMat3) == sizeof(F64) * 3 * 3, "Incorrect size");
  1340. /// F32 4x4 matrix
  1341. using Mat4 = TMat<F32, 4, 4>;
  1342. static_assert(sizeof(Mat4) == sizeof(F32) * 4 * 4, "Incorrect size");
  1343. /// F64 4x4 matrix
  1344. using DMat4 = TMat<F64, 4, 4>;
  1345. static_assert(sizeof(DMat4) == sizeof(F64) * 4 * 4, "Incorrect size");
  1346. /// F32 3x4 matrix
  1347. using Mat3x4 = TMat<F32, 3, 4>;
  1348. static_assert(sizeof(Mat3x4) == sizeof(F32) * 3 * 4, "Incorrect size");
  1349. /// F64 3x4 matrix
  1350. using DMat3x4 = TMat<F64, 3, 4>;
  1351. static_assert(sizeof(DMat3x4) == sizeof(F64) * 3 * 4, "Incorrect size");
  1352. /// @}
  1353. } // end namespace anki