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

795 lines
22 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.
  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. * Calculates the outer product of a pair of vectors.
  157. *
  158. * @param c Parameter to be treated as a column vector.
  159. * @param r Parameter to be treated as a row vector.
  160. */
  161. template <class T>
  162. matrix<T, 2, 2> outer_product(const vector<T, 2>& c, const vector<T, 2>& r);
  163. /// @copydoc outer_product(const vector<T, 2>&, const vector<T, 2>&)
  164. template <class T>
  165. matrix<T, 3, 3> outer_product(const vector<T, 3>& c, const vector<T, 3>& r);
  166. /// @copydoc outer_product(const vector<T, 2>&, const vector<T, 2>&)
  167. template <class T>
  168. matrix<T, 4, 4> outer_product(const vector<T, 4>& c, const vector<T, 4> r);
  169. /**
  170. * Creates a perspective projection matrix.
  171. *
  172. * @param vertical_fov Vertical field of view angle, in radians.
  173. * @param aspect_ratio Aspect ratio which determines the horizontal field of view.
  174. * @param z_near Distance to the near clipping plane.
  175. * @param z_far Distance to the far clipping plane.
  176. * @return Perspective projection matrix.
  177. */
  178. template <class T>
  179. matrix<T, 4, 4> perspective(T vertical_fov, T aspect_ratio, T z_near, T z_far);
  180. /**
  181. * Resizes a matrix. Any new elements will be set to `1` if in the diagonal, and `0` otherwise.
  182. *
  183. * @param m Matrix to resize.
  184. * @return Resized matrix.
  185. */
  186. template <std::size_t N1, std::size_t M1, class T, std::size_t N0, std::size_t M0>
  187. matrix<T, N1, M1> resize(const matrix<T, N0, M0>& m);
  188. /**
  189. * Rotates a matrix.
  190. *
  191. * @param m Matrix to rotate.
  192. * @param angle Angle of rotation (in radians).
  193. * @param axis Axis of rotation
  194. * @return Rotated matrix.
  195. */
  196. template <class T>
  197. matrix<T, 4, 4> rotate(const matrix<T, 4, 4>& m, T angle, const vector<T, 3>& axis);
  198. /**
  199. * Scales a matrix.
  200. *
  201. * @param m Matrix to scale.
  202. * @param v Scale vector.
  203. * @return Scaled matrix.
  204. */
  205. template <class T>
  206. matrix<T, 4, 4> scale(const matrix<T, 4, 4>& m, const vector<T, 3>& v);
  207. /**
  208. * Subtracts a matrix from another matrix.
  209. *
  210. * @param x First matrix.
  211. * @param y Second matrix.
  212. * @return Difference between the two matrices.
  213. */
  214. template <class T>
  215. matrix<T, 2, 2> sub(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y);
  216. /// @copydoc sub(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&)
  217. template <class T>
  218. matrix<T, 3, 3> sub(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y);
  219. /// @copydoc sub(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&)
  220. template <class T>
  221. matrix<T, 4, 4> sub(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y);
  222. /**
  223. * Translates a matrix.
  224. *
  225. * @param m Matrix to translate.
  226. * @param v Translation vector.
  227. * @return Translated matrix.
  228. */
  229. template <class T>
  230. matrix<T, 4, 4> translate(const matrix<T, 4, 4>& m, const vector<T, 3>& v);
  231. /**
  232. * Calculates the transpose of a matrix.
  233. *
  234. * @param m Matrix of which to take the transpose.
  235. */
  236. template <class T>
  237. matrix<T, 2, 2> transpose(const matrix<T, 2, 2>& m);
  238. /// @copydoc transpose(const matrix<T, 2, 2>&)
  239. template <class T>
  240. matrix<T, 3, 3> transpose(const matrix<T, 3, 3>& m);
  241. /// @copydoc transpose(const matrix<T, 2, 2>&)
  242. template <class T>
  243. matrix<T, 4, 4> transpose(const matrix<T, 4, 4>& m);
  244. template <class T>
  245. matrix<T, 2, 2> add(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y)
  246. {
  247. return
  248. {{
  249. x[0] + y[0],
  250. x[1] + y[1]
  251. }};
  252. }
  253. template <class T>
  254. matrix<T, 3, 3> add(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y)
  255. {
  256. return
  257. {{
  258. x[0] + y[0],
  259. x[1] + y[1],
  260. x[2] + y[2]
  261. }};
  262. }
  263. template <class T>
  264. matrix<T, 4, 4> add(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y)
  265. {
  266. return
  267. {{
  268. x[0] + y[0],
  269. x[1] + y[1],
  270. x[2] + y[2],
  271. x[3] + y[3]
  272. }};
  273. }
  274. template <std::size_t N, std::size_t M, typename T>
  275. inline matrix<T, N, M>& as_matrix(T& data)
  276. {
  277. static_assert(std::is_pod<matrix<T, N, M>>::value);
  278. return reinterpret_cast<matrix<T, N, M>&>(data);
  279. }
  280. template <class T>
  281. T determinant(const matrix<T, 2, 2>& m)
  282. {
  283. return m[0][0] * m[1][1] - m[0][1] * m[1][0];
  284. }
  285. template <class T>
  286. T determinant(const matrix<T, 3, 3>& m)
  287. {
  288. return m[0][0] * m [1][1] * m[2][2] +
  289. m[0][1] * m[1][2] * m[2][0] +
  290. m[0][2] * m[1][0] * m[2][1] -
  291. m[0][0] * m[1][2] * m[2][1] -
  292. m[0][1] * m[1][0] * m[2][2] -
  293. m[0][2] * m[1][1] * m[2][0];
  294. }
  295. template <class T>
  296. T determinant(const matrix<T, 4, 4>& m)
  297. {
  298. 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] -
  299. m[0][3] * m[1][1] * m[2][2] * m[3][0] + m[0][1] * m[1][3] * m[2][2] * m[3][0] +
  300. m[0][2] * m[1][1] * m[2][3] * m[3][0] - m[0][1] * m[1][2] * m[2][3] * m[3][0] -
  301. m[0][3] * m[1][2] * m[2][0] * m[3][1] + m[0][2] * m[1][3] * m[2][0] * m[3][1] +
  302. m[0][3] * m[1][0] * m[2][2] * m[3][1] - m[0][0] * m[1][3] * m[2][2] * m[3][1] -
  303. m[0][2] * m[1][0] * m[2][3] * m[3][1] + m[0][0] * m[1][2] * m[2][3] * m[3][1] +
  304. m[0][3] * m[1][1] * m[2][0] * m[3][2] - m[0][1] * m[1][3] * m[2][0] * m[3][2] -
  305. m[0][3] * m[1][0] * m[2][1] * m[3][2] + m[0][0] * m[1][3] * m[2][1] * m[3][2] +
  306. m[0][1] * m[1][0] * m[2][3] * m[3][2] - m[0][0] * m[1][1] * m[2][3] * m[3][2] -
  307. m[0][2] * m[1][1] * m[2][0] * m[3][3] + m[0][1] * m[1][2] * m[2][0] * m[3][3] +
  308. m[0][2] * m[1][0] * m[2][1] * m[3][3] - m[0][0] * m[1][2] * m[2][1] * m[3][3] -
  309. m[0][1] * m[1][0] * m[2][2] * m[3][3] + m[0][0] * m[1][1] * m[2][2] * m[3][3];
  310. }
  311. template <class T>
  312. matrix<T, 2, 2> inverse(const matrix<T, 2, 2>& m)
  313. {
  314. static_assert(std::is_floating_point<T>::value);
  315. const T rd(T(1) / determinant(m));
  316. return
  317. {{
  318. { m[1][1] * rd, -m[0][1] * rd},
  319. {-m[1][0] * rd, m[0][0] * rd}
  320. }};
  321. }
  322. template <class T>
  323. matrix<T, 3, 3> inverse(const matrix<T, 3, 3>& m)
  324. {
  325. static_assert(std::is_floating_point<T>::value);
  326. const T rd(T(1) / determinant(m));
  327. return
  328. {{
  329. {
  330. (m[1][1] * m[2][2] - m[1][2] * m[2][1]) * rd,
  331. (m[0][2] * m[2][1] - m[0][1] * m[2][2]) * rd,
  332. (m[0][1] * m[1][2] - m[0][2] * m[1][1]) * rd
  333. },
  334. {
  335. (m[1][2] * m[2][0] - m[1][0] * m[2][2]) * rd,
  336. (m[0][0] * m[2][2] - m[0][2] * m[2][0]) * rd,
  337. (m[0][2] * m[1][0] - m[0][0] * m[1][2]) * rd
  338. },
  339. {
  340. (m[1][0] * m[2][1] - m[1][1] * m[2][0]) * rd,
  341. (m[0][1] * m[2][0] - m[0][0] * m[2][1]) * rd,
  342. (m[0][0] * m[1][1] - m[0][1] * m[1][0]) * rd
  343. }
  344. }};
  345. }
  346. template <class T>
  347. matrix<T, 4, 4> inverse(const matrix<T, 4, 4>& m)
  348. {
  349. static_assert(std::is_floating_point<T>::value);
  350. const T rd(T(1) / determinant(m));
  351. return
  352. {{
  353. {
  354. (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,
  355. (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,
  356. (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,
  357. (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
  358. },
  359. {
  360. (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,
  361. (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,
  362. (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,
  363. (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
  364. },
  365. {
  366. (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,
  367. (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,
  368. (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,
  369. (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
  370. },
  371. {
  372. (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,
  373. (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,
  374. (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,
  375. (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
  376. }
  377. }};
  378. }
  379. template <class T>
  380. matrix<T, 2, 2> componentwise_mul(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y)
  381. {
  382. return
  383. {{
  384. {x[0][0] * y[0][0], x[0][1] * y[0][1]},
  385. {x[1][0] * y[1][0], x[1][1] * y[1][1]}
  386. }};
  387. }
  388. template <class T>
  389. matrix<T, 3, 3> componentwise_mul(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y)
  390. {
  391. return
  392. {{
  393. {x[0][0] * y[0][0], x[0][1] * y[0][1], x[0][2] * y[0][2]},
  394. {x[1][0] * y[1][0], x[1][1] * y[1][1], x[1][2] * y[1][2]},
  395. {x[2][0] * y[2][0], x[2][1] * y[2][1], x[2][2] * y[2][2]}
  396. }};
  397. }
  398. template <class T>
  399. matrix<T, 4, 4> componentwise_mul(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y)
  400. {
  401. return
  402. {{
  403. {x[0][0] * y[0][0], x[0][1] * y[0][1], x[0][2] * y[0][2], x[0][3] * y[0][3]},
  404. {x[1][0] * y[1][0], x[1][1] * y[1][1], x[1][2] * y[1][2], x[1][3] * y[1][3]},
  405. {x[2][0] * y[2][0], x[2][1] * y[2][1], x[2][2] * y[2][2], x[2][3] * y[2][3]},
  406. {x[3][0] * y[3][0], x[3][1] * y[3][1], x[3][2] * y[3][2], x[3][3] * y[3][3]}
  407. }};
  408. }
  409. template <class T>
  410. matrix<T, 4, 4> look_at(const vector<T, 3>& position, const vector<T, 3>& target, vector<T, 3> up)
  411. {
  412. vector<T, 3> forward = normalize(sub(target, position));
  413. vector<T, 3> right = normalize(cross(forward, up));
  414. up = cross(right, forward);
  415. matrix<T, 4, 4> m =
  416. {{
  417. {right[0], up[0], -forward[0], T(0)},
  418. {right[1], up[1], -forward[1], T(0)},
  419. {right[2], up[2], -forward[2], T(0)},
  420. {T(0), T(0), T(0), T(1)}
  421. }};
  422. return translate(m, negate(position));
  423. }
  424. template <class T>
  425. matrix<T, 2, 2> mul(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y)
  426. {
  427. return
  428. {{
  429. x[0] * y[0][0] + x[1] * y[0][1],
  430. x[0] * y[1][0] + x[1] * y[1][1]
  431. }};
  432. }
  433. template <class T>
  434. matrix<T, 3, 3> mul(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y)
  435. {
  436. return
  437. {{
  438. x[0] * y[0][0] + x[1] * y[0][1] + x[2] * y[0][2],
  439. x[0] * y[1][0] + x[1] * y[1][1] + x[2] * y[1][2],
  440. x[0] * y[2][0] + x[1] * y[2][1] + x[2] * y[2][2]
  441. }};
  442. }
  443. template <class T>
  444. matrix<T, 4, 4> mul(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y)
  445. {
  446. return
  447. {{
  448. x[0] * y[0][0] + x[1] * y[0][1] + x[2] * y[0][2] + x[3] * y[0][3],
  449. x[0] * y[1][0] + x[1] * y[1][1] + x[2] * y[1][2] + x[3] * y[1][3],
  450. x[0] * y[2][0] + x[1] * y[2][1] + x[2] * y[2][2] + x[3] * y[2][3],
  451. x[0] * y[3][0] + x[1] * y[3][1] + x[2] * y[3][2] + x[3] * y[3][3]
  452. }};
  453. }
  454. /// @private
  455. template <class T, std::size_t N, std::size_t M, std::size_t... I>
  456. inline matrix<T, N, M> mul(const matrix<T, N, M>& m, T s, std::index_sequence<I...>)
  457. {
  458. return {{(m[I] * s)...}};
  459. }
  460. template <class T, std::size_t N, std::size_t M>
  461. inline matrix<T, N, M> mul(const matrix<T, N, M>& m, T s)
  462. {
  463. return mul(m, s, std::make_index_sequence<N>{});
  464. }
  465. template <class T>
  466. vector<T, 2> mul(const matrix<T, 2, 2>& m, const vector<T, 2>& v)
  467. {
  468. return
  469. {
  470. m[0][0] * v[0] + m[1][0] * v[1],
  471. m[0][1] * v[0] + m[1][1] * v[1]
  472. };
  473. }
  474. template <class T>
  475. vector<T, 3> mul(const matrix<T, 3, 3>& m, const vector<T, 3>& v)
  476. {
  477. return
  478. {
  479. m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2],
  480. m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2],
  481. m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2]
  482. };
  483. }
  484. template <class T>
  485. vector<T, 4> mul(const matrix<T, 4, 4>& m, const vector<T, 4>& v)
  486. {
  487. return
  488. {
  489. m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2] + m[3][0] * v[3],
  490. m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2] + m[3][1] * v[3],
  491. m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2] * v[3],
  492. m[0][3] * v[0] + m[1][3] * v[1] + m[2][3] * v[2] + m[3][3] * v[3]
  493. };
  494. }
  495. template <class T>
  496. matrix<T, 4, 4> ortho(T left, T right, T bottom, T top, T z_near, T z_far)
  497. {
  498. return
  499. {{
  500. {T(2) / (right - left), T(0), T(0), T(0)},
  501. {T(0), T(2) / (top - bottom), T(0), T(0)},
  502. {T(0), T(0), T(-2) / (z_far - z_near), T(0)},
  503. {-((right + left) / (right - left)), -((top + bottom) / (top - bottom)), -((z_far + z_near) / (z_far - z_near)), T(1)}
  504. }};
  505. }
  506. template <class T>
  507. matrix<T, 2, 2> outer_product(const vector<T, 2>& c, const vector<T, 2>& r)
  508. {
  509. return
  510. {{
  511. {c[0] * r[0], c[1] * r[0]},
  512. {c[0] * r[1], c[1] * r[1]}
  513. }};
  514. }
  515. template <class T>
  516. matrix<T, 3, 3> outer_product(const vector<T, 3>& c, const vector<T, 3>& r)
  517. {
  518. return
  519. {{
  520. {c[0] * r[0], c[1] * r[0], c[2] * r[0]},
  521. {c[0] * r[1], c[1] * r[1], c[2] * r[1]},
  522. {c[0] * r[2], c[1] * r[2], c[2] * r[2]}
  523. }};
  524. }
  525. template <class T>
  526. matrix<T, 4, 4> outer_product(const vector<T, 4>& c, const vector<T, 4> r)
  527. {
  528. return
  529. {{
  530. {c[0] * r[0], c[1] * r[0], c[2] * r[0], c[3] * r[0]},
  531. {c[0] * r[1], c[1] * r[1], c[2] * r[1], c[3] * r[1]},
  532. {c[0] * r[2], c[1] * r[2], c[2] * r[2], c[3] * r[2]},
  533. {c[0] * r[3], c[1] * r[3], c[2] * r[3], c[3] * r[3]}
  534. }};
  535. }
  536. template <class T>
  537. matrix<T, 4, 4> perspective(T vertical_fov, T aspect_ratio, T z_near, T z_far)
  538. {
  539. T half_fov = vertical_fov * T(0.5);
  540. T f = std::cos(half_fov) / std::sin(half_fov);
  541. return
  542. {{
  543. {f / aspect_ratio, T(0), T(0), T(0)},
  544. {T(0), f, T(0), T(0)},
  545. {T(0), T(0), (z_far + z_near) / (z_near - z_far), T(-1)},
  546. {T(0), T(0), (T(2) * z_near * z_far) / (z_near - z_far), T(0)}
  547. }};
  548. }
  549. template <std::size_t N1, std::size_t M1, class T, std::size_t N0, std::size_t M0>
  550. matrix<T, N1, M1> resize(const matrix<T, N0, M0>& m)
  551. {
  552. matrix<T, N1, M1> resized;
  553. for (std::size_t i = 0; i < N1; ++i)
  554. {
  555. for (std::size_t j = 0; j < M1; ++j)
  556. {
  557. resized[i][j] = (i < N0 && j < M0) ? m[i][j] : ((i == j) ? T(1) : T(0));
  558. }
  559. }
  560. return resized;
  561. }
  562. template <class T>
  563. matrix<T, 4, 4> rotate(const matrix<T, 4, 4>& m, T angle, const vector<T, 3>& axis)
  564. {
  565. const T c = std::cos(angle);
  566. const T s = std::sin(angle);
  567. const vector<T, 3> temp = mul(axis, T(1) - c);
  568. matrix<T, 4, 4> rotation;
  569. rotation[0][0] = axis[0] * temp[0] + c
  570. rotation[0][1] = axis[1] * temp[0] + axis[2] * s;
  571. rotation[0][2] = axis[2] * temp[0] - axis[1] * s;
  572. rotation[0][3] = T(0);
  573. rotation[1][0] = axis[0] * temp[1] - axis[2] * s
  574. rotation[1][1] = axis[1] * temp[1] + c;
  575. rotation[1][2] = axis[2] * temp[1] + axis[0] * s;
  576. rotation[1][3] = T(0);
  577. rotation[2][0] = axis[0] * temp[2] + axis[1] * s;
  578. rotation[2][1] = axis[1] * temp[2] - axis[0] * s;
  579. rotation[2][2] = axis[2] * temp[2] + c
  580. rotation[2][3] = T(0);
  581. rotation[3][0] = T(0);
  582. rotation[3][1] = T(0);
  583. rotation[3][2] = T(0);
  584. rotation[3][3] = T(1);
  585. return mul(m, rotation);
  586. }
  587. template <class T>
  588. matrix<T, 4, 4> scale(const matrix<T, 4, 4>& m, const vector<T, 3>& v)
  589. {
  590. return mul(m, matrix<T, 4, 4>
  591. {{
  592. {v[0], T(0), T(0), T(0)},
  593. {T(0), v[1], T(0), T(0)},
  594. {T(0), T(0), v[2], T(0)},
  595. {T(0), T(0), T(0), T(1)}
  596. }});
  597. }
  598. template <class T>
  599. matrix<T, 2, 2> sub(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y)
  600. {
  601. return
  602. {{
  603. x[0] - y[0],
  604. x[1] - y[1]
  605. }};
  606. }
  607. template <class T>
  608. matrix<T, 3, 3> sub(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y)
  609. {
  610. return
  611. {{
  612. x[0] - y[0],
  613. x[1] - y[1],
  614. x[2] - y[2]
  615. }};
  616. }
  617. template <class T>
  618. matrix<T, 4, 4> sub(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y)
  619. {
  620. return
  621. {{
  622. x[0] - y[0],
  623. x[1] - y[1],
  624. x[2] - y[2],
  625. x[3] - y[3]
  626. }};
  627. }
  628. template <class T>
  629. matrix<T, 4, 4> translate(const matrix<T, 4, 4>& m, const vector<T, 3>& v)
  630. {
  631. return mul(m, matrix<T, 4, 4>
  632. {{
  633. {T(1), T(0), T(0), T(0)},
  634. {T(0), T(1), T(0), T(0)},
  635. {T(0), T(0), T(1), T(0)},
  636. {v[0], v[1], v[2], T(1)}
  637. }});
  638. }
  639. template <class T>
  640. matrix<T, 2, 2> transpose(const matrix<T, 2, 2>& m)
  641. {
  642. return
  643. {{
  644. {
  645. m[0][0], m[1][0]
  646. },
  647. {
  648. m[0][1], m[1][1]
  649. }
  650. }};
  651. }
  652. template <class T>
  653. matrix<T, 3, 3> transpose(const matrix<T, 3, 3>& m)
  654. {
  655. return
  656. {{
  657. {
  658. m[0][0], m[1][0], m[2][0]
  659. },
  660. {
  661. m[0][1], m[1][1], m[2][1]
  662. },
  663. {
  664. m[0][2], m[1][2], m[2][2]
  665. }
  666. }};
  667. }
  668. template <class T>
  669. matrix<T, 4, 4> transpose(const matrix<T, 4, 4>& m)
  670. {
  671. return
  672. {{
  673. {
  674. m[0][0], m[1][0], m[2][0], m[3][0]
  675. },
  676. {
  677. m[0][1], m[1][1], m[2][1], m[3][1]
  678. },
  679. {
  680. m[0][2], m[1][2], m[2][2], m[3][2]
  681. },
  682. {
  683. m[0][3], m[1][3], m[2][3], m[3][3]
  684. }
  685. }};
  686. }
  687. /// @}
  688. } // namespace math
  689. #endif // ANTKEEPER_MATH_MATRIX_FUNCTIONS_HPP