Mat4.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. #pragma once
  2. #include <iostream>
  3. #include "Logging.h"
  4. #include "Mat3.h"
  5. #include "Vec3.h"
  6. #include "Vec4.h"
  7. namespace Framework
  8. {
  9. template<typename T>
  10. //! A 4x4 Matrix
  11. class Mat4
  12. {
  13. public:
  14. union
  15. {
  16. T elements[4][4]; //! The elements of the matrix
  17. T allElements[16]; //! The elements of the matrix as a single array
  18. };
  19. //! Copies all values from another matrix
  20. //! \param r The other matrix
  21. Mat4& operator=(const Mat4& r)
  22. {
  23. memcpy(allElements, r.allElements, sizeof(allElements));
  24. return *this;
  25. }
  26. //! Scales the matrix
  27. //! \param r The factor
  28. Mat4& operator*=(const T r)
  29. {
  30. for (T& e : allElements)
  31. e *= r;
  32. return *this;
  33. }
  34. //! Multiplies the matrix with another
  35. //! \param r The other matrix
  36. Mat4& operator*=(const Mat4& r)
  37. {
  38. return *this = *this * r;
  39. }
  40. //! Scales the matrix without modifying it
  41. //! \param r The factor
  42. Mat4 operator*(const T r) const
  43. {
  44. Mat4 result = *this;
  45. return result *= r;
  46. }
  47. //! Multiplies two matrices
  48. //! \param r The other matrix
  49. Mat4 operator*(const Mat4& r) const
  50. {
  51. Mat4 result;
  52. for (int j = 0; j < 4; j++)
  53. {
  54. for (int k = 0; k < 4; k++)
  55. {
  56. T sum = 0;
  57. for (int i = 0; i < 4; i++)
  58. sum += elements[j][i] * r.elements[i][k];
  59. result.elements[j][k] = sum;
  60. }
  61. }
  62. return result;
  63. }
  64. //! Multiplies the matrix with a vector
  65. //! \param r The vector
  66. Vec4<T> operator*(const Vec4<T>& r) const
  67. {
  68. Vec4<T> result;
  69. result.x = elements[0][0] * r.x + elements[0][1] * r.y
  70. + elements[0][2] * r.z + elements[0][3] * r.w;
  71. result.y = elements[1][0] * r.x + elements[1][1] * r.y
  72. + elements[1][2] * r.z + elements[1][3] * r.w;
  73. result.z = elements[2][0] * r.x + elements[2][1] * r.y
  74. + elements[2][2] * r.z + elements[2][3] * r.w;
  75. result.w = elements[3][0] * r.x + elements[3][1] * r.y
  76. + elements[3][2] * r.z + elements[3][3] * r.w;
  77. return result;
  78. }
  79. //! Multiplies the matrix with a vector
  80. //! \param r The vector
  81. Vec3<T> operator*(const Vec3<T>& r) const
  82. {
  83. Vec3<T> result;
  84. result.x = elements[0][0] * r.x + elements[0][1] * r.y
  85. + elements[0][2] * r.z + elements[0][3];
  86. result.y = elements[1][0] * r.x + elements[1][1] * r.y
  87. + elements[1][2] * r.z + elements[1][3];
  88. result.z = elements[2][0] * r.x + elements[2][1] * r.y
  89. + elements[2][2] * r.z + elements[2][3];
  90. return result;
  91. }
  92. Vec3<T> mult0(const Vec3<T>& r) const
  93. {
  94. Vec3<T> result;
  95. result.x = elements[0][0] * r.x + elements[0][1] * r.y
  96. + elements[0][2] * r.z;
  97. result.y = elements[1][0] * r.x + elements[1][1] * r.y
  98. + elements[1][2] * r.z;
  99. result.z = elements[2][0] * r.x + elements[2][1] * r.y
  100. + elements[2][2] * r.z;
  101. return result;
  102. }
  103. //! Calculates the inverse matrix
  104. Mat4 getInverse() const
  105. {
  106. Mat4 ret;
  107. ret.elements[0][0]
  108. = elements[1][1] * elements[2][2] * elements[3][3]
  109. - elements[1][1] * elements[2][3] * elements[3][2]
  110. - elements[2][1] * elements[1][2] * elements[3][3]
  111. + elements[2][1] * elements[1][3] * elements[3][2]
  112. + elements[3][1] * elements[1][2] * elements[2][3]
  113. - elements[3][1] * elements[1][3] * elements[2][2];
  114. ret.elements[1][0]
  115. = -elements[1][0] * elements[2][2] * elements[3][3]
  116. + elements[1][0] * elements[2][3] * elements[3][2]
  117. + elements[2][0] * elements[1][2] * elements[3][3]
  118. - elements[2][0] * elements[1][3] * elements[3][2]
  119. - elements[3][0] * elements[1][2] * elements[2][3]
  120. + elements[3][0] * elements[1][3] * elements[2][2];
  121. ret.elements[2][0]
  122. = elements[1][0] * elements[2][1] * elements[3][3]
  123. - elements[1][0] * elements[2][3] * elements[3][1]
  124. - elements[2][0] * elements[1][1] * elements[3][3]
  125. + elements[2][0] * elements[1][3] * elements[3][1]
  126. + elements[3][0] * elements[1][1] * elements[2][3]
  127. - elements[3][0] * elements[1][3] * elements[2][1];
  128. ret.elements[3][0]
  129. = -elements[1][0] * elements[2][1] * elements[3][2]
  130. + elements[1][0] * elements[2][2] * elements[3][1]
  131. + elements[2][0] * elements[1][1] * elements[3][2]
  132. - elements[2][0] * elements[1][2] * elements[3][1]
  133. - elements[3][0] * elements[1][1] * elements[2][2]
  134. + elements[3][0] * elements[1][2] * elements[2][1];
  135. ret.elements[0][1]
  136. = -elements[0][1] * elements[2][2] * elements[3][3]
  137. + elements[0][1] * elements[2][3] * elements[3][2]
  138. + elements[2][1] * elements[0][2] * elements[3][3]
  139. - elements[2][1] * elements[0][3] * elements[3][2]
  140. - elements[3][1] * elements[0][2] * elements[2][3]
  141. + elements[3][1] * elements[0][3] * elements[2][2];
  142. ret.elements[1][1]
  143. = elements[0][0] * elements[2][2] * elements[3][3]
  144. - elements[0][0] * elements[2][3] * elements[3][2]
  145. - elements[2][0] * elements[0][2] * elements[3][3]
  146. + elements[2][0] * elements[0][3] * elements[3][2]
  147. + elements[3][0] * elements[0][2] * elements[2][3]
  148. - elements[3][0] * elements[0][3] * elements[2][2];
  149. ret.elements[2][1]
  150. = -elements[0][0] * elements[2][1] * elements[3][3]
  151. + elements[0][0] * elements[2][3] * elements[3][1]
  152. + elements[2][0] * elements[0][1] * elements[3][3]
  153. - elements[2][0] * elements[0][3] * elements[3][1]
  154. - elements[3][0] * elements[0][1] * elements[2][3]
  155. + elements[3][0] * elements[0][3] * elements[2][1];
  156. ret.elements[3][1]
  157. = elements[0][0] * elements[2][1] * elements[3][2]
  158. - elements[0][0] * elements[2][2] * elements[3][1]
  159. - elements[2][0] * elements[0][1] * elements[3][2]
  160. + elements[2][0] * elements[0][2] * elements[3][1]
  161. + elements[3][0] * elements[0][1] * elements[2][2]
  162. - elements[3][0] * elements[0][2] * elements[2][1];
  163. ret.elements[0][2]
  164. = elements[0][1] * elements[1][2] * elements[3][3]
  165. - elements[0][1] * elements[1][3] * elements[3][2]
  166. - elements[1][1] * elements[0][2] * elements[3][3]
  167. + elements[1][1] * elements[0][3] * elements[3][2]
  168. + elements[3][1] * elements[0][2] * elements[1][3]
  169. - elements[3][1] * elements[0][3] * elements[1][2];
  170. ret.elements[1][2]
  171. = -elements[0][0] * elements[1][2] * elements[3][3]
  172. + elements[0][0] * elements[1][3] * elements[3][2]
  173. + elements[1][0] * elements[0][2] * elements[3][3]
  174. - elements[1][0] * elements[0][3] * elements[3][2]
  175. - elements[3][0] * elements[0][2] * elements[1][3]
  176. + elements[3][0] * elements[0][3] * elements[1][2];
  177. ret.elements[2][2]
  178. = elements[0][0] * elements[1][1] * elements[3][3]
  179. - elements[0][0] * elements[1][3] * elements[3][1]
  180. - elements[1][0] * elements[0][1] * elements[3][3]
  181. + elements[1][0] * elements[0][3] * elements[3][1]
  182. + elements[3][0] * elements[0][1] * elements[1][3]
  183. - elements[3][0] * elements[0][3] * elements[1][1];
  184. ret.elements[3][2]
  185. = -elements[0][0] * elements[1][1] * elements[3][2]
  186. + elements[0][0] * elements[1][2] * elements[3][1]
  187. + elements[1][0] * elements[0][1] * elements[3][2]
  188. - elements[1][0] * elements[0][2] * elements[3][1]
  189. - elements[3][0] * elements[0][1] * elements[1][2]
  190. + elements[3][0] * elements[0][2] * elements[1][1];
  191. ret.elements[0][3]
  192. = -elements[0][1] * elements[1][2] * elements[2][3]
  193. + elements[0][1] * elements[1][3] * elements[2][2]
  194. + elements[1][1] * elements[0][2] * elements[2][3]
  195. - elements[1][1] * elements[0][3] * elements[2][2]
  196. - elements[2][1] * elements[0][2] * elements[1][3]
  197. + elements[2][1] * elements[0][3] * elements[1][2];
  198. ret.elements[1][3]
  199. = elements[0][0] * elements[1][2] * elements[2][3]
  200. - elements[0][0] * elements[1][3] * elements[2][2]
  201. - elements[1][0] * elements[0][2] * elements[2][3]
  202. + elements[1][0] * elements[0][3] * elements[2][2]
  203. + elements[2][0] * elements[0][2] * elements[1][3]
  204. - elements[2][0] * elements[0][3] * elements[1][2];
  205. ret.elements[2][3]
  206. = -elements[0][0] * elements[1][1] * elements[2][3]
  207. + elements[0][0] * elements[1][3] * elements[2][1]
  208. + elements[1][0] * elements[0][1] * elements[2][3]
  209. - elements[1][0] * elements[0][3] * elements[2][1]
  210. - elements[2][0] * elements[0][1] * elements[1][3]
  211. + elements[2][0] * elements[0][3] * elements[1][1];
  212. ret.elements[3][3]
  213. = elements[0][0] * elements[1][1] * elements[2][2]
  214. - elements[0][0] * elements[1][2] * elements[2][1]
  215. - elements[1][0] * elements[0][1] * elements[2][2]
  216. + elements[1][0] * elements[0][2] * elements[2][1]
  217. + elements[2][0] * elements[0][1] * elements[1][2]
  218. - elements[2][0] * elements[0][2] * elements[1][1];
  219. T det = elements[0][0] * ret.elements[0][0]
  220. + elements[0][1] * ret.elements[1][0]
  221. + elements[0][2] * ret.elements[2][0]
  222. + elements[0][3] * ret.elements[3][0];
  223. if (det == 0)
  224. {
  225. Logging::error() << "Error creating the inverse matrix";
  226. return ret;
  227. }
  228. det = 1.0f / det;
  229. for (int i = 0; i < 16; i++)
  230. ret.elements[i / 4][i % 4] = ret.elements[i / 4][i % 4] * det;
  231. return ret;
  232. }
  233. //! Creates a matrix that rotates a vector around the Z axis when
  234. //! multiplied with it \param radian The angle in radians
  235. static Mat4 rotationZ(T radian)
  236. {
  237. const T cosTheta = (T)lowPrecisionCos(radian);
  238. const T sinTheta = (T)lowPrecisionSin(radian);
  239. Mat4 r = {cosTheta,
  240. -sinTheta,
  241. 0,
  242. 0,
  243. sinTheta,
  244. cosTheta,
  245. 0,
  246. 0,
  247. 0,
  248. 0,
  249. 1,
  250. 0,
  251. 0,
  252. 0,
  253. 0,
  254. 1};
  255. return r;
  256. }
  257. //! Creates a matrix that rotates a vector around the X axis when
  258. //! multiplied with it \param radian The angle in radians
  259. static Mat4 rotationX(T radian)
  260. {
  261. const T cosTheta = (T)lowPrecisionCos(radian);
  262. const T sinTheta = (T)lowPrecisionSin(radian);
  263. Mat4 r = {1,
  264. 0,
  265. 0,
  266. 0,
  267. 0,
  268. cosTheta,
  269. -sinTheta,
  270. 0,
  271. 0,
  272. sinTheta,
  273. cosTheta,
  274. 0,
  275. 0,
  276. 0,
  277. 0,
  278. 1};
  279. return r;
  280. }
  281. //! Creates a matrix that rotates a vector around the Y axis when
  282. //! multiplied with it \param radian The angle in radians
  283. static Mat4 rotationY(T radian)
  284. {
  285. const T cosTheta = (T)lowPrecisionCos(radian);
  286. const T sinTheta = (T)lowPrecisionSin(radian);
  287. Mat4 r = {cosTheta,
  288. 0,
  289. sinTheta,
  290. 0,
  291. 0,
  292. 1,
  293. 0,
  294. 0,
  295. -sinTheta,
  296. 0,
  297. cosTheta,
  298. 0,
  299. 0,
  300. 0,
  301. 0,
  302. 1};
  303. return r;
  304. }
  305. //! Creates a matrix that scales a vector when multiplied with it
  306. //! \param faktor The factor
  307. static Mat4 scaling(T faktor)
  308. {
  309. Mat4 s = {
  310. faktor, 0, 0, 0, 0, faktor, 0, 0, 0, 0, faktor, 0, 0, 0, 0, 1};
  311. return s;
  312. }
  313. //! Creates a matrix that scales a vector when multiplied with it
  314. //! \param faktorX The factor for the X component of the vector
  315. //! \param faktorY The factor for the Y component of the vector
  316. //! \param faktorZ The factor for the Z component of the vector
  317. static Mat4 scaling(T faktorX, T faktorY, T faktorZ)
  318. {
  319. Mat4 s = {faktorX,
  320. 0,
  321. 0,
  322. 0,
  323. 0,
  324. faktorY,
  325. 0,
  326. 0,
  327. 0,
  328. 0,
  329. faktorZ,
  330. 0,
  331. 0,
  332. 0,
  333. 0,
  334. 1};
  335. return s;
  336. }
  337. //! Creates a matrix that translates a vector when multiplied with it
  338. //! \param offset The coordinates by which the vector should be shifted
  339. static Mat4 translation(const Vec3<T> offset)
  340. {
  341. Mat4 t = {1,
  342. 0,
  343. 0,
  344. offset.x,
  345. 0,
  346. 1,
  347. 0,
  348. offset.y,
  349. 0,
  350. 0,
  351. 1,
  352. offset.z,
  353. 0,
  354. 0,
  355. 0,
  356. 1};
  357. return t;
  358. }
  359. //! Creates a matrix that projects a vector onto the screen
  360. //! \param openingAngle The opening angle of the camera in radians
  361. //! \param bildschirmXY The aspect ratio of the rectangle on the
  362. //! screen to draw in. (Width / Height) \param
  363. //! minz The minimum distance to the camera from which drawing begins
  364. //! \param maxZ The maximum distance to the camera beyond which drawing
  365. //! stops
  366. static Mat4 projektion(
  367. float openingAngle, float bildschirmXY, float minZ, float maxZ)
  368. {
  369. Mat4 p = {(float)(1 / tan(openingAngle / 2)) / bildschirmXY,
  370. 0,
  371. 0,
  372. 0,
  373. 0,
  374. (float)(1 / tan(openingAngle / 2)),
  375. 0,
  376. 0,
  377. 0,
  378. 0,
  379. maxZ / (maxZ - minZ),
  380. -(minZ * maxZ) / (maxZ - minZ),
  381. 0,
  382. 0,
  383. 1,
  384. 0};
  385. return p;
  386. }
  387. //! Creates an identity matrix that can be multiplied with anything
  388. //! without changing it
  389. static Mat4 identity()
  390. {
  391. Mat4 i = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
  392. return i;
  393. }
  394. //! Returns a rotation matrix such that vector a, when rotated by it,
  395. //! points in the direction of vector b \param a The vector to rotate
  396. //! \param b The vector to rotate towards
  397. static Mat4 rotationTo(Vec3<T>& a, Vec3<T>& b)
  398. {
  399. Vec3<T> aNorm = Vec3<T>(a).normalize();
  400. Vec3<T> bNorm = Vec3<T>(b).normalize();
  401. Vec3<T> v = aNorm.crossProduct(bNorm);
  402. T s = v.getLengthSq();
  403. T c = aNorm * bNorm;
  404. T m = (1 - c) / s;
  405. Mat3<T> cpm({0, -v.z, v.y, v.z, 0, -v.x, -v.y, v.x, 0});
  406. Mat3<T> cpm2 = cpm * cpm;
  407. Mat3<T> res = Mat3<T>::identity() + cpm + cpm2 * m;
  408. return Mat4({res.elements[0][0],
  409. res.elements[0][1],
  410. res.elements[0][2],
  411. 0,
  412. res.elements[1][0],
  413. res.elements[1][1],
  414. res.elements[1][2],
  415. 0,
  416. res.elements[2][0],
  417. res.elements[2][1],
  418. res.elements[2][2],
  419. 0,
  420. 0,
  421. 0,
  422. 0,
  423. 1});
  424. }
  425. };
  426. } // namespace Framework