1
0

mat4.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  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. GLMS_MAT4_IDENTITY_INIT
  14. GLMS_MAT4_ZERO_INIT
  15. GLMS_MAT4_IDENTITY
  16. GLMS_MAT4_ZERO
  17. Functions:
  18. CGLM_INLINE mat4s glms_mat4_ucopy(mat4s mat);
  19. CGLM_INLINE mat4s glms_mat4_copy(mat4s mat);
  20. CGLM_INLINE mat4s glms_mat4_identity(void);
  21. CGLM_INLINE void glms_mat4_identity_array(mat4s * __restrict mat, size_t count);
  22. CGLM_INLINE mat4s glms_mat4_zero(void);
  23. CGLM_INLINE mat3s glms_mat4_pick3(mat4s mat);
  24. CGLM_INLINE mat3s glms_mat4_pick3t(mat4s mat);
  25. CGLM_INLINE mat4s glms_mat4_ins3(mat3s mat, mat4s dest);
  26. CGLM_INLINE mat4s glms_mat4_mul(mat4s m1, mat4s m2);
  27. CGLM_INLINE mat4s glms_mat4_mulN(mat4s * __restrict matrices[], uint32_t len);
  28. CGLM_INLINE vec4s glms_mat4_mulv(mat4s m, vec4s v);
  29. CGLM_INLINE float glms_mat4_trace(mat4s m);
  30. CGLM_INLINE float glms_mat4_trace3(mat4s m);
  31. CGLM_INLINE versors glms_mat4_quat(mat4s m);
  32. CGLM_INLINE vec3s glms_mat4_mulv3(mat4s m, vec3s v, float last);
  33. CGLM_INLINE mat4s glms_mat4_transpose(mat4s m);
  34. CGLM_INLINE mat4s glms_mat4_scale_p(mat4s m, float s);
  35. CGLM_INLINE mat4s glms_mat4_scale(mat4s m, float s);
  36. CGLM_INLINE float glms_mat4_det(mat4s mat);
  37. CGLM_INLINE mat4s glms_mat4_inv(mat4s mat);
  38. CGLM_INLINE mat4s glms_mat4_inv_fast(mat4s mat);
  39. CGLM_INLINE mat4s glms_mat4_swap_col(mat4s mat, int col1, int col2);
  40. CGLM_INLINE mat4s glms_mat4_swap_row(mat4s mat, int row1, int row2);
  41. CGLM_INLINE float glms_mat4_rmc(vec4s r, mat4s m, vec4s c);
  42. CGLM_INLINE mat4s glms_mat4_make(const float * __restrict src);
  43. */
  44. #ifndef cglms_mat4s_h
  45. #define cglms_mat4s_h
  46. #include "../common.h"
  47. #include "../types-struct.h"
  48. #include "../mat4.h"
  49. #include "vec4.h"
  50. #include "vec3.h"
  51. /* api definition */
  52. #define glms_mat4_(NAME) CGLM_STRUCTAPI(mat4, NAME)
  53. #define GLMS_MAT4_IDENTITY_INIT {GLM_MAT4_IDENTITY_INIT}
  54. #define GLMS_MAT4_ZERO_INIT {GLM_MAT4_ZERO_INIT}
  55. /* for C only */
  56. #define GLMS_MAT4_IDENTITY ((mat4s)GLMS_MAT4_IDENTITY_INIT)
  57. #define GLMS_MAT4_ZERO ((mat4s)GLMS_MAT4_ZERO_INIT)
  58. /*!
  59. * @brief copy all members of [mat] to [dest]
  60. *
  61. * matrix may not be aligned, u stands for unaligned, this may be useful when
  62. * copying a matrix from external source e.g. asset importer...
  63. *
  64. * @param[in] mat source
  65. * @returns destination
  66. */
  67. CGLM_INLINE
  68. mat4s
  69. glms_mat4_(ucopy)(mat4s mat) {
  70. mat4s r;
  71. glm_mat4_ucopy(mat.raw, r.raw);
  72. return r;
  73. }
  74. /*!
  75. * @brief copy all members of [mat] to [dest]
  76. *
  77. * @param[in] mat source
  78. * @returns destination
  79. */
  80. CGLM_INLINE
  81. mat4s
  82. glms_mat4_(copy)(mat4s mat) {
  83. mat4s r;
  84. glm_mat4_copy(mat.raw, r.raw);
  85. return r;
  86. }
  87. /*!
  88. * @brief make given matrix identity. It is identical with below,
  89. * but it is more easy to do that with this func especially for members
  90. * e.g. glm_mat4_identity(aStruct->aMatrix);
  91. *
  92. * @code
  93. * glm_mat4_copy(GLM_MAT4_IDENTITY, mat); // C only
  94. *
  95. * // or
  96. * mat4 mat = GLM_MAT4_IDENTITY_INIT;
  97. * @endcode
  98. *
  99. * @returns destination
  100. */
  101. CGLM_INLINE
  102. mat4s
  103. glms_mat4_(identity)(void) {
  104. mat4s r;
  105. glm_mat4_identity(r.raw);
  106. return r;
  107. }
  108. /*!
  109. * @brief make given matrix array's each element identity matrix
  110. *
  111. * @param[in, out] mat matrix array (must be aligned (16/32)
  112. * if alignment is not disabled)
  113. *
  114. * @param[in] count count of matrices
  115. */
  116. CGLM_INLINE
  117. void
  118. glms_mat4_(identity_array)(mat4s * __restrict mat, size_t count) {
  119. CGLM_ALIGN_MAT mat4s t = GLMS_MAT4_IDENTITY_INIT;
  120. size_t i;
  121. for (i = 0; i < count; i++) {
  122. glm_mat4_copy(t.raw, mat[i].raw);
  123. }
  124. }
  125. /*!
  126. * @brief make given matrix zero.
  127. *
  128. * @returns matrix
  129. */
  130. CGLM_INLINE
  131. mat4s
  132. glms_mat4_(zero)(void) {
  133. mat4s r;
  134. glm_mat4_zero(r.raw);
  135. return r;
  136. }
  137. /*!
  138. * @brief copy upper-left of mat4 to mat3
  139. *
  140. * @param[in] mat source
  141. * @returns destination
  142. */
  143. CGLM_INLINE
  144. mat3s
  145. glms_mat4_(pick3)(mat4s mat) {
  146. mat3s r;
  147. glm_mat4_pick3(mat.raw, r.raw);
  148. return r;
  149. }
  150. /*!
  151. * @brief copy upper-left of mat4 to mat3 (transposed)
  152. *
  153. * the postfix t stands for transpose
  154. *
  155. * @param[in] mat source
  156. * @returns destination
  157. */
  158. CGLM_INLINE
  159. mat3s
  160. glms_mat4_(pick3t)(mat4s mat) {
  161. mat3s r;
  162. glm_mat4_pick3t(mat.raw, r.raw);
  163. return r;
  164. }
  165. /*!
  166. * @brief copy mat3 to mat4's upper-left
  167. *
  168. * @param[in] mat source
  169. * @param[in] dest destination
  170. * @returns destination
  171. */
  172. CGLM_INLINE
  173. mat4s
  174. glms_mat4_(ins3)(mat3s mat, mat4s dest) {
  175. glm_mat4_ins3(mat.raw, dest.raw);
  176. return dest;
  177. }
  178. /*!
  179. * @brief multiply m1 and m2 to dest
  180. *
  181. * m1, m2 and dest matrices can be same matrix, it is possible to write this:
  182. *
  183. * @code
  184. * mat4 m = GLM_MAT4_IDENTITY_INIT;
  185. * r = glms_mat4_mul(m, m);
  186. * @endcode
  187. *
  188. * @param[in] m1 left matrix
  189. * @param[in] m2 right matrix
  190. * @returns destination matrix
  191. */
  192. CGLM_INLINE
  193. mat4s
  194. glms_mat4_(mul)(mat4s m1, mat4s m2) {
  195. mat4s r;
  196. glm_mat4_mul(m1.raw, m2.raw, r.raw);
  197. return r;
  198. }
  199. /*!
  200. * @brief mupliply N mat4 matrices and store result in dest
  201. *
  202. * this function lets you multiply multiple (more than two or more...) matrices
  203. * <br><br>multiplication will be done in loop, this may reduce instructions
  204. * size but if <b>len</b> is too small then compiler may unroll whole loop,
  205. * usage:
  206. * @code
  207. * mat m1, m2, m3, m4, res;
  208. *
  209. * res = glm_mat4_mulN((mat4 *[]){&m1, &m2, &m3, &m4}, 4);
  210. * @endcode
  211. *
  212. * @warning matrices parameter is pointer array not mat4 array!
  213. *
  214. * @param[in] matrices mat4 * array
  215. * @param[in] len matrices count
  216. * @returns result matrix
  217. */
  218. CGLM_INLINE
  219. mat4s
  220. glms_mat4_(mulN)(mat4s * __restrict matrices[], uint32_t len) {
  221. CGLM_ALIGN_MAT mat4s r = GLMS_MAT4_IDENTITY_INIT;
  222. size_t i;
  223. for (i = 0; i < len; i++) {
  224. r = glms_mat4_(mul)(r, *matrices[i]);
  225. }
  226. return r;
  227. }
  228. /*!
  229. * @brief multiply mat4 with vec4 (column vector) and store in dest vector
  230. *
  231. * @param[in] m mat4 (left)
  232. * @param[in] v vec4 (right, column vector)
  233. * @returns vec4 (result, column vector)
  234. */
  235. CGLM_INLINE
  236. vec4s
  237. glms_mat4_(mulv)(mat4s m, vec4s v) {
  238. vec4s r;
  239. glm_mat4_mulv(m.raw, v.raw, r.raw);
  240. return r;
  241. }
  242. /*!
  243. * @brief trace of matrix
  244. *
  245. * sum of the elements on the main diagonal from upper left to the lower right
  246. *
  247. * @param[in] m matrix
  248. */
  249. CGLM_INLINE
  250. float
  251. glms_mat4_(trace)(mat4s m) {
  252. return glm_mat4_trace(m.raw);
  253. }
  254. /*!
  255. * @brief trace of matrix (rotation part)
  256. *
  257. * sum of the elements on the main diagonal from upper left to the lower right
  258. *
  259. * @param[in] m matrix
  260. */
  261. CGLM_INLINE
  262. float
  263. glms_mat4_(trace3)(mat4s m) {
  264. return glm_mat4_trace3(m.raw);
  265. }
  266. /*!
  267. * @brief convert mat4's rotation part to quaternion
  268. *
  269. * @param[in] m affine matrix
  270. * @returns destination quaternion
  271. */
  272. CGLM_INLINE
  273. versors
  274. glms_mat4_(quat)(mat4s m) {
  275. versors r;
  276. glm_mat4_quat(m.raw, r.raw);
  277. return r;
  278. }
  279. /*!
  280. * @brief multiply vector with mat4
  281. *
  282. * @param[in] m mat4(affine transform)
  283. * @param[in] v vec3
  284. * @param[in] last 4th item to make it vec4
  285. * @returns result vector (vec3)
  286. */
  287. CGLM_INLINE
  288. vec3s
  289. glms_mat4_(mulv3)(mat4s m, vec3s v, float last) {
  290. vec3s r;
  291. glm_mat4_mulv3(m.raw, v.raw, last, r.raw);
  292. return r;
  293. }
  294. /*!
  295. * @brief transpose mat4 and store result in same matrix
  296. *
  297. * @param[in] m source
  298. * @returns result
  299. */
  300. CGLM_INLINE
  301. mat4s
  302. glms_mat4_(transpose)(mat4s m) {
  303. glm_mat4_transpose(m.raw);
  304. return m;
  305. }
  306. /*!
  307. * @brief scale (multiply with scalar) matrix without simd optimization
  308. *
  309. * multiply matrix with scalar
  310. *
  311. * @param[in] m matrix
  312. * @param[in] s scalar
  313. * @returns matrix
  314. */
  315. CGLM_INLINE
  316. mat4s
  317. glms_mat4_(scale_p)(mat4s m, float s) {
  318. glm_mat4_scale_p(m.raw, s);
  319. return m;
  320. }
  321. /*!
  322. * @brief scale (multiply with scalar) matrix
  323. *
  324. * multiply matrix with scalar
  325. *
  326. * @param[in] m matrix
  327. * @param[in] s scalar
  328. * @returns matrix
  329. */
  330. CGLM_INLINE
  331. mat4s
  332. glms_mat4_(scale)(mat4s m, float s) {
  333. glm_mat4_scale(m.raw, s);
  334. return m;
  335. }
  336. /*!
  337. * @brief mat4 determinant
  338. *
  339. * @param[in] mat matrix
  340. *
  341. * @return determinant
  342. */
  343. CGLM_INLINE
  344. float
  345. glms_mat4_(det)(mat4s mat) {
  346. return glm_mat4_det(mat.raw);
  347. }
  348. /*!
  349. * @brief inverse mat4 and store in dest
  350. *
  351. * @param[in] mat matrix
  352. * @returns inverse matrix
  353. */
  354. CGLM_INLINE
  355. mat4s
  356. glms_mat4_(inv)(mat4s mat) {
  357. mat4s r;
  358. glm_mat4_inv(mat.raw, r.raw);
  359. return r;
  360. }
  361. /*!
  362. * @brief inverse mat4 and store in dest
  363. *
  364. * this func uses reciprocal approximation without extra corrections
  365. * e.g Newton-Raphson. this should work faster than normal,
  366. * to get more precise use glm_mat4_inv version.
  367. *
  368. * NOTE: You will lose precision, glm_mat4_inv is more accurate
  369. *
  370. * @param[in] mat matrix
  371. * @returns inverse matrix
  372. */
  373. CGLM_INLINE
  374. mat4s
  375. glms_mat4_(inv_fast)(mat4s mat) {
  376. mat4s r;
  377. glm_mat4_inv_fast(mat.raw, r.raw);
  378. return r;
  379. }
  380. /*!
  381. * @brief swap two matrix columns
  382. *
  383. * @param[in] mat matrix
  384. * @param[in] col1 col1
  385. * @param[in] col2 col2
  386. * @returns matrix
  387. */
  388. CGLM_INLINE
  389. mat4s
  390. glms_mat4_(swap_col)(mat4s mat, int col1, int col2) {
  391. glm_mat4_swap_col(mat.raw, col1, col2);
  392. return mat;
  393. }
  394. /*!
  395. * @brief swap two matrix rows
  396. *
  397. * @param[in] mat matrix
  398. * @param[in] row1 row1
  399. * @param[in] row2 row2
  400. * @returns matrix
  401. */
  402. CGLM_INLINE
  403. mat4s
  404. glms_mat4_(swap_row)(mat4s mat, int row1, int row2) {
  405. glm_mat4_swap_row(mat.raw, row1, row2);
  406. return mat;
  407. }
  408. /*!
  409. * @brief helper for R (row vector) * M (matrix) * C (column vector)
  410. *
  411. * rmc stands for Row * Matrix * Column
  412. *
  413. * the result is scalar because R * M = Matrix1x4 (row vector),
  414. * then Matrix1x4 * Vec4 (column vector) = Matrix1x1 (Scalar)
  415. *
  416. * @param[in] r row vector or matrix1x4
  417. * @param[in] m matrix4x4
  418. * @param[in] c column vector or matrix4x1
  419. *
  420. * @return scalar value e.g. B(s)
  421. */
  422. CGLM_INLINE
  423. float
  424. glms_mat4_(rmc)(vec4s r, mat4s m, vec4s c) {
  425. return glm_mat4_rmc(r.raw, m.raw, c.raw);
  426. }
  427. /*!
  428. * @brief Create mat4 matrix from pointer
  429. *
  430. * @param[in] src pointer to an array of floats
  431. * @return constructed matrix from raw pointer
  432. */
  433. CGLM_INLINE
  434. mat4s
  435. glms_mat4_(make)(const float * __restrict src) {
  436. mat4s r;
  437. glm_mat4_make(src, r.raw);
  438. return r;
  439. }
  440. #endif /* cglms_mat4s_h */