diff --git a/include/cglm/quat.h b/include/cglm/quat.h index ff3c38c..fa760b7 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -39,6 +39,8 @@ #include "common.h" #include "vec4.h" +#include "mat4.h" +#include "mat3.h" #ifdef CGLM_SSE_FP # include "simd/sse2/quat.h" @@ -578,4 +580,29 @@ glm_quat_slerp(versor from, versor to, float t, versor dest) { glm_vec4_scale(q1, 1.0f / sinTheta, dest); } +CGLM_INLINE +void +glm_mat4_mulv(mat4 m, vec4 v, vec4 dest); + +/*! + * @brief creates view matrix using quaternion as camera orientation + * + * @param[in] eye eye + * @param[in] ori orientation in world space as quaternion + * @param[out] dest view matrix + */ +CGLM_INLINE +void +glm_quat_look(vec3 eye, versor ori, mat4 dest) { + vec4 t; + + /* orientation */ + glm_quat_mat4t(ori, dest); + + /* translate */ + glm_vec4(eye, 1.0f, t); + glm_mat4_mulv(dest, t, t); + glm_vec_flipsign_to(t, dest[3]); +} + #endif /* cglm_quat_h */ diff --git a/test/src/test_quat.c b/test/src/test_quat.c index 723dea1..b5db10f 100644 --- a/test/src/test_quat.c +++ b/test/src/test_quat.c @@ -18,8 +18,9 @@ test_quat_mul_raw(versor p, versor q, versor dest) { void test_quat(void **state) { - mat4 inRot, outRot; + mat4 inRot, outRot, view1, view2; versor inQuat, outQuat, q3, q4; + vec3 eye; int i; for (i = 0; i < 1000; i++) { @@ -35,4 +36,16 @@ test_quat(void **state) { test_assert_quat_eq(q3, q4); } + + /* test lookat */ + test_rand_vec3(eye); + glm_quatv(q3, glm_rad(-90.0f), GLM_YUP); + + /* now X axis must be forward axis, Z must be right axis */ + glm_look(eye, GLM_XUP, GLM_YUP, view1); + + /* create view matrix with quaternion */ + glm_quat_look(eye, q3, view2); + + test_assert_mat4_eq2(view1, view2, 0.000009); }