Mat4.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. // Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <anki/math/CommonIncludes.h>
  7. namespace anki
  8. {
  9. /// @addtogroup math
  10. /// @{
  11. /// Template struct that gives the type of the TVec4 SIMD
  12. template<typename T>
  13. class TMat4Simd
  14. {
  15. public:
  16. using Type = Array<T, 16>;
  17. };
  18. #if ANKI_SIMD == ANKI_SIMD_SSE
  19. // Specialize for F32
  20. template<>
  21. class TMat4Simd<F32>
  22. {
  23. public:
  24. using Type = Array<__m128, 4>;
  25. };
  26. #endif
  27. /// 4x4 Matrix. Used mainly for transformations but not necessarily. Its
  28. /// row major. SSE optimized
  29. /// @note TMat4*TMat4: 64 muls 48 adds
  30. template<typename T>
  31. class alignas(16) TMat4 : public TMat<T,
  32. 4,
  33. 4,
  34. typename TMat4Simd<T>::Type,
  35. TMat4<T>,
  36. TVec4<T>,
  37. TVec4<T>>
  38. {
  39. /// @name Friends
  40. /// @{
  41. template<typename Y>
  42. friend TMat4<Y> operator+(const Y f, const TMat4<Y>& m4);
  43. template<typename Y>
  44. friend TMat4<Y> operator-(const Y f, const TMat4<Y>& m4);
  45. template<typename Y>
  46. friend TMat4<Y> operator*(const Y f, const TMat4<Y>& m4);
  47. template<typename Y>
  48. friend TMat4<Y> operator/(const Y f, const TMat4<Y>& m4);
  49. /// @}
  50. public:
  51. using Base = TMat<T,
  52. 4,
  53. 4,
  54. typename TMat4Simd<T>::Type,
  55. TMat4<T>,
  56. TVec4<T>,
  57. TVec4<T>>;
  58. using Base::getTranslationPart;
  59. using Base::setTranslationPart;
  60. using Base::getRotationPart;
  61. using Base::setRotationPart;
  62. /// @name Constructors
  63. /// @{
  64. TMat4()
  65. : Base()
  66. {
  67. }
  68. TMat4(const TMat4& b)
  69. : Base(b)
  70. {
  71. }
  72. TMat4(T m00,
  73. T m01,
  74. T m02,
  75. T m03,
  76. T m10,
  77. T m11,
  78. T m12,
  79. T m13,
  80. T m20,
  81. T m21,
  82. T m22,
  83. T m23,
  84. T m30,
  85. T m31,
  86. T m32,
  87. T m33)
  88. {
  89. TMat4& m = *this;
  90. m(0, 0) = m00;
  91. m(0, 1) = m01;
  92. m(0, 2) = m02;
  93. m(0, 3) = m03;
  94. m(1, 0) = m10;
  95. m(1, 1) = m11;
  96. m(1, 2) = m12;
  97. m(1, 3) = m13;
  98. m(2, 0) = m20;
  99. m(2, 1) = m21;
  100. m(2, 2) = m22;
  101. m(2, 3) = m23;
  102. m(3, 0) = m30;
  103. m(3, 1) = m31;
  104. m(3, 2) = m32;
  105. m(3, 3) = m33;
  106. }
  107. explicit TMat4(const T f)
  108. : Base(f)
  109. {
  110. }
  111. explicit TMat4(const TMat3<T>& m3)
  112. {
  113. TMat4& m = *this;
  114. m(0, 0) = m3(0, 0);
  115. m(0, 1) = m3(0, 1);
  116. m(0, 2) = m3(0, 2);
  117. m(0, 3) = 0.0;
  118. m(1, 0) = m3(1, 0);
  119. m(1, 1) = m3(1, 1);
  120. m(1, 2) = m3(1, 2);
  121. m(1, 3) = 0.0;
  122. m(2, 0) = m3(2, 0);
  123. m(2, 1) = m3(2, 1);
  124. m(2, 2) = m3(2, 2);
  125. m(2, 3) = 0.0;
  126. m(3, 0) = 0.0;
  127. m(3, 1) = 0.0;
  128. m(3, 2) = 0.0;
  129. m(3, 3) = 1.0;
  130. }
  131. explicit TMat4(const TVec3<T>& v)
  132. {
  133. TMat4& m = *this;
  134. m(0, 0) = 1.0;
  135. m(0, 1) = 0.0;
  136. m(0, 2) = 0.0;
  137. m(0, 3) = v.x();
  138. m(1, 0) = 0.0;
  139. m(1, 1) = 1.0;
  140. m(1, 2) = 0.0;
  141. m(1, 3) = v.y();
  142. m(2, 0) = 0.0;
  143. m(2, 1) = 0.0;
  144. m(2, 2) = 1.0;
  145. m(2, 3) = v.z();
  146. m(3, 0) = 0.0;
  147. m(3, 1) = 0.0;
  148. m(3, 2) = 0.0;
  149. m(3, 3) = 1.0;
  150. }
  151. explicit TMat4(const TVec4<T>& v)
  152. {
  153. TMat4& m = *this;
  154. m(0, 0) = 1.0;
  155. m(0, 1) = 0.0;
  156. m(0, 2) = 0.0;
  157. m(0, 3) = v.x();
  158. m(1, 0) = 0.0;
  159. m(1, 1) = 1.0;
  160. m(1, 2) = 0.0;
  161. m(1, 3) = v.y();
  162. m(2, 0) = 0.0;
  163. m(2, 1) = 0.0;
  164. m(2, 2) = 1.0;
  165. m(2, 3) = v.z();
  166. m(3, 0) = 0.0;
  167. m(3, 1) = 0.0;
  168. m(3, 2) = 0.0;
  169. m(3, 3) = v.w();
  170. }
  171. TMat4(const TVec4<T>& transl, const TMat3<T>& rot)
  172. {
  173. setRotationPart(rot);
  174. setTranslationPart(transl);
  175. TMat4& m = *this;
  176. m(3, 0) = m(3, 1) = m(3, 2) = 0.0;
  177. }
  178. TMat4(const TVec4<T>& transl, const TMat3<T>& rot, const T scale)
  179. {
  180. if(isZero<T>(scale - 1.0))
  181. {
  182. setRotationPart(rot);
  183. }
  184. else
  185. {
  186. setRotationPart(rot * scale);
  187. }
  188. setTranslationPart(transl);
  189. TMat4& m = *this;
  190. m(3, 0) = m(3, 1) = m(3, 2) = 0.0;
  191. }
  192. explicit TMat4(const TTransform<T>& t)
  193. : TMat4(TVec4<T>(t.getOrigin().xyz(), 1.0),
  194. t.getRotation().getRotationPart(),
  195. t.getScale())
  196. {
  197. }
  198. /// @}
  199. /// @name Other
  200. /// @{
  201. T getDet() const
  202. {
  203. const TMat4& t = *this;
  204. return t(0, 3) * t(1, 2) * t(2, 1) * t(3, 0)
  205. - t(0, 2) * t(1, 3) * t(2, 1) * t(3, 0)
  206. - t(0, 3) * t(1, 1) * t(2, 2) * t(3, 0)
  207. + t(0, 1) * t(1, 3) * t(2, 2) * t(3, 0)
  208. + t(0, 2) * t(1, 1) * t(2, 3) * t(3, 0)
  209. - t(0, 1) * t(1, 2) * t(2, 3) * t(3, 0)
  210. - t(0, 3) * t(1, 2) * t(2, 0) * t(3, 1)
  211. + t(0, 2) * t(1, 3) * t(2, 0) * t(3, 1)
  212. + t(0, 3) * t(1, 0) * t(2, 2) * t(3, 1)
  213. - t(0, 0) * t(1, 3) * t(2, 2) * t(3, 1)
  214. - t(0, 2) * t(1, 0) * t(2, 3) * t(3, 1)
  215. + t(0, 0) * t(1, 2) * t(2, 3) * t(3, 1)
  216. + t(0, 3) * t(1, 1) * t(2, 0) * t(3, 2)
  217. - t(0, 1) * t(1, 3) * t(2, 0) * t(3, 2)
  218. - t(0, 3) * t(1, 0) * t(2, 1) * t(3, 2)
  219. + t(0, 0) * t(1, 3) * t(2, 1) * t(3, 2)
  220. + t(0, 1) * t(1, 0) * t(2, 3) * t(3, 2)
  221. - t(0, 0) * t(1, 1) * t(2, 3) * t(3, 2)
  222. - t(0, 2) * t(1, 1) * t(2, 0) * t(3, 3)
  223. + t(0, 1) * t(1, 2) * t(2, 0) * t(3, 3)
  224. + t(0, 2) * t(1, 0) * t(2, 1) * t(3, 3)
  225. - t(0, 0) * t(1, 2) * t(2, 1) * t(3, 3)
  226. - t(0, 1) * t(1, 0) * t(2, 2) * t(3, 3)
  227. + t(0, 0) * t(1, 1) * t(2, 2) * t(3, 3);
  228. }
  229. /// Invert using Cramer's rule
  230. TMat4 getInverse() const
  231. {
  232. Array<T, 12> tmp;
  233. const TMat4& in = (*this);
  234. TMat4 m4;
  235. tmp[0] = in(2, 2) * in(3, 3);
  236. tmp[1] = in(3, 2) * in(2, 3);
  237. tmp[2] = in(1, 2) * in(3, 3);
  238. tmp[3] = in(3, 2) * in(1, 3);
  239. tmp[4] = in(1, 2) * in(2, 3);
  240. tmp[5] = in(2, 2) * in(1, 3);
  241. tmp[6] = in(0, 2) * in(3, 3);
  242. tmp[7] = in(3, 2) * in(0, 3);
  243. tmp[8] = in(0, 2) * in(2, 3);
  244. tmp[9] = in(2, 2) * in(0, 3);
  245. tmp[10] = in(0, 2) * in(1, 3);
  246. tmp[11] = in(1, 2) * in(0, 3);
  247. m4(0, 0) = tmp[0] * in(1, 1) + tmp[3] * in(2, 1) + tmp[4] * in(3, 1);
  248. m4(0, 0) -= tmp[1] * in(1, 1) + tmp[2] * in(2, 1) + tmp[5] * in(3, 1);
  249. m4(0, 1) = tmp[1] * in(0, 1) + tmp[6] * in(2, 1) + tmp[9] * in(3, 1);
  250. m4(0, 1) -= tmp[0] * in(0, 1) + tmp[7] * in(2, 1) + tmp[8] * in(3, 1);
  251. m4(0, 2) = tmp[2] * in(0, 1) + tmp[7] * in(1, 1) + tmp[10] * in(3, 1);
  252. m4(0, 2) -= tmp[3] * in(0, 1) + tmp[6] * in(1, 1) + tmp[11] * in(3, 1);
  253. m4(0, 3) = tmp[5] * in(0, 1) + tmp[8] * in(1, 1) + tmp[11] * in(2, 1);
  254. m4(0, 3) -= tmp[4] * in(0, 1) + tmp[9] * in(1, 1) + tmp[10] * in(2, 1);
  255. m4(1, 0) = tmp[1] * in(1, 0) + tmp[2] * in(2, 0) + tmp[5] * in(3, 0);
  256. m4(1, 0) -= tmp[0] * in(1, 0) + tmp[3] * in(2, 0) + tmp[4] * in(3, 0);
  257. m4(1, 1) = tmp[0] * in(0, 0) + tmp[7] * in(2, 0) + tmp[8] * in(3, 0);
  258. m4(1, 1) -= tmp[1] * in(0, 0) + tmp[6] * in(2, 0) + tmp[9] * in(3, 0);
  259. m4(1, 2) = tmp[3] * in(0, 0) + tmp[6] * in(1, 0) + tmp[11] * in(3, 0);
  260. m4(1, 2) -= tmp[2] * in(0, 0) + tmp[7] * in(1, 0) + tmp[10] * in(3, 0);
  261. m4(1, 3) = tmp[4] * in(0, 0) + tmp[9] * in(1, 0) + tmp[10] * in(2, 0);
  262. m4(1, 3) -= tmp[5] * in(0, 0) + tmp[8] * in(1, 0) + tmp[11] * in(2, 0);
  263. tmp[0] = in(2, 0) * in(3, 1);
  264. tmp[1] = in(3, 0) * in(2, 1);
  265. tmp[2] = in(1, 0) * in(3, 1);
  266. tmp[3] = in(3, 0) * in(1, 1);
  267. tmp[4] = in(1, 0) * in(2, 1);
  268. tmp[5] = in(2, 0) * in(1, 1);
  269. tmp[6] = in(0, 0) * in(3, 1);
  270. tmp[7] = in(3, 0) * in(0, 1);
  271. tmp[8] = in(0, 0) * in(2, 1);
  272. tmp[9] = in(2, 0) * in(0, 1);
  273. tmp[10] = in(0, 0) * in(1, 1);
  274. tmp[11] = in(1, 0) * in(0, 1);
  275. m4(2, 0) = tmp[0] * in(1, 3) + tmp[3] * in(2, 3) + tmp[4] * in(3, 3);
  276. m4(2, 0) -= tmp[1] * in(1, 3) + tmp[2] * in(2, 3) + tmp[5] * in(3, 3);
  277. m4(2, 1) = tmp[1] * in(0, 3) + tmp[6] * in(2, 3) + tmp[9] * in(3, 3);
  278. m4(2, 1) -= tmp[0] * in(0, 3) + tmp[7] * in(2, 3) + tmp[8] * in(3, 3);
  279. m4(2, 2) = tmp[2] * in(0, 3) + tmp[7] * in(1, 3) + tmp[10] * in(3, 3);
  280. m4(2, 2) -= tmp[3] * in(0, 3) + tmp[6] * in(1, 3) + tmp[11] * in(3, 3);
  281. m4(2, 3) = tmp[5] * in(0, 3) + tmp[8] * in(1, 3) + tmp[11] * in(2, 3);
  282. m4(2, 3) -= tmp[4] * in(0, 3) + tmp[9] * in(1, 3) + tmp[10] * in(2, 3);
  283. m4(3, 0) = tmp[2] * in(2, 2) + tmp[5] * in(3, 2) + tmp[1] * in(1, 2);
  284. m4(3, 0) -= tmp[4] * in(3, 2) + tmp[0] * in(1, 2) + tmp[3] * in(2, 2);
  285. m4(3, 1) = tmp[8] * in(3, 2) + tmp[0] * in(0, 2) + tmp[7] * in(2, 2);
  286. m4(3, 1) -= tmp[6] * in(2, 2) + tmp[9] * in(3, 2) + tmp[1] * in(0, 2);
  287. m4(3, 2) = tmp[6] * in(1, 2) + tmp[11] * in(3, 2) + tmp[3] * in(0, 2);
  288. m4(3, 2) -= tmp[10] * in(3, 2) + tmp[2] * in(0, 2) + tmp[7] * in(1, 2);
  289. m4(3, 3) = tmp[10] * in(2, 2) + tmp[4] * in(0, 2) + tmp[9] * in(1, 2);
  290. m4(3, 3) -= tmp[8] * in(1, 2) + tmp[11] * in(2, 2) + tmp[5] * in(0, 2);
  291. T det = in(0, 0) * m4(0, 0) + in(1, 0) * m4(0, 1) + in(2, 0) * m4(0, 2)
  292. + in(3, 0) * m4(0, 3);
  293. ANKI_ASSERT(!isZero<T>(det)); // Cannot invert, det == 0
  294. det = 1.0 / det;
  295. m4 *= det;
  296. return m4;
  297. }
  298. /// See getInverse
  299. void invert()
  300. {
  301. (*this) = getInverse();
  302. }
  303. /// If we suppose this matrix represents a transformation, return the
  304. /// inverted transformation
  305. TMat4 getInverseTransformation() const
  306. {
  307. TMat3<T> invertedRot = getRotationPart().getTransposed();
  308. TVec3<T> invertedTsl = getTranslationPart().xyz();
  309. invertedTsl = -(invertedRot * invertedTsl);
  310. return TMat4(invertedTsl.xyz0(), invertedRot);
  311. }
  312. void setIdentity()
  313. {
  314. (*this) = getIdentity();
  315. }
  316. static const TMat4& getIdentity()
  317. {
  318. static const TMat4 ident(1.0,
  319. 0.0,
  320. 0.0,
  321. 0.0,
  322. 0.0,
  323. 1.0,
  324. 0.0,
  325. 0.0,
  326. 0.0,
  327. 0.0,
  328. 1.0,
  329. 0.0,
  330. 0.0,
  331. 0.0,
  332. 0.0,
  333. 1.0);
  334. return ident;
  335. }
  336. /// 12 muls, 27 adds. Something like m4 = m0 * m1 but without touching
  337. /// the 4rth row and allot faster
  338. static TMat4 combineTransformations(const TMat4& m0, const TMat4& m1)
  339. {
  340. // See the clean code in < r664
  341. // one of the 2 mat4 doesnt represent transformation
  342. ANKI_ASSERT(isZero<T>(m0(3, 0) + m0(3, 1) + m0(3, 2) + m0(3, 3) - 1.0)
  343. && isZero<T>(m1(3, 0) + m1(3, 1) + m1(3, 2) + m1(3, 3) - 1.0));
  344. TMat4 m4;
  345. m4(0, 0) =
  346. m0(0, 0) * m1(0, 0) + m0(0, 1) * m1(1, 0) + m0(0, 2) * m1(2, 0);
  347. m4(0, 1) =
  348. m0(0, 0) * m1(0, 1) + m0(0, 1) * m1(1, 1) + m0(0, 2) * m1(2, 1);
  349. m4(0, 2) =
  350. m0(0, 0) * m1(0, 2) + m0(0, 1) * m1(1, 2) + m0(0, 2) * m1(2, 2);
  351. m4(1, 0) =
  352. m0(1, 0) * m1(0, 0) + m0(1, 1) * m1(1, 0) + m0(1, 2) * m1(2, 0);
  353. m4(1, 1) =
  354. m0(1, 0) * m1(0, 1) + m0(1, 1) * m1(1, 1) + m0(1, 2) * m1(2, 1);
  355. m4(1, 2) =
  356. m0(1, 0) * m1(0, 2) + m0(1, 1) * m1(1, 2) + m0(1, 2) * m1(2, 2);
  357. m4(2, 0) =
  358. m0(2, 0) * m1(0, 0) + m0(2, 1) * m1(1, 0) + m0(2, 2) * m1(2, 0);
  359. m4(2, 1) =
  360. m0(2, 0) * m1(0, 1) + m0(2, 1) * m1(1, 1) + m0(2, 2) * m1(2, 1);
  361. m4(2, 2) =
  362. m0(2, 0) * m1(0, 2) + m0(2, 1) * m1(1, 2) + m0(2, 2) * m1(2, 2);
  363. m4(0, 3) = m0(0, 0) * m1(0, 3) + m0(0, 1) * m1(1, 3)
  364. + m0(0, 2) * m1(2, 3) + m0(0, 3);
  365. m4(1, 3) = m0(1, 0) * m1(0, 3) + m0(1, 1) * m1(1, 3)
  366. + m0(1, 2) * m1(2, 3) + m0(1, 3);
  367. m4(2, 3) = m0(2, 0) * m1(0, 3) + m0(2, 1) * m1(1, 3)
  368. + m0(2, 2) * m1(2, 3) + m0(2, 3);
  369. m4(3, 0) = m4(3, 1) = m4(3, 2) = 0.0;
  370. m4(3, 3) = 1.0;
  371. return m4;
  372. }
  373. /// @note 9 muls, 9 adds
  374. TVec3<T> transform(const TVec3<T>& v) const
  375. {
  376. const TMat4& m = *this;
  377. return TVec3<T>(
  378. m(0, 0) * v.x() + m(0, 1) * v.y() + m(0, 2) * v.z() + m(0, 3),
  379. m(1, 0) * v.x() + m(1, 1) * v.y() + m(1, 2) * v.z() + m(1, 3),
  380. m(2, 0) * v.x() + m(2, 1) * v.y() + m(2, 2) * v.z() + m(2, 3));
  381. }
  382. /// @}
  383. };
  384. #if ANKI_SIMD == ANKI_SIMD_SSE
  385. // Forward declare specializations
  386. template<>
  387. TMat4<F32>::Base::TMat(const TMat4<F32>::Base& b);
  388. template<>
  389. TMat4<F32>::Base::TMat(const F32 f);
  390. template<>
  391. TMat4<F32>& TMat4<F32>::Base::operator=(const TMat4<F32>& b);
  392. template<>
  393. TMat4<F32> TMat4<F32>::Base::operator+(const TMat4<F32>& b) const;
  394. template<>
  395. TMat4<F32>& TMat4<F32>::Base::operator+=(const TMat4<F32>& b);
  396. template<>
  397. TMat4<F32> TMat4<F32>::Base::operator-(const TMat4<F32>& b) const;
  398. template<>
  399. TMat4<F32>& TMat4<F32>::Base::operator-=(const TMat4<F32>& b);
  400. template<>
  401. TMat4<F32> TMat4<F32>::Base::operator*(const TMat4<F32>& b) const;
  402. template<>
  403. TVec4<F32> TMat4<F32>::Base::operator*(const TVec4<F32>& b) const;
  404. template<>
  405. void TMat4<F32>::Base::setRows(const TVec4<F32>& a,
  406. const TVec4<F32>& b,
  407. const TVec4<F32>& c,
  408. const TVec4<F32>& d);
  409. template<>
  410. void TMat4<F32>::Base::setRow(const U i, const TVec4<F32>& v);
  411. template<>
  412. void TMat4<F32>::Base::transpose();
  413. #elif ANKI_SIMD == ANKI_SIMD_NEON
  414. #error "TODO"
  415. #endif
  416. /// F32 4x4 matrix
  417. typedef TMat4<F32> Mat4;
  418. static_assert(sizeof(Mat4) == sizeof(F32) * 4 * 4, "Incorrect size");
  419. /// @}
  420. } // end namespace anki
  421. #include <anki/math/Mat4.inl.h>