Mat4.h 12 KB

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