💿🐜 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.

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