1
0

affine.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  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. Functions:
  9. CGLM_INLINE void glm_translate_to(mat4 m, vec3 v, mat4 dest);
  10. CGLM_INLINE void glm_translate(mat4 m, vec3 v);
  11. CGLM_INLINE void glm_translate_x(mat4 m, float to);
  12. CGLM_INLINE void glm_translate_y(mat4 m, float to);
  13. CGLM_INLINE void glm_translate_z(mat4 m, float to);
  14. CGLM_INLINE void glm_translate_make(mat4 m, vec3 v);
  15. CGLM_INLINE void glm_scale_to(mat4 m, vec3 v, mat4 dest);
  16. CGLM_INLINE void glm_scale_make(mat4 m, vec3 v);
  17. CGLM_INLINE void glm_scale(mat4 m, vec3 v);
  18. CGLM_INLINE void glm_scale_uni(mat4 m, float s);
  19. CGLM_INLINE void glm_rotate_x(mat4 m, float angle, mat4 dest);
  20. CGLM_INLINE void glm_rotate_y(mat4 m, float angle, mat4 dest);
  21. CGLM_INLINE void glm_rotate_z(mat4 m, float angle, mat4 dest);
  22. CGLM_INLINE void glm_rotate_make(mat4 m, float angle, vec3 axis);
  23. CGLM_INLINE void glm_rotate(mat4 m, float angle, vec3 axis);
  24. CGLM_INLINE void glm_rotate_at(mat4 m, vec3 pivot, float angle, vec3 axis);
  25. CGLM_INLINE void glm_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis);
  26. CGLM_INLINE void glm_spin(mat4 m, float angle, vec3 axis);
  27. CGLM_INLINE void glm_decompose_scalev(mat4 m, vec3 s);
  28. CGLM_INLINE bool glm_uniscaled(mat4 m);
  29. CGLM_INLINE void glm_decompose_rs(mat4 m, mat4 r, vec3 s);
  30. CGLM_INLINE void glm_decompose(mat4 m, vec4 t, mat4 r, vec3 s);
  31. */
  32. #ifndef cglm_affine_h
  33. #define cglm_affine_h
  34. #include "common.h"
  35. #include "util.h"
  36. #include "vec3.h"
  37. #include "vec4.h"
  38. #include "mat4.h"
  39. #include "affine-mat.h"
  40. /*!
  41. * @brief creates NEW translate transform matrix by v vector
  42. *
  43. * @param[out] m affine transform
  44. * @param[in] v translate vector [x, y, z]
  45. */
  46. CGLM_INLINE
  47. void
  48. glm_translate_make(mat4 m, vec3 v) {
  49. glm_mat4_identity(m);
  50. glm_vec3_copy(v, m[3]);
  51. }
  52. /*!
  53. * @brief scale existing transform matrix by v vector
  54. * and store result in dest
  55. *
  56. * @param[in] m affine transform
  57. * @param[in] v scale vector [x, y, z]
  58. * @param[out] dest scaled matrix
  59. */
  60. CGLM_INLINE
  61. void
  62. glm_scale_to(mat4 m, vec3 v, mat4 dest) {
  63. glm_vec4_scale(m[0], v[0], dest[0]);
  64. glm_vec4_scale(m[1], v[1], dest[1]);
  65. glm_vec4_scale(m[2], v[2], dest[2]);
  66. glm_vec4_copy(m[3], dest[3]);
  67. }
  68. /*!
  69. * @brief creates NEW scale matrix by v vector
  70. *
  71. * @param[out] m affine transform
  72. * @param[in] v scale vector [x, y, z]
  73. */
  74. CGLM_INLINE
  75. void
  76. glm_scale_make(mat4 m, vec3 v) {
  77. glm_mat4_identity(m);
  78. m[0][0] = v[0];
  79. m[1][1] = v[1];
  80. m[2][2] = v[2];
  81. }
  82. /*!
  83. * @brief scales existing transform matrix by v vector
  84. * and stores result in same matrix
  85. *
  86. * @param[in, out] m affine transform
  87. * @param[in] v scale vector [x, y, z]
  88. */
  89. CGLM_INLINE
  90. void
  91. glm_scale(mat4 m, vec3 v) {
  92. glm_scale_to(m, v, m);
  93. }
  94. /*!
  95. * @brief applies uniform scale to existing transform matrix v = [s, s, s]
  96. * and stores result in same matrix
  97. *
  98. * @param[in, out] m affine transform
  99. * @param[in] s scale factor
  100. */
  101. CGLM_INLINE
  102. void
  103. glm_scale_uni(mat4 m, float s) {
  104. CGLM_ALIGN(8) vec3 v = { s, s, s };
  105. glm_scale_to(m, v, m);
  106. }
  107. /*!
  108. * @brief creates NEW rotation matrix by angle and axis
  109. *
  110. * axis will be normalized so you don't need to normalize it
  111. *
  112. * @param[out] m affine transform
  113. * @param[in] angle angle (radians)
  114. * @param[in] axis axis
  115. */
  116. CGLM_INLINE
  117. void
  118. glm_rotate_make(mat4 m, float angle, vec3 axis) {
  119. CGLM_ALIGN(8) vec3 axisn, v, vs;
  120. float c;
  121. c = cosf(angle);
  122. glm_vec3_normalize_to(axis, axisn);
  123. glm_vec3_scale(axisn, 1.0f - c, v);
  124. glm_vec3_scale(axisn, sinf(angle), vs);
  125. glm_vec3_scale(axisn, v[0], m[0]);
  126. glm_vec3_scale(axisn, v[1], m[1]);
  127. glm_vec3_scale(axisn, v[2], m[2]);
  128. m[0][0] += c; m[1][0] -= vs[2]; m[2][0] += vs[1];
  129. m[0][1] += vs[2]; m[1][1] += c; m[2][1] -= vs[0];
  130. m[0][2] -= vs[1]; m[1][2] += vs[0]; m[2][2] += c;
  131. m[0][3] = m[1][3] = m[2][3] = m[3][0] = m[3][1] = m[3][2] = 0.0f;
  132. m[3][3] = 1.0f;
  133. }
  134. /*!
  135. * @brief decompose scale vector
  136. *
  137. * @param[in] m affine transform
  138. * @param[out] s scale vector (Sx, Sy, Sz)
  139. */
  140. CGLM_INLINE
  141. void
  142. glm_decompose_scalev(mat4 m, vec3 s) {
  143. s[0] = glm_vec3_norm(m[0]);
  144. s[1] = glm_vec3_norm(m[1]);
  145. s[2] = glm_vec3_norm(m[2]);
  146. }
  147. /*!
  148. * @brief returns true if matrix is uniform scaled. This is helpful for
  149. * creating normal matrix.
  150. *
  151. * @param[in] m m
  152. *
  153. * @return boolean
  154. */
  155. CGLM_INLINE
  156. bool
  157. glm_uniscaled(mat4 m) {
  158. CGLM_ALIGN(8) vec3 s;
  159. glm_decompose_scalev(m, s);
  160. return glm_vec3_eq_all(s);
  161. }
  162. /*!
  163. * @brief decompose rotation matrix (mat4) and scale vector [Sx, Sy, Sz]
  164. * DON'T pass projected matrix here
  165. *
  166. * @param[in] m affine transform
  167. * @param[out] r rotation matrix
  168. * @param[out] s scale matrix
  169. */
  170. CGLM_INLINE
  171. void
  172. glm_decompose_rs(mat4 m, mat4 r, vec3 s) {
  173. CGLM_ALIGN(16) vec4 t = {0.0f, 0.0f, 0.0f, 1.0f};
  174. CGLM_ALIGN(8) vec3 v;
  175. glm_vec4_copy(m[0], r[0]);
  176. glm_vec4_copy(m[1], r[1]);
  177. glm_vec4_copy(m[2], r[2]);
  178. glm_vec4_copy(t, r[3]);
  179. s[0] = glm_vec3_norm(m[0]);
  180. s[1] = glm_vec3_norm(m[1]);
  181. s[2] = glm_vec3_norm(m[2]);
  182. glm_vec4_scale(r[0], 1.0f/s[0], r[0]);
  183. glm_vec4_scale(r[1], 1.0f/s[1], r[1]);
  184. glm_vec4_scale(r[2], 1.0f/s[2], r[2]);
  185. /* Note from Apple Open Source (assume that the matrix is orthonormal):
  186. check for a coordinate system flip. If the determinant
  187. is -1, then negate the matrix and the scaling factors. */
  188. glm_vec3_cross(m[0], m[1], v);
  189. if (glm_vec3_dot(v, m[2]) < 0.0f) {
  190. glm_vec4_negate(r[0]);
  191. glm_vec4_negate(r[1]);
  192. glm_vec4_negate(r[2]);
  193. glm_vec3_negate(s);
  194. }
  195. }
  196. /*!
  197. * @brief decompose affine transform, TODO: extract shear factors.
  198. * DON'T pass projected matrix here
  199. *
  200. * @param[in] m affine transform
  201. * @param[out] t translation vector
  202. * @param[out] r rotation matrix (mat4)
  203. * @param[out] s scaling vector [X, Y, Z]
  204. */
  205. CGLM_INLINE
  206. void
  207. glm_decompose(mat4 m, vec4 t, mat4 r, vec3 s) {
  208. glm_vec4_copy(m[3], t);
  209. glm_decompose_rs(m, r, s);
  210. }
  211. #include "affine-pre.h"
  212. #include "affine-post.h"
  213. #endif /* cglm_affine_h */