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

869 lines
25 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. * Rotates a matrix.
  212. *
  213. * @param m Matrix to rotate.
  214. * @param angle Angle of rotation (in radians).
  215. * @param axis Axis of rotation
  216. * @return Rotated matrix.
  217. */
  218. template <class T>
  219. matrix<T, 4, 4> rotate(const matrix<T, 4, 4>& m, T angle, const vector<T, 3>& axis);
  220. /**
  221. * Scales a matrix.
  222. *
  223. * @param m Matrix to scale.
  224. * @param v Scale vector.
  225. * @return Scaled matrix.
  226. */
  227. template <class T>
  228. matrix<T, 4, 4> scale(const matrix<T, 4, 4>& m, const vector<T, 3>& v);
  229. /**
  230. * Subtracts a matrix from another matrix.
  231. *
  232. * @param x First matrix.
  233. * @param y Second matrix.
  234. * @return Difference between the two matrices.
  235. */
  236. template <class T>
  237. matrix<T, 2, 2> sub(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y);
  238. /// @copydoc sub(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&)
  239. template <class T>
  240. matrix<T, 3, 3> sub(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y);
  241. /// @copydoc sub(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&)
  242. template <class T>
  243. matrix<T, 4, 4> sub(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y);
  244. /**
  245. * Translates a matrix.
  246. *
  247. * @param m Matrix to translate.
  248. * @param v Translation vector.
  249. * @return Translated matrix.
  250. */
  251. template <class T>
  252. matrix<T, 4, 4> translate(const matrix<T, 4, 4>& m, const vector<T, 3>& v);
  253. /**
  254. * Calculates the transpose of a matrix.
  255. *
  256. * @param m Matrix of which to take the transpose.
  257. */
  258. template <class T>
  259. matrix<T, 2, 2> transpose(const matrix<T, 2, 2>& m);
  260. /// @copydoc transpose(const matrix<T, 2, 2>&)
  261. template <class T>
  262. matrix<T, 3, 3> transpose(const matrix<T, 3, 3>& m);
  263. /// @copydoc transpose(const matrix<T, 2, 2>&)
  264. template <class T>
  265. matrix<T, 4, 4> transpose(const matrix<T, 4, 4>& m);
  266. /**
  267. * Types casts each matrix element and returns a matrix of the casted type.
  268. *
  269. * @tparam T2 Target matrix element type.
  270. * @tparam T1 Source matrix element type.
  271. * @tparam N Number of columns.
  272. * @tparam M Number of rows.
  273. * @param m Matrix to type cast.
  274. * @return Type-casted matrix.
  275. */
  276. template <class T2, class T1, std::size_t N, std::size_t M>
  277. matrix<T2, N, M> type_cast(const matrix<T1, N, M>& m);
  278. template <class T>
  279. matrix<T, 2, 2> add(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y)
  280. {
  281. return
  282. {{
  283. x[0] + y[0],
  284. x[1] + y[1]
  285. }};
  286. }
  287. template <class T>
  288. matrix<T, 3, 3> add(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y)
  289. {
  290. return
  291. {{
  292. x[0] + y[0],
  293. x[1] + y[1],
  294. x[2] + y[2]
  295. }};
  296. }
  297. template <class T>
  298. matrix<T, 4, 4> add(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y)
  299. {
  300. return
  301. {{
  302. x[0] + y[0],
  303. x[1] + y[1],
  304. x[2] + y[2],
  305. x[3] + y[3]
  306. }};
  307. }
  308. template <std::size_t N, std::size_t M, typename T>
  309. inline matrix<T, N, M>& as_matrix(T& data)
  310. {
  311. static_assert(std::is_pod<matrix<T, N, M>>::value);
  312. return reinterpret_cast<matrix<T, N, M>&>(data);
  313. }
  314. template <class T>
  315. T determinant(const matrix<T, 2, 2>& m)
  316. {
  317. return m[0][0] * m[1][1] - m[0][1] * m[1][0];
  318. }
  319. template <class T>
  320. T determinant(const matrix<T, 3, 3>& m)
  321. {
  322. return m[0][0] * m [1][1] * m[2][2] +
  323. m[0][1] * m[1][2] * m[2][0] +
  324. m[0][2] * m[1][0] * m[2][1] -
  325. m[0][0] * m[1][2] * m[2][1] -
  326. m[0][1] * m[1][0] * m[2][2] -
  327. m[0][2] * m[1][1] * m[2][0];
  328. }
  329. template <class T>
  330. T determinant(const matrix<T, 4, 4>& m)
  331. {
  332. 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] -
  333. m[0][3] * m[1][1] * m[2][2] * m[3][0] + m[0][1] * m[1][3] * m[2][2] * m[3][0] +
  334. m[0][2] * m[1][1] * m[2][3] * m[3][0] - m[0][1] * m[1][2] * m[2][3] * m[3][0] -
  335. m[0][3] * m[1][2] * m[2][0] * m[3][1] + m[0][2] * m[1][3] * m[2][0] * m[3][1] +
  336. m[0][3] * m[1][0] * m[2][2] * m[3][1] - m[0][0] * m[1][3] * m[2][2] * m[3][1] -
  337. m[0][2] * m[1][0] * m[2][3] * m[3][1] + m[0][0] * m[1][2] * m[2][3] * m[3][1] +
  338. m[0][3] * m[1][1] * m[2][0] * m[3][2] - m[0][1] * m[1][3] * m[2][0] * m[3][2] -
  339. m[0][3] * m[1][0] * m[2][1] * m[3][2] + m[0][0] * m[1][3] * m[2][1] * m[3][2] +
  340. m[0][1] * m[1][0] * m[2][3] * m[3][2] - m[0][0] * m[1][1] * m[2][3] * m[3][2] -
  341. m[0][2] * m[1][1] * m[2][0] * m[3][3] + m[0][1] * m[1][2] * m[2][0] * m[3][3] +
  342. m[0][2] * m[1][0] * m[2][1] * m[3][3] - m[0][0] * m[1][2] * m[2][1] * m[3][3] -
  343. m[0][1] * m[1][0] * m[2][2] * m[3][3] + m[0][0] * m[1][1] * m[2][2] * m[3][3];
  344. }
  345. template <class T>
  346. matrix<T, 2, 2> inverse(const matrix<T, 2, 2>& m)
  347. {
  348. static_assert(std::is_floating_point<T>::value);
  349. const T rd(T(1) / determinant(m));
  350. return
  351. {{
  352. { m[1][1] * rd, -m[0][1] * rd},
  353. {-m[1][0] * rd, m[0][0] * rd}
  354. }};
  355. }
  356. template <class T>
  357. matrix<T, 3, 3> inverse(const matrix<T, 3, 3>& m)
  358. {
  359. static_assert(std::is_floating_point<T>::value);
  360. const T rd(T(1) / determinant(m));
  361. return
  362. {{
  363. {
  364. (m[1][1] * m[2][2] - m[1][2] * m[2][1]) * rd,
  365. (m[0][2] * m[2][1] - m[0][1] * m[2][2]) * rd,
  366. (m[0][1] * m[1][2] - m[0][2] * m[1][1]) * rd
  367. },
  368. {
  369. (m[1][2] * m[2][0] - m[1][0] * m[2][2]) * rd,
  370. (m[0][0] * m[2][2] - m[0][2] * m[2][0]) * rd,
  371. (m[0][2] * m[1][0] - m[0][0] * m[1][2]) * rd
  372. },
  373. {
  374. (m[1][0] * m[2][1] - m[1][1] * m[2][0]) * rd,
  375. (m[0][1] * m[2][0] - m[0][0] * m[2][1]) * rd,
  376. (m[0][0] * m[1][1] - m[0][1] * m[1][0]) * rd
  377. }
  378. }};
  379. }
  380. template <class T>
  381. matrix<T, 4, 4> inverse(const matrix<T, 4, 4>& m)
  382. {
  383. static_assert(std::is_floating_point<T>::value);
  384. const T rd(T(1) / determinant(m));
  385. return
  386. {{
  387. {
  388. (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,
  389. (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,
  390. (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,
  391. (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
  392. },
  393. {
  394. (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,
  395. (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,
  396. (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,
  397. (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
  398. },
  399. {
  400. (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,
  401. (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,
  402. (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,
  403. (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
  404. },
  405. {
  406. (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,
  407. (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,
  408. (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,
  409. (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
  410. }
  411. }};
  412. }
  413. template <class T>
  414. matrix<T, 2, 2> componentwise_mul(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y)
  415. {
  416. return
  417. {{
  418. {x[0][0] * y[0][0], x[0][1] * y[0][1]},
  419. {x[1][0] * y[1][0], x[1][1] * y[1][1]}
  420. }};
  421. }
  422. template <class T>
  423. matrix<T, 3, 3> componentwise_mul(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y)
  424. {
  425. return
  426. {{
  427. {x[0][0] * y[0][0], x[0][1] * y[0][1], x[0][2] * y[0][2]},
  428. {x[1][0] * y[1][0], x[1][1] * y[1][1], x[1][2] * y[1][2]},
  429. {x[2][0] * y[2][0], x[2][1] * y[2][1], x[2][2] * y[2][2]}
  430. }};
  431. }
  432. template <class T>
  433. matrix<T, 4, 4> componentwise_mul(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y)
  434. {
  435. return
  436. {{
  437. {x[0][0] * y[0][0], x[0][1] * y[0][1], x[0][2] * y[0][2], x[0][3] * y[0][3]},
  438. {x[1][0] * y[1][0], x[1][1] * y[1][1], x[1][2] * y[1][2], x[1][3] * y[1][3]},
  439. {x[2][0] * y[2][0], x[2][1] * y[2][1], x[2][2] * y[2][2], x[2][3] * y[2][3]},
  440. {x[3][0] * y[3][0], x[3][1] * y[3][1], x[3][2] * y[3][2], x[3][3] * y[3][3]}
  441. }};
  442. }
  443. template <class T>
  444. matrix<T, 4, 4> look_at(const vector<T, 3>& position, const vector<T, 3>& target, vector<T, 3> up)
  445. {
  446. vector<T, 3> forward = normalize(sub(target, position));
  447. vector<T, 3> right = normalize(cross(forward, up));
  448. up = cross(right, forward);
  449. matrix<T, 4, 4> m =
  450. {{
  451. {right[0], up[0], -forward[0], T(0)},
  452. {right[1], up[1], -forward[1], T(0)},
  453. {right[2], up[2], -forward[2], T(0)},
  454. {T(0), T(0), T(0), T(1)}
  455. }};
  456. return translate(m, negate(position));
  457. }
  458. template <class T>
  459. matrix<T, 2, 2> mul(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y)
  460. {
  461. return
  462. {{
  463. x[0] * y[0][0] + x[1] * y[0][1],
  464. x[0] * y[1][0] + x[1] * y[1][1]
  465. }};
  466. }
  467. template <class T>
  468. matrix<T, 3, 3> mul(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y)
  469. {
  470. return
  471. {{
  472. x[0] * y[0][0] + x[1] * y[0][1] + x[2] * y[0][2],
  473. x[0] * y[1][0] + x[1] * y[1][1] + x[2] * y[1][2],
  474. x[0] * y[2][0] + x[1] * y[2][1] + x[2] * y[2][2]
  475. }};
  476. }
  477. template <class T>
  478. matrix<T, 4, 4> mul(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y)
  479. {
  480. return
  481. {{
  482. x[0] * y[0][0] + x[1] * y[0][1] + x[2] * y[0][2] + x[3] * y[0][3],
  483. x[0] * y[1][0] + x[1] * y[1][1] + x[2] * y[1][2] + x[3] * y[1][3],
  484. x[0] * y[2][0] + x[1] * y[2][1] + x[2] * y[2][2] + x[3] * y[2][3],
  485. x[0] * y[3][0] + x[1] * y[3][1] + x[2] * y[3][2] + x[3] * y[3][3]
  486. }};
  487. }
  488. /// @private
  489. template <class T, std::size_t N, std::size_t M, std::size_t... I>
  490. inline matrix<T, N, M> mul(const matrix<T, N, M>& m, T s, std::index_sequence<I...>)
  491. {
  492. return {{(m[I] * s)...}};
  493. }
  494. template <class T, std::size_t N, std::size_t M>
  495. inline matrix<T, N, M> mul(const matrix<T, N, M>& m, T s)
  496. {
  497. return mul(m, s, std::make_index_sequence<N>{});
  498. }
  499. template <class T>
  500. vector<T, 2> mul(const matrix<T, 2, 2>& m, const vector<T, 2>& v)
  501. {
  502. return
  503. {
  504. m[0][0] * v[0] + m[1][0] * v[1],
  505. m[0][1] * v[0] + m[1][1] * v[1]
  506. };
  507. }
  508. template <class T>
  509. vector<T, 3> mul(const matrix<T, 3, 3>& m, const vector<T, 3>& v)
  510. {
  511. return
  512. {
  513. m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2],
  514. m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2],
  515. m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2]
  516. };
  517. }
  518. template <class T>
  519. vector<T, 4> mul(const matrix<T, 4, 4>& m, const vector<T, 4>& v)
  520. {
  521. return
  522. {
  523. m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2] + m[3][0] * v[3],
  524. m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2] + m[3][1] * v[3],
  525. m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2] * v[3],
  526. m[0][3] * v[0] + m[1][3] * v[1] + m[2][3] * v[2] + m[3][3] * v[3]
  527. };
  528. }
  529. template <class T>
  530. matrix<T, 4, 4> ortho(T left, T right, T bottom, T top, T z_near, T z_far)
  531. {
  532. return
  533. {{
  534. {T(2) / (right - left), T(0), T(0), T(0)},
  535. {T(0), T(2) / (top - bottom), T(0), T(0)},
  536. {T(0), T(0), T(-2) / (z_far - z_near), T(0)},
  537. {-((right + left) / (right - left)), -((top + bottom) / (top - bottom)), -((z_far + z_near) / (z_far - z_near)), T(1)}
  538. }};
  539. }
  540. template <class T>
  541. matrix<T, 4, 4> ortho_half_z(T left, T right, T bottom, T top, T z_near, T z_far)
  542. {
  543. return
  544. {{
  545. {T(2) / (right - left), T(0), T(0), T(0)},
  546. {T(0), T(2) / (top - bottom), T(0), T(0)},
  547. {T(0), T(0), T(-1) / (z_far - z_near), T(0)},
  548. {-((right + left) / (right - left)), -((top + bottom) / (top - bottom)), -z_near / (z_far - z_near), T(1)}
  549. }};
  550. }
  551. template <class T>
  552. matrix<T, 2, 2> outer_product(const vector<T, 2>& c, const vector<T, 2>& r)
  553. {
  554. return
  555. {{
  556. {c[0] * r[0], c[1] * r[0]},
  557. {c[0] * r[1], c[1] * r[1]}
  558. }};
  559. }
  560. template <class T>
  561. matrix<T, 3, 3> outer_product(const vector<T, 3>& c, const vector<T, 3>& r)
  562. {
  563. return
  564. {{
  565. {c[0] * r[0], c[1] * r[0], c[2] * r[0]},
  566. {c[0] * r[1], c[1] * r[1], c[2] * r[1]},
  567. {c[0] * r[2], c[1] * r[2], c[2] * r[2]}
  568. }};
  569. }
  570. template <class T>
  571. matrix<T, 4, 4> outer_product(const vector<T, 4>& c, const vector<T, 4> r)
  572. {
  573. return
  574. {{
  575. {c[0] * r[0], c[1] * r[0], c[2] * r[0], c[3] * r[0]},
  576. {c[0] * r[1], c[1] * r[1], c[2] * r[1], c[3] * r[1]},
  577. {c[0] * r[2], c[1] * r[2], c[2] * r[2], c[3] * r[2]},
  578. {c[0] * r[3], c[1] * r[3], c[2] * r[3], c[3] * r[3]}
  579. }};
  580. }
  581. template <class T>
  582. matrix<T, 4, 4> perspective(T vertical_fov, T aspect_ratio, T z_near, T z_far)
  583. {
  584. T half_fov = vertical_fov * T(0.5);
  585. T f = std::cos(half_fov) / std::sin(half_fov);
  586. return
  587. {{
  588. {f / aspect_ratio, T(0), T(0), T(0)},
  589. {T(0), f, T(0), T(0)},
  590. {T(0), T(0), (z_far + z_near) / (z_near - z_far), T(-1)},
  591. {T(0), T(0), (T(2) * z_far * z_near) / (z_near - z_far), T(0)}
  592. }};
  593. }
  594. template <class T>
  595. matrix<T, 4, 4> perspective_half_z(T vertical_fov, T aspect_ratio, T z_near, T z_far)
  596. {
  597. T half_fov = vertical_fov * T(0.5);
  598. T f = std::cos(half_fov) / std::sin(half_fov);
  599. return
  600. {{
  601. {f / aspect_ratio, T(0), T(0), T(0)},
  602. {T(0), f, T(0), T(0)},
  603. {T(0), T(0), z_far / (z_near - z_far), T(-1)},
  604. {T(0), T(0), -(z_far * z_near) / (z_far - z_near), T(0)}
  605. }};
  606. }
  607. template <std::size_t N1, std::size_t M1, class T, std::size_t N0, std::size_t M0>
  608. matrix<T, N1, M1> resize(const matrix<T, N0, M0>& m)
  609. {
  610. matrix<T, N1, M1> resized;
  611. for (std::size_t i = 0; i < N1; ++i)
  612. {
  613. for (std::size_t j = 0; j < M1; ++j)
  614. {
  615. resized[i][j] = (i < N0 && j < M0) ? m[i][j] : ((i == j) ? T(1) : T(0));
  616. }
  617. }
  618. return resized;
  619. }
  620. template <class T>
  621. matrix<T, 4, 4> rotate(const matrix<T, 4, 4>& m, T angle, const vector<T, 3>& axis)
  622. {
  623. const T c = std::cos(angle);
  624. const T s = std::sin(angle);
  625. const vector<T, 3> temp = mul(axis, T(1) - c);
  626. matrix<T, 4, 4> rotation;
  627. rotation[0][0] = axis[0] * temp[0] + c
  628. rotation[0][1] = axis[1] * temp[0] + axis[2] * s;
  629. rotation[0][2] = axis[2] * temp[0] - axis[1] * s;
  630. rotation[0][3] = T(0);
  631. rotation[1][0] = axis[0] * temp[1] - axis[2] * s
  632. rotation[1][1] = axis[1] * temp[1] + c;
  633. rotation[1][2] = axis[2] * temp[1] + axis[0] * s;
  634. rotation[1][3] = T(0);
  635. rotation[2][0] = axis[0] * temp[2] + axis[1] * s;
  636. rotation[2][1] = axis[1] * temp[2] - axis[0] * s;
  637. rotation[2][2] = axis[2] * temp[2] + c
  638. rotation[2][3] = T(0);
  639. rotation[3][0] = T(0);
  640. rotation[3][1] = T(0);
  641. rotation[3][2] = T(0);
  642. rotation[3][3] = T(1);
  643. return mul(m, rotation);
  644. }
  645. template <class T>
  646. matrix<T, 4, 4> scale(const matrix<T, 4, 4>& m, const vector<T, 3>& v)
  647. {
  648. return mul(m, matrix<T, 4, 4>
  649. {{
  650. {v[0], T(0), T(0), T(0)},
  651. {T(0), v[1], T(0), T(0)},
  652. {T(0), T(0), v[2], T(0)},
  653. {T(0), T(0), T(0), T(1)}
  654. }});
  655. }
  656. template <class T>
  657. matrix<T, 2, 2> sub(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y)
  658. {
  659. return
  660. {{
  661. x[0] - y[0],
  662. x[1] - y[1]
  663. }};
  664. }
  665. template <class T>
  666. matrix<T, 3, 3> sub(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y)
  667. {
  668. return
  669. {{
  670. x[0] - y[0],
  671. x[1] - y[1],
  672. x[2] - y[2]
  673. }};
  674. }
  675. template <class T>
  676. matrix<T, 4, 4> sub(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y)
  677. {
  678. return
  679. {{
  680. x[0] - y[0],
  681. x[1] - y[1],
  682. x[2] - y[2],
  683. x[3] - y[3]
  684. }};
  685. }
  686. template <class T>
  687. matrix<T, 4, 4> translate(const matrix<T, 4, 4>& m, const vector<T, 3>& v)
  688. {
  689. return mul(m, matrix<T, 4, 4>
  690. {{
  691. {T(1), T(0), T(0), T(0)},
  692. {T(0), T(1), T(0), T(0)},
  693. {T(0), T(0), T(1), T(0)},
  694. {v[0], v[1], v[2], T(1)}
  695. }});
  696. }
  697. template <class T>
  698. matrix<T, 2, 2> transpose(const matrix<T, 2, 2>& m)
  699. {
  700. return
  701. {{
  702. {
  703. m[0][0], m[1][0]
  704. },
  705. {
  706. m[0][1], m[1][1]
  707. }
  708. }};
  709. }
  710. template <class T>
  711. matrix<T, 3, 3> transpose(const matrix<T, 3, 3>& m)
  712. {
  713. return
  714. {{
  715. {
  716. m[0][0], m[1][0], m[2][0]
  717. },
  718. {
  719. m[0][1], m[1][1], m[2][1]
  720. },
  721. {
  722. m[0][2], m[1][2], m[2][2]
  723. }
  724. }};
  725. }
  726. template <class T>
  727. matrix<T, 4, 4> transpose(const matrix<T, 4, 4>& m)
  728. {
  729. return
  730. {{
  731. {
  732. m[0][0], m[1][0], m[2][0], m[3][0]
  733. },
  734. {
  735. m[0][1], m[1][1], m[2][1], m[3][1]
  736. },
  737. {
  738. m[0][2], m[1][2], m[2][2], m[3][2]
  739. },
  740. {
  741. m[0][3], m[1][3], m[2][3], m[3][3]
  742. }
  743. }};
  744. }
  745. /// @private
  746. template <class T2, class T1, std::size_t N, std::size_t M, std::size_t... I>
  747. inline matrix<T2, N, M> type_cast(const matrix<T1, N, M>& m, std::index_sequence<I...>)
  748. {
  749. return {type_cast<T2>(m[I])...};
  750. }
  751. template <class T2, class T1, std::size_t N, std::size_t M>
  752. matrix<T2, N, M> type_cast(const matrix<T1, N, M>& m)
  753. {
  754. return type_cast<T2>(m, std::make_index_sequence<N>{});
  755. }
  756. } // namespace math
  757. #endif // ANTKEEPER_MATH_MATRIX_FUNCTIONS_HPP