💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

930 lines
26 KiB

  1. /*
  2. * Copyright (C) 2021 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #ifndef ANTKEEPER_MATH_MATRIX_FUNCTIONS_HPP
  20. #define ANTKEEPER_MATH_MATRIX_FUNCTIONS_HPP
  21. #include "math/matrix-type.hpp"
  22. #include "math/vector-type.hpp"
  23. #include "math/vector-functions.hpp"
  24. #include <type_traits>
  25. namespace math {
  26. /**
  27. * Adds two matrices.
  28. *
  29. * @param x First matrix.
  30. * @param y Second matrix.
  31. * @return Sum of the two matrices.
  32. */
  33. template <class T>
  34. matrix<T, 2, 2> add(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y);
  35. /// @copydoc add(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&)
  36. template <class T>
  37. matrix<T, 3, 3> add(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y);
  38. /// @copydoc add(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&)
  39. template <class T>
  40. matrix<T, 4, 4> add(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y);
  41. /**
  42. * Reinterprets data as an `NxM` matrix of type `T`.
  43. *
  44. * @tparam N Number of columns.
  45. * @tparam M Number of rows.
  46. * @tparam T Element type.
  47. * @param data Data to reinterpret.
  48. */
  49. template <std::size_t N, std::size_t M, typename T>
  50. matrix<T, N, M>& as_matrix(T& data);
  51. /**
  52. * Calculates the determinant of a matrix.
  53. *
  54. * @param m Matrix of which to take the determinant.
  55. */
  56. template <class T>
  57. T determinant(const matrix<T, 2, 2>& m);
  58. /// @copydoc determinant(const matrix<T, 2, 2>&)
  59. template <class T>
  60. T determinant(const matrix<T, 3, 3>& m);
  61. /// @copydoc determinant(const matrix<T, 2, 2>&)
  62. template <class T>
  63. T determinant(const matrix<T, 4, 4>& m);
  64. /**
  65. * Calculates the inverse of a matrix.
  66. *
  67. * @param m Matrix of which to take the inverse.
  68. */
  69. template <class T>
  70. matrix<T, 2, 2> inverse(const matrix<T, 2, 2>& m);
  71. /// @copydoc inverse(const matrix<T, 2, 2>&)
  72. template <class T>
  73. matrix<T, 3, 3> inverse(const matrix<T, 3, 3>& m);
  74. /// @copydoc inverse(const matrix<T, 2, 2>&)
  75. template <class T>
  76. matrix<T, 4, 4> inverse(const matrix<T, 4, 4>& m);
  77. /**
  78. * Performs a component-wise multiplication of two matrices.
  79. *
  80. * @param x First matrix multiplicand.
  81. * @param y Second matrix multiplicand.
  82. */
  83. template <class T>
  84. matrix<T, 2, 2> componentwise_mul(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y);
  85. /// @copydoc componentwise_mul(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&)
  86. template <class T>
  87. matrix<T, 3, 3> componentwise_mul(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y);
  88. /// @copydoc componentwise_mul(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&)
  89. template <class T>
  90. matrix<T, 4, 4> componentwise_mul(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y);
  91. /**
  92. * Creates a viewing transformation matrix.
  93. *
  94. * @param position Position of the view point.
  95. * @param target Position of the target.
  96. * @param up Normalized direction of the up vector.
  97. * @return Viewing transformation matrix.
  98. */
  99. template <class T>
  100. matrix<T, 4, 4> look_at(const vector<T, 3>& position, const vector<T, 3>& target, vector<T, 3> up);
  101. /**
  102. * Multiplies two matrices.
  103. *
  104. * @param x First matrix.
  105. * @param y Second matrix.
  106. * @return Product of the two matrices.
  107. */
  108. template <class T>
  109. matrix<T, 2, 2> mul(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y);
  110. /// @copydoc mul(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&);
  111. template <class T>
  112. matrix<T, 3, 3> mul(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y);
  113. /// @copydoc mul(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&);
  114. template <class T>
  115. matrix<T, 4, 4> mul(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y);
  116. /**
  117. * Multiplies a matrix by a scalar.
  118. *
  119. * @param m Matrix.
  120. * @param s Scalar.
  121. * @return Product of the matrix and the scalar..
  122. */
  123. template <class T, std::size_t N, std::size_t M>
  124. matrix<T, N, M> mul(const matrix<T, N, M>& m, T s);
  125. /**
  126. * Transforms a vector by a matrix.
  127. *
  128. * @param m Matrix.
  129. * @param v Vector.
  130. * @return Transformed vector.
  131. */
  132. template <class T>
  133. vector<T, 2> mul(const matrix<T, 2, 2>& m, const vector<T, 2>& v);
  134. /// @copydoc mul(const matrix<T, 2, 2>&, const vector<T, 2>&)
  135. template <class T>
  136. vector<T, 3> mul(const matrix<T, 3, 3>& m, const vector<T, 3>& v);
  137. /// @copydoc mul(const matrix<T, 2, 2>&, const vector<T, 2>&)
  138. template <class T>
  139. vector<T, 4> mul(const matrix<T, 4, 4>& m, const vector<T, 4>& v);
  140. /**
  141. * Creates an orthographic projection matrix which will transform the near and far clipping planes to `[-1, 1]`, respectively.
  142. *
  143. * @param left Signed distance to the left clipping plane.
  144. * @param right Signed distance to the right clipping plane.
  145. * @param bottom Signed distance to the bottom clipping plane.
  146. * @param top Signed distance to the top clipping plane.
  147. * @param z_near Signed distance to the near clipping plane.
  148. * @param z_far Signed distance to the far clipping plane.
  149. * @return Orthographic projection matrix.
  150. */
  151. template <class T>
  152. matrix<T, 4, 4> ortho(T left, T right, T bottom, T top, T z_near, T z_far);
  153. /**
  154. * Creates an orthographic projection matrix which will transform the near and far clipping planes to `[0, 1]`, respectively.
  155. *
  156. * @param left Signed distance to the left clipping plane.
  157. * @param right Signed distance to the right clipping plane.
  158. * @param bottom Signed distance to the bottom clipping plane.
  159. * @param top Signed distance to the top clipping plane.
  160. * @param z_near Signed distance to the near clipping plane.
  161. * @param z_far Signed distance to the far clipping plane.
  162. * @return Orthographic projection matrix.
  163. */
  164. template <class T>
  165. matrix<T, 4, 4> ortho_half_z(T left, T right, T bottom, T top, T z_near, T z_far);
  166. /**
  167. * Calculates the outer product of a pair of vectors.
  168. *
  169. * @param c Parameter to be treated as a column vector.
  170. * @param r Parameter to be treated as a row vector.
  171. */
  172. template <class T>
  173. matrix<T, 2, 2> outer_product(const vector<T, 2>& c, const vector<T, 2>& r);
  174. /// @copydoc outer_product(const vector<T, 2>&, const vector<T, 2>&)
  175. template <class T>
  176. matrix<T, 3, 3> outer_product(const vector<T, 3>& c, const vector<T, 3>& r);
  177. /// @copydoc outer_product(const vector<T, 2>&, const vector<T, 2>&)
  178. template <class T>
  179. matrix<T, 4, 4> outer_product(const vector<T, 4>& c, const vector<T, 4> r);
  180. /**
  181. * Creates a perspective projection matrix which will transform the near and far clipping planes to `[-1, 1]`, respectively.
  182. *
  183. * @param vertical_fov Vertical field of view angle, in radians.
  184. * @param aspect_ratio Aspect ratio which determines the horizontal field of view.
  185. * @param z_near Distance to the near clipping plane.
  186. * @param z_far Distance to the far clipping plane.
  187. * @return Perspective projection matrix.
  188. */
  189. template <class T>
  190. matrix<T, 4, 4> perspective(T vertical_fov, T aspect_ratio, T z_near, T z_far);
  191. /**
  192. * Creates a perspective projection matrix which will transform the near and far clipping planes to `[0, 1]`, respectively.
  193. *
  194. * @param vertical_fov Vertical field of view angle, in radians.
  195. * @param aspect_ratio Aspect ratio which determines the horizontal field of view.
  196. * @param z_near Distance to the near clipping plane.
  197. * @param z_far Distance to the far clipping plane.
  198. * @return Perspective projection matrix.
  199. */
  200. template <class T>
  201. matrix<T, 4, 4> perspective_half_z(T vertical_fov, T aspect_ratio, T z_near, T z_far);
  202. /**
  203. * Resizes a matrix. Any new elements will be set to `1` if in the diagonal, and `0` otherwise.
  204. *
  205. * @param m Matrix to resize.
  206. * @return Resized matrix.
  207. */
  208. template <std::size_t N1, std::size_t M1, class T, std::size_t N0, std::size_t M0>
  209. matrix<T, N1, M1> resize(const matrix<T, N0, M0>& m);
  210. /**
  211. * Constructs a rotation matrix.
  212. *
  213. * @param angle Angle of rotation, in radians.
  214. * @param axis Axis of rotation
  215. * @return Rotation matrix.
  216. */
  217. template <class T>
  218. matrix<T, 3, 3> rotate(T angle, const vector<T, 3>& axis);
  219. /**
  220. * Produces a matrix which rotates Cartesian coordinates about the x-axis by a given angle.
  221. *
  222. * @param angle Angle of rotation, in radians.
  223. * @return Rotation matrix.
  224. */
  225. template <class T>
  226. matrix3<T> rotate_x(T angle);
  227. /**
  228. * Produces a matrix which rotates Cartesian coordinates about the y-axis by a given angle.
  229. *
  230. * @param angle Angle of rotation, in radians.
  231. * @return Rotation matrix.
  232. */
  233. template <class T>
  234. matrix3<T> rotate_y(T angle);
  235. /**
  236. * Produces a matrix which rotates Cartesian coordinates about the z-axis by a given angle.
  237. *
  238. * @param angle Angle of rotation, in radians.
  239. * @return Rotation matrix.
  240. */
  241. template <class T>
  242. matrix3<T> rotate_z(T angle);
  243. /**
  244. * Scales a matrix.
  245. *
  246. * @param m Matrix to scale.
  247. * @param v Scale vector.
  248. * @return Scaled matrix.
  249. */
  250. template <class T>
  251. matrix<T, 4, 4> scale(const matrix<T, 4, 4>& m, const vector<T, 3>& v);
  252. /**
  253. * Subtracts a matrix from another matrix.
  254. *
  255. * @param x First matrix.
  256. * @param y Second matrix.
  257. * @return Difference between the two matrices.
  258. */
  259. template <class T>
  260. matrix<T, 2, 2> sub(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y);
  261. /// @copydoc sub(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&)
  262. template <class T>
  263. matrix<T, 3, 3> sub(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y);
  264. /// @copydoc sub(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&)
  265. template <class T>
  266. matrix<T, 4, 4> sub(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y);
  267. /**
  268. * Translates a matrix.
  269. *
  270. * @param m Matrix to translate.
  271. * @param v Translation vector.
  272. * @return Translated matrix.
  273. */
  274. template <class T>
  275. matrix<T, 4, 4> translate(const matrix<T, 4, 4>& m, const vector<T, 3>& v);
  276. /**
  277. * Calculates the transpose of a matrix.
  278. *
  279. * @param m Matrix of which to take the transpose.
  280. */
  281. template <class T>
  282. matrix<T, 2, 2> transpose(const matrix<T, 2, 2>& m);
  283. /// @copydoc transpose(const matrix<T, 2, 2>&)
  284. template <class T>
  285. matrix<T, 3, 3> transpose(const matrix<T, 3, 3>& m);
  286. /// @copydoc transpose(const matrix<T, 2, 2>&)
  287. template <class T>
  288. matrix<T, 4, 4> transpose(const matrix<T, 4, 4>& m);
  289. /**
  290. * Types casts each matrix element and returns a matrix of the casted type.
  291. *
  292. * @tparam T2 Target matrix element type.
  293. * @tparam T1 Source matrix element type.
  294. * @tparam N Number of columns.
  295. * @tparam M Number of rows.
  296. * @param m Matrix to type cast.
  297. * @return Type-casted matrix.
  298. */
  299. template <class T2, class T1, std::size_t N, std::size_t M>
  300. matrix<T2, N, M> type_cast(const matrix<T1, N, M>& m);
  301. template <class T>
  302. matrix<T, 2, 2> add(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y)
  303. {
  304. return
  305. {{
  306. x[0] + y[0],
  307. x[1] + y[1]
  308. }};
  309. }
  310. template <class T>
  311. matrix<T, 3, 3> add(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y)
  312. {
  313. return
  314. {{
  315. x[0] + y[0],
  316. x[1] + y[1],
  317. x[2] + y[2]
  318. }};
  319. }
  320. template <class T>
  321. matrix<T, 4, 4> add(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y)
  322. {
  323. return
  324. {{
  325. x[0] + y[0],
  326. x[1] + y[1],
  327. x[2] + y[2],
  328. x[3] + y[3]
  329. }};
  330. }
  331. template <std::size_t N, std::size_t M, typename T>
  332. inline matrix<T, N, M>& as_matrix(T& data)
  333. {
  334. static_assert(std::is_pod<matrix<T, N, M>>::value);
  335. return reinterpret_cast<matrix<T, N, M>&>(data);
  336. }
  337. template <class T>
  338. T determinant(const matrix<T, 2, 2>& m)
  339. {
  340. return m[0][0] * m[1][1] - m[0][1] * m[1][0];
  341. }
  342. template <class T>
  343. T determinant(const matrix<T, 3, 3>& m)
  344. {
  345. return m[0][0] * m [1][1] * m[2][2] +
  346. m[0][1] * m[1][2] * m[2][0] +
  347. m[0][2] * m[1][0] * m[2][1] -
  348. m[0][0] * m[1][2] * m[2][1] -
  349. m[0][1] * m[1][0] * m[2][2] -
  350. m[0][2] * m[1][1] * m[2][0];
  351. }
  352. template <class T>
  353. T determinant(const matrix<T, 4, 4>& m)
  354. {
  355. return m[0][3] * m[1][2] * m[2][1] * m[3][0] - m[0][2] * m[1][3] * m[2][1] * m[3][0] -
  356. m[0][3] * m[1][1] * m[2][2] * m[3][0] + m[0][1] * m[1][3] * m[2][2] * m[3][0] +
  357. m[0][2] * m[1][1] * m[2][3] * m[3][0] - m[0][1] * m[1][2] * m[2][3] * m[3][0] -
  358. m[0][3] * m[1][2] * m[2][0] * m[3][1] + m[0][2] * m[1][3] * m[2][0] * m[3][1] +
  359. m[0][3] * m[1][0] * m[2][2] * m[3][1] - m[0][0] * m[1][3] * m[2][2] * m[3][1] -
  360. m[0][2] * m[1][0] * m[2][3] * m[3][1] + m[0][0] * m[1][2] * m[2][3] * m[3][1] +
  361. m[0][3] * m[1][1] * m[2][0] * m[3][2] - m[0][1] * m[1][3] * m[2][0] * m[3][2] -
  362. m[0][3] * m[1][0] * m[2][1] * m[3][2] + m[0][0] * m[1][3] * m[2][1] * m[3][2] +
  363. m[0][1] * m[1][0] * m[2][3] * m[3][2] - m[0][0] * m[1][1] * m[2][3] * m[3][2] -
  364. m[0][2] * m[1][1] * m[2][0] * m[3][3] + m[0][1] * m[1][2] * m[2][0] * m[3][3] +
  365. m[0][2] * m[1][0] * m[2][1] * m[3][3] - m[0][0] * m[1][2] * m[2][1] * m[3][3] -
  366. m[0][1] * m[1][0] * m[2][2] * m[3][3] + m[0][0] * m[1][1] * m[2][2] * m[3][3];
  367. }
  368. template <class T>
  369. matrix<T, 2, 2> inverse(const matrix<T, 2, 2>& m)
  370. {
  371. static_assert(std::is_floating_point<T>::value);
  372. const T rd(T(1) / determinant(m));
  373. return
  374. {{
  375. { m[1][1] * rd, -m[0][1] * rd},
  376. {-m[1][0] * rd, m[0][0] * rd}
  377. }};
  378. }
  379. template <class T>
  380. matrix<T, 3, 3> inverse(const matrix<T, 3, 3>& m)
  381. {
  382. static_assert(std::is_floating_point<T>::value);
  383. const T rd(T(1) / determinant(m));
  384. return
  385. {{
  386. {
  387. (m[1][1] * m[2][2] - m[1][2] * m[2][1]) * rd,
  388. (m[0][2] * m[2][1] - m[0][1] * m[2][2]) * rd,
  389. (m[0][1] * m[1][2] - m[0][2] * m[1][1]) * rd
  390. },
  391. {
  392. (m[1][2] * m[2][0] - m[1][0] * m[2][2]) * rd,
  393. (m[0][0] * m[2][2] - m[0][2] * m[2][0]) * rd,
  394. (m[0][2] * m[1][0] - m[0][0] * m[1][2]) * rd
  395. },
  396. {
  397. (m[1][0] * m[2][1] - m[1][1] * m[2][0]) * rd,
  398. (m[0][1] * m[2][0] - m[0][0] * m[2][1]) * rd,
  399. (m[0][0] * m[1][1] - m[0][1] * m[1][0]) * rd
  400. }
  401. }};
  402. }
  403. template <class T>
  404. matrix<T, 4, 4> inverse(const matrix<T, 4, 4>& m)
  405. {
  406. static_assert(std::is_floating_point<T>::value);
  407. const T rd(T(1) / determinant(m));
  408. return
  409. {{
  410. {
  411. (m[1][2] * m[2][3] * m[3][1] - m[1][3] * m[2][2] * m[3][1] + m[1][3] * m[2][1] * m[3][2] - m[1][1] * m[2][3] * m[3][2] - m[1][2] * m[2][1] * m[3][3] + m[1][1] * m[2][2] * m[3][3]) * rd,
  412. (m[0][3] * m[2][2] * m[3][1] - m[0][2] * m[2][3] * m[3][1] - m[0][3] * m[2][1] * m[3][2] + m[0][1] * m[2][3] * m[3][2] + m[0][2] * m[2][1] * m[3][3] - m[0][1] * m[2][2] * m[3][3]) * rd,
  413. (m[0][2] * m[1][3] * m[3][1] - m[0][3] * m[1][2] * m[3][1] + m[0][3] * m[1][1] * m[3][2] - m[0][1] * m[1][3] * m[3][2] - m[0][2] * m[1][1] * m[3][3] + m[0][1] * m[1][2] * m[3][3]) * rd,
  414. (m[0][3] * m[1][2] * m[2][1] - m[0][2] * m[1][3] * m[2][1] - m[0][3] * m[1][1] * m[2][2] + m[0][1] * m[1][3] * m[2][2] + m[0][2] * m[1][1] * m[2][3] - m[0][1] * m[1][2] * m[2][3]) * rd
  415. },
  416. {
  417. (m[1][3] * m[2][2] * m[3][0] - m[1][2] * m[2][3] * m[3][0] - m[1][3] * m[2][0] * m[3][2] + m[1][0] * m[2][3] * m[3][2] + m[1][2] * m[2][0] * m[3][3] - m[1][0] * m[2][2] * m[3][3]) * rd,
  418. (m[0][2] * m[2][3] * m[3][0] - m[0][3] * m[2][2] * m[3][0] + m[0][3] * m[2][0] * m[3][2] - m[0][0] * m[2][3] * m[3][2] - m[0][2] * m[2][0] * m[3][3] + m[0][0] * m[2][2] * m[3][3]) * rd,
  419. (m[0][3] * m[1][2] * m[3][0] - m[0][2] * m[1][3] * m[3][0] - m[0][3] * m[1][0] * m[3][2] + m[0][0] * m[1][3] * m[3][2] + m[0][2] * m[1][0] * m[3][3] - m[0][0] * m[1][2] * m[3][3]) * rd,
  420. (m[0][2] * m[1][3] * m[2][0] - m[0][3] * m[1][2] * m[2][0] + m[0][3] * m[1][0] * m[2][2] - m[0][0] * m[1][3] * m[2][2] - m[0][2] * m[1][0] * m[2][3] + m[0][0] * m[1][2] * m[2][3]) * rd
  421. },
  422. {
  423. (m[1][1] * m[2][3] * m[3][0] - m[1][3] * m[2][1] * m[3][0] + m[1][3] * m[2][0] * m[3][1] - m[1][0] * m[2][3] * m[3][1] - m[1][1] * m[2][0] * m[3][3] + m[1][0] * m[2][1] * m[3][3]) * rd,
  424. (m[0][3] * m[2][1] * m[3][0] - m[0][1] * m[2][3] * m[3][0] - m[0][3] * m[2][0] * m[3][1] + m[0][0] * m[2][3] * m[3][1] + m[0][1] * m[2][0] * m[3][3] - m[0][0] * m[2][1] * m[3][3]) * rd,
  425. (m[0][1] * m[1][3] * m[3][0] - m[0][3] * m[1][1] * m[3][0] + m[0][3] * m[1][0] * m[3][1] - m[0][0] * m[1][3] * m[3][1] - m[0][1] * m[1][0] * m[3][3] + m[0][0] * m[1][1] * m[3][3]) * rd,
  426. (m[0][3] * m[1][1] * m[2][0] - m[0][1] * m[1][3] * m[2][0] - m[0][3] * m[1][0] * m[2][1] + m[0][0] * m[1][3] * m[2][1] + m[0][1] * m[1][0] * m[2][3] - m[0][0] * m[1][1] * m[2][3]) * rd
  427. },
  428. {
  429. (m[1][2] * m[2][1] * m[3][0] - m[1][1] * m[2][2] * m[3][0] - m[1][2] * m[2][0] * m[3][1] + m[1][0] * m[2][2] * m[3][1] + m[1][1] * m[2][0] * m[3][2] - m[1][0] * m[2][1] * m[3][2]) * rd,
  430. (m[0][1] * m[2][2] * m[3][0] - m[0][2] * m[2][1] * m[3][0] + m[0][2] * m[2][0] * m[3][1] - m[0][0] * m[2][2] * m[3][1] - m[0][1] * m[2][0] * m[3][2] + m[0][0] * m[2][1] * m[3][2]) * rd,
  431. (m[0][2] * m[1][1] * m[3][0] - m[0][1] * m[1][2] * m[3][0] - m[0][2] * m[1][0] * m[3][1] + m[0][0] * m[1][2] * m[3][1] + m[0][1] * m[1][0] * m[3][2] - m[0][0] * m[1][1] * m[3][2]) * rd,
  432. (m[0][1] * m[1][2] * m[2][0] - m[0][2] * m[1][1] * m[2][0] + m[0][2] * m[1][0] * m[2][1] - m[0][0] * m[1][2] * m[2][1] - m[0][1] * m[1][0] * m[2][2] + m[0][0] * m[1][1] * m[2][2]) * rd
  433. }
  434. }};
  435. }
  436. template <class T>
  437. matrix<T, 2, 2> componentwise_mul(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y)
  438. {
  439. return
  440. {{
  441. {x[0][0] * y[0][0], x[0][1] * y[0][1]},
  442. {x[1][0] * y[1][0], x[1][1] * y[1][1]}
  443. }};
  444. }
  445. template <class T>
  446. matrix<T, 3, 3> componentwise_mul(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y)
  447. {
  448. return
  449. {{
  450. {x[0][0] * y[0][0], x[0][1] * y[0][1], x[0][2] * y[0][2]},
  451. {x[1][0] * y[1][0], x[1][1] * y[1][1], x[1][2] * y[1][2]},
  452. {x[2][0] * y[2][0], x[2][1] * y[2][1], x[2][2] * y[2][2]}
  453. }};
  454. }
  455. template <class T>
  456. matrix<T, 4, 4> componentwise_mul(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y)
  457. {
  458. return
  459. {{
  460. {x[0][0] * y[0][0], x[0][1] * y[0][1], x[0][2] * y[0][2], x[0][3] * y[0][3]},
  461. {x[1][0] * y[1][0], x[1][1] * y[1][1], x[1][2] * y[1][2], x[1][3] * y[1][3]},
  462. {x[2][0] * y[2][0], x[2][1] * y[2][1], x[2][2] * y[2][2], x[2][3] * y[2][3]},
  463. {x[3][0] * y[3][0], x[3][1] * y[3][1], x[3][2] * y[3][2], x[3][3] * y[3][3]}
  464. }};
  465. }
  466. template <class T>
  467. matrix<T, 4, 4> look_at(const vector<T, 3>& position, const vector<T, 3>& target, vector<T, 3> up)
  468. {
  469. vector<T, 3> forward = normalize(sub(target, position));
  470. vector<T, 3> right = normalize(cross(forward, up));
  471. up = cross(right, forward);
  472. matrix<T, 4, 4> m =
  473. {{
  474. {right[0], up[0], -forward[0], T(0)},
  475. {right[1], up[1], -forward[1], T(0)},
  476. {right[2], up[2], -forward[2], T(0)},
  477. {T(0), T(0), T(0), T(1)}
  478. }};
  479. return translate(m, negate(position));
  480. }
  481. template <class T>
  482. matrix<T, 2, 2> mul(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y)
  483. {
  484. return
  485. {{
  486. x[0] * y[0][0] + x[1] * y[0][1],
  487. x[0] * y[1][0] + x[1] * y[1][1]
  488. }};
  489. }
  490. template <class T>
  491. matrix<T, 3, 3> mul(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y)
  492. {
  493. return
  494. {{
  495. x[0] * y[0][0] + x[1] * y[0][1] + x[2] * y[0][2],
  496. x[0] * y[1][0] + x[1] * y[1][1] + x[2] * y[1][2],
  497. x[0] * y[2][0] + x[1] * y[2][1] + x[2] * y[2][2]
  498. }};
  499. }
  500. template <class T>
  501. matrix<T, 4, 4> mul(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y)
  502. {
  503. return
  504. {{
  505. x[0] * y[0][0] + x[1] * y[0][1] + x[2] * y[0][2] + x[3] * y[0][3],
  506. x[0] * y[1][0] + x[1] * y[1][1] + x[2] * y[1][2] + x[3] * y[1][3],
  507. x[0] * y[2][0] + x[1] * y[2][1] + x[2] * y[2][2] + x[3] * y[2][3],
  508. x[0] * y[3][0] + x[1] * y[3][1] + x[2] * y[3][2] + x[3] * y[3][3]
  509. }};
  510. }
  511. /// @private
  512. template <class T, std::size_t N, std::size_t M, std::size_t... I>
  513. inline matrix<T, N, M> mul(const matrix<T, N, M>& m, T s, std::index_sequence<I...>)
  514. {
  515. return {{(m[I] * s)...}};
  516. }
  517. template <class T, std::size_t N, std::size_t M>
  518. inline matrix<T, N, M> mul(const matrix<T, N, M>& m, T s)
  519. {
  520. return mul(m, s, std::make_index_sequence<N>{});
  521. }
  522. template <class T>
  523. vector<T, 2> mul(const matrix<T, 2, 2>& m, const vector<T, 2>& v)
  524. {
  525. return
  526. {
  527. m[0][0] * v[0] + m[1][0] * v[1],
  528. m[0][1] * v[0] + m[1][1] * v[1]
  529. };
  530. }
  531. template <class T>
  532. vector<T, 3> mul(const matrix<T, 3, 3>& m, const vector<T, 3>& v)
  533. {
  534. return
  535. {
  536. m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2],
  537. m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2],
  538. m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2]
  539. };
  540. }
  541. template <class T>
  542. vector<T, 4> mul(const matrix<T, 4, 4>& m, const vector<T, 4>& v)
  543. {
  544. return
  545. {
  546. m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2] + m[3][0] * v[3],
  547. m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2] + m[3][1] * v[3],
  548. m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2] * v[3],
  549. m[0][3] * v[0] + m[1][3] * v[1] + m[2][3] * v[2] + m[3][3] * v[3]
  550. };
  551. }
  552. template <class T>
  553. matrix<T, 4, 4> ortho(T left, T right, T bottom, T top, T z_near, T z_far)
  554. {
  555. return
  556. {{
  557. {T(2) / (right - left), T(0), T(0), T(0)},
  558. {T(0), T(2) / (top - bottom), T(0), T(0)},
  559. {T(0), T(0), T(-2) / (z_far - z_near), T(0)},
  560. {-((right + left) / (right - left)), -((top + bottom) / (top - bottom)), -((z_far + z_near) / (z_far - z_near)), T(1)}
  561. }};
  562. }
  563. template <class T>
  564. matrix<T, 4, 4> ortho_half_z(T left, T right, T bottom, T top, T z_near, T z_far)
  565. {
  566. return
  567. {{
  568. {T(2) / (right - left), T(0), T(0), T(0)},
  569. {T(0), T(2) / (top - bottom), T(0), T(0)},
  570. {T(0), T(0), T(-1) / (z_far - z_near), T(0)},
  571. {-((right + left) / (right - left)), -((top + bottom) / (top - bottom)), -z_near / (z_far - z_near), T(1)}
  572. }};
  573. }
  574. template <class T>
  575. matrix<T, 2, 2> outer_product(const vector<T, 2>& c, const vector<T, 2>& r)
  576. {
  577. return
  578. {{
  579. {c[0] * r[0], c[1] * r[0]},
  580. {c[0] * r[1], c[1] * r[1]}
  581. }};
  582. }
  583. template <class T>
  584. matrix<T, 3, 3> outer_product(const vector<T, 3>& c, const vector<T, 3>& r)
  585. {
  586. return
  587. {{
  588. {c[0] * r[0], c[1] * r[0], c[2] * r[0]},
  589. {c[0] * r[1], c[1] * r[1], c[2] * r[1]},
  590. {c[0] * r[2], c[1] * r[2], c[2] * r[2]}
  591. }};
  592. }
  593. template <class T>
  594. matrix<T, 4, 4> outer_product(const vector<T, 4>& c, const vector<T, 4> r)
  595. {
  596. return
  597. {{
  598. {c[0] * r[0], c[1] * r[0], c[2] * r[0], c[3] * r[0]},
  599. {c[0] * r[1], c[1] * r[1], c[2] * r[1], c[3] * r[1]},
  600. {c[0] * r[2], c[1] * r[2], c[2] * r[2], c[3] * r[2]},
  601. {c[0] * r[3], c[1] * r[3], c[2] * r[3], c[3] * r[3]}
  602. }};
  603. }
  604. template <class T>
  605. matrix<T, 4, 4> perspective(T vertical_fov, T aspect_ratio, T z_near, T z_far)
  606. {
  607. T half_fov = vertical_fov * T(0.5);
  608. T f = std::cos(half_fov) / std::sin(half_fov);
  609. return
  610. {{
  611. {f / aspect_ratio, T(0), T(0), T(0)},
  612. {T(0), f, T(0), T(0)},
  613. {T(0), T(0), (z_far + z_near) / (z_near - z_far), T(-1)},
  614. {T(0), T(0), (T(2) * z_far * z_near) / (z_near - z_far), T(0)}
  615. }};
  616. }
  617. template <class T>
  618. matrix<T, 4, 4> perspective_half_z(T vertical_fov, T aspect_ratio, T z_near, T z_far)
  619. {
  620. T half_fov = vertical_fov * T(0.5);
  621. T f = std::cos(half_fov) / std::sin(half_fov);
  622. return
  623. {{
  624. {f / aspect_ratio, T(0), T(0), T(0)},
  625. {T(0), f, T(0), T(0)},
  626. {T(0), T(0), z_far / (z_near - z_far), T(-1)},
  627. {T(0), T(0), -(z_far * z_near) / (z_far - z_near), T(0)}
  628. }};
  629. }
  630. template <std::size_t N1, std::size_t M1, class T, std::size_t N0, std::size_t M0>
  631. matrix<T, N1, M1> resize(const matrix<T, N0, M0>& m)
  632. {
  633. matrix<T, N1, M1> resized;
  634. for (std::size_t i = 0; i < N1; ++i)
  635. {
  636. for (std::size_t j = 0; j < M1; ++j)
  637. {
  638. resized[i][j] = (i < N0 && j < M0) ? m[i][j] : ((i == j) ? T(1) : T(0));
  639. }
  640. }
  641. return resized;
  642. }
  643. template <class T>
  644. matrix<T, 3, 3> rotate(T angle, const vector<T, 3>& axis)
  645. {
  646. const T c = std::cos(angle);
  647. const T s = std::sin(angle);
  648. const vector<T, 3> temp = mul(axis, T(1) - c);
  649. matrix<T, 3, 3> rotation;
  650. rotation[0][0] = axis[0] * temp[0] + c;
  651. rotation[0][1] = axis[1] * temp[0] + axis[2] * s;
  652. rotation[0][2] = axis[2] * temp[0] - axis[1] * s;
  653. rotation[1][0] = axis[0] * temp[1] - axis[2] * s;
  654. rotation[1][1] = axis[1] * temp[1] + c;
  655. rotation[1][2] = axis[2] * temp[1] + axis[0] * s;
  656. rotation[2][0] = axis[0] * temp[2] + axis[1] * s;
  657. rotation[2][1] = axis[1] * temp[2] - axis[0] * s;
  658. rotation[2][2] = axis[2] * temp[2] + c;
  659. return rotation;
  660. }
  661. template <class T>
  662. matrix3<T> rotate_x(T angle)
  663. {
  664. const T c = std::cos(angle);
  665. const T s = std::sin(angle);
  666. return matrix3<T>
  667. {
  668. T(1), T(0), T(0),
  669. T(0), c, s,
  670. T(0), -s, c
  671. };
  672. }
  673. template <class T>
  674. matrix3<T> rotate_y(T angle)
  675. {
  676. const T c = std::cos(angle);
  677. const T s = std::sin(angle);
  678. return matrix3<T>
  679. {
  680. c, T(0), -s,
  681. T(0), T(1), T(0),
  682. s, T(0), c
  683. };
  684. }
  685. template <class T>
  686. matrix3<T> rotate_z(T angle)
  687. {
  688. const T c = std::cos(angle);
  689. const T s = std::sin(angle);
  690. return matrix3<T>
  691. {
  692. c, s, T(0),
  693. -s, c, T(0),
  694. T(0), T(0), T(1)
  695. };
  696. }
  697. template <class T>
  698. matrix<T, 4, 4> scale(const matrix<T, 4, 4>& m, const vector<T, 3>& v)
  699. {
  700. return mul(m, matrix<T, 4, 4>
  701. {{
  702. {v[0], T(0), T(0), T(0)},
  703. {T(0), v[1], T(0), T(0)},
  704. {T(0), T(0), v[2], T(0)},
  705. {T(0), T(0), T(0), T(1)}
  706. }});
  707. }
  708. template <class T>
  709. matrix<T, 2, 2> sub(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y)
  710. {
  711. return
  712. {{
  713. x[0] - y[0],
  714. x[1] - y[1]
  715. }};
  716. }
  717. template <class T>
  718. matrix<T, 3, 3> sub(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y)
  719. {
  720. return
  721. {{
  722. x[0] - y[0],
  723. x[1] - y[1],
  724. x[2] - y[2]
  725. }};
  726. }
  727. template <class T>
  728. matrix<T, 4, 4> sub(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y)
  729. {
  730. return
  731. {{
  732. x[0] - y[0],
  733. x[1] - y[1],
  734. x[2] - y[2],
  735. x[3] - y[3]
  736. }};
  737. }
  738. template <class T>
  739. matrix<T, 4, 4> translate(const matrix<T, 4, 4>& m, const vector<T, 3>& v)
  740. {
  741. return mul(m, matrix<T, 4, 4>
  742. {{
  743. {T(1), T(0), T(0), T(0)},
  744. {T(0), T(1), T(0), T(0)},
  745. {T(0), T(0), T(1), T(0)},
  746. {v[0], v[1], v[2], T(1)}
  747. }});
  748. }
  749. template <class T>
  750. matrix<T, 2, 2> transpose(const matrix<T, 2, 2>& m)
  751. {
  752. return
  753. {{
  754. {
  755. m[0][0], m[1][0]
  756. },
  757. {
  758. m[0][1], m[1][1]
  759. }
  760. }};
  761. }
  762. template <class T>
  763. matrix<T, 3, 3> transpose(const matrix<T, 3, 3>& m)
  764. {
  765. return
  766. {{
  767. {
  768. m[0][0], m[1][0], m[2][0]
  769. },
  770. {
  771. m[0][1], m[1][1], m[2][1]
  772. },
  773. {
  774. m[0][2], m[1][2], m[2][2]
  775. }
  776. }};
  777. }
  778. template <class T>
  779. matrix<T, 4, 4> transpose(const matrix<T, 4, 4>& m)
  780. {
  781. return
  782. {{
  783. {
  784. m[0][0], m[1][0], m[2][0], m[3][0]
  785. },
  786. {
  787. m[0][1], m[1][1], m[2][1], m[3][1]
  788. },
  789. {
  790. m[0][2], m[1][2], m[2][2], m[3][2]
  791. },
  792. {
  793. m[0][3], m[1][3], m[2][3], m[3][3]
  794. }
  795. }};
  796. }
  797. /// @private
  798. template <class T2, class T1, std::size_t N, std::size_t M, std::size_t... I>
  799. inline matrix<T2, N, M> type_cast(const matrix<T1, N, M>& m, std::index_sequence<I...>)
  800. {
  801. return {type_cast<T2>(m[I])...};
  802. }
  803. template <class T2, class T1, std::size_t N, std::size_t M>
  804. matrix<T2, N, M> type_cast(const matrix<T1, N, M>& m)
  805. {
  806. return type_cast<T2>(m, std::make_index_sequence<N>{});
  807. }
  808. } // namespace math
  809. #endif // ANTKEEPER_MATH_MATRIX_FUNCTIONS_HPP