Skip to content

Commit

Permalink
Merge pull request #416 from telephone001/quat_slerp_longest
Browse files Browse the repository at this point in the history
added quat_slerp_longest
  • Loading branch information
recp committed May 13, 2024
2 parents eb3a51e + c5b2afc commit a93a9ef
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 0 deletions.
12 changes: 12 additions & 0 deletions docs/source/quat.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Functions:
#. :c:func:`glm_quat_lerp`
#. :c:func:`glm_quat_nlerp`
#. :c:func:`glm_quat_slerp`
#. :c:func:`glm_quat_slerp_longest`
#. :c:func:`glm_quat_look`
#. :c:func:`glm_quat_for`
#. :c:func:`glm_quat_forp`
Expand Down Expand Up @@ -351,6 +352,17 @@ Functions documentation
| *[in]* **t** interpolant (amount) clamped between 0 and 1
| *[out]* **dest** result quaternion
.. c:function:: void glm_quat_slerp_longest(versor q, versor r, float t, versor dest)
| interpolates between two quaternions
| using spherical linear interpolation (SLERP) and always takes the longest path
Parameters:
| *[in]* **from** from
| *[in]* **to** to
| *[in]* **t** interpolant (amount) clamped between 0 and 1
| *[out]* **dest** result quaternion
.. c:function:: void glm_quat_look(vec3 eye, versor ori, mat4 dest)
| creates view matrix using quaternion as camera orientation
Expand Down
4 changes: 4 additions & 0 deletions include/cglm/call/quat.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ CGLM_EXPORT
void
glmc_quat_slerp(versor q, versor r, float t, versor dest);

CGLM_EXPORT
void
glmc_quat_slerp_longest(versor q, versor r, float t, versor dest);

CGLM_EXPORT
void
glmc_quat_look(vec3 eye, versor ori, mat4 dest);
Expand Down
47 changes: 47 additions & 0 deletions include/cglm/quat.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
CGLM_INLINE void glm_quat_lerp(versor from, versor to, float t, versor dest);
CGLM_INLINE void glm_quat_lerpc(versor from, versor to, float t, versor dest);
CGLM_INLINE void glm_quat_slerp(versor q, versor r, float t, versor dest);
CGLM_INLINE void glm_quat_slerp_longest(versor q, versor r, float t, versor dest);
CGLM_INLINE void glm_quat_nlerp(versor q, versor r, float t, versor dest);
CGLM_INLINE void glm_quat_look(vec3 eye, versor ori, mat4 dest);
CGLM_INLINE void glm_quat_for(vec3 dir, vec3 fwd, vec3 up, versor dest);
Expand Down Expand Up @@ -742,6 +743,52 @@ glm_quat_slerp(versor from, versor to, float t, versor dest) {
glm_vec4_scale(q1, 1.0f / sinTheta, dest);
}

/*!
* @brief interpolates between two quaternions
* using spherical linear interpolation (SLERP) and always takes the long path
*
* @param[in] from from
* @param[in] to to
* @param[in] t amout
* @param[out] dest result quaternion
*/
CGLM_INLINE
void
glm_quat_slerp_longest(versor from, versor to, float t, versor dest) {
CGLM_ALIGN(16) vec4 q1, q2;
float cosTheta, sinTheta, angle;

cosTheta = glm_quat_dot(from, to);
glm_quat_copy(from, q1);

if (fabsf(cosTheta) >= 1.0f) {
glm_quat_copy(q1, dest);
return;
}

/* longest path */
if (!(cosTheta < 0.0f)) {
glm_vec4_negate(q1);
cosTheta = -cosTheta;
}

sinTheta = sqrtf(1.0f - cosTheta * cosTheta);

/* LERP to avoid zero division */
if (fabsf(sinTheta) < 0.001f) {
glm_quat_lerp(from, to, t, dest);
return;
}

/* SLERP */
angle = acosf(cosTheta);
glm_vec4_scale(q1, sinf((1.0f - t) * angle), q1);
glm_vec4_scale(to, sinf(t * angle), q2);

glm_vec4_add(q1, q2, q1);
glm_vec4_scale(q1, 1.0f / sinTheta, dest);
}

/*!
* @brief creates view matrix using quaternion as camera orientation
*
Expand Down
18 changes: 18 additions & 0 deletions include/cglm/struct/quat.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
CGLM_INLINE versors glms_quat_lerpc(versors from, versors to, float t)
CGLM_INLINE versors glms_quat_nlerp(versors from, versors to, float t)
CGLM_INLINE versors glms_quat_slerp(versors from, versors to, float t)
CGLM_INLINE versors glms_quat_slerp_longest(versors from, versors to, float t)
CGLM_INLINE mat4s. glms_quat_look(vec3s eye, versors ori)
CGLM_INLINE versors glms_quat_for(vec3s dir, vec3s fwd, vec3s up)
CGLM_INLINE versors glms_quat_forp(vec3s from, vec3s to, vec3s fwd, vec3s up)
Expand Down Expand Up @@ -457,6 +458,23 @@ glms_quat_(slerp)(versors from, versors to, float t) {
return dest;
}

/*!
* @brief interpolates between two quaternions
* using spherical linear interpolation (SLERP) and always takes the longest path
*
* @param[in] from from
* @param[in] to to
* @param[in] t amout
* @returns result quaternion
*/
CGLM_INLINE
versors
glms_quat_(slerp_longest)(versors from, versors to, float t) {
versors dest;
glm_quat_slerp_longest(from.raw, to.raw, t, dest.raw);
return dest;
}

/*!
* @brief creates view matrix using quaternion as camera orientation
*
Expand Down
6 changes: 6 additions & 0 deletions src/quat.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,12 @@ glmc_quat_slerp(versor from, versor to, float t, versor dest) {
glm_quat_slerp(from, to, t, dest);
}

CGLM_EXPORT
void
glmc_quat_slerp_longest(versor from, versor to, float t, versor dest) {
glm_quat_slerp_longest(from, to, t, dest);
}

CGLM_EXPORT
void
glmc_quat_look(vec3 eye, versor ori, mat4 dest) {
Expand Down

0 comments on commit a93a9ef

Please sign in to comment.