diff --git a/include/cglm/call/quat.h b/include/cglm/call/quat.h index e40bcdf..576f43b 100644 --- a/include/cglm/call/quat.h +++ b/include/cglm/call/quat.h @@ -19,17 +19,11 @@ glmc_quat_identity(versor q); CGLM_EXPORT void -glmc_quat(versor q, - float angle, - float x, - float y, - float z); +glmc_quat(versor q, float angle, float x, float y, float z); CGLM_EXPORT void -glmc_quatv(versor q, - float angle, - vec3 v); +glmc_quatv(versor q, float angle, vec3 v); CGLM_EXPORT float @@ -57,10 +51,7 @@ glmc_quat_mat3(versor q, mat3 dest); CGLM_EXPORT void -glmc_quat_slerp(versor q, - versor r, - float t, - versor dest); +glmc_quat_slerp(versor q, versor r, float t, versor dest); #ifdef __cplusplus } diff --git a/include/cglm/mat3.h b/include/cglm/mat3.h index e7f8bcc..9512aef 100644 --- a/include/cglm/mat3.h +++ b/include/cglm/mat3.h @@ -198,39 +198,41 @@ void glm_mat3_quat(mat3 m, versor dest) { float trace, r, rinv; + /* it seems using like m12 instead of m[1][2] causes extra instructions */ + trace = m[0][0] + m[1][1] + m[2][2]; if (trace >= 0.0f) { - r = 2.0f * sqrtf(1 + trace); - rinv = 1.0f / r; + r = sqrtf(1.0f + trace); + rinv = 0.5f / r; - dest[1] = rinv * (m[1][2] - m[2][1]); - dest[2] = rinv * (m[2][0] - m[0][2]); - dest[3] = rinv * (m[0][1] - m[1][0]); - dest[0] = r * 0.25f; - } else if (m[0][0] >= m[1][1] && m[0][0] >= m[2][2]) { - r = 2.0f * sqrtf(1 - m[1][1] - m[2][2] + m[0][0]); - rinv = 1.0f / r; - - dest[1] = r * 0.25f; - dest[2] = rinv * (m[0][1] + m[1][0]); - dest[3] = rinv * (m[0][2] + m[2][0]); dest[0] = rinv * (m[1][2] - m[2][1]); - } else if (m[1][1] >= m[2][2]) { - r = 2.0f * sqrtf(1 - m[0][0] - m[2][2] + m[1][1]); - rinv = 1.0f / r; + dest[1] = rinv * (m[2][0] - m[0][2]); + dest[2] = rinv * (m[0][1] - m[1][0]); + dest[3] = r * 0.5f; + } else if (m[0][0] >= m[1][1] && m[0][0] >= m[2][2]) { + r = sqrtf(1.0f - m[1][1] - m[2][2] + m[0][0]); + rinv = 0.5f / r; + dest[0] = r * 0.5f; dest[1] = rinv * (m[0][1] + m[1][0]); - dest[2] = r * 0.25f; - dest[3] = rinv * (m[1][2] + m[2][1]); - dest[0] = rinv * (m[2][0] - m[0][2]); - } else { - r = 2.0f * sqrtf(1 - m[0][0] - m[1][1] + m[2][2]); - rinv = 1.0f / r; + dest[2] = rinv * (m[0][2] + m[2][0]); + dest[3] = rinv * (m[1][2] - m[2][1]); + } else if (m[1][1] >= m[2][2]) { + r = sqrtf(1.0f - m[0][0] - m[2][2] + m[1][1]); + rinv = 0.5f / r; - dest[1] = rinv * (m[0][2] + m[2][0]); + dest[0] = rinv * (m[0][1] + m[1][0]); + dest[1] = r * 0.5f; dest[2] = rinv * (m[1][2] + m[2][1]); - dest[3] = r * 0.25f; - dest[0] = rinv * (m[0][1] - m[1][0]); + dest[3] = rinv * (m[2][0] - m[0][2]); + } else { + r = sqrtf(1.0f - m[0][0] - m[1][1] + m[2][2]); + rinv = 0.5f / r; + + dest[0] = rinv * (m[0][2] + m[2][0]); + dest[1] = rinv * (m[1][2] + m[2][1]); + dest[2] = r * 0.5f; + dest[3] = rinv * (m[0][1] - m[1][0]); } } diff --git a/include/cglm/mat4.h b/include/cglm/mat4.h index 05aac60..fd7a340 100644 --- a/include/cglm/mat4.h +++ b/include/cglm/mat4.h @@ -345,39 +345,41 @@ void glm_mat4_quat(mat4 m, versor dest) { float trace, r, rinv; + /* it seems using like m12 instead of m[1][2] causes extra instructions */ + trace = m[0][0] + m[1][1] + m[2][2]; if (trace >= 0.0f) { - r = 2.0f * sqrtf(1 + trace); - rinv = 1.0f / r; + r = sqrtf(1.0f + trace); + rinv = 0.5f / r; - dest[1] = rinv * (m[1][2] - m[2][1]); - dest[2] = rinv * (m[2][0] - m[0][2]); - dest[3] = rinv * (m[0][1] - m[1][0]); - dest[0] = r * 0.25f; - } else if (m[0][0] >= m[1][1] && m[0][0] >= m[2][2]) { - r = 2.0f * sqrtf(1 - m[1][1] - m[2][2] + m[0][0]); - rinv = 1.0f / r; - - dest[1] = r * 0.25f; - dest[2] = rinv * (m[0][1] + m[1][0]); - dest[3] = rinv * (m[0][2] + m[2][0]); dest[0] = rinv * (m[1][2] - m[2][1]); - } else if (m[1][1] >= m[2][2]) { - r = 2.0f * sqrtf(1 - m[0][0] - m[2][2] + m[1][1]); - rinv = 1.0f / r; + dest[1] = rinv * (m[2][0] - m[0][2]); + dest[2] = rinv * (m[0][1] - m[1][0]); + dest[3] = r * 0.5f; + } else if (m[0][0] >= m[1][1] && m[0][0] >= m[2][2]) { + r = sqrtf(1.0f - m[1][1] - m[2][2] + m[0][0]); + rinv = 0.5f / r; + dest[0] = r * 0.5f; dest[1] = rinv * (m[0][1] + m[1][0]); - dest[2] = r * 0.25f; - dest[3] = rinv * (m[1][2] + m[2][1]); - dest[0] = rinv * (m[2][0] - m[0][2]); - } else { - r = 2.0f * sqrtf(1 - m[0][0] - m[1][1] + m[2][2]); - rinv = 1.0f / r; + dest[2] = rinv * (m[0][2] + m[2][0]); + dest[3] = rinv * (m[1][2] - m[2][1]); + } else if (m[1][1] >= m[2][2]) { + r = sqrtf(1.0f - m[0][0] - m[2][2] + m[1][1]); + rinv = 0.5f / r; - dest[1] = rinv * (m[0][2] + m[2][0]); + dest[0] = rinv * (m[0][1] + m[1][0]); + dest[1] = r * 0.5f; dest[2] = rinv * (m[1][2] + m[2][1]); - dest[3] = r * 0.25f; - dest[0] = rinv * (m[0][1] - m[1][0]); + dest[3] = rinv * (m[2][0] - m[0][2]); + } else { + r = sqrtf(1.0f - m[0][0] - m[1][1] + m[2][2]); + rinv = 0.5f / r; + + dest[0] = rinv * (m[0][2] + m[2][0]); + dest[1] = rinv * (m[1][2] + m[2][1]); + dest[2] = r * 0.5f; + dest[3] = rinv * (m[0][1] - m[1][0]); } } diff --git a/include/cglm/quat.h b/include/cglm/quat.h index bbad5f2..4d6ee5d 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -13,7 +13,7 @@ Functions: CGLM_INLINE void glm_quat_identity(versor q); CGLM_INLINE void glm_quat(versor q, float angle, float x, float y, float z); - CGLM_INLINE void glm_quatv(versor q, float angle, vec3 v); + CGLM_INLINE void glm_quatv(versor q, float angle, vec3 axis); CGLM_INLINE float glm_quat_norm(versor q); CGLM_INLINE void glm_quat_normalize(versor q); CGLM_INLINE float glm_quat_dot(versor q, versor r); @@ -33,19 +33,16 @@ #endif /* - * IMPORTANT! cglm stores quat as [w, x, y, z] + * IMPORTANT: + * ---------------------------------------------------------------------------- + * cglm stores quat as [x, y, z, w] since v0.3.6 * - * Possible changes (these may be changed in the future): - * - versor is identity quat, we can define new type for quat. - * it can't be quat or quaternion becuase someone can use that name for - * variable name. maybe just vec4. - * - it stores [w, x, y, z] but it may change to [x, y, z, w] if we get enough - * feedback to change it. - * - in general we use last param as dest, but this header used first param - * as dest this may be changed but decided yet + * it was [w, x, y, z] before v0.3.6 it has been changed to [x, y, z, w] + * with v0.3.6 version. + * ---------------------------------------------------------------------------- */ -#define GLM_QUAT_IDENTITY_INIT {1.0f, 0.0f, 0.0f, 0.0f} +#define GLM_QUAT_IDENTITY_INIT {0.0f, 0.0f, 0.0f, 1.0f} #define GLM_QUAT_IDENTITY ((versor)GLM_QUAT_IDENTITY_INIT) /*! @@ -60,6 +57,24 @@ glm_quat_identity(versor q) { glm_vec4_copy(v, q); } +/*! + * @brief inits quaterion with raw values + * + * @param[out] q quaternion + * @param[in] x x + * @param[in] y y + * @param[in] z z + * @param[in] w w (real part) + */ +CGLM_INLINE +void +glm_quat_init(versor q, float x, float y, float z, float w) { + q[0] = x; + q[1] = y; + q[2] = z; + q[3] = w; +} + /*! * @brief creates NEW quaternion with individual axis components * @@ -71,21 +86,17 @@ glm_quat_identity(versor q) { */ CGLM_INLINE void -glm_quat(versor q, - float angle, - float x, - float y, - float z) { +glm_quat(versor q, float angle, float x, float y, float z) { float a, c, s; a = angle * 0.5f; c = cosf(a); s = sinf(a); - q[0] = c; - q[1] = s * x; - q[2] = s * y; - q[3] = s * z; + q[0] = s * x; + q[1] = s * y; + q[2] = s * z; + q[3] = c; } /*! @@ -93,23 +104,21 @@ glm_quat(versor q, * * @param[out] q quaternion * @param[in] angle angle (radians) - * @param[in] v axis + * @param[in] axis axis */ CGLM_INLINE void -glm_quatv(versor q, - float angle, - vec3 v) { +glm_quatv(versor q, float angle, vec3 axis) { float a, c, s; a = angle * 0.5f; c = cosf(a); s = sinf(a); - q[0] = c; - q[1] = s * v[0]; - q[2] = s * v[1]; - q[3] = s * v[2]; + q[0] = s * axis[0]; + q[1] = s * axis[1]; + q[2] = s * axis[2]; + q[3] = c; } /*! @@ -146,13 +155,13 @@ glm_quat_normalize(versor q) { /*! * @brief dot product of two quaternion * - * @param[in] q quaternion 1 - * @param[in] r quaternion 2 + * @param[in] q1 quaternion 1 + * @param[in] q2 quaternion 2 */ CGLM_INLINE float -glm_quat_dot(versor q, versor r) { - return glm_vec4_dot(q, r); +glm_quat_dot(versor q1, versor q2) { + return glm_vec4_dot(q1, q2); } /*! @@ -190,10 +199,10 @@ glm_quat_mat4(versor q, mat4 dest) { norm = glm_quat_norm(q); s = norm > 0.0f ? 2.0f / norm : 0.0f; - w = q[0]; - x = q[1]; - y = q[2]; - z = q[3]; + x = q[0]; + y = q[1]; + z = q[2]; + w = q[3]; xx = s * x * x; xy = s * x * y; wx = s * w * x; yy = s * y * y; yz = s * y * z; wy = s * w * y; @@ -237,10 +246,10 @@ glm_quat_mat3(versor q, mat3 dest) { norm = glm_quat_norm(q); s = norm > 0.0f ? 2.0f / norm : 0.0f; - w = q[0]; - x = q[1]; - y = q[2]; - z = q[3]; + x = q[0]; + y = q[1]; + z = q[2]; + w = q[3]; xx = s * x * x; xy = s * x * y; wx = s * w * x; yy = s * y * y; yz = s * y * z; wy = s * w * y; @@ -270,10 +279,8 @@ glm_quat_mat3(versor q, mat3 dest) { */ CGLM_INLINE void -glm_quat_slerp(versor q, - versor r, - float t, - versor dest) { +glm_quat_slerp(versor q, versor r, float t, versor dest) { + /* https://en.wikipedia.org/wiki/Slerp */ #if defined( __SSE__ ) || defined( __SSE2__ ) glm_quat_slerp_sse2(q, r, t, dest); diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index 873c172..65fe0ba 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -327,9 +327,7 @@ glm_vec_angle(vec3 v1, vec3 v2) { CGLM_INLINE void -glm_quatv(versor q, - float angle, - vec3 v); +glm_quatv(versor q, float angle, vec3 axis); /*! * @brief rotate vec3 around axis by angle using Rodrigues' rotation formula diff --git a/src/quat.c b/src/quat.c index 9955ce1..35ec890 100644 --- a/src/quat.c +++ b/src/quat.c @@ -16,19 +16,13 @@ glmc_quat_identity(versor q) { CGLM_EXPORT void -glmc_quat(versor q, - float angle, - float x, - float y, - float z) { +glmc_quat(versor q, float angle, float x, float y, float z) { glm_quat(q, angle, x, y, z); } CGLM_EXPORT void -glmc_quatv(versor q, - float angle, - vec3 v) { +glmc_quatv(versor q, float angle, vec3 v) { glm_quatv(q, angle, v); } @@ -53,7 +47,7 @@ glmc_quat_dot(versor q, versor r) { CGLM_EXPORT void glmc_quat_mulv(versor q1, versor q2, versor dest) { - glm_quat_mulv(q1, q2, dest); + glm_quat_mul(q1, q2, dest); } CGLM_EXPORT