diff --git a/docs/source/quat.rst b/docs/source/quat.rst index 84970998a..eb53638e2 100644 --- a/docs/source/quat.rst +++ b/docs/source/quat.rst @@ -56,6 +56,7 @@ Functions: #. :c:func:`glm_quat_nlerp` #. :c:func:`glm_quat_slerp` #. :c:func:`glm_quat_slerp_longest` +#. :c:func:`glm_quat_bezier` #. :c:func:`glm_quat_look` #. :c:func:`glm_quat_for` #. :c:func:`glm_quat_forp` @@ -363,6 +364,18 @@ Functions documentation | *[in]* **t** interpolant (amount) clamped between 0 and 1 | *[out]* **dest** result quaternion +.. c:function:: void glm_quat_bezier(versor from, versor ctrl1, versor ctrl2, versor to, float t, versor dest); + + | interpolates between two quaternions using a cubic bezier + + Parameters: + | *[in]* **from** from + | *[in]* **ctrl1** control point corresponding to from + | *[in]* **ctrl2** control point corresponding to to + | *[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 diff --git a/include/cglm/call/quat.h b/include/cglm/call/quat.h index 4244d3621..309167a0f 100644 --- a/include/cglm/call/quat.h +++ b/include/cglm/call/quat.h @@ -137,6 +137,10 @@ CGLM_EXPORT void glmc_quat_slerp_longest(versor q, versor r, float t, versor dest); +CGLM_EXPORT +void +glmc_quat_bezier(versor from, versor ctrl1, versor ctrl2, versor to, float t, versor dest); + CGLM_EXPORT void glmc_quat_look(vec3 eye, versor ori, mat4 dest); diff --git a/include/cglm/quat.h b/include/cglm/quat.h index 777e7937f..04c830ee8 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -41,6 +41,12 @@ 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_bezier(versor from, + versor ctrl1, + versor ctrl2, + versor to, + 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); CGLM_INLINE void glm_quat_forp(vec3 from, @@ -789,6 +795,35 @@ glm_quat_slerp_longest(versor from, versor to, float t, versor dest) { glm_vec4_scale(q1, 1.0f / sinTheta, dest); } +/*! + * @brief interpolates between two quaternions using a cubic bezier + * + * @param[in] from from + * @param[in] ctrl1 control point corresponding to from + * @param[in] ctrl2 control point corresponding to to + * @param[in] to to + * @param[in] t interpolant (amount) + * @param[out] dest result + */ +CGLM_INLINE +void +glm_quat_bezier(versor from, versor ctrl1, versor ctrl2, versor to, float t, versor dest) { + + //do normal Decasteljau bezier but replace lerp with slerp + + //tried to get it into bernstein polynomial but seems more efficient this way? + //because unlike normal bezier, this one depends on angle between quaternions to slerp + CGLM_ALIGN(16) versor a, b, c, d, e; + + glm_quat_slerp(from, ctrl1, t, a); + glm_quat_slerp(ctrl1, ctrl2, t, b); + glm_quat_slerp(ctrl2, to, t, c); + glm_quat_slerp(a, b, t, d); + glm_quat_slerp(b, c, t, e); + glm_quat_slerp(d, e, t, dest); + +} + /*! * @brief creates view matrix using quaternion as camera orientation * diff --git a/include/cglm/struct/quat.h b/include/cglm/struct/quat.h index ff8774018..3aae21d98 100644 --- a/include/cglm/struct/quat.h +++ b/include/cglm/struct/quat.h @@ -38,6 +38,11 @@ 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 versors glms_quat_bezier(versor from, + versor ctrl1, + versor ctrl2, + versor 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) @@ -475,6 +480,24 @@ glms_quat_(slerp_longest)(versors from, versors to, float t) { return dest; } +/*! + * @brief interpolates between two quaternions using a cubic bezier + * + * @param[in] from from + * @param[in] ctrl1 control point corresponding to from + * @param[in] ctrl2 control point corresponding to to + * @param[in] to to + * @param[in] t interpolant (amount) + * @returns result + */ +CGLM_INLINE +versors +glms_quat_(bezier)(versors from, versors ctrl1, versors ctrl2, versors to, float t) { + versors dest; + glm_quat_bezier(from.raw, ctrl1.raw, ctrl2.raw, to.raw, t, dest.raw); + return dest; +} + /*! * @brief creates view matrix using quaternion as camera orientation *