1
0

affine-pre.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  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. #ifndef cglm_affine_pre_h
  8. #define cglm_affine_pre_h
  9. /*
  10. Functions:
  11. CGLM_INLINE void glm_translate_to(mat4 m, vec3 v, mat4 dest);
  12. CGLM_INLINE void glm_translate(mat4 m, vec3 v);
  13. CGLM_INLINE void glm_translate_x(mat4 m, float to);
  14. CGLM_INLINE void glm_translate_y(mat4 m, float to);
  15. CGLM_INLINE void glm_translate_z(mat4 m, float to);
  16. CGLM_INLINE void glm_rotate_x(mat4 m, float angle, mat4 dest);
  17. CGLM_INLINE void glm_rotate_y(mat4 m, float angle, mat4 dest);
  18. CGLM_INLINE void glm_rotate_z(mat4 m, float angle, mat4 dest);
  19. CGLM_INLINE void glm_rotate(mat4 m, float angle, vec3 axis);
  20. CGLM_INLINE void glm_rotate_at(mat4 m, vec3 pivot, float angle, vec3 axis);
  21. CGLM_INLINE void glm_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis);
  22. CGLM_INLINE void glm_spin(mat4 m, float angle, vec3 axis);
  23. */
  24. #include "common.h"
  25. #include "util.h"
  26. #include "vec3.h"
  27. #include "vec4.h"
  28. #include "mat4.h"
  29. #include "affine-mat.h"
  30. /*!
  31. * @brief translate existing transform matrix by v vector
  32. * and stores result in same matrix
  33. *
  34. * @param[in, out] m affine transform
  35. * @param[in] v translate vector [x, y, z]
  36. */
  37. CGLM_INLINE
  38. void
  39. glm_translate(mat4 m, vec3 v) {
  40. #if defined(CGLM_SIMD)
  41. glmm_128 m0, m1, m2, m3;
  42. m0 = glmm_load(m[0]);
  43. m1 = glmm_load(m[1]);
  44. m2 = glmm_load(m[2]);
  45. m3 = glmm_load(m[3]);
  46. glmm_store(m[3],
  47. glmm_fmadd(m0, glmm_set1(v[0]),
  48. glmm_fmadd(m1, glmm_set1(v[1]),
  49. glmm_fmadd(m2, glmm_set1(v[2]), m3))));
  50. #else
  51. glm_vec4_muladds(m[0], v[0], m[3]);
  52. glm_vec4_muladds(m[1], v[1], m[3]);
  53. glm_vec4_muladds(m[2], v[2], m[3]);
  54. #endif
  55. }
  56. /*!
  57. * @brief translate existing transform matrix by v vector
  58. * and store result in dest
  59. *
  60. * source matrix will remain same
  61. *
  62. * @param[in] m affine transform
  63. * @param[in] v translate vector [x, y, z]
  64. * @param[out] dest translated matrix
  65. */
  66. CGLM_INLINE
  67. void
  68. glm_translate_to(mat4 m, vec3 v, mat4 dest) {
  69. glm_mat4_copy(m, dest);
  70. glm_translate(dest, v);
  71. }
  72. /*!
  73. * @brief translate existing transform matrix by x factor
  74. *
  75. * @param[in, out] m affine transform
  76. * @param[in] x x factor
  77. */
  78. CGLM_INLINE
  79. void
  80. glm_translate_x(mat4 m, float x) {
  81. #if defined(CGLM_SIMD)
  82. glmm_store(m[3], glmm_fmadd(glmm_load(m[0]), glmm_set1(x), glmm_load(m[3])));
  83. #else
  84. vec4 v1;
  85. glm_vec4_scale(m[0], x, v1);
  86. glm_vec4_add(v1, m[3], m[3]);
  87. #endif
  88. }
  89. /*!
  90. * @brief translate existing transform matrix by y factor
  91. *
  92. * @param[in, out] m affine transform
  93. * @param[in] y y factor
  94. */
  95. CGLM_INLINE
  96. void
  97. glm_translate_y(mat4 m, float y) {
  98. #if defined(CGLM_SIMD)
  99. glmm_store(m[3], glmm_fmadd(glmm_load(m[1]), glmm_set1(y), glmm_load(m[3])));
  100. #else
  101. vec4 v1;
  102. glm_vec4_scale(m[1], y, v1);
  103. glm_vec4_add(v1, m[3], m[3]);
  104. #endif
  105. }
  106. /*!
  107. * @brief translate existing transform matrix by z factor
  108. *
  109. * @param[in, out] m affine transform
  110. * @param[in] z z factor
  111. */
  112. CGLM_INLINE
  113. void
  114. glm_translate_z(mat4 m, float z) {
  115. #if defined(CGLM_SIMD)
  116. glmm_store(m[3], glmm_fmadd(glmm_load(m[2]), glmm_set1(z), glmm_load(m[3])));
  117. #else
  118. vec4 v1;
  119. glm_vec4_scale(m[2], z, v1);
  120. glm_vec4_add(v1, m[3], m[3]);
  121. #endif
  122. }
  123. /*!
  124. * @brief rotate existing transform matrix around X axis by angle
  125. * and store result in dest
  126. *
  127. * @param[in] m affine transform
  128. * @param[in] angle angle (radians)
  129. * @param[out] dest rotated matrix
  130. */
  131. CGLM_INLINE
  132. void
  133. glm_rotate_x(mat4 m, float angle, mat4 dest) {
  134. CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT;
  135. float c, s;
  136. c = cosf(angle);
  137. s = sinf(angle);
  138. t[1][1] = c;
  139. t[1][2] = s;
  140. t[2][1] = -s;
  141. t[2][2] = c;
  142. glm_mul_rot(m, t, dest);
  143. }
  144. /*!
  145. * @brief rotate existing transform matrix around Y axis by angle
  146. * and store result in dest
  147. *
  148. * @param[in] m affine transform
  149. * @param[in] angle angle (radians)
  150. * @param[out] dest rotated matrix
  151. */
  152. CGLM_INLINE
  153. void
  154. glm_rotate_y(mat4 m, float angle, mat4 dest) {
  155. CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT;
  156. float c, s;
  157. c = cosf(angle);
  158. s = sinf(angle);
  159. t[0][0] = c;
  160. t[0][2] = -s;
  161. t[2][0] = s;
  162. t[2][2] = c;
  163. glm_mul_rot(m, t, dest);
  164. }
  165. /*!
  166. * @brief rotate existing transform matrix around Z axis by angle
  167. * and store result in dest
  168. *
  169. * @param[in] m affine transform
  170. * @param[in] angle angle (radians)
  171. * @param[out] dest rotated matrix
  172. */
  173. CGLM_INLINE
  174. void
  175. glm_rotate_z(mat4 m, float angle, mat4 dest) {
  176. CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT;
  177. float c, s;
  178. c = cosf(angle);
  179. s = sinf(angle);
  180. t[0][0] = c;
  181. t[0][1] = s;
  182. t[1][0] = -s;
  183. t[1][1] = c;
  184. glm_mul_rot(m, t, dest);
  185. }
  186. /*!
  187. * @brief rotate existing transform matrix
  188. * around given axis by angle at ORIGIN (0,0,0)
  189. *
  190. * **❗️IMPORTANT ❗️**
  191. *
  192. * If you need to rotate object around itself e.g. center of object or at
  193. * some point [of object] then `glm_rotate_at()` would be better choice to do so.
  194. *
  195. * Even if object's model transform is identity, rotation may not be around
  196. * center of object if object does not lay out at ORIGIN perfectly.
  197. *
  198. * Using `glm_rotate_at()` with center of bounding shape ( AABB, Sphere ... )
  199. * would be an easy option to rotate around object if object is not at origin.
  200. *
  201. * One another option to rotate around itself at any point is `glm_spin()`
  202. * which is perfect if only rotating around model position is desired e.g. not
  203. * specific point on model for instance center of geometry or center of mass,
  204. * again if geometry is not perfectly centered at origin at identity transform,
  205. * rotation may not be around geometry.
  206. *
  207. * @param[in, out] m affine transform
  208. * @param[in] angle angle (radians)
  209. * @param[in] axis axis
  210. */
  211. CGLM_INLINE
  212. void
  213. glm_rotate(mat4 m, float angle, vec3 axis) {
  214. CGLM_ALIGN_MAT mat4 rot;
  215. glm_rotate_make(rot, angle, axis);
  216. glm_mul_rot(m, rot, m);
  217. }
  218. /*!
  219. * @brief rotate existing transform
  220. * around given axis by angle at given pivot point (rotation center)
  221. *
  222. * @param[in, out] m affine transform
  223. * @param[in] pivot rotation center
  224. * @param[in] angle angle (radians)
  225. * @param[in] axis axis
  226. */
  227. CGLM_INLINE
  228. void
  229. glm_rotate_at(mat4 m, vec3 pivot, float angle, vec3 axis) {
  230. CGLM_ALIGN(8) vec3 pivotInv;
  231. glm_vec3_negate_to(pivot, pivotInv);
  232. glm_translate(m, pivot);
  233. glm_rotate(m, angle, axis);
  234. glm_translate(m, pivotInv);
  235. }
  236. /*!
  237. * @brief creates NEW rotation matrix by angle and axis at given point
  238. *
  239. * this creates rotation matrix, it assumes you don't have a matrix
  240. *
  241. * this should work faster than glm_rotate_at because it reduces
  242. * one glm_translate.
  243. *
  244. * @param[out] m affine transform
  245. * @param[in] pivot rotation center
  246. * @param[in] angle angle (radians)
  247. * @param[in] axis axis
  248. */
  249. CGLM_INLINE
  250. void
  251. glm_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis) {
  252. CGLM_ALIGN(8) vec3 pivotInv;
  253. glm_vec3_negate_to(pivot, pivotInv);
  254. glm_translate_make(m, pivot);
  255. glm_rotate(m, angle, axis);
  256. glm_translate(m, pivotInv);
  257. }
  258. /*!
  259. * @brief rotate existing transform matrix
  260. * around given axis by angle around self (doesn't affected by position)
  261. *
  262. * @param[in, out] m affine transform
  263. * @param[in] angle angle (radians)
  264. * @param[in] axis axis
  265. */
  266. CGLM_INLINE
  267. void
  268. glm_spin(mat4 m, float angle, vec3 axis) {
  269. CGLM_ALIGN_MAT mat4 rot;
  270. glm_rotate_atm(rot, m[3], angle, axis);
  271. glm_mat4_mul(m, rot, m);
  272. }
  273. #endif /* cglm_affine_pre_h */