1
0

quat.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  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. GLMS_QUAT_IDENTITY_INIT
  10. GLMS_QUAT_IDENTITY
  11. Functions:
  12. CGLM_INLINE versors glms_quat_identity(void)
  13. CGLM_INLINE void glms_quat_identity_array(versor *q, size_t count)
  14. CGLM_INLINE versors glms_quat_init(float x, float y, float z, float w)
  15. CGLM_INLINE versors glms_quatv(float angle, vec3s axis)
  16. CGLM_INLINE versors glms_quat(float angle, float x, float y, float z)
  17. CGLM_INLINE versors glms_quat_from_vecs(vec3s a, vec3s b)
  18. CGLM_INLINE float glms_quat_norm(versors q)
  19. CGLM_INLINE versors glms_quat_normalize(versors q)
  20. CGLM_INLINE float glms_quat_dot(versors p, versors q)
  21. CGLM_INLINE versors glms_quat_conjugate(versors q)
  22. CGLM_INLINE versors glms_quat_inv(versors q)
  23. CGLM_INLINE versors glms_quat_add(versors p, versors q)
  24. CGLM_INLINE versors glms_quat_sub(versors p, versors q)
  25. CGLM_INLINE vec3s glms_quat_imagn(versors q)
  26. CGLM_INLINE float glms_quat_imaglen(versors q)
  27. CGLM_INLINE float glms_quat_angle(versors q)
  28. CGLM_INLINE vec3s glms_quat_axis(versors q)
  29. CGLM_INLINE versors glms_quat_mul(versors p, versors q)
  30. CGLM_INLINE mat4s glms_quat_mat4(versors q)
  31. CGLM_INLINE mat4s glms_quat_mat4t(versors q)
  32. CGLM_INLINE mat3s glms_quat_mat3(versors q)
  33. CGLM_INLINE mat3s glms_quat_mat3t(versors q)
  34. CGLM_INLINE versors glms_quat_lerp(versors from, versors to, float t)
  35. CGLM_INLINE versors glms_quat_lerpc(versors from, versors to, float t)
  36. CGLM_INLINE versors glms_quat_nlerp(versors from, versors to, float t)
  37. CGLM_INLINE versors glms_quat_slerp(versors from, versors to, float t)
  38. CGLM_INLINE versors glms_quat_slerp_longest(versors from, versors to, float t)
  39. CGLM_INLINE mat4s. glms_quat_look(vec3s eye, versors ori)
  40. CGLM_INLINE versors glms_quat_for(vec3s dir, vec3s fwd, vec3s up)
  41. CGLM_INLINE versors glms_quat_forp(vec3s from, vec3s to, vec3s fwd, vec3s up)
  42. CGLM_INLINE vec3s glms_quat_rotatev(versors q, vec3s v)
  43. CGLM_INLINE mat4s glms_quat_rotate(mat4s m, versors q)
  44. CGLM_INLINE mat4s glms_quat_rotate_at(mat4s m, versors q, vec3s pivot)
  45. CGLM_INLINE mat4s glms_quat_rotate_atm(versors q, vec3s pivot)
  46. CGLM_INLINE versors glms_quat_make(float * restrict src)
  47. */
  48. #ifndef cglms_quat_h
  49. #define cglms_quat_h
  50. #include "../common.h"
  51. #include "../types-struct.h"
  52. #include "../plane.h"
  53. #include "../quat.h"
  54. /* api definition */
  55. #define glms_quat_(NAME) CGLM_STRUCTAPI(quat, NAME)
  56. /*
  57. * IMPORTANT:
  58. * ----------------------------------------------------------------------------
  59. * cglm stores quat as [x, y, z, w] since v0.3.6
  60. *
  61. * it was [w, x, y, z] before v0.3.6 it has been changed to [x, y, z, w]
  62. * with v0.3.6 version.
  63. * ----------------------------------------------------------------------------
  64. */
  65. #define GLMS_QUAT_IDENTITY_INIT {GLM_QUAT_IDENTITY_INIT}
  66. #define GLMS_QUAT_IDENTITY ((versors)GLMS_QUAT_IDENTITY_INIT)
  67. /*!
  68. * @brief makes given quat to identity
  69. *
  70. * @returns identity quaternion
  71. */
  72. CGLM_INLINE
  73. versors
  74. glms_quat_(identity)(void) {
  75. versors dest;
  76. glm_quat_identity(dest.raw);
  77. return dest;
  78. }
  79. /*!
  80. * @brief make given quaternion array's each element identity quaternion
  81. *
  82. * @param[in, out] q quat array (must be aligned (16)
  83. * if alignment is not disabled)
  84. *
  85. * @param[in] count count of quaternions
  86. */
  87. CGLM_INLINE
  88. void
  89. glms_quat_(identity_array)(versors * __restrict q, size_t count) {
  90. CGLM_ALIGN(16) versor v = GLM_QUAT_IDENTITY_INIT;
  91. size_t i;
  92. for (i = 0; i < count; i++) {
  93. glm_vec4_copy(v, q[i].raw);
  94. }
  95. }
  96. /*!
  97. * @brief inits quaternion with raw values
  98. *
  99. * @param[in] x x
  100. * @param[in] y y
  101. * @param[in] z z
  102. * @param[in] w w (real part)
  103. * @returns quaternion
  104. */
  105. CGLM_INLINE
  106. versors
  107. glms_quat_(init)(float x, float y, float z, float w) {
  108. versors dest;
  109. glm_quat_init(dest.raw, x, y, z, w);
  110. return dest;
  111. }
  112. /*!
  113. * @brief creates NEW quaternion with axis vector
  114. *
  115. * @param[in] angle angle (radians)
  116. * @param[in] axis axis
  117. * @returns quaternion
  118. */
  119. CGLM_INLINE
  120. versors
  121. glms_quatv(float angle, vec3s axis) {
  122. versors dest;
  123. glm_quatv(dest.raw, angle, axis.raw);
  124. return dest;
  125. }
  126. /*!
  127. * @brief creates NEW quaternion with individual axis components
  128. *
  129. * @param[in] angle angle (radians)
  130. * @param[in] x axis.x
  131. * @param[in] y axis.y
  132. * @param[in] z axis.z
  133. * @returns quaternion
  134. */
  135. CGLM_INLINE
  136. versors
  137. glms_quat(float angle, float x, float y, float z) {
  138. versors dest;
  139. glm_quat(dest.raw, angle, x, y, z);
  140. return dest;
  141. }
  142. /*!
  143. * @brief compute quaternion rotating vector A to vector B
  144. *
  145. * @param[in] a vec3 (must have unit length)
  146. * @param[in] b vec3 (must have unit length)
  147. * @returns quaternion (of unit length)
  148. */
  149. CGLM_INLINE
  150. versors
  151. glms_quat_(from_vecs)(vec3s a, vec3s b) {
  152. versors dest;
  153. glm_quat_from_vecs(a.raw, b.raw, dest.raw);
  154. return dest;
  155. }
  156. /*!
  157. * @brief returns norm (magnitude) of quaternion
  158. *
  159. * @param[in] q quaternion
  160. */
  161. CGLM_INLINE
  162. float
  163. glms_quat_(norm)(versors q) {
  164. return glm_quat_norm(q.raw);
  165. }
  166. /*!
  167. * @brief normalize quaternion
  168. *
  169. * @param[in] q quaternion
  170. * @returns quaternion
  171. */
  172. CGLM_INLINE
  173. versors
  174. glms_quat_(normalize)(versors q) {
  175. versors dest;
  176. glm_quat_normalize_to(q.raw, dest.raw);
  177. return dest;
  178. }
  179. /*!
  180. * @brief dot product of two quaternion
  181. *
  182. * @param[in] p quaternion 1
  183. * @param[in] q quaternion 2
  184. * @returns dot product
  185. */
  186. CGLM_INLINE
  187. float
  188. glms_quat_(dot)(versors p, versors q) {
  189. return glm_quat_dot(p.raw, q.raw);
  190. }
  191. /*!
  192. * @brief conjugate of quaternion
  193. *
  194. * @param[in] q quaternion
  195. * @returns conjugate
  196. */
  197. CGLM_INLINE
  198. versors
  199. glms_quat_(conjugate)(versors q) {
  200. versors dest;
  201. glm_quat_conjugate(q.raw, dest.raw);
  202. return dest;
  203. }
  204. /*!
  205. * @brief inverse of non-zero quaternion
  206. *
  207. * @param[in] q quaternion
  208. * @returns inverse quaternion
  209. */
  210. CGLM_INLINE
  211. versors
  212. glms_quat_(inv)(versors q) {
  213. versors dest;
  214. glm_quat_inv(q.raw, dest.raw);
  215. return dest;
  216. }
  217. /*!
  218. * @brief add (componentwise) two quaternions and store result in dest
  219. *
  220. * @param[in] p quaternion 1
  221. * @param[in] q quaternion 2
  222. * @returns result quaternion
  223. */
  224. CGLM_INLINE
  225. versors
  226. glms_quat_(add)(versors p, versors q) {
  227. versors dest;
  228. glm_quat_add(p.raw, q.raw, dest.raw);
  229. return dest;
  230. }
  231. /*!
  232. * @brief subtract (componentwise) two quaternions and store result in dest
  233. *
  234. * @param[in] p quaternion 1
  235. * @param[in] q quaternion 2
  236. * @returns result quaternion
  237. */
  238. CGLM_INLINE
  239. versors
  240. glms_quat_(sub)(versors p, versors q) {
  241. versors dest;
  242. glm_quat_sub(p.raw, q.raw, dest.raw);
  243. return dest;
  244. }
  245. /*!
  246. * @brief returns normalized imaginary part of quaternion
  247. *
  248. * @param[in] q quaternion
  249. */
  250. CGLM_INLINE
  251. vec3s
  252. glms_quat_(imagn)(versors q) {
  253. vec3s dest;
  254. glm_normalize_to(q.raw, dest.raw);
  255. return dest;
  256. }
  257. /*!
  258. * @brief returns length of imaginary part of quaternion
  259. *
  260. * @param[in] q quaternion
  261. */
  262. CGLM_INLINE
  263. float
  264. glms_quat_(imaglen)(versors q) {
  265. return glm_quat_imaglen(q.raw);
  266. }
  267. /*!
  268. * @brief returns angle of quaternion
  269. *
  270. * @param[in] q quaternion
  271. */
  272. CGLM_INLINE
  273. float
  274. glms_quat_(angle)(versors q) {
  275. return glm_quat_angle(q.raw);
  276. }
  277. /*!
  278. * @brief axis of quaternion
  279. *
  280. * @param[in] q quaternion
  281. * @returns axis of quaternion
  282. */
  283. CGLM_INLINE
  284. vec3s
  285. glms_quat_(axis)(versors q) {
  286. vec3s dest;
  287. glm_quat_axis(q.raw, dest.raw);
  288. return dest;
  289. }
  290. /*!
  291. * @brief multiplies two quaternion and stores result in dest
  292. * this is also called Hamilton Product
  293. *
  294. * According to WikiPedia:
  295. * The product of two rotation quaternions [clarification needed] will be
  296. * equivalent to the rotation q followed by the rotation p
  297. *
  298. * @param[in] p quaternion 1
  299. * @param[in] q quaternion 2
  300. * @returns result quaternion
  301. */
  302. CGLM_INLINE
  303. versors
  304. glms_quat_(mul)(versors p, versors q) {
  305. versors dest;
  306. glm_quat_mul(p.raw, q.raw, dest.raw);
  307. return dest;
  308. }
  309. /*!
  310. * @brief convert quaternion to mat4
  311. *
  312. * @param[in] q quaternion
  313. * @returns result matrix
  314. */
  315. CGLM_INLINE
  316. mat4s
  317. glms_quat_(mat4)(versors q) {
  318. mat4s dest;
  319. glm_quat_mat4(q.raw, dest.raw);
  320. return dest;
  321. }
  322. /*!
  323. * @brief convert quaternion to mat4 (transposed)
  324. *
  325. * @param[in] q quaternion
  326. * @returns result matrix as transposed
  327. */
  328. CGLM_INLINE
  329. mat4s
  330. glms_quat_(mat4t)(versors q) {
  331. mat4s dest;
  332. glm_quat_mat4t(q.raw, dest.raw);
  333. return dest;
  334. }
  335. /*!
  336. * @brief convert quaternion to mat3
  337. *
  338. * @param[in] q quaternion
  339. * @returns result matrix
  340. */
  341. CGLM_INLINE
  342. mat3s
  343. glms_quat_(mat3)(versors q) {
  344. mat3s dest;
  345. glm_quat_mat3(q.raw, dest.raw);
  346. return dest;
  347. }
  348. /*!
  349. * @brief convert quaternion to mat3 (transposed)
  350. *
  351. * @param[in] q quaternion
  352. * @returns result matrix
  353. */
  354. CGLM_INLINE
  355. mat3s
  356. glms_quat_(mat3t)(versors q) {
  357. mat3s dest;
  358. glm_quat_mat3t(q.raw, dest.raw);
  359. return dest;
  360. }
  361. /*!
  362. * @brief interpolates between two quaternions
  363. * using linear interpolation (LERP)
  364. *
  365. * @param[in] from from
  366. * @param[in] to to
  367. * @param[in] t interpolant (amount)
  368. * @returns result quaternion
  369. */
  370. CGLM_INLINE
  371. versors
  372. glms_quat_(lerp)(versors from, versors to, float t) {
  373. versors dest;
  374. glm_quat_lerp(from.raw, to.raw, t, dest.raw);
  375. return dest;
  376. }
  377. /*!
  378. * @brief interpolates between two quaternions
  379. * using linear interpolation (LERP)
  380. *
  381. * @param[in] from from
  382. * @param[in] to to
  383. * @param[in] t interpolant (amount) clamped between 0 and 1
  384. * @returns result quaternion
  385. */
  386. CGLM_INLINE
  387. versors
  388. glms_quat_(lerpc)(versors from, versors to, float t) {
  389. versors dest;
  390. glm_quat_lerpc(from.raw, to.raw, t, dest.raw);
  391. return dest;
  392. }
  393. /*!
  394. * @brief interpolates between two quaternions
  395. * taking the shortest rotation path using
  396. * normalized linear interpolation (NLERP)
  397. *
  398. * @param[in] from from
  399. * @param[in] to to
  400. * @param[in] t interpolant (amount)
  401. * @returns result quaternion
  402. */
  403. CGLM_INLINE
  404. versors
  405. glms_quat_(nlerp)(versors from, versors to, float t) {
  406. versors dest;
  407. glm_quat_nlerp(from.raw, to.raw, t, dest.raw);
  408. return dest;
  409. }
  410. /*!
  411. * @brief interpolates between two quaternions
  412. * using spherical linear interpolation (SLERP)
  413. *
  414. * @param[in] from from
  415. * @param[in] to to
  416. * @param[in] t amount
  417. * @returns result quaternion
  418. */
  419. CGLM_INLINE
  420. versors
  421. glms_quat_(slerp)(versors from, versors to, float t) {
  422. versors dest;
  423. glm_quat_slerp(from.raw, to.raw, t, dest.raw);
  424. return dest;
  425. }
  426. /*!
  427. * @brief interpolates between two quaternions
  428. * using spherical linear interpolation (SLERP) and always takes the longest path
  429. *
  430. * @param[in] from from
  431. * @param[in] to to
  432. * @param[in] t amount
  433. * @returns result quaternion
  434. */
  435. CGLM_INLINE
  436. versors
  437. glms_quat_(slerp_longest)(versors from, versors to, float t) {
  438. versors dest;
  439. glm_quat_slerp_longest(from.raw, to.raw, t, dest.raw);
  440. return dest;
  441. }
  442. /*!
  443. * @brief creates view matrix using quaternion as camera orientation
  444. *
  445. * @param[in] eye eye
  446. * @param[in] ori orientation in world space as quaternion
  447. * @returns view matrix
  448. */
  449. CGLM_INLINE
  450. mat4s
  451. glms_quat_(look)(vec3s eye, versors ori) {
  452. mat4s dest;
  453. glm_quat_look(eye.raw, ori.raw, dest.raw);
  454. return dest;
  455. }
  456. /*!
  457. * @brief creates look rotation quaternion
  458. *
  459. * @param[in] dir direction to look
  460. * @param[in] up up vector
  461. * @returns destination quaternion
  462. */
  463. CGLM_INLINE
  464. versors
  465. glms_quat_(for)(vec3s dir, vec3s up) {
  466. versors dest;
  467. glm_quat_for(dir.raw, up.raw, dest.raw);
  468. return dest;
  469. }
  470. /*!
  471. * @brief creates look rotation quaternion using source and
  472. * destination positions p suffix stands for position
  473. *
  474. * @param[in] from source point
  475. * @param[in] to destination point
  476. * @param[in] up up vector
  477. * @returns destination quaternion
  478. */
  479. CGLM_INLINE
  480. versors
  481. glms_quat_(forp)(vec3s from, vec3s to, vec3s up) {
  482. versors dest;
  483. glm_quat_forp(from.raw, to.raw, up.raw, dest.raw);
  484. return dest;
  485. }
  486. /*!
  487. * @brief rotate vector using using quaternion
  488. *
  489. * @param[in] q quaternion
  490. * @param[in] v vector to rotate
  491. * @returns rotated vector
  492. */
  493. CGLM_INLINE
  494. vec3s
  495. glms_quat_(rotatev)(versors q, vec3s v) {
  496. vec3s dest;
  497. glm_quat_rotatev(q.raw, v.raw, dest.raw);
  498. return dest;
  499. }
  500. /*!
  501. * @brief rotate existing transform matrix using quaternion
  502. *
  503. * @param[in] m existing transform matrix
  504. * @param[in] q quaternion
  505. * @returns rotated matrix/transform
  506. */
  507. CGLM_INLINE
  508. mat4s
  509. glms_quat_(rotate)(mat4s m, versors q) {
  510. glm_quat_rotate(m.raw, q.raw, m.raw);
  511. return m;
  512. }
  513. /*!
  514. * @brief rotate existing transform matrix using quaternion at pivot point
  515. *
  516. * @param[in, out] m existing transform matrix
  517. * @param[in] q quaternion
  518. * @returns pivot
  519. */
  520. CGLM_INLINE
  521. mat4s
  522. glms_quat_(rotate_at)(mat4s m, versors q, vec3s pivot) {
  523. glm_quat_rotate_at(m.raw, q.raw, pivot.raw);
  524. return m;
  525. }
  526. /*!
  527. * @brief rotate NEW transform matrix using quaternion at pivot point
  528. *
  529. * this creates rotation matrix, it assumes you don't have a matrix
  530. *
  531. * this should work faster than glm_quat_rotate_at because it reduces
  532. * one glm_translate.
  533. *
  534. * @param[in] q quaternion
  535. * @returns pivot
  536. */
  537. CGLM_INLINE
  538. mat4s
  539. glms_quat_(rotate_atm)(versors q, vec3s pivot) {
  540. mat4s dest;
  541. glm_quat_rotate_atm(dest.raw, q.raw, pivot.raw);
  542. return dest;
  543. }
  544. /*!
  545. * @brief Create CGLM quaternion from pointer
  546. *
  547. * @param[in] src pointer to an array of floats
  548. * @returns constructed quaternion from raw pointer
  549. */
  550. CGLM_INLINE
  551. versors
  552. glms_quat_(make)(const float * __restrict src) {
  553. versors dest;
  554. glm_quat_make(src, dest.raw);
  555. return dest;
  556. }
  557. #endif /* cglms_quat_h */