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

874 lines
25 KiB

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