mat4.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802
  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. * Most of functions in this header are optimized manually with SIMD
  9. * if available. You dont need to call/incude SIMD headers manually
  10. */
  11. /*
  12. Macros:
  13. GLM_MAT4_IDENTITY_INIT
  14. GLM_MAT4_ZERO_INIT
  15. GLM_MAT4_IDENTITY
  16. GLM_MAT4_ZERO
  17. Functions:
  18. CGLM_INLINE void glm_mat4_ucopy(mat4 mat, mat4 dest);
  19. CGLM_INLINE void glm_mat4_copy(mat4 mat, mat4 dest);
  20. CGLM_INLINE void glm_mat4_identity(mat4 mat);
  21. CGLM_INLINE void glm_mat4_identity_array(mat4 * restrict mat, size_t count);
  22. CGLM_INLINE void glm_mat4_zero(mat4 mat);
  23. CGLM_INLINE void glm_mat4_pick3(mat4 mat, mat3 dest);
  24. CGLM_INLINE void glm_mat4_pick3t(mat4 mat, mat3 dest);
  25. CGLM_INLINE void glm_mat4_ins3(mat3 mat, mat4 dest);
  26. CGLM_INLINE void glm_mat4_mul(mat4 m1, mat4 m2, mat4 dest);
  27. CGLM_INLINE void glm_mat4_mulN(mat4 *matrices[], int len, mat4 dest);
  28. CGLM_INLINE void glm_mat4_mulv(mat4 m, vec4 v, vec4 dest);
  29. CGLM_INLINE void glm_mat4_mulv3(mat4 m, vec3 v, float last, vec3 dest);
  30. CGLM_INLINE float glm_mat4_trace(mat4 m);
  31. CGLM_INLINE float glm_mat4_trace3(mat4 m);
  32. CGLM_INLINE void glm_mat4_quat(mat4 m, versor dest) ;
  33. CGLM_INLINE void glm_mat4_transpose_to(mat4 m, mat4 dest);
  34. CGLM_INLINE void glm_mat4_transpose(mat4 m);
  35. CGLM_INLINE void glm_mat4_scale_p(mat4 m, float s);
  36. CGLM_INLINE void glm_mat4_scale(mat4 m, float s);
  37. CGLM_INLINE float glm_mat4_det(mat4 mat);
  38. CGLM_INLINE void glm_mat4_inv(mat4 mat, mat4 dest);
  39. CGLM_INLINE void glm_mat4_inv_fast(mat4 mat, mat4 dest);
  40. CGLM_INLINE void glm_mat4_swap_col(mat4 mat, int col1, int col2);
  41. CGLM_INLINE void glm_mat4_swap_row(mat4 mat, int row1, int row2);
  42. CGLM_INLINE float glm_mat4_rmc(vec4 r, mat4 m, vec4 c);
  43. CGLM_INLINE void glm_mat4_make(float * restrict src, mat4 dest);
  44. */
  45. #ifndef cglm_mat_h
  46. #define cglm_mat_h
  47. #include "common.h"
  48. #include "vec4.h"
  49. #include "vec3.h"
  50. #ifdef CGLM_SSE_FP
  51. # include "simd/sse2/mat4.h"
  52. #endif
  53. #ifdef CGLM_AVX_FP
  54. # include "simd/avx/mat4.h"
  55. #endif
  56. #ifdef CGLM_NEON_FP
  57. # include "simd/neon/mat4.h"
  58. #endif
  59. #ifdef CGLM_SIMD_WASM
  60. # include "simd/wasm/mat4.h"
  61. #endif
  62. #ifndef NDEBUG
  63. # include <assert.h>
  64. #endif
  65. #define GLM_MAT4_IDENTITY_INIT {{1.0f, 0.0f, 0.0f, 0.0f}, \
  66. {0.0f, 1.0f, 0.0f, 0.0f}, \
  67. {0.0f, 0.0f, 1.0f, 0.0f}, \
  68. {0.0f, 0.0f, 0.0f, 1.0f}}
  69. #define GLM_MAT4_ZERO_INIT {{0.0f, 0.0f, 0.0f, 0.0f}, \
  70. {0.0f, 0.0f, 0.0f, 0.0f}, \
  71. {0.0f, 0.0f, 0.0f, 0.0f}, \
  72. {0.0f, 0.0f, 0.0f, 0.0f}}
  73. /* for C only */
  74. #define GLM_MAT4_IDENTITY ((mat4)GLM_MAT4_IDENTITY_INIT)
  75. #define GLM_MAT4_ZERO ((mat4)GLM_MAT4_ZERO_INIT)
  76. /* DEPRECATED! use _copy, _ucopy versions */
  77. #define glm_mat4_udup(mat, dest) glm_mat4_ucopy(mat, dest)
  78. #define glm_mat4_dup(mat, dest) glm_mat4_copy(mat, dest)
  79. /* DEPRECATED! default is precise now. */
  80. #define glm_mat4_inv_precise(mat, dest) glm_mat4_inv(mat, dest)
  81. /*!
  82. * @brief copy all members of [mat] to [dest]
  83. *
  84. * matrix may not be aligned, u stands for unaligned, this may be useful when
  85. * copying a matrix from external source e.g. asset importer...
  86. *
  87. * @param[in] mat source
  88. * @param[out] dest destination
  89. */
  90. CGLM_INLINE
  91. void
  92. glm_mat4_ucopy(mat4 mat, mat4 dest) {
  93. dest[0][0] = mat[0][0]; dest[1][0] = mat[1][0];
  94. dest[0][1] = mat[0][1]; dest[1][1] = mat[1][1];
  95. dest[0][2] = mat[0][2]; dest[1][2] = mat[1][2];
  96. dest[0][3] = mat[0][3]; dest[1][3] = mat[1][3];
  97. dest[2][0] = mat[2][0]; dest[3][0] = mat[3][0];
  98. dest[2][1] = mat[2][1]; dest[3][1] = mat[3][1];
  99. dest[2][2] = mat[2][2]; dest[3][2] = mat[3][2];
  100. dest[2][3] = mat[2][3]; dest[3][3] = mat[3][3];
  101. }
  102. /*!
  103. * @brief copy all members of [mat] to [dest]
  104. *
  105. * @param[in] mat source
  106. * @param[out] dest destination
  107. */
  108. CGLM_INLINE
  109. void
  110. glm_mat4_copy(mat4 mat, mat4 dest) {
  111. #if defined(__wasm__) && defined(__wasm_simd128__)
  112. glmm_store(dest[0], glmm_load(mat[0]));
  113. glmm_store(dest[1], glmm_load(mat[1]));
  114. glmm_store(dest[2], glmm_load(mat[2]));
  115. glmm_store(dest[3], glmm_load(mat[3]));
  116. #elif defined(__AVX__)
  117. glmm_store256(dest[0], glmm_load256(mat[0]));
  118. glmm_store256(dest[2], glmm_load256(mat[2]));
  119. #elif defined( __SSE__ ) || defined( __SSE2__ )
  120. glmm_store(dest[0], glmm_load(mat[0]));
  121. glmm_store(dest[1], glmm_load(mat[1]));
  122. glmm_store(dest[2], glmm_load(mat[2]));
  123. glmm_store(dest[3], glmm_load(mat[3]));
  124. #elif defined(CGLM_NEON_FP)
  125. vst1q_f32(dest[0], vld1q_f32(mat[0]));
  126. vst1q_f32(dest[1], vld1q_f32(mat[1]));
  127. vst1q_f32(dest[2], vld1q_f32(mat[2]));
  128. vst1q_f32(dest[3], vld1q_f32(mat[3]));
  129. #else
  130. glm_mat4_ucopy(mat, dest);
  131. #endif
  132. }
  133. /*!
  134. * @brief make given matrix identity. It is identical with below,
  135. * but it is more easy to do that with this func especially for members
  136. * e.g. glm_mat4_identity(aStruct->aMatrix);
  137. *
  138. * @code
  139. * glm_mat4_copy(GLM_MAT4_IDENTITY, mat); // C only
  140. *
  141. * // or
  142. * mat4 mat = GLM_MAT4_IDENTITY_INIT;
  143. * @endcode
  144. *
  145. * @param[in, out] mat destination
  146. */
  147. CGLM_INLINE
  148. void
  149. glm_mat4_identity(mat4 mat) {
  150. CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT;
  151. glm_mat4_copy(t, mat);
  152. }
  153. /*!
  154. * @brief make given matrix array's each element identity matrix
  155. *
  156. * @param[in, out] mat matrix array (must be aligned (16/32)
  157. * if alignment is not disabled)
  158. *
  159. * @param[in] count count of matrices
  160. */
  161. CGLM_INLINE
  162. void
  163. glm_mat4_identity_array(mat4 * __restrict mat, size_t count) {
  164. CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT;
  165. size_t i;
  166. for (i = 0; i < count; i++) {
  167. glm_mat4_copy(t, mat[i]);
  168. }
  169. }
  170. /*!
  171. * @brief make given matrix zero.
  172. *
  173. * @param[in, out] mat matrix
  174. */
  175. CGLM_INLINE
  176. void
  177. glm_mat4_zero(mat4 mat) {
  178. #if defined(__wasm__) && defined(__wasm_simd128__)
  179. glmm_128 x0;
  180. x0 = wasm_f32x4_const_splat(0.f);
  181. glmm_store(mat[0], x0);
  182. glmm_store(mat[1], x0);
  183. glmm_store(mat[2], x0);
  184. glmm_store(mat[3], x0);
  185. #elif defined(__AVX__)
  186. __m256 y0;
  187. y0 = _mm256_setzero_ps();
  188. glmm_store256(mat[0], y0);
  189. glmm_store256(mat[2], y0);
  190. #elif defined( __SSE__ ) || defined( __SSE2__ )
  191. glmm_128 x0;
  192. x0 = _mm_setzero_ps();
  193. glmm_store(mat[0], x0);
  194. glmm_store(mat[1], x0);
  195. glmm_store(mat[2], x0);
  196. glmm_store(mat[3], x0);
  197. #elif defined(CGLM_NEON_FP)
  198. glmm_128 x0;
  199. x0 = vdupq_n_f32(0.0f);
  200. vst1q_f32(mat[0], x0);
  201. vst1q_f32(mat[1], x0);
  202. vst1q_f32(mat[2], x0);
  203. vst1q_f32(mat[3], x0);
  204. #else
  205. CGLM_ALIGN_MAT mat4 t = GLM_MAT4_ZERO_INIT;
  206. glm_mat4_copy(t, mat);
  207. #endif
  208. }
  209. /*!
  210. * @brief copy upper-left of mat4 to mat3
  211. *
  212. * @param[in] mat source
  213. * @param[out] dest destination
  214. */
  215. CGLM_INLINE
  216. void
  217. glm_mat4_pick3(mat4 mat, mat3 dest) {
  218. dest[0][0] = mat[0][0];
  219. dest[0][1] = mat[0][1];
  220. dest[0][2] = mat[0][2];
  221. dest[1][0] = mat[1][0];
  222. dest[1][1] = mat[1][1];
  223. dest[1][2] = mat[1][2];
  224. dest[2][0] = mat[2][0];
  225. dest[2][1] = mat[2][1];
  226. dest[2][2] = mat[2][2];
  227. }
  228. /*!
  229. * @brief copy upper-left of mat4 to mat3 (transposed)
  230. *
  231. * the postfix t stands for transpose
  232. *
  233. * @param[in] mat source
  234. * @param[out] dest destination
  235. */
  236. CGLM_INLINE
  237. void
  238. glm_mat4_pick3t(mat4 mat, mat3 dest) {
  239. dest[0][0] = mat[0][0];
  240. dest[0][1] = mat[1][0];
  241. dest[0][2] = mat[2][0];
  242. dest[1][0] = mat[0][1];
  243. dest[1][1] = mat[1][1];
  244. dest[1][2] = mat[2][1];
  245. dest[2][0] = mat[0][2];
  246. dest[2][1] = mat[1][2];
  247. dest[2][2] = mat[2][2];
  248. }
  249. /*!
  250. * @brief copy mat3 to mat4's upper-left
  251. *
  252. * @param[in] mat source
  253. * @param[out] dest destination
  254. */
  255. CGLM_INLINE
  256. void
  257. glm_mat4_ins3(mat3 mat, mat4 dest) {
  258. dest[0][0] = mat[0][0];
  259. dest[0][1] = mat[0][1];
  260. dest[0][2] = mat[0][2];
  261. dest[1][0] = mat[1][0];
  262. dest[1][1] = mat[1][1];
  263. dest[1][2] = mat[1][2];
  264. dest[2][0] = mat[2][0];
  265. dest[2][1] = mat[2][1];
  266. dest[2][2] = mat[2][2];
  267. }
  268. /*!
  269. * @brief multiply m1 and m2 to dest
  270. *
  271. * m1, m2 and dest matrices can be same matrix, it is possible to write this:
  272. *
  273. * @code
  274. * mat4 m = GLM_MAT4_IDENTITY_INIT;
  275. * glm_mat4_mul(m, m, m);
  276. * @endcode
  277. *
  278. * @param[in] m1 left matrix
  279. * @param[in] m2 right matrix
  280. * @param[out] dest destination matrix
  281. */
  282. CGLM_INLINE
  283. void
  284. glm_mat4_mul(mat4 m1, mat4 m2, mat4 dest) {
  285. #if defined(__wasm__) && defined(__wasm_simd128__)
  286. glm_mat4_mul_wasm(m1, m2, dest);
  287. #elif defined(__AVX__)
  288. glm_mat4_mul_avx(m1, m2, dest);
  289. #elif defined( __SSE__ ) || defined( __SSE2__ )
  290. glm_mat4_mul_sse2(m1, m2, dest);
  291. #elif defined(CGLM_NEON_FP)
  292. glm_mat4_mul_neon(m1, m2, dest);
  293. #else
  294. float a00 = m1[0][0], a01 = m1[0][1], a02 = m1[0][2], a03 = m1[0][3],
  295. a10 = m1[1][0], a11 = m1[1][1], a12 = m1[1][2], a13 = m1[1][3],
  296. a20 = m1[2][0], a21 = m1[2][1], a22 = m1[2][2], a23 = m1[2][3],
  297. a30 = m1[3][0], a31 = m1[3][1], a32 = m1[3][2], a33 = m1[3][3],
  298. b00 = m2[0][0], b01 = m2[0][1], b02 = m2[0][2], b03 = m2[0][3],
  299. b10 = m2[1][0], b11 = m2[1][1], b12 = m2[1][2], b13 = m2[1][3],
  300. b20 = m2[2][0], b21 = m2[2][1], b22 = m2[2][2], b23 = m2[2][3],
  301. b30 = m2[3][0], b31 = m2[3][1], b32 = m2[3][2], b33 = m2[3][3];
  302. dest[0][0] = a00 * b00 + a10 * b01 + a20 * b02 + a30 * b03;
  303. dest[0][1] = a01 * b00 + a11 * b01 + a21 * b02 + a31 * b03;
  304. dest[0][2] = a02 * b00 + a12 * b01 + a22 * b02 + a32 * b03;
  305. dest[0][3] = a03 * b00 + a13 * b01 + a23 * b02 + a33 * b03;
  306. dest[1][0] = a00 * b10 + a10 * b11 + a20 * b12 + a30 * b13;
  307. dest[1][1] = a01 * b10 + a11 * b11 + a21 * b12 + a31 * b13;
  308. dest[1][2] = a02 * b10 + a12 * b11 + a22 * b12 + a32 * b13;
  309. dest[1][3] = a03 * b10 + a13 * b11 + a23 * b12 + a33 * b13;
  310. dest[2][0] = a00 * b20 + a10 * b21 + a20 * b22 + a30 * b23;
  311. dest[2][1] = a01 * b20 + a11 * b21 + a21 * b22 + a31 * b23;
  312. dest[2][2] = a02 * b20 + a12 * b21 + a22 * b22 + a32 * b23;
  313. dest[2][3] = a03 * b20 + a13 * b21 + a23 * b22 + a33 * b23;
  314. dest[3][0] = a00 * b30 + a10 * b31 + a20 * b32 + a30 * b33;
  315. dest[3][1] = a01 * b30 + a11 * b31 + a21 * b32 + a31 * b33;
  316. dest[3][2] = a02 * b30 + a12 * b31 + a22 * b32 + a32 * b33;
  317. dest[3][3] = a03 * b30 + a13 * b31 + a23 * b32 + a33 * b33;
  318. #endif
  319. }
  320. /*!
  321. * @brief mupliply N mat4 matrices and store result in dest
  322. *
  323. * this function lets you multiply multiple (more than two or more...) matrices
  324. * <br><br>multiplication will be done in loop, this may reduce instructions
  325. * size but if <b>len</b> is too small then compiler may unroll whole loop,
  326. * usage:
  327. * @code
  328. * mat m1, m2, m3, m4, res;
  329. *
  330. * glm_mat4_mulN((mat4 *[]){&m1, &m2, &m3, &m4}, 4, res);
  331. * @endcode
  332. *
  333. * @warning matrices parameter is pointer array not mat4 array!
  334. *
  335. * @param[in] matrices mat4 * array
  336. * @param[in] len matrices count
  337. * @param[out] dest result
  338. */
  339. CGLM_INLINE
  340. void
  341. glm_mat4_mulN(mat4 * __restrict matrices[], uint32_t len, mat4 dest) {
  342. uint32_t i;
  343. #ifndef NDEBUG
  344. assert(len > 1 && "there must be least 2 matrices to go!");
  345. #endif
  346. glm_mat4_mul(*matrices[0], *matrices[1], dest);
  347. for (i = 2; i < len; i++)
  348. glm_mat4_mul(dest, *matrices[i], dest);
  349. }
  350. /*!
  351. * @brief multiply mat4 with vec4 (column vector) and store in dest vector
  352. *
  353. * @param[in] m mat4 (left)
  354. * @param[in] v vec4 (right, column vector)
  355. * @param[out] dest vec4 (result, column vector)
  356. */
  357. CGLM_INLINE
  358. void
  359. glm_mat4_mulv(mat4 m, vec4 v, vec4 dest) {
  360. #if defined(__wasm__) && defined(__wasm_simd128__)
  361. glm_mat4_mulv_wasm(m, v, dest);
  362. #elif defined( __SSE__ ) || defined( __SSE2__ )
  363. glm_mat4_mulv_sse2(m, v, dest);
  364. #elif defined(CGLM_NEON_FP)
  365. glm_mat4_mulv_neon(m, v, dest);
  366. #else
  367. vec4 res;
  368. res[0] = m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2] + m[3][0] * v[3];
  369. res[1] = m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2] + m[3][1] * v[3];
  370. res[2] = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2] * v[3];
  371. res[3] = m[0][3] * v[0] + m[1][3] * v[1] + m[2][3] * v[2] + m[3][3] * v[3];
  372. glm_vec4_copy(res, dest);
  373. #endif
  374. }
  375. /*!
  376. * @brief trace of matrix
  377. *
  378. * sum of the elements on the main diagonal from upper left to the lower right
  379. *
  380. * @param[in] m matrix
  381. */
  382. CGLM_INLINE
  383. float
  384. glm_mat4_trace(mat4 m) {
  385. return m[0][0] + m[1][1] + m[2][2] + m[3][3];
  386. }
  387. /*!
  388. * @brief trace of matrix (rotation part)
  389. *
  390. * sum of the elements on the main diagonal from upper left to the lower right
  391. *
  392. * @param[in] m matrix
  393. */
  394. CGLM_INLINE
  395. float
  396. glm_mat4_trace3(mat4 m) {
  397. return m[0][0] + m[1][1] + m[2][2];
  398. }
  399. /*!
  400. * @brief convert mat4's rotation part to quaternion
  401. *
  402. * @param[in] m affine matrix
  403. * @param[out] dest destination quaternion
  404. */
  405. CGLM_INLINE
  406. void
  407. glm_mat4_quat(mat4 m, versor dest) {
  408. float trace, r, rinv;
  409. /* it seems using like m12 instead of m[1][2] causes extra instructions */
  410. trace = m[0][0] + m[1][1] + m[2][2];
  411. if (trace >= 0.0f) {
  412. r = sqrtf(1.0f + trace);
  413. rinv = 0.5f / r;
  414. dest[0] = rinv * (m[1][2] - m[2][1]);
  415. dest[1] = rinv * (m[2][0] - m[0][2]);
  416. dest[2] = rinv * (m[0][1] - m[1][0]);
  417. dest[3] = r * 0.5f;
  418. } else if (m[0][0] >= m[1][1] && m[0][0] >= m[2][2]) {
  419. r = sqrtf(1.0f - m[1][1] - m[2][2] + m[0][0]);
  420. rinv = 0.5f / r;
  421. dest[0] = r * 0.5f;
  422. dest[1] = rinv * (m[0][1] + m[1][0]);
  423. dest[2] = rinv * (m[0][2] + m[2][0]);
  424. dest[3] = rinv * (m[1][2] - m[2][1]);
  425. } else if (m[1][1] >= m[2][2]) {
  426. r = sqrtf(1.0f - m[0][0] - m[2][2] + m[1][1]);
  427. rinv = 0.5f / r;
  428. dest[0] = rinv * (m[0][1] + m[1][0]);
  429. dest[1] = r * 0.5f;
  430. dest[2] = rinv * (m[1][2] + m[2][1]);
  431. dest[3] = rinv * (m[2][0] - m[0][2]);
  432. } else {
  433. r = sqrtf(1.0f - m[0][0] - m[1][1] + m[2][2]);
  434. rinv = 0.5f / r;
  435. dest[0] = rinv * (m[0][2] + m[2][0]);
  436. dest[1] = rinv * (m[1][2] + m[2][1]);
  437. dest[2] = r * 0.5f;
  438. dest[3] = rinv * (m[0][1] - m[1][0]);
  439. }
  440. }
  441. /*!
  442. * @brief multiply vector with mat4
  443. *
  444. * actually the result is vec4, after multiplication the last component
  445. * is trimmed. if you need it don't use this func.
  446. *
  447. * @param[in] m mat4(affine transform)
  448. * @param[in] v vec3
  449. * @param[in] last 4th item to make it vec4
  450. * @param[out] dest result vector (vec3)
  451. */
  452. CGLM_INLINE
  453. void
  454. glm_mat4_mulv3(mat4 m, vec3 v, float last, vec3 dest) {
  455. vec4 res;
  456. glm_vec4(v, last, res);
  457. glm_mat4_mulv(m, res, res);
  458. glm_vec3(res, dest);
  459. }
  460. /*!
  461. * @brief transpose mat4 and store in dest
  462. *
  463. * source matrix will not be transposed unless dest is m
  464. *
  465. * @param[in] m matrix
  466. * @param[out] dest result
  467. */
  468. CGLM_INLINE
  469. void
  470. glm_mat4_transpose_to(mat4 m, mat4 dest) {
  471. #if defined(__wasm__) && defined(__wasm_simd128__)
  472. glm_mat4_transp_wasm(m, dest);
  473. #elif defined(__AVX__)
  474. glm_mat4_transp_avx(m, dest);
  475. #elif defined( __SSE__ ) || defined( __SSE2__ )
  476. glm_mat4_transp_sse2(m, dest);
  477. #elif defined(CGLM_NEON_FP)
  478. glm_mat4_transp_neon(m, dest);
  479. #else
  480. dest[0][0] = m[0][0]; dest[1][0] = m[0][1];
  481. dest[0][1] = m[1][0]; dest[1][1] = m[1][1];
  482. dest[0][2] = m[2][0]; dest[1][2] = m[2][1];
  483. dest[0][3] = m[3][0]; dest[1][3] = m[3][1];
  484. dest[2][0] = m[0][2]; dest[3][0] = m[0][3];
  485. dest[2][1] = m[1][2]; dest[3][1] = m[1][3];
  486. dest[2][2] = m[2][2]; dest[3][2] = m[2][3];
  487. dest[2][3] = m[3][2]; dest[3][3] = m[3][3];
  488. #endif
  489. }
  490. /*!
  491. * @brief transpose mat4 and store result in same matrix
  492. *
  493. * @param[in, out] m source and dest
  494. */
  495. CGLM_INLINE
  496. void
  497. glm_mat4_transpose(mat4 m) {
  498. #if defined(__wasm__) && defined(__wasm_simd128__)
  499. glm_mat4_transp_wasm(m, m);
  500. #elif defined(__AVX__)
  501. glm_mat4_transp_avx(m, m);
  502. #elif defined( __SSE__ ) || defined( __SSE2__ )
  503. glm_mat4_transp_sse2(m, m);
  504. #elif defined(CGLM_NEON_FP)
  505. glm_mat4_transp_neon(m, m);
  506. #else
  507. mat4 d;
  508. glm_mat4_transpose_to(m, d);
  509. glm_mat4_ucopy(d, m);
  510. #endif
  511. }
  512. /*!
  513. * @brief scale (multiply with scalar) matrix without simd optimization
  514. *
  515. * multiply matrix with scalar
  516. *
  517. * @param[in, out] m matrix
  518. * @param[in] s scalar
  519. */
  520. CGLM_INLINE
  521. void
  522. glm_mat4_scale_p(mat4 m, float s) {
  523. m[0][0] *= s; m[0][1] *= s; m[0][2] *= s; m[0][3] *= s;
  524. m[1][0] *= s; m[1][1] *= s; m[1][2] *= s; m[1][3] *= s;
  525. m[2][0] *= s; m[2][1] *= s; m[2][2] *= s; m[2][3] *= s;
  526. m[3][0] *= s; m[3][1] *= s; m[3][2] *= s; m[3][3] *= s;
  527. }
  528. /*!
  529. * @brief scale (multiply with scalar) matrix
  530. *
  531. * multiply matrix with scalar
  532. *
  533. * @param[in, out] m matrix
  534. * @param[in] s scalar
  535. */
  536. CGLM_INLINE
  537. void
  538. glm_mat4_scale(mat4 m, float s) {
  539. #if defined(__wasm__) && defined(__wasm_simd128__)
  540. glm_mat4_scale_wasm(m, s);
  541. #elif defined(__AVX__)
  542. glm_mat4_scale_avx(m, s);
  543. #elif defined( __SSE__ ) || defined( __SSE2__ )
  544. glm_mat4_scale_sse2(m, s);
  545. #elif defined(CGLM_NEON_FP)
  546. glm_mat4_scale_neon(m, s);
  547. #else
  548. glm_mat4_scale_p(m, s);
  549. #endif
  550. }
  551. /*!
  552. * @brief mat4 determinant
  553. *
  554. * @param[in] mat matrix
  555. *
  556. * @return determinant
  557. */
  558. CGLM_INLINE
  559. float
  560. glm_mat4_det(mat4 mat) {
  561. #if defined(__wasm__) && defined(__wasm_simd128__)
  562. return glm_mat4_det_wasm(mat);
  563. #elif defined( __SSE__ ) || defined( __SSE2__ )
  564. return glm_mat4_det_sse2(mat);
  565. #elif defined(CGLM_NEON_FP)
  566. return glm_mat4_det_neon(mat);
  567. #else
  568. /* [square] det(A) = det(At) */
  569. float t[6];
  570. float a = mat[0][0], b = mat[0][1], c = mat[0][2], d = mat[0][3],
  571. e = mat[1][0], f = mat[1][1], g = mat[1][2], h = mat[1][3],
  572. i = mat[2][0], j = mat[2][1], k = mat[2][2], l = mat[2][3],
  573. m = mat[3][0], n = mat[3][1], o = mat[3][2], p = mat[3][3];
  574. t[0] = k * p - o * l;
  575. t[1] = j * p - n * l;
  576. t[2] = j * o - n * k;
  577. t[3] = i * p - m * l;
  578. t[4] = i * o - m * k;
  579. t[5] = i * n - m * j;
  580. return a * (f * t[0] - g * t[1] + h * t[2])
  581. - b * (e * t[0] - g * t[3] + h * t[4])
  582. + c * (e * t[1] - f * t[3] + h * t[5])
  583. - d * (e * t[2] - f * t[4] + g * t[5]);
  584. #endif
  585. }
  586. /*!
  587. * @brief inverse mat4 and store in dest
  588. *
  589. * @param[in] mat matrix
  590. * @param[out] dest inverse matrix
  591. */
  592. CGLM_INLINE
  593. void
  594. glm_mat4_inv(mat4 mat, mat4 dest) {
  595. #if defined(__wasm__) && defined(__wasm_simd128__)
  596. glm_mat4_inv_wasm(mat, dest);
  597. #elif defined( __SSE__ ) || defined( __SSE2__ )
  598. glm_mat4_inv_sse2(mat, dest);
  599. #elif defined(CGLM_NEON_FP)
  600. glm_mat4_inv_neon(mat, dest);
  601. #else
  602. float a = mat[0][0], b = mat[0][1], c = mat[0][2], d = mat[0][3],
  603. e = mat[1][0], f = mat[1][1], g = mat[1][2], h = mat[1][3],
  604. i = mat[2][0], j = mat[2][1], k = mat[2][2], l = mat[2][3],
  605. m = mat[3][0], n = mat[3][1], o = mat[3][2], p = mat[3][3],
  606. c1 = k * p - l * o, c2 = c * h - d * g, c3 = i * p - l * m,
  607. c4 = a * h - d * e, c5 = j * p - l * n, c6 = b * h - d * f,
  608. c7 = i * n - j * m, c8 = a * f - b * e, c9 = j * o - k * n,
  609. c10 = b * g - c * f, c11 = i * o - k * m, c12 = a * g - c * e,
  610. idt = 1.0f/(c8*c1+c4*c9+c10*c3+c2*c7-c12*c5-c6*c11), ndt = -idt;
  611. dest[0][0] = (f * c1 - g * c5 + h * c9) * idt;
  612. dest[0][1] = (b * c1 - c * c5 + d * c9) * ndt;
  613. dest[0][2] = (n * c2 - o * c6 + p * c10) * idt;
  614. dest[0][3] = (j * c2 - k * c6 + l * c10) * ndt;
  615. dest[1][0] = (e * c1 - g * c3 + h * c11) * ndt;
  616. dest[1][1] = (a * c1 - c * c3 + d * c11) * idt;
  617. dest[1][2] = (m * c2 - o * c4 + p * c12) * ndt;
  618. dest[1][3] = (i * c2 - k * c4 + l * c12) * idt;
  619. dest[2][0] = (e * c5 - f * c3 + h * c7) * idt;
  620. dest[2][1] = (a * c5 - b * c3 + d * c7) * ndt;
  621. dest[2][2] = (m * c6 - n * c4 + p * c8) * idt;
  622. dest[2][3] = (i * c6 - j * c4 + l * c8) * ndt;
  623. dest[3][0] = (e * c9 - f * c11 + g * c7) * ndt;
  624. dest[3][1] = (a * c9 - b * c11 + c * c7) * idt;
  625. dest[3][2] = (m * c10 - n * c12 + o * c8) * ndt;
  626. dest[3][3] = (i * c10 - j * c12 + k * c8) * idt;
  627. #endif
  628. }
  629. /*!
  630. * @brief inverse mat4 and store in dest
  631. *
  632. * this func uses reciprocal approximation without extra corrections
  633. * e.g Newton-Raphson. this should work faster than normal,
  634. * to get more precise use glm_mat4_inv version.
  635. *
  636. * NOTE: You will lose precision, glm_mat4_inv is more accurate
  637. *
  638. * @param[in] mat matrix
  639. * @param[out] dest inverse matrix
  640. */
  641. CGLM_INLINE
  642. void
  643. glm_mat4_inv_fast(mat4 mat, mat4 dest) {
  644. #if defined(__wasm__) && defined(__wasm_simd128__)
  645. glm_mat4_inv_fast_wasm(mat, dest);
  646. #elif defined( __SSE__ ) || defined( __SSE2__ )
  647. glm_mat4_inv_fast_sse2(mat, dest);
  648. #else
  649. glm_mat4_inv(mat, dest);
  650. #endif
  651. }
  652. /*!
  653. * @brief swap two matrix columns
  654. *
  655. * @param[in,out] mat matrix
  656. * @param[in] col1 col1
  657. * @param[in] col2 col2
  658. */
  659. CGLM_INLINE
  660. void
  661. glm_mat4_swap_col(mat4 mat, int col1, int col2) {
  662. CGLM_ALIGN(16) vec4 tmp;
  663. glm_vec4_copy(mat[col1], tmp);
  664. glm_vec4_copy(mat[col2], mat[col1]);
  665. glm_vec4_copy(tmp, mat[col2]);
  666. }
  667. /*!
  668. * @brief swap two matrix rows
  669. *
  670. * @param[in,out] mat matrix
  671. * @param[in] row1 row1
  672. * @param[in] row2 row2
  673. */
  674. CGLM_INLINE
  675. void
  676. glm_mat4_swap_row(mat4 mat, int row1, int row2) {
  677. CGLM_ALIGN(16) vec4 tmp;
  678. tmp[0] = mat[0][row1];
  679. tmp[1] = mat[1][row1];
  680. tmp[2] = mat[2][row1];
  681. tmp[3] = mat[3][row1];
  682. mat[0][row1] = mat[0][row2];
  683. mat[1][row1] = mat[1][row2];
  684. mat[2][row1] = mat[2][row2];
  685. mat[3][row1] = mat[3][row2];
  686. mat[0][row2] = tmp[0];
  687. mat[1][row2] = tmp[1];
  688. mat[2][row2] = tmp[2];
  689. mat[3][row2] = tmp[3];
  690. }
  691. /*!
  692. * @brief helper for R (row vector) * M (matrix) * C (column vector)
  693. *
  694. * rmc stands for Row * Matrix * Column
  695. *
  696. * the result is scalar because R * M = Matrix1x4 (row vector),
  697. * then Matrix1x4 * Vec4 (column vector) = Matrix1x1 (Scalar)
  698. *
  699. * @param[in] r row vector or matrix1x4
  700. * @param[in] m matrix4x4
  701. * @param[in] c column vector or matrix4x1
  702. *
  703. * @return scalar value e.g. B(s)
  704. */
  705. CGLM_INLINE
  706. float
  707. glm_mat4_rmc(vec4 r, mat4 m, vec4 c) {
  708. vec4 tmp;
  709. glm_mat4_mulv(m, c, tmp);
  710. return glm_vec4_dot(r, tmp);
  711. }
  712. /*!
  713. * @brief Create mat4 matrix from pointer
  714. *
  715. * @param[in] src pointer to an array of floats
  716. * @param[out] dest matrix
  717. */
  718. CGLM_INLINE
  719. void
  720. glm_mat4_make(const float * __restrict src, mat4 dest) {
  721. dest[0][0] = src[0]; dest[1][0] = src[4];
  722. dest[0][1] = src[1]; dest[1][1] = src[5];
  723. dest[0][2] = src[2]; dest[1][2] = src[6];
  724. dest[0][3] = src[3]; dest[1][3] = src[7];
  725. dest[2][0] = src[8]; dest[3][0] = src[12];
  726. dest[2][1] = src[9]; dest[3][1] = src[13];
  727. dest[2][2] = src[10]; dest[3][2] = src[14];
  728. dest[2][3] = src[11]; dest[3][3] = src[15];
  729. }
  730. #endif /* cglm_mat_h */