diff --git a/include/cglm/call/quat.h b/include/cglm/call/quat.h index ad5f82d..32e503c 100644 --- a/include/cglm/call/quat.h +++ b/include/cglm/call/quat.h @@ -131,11 +131,11 @@ glmc_quat_look(vec3 eye, versor ori, mat4 dest); CGLM_EXPORT void -glmc_quat_for(vec3 dir, vec3 fwd, vec3 up, versor dest); +glmc_quat_for(vec3 dir, vec3 up, versor dest); CGLM_EXPORT void -glmc_quat_forp(vec3 from, vec3 to, vec3 fwd, vec3 up, versor dest); +glmc_quat_forp(vec3 from, vec3 to, vec3 up, versor dest); CGLM_EXPORT void diff --git a/include/cglm/cam.h b/include/cglm/cam.h index ad971fe..bbe7fec 100644 --- a/include/cglm/cam.h +++ b/include/cglm/cam.h @@ -319,10 +319,7 @@ glm_perspective_resize(float aspect, mat4 proj) { */ CGLM_INLINE void -glm_lookat(vec3 eye, - vec3 center, - vec3 up, - mat4 dest) { +glm_lookat(vec3 eye, vec3 center, vec3 up, mat4 dest) { CGLM_ALIGN(8) vec3 f, u, s; glm_vec3_sub(center, eye, f); diff --git a/include/cglm/quat.h b/include/cglm/quat.h index 573932f..42caf14 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -693,32 +693,23 @@ glm_quat_look(vec3 eye, versor ori, mat4 dest) { * @brief creates look rotation quaternion * * @param[in] dir direction to look - * @param[in] fwd forward vector * @param[in] up up vector * @param[out] dest destination quaternion */ CGLM_INLINE void -glm_quat_for(vec3 dir, vec3 fwd, vec3 up, versor dest) { - CGLM_ALIGN(8) vec3 axis; - float dot, angle; +glm_quat_for(vec3 dir, vec3 up, versor dest) { + CGLM_ALIGN_MAT mat3 m; - dot = glm_vec3_dot(dir, fwd); - if (fabsf(dot + 1.0f) < 0.000001f) { - glm_quat_init(dest, up[0], up[1], up[2], GLM_PIf); - return; - } + glm_vec3_normalize_to(dir, m[2]); - if (fabsf(dot - 1.0f) < 0.000001f) { - glm_quat_identity(dest); - return; - } + /* No need to negate in LH, but we use RH here */ + glm_vec3_negate(m[2]); + + glm_vec3_crossn(up, m[2], m[0]); + glm_vec3_cross(m[2], m[0], m[1]); - angle = acosf(dot); - glm_cross(fwd, dir, axis); - glm_normalize(axis); - - glm_quatv(dest, angle, axis); + glm_mat3_quat(m, dest); } /*! @@ -733,10 +724,10 @@ glm_quat_for(vec3 dir, vec3 fwd, vec3 up, versor dest) { */ CGLM_INLINE void -glm_quat_forp(vec3 from, vec3 to, vec3 fwd, vec3 up, versor dest) { +glm_quat_forp(vec3 from, vec3 to, vec3 up, versor dest) { CGLM_ALIGN(8) vec3 dir; glm_vec3_sub(to, from, dir); - glm_quat_for(dir, fwd, up, dest); + glm_quat_for(dir, up, dest); } /*! diff --git a/include/cglm/struct/quat.h b/include/cglm/struct/quat.h index 5940af5..a855bcf 100644 --- a/include/cglm/struct/quat.h +++ b/include/cglm/struct/quat.h @@ -443,9 +443,9 @@ glms_quat_look(vec3s eye, versors ori) { */ CGLM_INLINE versors -glms_quat_for(vec3s dir, vec3s fwd, vec3s up) { +glms_quat_for(vec3s dir, vec3s up) { versors dest; - glm_quat_for(dir.raw, fwd.raw, up.raw, dest.raw); + glm_quat_for(dir.raw, up.raw, dest.raw); return dest; } @@ -461,9 +461,9 @@ glms_quat_for(vec3s dir, vec3s fwd, vec3s up) { */ CGLM_INLINE versors -glms_quat_forp(vec3s from, vec3s to, vec3s fwd, vec3s up) { +glms_quat_forp(vec3s from, vec3s to, vec3s up) { versors dest; - glm_quat_forp(from.raw, to.raw, fwd.raw, up.raw, dest.raw); + glm_quat_forp(from.raw, to.raw, up.raw, dest.raw); return dest; } diff --git a/src/quat.c b/src/quat.c index efe9458..f992f7c 100644 --- a/src/quat.c +++ b/src/quat.c @@ -184,14 +184,14 @@ glmc_quat_look(vec3 eye, versor ori, mat4 dest) { CGLM_EXPORT void -glmc_quat_for(vec3 dir, vec3 fwd, vec3 up, versor dest) { - glm_quat_for(dir, fwd, up, dest); +glmc_quat_for(vec3 dir, vec3 up, versor dest) { + glm_quat_for(dir, up, dest); } CGLM_EXPORT void -glmc_quat_forp(vec3 from, vec3 to, vec3 fwd, vec3 up, versor dest) { - glm_quat_forp(from, to, fwd, up, dest); +glmc_quat_forp(vec3 from, vec3 to, vec3 up, versor dest) { + glm_quat_forp(from, to, up, dest); } CGLM_EXPORT diff --git a/test/src/test_quat.h b/test/src/test_quat.h index 2d4625c..0bfd70c 100644 --- a/test/src/test_quat.h +++ b/test/src/test_quat.h @@ -760,3 +760,48 @@ TEST_IMPL(GLM_PREFIX, quat_look) { TEST_SUCCESS } + +TEST_IMPL(GLM_PREFIX, quat_for) { + versor q1, q2; + + glm_quat(q1, glm_rad(90.0f), 0.0f, 1.0f, 0.0f); + GLM(quat_for)((vec3){-1.0f, 0.0f, 0.0f}, (vec3){0.0f, 1.0f, 0.0f}, q2); + ASSERTIFY(test_assert_quat_eq(q1, q2)); + + glm_quat(q2, glm_rad(90.0f), 1.0f, 0.0f, 0.0f); + GLM(quat_for)((vec3){0.0f, 1.0f, 0.0f}, (vec3){0.0f, 0.0f, 1.0f}, q1); + ASSERTIFY(test_assert_quat_eq(q1, q2)); + + glm_quat(q2, glm_rad(180.0f), 1.0f, 0.0f, 0.0f); + GLM(quat_for)((vec3){0.0f, 0.0f, 1.0f}, (vec3){0.0f, -1.0f, 0.0f}, q1); + ASSERTIFY(test_assert_quat_eq(q1, q2)); + + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, quat_forp) { + versor q1, q2; + + glm_quat(q1, glm_rad(90.0f), 0.0f, 1.0f, 0.0f); + GLM(quat_forp)((vec3){2.0f, 0.0f, 0.0f}, + (vec3){1.0f, 0.0f, 0.0f}, + (vec3){0.0f, 1.0f, 0.0f}, + q2); + ASSERTIFY(test_assert_quat_eq(q1, q2)); + + glm_quat(q2, glm_rad(90.0f), 1.0f, 0.0f, 0.0f); + GLM(quat_forp)((vec3){0.0f, 1.0f, 0.0f}, + (vec3){0.0f, 2.0f, 0.0f}, + (vec3){0.0f, 0.0f, 1.0f}, + q1); + ASSERTIFY(test_assert_quat_eq(q1, q2)); + + glm_quat(q2, glm_rad(180.0f), 1.0f, 0.0f, 0.0f); + GLM(quat_forp)((vec3){0.0f, 1.0f, 1.0f}, + (vec3){0.0f, 1.0f, 2.0f}, + (vec3){0.0f, -1.0f, 0.0f}, + q1); + ASSERTIFY(test_assert_quat_eq(q1, q2)); + + TEST_SUCCESS +} diff --git a/test/tests.h b/test/tests.h index ec6da23..8f132cd 100644 --- a/test/tests.h +++ b/test/tests.h @@ -163,6 +163,8 @@ TEST_DECLARE(glm_quat_lerp) TEST_DECLARE(glm_quat_lerpc) TEST_DECLARE(glm_quat_slerp) TEST_DECLARE(glm_quat_look) +TEST_DECLARE(glm_quat_for) +TEST_DECLARE(glm_quat_forp) TEST_DECLARE(glmc_quat_identity) TEST_DECLARE(glmc_quat_identity_array) @@ -193,6 +195,8 @@ TEST_DECLARE(glmc_quat_lerp) TEST_DECLARE(glmc_quat_lerpc) TEST_DECLARE(glmc_quat_slerp) TEST_DECLARE(glmc_quat_look) +TEST_DECLARE(glmc_quat_for) +TEST_DECLARE(glmc_quat_forp) /* bezier */ TEST_DECLARE(bezier) @@ -671,6 +675,8 @@ TEST_LIST { TEST_ENTRY(glm_quat_lerpc) TEST_ENTRY(glm_quat_slerp) TEST_ENTRY(glm_quat_look) + TEST_ENTRY(glm_quat_for) + TEST_ENTRY(glm_quat_forp) TEST_ENTRY(glmc_quat_identity) TEST_ENTRY(glmc_quat_identity_array) @@ -701,6 +707,8 @@ TEST_LIST { TEST_ENTRY(glmc_quat_lerpc) TEST_ENTRY(glmc_quat_slerp) TEST_ENTRY(glmc_quat_look) + TEST_ENTRY(glmc_quat_for) + TEST_ENTRY(glmc_quat_forp) /* bezier */ TEST_ENTRY(bezier)