mat3.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. /*
  2. * Copyright (c), Recep Aslantas.
  3. *
  4. * MIT License (MIT), http://opensource.org/licenses/MIT
  5. * Full license can be found in the LICENSE file
  6. */
  7. /*
  8. Macros:
  9. GLM_MAT3_IDENTITY_INIT
  10. GLM_MAT3_ZERO_INIT
  11. GLM_MAT3_IDENTITY
  12. GLM_MAT3_ZERO
  13. glm_mat3_dup(mat, dest)
  14. Functions:
  15. CGLM_INLINE void glm_mat3_copy(mat3 mat, mat3 dest);
  16. CGLM_INLINE void glm_mat3_identity(mat3 mat);
  17. CGLM_INLINE void glm_mat3_identity_array(mat3 * restrict mat, size_t count);
  18. CGLM_INLINE void glm_mat3_zero(mat3 mat);
  19. CGLM_INLINE void glm_mat3_mul(mat3 m1, mat3 m2, mat3 dest);
  20. CGLM_INLINE void glm_mat3_transpose_to(mat3 m, mat3 dest);
  21. CGLM_INLINE void glm_mat3_transpose(mat3 m);
  22. CGLM_INLINE void glm_mat3_mulv(mat3 m, vec3 v, vec3 dest);
  23. CGLM_INLINE float glm_mat3_trace(mat3 m);
  24. CGLM_INLINE void glm_mat3_quat(mat3 m, versor dest);
  25. CGLM_INLINE void glm_mat3_scale(mat3 m, float s);
  26. CGLM_INLINE float glm_mat3_det(mat3 mat);
  27. CGLM_INLINE void glm_mat3_inv(mat3 mat, mat3 dest);
  28. CGLM_INLINE void glm_mat3_swap_col(mat3 mat, int col1, int col2);
  29. CGLM_INLINE void glm_mat3_swap_row(mat3 mat, int row1, int row2);
  30. CGLM_INLINE float glm_mat3_rmc(vec3 r, mat3 m, vec3 c);
  31. CGLM_INLINE void glm_mat3_make(float * restrict src, mat3 dest);
  32. */
  33. #ifndef cglm_mat3_h
  34. #define cglm_mat3_h
  35. #include "common.h"
  36. #include "vec3.h"
  37. #ifdef CGLM_SSE_FP
  38. # include "simd/sse2/mat3.h"
  39. #endif
  40. #ifdef CGLM_SIMD_WASM
  41. # include "simd/wasm/mat3.h"
  42. #endif
  43. #define GLM_MAT3_IDENTITY_INIT {{1.0f, 0.0f, 0.0f}, \
  44. {0.0f, 1.0f, 0.0f}, \
  45. {0.0f, 0.0f, 1.0f}}
  46. #define GLM_MAT3_ZERO_INIT {{0.0f, 0.0f, 0.0f}, \
  47. {0.0f, 0.0f, 0.0f}, \
  48. {0.0f, 0.0f, 0.0f}}
  49. /* for C only */
  50. #define GLM_MAT3_IDENTITY ((mat3)GLM_MAT3_IDENTITY_INIT)
  51. #define GLM_MAT3_ZERO ((mat3)GLM_MAT3_ZERO_INIT)
  52. /* DEPRECATED! use _copy, _ucopy versions */
  53. #define glm_mat3_dup(mat, dest) glm_mat3_copy(mat, dest)
  54. /*!
  55. * @brief copy all members of [mat] to [dest]
  56. *
  57. * @param[in] mat source
  58. * @param[out] dest destination
  59. */
  60. CGLM_INLINE
  61. void
  62. glm_mat3_copy(mat3 mat, mat3 dest) {
  63. dest[0][0] = mat[0][0];
  64. dest[0][1] = mat[0][1];
  65. dest[0][2] = mat[0][2];
  66. dest[1][0] = mat[1][0];
  67. dest[1][1] = mat[1][1];
  68. dest[1][2] = mat[1][2];
  69. dest[2][0] = mat[2][0];
  70. dest[2][1] = mat[2][1];
  71. dest[2][2] = mat[2][2];
  72. }
  73. /*!
  74. * @brief make given matrix identity. It is identical with below,
  75. * but it is more easy to do that with this func especially for members
  76. * e.g. glm_mat3_identity(aStruct->aMatrix);
  77. *
  78. * @code
  79. * glm_mat3_copy(GLM_MAT3_IDENTITY, mat); // C only
  80. *
  81. * // or
  82. * mat3 mat = GLM_MAT3_IDENTITY_INIT;
  83. * @endcode
  84. *
  85. * @param[in, out] mat destination
  86. */
  87. CGLM_INLINE
  88. void
  89. glm_mat3_identity(mat3 mat) {
  90. CGLM_ALIGN_MAT mat3 t = GLM_MAT3_IDENTITY_INIT;
  91. glm_mat3_copy(t, mat);
  92. }
  93. /*!
  94. * @brief make given matrix array's each element identity matrix
  95. *
  96. * @param[in, out] mat matrix array (must be aligned (16/32)
  97. * if alignment is not disabled)
  98. *
  99. * @param[in] count count of matrices
  100. */
  101. CGLM_INLINE
  102. void
  103. glm_mat3_identity_array(mat3 * __restrict mat, size_t count) {
  104. CGLM_ALIGN_MAT mat3 t = GLM_MAT3_IDENTITY_INIT;
  105. size_t i;
  106. for (i = 0; i < count; i++) {
  107. glm_mat3_copy(t, mat[i]);
  108. }
  109. }
  110. /*!
  111. * @brief make given matrix zero.
  112. *
  113. * @param[in, out] mat matrix
  114. */
  115. CGLM_INLINE
  116. void
  117. glm_mat3_zero(mat3 mat) {
  118. CGLM_ALIGN_MAT mat3 t = GLM_MAT3_ZERO_INIT;
  119. glm_mat3_copy(t, mat);
  120. }
  121. /*!
  122. * @brief multiply m1 and m2 to dest
  123. *
  124. * m1, m2 and dest matrices can be same matrix, it is possible to write this:
  125. *
  126. * @code
  127. * mat3 m = GLM_MAT3_IDENTITY_INIT;
  128. * glm_mat3_mul(m, m, m);
  129. * @endcode
  130. *
  131. * @param[in] m1 left matrix
  132. * @param[in] m2 right matrix
  133. * @param[out] dest destination matrix
  134. */
  135. CGLM_INLINE
  136. void
  137. glm_mat3_mul(mat3 m1, mat3 m2, mat3 dest) {
  138. #if defined(__wasm__) && defined(__wasm_simd128__)
  139. glm_mat3_mul_wasm(m1, m2, dest);
  140. #elif defined( __SSE__ ) || defined( __SSE2__ )
  141. glm_mat3_mul_sse2(m1, m2, dest);
  142. #else
  143. float a00 = m1[0][0], a01 = m1[0][1], a02 = m1[0][2],
  144. a10 = m1[1][0], a11 = m1[1][1], a12 = m1[1][2],
  145. a20 = m1[2][0], a21 = m1[2][1], a22 = m1[2][2],
  146. b00 = m2[0][0], b01 = m2[0][1], b02 = m2[0][2],
  147. b10 = m2[1][0], b11 = m2[1][1], b12 = m2[1][2],
  148. b20 = m2[2][0], b21 = m2[2][1], b22 = m2[2][2];
  149. dest[0][0] = a00 * b00 + a10 * b01 + a20 * b02;
  150. dest[0][1] = a01 * b00 + a11 * b01 + a21 * b02;
  151. dest[0][2] = a02 * b00 + a12 * b01 + a22 * b02;
  152. dest[1][0] = a00 * b10 + a10 * b11 + a20 * b12;
  153. dest[1][1] = a01 * b10 + a11 * b11 + a21 * b12;
  154. dest[1][2] = a02 * b10 + a12 * b11 + a22 * b12;
  155. dest[2][0] = a00 * b20 + a10 * b21 + a20 * b22;
  156. dest[2][1] = a01 * b20 + a11 * b21 + a21 * b22;
  157. dest[2][2] = a02 * b20 + a12 * b21 + a22 * b22;
  158. #endif
  159. }
  160. /*!
  161. * @brief transpose mat3 and store in dest
  162. *
  163. * source matrix will not be transposed unless dest is m
  164. *
  165. * @param[in] m matrix
  166. * @param[out] dest result
  167. */
  168. CGLM_INLINE
  169. void
  170. glm_mat3_transpose_to(mat3 m, mat3 dest) {
  171. dest[0][0] = m[0][0];
  172. dest[0][1] = m[1][0];
  173. dest[0][2] = m[2][0];
  174. dest[1][0] = m[0][1];
  175. dest[1][1] = m[1][1];
  176. dest[1][2] = m[2][1];
  177. dest[2][0] = m[0][2];
  178. dest[2][1] = m[1][2];
  179. dest[2][2] = m[2][2];
  180. }
  181. /*!
  182. * @brief tranpose mat3 and store result in same matrix
  183. *
  184. * @param[in, out] m source and dest
  185. */
  186. CGLM_INLINE
  187. void
  188. glm_mat3_transpose(mat3 m) {
  189. CGLM_ALIGN_MAT mat3 tmp;
  190. tmp[0][1] = m[1][0];
  191. tmp[0][2] = m[2][0];
  192. tmp[1][0] = m[0][1];
  193. tmp[1][2] = m[2][1];
  194. tmp[2][0] = m[0][2];
  195. tmp[2][1] = m[1][2];
  196. m[0][1] = tmp[0][1];
  197. m[0][2] = tmp[0][2];
  198. m[1][0] = tmp[1][0];
  199. m[1][2] = tmp[1][2];
  200. m[2][0] = tmp[2][0];
  201. m[2][1] = tmp[2][1];
  202. }
  203. /*!
  204. * @brief multiply mat3 with vec3 (column vector) and store in dest vector
  205. *
  206. * @param[in] m mat3 (left)
  207. * @param[in] v vec3 (right, column vector)
  208. * @param[out] dest vec3 (result, column vector)
  209. */
  210. CGLM_INLINE
  211. void
  212. glm_mat3_mulv(mat3 m, vec3 v, vec3 dest) {
  213. vec3 res;
  214. res[0] = m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2];
  215. res[1] = m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2];
  216. res[2] = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2];
  217. glm_vec3_copy(res, dest);
  218. }
  219. /*!
  220. * @brief trace of matrix
  221. *
  222. * sum of the elements on the main diagonal from upper left to the lower right
  223. *
  224. * @param[in] m matrix
  225. */
  226. CGLM_INLINE
  227. float
  228. glm_mat3_trace(mat3 m) {
  229. return m[0][0] + m[1][1] + m[2][2];
  230. }
  231. /*!
  232. * @brief convert mat3 to quaternion
  233. *
  234. * @param[in] m rotation matrix
  235. * @param[out] dest destination quaternion
  236. */
  237. CGLM_INLINE
  238. void
  239. glm_mat3_quat(mat3 m, versor dest) {
  240. float trace, r, rinv;
  241. /* it seems using like m12 instead of m[1][2] causes extra instructions */
  242. trace = m[0][0] + m[1][1] + m[2][2];
  243. if (trace >= 0.0f) {
  244. r = sqrtf(1.0f + trace);
  245. rinv = 0.5f / r;
  246. dest[0] = rinv * (m[1][2] - m[2][1]);
  247. dest[1] = rinv * (m[2][0] - m[0][2]);
  248. dest[2] = rinv * (m[0][1] - m[1][0]);
  249. dest[3] = r * 0.5f;
  250. } else if (m[0][0] >= m[1][1] && m[0][0] >= m[2][2]) {
  251. r = sqrtf(1.0f - m[1][1] - m[2][2] + m[0][0]);
  252. rinv = 0.5f / r;
  253. dest[0] = r * 0.5f;
  254. dest[1] = rinv * (m[0][1] + m[1][0]);
  255. dest[2] = rinv * (m[0][2] + m[2][0]);
  256. dest[3] = rinv * (m[1][2] - m[2][1]);
  257. } else if (m[1][1] >= m[2][2]) {
  258. r = sqrtf(1.0f - m[0][0] - m[2][2] + m[1][1]);
  259. rinv = 0.5f / r;
  260. dest[0] = rinv * (m[0][1] + m[1][0]);
  261. dest[1] = r * 0.5f;
  262. dest[2] = rinv * (m[1][2] + m[2][1]);
  263. dest[3] = rinv * (m[2][0] - m[0][2]);
  264. } else {
  265. r = sqrtf(1.0f - m[0][0] - m[1][1] + m[2][2]);
  266. rinv = 0.5f / r;
  267. dest[0] = rinv * (m[0][2] + m[2][0]);
  268. dest[1] = rinv * (m[1][2] + m[2][1]);
  269. dest[2] = r * 0.5f;
  270. dest[3] = rinv * (m[0][1] - m[1][0]);
  271. }
  272. }
  273. /*!
  274. * @brief scale (multiply with scalar) matrix
  275. *
  276. * multiply matrix with scalar
  277. *
  278. * @param[in, out] m matrix
  279. * @param[in] s scalar
  280. */
  281. CGLM_INLINE
  282. void
  283. glm_mat3_scale(mat3 m, float s) {
  284. m[0][0] *= s; m[0][1] *= s; m[0][2] *= s;
  285. m[1][0] *= s; m[1][1] *= s; m[1][2] *= s;
  286. m[2][0] *= s; m[2][1] *= s; m[2][2] *= s;
  287. }
  288. /*!
  289. * @brief mat3 determinant
  290. *
  291. * @param[in] mat matrix
  292. *
  293. * @return determinant
  294. */
  295. CGLM_INLINE
  296. float
  297. glm_mat3_det(mat3 mat) {
  298. float a = mat[0][0], b = mat[0][1], c = mat[0][2],
  299. d = mat[1][0], e = mat[1][1], f = mat[1][2],
  300. g = mat[2][0], h = mat[2][1], i = mat[2][2];
  301. return a * (e * i - h * f) - d * (b * i - c * h) + g * (b * f - c * e);
  302. }
  303. /*!
  304. * @brief inverse mat3 and store in dest
  305. *
  306. * @param[in] mat matrix
  307. * @param[out] dest inverse matrix
  308. */
  309. CGLM_INLINE
  310. void
  311. glm_mat3_inv(mat3 mat, mat3 dest) {
  312. float det;
  313. float a = mat[0][0], b = mat[0][1], c = mat[0][2],
  314. d = mat[1][0], e = mat[1][1], f = mat[1][2],
  315. g = mat[2][0], h = mat[2][1], i = mat[2][2];
  316. dest[0][0] = e * i - f * h;
  317. dest[0][1] = -(b * i - h * c);
  318. dest[0][2] = b * f - e * c;
  319. dest[1][0] = -(d * i - g * f);
  320. dest[1][1] = a * i - c * g;
  321. dest[1][2] = -(a * f - d * c);
  322. dest[2][0] = d * h - g * e;
  323. dest[2][1] = -(a * h - g * b);
  324. dest[2][2] = a * e - b * d;
  325. det = 1.0f / (a * dest[0][0] + b * dest[1][0] + c * dest[2][0]);
  326. glm_mat3_scale(dest, det);
  327. }
  328. /*!
  329. * @brief swap two matrix columns
  330. *
  331. * @param[in,out] mat matrix
  332. * @param[in] col1 col1
  333. * @param[in] col2 col2
  334. */
  335. CGLM_INLINE
  336. void
  337. glm_mat3_swap_col(mat3 mat, int col1, int col2) {
  338. vec3 tmp;
  339. glm_vec3_copy(mat[col1], tmp);
  340. glm_vec3_copy(mat[col2], mat[col1]);
  341. glm_vec3_copy(tmp, mat[col2]);
  342. }
  343. /*!
  344. * @brief swap two matrix rows
  345. *
  346. * @param[in,out] mat matrix
  347. * @param[in] row1 row1
  348. * @param[in] row2 row2
  349. */
  350. CGLM_INLINE
  351. void
  352. glm_mat3_swap_row(mat3 mat, int row1, int row2) {
  353. vec3 tmp;
  354. tmp[0] = mat[0][row1];
  355. tmp[1] = mat[1][row1];
  356. tmp[2] = mat[2][row1];
  357. mat[0][row1] = mat[0][row2];
  358. mat[1][row1] = mat[1][row2];
  359. mat[2][row1] = mat[2][row2];
  360. mat[0][row2] = tmp[0];
  361. mat[1][row2] = tmp[1];
  362. mat[2][row2] = tmp[2];
  363. }
  364. /*!
  365. * @brief helper for R (row vector) * M (matrix) * C (column vector)
  366. *
  367. * rmc stands for Row * Matrix * Column
  368. *
  369. * the result is scalar because R * M = Matrix1x3 (row vector),
  370. * then Matrix1x3 * Vec3 (column vector) = Matrix1x1 (Scalar)
  371. *
  372. * @param[in] r row vector or matrix1x3
  373. * @param[in] m matrix3x3
  374. * @param[in] c column vector or matrix3x1
  375. *
  376. * @return scalar value e.g. Matrix1x1
  377. */
  378. CGLM_INLINE
  379. float
  380. glm_mat3_rmc(vec3 r, mat3 m, vec3 c) {
  381. vec3 tmp;
  382. glm_mat3_mulv(m, c, tmp);
  383. return glm_vec3_dot(r, tmp);
  384. }
  385. /*!
  386. * @brief Create mat3 matrix from pointer
  387. *
  388. * @param[in] src pointer to an array of floats
  389. * @param[out] dest matrix
  390. */
  391. CGLM_INLINE
  392. void
  393. glm_mat3_make(float * __restrict src, mat3 dest) {
  394. dest[0][0] = src[0];
  395. dest[0][1] = src[1];
  396. dest[0][2] = src[2];
  397. dest[1][0] = src[3];
  398. dest[1][1] = src[4];
  399. dest[1][2] = src[5];
  400. dest[2][0] = src[6];
  401. dest[2][1] = src[7];
  402. dest[2][2] = src[8];
  403. }
  404. #endif /* cglm_mat3_h */