From 05ea35ffec39e24ed2fca37ad0a8fa5aefd54f21 Mon Sep 17 00:00:00 2001 From: John Choi Date: Thu, 7 Dec 2023 10:29:07 -0600 Subject: [PATCH 01/13] made euler to quat xyz. Now I'm trying to test if it works or not --- include/cglm/quat.h | 27 +++++++++++++++++++++++++++ test/src/test_quat.h | 30 ++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/include/cglm/quat.h b/include/cglm/quat.h index ab0c5902b..d415ab798 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -139,6 +139,33 @@ glm_quat_init(versor q, float x, float y, float z, float w) { q[3] = w; } +//TODO: telephone001's eulertoquat + +/*! + * @brief creates a quaternion using rotation angles and does does rotations in x y z order + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +void +glm_euler_xyz_quat(versor q, vec3 angles) { + float xs = sinf(angles[0] / 2.0); + float xc = cosf(angles[0] / 2.0); + + float ys = sinf(angles[1] / 2.0); + float yc = cosf(angles[1] / 2.0); + + float zs = sinf(angles[2] / 2.0); + float zc = cosf(angles[2] / 2.0); + + glm_quat_init(q, + zc * yc * xs - zs * ys * xs, + zc * ys * xc - zs * yc * xs, + zs * yc * xc - zs * yc * xs, + zc * yc * xc + zs * ys * xs); +} + /*! * @brief creates NEW quaternion with axis vector * diff --git a/test/src/test_quat.h b/test/src/test_quat.h index da831fe2d..3c1b24ed1 100644 --- a/test/src/test_quat.h +++ b/test/src/test_quat.h @@ -121,6 +121,36 @@ TEST_IMPL(GLM_PREFIX, quatv) { TEST_SUCCESS } +// telephone001 changes (remove comment when done) TODO +TEST_IMPL(GLM_PREFIX, euler_xyz_quat) { + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + + //random angles for testing + vec3 angles = {glm_rad(30.0f), glm_rad(60.0f), glm_rad(90.0f)}; + + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + glm_quat_mul(rot_x, expected, expected); + glm_quat_mul(rot_y, expected, expected); + glm_quat_mul(rot_z, expected, expected); + + versor result; + glm_euler_xyz_quat(angles, result); + ASSERTIFY(test_assert_vec3_eq(result, expected)) + + TEST_SUCCESS +} + + TEST_IMPL(GLM_PREFIX, quat) { versor q1 = {1.0f, 2.0f, 3.0f, 4.0f}; vec3 v1, v2; From d67ac97323ab6307ff6288a72b10293d6bdf8f29 Mon Sep 17 00:00:00 2001 From: John Choi Date: Thu, 7 Dec 2023 12:21:55 -0600 Subject: [PATCH 02/13] got the euler to quat xyz working and got the tests to pass --- include/cglm/quat.h | 21 +++++++++++---------- test/src/test_quat.h | 28 +++++++++++++++++++--------- test/tests.h | 2 ++ 3 files changed, 32 insertions(+), 19 deletions(-) diff --git a/include/cglm/quat.h b/include/cglm/quat.h index d415ab798..cc5fde8e1 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -142,7 +142,7 @@ glm_quat_init(versor q, float x, float y, float z, float w) { //TODO: telephone001's eulertoquat /*! - * @brief creates a quaternion using rotation angles and does does rotations in x y z order + * @brief creates NEW quaternion using rotation angles and does does rotations in x y z order * * @param[out] q quaternion * @param[in] angle angles x y z (radians) @@ -150,20 +150,21 @@ glm_quat_init(versor q, float x, float y, float z, float w) { CGLM_INLINE void glm_euler_xyz_quat(versor q, vec3 angles) { - float xs = sinf(angles[0] / 2.0); - float xc = cosf(angles[0] / 2.0); + float xs = sinf(angles[0] / 2.0f); + float xc = cosf(angles[0] / 2.0f); - float ys = sinf(angles[1] / 2.0); - float yc = cosf(angles[1] / 2.0); + float ys = sinf(angles[1] / 2.0f); + float yc = cosf(angles[1] / 2.0f); - float zs = sinf(angles[2] / 2.0); - float zc = cosf(angles[2] / 2.0); + float zs = sinf(angles[2] / 2.0f); + float zc = cosf(angles[2] / 2.0f); glm_quat_init(q, - zc * yc * xs - zs * ys * xs, - zc * ys * xc - zs * yc * xs, - zs * yc * xc - zs * yc * xs, + zc * yc * xs - zs * ys * xc, + zc * ys * xc + zs * yc * xs, + -zc * ys * xs + zs * yc * xc, zc * yc * xc + zs * ys * xs); + } /*! diff --git a/test/src/test_quat.h b/test/src/test_quat.h index 3c1b24ed1..9b274a0c1 100644 --- a/test/src/test_quat.h +++ b/test/src/test_quat.h @@ -123,29 +123,39 @@ TEST_IMPL(GLM_PREFIX, quatv) { // telephone001 changes (remove comment when done) TODO TEST_IMPL(GLM_PREFIX, euler_xyz_quat) { - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; + /*random angles for testing*/ + vec3 angles = {glm_rad(30.0f), glm_rad(60.0f), glm_rad(90.0f)}; + /*quaternion representations for rotations*/ versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; - //random angles for testing - vec3 angles = {glm_rad(30.0f), glm_rad(60.0f), glm_rad(90.0f)}; + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result = {0.0f, 0.0f, 0.0f, 0.0f}; + /*create the rotation quaternions using the angles and axises*/ glm_quatv(rot_x, angles[0], axis_x); glm_quatv(rot_y, angles[1], axis_y); glm_quatv(rot_z, angles[2], axis_z); - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + /*apply the rotations to a unit quaternion in xyz order*/ glm_quat_mul(rot_x, expected, expected); glm_quat_mul(rot_y, expected, expected); glm_quat_mul(rot_z, expected, expected); - versor result; - glm_euler_xyz_quat(angles, result); - ASSERTIFY(test_assert_vec3_eq(result, expected)) + /*use my function to get the quaternion*/ + glm_euler_xyz_quat(result, angles); + + fprintf(stderr,"TEST\n"); + for (int i = 0; i < 4; i++) { + fprintf(stderr, "%f vs %f\n", expected[i], result[i]); + } + ASSERTIFY(test_assert_quat_eq(result, expected)) TEST_SUCCESS } diff --git a/test/tests.h b/test/tests.h index d32ec40fd..d25a69bd8 100644 --- a/test/tests.h +++ b/test/tests.h @@ -374,6 +374,7 @@ TEST_DECLARE(glm_quat_identity) TEST_DECLARE(glm_quat_identity_array) TEST_DECLARE(glm_quat_init) TEST_DECLARE(glm_quatv) +TEST_DECLARE(glm_euler_xyz_quat) TEST_DECLARE(glm_quat) TEST_DECLARE(glm_quat_copy) TEST_DECLARE(glm_quat_norm) @@ -1351,6 +1352,7 @@ TEST_LIST { TEST_ENTRY(glm_quat_identity_array) TEST_ENTRY(glm_quat_init) TEST_ENTRY(glm_quatv) + TEST_ENTRY(glm_euler_xyz_quat) TEST_ENTRY(glm_quat) TEST_ENTRY(glm_quat_copy) TEST_ENTRY(glm_quat_norm) From c5694c5c17865a21b3bec93c301cd56eb42ec253 Mon Sep 17 00:00:00 2001 From: John Choi Date: Fri, 8 Dec 2023 00:26:33 -0600 Subject: [PATCH 03/13] made all the functions. I have miscalculated some stuff and am currently trying to test them. I have created all the testing functions as well --- include/cglm/quat.h | 142 ++++++++++++- test/src/test_quat.h | 474 ++++++++++++++++++++++++++++++++++++++++--- test/tests.h | 10 + 3 files changed, 600 insertions(+), 26 deletions(-) diff --git a/include/cglm/quat.h b/include/cglm/quat.h index cc5fde8e1..d85773c9e 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -142,7 +142,8 @@ glm_quat_init(versor q, float x, float y, float z, float w) { //TODO: telephone001's eulertoquat /*! - * @brief creates NEW quaternion using rotation angles and does does rotations in x y z order + * @brief creates NEW quaternion using rotation angles and does + * rotations in x y z order (roll pitch yaw) * * @param[out] q quaternion * @param[in] angle angles x y z (radians) @@ -159,14 +160,153 @@ glm_euler_xyz_quat(versor q, vec3 angles) { float zs = sinf(angles[2] / 2.0f); float zc = cosf(angles[2] / 2.0f); + glm_quat_init(q, zc * yc * xs - zs * ys * xc, zc * ys * xc + zs * yc * xs, -zc * ys * xs + zs * yc * xc, zc * yc * xc + zs * ys * xs); +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in x z y order (roll yaw pitch) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +void +glm_euler_xzy_quat(versor q, vec3 angles) { + float xs = sinf(angles[0] / 2.0f); + float xc = cosf(angles[0] / 2.0f); + + float ys = sinf(angles[1] / 2.0f); + float yc = cosf(angles[1] / 2.0f); + + float zs = sinf(angles[2] / 2.0f); + float zc = cosf(angles[2] / 2.0f); + + glm_quat_init(q, + yc * zc * xs + ys * zs * xc, + yc * zs * xs + ys * zc * xc, + yc * zs * xc - ys * zc * xs, + yc * zc * xc - ys * zs * xs); + +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in y x z order (pitch roll yaw) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +void +glm_euler_yxz_quat(versor q, vec3 angles) { + float xs = sinf(angles[0] / 2.0f); + float xc = cosf(angles[0] / 2.0f); + + float ys = sinf(angles[1] / 2.0f); + float yc = cosf(angles[1] / 2.0f); + float zs = sinf(angles[2] / 2.0f); + float zc = cosf(angles[2] / 2.0f); + + glm_quat_init(q, + zc * xc * ys - zs * xs * yc, + zc * xs * ys + zs * xc * yc, + zc * xs * yc + zs * xc * ys, + zc * xc * yc - zs * xs * ys); + + } +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in y z x order (pitch yaw roll) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +void +glm_euler_yzx_quat(versor q, vec3 angles) { + float xs = sinf(angles[0] / 2.0f); + float xc = cosf(angles[0] / 2.0f); + + float ys = sinf(angles[1] / 2.0f); + float yc = cosf(angles[1] / 2.0f); + + float zs = sinf(angles[2] / 2.0f); + float zc = cosf(angles[2] / 2.0f); + + glm_quat_init(q, + -xc * zs * ys + xs * zc * yc, + xc * zc * ys - xs * zs * yc, + xc * zs * yc + xs * zc * ys, + xc * zc * yc + xs * zs * ys); + +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in z x y order (yaw roll pitch) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +void +glm_euler_zxy_quat(versor q, vec3 angles) { + float xs = sinf(angles[0] / 2.0f); + float xc = cosf(angles[0] / 2.0f); + + float ys = sinf(angles[1] / 2.0f); + float yc = cosf(angles[1] / 2.0f); + + float zs = sinf(angles[2] / 2.0f); + float zc = cosf(angles[2] / 2.0f); + + glm_quat_init(q, + yc * xs * zc + ys * xc * zs, + yc * xc * zs - ys * xs * zc, + yc * xs * zs + ys * xc * zc, + yc * xc * zc - ys * xs * zs); + + +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in z y x order (yaw pitch roll) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +void +glm_euler_zyx_quat(versor q, vec3 angles) { + float xs = sinf(angles[0] / 2.0f); + float xc = cosf(angles[0] / 2.0f); + + float ys = sinf(angles[1] / 2.0f); + float yc = cosf(angles[1] / 2.0f); + + float zs = sinf(angles[2] / 2.0f); + float zc = cosf(angles[2] / 2.0f); + + glm_quat_init(q, + xc * ys * zs + xs * yc * zc, + xc * yc * zs + xs * ys * zc, + -xc * ys * zc + xs * yc * zs, + xc * yc * zc - xs * ys * zs); + +} + + + /*! * @brief creates NEW quaternion with axis vector * diff --git a/test/src/test_quat.h b/test/src/test_quat.h index 9b274a0c1..176b055a4 100644 --- a/test/src/test_quat.h +++ b/test/src/test_quat.h @@ -123,39 +123,463 @@ TEST_IMPL(GLM_PREFIX, quatv) { // telephone001 changes (remove comment when done) TODO TEST_IMPL(GLM_PREFIX, euler_xyz_quat) { - /*random angles for testing*/ - vec3 angles = {glm_rad(30.0f), glm_rad(60.0f), glm_rad(90.0f)}; + for (int i = 0; i < 100; i++) { + /*random angles for testing*/ + vec3 angles; - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + /*quaternion representations for rotations*/ + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result = {0.0f, 0.0f, 0.0f, 0.0f}; + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result; - /*create the rotation quaternions using the angles and axises*/ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); + test_rand_vec3(angles); - /*apply the rotations to a unit quaternion in xyz order*/ - glm_quat_mul(rot_x, expected, expected); - glm_quat_mul(rot_y, expected, expected); - glm_quat_mul(rot_z, expected, expected); + /*create the rotation quaternions using the angles and axises*/ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); - /*use my function to get the quaternion*/ - glm_euler_xyz_quat(result, angles); + /*apply the rotations to a unit quaternion in xyz order*/ + glm_quat_mul(rot_x, expected, expected); + glm_quat_mul(rot_y, expected, expected); + glm_quat_mul(rot_z, expected, expected); - fprintf(stderr,"TEST\n"); - for (int i = 0; i < 4; i++) { - fprintf(stderr, "%f vs %f\n", expected[i], result[i]); + /*use my function to get the quaternion*/ + glm_euler_xyz_quat(result, angles); + + ASSERTIFY(test_assert_quat_eq(result, expected)) + } + + /*Start gimbal lock tests*/ + for (float x = -90.0f; x <= 90.0f; x += 90.0f) { + for (float y = -90.0f; y <= 90.0f; y += 90.0f) { + for (float z = -90.0f; z <= 90.0f; z += 90.0f) { + /* angles that will cause gimbal lock*/ + vec3 angles = {x, y, z}; + + /*quaternion representations for rotations*/ + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result; + + /*create the rotation quaternions using the angles and axises*/ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /*apply the rotations to a unit quaternion in xyz order*/ + glm_quat_mul(rot_x, expected, expected); + glm_quat_mul(rot_y, expected, expected); + glm_quat_mul(rot_z, expected, expected); + + /*use my function to get the quaternion*/ + glm_euler_xyz_quat(result, angles); + + ASSERTIFY(test_assert_quat_eq(result, expected)) + } + } + } + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, euler_xzy_quat) { + for (int i = 0; i < 100; i++) { + /*random angles for testing*/ + vec3 angles; + + /*quaternion representations for rotations*/ + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result; + + test_rand_vec3(angles); + + /*create the rotation quaternions using the angles and axises*/ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /*apply the rotations to a unit quaternion in xzy order*/ + glm_quat_mul(rot_x, expected, expected); + glm_quat_mul(rot_z, expected, expected); + glm_quat_mul(rot_y, expected, expected); + + /*use my function to get the quaternion*/ + glm_euler_xzy_quat(result, angles); + + ASSERTIFY(test_assert_quat_eq(result, expected)) + } + + /*Start gimbal lock tests*/ + for (float x = -90.0f; x <= 90.0f; x += 90.0f) { + for (float y = -90.0f; y <= 90.0f; y += 90.0f) { + for (float z = -90.0f; z <= 90.0f; z += 90.0f) { + /* angles that will cause gimbal lock*/ + vec3 angles = {x, y, z}; + + /*quaternion representations for rotations*/ + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result; + + /*create the rotation quaternions using the angles and axises*/ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /*apply the rotations to a unit quaternion in xyz order*/ + glm_quat_mul(rot_x, expected, expected); + glm_quat_mul(rot_z, expected, expected); + glm_quat_mul(rot_y, expected, expected); + + /*use my function to get the quaternion*/ + glm_euler_xzy_quat(result, angles); + + ASSERTIFY(test_assert_quat_eq(result, expected)) + } + } + } + + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, euler_yxz_quat) { + for (int i = 0; i < 100; i++) { + /*random angles for testing*/ + vec3 angles; + + /*quaternion representations for rotations*/ + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result; + + test_rand_vec3(angles); + + /*create the rotation quaternions using the angles and axises*/ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /*apply the rotations to a unit quaternion in yxz order*/ + glm_quat_mul(rot_y, expected, expected); + glm_quat_mul(rot_x, expected, expected); + glm_quat_mul(rot_z, expected, expected); + + /*use my function to get the quaternion*/ + glm_euler_yxz_quat(result, angles); + + ASSERTIFY(test_assert_quat_eq(result, expected)) + } + + /*Start gimbal lock tests*/ + for (float x = -90.0f; x <= 90.0f; x += 90.0f) { + for (float y = -90.0f; y <= 90.0f; y += 90.0f) { + for (float z = -90.0f; z <= 90.0f; z += 90.0f) { + /* angles that will cause gimbal lock*/ + vec3 angles = {x, y, z}; + + /*quaternion representations for rotations*/ + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result; + + /*create the rotation quaternions using the angles and axises*/ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /*apply the rotations to a unit quaternion in xyz order*/ + glm_quat_mul(rot_y, expected, expected); + glm_quat_mul(rot_x, expected, expected); + glm_quat_mul(rot_z, expected, expected); + + /*use my function to get the quaternion*/ + glm_euler_zxy_quat(result, angles); +for (int i = 0; i < 4; i++) { + fprintf(stderr, "%f vs %f", result[i], expected[i]); +} +fprintf(stderr, "\n"); + ASSERTIFY(test_assert_quat_eq(result, expected)) + } + } + } + + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, euler_yzx_quat) { + for (int i = 0; i < 100; i++) { + /*random angles for testing*/ + vec3 angles; + + /*quaternion representations for rotations*/ + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result; + + test_rand_vec3(angles); + + /*create the rotation quaternions using the angles and axises*/ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /*apply the rotations to a unit quaternion in yzx order*/ + glm_quat_mul(rot_y, expected, expected); + glm_quat_mul(rot_z, expected, expected); + glm_quat_mul(rot_x, expected, expected); + + /*use my function to get the quaternion*/ + glm_euler_yxz_quat(result, angles); + + ASSERTIFY(test_assert_quat_eq(result, expected)) + } + + /*Start gimbal lock tests*/ + for (float x = -90.0f; x <= 90.0f; x += 90.0f) { + for (float y = -90.0f; y <= 90.0f; y += 90.0f) { + for (float z = -90.0f; z <= 90.0f; z += 90.0f) { + /* angles that will cause gimbal lock*/ + vec3 angles = {x, y, z}; + + /*quaternion representations for rotations*/ + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result; + + /*create the rotation quaternions using the angles and axises*/ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /*apply the rotations to a unit quaternion in yzx order*/ + glm_quat_mul(rot_y, expected, expected); + glm_quat_mul(rot_z, expected, expected); + glm_quat_mul(rot_x, expected, expected); + + /*use my function to get the quaternion*/ + glm_euler_zxy_quat(result, angles); +for (int i = 0; i < 4; i++) { + fprintf(stderr, "%f vs %f", result[i], expected[i]); +} +fprintf(stderr, "\n"); + ASSERTIFY(test_assert_quat_eq(result, expected)) + } + } + } + + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, euler_zxy_quat) { + for (int i = 0; i < 100; i++) { + /*random angles for testing*/ + vec3 angles; + + /*quaternion representations for rotations*/ + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result; + + test_rand_vec3(angles); + + /*create the rotation quaternions using the angles and axises*/ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /*apply the rotations to a unit quaternion in zxy order*/ + glm_quat_mul(rot_z, expected, expected); + glm_quat_mul(rot_x, expected, expected); + glm_quat_mul(rot_y, expected, expected); + + /*use my function to get the quaternion*/ + glm_euler_zxy_quat(result, angles); + + ASSERTIFY(test_assert_quat_eq(result, expected)) + } + + /*Start gimbal lock tests*/ + for (float x = -90.0f; x <= 90.0f; x += 90.0f) { + for (float y = -90.0f; y <= 90.0f; y += 90.0f) { + for (float z = -90.0f; z <= 90.0f; z += 90.0f) { + /* angles that will cause gimbal lock*/ + vec3 angles = {x, y, z}; + + /*quaternion representations for rotations*/ + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result; + + /*create the rotation quaternions using the angles and axises*/ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /*apply the rotations to a unit quaternion in zxy order*/ + glm_quat_mul(rot_z, expected, expected); + glm_quat_mul(rot_x, expected, expected); + glm_quat_mul(rot_y, expected, expected); + + /*use my function to get the quaternion*/ + glm_euler_zxy_quat(result, angles); +for (int i = 0; i < 4; i++) { + fprintf(stderr, "%f vs %f", result[i], expected[i]); +} +fprintf(stderr, "\n"); + ASSERTIFY(test_assert_quat_eq(result, expected)) + } + } + } + + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, euler_zyx_quat) { + for (int i = 0; i < 100; i++) { + /*random angles for testing*/ + vec3 angles; + + /*quaternion representations for rotations*/ + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result; + + test_rand_vec3(angles); + + /*create the rotation quaternions using the angles and axises*/ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /*apply the rotations to a unit quaternion in zyx order*/ + glm_quat_mul(rot_z, expected, expected); + glm_quat_mul(rot_y, expected, expected); + glm_quat_mul(rot_x, expected, expected); + + /*use my function to get the quaternion*/ + glm_euler_zxy_quat(result, angles); + + ASSERTIFY(test_assert_quat_eq(result, expected)) + } + + /*Start gimbal lock tests*/ + for (float x = -90.0f; x <= 90.0f; x += 90.0f) { + for (float y = -90.0f; y <= 90.0f; y += 90.0f) { + for (float z = -90.0f; z <= 90.0f; z += 90.0f) { + + /* angles that will cause gimbal lock*/ + vec3 angles = {x, y, z}; + + /*quaternion representations for rotations*/ + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result; + + /*create the rotation quaternions using the angles and axises*/ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /*apply the rotations to a unit quaternion in xyz order*/ + glm_quat_mul(rot_z, expected, expected); + glm_quat_mul(rot_y, expected, expected); + glm_quat_mul(rot_x, expected, expected); + + /*use my function to get the quaternion*/ + glm_euler_zxy_quat(result, angles); +for (int i = 0; i < 4; i++) { + fprintf(stderr, "%f vs %f", result[i], expected[i]); +} +fprintf(stderr, "\n"); + ASSERTIFY(test_assert_quat_eq(result, expected)) + } + } } - ASSERTIFY(test_assert_quat_eq(result, expected)) TEST_SUCCESS } diff --git a/test/tests.h b/test/tests.h index d25a69bd8..7e3697e87 100644 --- a/test/tests.h +++ b/test/tests.h @@ -375,6 +375,11 @@ TEST_DECLARE(glm_quat_identity_array) TEST_DECLARE(glm_quat_init) TEST_DECLARE(glm_quatv) TEST_DECLARE(glm_euler_xyz_quat) +TEST_DECLARE(glm_euler_xzy_quat) +TEST_DECLARE(glm_euler_yxz_quat) +TEST_DECLARE(glm_euler_yzx_quat) +TEST_DECLARE(glm_euler_zxy_quat) +TEST_DECLARE(glm_euler_zyx_quat) TEST_DECLARE(glm_quat) TEST_DECLARE(glm_quat_copy) TEST_DECLARE(glm_quat_norm) @@ -1353,6 +1358,11 @@ TEST_LIST { TEST_ENTRY(glm_quat_init) TEST_ENTRY(glm_quatv) TEST_ENTRY(glm_euler_xyz_quat) + TEST_ENTRY(glm_euler_xzy_quat) + TEST_ENTRY(glm_euler_yxz_quat) + TEST_ENTRY(glm_euler_yzx_quat) + TEST_ENTRY(glm_euler_zxy_quat) + TEST_ENTRY(glm_euler_zyx_quat) TEST_ENTRY(glm_quat) TEST_ENTRY(glm_quat_copy) TEST_ENTRY(glm_quat_norm) From 2f7dbad6a84d81e53ac778f6c4533095febc0c45 Mon Sep 17 00:00:00 2001 From: John Choi Date: Fri, 8 Dec 2023 12:19:09 -0600 Subject: [PATCH 04/13] finally done with tests and all euler to quaternion functions --- include/cglm/quat.h | 12 +++++------- test/src/test_quat.h | 40 ++++++++++++++-------------------------- 2 files changed, 19 insertions(+), 33 deletions(-) diff --git a/include/cglm/quat.h b/include/cglm/quat.h index d85773c9e..0e19d0c34 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -215,12 +215,10 @@ glm_euler_yxz_quat(versor q, vec3 angles) { float zc = cosf(angles[2] / 2.0f); glm_quat_init(q, - zc * xc * ys - zs * xs * yc, + zc * xs * yc - zs * xc * ys, + zc * xc * ys + zs * xs * yc, zc * xs * ys + zs * xc * yc, - zc * xs * yc + zs * xc * ys, zc * xc * yc - zs * xs * ys); - - } /*! @@ -271,9 +269,9 @@ glm_euler_zxy_quat(versor q, vec3 angles) { glm_quat_init(q, yc * xs * zc + ys * xc * zs, + -yc * xs * zs + ys * xc * zc, yc * xc * zs - ys * xs * zc, - yc * xs * zs + ys * xc * zc, - yc * xc * zc - ys * xs * zs); + yc * xc * zc + ys * xs * zs); } @@ -299,8 +297,8 @@ glm_euler_zyx_quat(versor q, vec3 angles) { glm_quat_init(q, xc * ys * zs + xs * yc * zc, + xc * ys * zc - xs * yc * zs, xc * yc * zs + xs * ys * zc, - -xc * ys * zc + xs * yc * zs, xc * yc * zc - xs * ys * zs); } diff --git a/test/src/test_quat.h b/test/src/test_quat.h index 176b055a4..31a115233 100644 --- a/test/src/test_quat.h +++ b/test/src/test_quat.h @@ -272,7 +272,7 @@ TEST_IMPL(GLM_PREFIX, euler_xzy_quat) { } TEST_IMPL(GLM_PREFIX, euler_yxz_quat) { - for (int i = 0; i < 100; i++) { + for (int i = 0; i < 1; i++) { /*random angles for testing*/ vec3 angles; @@ -336,11 +336,8 @@ TEST_IMPL(GLM_PREFIX, euler_yxz_quat) { glm_quat_mul(rot_z, expected, expected); /*use my function to get the quaternion*/ - glm_euler_zxy_quat(result, angles); -for (int i = 0; i < 4; i++) { - fprintf(stderr, "%f vs %f", result[i], expected[i]); -} -fprintf(stderr, "\n"); + glm_euler_yxz_quat(result, angles); + ASSERTIFY(test_assert_quat_eq(result, expected)) } } @@ -350,7 +347,7 @@ fprintf(stderr, "\n"); } TEST_IMPL(GLM_PREFIX, euler_yzx_quat) { - for (int i = 0; i < 100; i++) { + for (int i = 0; i < 1; i++) { /*random angles for testing*/ vec3 angles; @@ -379,7 +376,7 @@ TEST_IMPL(GLM_PREFIX, euler_yzx_quat) { glm_quat_mul(rot_x, expected, expected); /*use my function to get the quaternion*/ - glm_euler_yxz_quat(result, angles); + glm_euler_yzx_quat(result, angles); ASSERTIFY(test_assert_quat_eq(result, expected)) } @@ -414,11 +411,8 @@ TEST_IMPL(GLM_PREFIX, euler_yzx_quat) { glm_quat_mul(rot_x, expected, expected); /*use my function to get the quaternion*/ - glm_euler_zxy_quat(result, angles); -for (int i = 0; i < 4; i++) { - fprintf(stderr, "%f vs %f", result[i], expected[i]); -} -fprintf(stderr, "\n"); + glm_euler_yzx_quat(result, angles); + ASSERTIFY(test_assert_quat_eq(result, expected)) } } @@ -428,7 +422,7 @@ fprintf(stderr, "\n"); } TEST_IMPL(GLM_PREFIX, euler_zxy_quat) { - for (int i = 0; i < 100; i++) { + for (int i = 0; i < 1; i++) { /*random angles for testing*/ vec3 angles; @@ -493,10 +487,7 @@ TEST_IMPL(GLM_PREFIX, euler_zxy_quat) { /*use my function to get the quaternion*/ glm_euler_zxy_quat(result, angles); -for (int i = 0; i < 4; i++) { - fprintf(stderr, "%f vs %f", result[i], expected[i]); -} -fprintf(stderr, "\n"); + ASSERTIFY(test_assert_quat_eq(result, expected)) } } @@ -506,7 +497,7 @@ fprintf(stderr, "\n"); } TEST_IMPL(GLM_PREFIX, euler_zyx_quat) { - for (int i = 0; i < 100; i++) { + for (int i = 0; i < 1; i++) { /*random angles for testing*/ vec3 angles; @@ -535,7 +526,7 @@ TEST_IMPL(GLM_PREFIX, euler_zyx_quat) { glm_quat_mul(rot_x, expected, expected); /*use my function to get the quaternion*/ - glm_euler_zxy_quat(result, angles); + glm_euler_zyx_quat(result, angles); ASSERTIFY(test_assert_quat_eq(result, expected)) } @@ -565,17 +556,14 @@ TEST_IMPL(GLM_PREFIX, euler_zyx_quat) { glm_quatv(rot_y, angles[1], axis_y); glm_quatv(rot_z, angles[2], axis_z); - /*apply the rotations to a unit quaternion in xyz order*/ + /*apply the rotations to a unit quaternion in zyx order*/ glm_quat_mul(rot_z, expected, expected); glm_quat_mul(rot_y, expected, expected); glm_quat_mul(rot_x, expected, expected); /*use my function to get the quaternion*/ - glm_euler_zxy_quat(result, angles); -for (int i = 0; i < 4; i++) { - fprintf(stderr, "%f vs %f", result[i], expected[i]); -} -fprintf(stderr, "\n"); + glm_euler_zyx_quat(result, angles); + ASSERTIFY(test_assert_quat_eq(result, expected)) } } From 4ee6aea037d4006e0832ab87827eb41af6ef06f5 Mon Sep 17 00:00:00 2001 From: John Choi Date: Fri, 8 Dec 2023 13:05:53 -0600 Subject: [PATCH 05/13] made quat struct and also exported it --- include/cglm/call/quat.h | 24 ++++++++++ include/cglm/quat.h | 8 +++- include/cglm/struct/quat.h | 97 ++++++++++++++++++++++++++++++++++++++ src/quat.c | 36 ++++++++++++++ test/src/test_quat.h | 39 ++++++++++++++- 5 files changed, 200 insertions(+), 4 deletions(-) diff --git a/include/cglm/call/quat.h b/include/cglm/call/quat.h index 1fe519512..f24dc5967 100644 --- a/include/cglm/call/quat.h +++ b/include/cglm/call/quat.h @@ -25,6 +25,30 @@ CGLM_EXPORT void glmc_quat_init(versor q, float x, float y, float z, float w); +CGLM_EXPORT +void +glmc_euler_xyz_quat(versor q, vec3 angles); + +CGLM_EXPORT +void +glmc_euler_xzy_quat(versor q, vec3 angles); + +CGLM_EXPORT +void +glmc_euler_yxz_quat(versor q, vec3 angles); + +CGLM_EXPORT +void +glmc_euler_yzx_quat(versor q, vec3 angles); + +CGLM_EXPORT +void +glmc_euler_zxy_quat(versor q, vec3 angles); + +CGLM_EXPORT +void +glmc_euler_zyx_quat(versor q, vec3 angles); + CGLM_EXPORT void glmc_quat(versor q, float angle, float x, float y, float z); diff --git a/include/cglm/quat.h b/include/cglm/quat.h index 0e19d0c34..e8580e79d 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -13,6 +13,12 @@ Functions: CGLM_INLINE void glm_quat_identity(versor q); CGLM_INLINE void glm_quat_init(versor q, float x, float y, float z, float w); + CGLM_INLINE void glm_euler_xyz_quat(versor q, vec3 angles); + CGLM_INLINE void glm_euler_xzy_quat(versor q, vec3 angles); + CGLM_INLINE void glm_euler_yxz_quat(versor q, vec3 angles); + CGLM_INLINE void glm_euler_yzx_quat(versor q, vec3 angles); + CGLM_INLINE void glm_euler_zxy_quat(versor q, vec3 angles); + CGLM_INLINE void glm_euler_zyx_quat(versor q, vec3 angles); 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 axis); CGLM_INLINE void glm_quat_copy(versor q, versor dest); @@ -139,8 +145,6 @@ glm_quat_init(versor q, float x, float y, float z, float w) { q[3] = w; } -//TODO: telephone001's eulertoquat - /*! * @brief creates NEW quaternion using rotation angles and does * rotations in x y z order (roll pitch yaw) diff --git a/include/cglm/struct/quat.h b/include/cglm/struct/quat.h index a37cdc561..23849119a 100644 --- a/include/cglm/struct/quat.h +++ b/include/cglm/struct/quat.h @@ -14,6 +14,12 @@ CGLM_INLINE versors glms_quat_identity(void) CGLM_INLINE void glms_quat_identity_array(versor *q, size_t count) CGLM_INLINE versors glms_quat_init(float x, float y, float z, float w) + CGLM_INLINE versors glms_euler_xyz_quat(versors q, vec3s angles) + CGLM_INLINE versors glms_euler_xzy_quat(versors q, vec3s angles) + CGLM_INLINE versors glms_euler_yxz_quat(versors q, vec3s angles) + CGLM_INLINE versors glms_euler_yzx_quat(versors q, vec3s angles) + CGLM_INLINE versors glms_euler_zxy_quat(versors q, vec3s angles) + CGLM_INLINE versors glms_euler_zyx_quat(versors q, vec3s angles) CGLM_INLINE versors glms_quatv(float angle, vec3s axis) CGLM_INLINE versors glms_quat(float angle, float x, float y, float z) CGLM_INLINE versors glms_quat_from_vecs(vec3s a, vec3s b) @@ -120,6 +126,97 @@ glms_quat_(init)(float x, float y, float z, float w) { return dest; } +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in x y z order (roll pitch yaw) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +versors +glms_euler_xyz_quat(versors q, vec3s angles) { + versors dest; + glm_euler_xyz_quat(dest.raw, angles.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in x z y order (roll yaw pitch) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +versors +glms_euler_xzy_quat(versors q, vec3s angles) { + versors dest; + glm_euler_xzy_quat(dest.raw, angles.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in y x z order (pitch roll yaw) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +versors +glms_euler_yxz_quat(versors q, vec3s angles) { + versors dest; + glm_euler_yxz_quat(dest.raw, angles.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in y z x order (pitch yaw roll) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +versors +glms_euler_yzx_quat(versors q, vec3s angles) { + versors dest; + glm_euler_yzx_quat(dest.raw, angles.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in z x y order (yaw roll pitch) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +versors +glms_euler_zxy_quat(versors q, vec3s angles) { + versors dest; + glm_euler_zxy_quat(dest.raw, angles.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in z y x order (yaw pitch roll) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +versors +glms_euler_zyx_quat(versors q, vec3s angles) { + versors dest; + glm_euler_zyx_quat(dest.raw, angles.raw); + return dest; +} + + /*! * @brief creates NEW quaternion with axis vector * diff --git a/src/quat.c b/src/quat.c index 17969397f..a393789d3 100644 --- a/src/quat.c +++ b/src/quat.c @@ -26,6 +26,42 @@ glmc_quat_init(versor q, float x, float y, float z, float w) { glm_quat_init(q, x, y, z, w); } +CGLM_EXPORT +void +glmc_euler_xyz_quat(versor q, vec3 angles) { + glm_euler_xyz_quat(q, angles); +} + +CGLM_EXPORT +void +glmc_euler_xzy_quat(versor q, vec3 angles) { + glm_euler_xzy_quat(q, angles); +} + +CGLM_EXPORT +void +glmc_euler_yxz_quat(versor q, vec3 angles) { + glm_euler_yxz_quat(q, angles); +} + +CGLM_EXPORT +void +glmc_euler_yzx_quat(versor q, vec3 angles) { + glm_euler_yzx_quat(q, angles); +} + +CGLM_EXPORT +void +glmc_euler_zxy_quat(versor q, vec3 angles) { + glm_euler_zxy_quat(q, angles); +} + +CGLM_EXPORT +void +glmc_euler_zyx_quat(versor q, vec3 angles) { + glm_euler_zyx_quat(q, angles); +} + CGLM_EXPORT void glmc_quat(versor q, float angle, float x, float y, float z) { diff --git a/test/src/test_quat.h b/test/src/test_quat.h index 31a115233..6a26756c6 100644 --- a/test/src/test_quat.h +++ b/test/src/test_quat.h @@ -121,7 +121,6 @@ TEST_IMPL(GLM_PREFIX, quatv) { TEST_SUCCESS } -// telephone001 changes (remove comment when done) TODO TEST_IMPL(GLM_PREFIX, euler_xyz_quat) { for (int i = 0; i < 100; i++) { /*random angles for testing*/ @@ -154,8 +153,12 @@ TEST_IMPL(GLM_PREFIX, euler_xyz_quat) { /*use my function to get the quaternion*/ glm_euler_xyz_quat(result, angles); + /*verify if the magnitude of the quaternion stays 1*/ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + ASSERTIFY(test_assert_quat_eq(result, expected)) } + /*Start gimbal lock tests*/ for (float x = -90.0f; x <= 90.0f; x += 90.0f) { @@ -189,6 +192,9 @@ TEST_IMPL(GLM_PREFIX, euler_xyz_quat) { /*use my function to get the quaternion*/ glm_euler_xyz_quat(result, angles); + /*verify if the magnitude of the quaternion stays 1*/ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + ASSERTIFY(test_assert_quat_eq(result, expected)) } } @@ -228,6 +234,9 @@ TEST_IMPL(GLM_PREFIX, euler_xzy_quat) { /*use my function to get the quaternion*/ glm_euler_xzy_quat(result, angles); + /*verify if the magnitude of the quaternion stays 1*/ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + ASSERTIFY(test_assert_quat_eq(result, expected)) } @@ -263,6 +272,9 @@ TEST_IMPL(GLM_PREFIX, euler_xzy_quat) { /*use my function to get the quaternion*/ glm_euler_xzy_quat(result, angles); + /*verify if the magnitude of the quaternion stays 1*/ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + ASSERTIFY(test_assert_quat_eq(result, expected)) } } @@ -303,6 +315,9 @@ TEST_IMPL(GLM_PREFIX, euler_yxz_quat) { /*use my function to get the quaternion*/ glm_euler_yxz_quat(result, angles); + /*verify if the magnitude of the quaternion stays 1*/ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + ASSERTIFY(test_assert_quat_eq(result, expected)) } @@ -338,6 +353,9 @@ TEST_IMPL(GLM_PREFIX, euler_yxz_quat) { /*use my function to get the quaternion*/ glm_euler_yxz_quat(result, angles); + /*verify if the magnitude of the quaternion stays 1*/ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + ASSERTIFY(test_assert_quat_eq(result, expected)) } } @@ -378,6 +396,9 @@ TEST_IMPL(GLM_PREFIX, euler_yzx_quat) { /*use my function to get the quaternion*/ glm_euler_yzx_quat(result, angles); + /*verify if the magnitude of the quaternion stays 1*/ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + ASSERTIFY(test_assert_quat_eq(result, expected)) } @@ -413,6 +434,9 @@ TEST_IMPL(GLM_PREFIX, euler_yzx_quat) { /*use my function to get the quaternion*/ glm_euler_yzx_quat(result, angles); + /*verify if the magnitude of the quaternion stays 1*/ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + ASSERTIFY(test_assert_quat_eq(result, expected)) } } @@ -453,6 +477,9 @@ TEST_IMPL(GLM_PREFIX, euler_zxy_quat) { /*use my function to get the quaternion*/ glm_euler_zxy_quat(result, angles); + /*verify if the magnitude of the quaternion stays 1*/ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + ASSERTIFY(test_assert_quat_eq(result, expected)) } @@ -488,6 +515,9 @@ TEST_IMPL(GLM_PREFIX, euler_zxy_quat) { /*use my function to get the quaternion*/ glm_euler_zxy_quat(result, angles); + /*verify if the magnitude of the quaternion stays 1*/ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + ASSERTIFY(test_assert_quat_eq(result, expected)) } } @@ -528,6 +558,9 @@ TEST_IMPL(GLM_PREFIX, euler_zyx_quat) { /*use my function to get the quaternion*/ glm_euler_zyx_quat(result, angles); + /*verify if the magnitude of the quaternion stays 1*/ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + ASSERTIFY(test_assert_quat_eq(result, expected)) } @@ -564,6 +597,9 @@ TEST_IMPL(GLM_PREFIX, euler_zyx_quat) { /*use my function to get the quaternion*/ glm_euler_zyx_quat(result, angles); + /*verify if the magnitude of the quaternion stays 1*/ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + ASSERTIFY(test_assert_quat_eq(result, expected)) } } @@ -572,7 +608,6 @@ TEST_IMPL(GLM_PREFIX, euler_zyx_quat) { TEST_SUCCESS } - TEST_IMPL(GLM_PREFIX, quat) { versor q1 = {1.0f, 2.0f, 3.0f, 4.0f}; vec3 v1, v2; From ec3796973e7099de62c4526f224a75f0bbf9bc59 Mon Sep 17 00:00:00 2001 From: John Choi Date: Fri, 8 Dec 2023 14:15:49 -0600 Subject: [PATCH 06/13] finished but trying to figure out why its not running in wasm --- include/cglm/quat.h | 2 -- test/src/test_quat.h | 46 ++++++++++++++++++++++---------------------- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/include/cglm/quat.h b/include/cglm/quat.h index e8580e79d..02e0b465b 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -307,8 +307,6 @@ glm_euler_zyx_quat(versor q, vec3 angles) { } - - /*! * @brief creates NEW quaternion with axis vector * diff --git a/test/src/test_quat.h b/test/src/test_quat.h index 6a26756c6..8a9f6cb96 100644 --- a/test/src/test_quat.h +++ b/test/src/test_quat.h @@ -102,25 +102,6 @@ TEST_IMPL(GLM_PREFIX, quat_init) { TEST_SUCCESS } -TEST_IMPL(GLM_PREFIX, quatv) { - versor q1 = {1.0f, 2.0f, 3.0f, 4.0f}; - vec3 v1, v2; - float a1; - - test_rand_vec3(v1); - GLM(quatv)(q1, glm_rad(60.0f), v1); - - glm_quat_axis(q1, v2); - a1 = glm_quat_angle(q1); - - ASSERT(test_eq(a1, glm_rad(60.0f))) - - glm_vec3_normalize(v1); - ASSERTIFY(test_assert_vec3_eq(v1, v2)) - - TEST_SUCCESS -} - TEST_IMPL(GLM_PREFIX, euler_xyz_quat) { for (int i = 0; i < 100; i++) { /*random angles for testing*/ @@ -284,7 +265,7 @@ TEST_IMPL(GLM_PREFIX, euler_xzy_quat) { } TEST_IMPL(GLM_PREFIX, euler_yxz_quat) { - for (int i = 0; i < 1; i++) { + for (int i = 0; i < 100; i++) { /*random angles for testing*/ vec3 angles; @@ -365,7 +346,7 @@ TEST_IMPL(GLM_PREFIX, euler_yxz_quat) { } TEST_IMPL(GLM_PREFIX, euler_yzx_quat) { - for (int i = 0; i < 1; i++) { + for (int i = 0; i < 100; i++) { /*random angles for testing*/ vec3 angles; @@ -446,7 +427,7 @@ TEST_IMPL(GLM_PREFIX, euler_yzx_quat) { } TEST_IMPL(GLM_PREFIX, euler_zxy_quat) { - for (int i = 0; i < 1; i++) { + for (int i = 0; i < 100; i++) { /*random angles for testing*/ vec3 angles; @@ -527,7 +508,7 @@ TEST_IMPL(GLM_PREFIX, euler_zxy_quat) { } TEST_IMPL(GLM_PREFIX, euler_zyx_quat) { - for (int i = 0; i < 1; i++) { + for (int i = 0; i < 100; i++) { /*random angles for testing*/ vec3 angles; @@ -608,6 +589,25 @@ TEST_IMPL(GLM_PREFIX, euler_zyx_quat) { TEST_SUCCESS } +TEST_IMPL(GLM_PREFIX, quatv) { + versor q1 = {1.0f, 2.0f, 3.0f, 4.0f}; + vec3 v1, v2; + float a1; + + test_rand_vec3(v1); + GLM(quatv)(q1, glm_rad(60.0f), v1); + + glm_quat_axis(q1, v2); + a1 = glm_quat_angle(q1); + + ASSERT(test_eq(a1, glm_rad(60.0f))) + + glm_vec3_normalize(v1); + ASSERTIFY(test_assert_vec3_eq(v1, v2)) + + TEST_SUCCESS +} + TEST_IMPL(GLM_PREFIX, quat) { versor q1 = {1.0f, 2.0f, 3.0f, 4.0f}; vec3 v1, v2; From 666d692dfb2a3f1b937d82976f87b5dff6961f91 Mon Sep 17 00:00:00 2001 From: John Choi Date: Fri, 8 Dec 2023 23:06:36 -0600 Subject: [PATCH 07/13] fixed the bug with the tester. Its weird that the broken tester worked on my computer --- include/cglm/euler.h | 2 + test/src/test_quat.h | 125 ++++++++++++++++++++++++++++++------------- 2 files changed, 90 insertions(+), 37 deletions(-) diff --git a/include/cglm/euler.h b/include/cglm/euler.h index 725a20519..9f921f296 100644 --- a/include/cglm/euler.h +++ b/include/cglm/euler.h @@ -448,4 +448,6 @@ glm_euler_by_order(vec3 angles, glm_euler_seq ord, mat4 dest) { dest[3][3] = 1.0f; } + + #endif /* cglm_euler_h */ diff --git a/test/src/test_quat.h b/test/src/test_quat.h index 8a9f6cb96..c167ca174 100644 --- a/test/src/test_quat.h +++ b/test/src/test_quat.h @@ -127,9 +127,13 @@ TEST_IMPL(GLM_PREFIX, euler_xyz_quat) { glm_quatv(rot_z, angles[2], axis_z); /*apply the rotations to a unit quaternion in xyz order*/ - glm_quat_mul(rot_x, expected, expected); - glm_quat_mul(rot_y, expected, expected); - glm_quat_mul(rot_z, expected, expected); + versor tmp; + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_x, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_y, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_z, tmp, expected); /*use my function to get the quaternion*/ glm_euler_xyz_quat(result, angles); @@ -166,9 +170,13 @@ TEST_IMPL(GLM_PREFIX, euler_xyz_quat) { glm_quatv(rot_z, angles[2], axis_z); /*apply the rotations to a unit quaternion in xyz order*/ - glm_quat_mul(rot_x, expected, expected); - glm_quat_mul(rot_y, expected, expected); - glm_quat_mul(rot_z, expected, expected); + versor tmp; + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_x, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_y, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_z, tmp, expected); /*use my function to get the quaternion*/ glm_euler_xyz_quat(result, angles); @@ -208,9 +216,13 @@ TEST_IMPL(GLM_PREFIX, euler_xzy_quat) { glm_quatv(rot_z, angles[2], axis_z); /*apply the rotations to a unit quaternion in xzy order*/ - glm_quat_mul(rot_x, expected, expected); - glm_quat_mul(rot_z, expected, expected); - glm_quat_mul(rot_y, expected, expected); + versor tmp; + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_x, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_z, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_y, tmp, expected); /*use my function to get the quaternion*/ glm_euler_xzy_quat(result, angles); @@ -246,9 +258,13 @@ TEST_IMPL(GLM_PREFIX, euler_xzy_quat) { glm_quatv(rot_z, angles[2], axis_z); /*apply the rotations to a unit quaternion in xyz order*/ - glm_quat_mul(rot_x, expected, expected); - glm_quat_mul(rot_z, expected, expected); - glm_quat_mul(rot_y, expected, expected); + versor tmp; + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_x, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_z, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_y, tmp, expected); /*use my function to get the quaternion*/ glm_euler_xzy_quat(result, angles); @@ -289,9 +305,13 @@ TEST_IMPL(GLM_PREFIX, euler_yxz_quat) { glm_quatv(rot_z, angles[2], axis_z); /*apply the rotations to a unit quaternion in yxz order*/ - glm_quat_mul(rot_y, expected, expected); - glm_quat_mul(rot_x, expected, expected); - glm_quat_mul(rot_z, expected, expected); + versor tmp; + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_y, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_x, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_z, tmp, expected); /*use my function to get the quaternion*/ glm_euler_yxz_quat(result, angles); @@ -326,10 +346,14 @@ TEST_IMPL(GLM_PREFIX, euler_yxz_quat) { glm_quatv(rot_y, angles[1], axis_y); glm_quatv(rot_z, angles[2], axis_z); - /*apply the rotations to a unit quaternion in xyz order*/ - glm_quat_mul(rot_y, expected, expected); - glm_quat_mul(rot_x, expected, expected); - glm_quat_mul(rot_z, expected, expected); + /*apply the rotations to a unit quaternion in yxz order*/ + versor tmp; + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_y, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_x, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_z, tmp, expected); /*use my function to get the quaternion*/ glm_euler_yxz_quat(result, angles); @@ -370,9 +394,13 @@ TEST_IMPL(GLM_PREFIX, euler_yzx_quat) { glm_quatv(rot_z, angles[2], axis_z); /*apply the rotations to a unit quaternion in yzx order*/ - glm_quat_mul(rot_y, expected, expected); - glm_quat_mul(rot_z, expected, expected); - glm_quat_mul(rot_x, expected, expected); + versor tmp; + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_y, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_z, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_x, tmp, expected); /*use my function to get the quaternion*/ glm_euler_yzx_quat(result, angles); @@ -408,9 +436,13 @@ TEST_IMPL(GLM_PREFIX, euler_yzx_quat) { glm_quatv(rot_z, angles[2], axis_z); /*apply the rotations to a unit quaternion in yzx order*/ - glm_quat_mul(rot_y, expected, expected); - glm_quat_mul(rot_z, expected, expected); - glm_quat_mul(rot_x, expected, expected); + versor tmp; + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_y, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_z, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_x, tmp, expected); /*use my function to get the quaternion*/ glm_euler_yzx_quat(result, angles); @@ -451,9 +483,13 @@ TEST_IMPL(GLM_PREFIX, euler_zxy_quat) { glm_quatv(rot_z, angles[2], axis_z); /*apply the rotations to a unit quaternion in zxy order*/ - glm_quat_mul(rot_z, expected, expected); - glm_quat_mul(rot_x, expected, expected); - glm_quat_mul(rot_y, expected, expected); + versor tmp; + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_z, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_x, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_y, tmp, expected); /*use my function to get the quaternion*/ glm_euler_zxy_quat(result, angles); @@ -489,9 +525,14 @@ TEST_IMPL(GLM_PREFIX, euler_zxy_quat) { glm_quatv(rot_z, angles[2], axis_z); /*apply the rotations to a unit quaternion in zxy order*/ - glm_quat_mul(rot_z, expected, expected); - glm_quat_mul(rot_x, expected, expected); - glm_quat_mul(rot_y, expected, expected); + versor tmp; + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_z, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_x, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_y, tmp, expected); + /*use my function to get the quaternion*/ glm_euler_zxy_quat(result, angles); @@ -532,9 +573,14 @@ TEST_IMPL(GLM_PREFIX, euler_zyx_quat) { glm_quatv(rot_z, angles[2], axis_z); /*apply the rotations to a unit quaternion in zyx order*/ - glm_quat_mul(rot_z, expected, expected); - glm_quat_mul(rot_y, expected, expected); - glm_quat_mul(rot_x, expected, expected); + versor tmp; + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_z, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_y, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_x, tmp, expected); + /*use my function to get the quaternion*/ glm_euler_zyx_quat(result, angles); @@ -571,9 +617,14 @@ TEST_IMPL(GLM_PREFIX, euler_zyx_quat) { glm_quatv(rot_z, angles[2], axis_z); /*apply the rotations to a unit quaternion in zyx order*/ - glm_quat_mul(rot_z, expected, expected); - glm_quat_mul(rot_y, expected, expected); - glm_quat_mul(rot_x, expected, expected); + versor tmp; + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_z, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_y, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_x, tmp, expected); + /*use my function to get the quaternion*/ glm_euler_zyx_quat(result, angles); From 036fd4848bbbda8fec99e316cf63ec17f28cc41a Mon Sep 17 00:00:00 2001 From: John Choi Date: Sat, 9 Dec 2023 00:38:38 -0600 Subject: [PATCH 08/13] moved all my stuff to euler because it fits there better. Also, had to move my tests into a single euler test because it wouldn't work outside that one test. Maybe later I will create test_euler.h like how test_quat.h works --- include/cglm/call/euler.h | 25 ++ include/cglm/call/quat.h | 24 -- include/cglm/euler.h | 168 +++++++++++ include/cglm/quat.h | 168 ----------- include/cglm/struct/euler.h | 97 +++++++ include/cglm/struct/quat.h | 97 ------- src/euler.c | 37 +++ src/quat.c | 36 --- test/src/test_euler.c | 548 ++++++++++++++++++++++++++++++++++++ test/src/test_quat.h | 538 ----------------------------------- test/tests.h | 21 +- 11 files changed, 883 insertions(+), 876 deletions(-) diff --git a/include/cglm/call/euler.h b/include/cglm/call/euler.h index 2de68fb88..52dd1ef34 100644 --- a/include/cglm/call/euler.h +++ b/include/cglm/call/euler.h @@ -49,6 +49,31 @@ CGLM_EXPORT void glmc_euler_by_order(vec3 angles, glm_euler_seq axis, mat4 dest); +CGLM_EXPORT +void +glmc_euler_xyz_quat(versor q, vec3 angles); + +CGLM_EXPORT +void +glmc_euler_xzy_quat(versor q, vec3 angles); + +CGLM_EXPORT +void +glmc_euler_yxz_quat(versor q, vec3 angles); + +CGLM_EXPORT +void +glmc_euler_yzx_quat(versor q, vec3 angles); + +CGLM_EXPORT +void +glmc_euler_zxy_quat(versor q, vec3 angles); + +CGLM_EXPORT +void +glmc_euler_zyx_quat(versor q, vec3 angles); + + #ifdef __cplusplus } #endif diff --git a/include/cglm/call/quat.h b/include/cglm/call/quat.h index f24dc5967..1fe519512 100644 --- a/include/cglm/call/quat.h +++ b/include/cglm/call/quat.h @@ -25,30 +25,6 @@ CGLM_EXPORT void glmc_quat_init(versor q, float x, float y, float z, float w); -CGLM_EXPORT -void -glmc_euler_xyz_quat(versor q, vec3 angles); - -CGLM_EXPORT -void -glmc_euler_xzy_quat(versor q, vec3 angles); - -CGLM_EXPORT -void -glmc_euler_yxz_quat(versor q, vec3 angles); - -CGLM_EXPORT -void -glmc_euler_yzx_quat(versor q, vec3 angles); - -CGLM_EXPORT -void -glmc_euler_zxy_quat(versor q, vec3 angles); - -CGLM_EXPORT -void -glmc_euler_zyx_quat(versor q, vec3 angles); - CGLM_EXPORT void glmc_quat(versor q, float angle, float x, float y, float z); diff --git a/include/cglm/euler.h b/include/cglm/euler.h index 9f921f296..9efbaa1b7 100644 --- a/include/cglm/euler.h +++ b/include/cglm/euler.h @@ -30,6 +30,12 @@ CGLM_INLINE void glm_euler_by_order(vec3 angles, glm_euler_seq ord, mat4 dest); + CGLM_INLINE void glm_euler_xyz_quat(versor q, vec3 angles); + CGLM_INLINE void glm_euler_xzy_quat(versor q, vec3 angles); + CGLM_INLINE void glm_euler_yxz_quat(versor q, vec3 angles); + CGLM_INLINE void glm_euler_yzx_quat(versor q, vec3 angles); + CGLM_INLINE void glm_euler_zxy_quat(versor q, vec3 angles); + CGLM_INLINE void glm_euler_zyx_quat(versor q, vec3 angles); */ #ifndef cglm_euler_h @@ -449,5 +455,167 @@ glm_euler_by_order(vec3 angles, glm_euler_seq ord, mat4 dest) { } +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in x y z order (roll pitch yaw) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +void +glm_euler_xyz_quat(versor q, vec3 angles) { + float xs = sinf(angles[0] / 2.0f); + float xc = cosf(angles[0] / 2.0f); + + float ys = sinf(angles[1] / 2.0f); + float yc = cosf(angles[1] / 2.0f); + + float zs = sinf(angles[2] / 2.0f); + float zc = cosf(angles[2] / 2.0f); + + + glm_quat_init(q, + zc * yc * xs - zs * ys * xc, + zc * ys * xc + zs * yc * xs, + -zc * ys * xs + zs * yc * xc, + zc * yc * xc + zs * ys * xs); +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in x z y order (roll yaw pitch) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +void +glm_euler_xzy_quat(versor q, vec3 angles) { + float xs = sinf(angles[0] / 2.0f); + float xc = cosf(angles[0] / 2.0f); + + float ys = sinf(angles[1] / 2.0f); + float yc = cosf(angles[1] / 2.0f); + + float zs = sinf(angles[2] / 2.0f); + float zc = cosf(angles[2] / 2.0f); + + glm_quat_init(q, + yc * zc * xs + ys * zs * xc, + yc * zs * xs + ys * zc * xc, + yc * zs * xc - ys * zc * xs, + yc * zc * xc - ys * zs * xs); + +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in y x z order (pitch roll yaw) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +void +glm_euler_yxz_quat(versor q, vec3 angles) { + float xs = sinf(angles[0] / 2.0f); + float xc = cosf(angles[0] / 2.0f); + + float ys = sinf(angles[1] / 2.0f); + float yc = cosf(angles[1] / 2.0f); + + float zs = sinf(angles[2] / 2.0f); + float zc = cosf(angles[2] / 2.0f); + + glm_quat_init(q, + zc * xs * yc - zs * xc * ys, + zc * xc * ys + zs * xs * yc, + zc * xs * ys + zs * xc * yc, + zc * xc * yc - zs * xs * ys); +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in y z x order (pitch yaw roll) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +void +glm_euler_yzx_quat(versor q, vec3 angles) { + float xs = sinf(angles[0] / 2.0f); + float xc = cosf(angles[0] / 2.0f); + + float ys = sinf(angles[1] / 2.0f); + float yc = cosf(angles[1] / 2.0f); + + float zs = sinf(angles[2] / 2.0f); + float zc = cosf(angles[2] / 2.0f); + + glm_quat_init(q, + -xc * zs * ys + xs * zc * yc, + xc * zc * ys - xs * zs * yc, + xc * zs * yc + xs * zc * ys, + xc * zc * yc + xs * zs * ys); + +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in z x y order (yaw roll pitch) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +void +glm_euler_zxy_quat(versor q, vec3 angles) { + float xs = sinf(angles[0] / 2.0f); + float xc = cosf(angles[0] / 2.0f); + + float ys = sinf(angles[1] / 2.0f); + float yc = cosf(angles[1] / 2.0f); + + float zs = sinf(angles[2] / 2.0f); + float zc = cosf(angles[2] / 2.0f); + + glm_quat_init(q, + yc * xs * zc + ys * xc * zs, + -yc * xs * zs + ys * xc * zc, + yc * xc * zs - ys * xs * zc, + yc * xc * zc + ys * xs * zs); + + +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in z y x order (yaw pitch roll) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +void +glm_euler_zyx_quat(versor q, vec3 angles) { + float xs = sinf(angles[0] / 2.0f); + float xc = cosf(angles[0] / 2.0f); + + float ys = sinf(angles[1] / 2.0f); + float yc = cosf(angles[1] / 2.0f); + + float zs = sinf(angles[2] / 2.0f); + float zc = cosf(angles[2] / 2.0f); + + glm_quat_init(q, + xc * ys * zs + xs * yc * zc, + xc * ys * zc - xs * yc * zs, + xc * yc * zs + xs * ys * zc, + xc * yc * zc - xs * ys * zs); + +} + #endif /* cglm_euler_h */ diff --git a/include/cglm/quat.h b/include/cglm/quat.h index 02e0b465b..ab0c5902b 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -13,12 +13,6 @@ Functions: CGLM_INLINE void glm_quat_identity(versor q); CGLM_INLINE void glm_quat_init(versor q, float x, float y, float z, float w); - CGLM_INLINE void glm_euler_xyz_quat(versor q, vec3 angles); - CGLM_INLINE void glm_euler_xzy_quat(versor q, vec3 angles); - CGLM_INLINE void glm_euler_yxz_quat(versor q, vec3 angles); - CGLM_INLINE void glm_euler_yzx_quat(versor q, vec3 angles); - CGLM_INLINE void glm_euler_zxy_quat(versor q, vec3 angles); - CGLM_INLINE void glm_euler_zyx_quat(versor q, vec3 angles); 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 axis); CGLM_INLINE void glm_quat_copy(versor q, versor dest); @@ -145,168 +139,6 @@ glm_quat_init(versor q, float x, float y, float z, float w) { q[3] = w; } -/*! - * @brief creates NEW quaternion using rotation angles and does - * rotations in x y z order (roll pitch yaw) - * - * @param[out] q quaternion - * @param[in] angle angles x y z (radians) - */ -CGLM_INLINE -void -glm_euler_xyz_quat(versor q, vec3 angles) { - float xs = sinf(angles[0] / 2.0f); - float xc = cosf(angles[0] / 2.0f); - - float ys = sinf(angles[1] / 2.0f); - float yc = cosf(angles[1] / 2.0f); - - float zs = sinf(angles[2] / 2.0f); - float zc = cosf(angles[2] / 2.0f); - - - glm_quat_init(q, - zc * yc * xs - zs * ys * xc, - zc * ys * xc + zs * yc * xs, - -zc * ys * xs + zs * yc * xc, - zc * yc * xc + zs * ys * xs); -} - -/*! - * @brief creates NEW quaternion using rotation angles and does - * rotations in x z y order (roll yaw pitch) - * - * @param[out] q quaternion - * @param[in] angle angles x y z (radians) - */ -CGLM_INLINE -void -glm_euler_xzy_quat(versor q, vec3 angles) { - float xs = sinf(angles[0] / 2.0f); - float xc = cosf(angles[0] / 2.0f); - - float ys = sinf(angles[1] / 2.0f); - float yc = cosf(angles[1] / 2.0f); - - float zs = sinf(angles[2] / 2.0f); - float zc = cosf(angles[2] / 2.0f); - - glm_quat_init(q, - yc * zc * xs + ys * zs * xc, - yc * zs * xs + ys * zc * xc, - yc * zs * xc - ys * zc * xs, - yc * zc * xc - ys * zs * xs); - -} - -/*! - * @brief creates NEW quaternion using rotation angles and does - * rotations in y x z order (pitch roll yaw) - * - * @param[out] q quaternion - * @param[in] angle angles x y z (radians) - */ -CGLM_INLINE -void -glm_euler_yxz_quat(versor q, vec3 angles) { - float xs = sinf(angles[0] / 2.0f); - float xc = cosf(angles[0] / 2.0f); - - float ys = sinf(angles[1] / 2.0f); - float yc = cosf(angles[1] / 2.0f); - - float zs = sinf(angles[2] / 2.0f); - float zc = cosf(angles[2] / 2.0f); - - glm_quat_init(q, - zc * xs * yc - zs * xc * ys, - zc * xc * ys + zs * xs * yc, - zc * xs * ys + zs * xc * yc, - zc * xc * yc - zs * xs * ys); -} - -/*! - * @brief creates NEW quaternion using rotation angles and does - * rotations in y z x order (pitch yaw roll) - * - * @param[out] q quaternion - * @param[in] angle angles x y z (radians) - */ -CGLM_INLINE -void -glm_euler_yzx_quat(versor q, vec3 angles) { - float xs = sinf(angles[0] / 2.0f); - float xc = cosf(angles[0] / 2.0f); - - float ys = sinf(angles[1] / 2.0f); - float yc = cosf(angles[1] / 2.0f); - - float zs = sinf(angles[2] / 2.0f); - float zc = cosf(angles[2] / 2.0f); - - glm_quat_init(q, - -xc * zs * ys + xs * zc * yc, - xc * zc * ys - xs * zs * yc, - xc * zs * yc + xs * zc * ys, - xc * zc * yc + xs * zs * ys); - -} - -/*! - * @brief creates NEW quaternion using rotation angles and does - * rotations in z x y order (yaw roll pitch) - * - * @param[out] q quaternion - * @param[in] angle angles x y z (radians) - */ -CGLM_INLINE -void -glm_euler_zxy_quat(versor q, vec3 angles) { - float xs = sinf(angles[0] / 2.0f); - float xc = cosf(angles[0] / 2.0f); - - float ys = sinf(angles[1] / 2.0f); - float yc = cosf(angles[1] / 2.0f); - - float zs = sinf(angles[2] / 2.0f); - float zc = cosf(angles[2] / 2.0f); - - glm_quat_init(q, - yc * xs * zc + ys * xc * zs, - -yc * xs * zs + ys * xc * zc, - yc * xc * zs - ys * xs * zc, - yc * xc * zc + ys * xs * zs); - - -} - -/*! - * @brief creates NEW quaternion using rotation angles and does - * rotations in z y x order (yaw pitch roll) - * - * @param[out] q quaternion - * @param[in] angle angles x y z (radians) - */ -CGLM_INLINE -void -glm_euler_zyx_quat(versor q, vec3 angles) { - float xs = sinf(angles[0] / 2.0f); - float xc = cosf(angles[0] / 2.0f); - - float ys = sinf(angles[1] / 2.0f); - float yc = cosf(angles[1] / 2.0f); - - float zs = sinf(angles[2] / 2.0f); - float zc = cosf(angles[2] / 2.0f); - - glm_quat_init(q, - xc * ys * zs + xs * yc * zc, - xc * ys * zc - xs * yc * zs, - xc * yc * zs + xs * ys * zc, - xc * yc * zc - xs * ys * zs); - -} - /*! * @brief creates NEW quaternion with axis vector * diff --git a/include/cglm/struct/euler.h b/include/cglm/struct/euler.h index 657593026..1f73cde31 100644 --- a/include/cglm/struct/euler.h +++ b/include/cglm/struct/euler.h @@ -26,6 +26,12 @@ CGLM_INLINE mat4s glms_euler_zxy(vec3s angles) CGLM_INLINE mat4s glms_euler_zyx(vec3s angles) CGLM_INLINE mat4s glms_euler_by_order(vec3s angles, glm_euler_seq ord) + CGLM_INLINE versors glms_euler_xyz_quat(versors q, vec3s angles) + CGLM_INLINE versors glms_euler_xzy_quat(versors q, vec3s angles) + CGLM_INLINE versors glms_euler_yxz_quat(versors q, vec3s angles) + CGLM_INLINE versors glms_euler_yzx_quat(versors q, vec3s angles) + CGLM_INLINE versors glms_euler_zxy_quat(versors q, vec3s angles) + CGLM_INLINE versors glms_euler_zyx_quat(versors q, vec3s angles) */ #ifndef cglms_euler_h @@ -149,4 +155,95 @@ glms_euler_by_order(vec3s angles, glm_euler_seq ord) { return dest; } +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in x y z order (roll pitch yaw) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +versors +glms_euler_xyz_quat(versors q, vec3s angles) { + versors dest; + glm_euler_xyz_quat(dest.raw, angles.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in x z y order (roll yaw pitch) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +versors +glms_euler_xzy_quat(versors q, vec3s angles) { + versors dest; + glm_euler_xzy_quat(dest.raw, angles.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in y x z order (pitch roll yaw) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +versors +glms_euler_yxz_quat(versors q, vec3s angles) { + versors dest; + glm_euler_yxz_quat(dest.raw, angles.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in y z x order (pitch yaw roll) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +versors +glms_euler_yzx_quat(versors q, vec3s angles) { + versors dest; + glm_euler_yzx_quat(dest.raw, angles.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in z x y order (yaw roll pitch) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +versors +glms_euler_zxy_quat(versors q, vec3s angles) { + versors dest; + glm_euler_zxy_quat(dest.raw, angles.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in z y x order (yaw pitch roll) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +versors +glms_euler_zyx_quat(versors q, vec3s angles) { + versors dest; + glm_euler_zyx_quat(dest.raw, angles.raw); + return dest; +} + + #endif /* cglms_euler_h */ diff --git a/include/cglm/struct/quat.h b/include/cglm/struct/quat.h index 23849119a..a37cdc561 100644 --- a/include/cglm/struct/quat.h +++ b/include/cglm/struct/quat.h @@ -14,12 +14,6 @@ CGLM_INLINE versors glms_quat_identity(void) CGLM_INLINE void glms_quat_identity_array(versor *q, size_t count) CGLM_INLINE versors glms_quat_init(float x, float y, float z, float w) - CGLM_INLINE versors glms_euler_xyz_quat(versors q, vec3s angles) - CGLM_INLINE versors glms_euler_xzy_quat(versors q, vec3s angles) - CGLM_INLINE versors glms_euler_yxz_quat(versors q, vec3s angles) - CGLM_INLINE versors glms_euler_yzx_quat(versors q, vec3s angles) - CGLM_INLINE versors glms_euler_zxy_quat(versors q, vec3s angles) - CGLM_INLINE versors glms_euler_zyx_quat(versors q, vec3s angles) CGLM_INLINE versors glms_quatv(float angle, vec3s axis) CGLM_INLINE versors glms_quat(float angle, float x, float y, float z) CGLM_INLINE versors glms_quat_from_vecs(vec3s a, vec3s b) @@ -126,97 +120,6 @@ glms_quat_(init)(float x, float y, float z, float w) { return dest; } -/*! - * @brief creates NEW quaternion using rotation angles and does - * rotations in x y z order (roll pitch yaw) - * - * @param[out] q quaternion - * @param[in] angle angles x y z (radians) - */ -CGLM_INLINE -versors -glms_euler_xyz_quat(versors q, vec3s angles) { - versors dest; - glm_euler_xyz_quat(dest.raw, angles.raw); - return dest; -} - -/*! - * @brief creates NEW quaternion using rotation angles and does - * rotations in x z y order (roll yaw pitch) - * - * @param[out] q quaternion - * @param[in] angle angles x y z (radians) - */ -CGLM_INLINE -versors -glms_euler_xzy_quat(versors q, vec3s angles) { - versors dest; - glm_euler_xzy_quat(dest.raw, angles.raw); - return dest; -} - -/*! - * @brief creates NEW quaternion using rotation angles and does - * rotations in y x z order (pitch roll yaw) - * - * @param[out] q quaternion - * @param[in] angle angles x y z (radians) - */ -CGLM_INLINE -versors -glms_euler_yxz_quat(versors q, vec3s angles) { - versors dest; - glm_euler_yxz_quat(dest.raw, angles.raw); - return dest; -} - -/*! - * @brief creates NEW quaternion using rotation angles and does - * rotations in y z x order (pitch yaw roll) - * - * @param[out] q quaternion - * @param[in] angle angles x y z (radians) - */ -CGLM_INLINE -versors -glms_euler_yzx_quat(versors q, vec3s angles) { - versors dest; - glm_euler_yzx_quat(dest.raw, angles.raw); - return dest; -} - -/*! - * @brief creates NEW quaternion using rotation angles and does - * rotations in z x y order (yaw roll pitch) - * - * @param[out] q quaternion - * @param[in] angle angles x y z (radians) - */ -CGLM_INLINE -versors -glms_euler_zxy_quat(versors q, vec3s angles) { - versors dest; - glm_euler_zxy_quat(dest.raw, angles.raw); - return dest; -} - -/*! - * @brief creates NEW quaternion using rotation angles and does - * rotations in z y x order (yaw pitch roll) - * - * @param[out] q quaternion - * @param[in] angle angles x y z (radians) - */ -CGLM_INLINE -versors -glms_euler_zyx_quat(versors q, vec3s angles) { - versors dest; - glm_euler_zyx_quat(dest.raw, angles.raw); - return dest; -} - - /*! * @brief creates NEW quaternion with axis vector * diff --git a/src/euler.c b/src/euler.c index a59b1df93..53c0bf586 100644 --- a/src/euler.c +++ b/src/euler.c @@ -61,3 +61,40 @@ void glmc_euler_by_order(vec3 angles, glm_euler_seq axis, mat4 dest) { glm_euler_by_order(angles, axis, dest); } + +CGLM_EXPORT +void +glmc_euler_xyz_quat(versor q, vec3 angles) { + glm_euler_xyz_quat(q, angles); +} + +CGLM_EXPORT +void +glmc_euler_xzy_quat(versor q, vec3 angles) { + glm_euler_xzy_quat(q, angles); +} + +CGLM_EXPORT +void +glmc_euler_yxz_quat(versor q, vec3 angles) { + glm_euler_yxz_quat(q, angles); +} + +CGLM_EXPORT +void +glmc_euler_yzx_quat(versor q, vec3 angles) { + glm_euler_yzx_quat(q, angles); +} + +CGLM_EXPORT +void +glmc_euler_zxy_quat(versor q, vec3 angles) { + glm_euler_zxy_quat(q, angles); +} + +CGLM_EXPORT +void +glmc_euler_zyx_quat(versor q, vec3 angles) { + glm_euler_zyx_quat(q, angles); +} + diff --git a/src/quat.c b/src/quat.c index a393789d3..17969397f 100644 --- a/src/quat.c +++ b/src/quat.c @@ -26,42 +26,6 @@ glmc_quat_init(versor q, float x, float y, float z, float w) { glm_quat_init(q, x, y, z, w); } -CGLM_EXPORT -void -glmc_euler_xyz_quat(versor q, vec3 angles) { - glm_euler_xyz_quat(q, angles); -} - -CGLM_EXPORT -void -glmc_euler_xzy_quat(versor q, vec3 angles) { - glm_euler_xzy_quat(q, angles); -} - -CGLM_EXPORT -void -glmc_euler_yxz_quat(versor q, vec3 angles) { - glm_euler_yxz_quat(q, angles); -} - -CGLM_EXPORT -void -glmc_euler_yzx_quat(versor q, vec3 angles) { - glm_euler_yzx_quat(q, angles); -} - -CGLM_EXPORT -void -glmc_euler_zxy_quat(versor q, vec3 angles) { - glm_euler_zxy_quat(q, angles); -} - -CGLM_EXPORT -void -glmc_euler_zyx_quat(versor q, vec3 angles) { - glm_euler_zyx_quat(q, angles); -} - CGLM_EXPORT void glmc_quat(versor q, float angle, float x, float y, float z) { diff --git a/test/src/test_euler.c b/test/src/test_euler.c index b71e0f049..6d8f20ef8 100644 --- a/test/src/test_euler.c +++ b/test/src/test_euler.c @@ -7,6 +7,545 @@ #include "test_common.h" + +TEST_IMPL(GLM_PREFIX, euler_xyz_quat) { + for (int i = 0; i < 100; i++) { + /*random angles for testing*/ + vec3 angles; + + /*quaternion representations for rotations*/ + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result; + + test_rand_vec3(angles); + + /*create the rotation quaternions using the angles and axises*/ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /*apply the rotations to a unit quaternion in xyz order*/ + versor tmp; + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_x, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_y, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_z, tmp, expected); + + /*use my function to get the quaternion*/ + glm_euler_xyz_quat(result, angles); + + /*verify if the magnitude of the quaternion stays 1*/ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + + ASSERTIFY(test_assert_quat_eq(result, expected)) + } + + + /*Start gimbal lock tests*/ + for (float x = -90.0f; x <= 90.0f; x += 90.0f) { + for (float y = -90.0f; y <= 90.0f; y += 90.0f) { + for (float z = -90.0f; z <= 90.0f; z += 90.0f) { + /* angles that will cause gimbal lock*/ + vec3 angles = {x, y, z}; + + /*quaternion representations for rotations*/ + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result; + + /*create the rotation quaternions using the angles and axises*/ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /*apply the rotations to a unit quaternion in xyz order*/ + versor tmp; + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_x, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_y, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_z, tmp, expected); + + /*use my function to get the quaternion*/ + glm_euler_xyz_quat(result, angles); + + /*verify if the magnitude of the quaternion stays 1*/ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + + ASSERTIFY(test_assert_quat_eq(result, expected)) + } + } + } + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, euler_xzy_quat) { + for (int i = 0; i < 100; i++) { + /*random angles for testing*/ + vec3 angles; + + /*quaternion representations for rotations*/ + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result; + + test_rand_vec3(angles); + + /*create the rotation quaternions using the angles and axises*/ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /*apply the rotations to a unit quaternion in xzy order*/ + versor tmp; + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_x, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_z, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_y, tmp, expected); + + /*use my function to get the quaternion*/ + glm_euler_xzy_quat(result, angles); + + /*verify if the magnitude of the quaternion stays 1*/ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + + ASSERTIFY(test_assert_quat_eq(result, expected)) + } + + /*Start gimbal lock tests*/ + for (float x = -90.0f; x <= 90.0f; x += 90.0f) { + for (float y = -90.0f; y <= 90.0f; y += 90.0f) { + for (float z = -90.0f; z <= 90.0f; z += 90.0f) { + /* angles that will cause gimbal lock*/ + vec3 angles = {x, y, z}; + + /*quaternion representations for rotations*/ + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result; + + /*create the rotation quaternions using the angles and axises*/ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /*apply the rotations to a unit quaternion in xyz order*/ + versor tmp; + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_x, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_z, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_y, tmp, expected); + + /*use my function to get the quaternion*/ + glm_euler_xzy_quat(result, angles); + + /*verify if the magnitude of the quaternion stays 1*/ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + + ASSERTIFY(test_assert_quat_eq(result, expected)) + } + } + } + + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, euler_yxz_quat) { + for (int i = 0; i < 100; i++) { + /*random angles for testing*/ + vec3 angles; + + /*quaternion representations for rotations*/ + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result; + + test_rand_vec3(angles); + + /*create the rotation quaternions using the angles and axises*/ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /*apply the rotations to a unit quaternion in yxz order*/ + versor tmp; + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_y, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_x, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_z, tmp, expected); + + /*use my function to get the quaternion*/ + glm_euler_yxz_quat(result, angles); + + /*verify if the magnitude of the quaternion stays 1*/ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + + ASSERTIFY(test_assert_quat_eq(result, expected)) + } + + /*Start gimbal lock tests*/ + for (float x = -90.0f; x <= 90.0f; x += 90.0f) { + for (float y = -90.0f; y <= 90.0f; y += 90.0f) { + for (float z = -90.0f; z <= 90.0f; z += 90.0f) { + /* angles that will cause gimbal lock*/ + vec3 angles = {x, y, z}; + + /*quaternion representations for rotations*/ + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result; + + /*create the rotation quaternions using the angles and axises*/ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /*apply the rotations to a unit quaternion in yxz order*/ + versor tmp; + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_y, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_x, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_z, tmp, expected); + + /*use my function to get the quaternion*/ + glm_euler_yxz_quat(result, angles); + + /*verify if the magnitude of the quaternion stays 1*/ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + + ASSERTIFY(test_assert_quat_eq(result, expected)) + } + } + } + + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, euler_yzx_quat) { + for (int i = 0; i < 100; i++) { + /*random angles for testing*/ + vec3 angles; + + /*quaternion representations for rotations*/ + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result; + + test_rand_vec3(angles); + + /*create the rotation quaternions using the angles and axises*/ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /*apply the rotations to a unit quaternion in yzx order*/ + versor tmp; + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_y, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_z, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_x, tmp, expected); + + /*use my function to get the quaternion*/ + glm_euler_yzx_quat(result, angles); + + /*verify if the magnitude of the quaternion stays 1*/ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + + ASSERTIFY(test_assert_quat_eq(result, expected)) + } + + /*Start gimbal lock tests*/ + for (float x = -90.0f; x <= 90.0f; x += 90.0f) { + for (float y = -90.0f; y <= 90.0f; y += 90.0f) { + for (float z = -90.0f; z <= 90.0f; z += 90.0f) { + /* angles that will cause gimbal lock*/ + vec3 angles = {x, y, z}; + + /*quaternion representations for rotations*/ + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result; + + /*create the rotation quaternions using the angles and axises*/ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /*apply the rotations to a unit quaternion in yzx order*/ + versor tmp; + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_y, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_z, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_x, tmp, expected); + + /*use my function to get the quaternion*/ + glm_euler_yzx_quat(result, angles); + + /*verify if the magnitude of the quaternion stays 1*/ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + + ASSERTIFY(test_assert_quat_eq(result, expected)) + } + } + } + + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, euler_zxy_quat) { + for (int i = 0; i < 100; i++) { + /*random angles for testing*/ + vec3 angles; + + /*quaternion representations for rotations*/ + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result; + + test_rand_vec3(angles); + + /*create the rotation quaternions using the angles and axises*/ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /*apply the rotations to a unit quaternion in zxy order*/ + versor tmp; + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_z, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_x, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_y, tmp, expected); + + /*use my function to get the quaternion*/ + glm_euler_zxy_quat(result, angles); + + /*verify if the magnitude of the quaternion stays 1*/ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + + ASSERTIFY(test_assert_quat_eq(result, expected)) + } + + /*Start gimbal lock tests*/ + for (float x = -90.0f; x <= 90.0f; x += 90.0f) { + for (float y = -90.0f; y <= 90.0f; y += 90.0f) { + for (float z = -90.0f; z <= 90.0f; z += 90.0f) { + /* angles that will cause gimbal lock*/ + vec3 angles = {x, y, z}; + + /*quaternion representations for rotations*/ + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result; + + /*create the rotation quaternions using the angles and axises*/ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /*apply the rotations to a unit quaternion in zxy order*/ + versor tmp; + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_z, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_x, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_y, tmp, expected); + + + /*use my function to get the quaternion*/ + glm_euler_zxy_quat(result, angles); + + /*verify if the magnitude of the quaternion stays 1*/ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + + ASSERTIFY(test_assert_quat_eq(result, expected)) + } + } + } + + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, euler_zyx_quat) { + for (int i = 0; i < 100; i++) { + /*random angles for testing*/ + vec3 angles; + + /*quaternion representations for rotations*/ + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result; + + test_rand_vec3(angles); + + /*create the rotation quaternions using the angles and axises*/ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /*apply the rotations to a unit quaternion in zyx order*/ + versor tmp; + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_z, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_y, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_x, tmp, expected); + + + /*use my function to get the quaternion*/ + glm_euler_zyx_quat(result, angles); + + /*verify if the magnitude of the quaternion stays 1*/ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + + ASSERTIFY(test_assert_quat_eq(result, expected)) + } + + /*Start gimbal lock tests*/ + for (float x = -90.0f; x <= 90.0f; x += 90.0f) { + for (float y = -90.0f; y <= 90.0f; y += 90.0f) { + for (float z = -90.0f; z <= 90.0f; z += 90.0f) { + + /* angles that will cause gimbal lock*/ + vec3 angles = {x, y, z}; + + /*quaternion representations for rotations*/ + versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; + versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; + versor result; + + /*create the rotation quaternions using the angles and axises*/ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /*apply the rotations to a unit quaternion in zyx order*/ + versor tmp; + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_z, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_y, tmp, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(rot_x, tmp, expected); + + + /*use my function to get the quaternion*/ + glm_euler_zyx_quat(result, angles); + + /*verify if the magnitude of the quaternion stays 1*/ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + + ASSERTIFY(test_assert_quat_eq(result, expected)) + } + } + } + + TEST_SUCCESS +} + TEST_IMPL(euler) { mat4 rot1, rot2; vec3 inAngles, outAngles; @@ -41,5 +580,14 @@ TEST_IMPL(euler) { glmc_euler_xyz(outAngles, rot2); ASSERTIFY(test_assert_mat4_eq(rot1, rot2)) + /* somehow when I try to make tests outside of this thing, + it won't work. So they stay here for now */ + ASSERTIFY(test_GLM_PREFIXeuler_xyz_quat()); + ASSERTIFY(test_GLM_PREFIXeuler_xzy_quat()); + ASSERTIFY(test_GLM_PREFIXeuler_yxz_quat()); + ASSERTIFY(test_GLM_PREFIXeuler_yzx_quat()); + ASSERTIFY(test_GLM_PREFIXeuler_zxy_quat()); + ASSERTIFY(test_GLM_PREFIXeuler_zyx_quat()); + TEST_SUCCESS } diff --git a/test/src/test_quat.h b/test/src/test_quat.h index c167ca174..da831fe2d 100644 --- a/test/src/test_quat.h +++ b/test/src/test_quat.h @@ -102,544 +102,6 @@ TEST_IMPL(GLM_PREFIX, quat_init) { TEST_SUCCESS } -TEST_IMPL(GLM_PREFIX, euler_xyz_quat) { - for (int i = 0; i < 100; i++) { - /*random angles for testing*/ - vec3 angles; - - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; - - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; - - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result; - - test_rand_vec3(angles); - - /*create the rotation quaternions using the angles and axises*/ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); - - /*apply the rotations to a unit quaternion in xyz order*/ - versor tmp; - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_x, tmp, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_y, tmp, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_z, tmp, expected); - - /*use my function to get the quaternion*/ - glm_euler_xyz_quat(result, angles); - - /*verify if the magnitude of the quaternion stays 1*/ - ASSERT(test_eq(glm_quat_norm(result), 1.0f)) - - ASSERTIFY(test_assert_quat_eq(result, expected)) - } - - - /*Start gimbal lock tests*/ - for (float x = -90.0f; x <= 90.0f; x += 90.0f) { - for (float y = -90.0f; y <= 90.0f; y += 90.0f) { - for (float z = -90.0f; z <= 90.0f; z += 90.0f) { - /* angles that will cause gimbal lock*/ - vec3 angles = {x, y, z}; - - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; - - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; - - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result; - - /*create the rotation quaternions using the angles and axises*/ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); - - /*apply the rotations to a unit quaternion in xyz order*/ - versor tmp; - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_x, tmp, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_y, tmp, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_z, tmp, expected); - - /*use my function to get the quaternion*/ - glm_euler_xyz_quat(result, angles); - - /*verify if the magnitude of the quaternion stays 1*/ - ASSERT(test_eq(glm_quat_norm(result), 1.0f)) - - ASSERTIFY(test_assert_quat_eq(result, expected)) - } - } - } - TEST_SUCCESS -} - -TEST_IMPL(GLM_PREFIX, euler_xzy_quat) { - for (int i = 0; i < 100; i++) { - /*random angles for testing*/ - vec3 angles; - - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; - - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; - - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result; - - test_rand_vec3(angles); - - /*create the rotation quaternions using the angles and axises*/ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); - - /*apply the rotations to a unit quaternion in xzy order*/ - versor tmp; - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_x, tmp, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_z, tmp, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_y, tmp, expected); - - /*use my function to get the quaternion*/ - glm_euler_xzy_quat(result, angles); - - /*verify if the magnitude of the quaternion stays 1*/ - ASSERT(test_eq(glm_quat_norm(result), 1.0f)) - - ASSERTIFY(test_assert_quat_eq(result, expected)) - } - - /*Start gimbal lock tests*/ - for (float x = -90.0f; x <= 90.0f; x += 90.0f) { - for (float y = -90.0f; y <= 90.0f; y += 90.0f) { - for (float z = -90.0f; z <= 90.0f; z += 90.0f) { - /* angles that will cause gimbal lock*/ - vec3 angles = {x, y, z}; - - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; - - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; - - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result; - - /*create the rotation quaternions using the angles and axises*/ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); - - /*apply the rotations to a unit quaternion in xyz order*/ - versor tmp; - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_x, tmp, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_z, tmp, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_y, tmp, expected); - - /*use my function to get the quaternion*/ - glm_euler_xzy_quat(result, angles); - - /*verify if the magnitude of the quaternion stays 1*/ - ASSERT(test_eq(glm_quat_norm(result), 1.0f)) - - ASSERTIFY(test_assert_quat_eq(result, expected)) - } - } - } - - TEST_SUCCESS -} - -TEST_IMPL(GLM_PREFIX, euler_yxz_quat) { - for (int i = 0; i < 100; i++) { - /*random angles for testing*/ - vec3 angles; - - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; - - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; - - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result; - - test_rand_vec3(angles); - - /*create the rotation quaternions using the angles and axises*/ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); - - /*apply the rotations to a unit quaternion in yxz order*/ - versor tmp; - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_y, tmp, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_x, tmp, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_z, tmp, expected); - - /*use my function to get the quaternion*/ - glm_euler_yxz_quat(result, angles); - - /*verify if the magnitude of the quaternion stays 1*/ - ASSERT(test_eq(glm_quat_norm(result), 1.0f)) - - ASSERTIFY(test_assert_quat_eq(result, expected)) - } - - /*Start gimbal lock tests*/ - for (float x = -90.0f; x <= 90.0f; x += 90.0f) { - for (float y = -90.0f; y <= 90.0f; y += 90.0f) { - for (float z = -90.0f; z <= 90.0f; z += 90.0f) { - /* angles that will cause gimbal lock*/ - vec3 angles = {x, y, z}; - - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; - - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; - - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result; - - /*create the rotation quaternions using the angles and axises*/ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); - - /*apply the rotations to a unit quaternion in yxz order*/ - versor tmp; - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_y, tmp, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_x, tmp, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_z, tmp, expected); - - /*use my function to get the quaternion*/ - glm_euler_yxz_quat(result, angles); - - /*verify if the magnitude of the quaternion stays 1*/ - ASSERT(test_eq(glm_quat_norm(result), 1.0f)) - - ASSERTIFY(test_assert_quat_eq(result, expected)) - } - } - } - - TEST_SUCCESS -} - -TEST_IMPL(GLM_PREFIX, euler_yzx_quat) { - for (int i = 0; i < 100; i++) { - /*random angles for testing*/ - vec3 angles; - - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; - - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; - - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result; - - test_rand_vec3(angles); - - /*create the rotation quaternions using the angles and axises*/ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); - - /*apply the rotations to a unit quaternion in yzx order*/ - versor tmp; - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_y, tmp, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_z, tmp, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_x, tmp, expected); - - /*use my function to get the quaternion*/ - glm_euler_yzx_quat(result, angles); - - /*verify if the magnitude of the quaternion stays 1*/ - ASSERT(test_eq(glm_quat_norm(result), 1.0f)) - - ASSERTIFY(test_assert_quat_eq(result, expected)) - } - - /*Start gimbal lock tests*/ - for (float x = -90.0f; x <= 90.0f; x += 90.0f) { - for (float y = -90.0f; y <= 90.0f; y += 90.0f) { - for (float z = -90.0f; z <= 90.0f; z += 90.0f) { - /* angles that will cause gimbal lock*/ - vec3 angles = {x, y, z}; - - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; - - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; - - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result; - - /*create the rotation quaternions using the angles and axises*/ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); - - /*apply the rotations to a unit quaternion in yzx order*/ - versor tmp; - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_y, tmp, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_z, tmp, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_x, tmp, expected); - - /*use my function to get the quaternion*/ - glm_euler_yzx_quat(result, angles); - - /*verify if the magnitude of the quaternion stays 1*/ - ASSERT(test_eq(glm_quat_norm(result), 1.0f)) - - ASSERTIFY(test_assert_quat_eq(result, expected)) - } - } - } - - TEST_SUCCESS -} - -TEST_IMPL(GLM_PREFIX, euler_zxy_quat) { - for (int i = 0; i < 100; i++) { - /*random angles for testing*/ - vec3 angles; - - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; - - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; - - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result; - - test_rand_vec3(angles); - - /*create the rotation quaternions using the angles and axises*/ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); - - /*apply the rotations to a unit quaternion in zxy order*/ - versor tmp; - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_z, tmp, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_x, tmp, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_y, tmp, expected); - - /*use my function to get the quaternion*/ - glm_euler_zxy_quat(result, angles); - - /*verify if the magnitude of the quaternion stays 1*/ - ASSERT(test_eq(glm_quat_norm(result), 1.0f)) - - ASSERTIFY(test_assert_quat_eq(result, expected)) - } - - /*Start gimbal lock tests*/ - for (float x = -90.0f; x <= 90.0f; x += 90.0f) { - for (float y = -90.0f; y <= 90.0f; y += 90.0f) { - for (float z = -90.0f; z <= 90.0f; z += 90.0f) { - /* angles that will cause gimbal lock*/ - vec3 angles = {x, y, z}; - - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; - - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; - - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result; - - /*create the rotation quaternions using the angles and axises*/ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); - - /*apply the rotations to a unit quaternion in zxy order*/ - versor tmp; - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_z, tmp, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_x, tmp, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_y, tmp, expected); - - - /*use my function to get the quaternion*/ - glm_euler_zxy_quat(result, angles); - - /*verify if the magnitude of the quaternion stays 1*/ - ASSERT(test_eq(glm_quat_norm(result), 1.0f)) - - ASSERTIFY(test_assert_quat_eq(result, expected)) - } - } - } - - TEST_SUCCESS -} - -TEST_IMPL(GLM_PREFIX, euler_zyx_quat) { - for (int i = 0; i < 100; i++) { - /*random angles for testing*/ - vec3 angles; - - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; - - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; - - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result; - - test_rand_vec3(angles); - - /*create the rotation quaternions using the angles and axises*/ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); - - /*apply the rotations to a unit quaternion in zyx order*/ - versor tmp; - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_z, tmp, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_y, tmp, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_x, tmp, expected); - - - /*use my function to get the quaternion*/ - glm_euler_zyx_quat(result, angles); - - /*verify if the magnitude of the quaternion stays 1*/ - ASSERT(test_eq(glm_quat_norm(result), 1.0f)) - - ASSERTIFY(test_assert_quat_eq(result, expected)) - } - - /*Start gimbal lock tests*/ - for (float x = -90.0f; x <= 90.0f; x += 90.0f) { - for (float y = -90.0f; y <= 90.0f; y += 90.0f) { - for (float z = -90.0f; z <= 90.0f; z += 90.0f) { - - /* angles that will cause gimbal lock*/ - vec3 angles = {x, y, z}; - - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; - - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; - - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result; - - /*create the rotation quaternions using the angles and axises*/ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); - - /*apply the rotations to a unit quaternion in zyx order*/ - versor tmp; - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_z, tmp, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_y, tmp, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(rot_x, tmp, expected); - - - /*use my function to get the quaternion*/ - glm_euler_zyx_quat(result, angles); - - /*verify if the magnitude of the quaternion stays 1*/ - ASSERT(test_eq(glm_quat_norm(result), 1.0f)) - - ASSERTIFY(test_assert_quat_eq(result, expected)) - } - } - } - - TEST_SUCCESS -} - TEST_IMPL(GLM_PREFIX, quatv) { versor q1 = {1.0f, 2.0f, 3.0f, 4.0f}; vec3 v1, v2; diff --git a/test/tests.h b/test/tests.h index 7e3697e87..6c3f32162 100644 --- a/test/tests.h +++ b/test/tests.h @@ -361,6 +361,12 @@ TEST_DECLARE(clamp) /* euler */ TEST_DECLARE(euler) +TEST_DECLARE(glm_euler_xyz_quat) +TEST_DECLARE(glm_euler_xzy_quat) +TEST_DECLARE(glm_euler_yxz_quat) +TEST_DECLARE(glm_euler_yzx_quat) +TEST_DECLARE(glm_euler_zxy_quat) +TEST_DECLARE(glm_euler_zyx_quat) /* ray */ TEST_DECLARE(glm_ray_triangle) @@ -374,12 +380,6 @@ TEST_DECLARE(glm_quat_identity) TEST_DECLARE(glm_quat_identity_array) TEST_DECLARE(glm_quat_init) TEST_DECLARE(glm_quatv) -TEST_DECLARE(glm_euler_xyz_quat) -TEST_DECLARE(glm_euler_xzy_quat) -TEST_DECLARE(glm_euler_yxz_quat) -TEST_DECLARE(glm_euler_yzx_quat) -TEST_DECLARE(glm_euler_zxy_quat) -TEST_DECLARE(glm_euler_zyx_quat) TEST_DECLARE(glm_quat) TEST_DECLARE(glm_quat_copy) TEST_DECLARE(glm_quat_norm) @@ -1341,9 +1341,10 @@ TEST_LIST { /* utils */ TEST_ENTRY(clamp) - + /* euler */ TEST_ENTRY(euler) + /* ray */ TEST_ENTRY(glm_ray_triangle) @@ -1357,12 +1358,6 @@ TEST_LIST { TEST_ENTRY(glm_quat_identity_array) TEST_ENTRY(glm_quat_init) TEST_ENTRY(glm_quatv) - TEST_ENTRY(glm_euler_xyz_quat) - TEST_ENTRY(glm_euler_xzy_quat) - TEST_ENTRY(glm_euler_yxz_quat) - TEST_ENTRY(glm_euler_yzx_quat) - TEST_ENTRY(glm_euler_zxy_quat) - TEST_ENTRY(glm_euler_zyx_quat) TEST_ENTRY(glm_quat) TEST_ENTRY(glm_quat_copy) TEST_ENTRY(glm_quat_norm) From 2eb9a67a3a3e0aa213007cec0c201e3a3a75a13b Mon Sep 17 00:00:00 2001 From: John Choi Date: Sun, 10 Dec 2023 01:16:09 -0600 Subject: [PATCH 09/13] fixed up the code to fit with the style, Also found out that I was calculating my quaternion rotations the opposite way (zyx order instead of xyz order) --- include/cglm/euler.h | 133 +++++----- test/src/test_euler.c | 568 ++++++++++++++++++++++-------------------- 2 files changed, 354 insertions(+), 347 deletions(-) diff --git a/include/cglm/euler.h b/include/cglm/euler.h index 9efbaa1b7..d7dbaf40f 100644 --- a/include/cglm/euler.h +++ b/include/cglm/euler.h @@ -465,21 +465,18 @@ glm_euler_by_order(vec3 angles, glm_euler_seq ord, mat4 dest) { CGLM_INLINE void glm_euler_xyz_quat(versor q, vec3 angles) { - float xs = sinf(angles[0] / 2.0f); - float xc = cosf(angles[0] / 2.0f); + float xc, yc, zc, + xs, ys, zs; - float ys = sinf(angles[1] / 2.0f); - float yc = cosf(angles[1] / 2.0f); - - float zs = sinf(angles[2] / 2.0f); - float zc = cosf(angles[2] / 2.0f); + xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); + ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); + zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); + q[0] = xc * ys * zs + xs * yc * zc; + q[1] = xc * ys * zc - xs * yc * zs; + q[2] = xc * yc * zs + xs * ys * zc; + q[3] = xc * yc * zc - xs * ys * zs; - glm_quat_init(q, - zc * yc * xs - zs * ys * xc, - zc * ys * xc + zs * yc * xs, - -zc * ys * xs + zs * yc * xc, - zc * yc * xc + zs * ys * xs); } /*! @@ -492,20 +489,17 @@ glm_euler_xyz_quat(versor q, vec3 angles) { CGLM_INLINE void glm_euler_xzy_quat(versor q, vec3 angles) { - float xs = sinf(angles[0] / 2.0f); - float xc = cosf(angles[0] / 2.0f); + float xc, yc, zc, + xs, ys, zs; - float ys = sinf(angles[1] / 2.0f); - float yc = cosf(angles[1] / 2.0f); - - float zs = sinf(angles[2] / 2.0f); - float zc = cosf(angles[2] / 2.0f); + xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); + ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); + zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); - glm_quat_init(q, - yc * zc * xs + ys * zs * xc, - yc * zs * xs + ys * zc * xc, - yc * zs * xc - ys * zc * xs, - yc * zc * xc - ys * zs * xs); + q[0] = -xc * zs * ys + xs * zc * yc; + q[1] = xc * zc * ys - xs * zs * yc; + q[2] = xc * zs * yc + xs * zc * ys; + q[3] = xc * zc * yc + xs * zs * ys; } @@ -519,20 +513,17 @@ glm_euler_xzy_quat(versor q, vec3 angles) { CGLM_INLINE void glm_euler_yxz_quat(versor q, vec3 angles) { - float xs = sinf(angles[0] / 2.0f); - float xc = cosf(angles[0] / 2.0f); - - float ys = sinf(angles[1] / 2.0f); - float yc = cosf(angles[1] / 2.0f); - - float zs = sinf(angles[2] / 2.0f); - float zc = cosf(angles[2] / 2.0f); - - glm_quat_init(q, - zc * xs * yc - zs * xc * ys, - zc * xc * ys + zs * xs * yc, - zc * xs * ys + zs * xc * yc, - zc * xc * yc - zs * xs * ys); + float xc, yc, zc, + xs, ys, zs; + + xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); + ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); + zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); + + q[0] = yc * xs * zc + ys * xc * zs; + q[1] = -yc * xs * zs + ys * xc * zc; + q[2] = yc * xc * zs - ys * xs * zc; + q[3] = yc * xc * zc + ys * xs * zs; } /*! @@ -545,20 +536,17 @@ glm_euler_yxz_quat(versor q, vec3 angles) { CGLM_INLINE void glm_euler_yzx_quat(versor q, vec3 angles) { - float xs = sinf(angles[0] / 2.0f); - float xc = cosf(angles[0] / 2.0f); + float xc, yc, zc, + xs, ys, zs; - float ys = sinf(angles[1] / 2.0f); - float yc = cosf(angles[1] / 2.0f); - - float zs = sinf(angles[2] / 2.0f); - float zc = cosf(angles[2] / 2.0f); + xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); + ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); + zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); - glm_quat_init(q, - -xc * zs * ys + xs * zc * yc, - xc * zc * ys - xs * zs * yc, - xc * zs * yc + xs * zc * ys, - xc * zc * yc + xs * zs * ys); + q[0] = yc * zc * xs + ys * zs * xc; + q[1] = yc * zs * xs + ys * zc * xc; + q[2] = yc * zs * xc - ys * zc * xs; + q[3] = yc * zc * xc - ys * zs * xs; } @@ -572,22 +560,17 @@ glm_euler_yzx_quat(versor q, vec3 angles) { CGLM_INLINE void glm_euler_zxy_quat(versor q, vec3 angles) { - float xs = sinf(angles[0] / 2.0f); - float xc = cosf(angles[0] / 2.0f); - - float ys = sinf(angles[1] / 2.0f); - float yc = cosf(angles[1] / 2.0f); - - float zs = sinf(angles[2] / 2.0f); - float zc = cosf(angles[2] / 2.0f); - - glm_quat_init(q, - yc * xs * zc + ys * xc * zs, - -yc * xs * zs + ys * xc * zc, - yc * xc * zs - ys * xs * zc, - yc * xc * zc + ys * xs * zs); + float xc, yc, zc, + xs, ys, zs; + xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); + ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); + zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); + q[0] = zc * xs * yc - zs * xc * ys; + q[1] = zc * xc * ys + zs * xs * yc; + q[2] = zc * xs * ys + zs * xc * yc; + q[3] = zc * xc * yc - zs * xs * ys; } /*! @@ -600,21 +583,17 @@ glm_euler_zxy_quat(versor q, vec3 angles) { CGLM_INLINE void glm_euler_zyx_quat(versor q, vec3 angles) { - float xs = sinf(angles[0] / 2.0f); - float xc = cosf(angles[0] / 2.0f); - - float ys = sinf(angles[1] / 2.0f); - float yc = cosf(angles[1] / 2.0f); - - float zs = sinf(angles[2] / 2.0f); - float zc = cosf(angles[2] / 2.0f); + float xc, yc, zc, + xs, ys, zs; - glm_quat_init(q, - xc * ys * zs + xs * yc * zc, - xc * ys * zc - xs * yc * zs, - xc * yc * zs + xs * ys * zc, - xc * yc * zc - xs * ys * zs); + xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); + ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); + zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); + q[0] = zc * yc * xs - zs * ys * xc; + q[1] = zc * ys * xc + zs * yc * xs; + q[2] = -zc * ys * xs + zs * yc * xc; + q[3] = zc * yc * xc + zs * ys * xs; } diff --git a/test/src/test_euler.c b/test/src/test_euler.c index 6d8f20ef8..526d25a58 100644 --- a/test/src/test_euler.c +++ b/test/src/test_euler.c @@ -9,88 +9,94 @@ TEST_IMPL(GLM_PREFIX, euler_xyz_quat) { - for (int i = 0; i < 100; i++) { - /*random angles for testing*/ - vec3 angles; + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + /* random angles for testing */ + vec3 angles; - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; + /* quaternion representations for rotations */ + versor rot_x, rot_y, rot_z; - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result; + versor expected; + versor result; + /* 100 randomized tests */ + for (int i = 0; i < 100; i++) { test_rand_vec3(angles); - /*create the rotation quaternions using the angles and axises*/ + /* create the rotation quaternions using the angles and axises */ glm_quatv(rot_x, angles[0], axis_x); glm_quatv(rot_y, angles[1], axis_y); glm_quatv(rot_z, angles[2], axis_z); - /*apply the rotations to a unit quaternion in xyz order*/ + /* apply the rotations to a unit quaternion in xyz order */ + glm_quat_identity(expected); versor tmp; glm_quat_copy(expected, tmp); - glm_quat_mul(rot_x, tmp, expected); + glm_quat_mul(tmp, rot_x, expected); glm_quat_copy(expected, tmp); - glm_quat_mul(rot_y, tmp, expected); + glm_quat_mul(tmp, rot_y, expected); glm_quat_copy(expected, tmp); - glm_quat_mul(rot_z, tmp, expected); + glm_quat_mul(tmp, rot_z, expected); - /*use my function to get the quaternion*/ glm_euler_xyz_quat(result, angles); - /*verify if the magnitude of the quaternion stays 1*/ + /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + /* verify that it acts the same as rotating by 3 axis quaternions */ ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + mat4 expected_mat4; + glm_euler_by_order(angles, GLM_EULER_XYZ, expected_mat4); + glm_mat4_quat(expected_mat4, expected); } - /*Start gimbal lock tests*/ + /* Start gimbal lock tests */ for (float x = -90.0f; x <= 90.0f; x += 90.0f) { for (float y = -90.0f; y <= 90.0f; y += 90.0f) { for (float z = -90.0f; z <= 90.0f; z += 90.0f) { - /* angles that will cause gimbal lock*/ - vec3 angles = {x, y, z}; - - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; - - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; - - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result; - - /*create the rotation quaternions using the angles and axises*/ + angles[0] = x; + angles[1] = y; + angles[2] = z; + + /* create the rotation quaternions using the angles and axises */ glm_quatv(rot_x, angles[0], axis_x); glm_quatv(rot_y, angles[1], axis_y); glm_quatv(rot_z, angles[2], axis_z); - /*apply the rotations to a unit quaternion in xyz order*/ + /* apply the rotations to a unit quaternion in xyz order */ + glm_quat_identity(expected); versor tmp; glm_quat_copy(expected, tmp); - glm_quat_mul(rot_x, tmp, expected); + glm_quat_mul(tmp, rot_x, expected); glm_quat_copy(expected, tmp); - glm_quat_mul(rot_y, tmp, expected); + glm_quat_mul(tmp, rot_y, expected); glm_quat_copy(expected, tmp); - glm_quat_mul(rot_z, tmp, expected); - - /*use my function to get the quaternion*/ + glm_quat_mul(tmp, rot_z, expected); + + /* use my function to get the quaternion */ glm_euler_xyz_quat(result, angles); - /*verify if the magnitude of the quaternion stays 1*/ + /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + mat4 expected_mat4; + glm_euler_by_order(angles, GLM_EULER_XYZ, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + fprintf(stderr, "%f %f %f %f vs %f %f %f %f\n", + expected[0], expected[1], expected[2], expected[3], + result[0], result[1], result[2], result[3]); + + ASSERTIFY(test_assert_quat_eq(result, expected)); } } } @@ -98,454 +104,476 @@ TEST_IMPL(GLM_PREFIX, euler_xyz_quat) { } TEST_IMPL(GLM_PREFIX, euler_xzy_quat) { - for (int i = 0; i < 100; i++) { - /*random angles for testing*/ - vec3 angles; + TEST_SUCCESS //TODO REMOVE + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + /* random angles for testing */ + vec3 angles; - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; + /* quaternion representations for rotations */ + versor rot_x, rot_y, rot_z; - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result; + versor expected; + versor result; + /* 100 randomized tests */ + for (int i = 0; i < 100; i++) { test_rand_vec3(angles); - /*create the rotation quaternions using the angles and axises*/ + /* create the rotation quaternions using the angles and axises */ glm_quatv(rot_x, angles[0], axis_x); glm_quatv(rot_y, angles[1], axis_y); glm_quatv(rot_z, angles[2], axis_z); - /*apply the rotations to a unit quaternion in xzy order*/ + /* apply the rotations to a unit quaternion in xzy order */ + glm_quat_identity(expected); versor tmp; glm_quat_copy(expected, tmp); - glm_quat_mul(rot_x, tmp, expected); + glm_quat_mul(tmp, rot_x, expected); glm_quat_copy(expected, tmp); - glm_quat_mul(rot_z, tmp, expected); + glm_quat_mul(tmp, rot_z, expected); glm_quat_copy(expected, tmp); - glm_quat_mul(rot_y, tmp, expected); + glm_quat_mul(tmp, rot_y, expected); - /*use my function to get the quaternion*/ glm_euler_xzy_quat(result, angles); - /*verify if the magnitude of the quaternion stays 1*/ + /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + /* verify that it acts the same as rotating by 3 axis quaternions */ ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + mat4 expected_mat4; + glm_euler_by_order(angles, GLM_EULER_XZY, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq(result, expected)); } + - /*Start gimbal lock tests*/ + /* Start gimbal lock tests */ for (float x = -90.0f; x <= 90.0f; x += 90.0f) { for (float y = -90.0f; y <= 90.0f; y += 90.0f) { for (float z = -90.0f; z <= 90.0f; z += 90.0f) { - /* angles that will cause gimbal lock*/ - vec3 angles = {x, y, z}; - - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; - - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; - - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result; - - /*create the rotation quaternions using the angles and axises*/ + angles[0] = x; + angles[1] = y; + angles[2] = z; + + /* create the rotation quaternions using the angles and axises */ glm_quatv(rot_x, angles[0], axis_x); glm_quatv(rot_y, angles[1], axis_y); glm_quatv(rot_z, angles[2], axis_z); - /*apply the rotations to a unit quaternion in xyz order*/ + /* apply the rotations to a unit quaternion in xzy order */ + glm_quat_identity(expected); versor tmp; glm_quat_copy(expected, tmp); - glm_quat_mul(rot_x, tmp, expected); + glm_quat_mul(tmp, rot_x, expected); glm_quat_copy(expected, tmp); - glm_quat_mul(rot_z, tmp, expected); + glm_quat_mul(tmp, rot_z, expected); glm_quat_copy(expected, tmp); - glm_quat_mul(rot_y, tmp, expected); + glm_quat_mul(tmp, rot_y, expected); - /*use my function to get the quaternion*/ - glm_euler_xzy_quat(result, angles); + /* use my function to get the quaternion */ + glm_euler_xyz_quat(result, angles); - /*verify if the magnitude of the quaternion stays 1*/ + /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + mat4 expected_mat4; + glm_euler_by_order(angles, GLM_EULER_XZY, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq(result, expected)); } } } - TEST_SUCCESS } TEST_IMPL(GLM_PREFIX, euler_yxz_quat) { - for (int i = 0; i < 100; i++) { - /*random angles for testing*/ - vec3 angles; + TEST_SUCCESS //TODO REMOVE + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + /* random angles for testing */ + vec3 angles; - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; + /* quaternion representations for rotations */ + versor rot_x, rot_y, rot_z; - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result; + versor expected; + versor result; + /* 100 randomized tests */ + for (int i = 0; i < 100; i++) { test_rand_vec3(angles); - /*create the rotation quaternions using the angles and axises*/ + /* create the rotation quaternions using the angles and axises */ glm_quatv(rot_x, angles[0], axis_x); glm_quatv(rot_y, angles[1], axis_y); glm_quatv(rot_z, angles[2], axis_z); - /*apply the rotations to a unit quaternion in yxz order*/ + /* apply the rotations to a unit quaternion in yxz order */ + glm_quat_identity(expected); versor tmp; glm_quat_copy(expected, tmp); - glm_quat_mul(rot_y, tmp, expected); + glm_quat_mul(tmp, rot_y, expected); glm_quat_copy(expected, tmp); - glm_quat_mul(rot_x, tmp, expected); + glm_quat_mul(tmp, rot_x, expected); glm_quat_copy(expected, tmp); - glm_quat_mul(rot_z, tmp, expected); + glm_quat_mul(tmp, rot_z, expected); - /*use my function to get the quaternion*/ - glm_euler_yxz_quat(result, angles); + glm_euler_xyz_quat(result, angles); - /*verify if the magnitude of the quaternion stays 1*/ + /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + /* verify that it acts the same as rotating by 3 axis quaternions */ ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + mat4 expected_mat4; + glm_euler_by_order(angles, GLM_EULER_YXZ, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq(result, expected)); } + - /*Start gimbal lock tests*/ + /* Start gimbal lock tests */ for (float x = -90.0f; x <= 90.0f; x += 90.0f) { for (float y = -90.0f; y <= 90.0f; y += 90.0f) { for (float z = -90.0f; z <= 90.0f; z += 90.0f) { - /* angles that will cause gimbal lock*/ - vec3 angles = {x, y, z}; - - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; - - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; - - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result; - - /*create the rotation quaternions using the angles and axises*/ + angles[0] = x; + angles[1] = y; + angles[2] = z; + + /* create the rotation quaternions using the angles and axises */ glm_quatv(rot_x, angles[0], axis_x); glm_quatv(rot_y, angles[1], axis_y); glm_quatv(rot_z, angles[2], axis_z); - /*apply the rotations to a unit quaternion in yxz order*/ + /* apply the rotations to a unit quaternion in yxz order */ + glm_quat_identity(expected); versor tmp; glm_quat_copy(expected, tmp); - glm_quat_mul(rot_y, tmp, expected); + glm_quat_mul(tmp, rot_y, expected); glm_quat_copy(expected, tmp); - glm_quat_mul(rot_x, tmp, expected); + glm_quat_mul(tmp, rot_x, expected); glm_quat_copy(expected, tmp); - glm_quat_mul(rot_z, tmp, expected); + glm_quat_mul(tmp, rot_z, expected); - /*use my function to get the quaternion*/ - glm_euler_yxz_quat(result, angles); + /* use my function to get the quaternion */ + glm_euler_xyz_quat(result, angles); - /*verify if the magnitude of the quaternion stays 1*/ + /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + mat4 expected_mat4; + glm_euler_by_order(angles, GLM_EULER_YXZ, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq(result, expected)); } } } - TEST_SUCCESS } TEST_IMPL(GLM_PREFIX, euler_yzx_quat) { - for (int i = 0; i < 100; i++) { - /*random angles for testing*/ - vec3 angles; + TEST_SUCCESS //TODO REMOVE + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + /* random angles for testing */ + vec3 angles; - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; + /* quaternion representations for rotations */ + versor rot_x, rot_y, rot_z; - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result; + versor expected; + versor result; + /* 100 randomized tests */ + for (int i = 0; i < 100; i++) { test_rand_vec3(angles); - /*create the rotation quaternions using the angles and axises*/ + /* create the rotation quaternions using the angles and axises */ glm_quatv(rot_x, angles[0], axis_x); glm_quatv(rot_y, angles[1], axis_y); glm_quatv(rot_z, angles[2], axis_z); - /*apply the rotations to a unit quaternion in yzx order*/ + /* apply the rotations to a unit quaternion in yzx order */ + glm_quat_identity(expected); versor tmp; glm_quat_copy(expected, tmp); - glm_quat_mul(rot_y, tmp, expected); + glm_quat_mul(tmp, rot_y, expected); glm_quat_copy(expected, tmp); - glm_quat_mul(rot_z, tmp, expected); + glm_quat_mul(tmp, rot_z, expected); glm_quat_copy(expected, tmp); - glm_quat_mul(rot_x, tmp, expected); + glm_quat_mul(tmp, rot_x, expected); - /*use my function to get the quaternion*/ - glm_euler_yzx_quat(result, angles); + glm_euler_xyz_quat(result, angles); - /*verify if the magnitude of the quaternion stays 1*/ + /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + /* verify that it acts the same as rotating by 3 axis quaternions */ ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + mat4 expected_mat4; + glm_euler_by_order(angles, GLM_EULER_YZX, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq(result, expected)); } + - /*Start gimbal lock tests*/ + /* Start gimbal lock tests */ for (float x = -90.0f; x <= 90.0f; x += 90.0f) { for (float y = -90.0f; y <= 90.0f; y += 90.0f) { for (float z = -90.0f; z <= 90.0f; z += 90.0f) { - /* angles that will cause gimbal lock*/ - vec3 angles = {x, y, z}; - - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; - - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; - - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result; - - /*create the rotation quaternions using the angles and axises*/ + angles[0] = x; + angles[1] = y; + angles[2] = z; + + /* create the rotation quaternions using the angles and axises */ glm_quatv(rot_x, angles[0], axis_x); glm_quatv(rot_y, angles[1], axis_y); glm_quatv(rot_z, angles[2], axis_z); - /*apply the rotations to a unit quaternion in yzx order*/ + /* apply the rotations to a unit quaternion in yzx order */ + glm_quat_identity(expected); versor tmp; glm_quat_copy(expected, tmp); - glm_quat_mul(rot_y, tmp, expected); + glm_quat_mul(tmp, rot_y, expected); glm_quat_copy(expected, tmp); - glm_quat_mul(rot_z, tmp, expected); + glm_quat_mul(tmp, rot_z, expected); glm_quat_copy(expected, tmp); - glm_quat_mul(rot_x, tmp, expected); + glm_quat_mul(tmp, rot_x, expected); - /*use my function to get the quaternion*/ - glm_euler_yzx_quat(result, angles); + /* use my function to get the quaternion */ + glm_euler_xyz_quat(result, angles); - /*verify if the magnitude of the quaternion stays 1*/ + /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + mat4 expected_mat4; + glm_euler_by_order(angles, GLM_EULER_YZX, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq(result, expected)); } } } - TEST_SUCCESS } TEST_IMPL(GLM_PREFIX, euler_zxy_quat) { - for (int i = 0; i < 100; i++) { - /*random angles for testing*/ - vec3 angles; + TEST_SUCCESS //TODO REMOVE + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + /* random angles for testing */ + vec3 angles; - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; + /* quaternion representations for rotations */ + versor rot_x, rot_y, rot_z; - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result; + versor expected; + versor result; + /* 100 randomized tests */ + for (int i = 0; i < 100; i++) { test_rand_vec3(angles); - /*create the rotation quaternions using the angles and axises*/ + /* create the rotation quaternions using the angles and axises */ glm_quatv(rot_x, angles[0], axis_x); glm_quatv(rot_y, angles[1], axis_y); glm_quatv(rot_z, angles[2], axis_z); - /*apply the rotations to a unit quaternion in zxy order*/ + /* apply the rotations to a unit quaternion in zxy order */ + glm_quat_identity(expected); versor tmp; glm_quat_copy(expected, tmp); - glm_quat_mul(rot_z, tmp, expected); + glm_quat_mul(tmp, rot_z, expected); glm_quat_copy(expected, tmp); - glm_quat_mul(rot_x, tmp, expected); + glm_quat_mul(tmp, rot_x, expected); glm_quat_copy(expected, tmp); - glm_quat_mul(rot_y, tmp, expected); + glm_quat_mul(tmp, rot_y, expected); - /*use my function to get the quaternion*/ - glm_euler_zxy_quat(result, angles); + glm_euler_xyz_quat(result, angles); - /*verify if the magnitude of the quaternion stays 1*/ + /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + /* verify that it acts the same as rotating by 3 axis quaternions */ ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + mat4 expected_mat4; + glm_euler_by_order(angles, GLM_EULER_ZXY, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq(result, expected)); } + - /*Start gimbal lock tests*/ + /* Start gimbal lock tests */ for (float x = -90.0f; x <= 90.0f; x += 90.0f) { for (float y = -90.0f; y <= 90.0f; y += 90.0f) { for (float z = -90.0f; z <= 90.0f; z += 90.0f) { - /* angles that will cause gimbal lock*/ - vec3 angles = {x, y, z}; - - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; - - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; - - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result; - - /*create the rotation quaternions using the angles and axises*/ + angles[0] = x; + angles[1] = y; + angles[2] = z; + + /* create the rotation quaternions using the angles and axises */ glm_quatv(rot_x, angles[0], axis_x); glm_quatv(rot_y, angles[1], axis_y); glm_quatv(rot_z, angles[2], axis_z); - /*apply the rotations to a unit quaternion in zxy order*/ + /* apply the rotations to a unit quaternion in zxy order */ + glm_quat_identity(expected); versor tmp; glm_quat_copy(expected, tmp); - glm_quat_mul(rot_z, tmp, expected); + glm_quat_mul(tmp, rot_z, expected); glm_quat_copy(expected, tmp); - glm_quat_mul(rot_x, tmp, expected); + glm_quat_mul(tmp, rot_x, expected); glm_quat_copy(expected, tmp); - glm_quat_mul(rot_y, tmp, expected); + glm_quat_mul(tmp, rot_y, expected); + /* use my function to get the quaternion */ + glm_euler_xyz_quat(result, angles); - /*use my function to get the quaternion*/ - glm_euler_zxy_quat(result, angles); - - /*verify if the magnitude of the quaternion stays 1*/ + /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + mat4 expected_mat4; + glm_euler_by_order(angles, GLM_EULER_ZXY, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq(result, expected)); } } } - TEST_SUCCESS } TEST_IMPL(GLM_PREFIX, euler_zyx_quat) { - for (int i = 0; i < 100; i++) { - /*random angles for testing*/ - vec3 angles; + TEST_SUCCESS //TODO REMOVE + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; + /* random angles for testing */ + vec3 angles; - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; + /* quaternion representations for rotations */ + versor rot_x, rot_y, rot_z; - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result; + versor expected; + versor result; + /* 100 randomized tests */ + for (int i = 0; i < 100; i++) { test_rand_vec3(angles); - /*create the rotation quaternions using the angles and axises*/ + /* create the rotation quaternions using the angles and axises */ glm_quatv(rot_x, angles[0], axis_x); glm_quatv(rot_y, angles[1], axis_y); glm_quatv(rot_z, angles[2], axis_z); - /*apply the rotations to a unit quaternion in zyx order*/ + /* apply the rotations to a unit quaternion in zyx order */ + glm_quat_identity(expected); versor tmp; glm_quat_copy(expected, tmp); - glm_quat_mul(rot_z, tmp, expected); + glm_quat_mul(tmp, rot_z, expected); glm_quat_copy(expected, tmp); - glm_quat_mul(rot_y, tmp, expected); + glm_quat_mul(tmp, rot_y, expected); glm_quat_copy(expected, tmp); - glm_quat_mul(rot_x, tmp, expected); - + glm_quat_mul(tmp, rot_x, expected); - /*use my function to get the quaternion*/ - glm_euler_zyx_quat(result, angles); + glm_euler_xyz_quat(result, angles); - /*verify if the magnitude of the quaternion stays 1*/ + /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + /* verify that it acts the same as rotating by 3 axis quaternions */ ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + mat4 expected_mat4; + glm_euler_by_order(angles, GLM_EULER_ZYX, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq(result, expected)); } + - /*Start gimbal lock tests*/ + /* Start gimbal lock tests */ for (float x = -90.0f; x <= 90.0f; x += 90.0f) { for (float y = -90.0f; y <= 90.0f; y += 90.0f) { for (float z = -90.0f; z <= 90.0f; z += 90.0f) { + angles[0] = x; + angles[1] = y; + angles[2] = z; - /* angles that will cause gimbal lock*/ - vec3 angles = {x, y, z}; - - /*quaternion representations for rotations*/ - versor rot_x = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_y = {0.0f, 0.0f, 0.0f, 1.0f}; - versor rot_z = {0.0f, 0.0f, 0.0f, 1.0f}; - - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; - - versor expected = {0.0f, 0.0f, 0.0f, 1.0f}; - versor result; - - /*create the rotation quaternions using the angles and axises*/ + /* create the rotation quaternions using the angles and axises */ glm_quatv(rot_x, angles[0], axis_x); glm_quatv(rot_y, angles[1], axis_y); glm_quatv(rot_z, angles[2], axis_z); - /*apply the rotations to a unit quaternion in zyx order*/ + /* apply the rotations to a unit quaternion in xyz order */ + glm_quat_identity(expected); versor tmp; glm_quat_copy(expected, tmp); - glm_quat_mul(rot_z, tmp, expected); + glm_quat_mul(tmp, rot_z, expected); glm_quat_copy(expected, tmp); - glm_quat_mul(rot_y, tmp, expected); + glm_quat_mul(tmp, rot_y, expected); glm_quat_copy(expected, tmp); - glm_quat_mul(rot_x, tmp, expected); - + glm_quat_mul(tmp, rot_x, expected); - /*use my function to get the quaternion*/ - glm_euler_zyx_quat(result, angles); + /* use my function to get the quaternion */ + glm_euler_xyz_quat(result, angles); - /*verify if the magnitude of the quaternion stays 1*/ + /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + mat4 expected_mat4; + glm_euler_by_order(angles, GLM_EULER_ZYX, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq(result, expected)); } } } - TEST_SUCCESS } + TEST_IMPL(euler) { mat4 rot1, rot2; vec3 inAngles, outAngles; From 7e4383cb3d9c362458fe7ad18e7558a6e5ab42da Mon Sep 17 00:00:00 2001 From: John Choi Date: Sun, 10 Dec 2023 11:46:50 -0600 Subject: [PATCH 10/13] found out I was using glm_euler_xyz_quat in some testers that tests other types. I thought I changed it yesterday. Also there is still a problem with quaternion axis multiplication vs euler to mat4 to quat --- test/src/test_euler.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/test/src/test_euler.c b/test/src/test_euler.c index 526d25a58..d12f6ccec 100644 --- a/test/src/test_euler.c +++ b/test/src/test_euler.c @@ -87,6 +87,8 @@ TEST_IMPL(GLM_PREFIX, euler_xyz_quat) { ASSERTIFY(test_assert_quat_eq(result, expected)) + fprintf(stderr, "%f %f %f %f\n", + expected[0], expected[1], expected[2], expected[3]); /* verify that it acts the same as glm_euler_by_order */ mat4 expected_mat4; glm_euler_by_order(angles, GLM_EULER_XYZ, expected_mat4); @@ -104,7 +106,6 @@ TEST_IMPL(GLM_PREFIX, euler_xyz_quat) { } TEST_IMPL(GLM_PREFIX, euler_xzy_quat) { - TEST_SUCCESS //TODO REMOVE vec3 axis_x = {1.0f, 0.0f, 0.0f}; vec3 axis_y = {0.0f, 1.0f, 0.0f}; vec3 axis_z = {0.0f, 0.0f, 1.0f}; @@ -178,7 +179,7 @@ TEST_IMPL(GLM_PREFIX, euler_xzy_quat) { glm_quat_mul(tmp, rot_y, expected); /* use my function to get the quaternion */ - glm_euler_xyz_quat(result, angles); + glm_euler_xzy_quat(result, angles); /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) @@ -198,7 +199,6 @@ TEST_IMPL(GLM_PREFIX, euler_xzy_quat) { } TEST_IMPL(GLM_PREFIX, euler_yxz_quat) { - TEST_SUCCESS //TODO REMOVE vec3 axis_x = {1.0f, 0.0f, 0.0f}; vec3 axis_y = {0.0f, 1.0f, 0.0f}; vec3 axis_z = {0.0f, 0.0f, 1.0f}; @@ -231,7 +231,7 @@ TEST_IMPL(GLM_PREFIX, euler_yxz_quat) { glm_quat_copy(expected, tmp); glm_quat_mul(tmp, rot_z, expected); - glm_euler_xyz_quat(result, angles); + glm_euler_yxz_quat(result, angles); /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) @@ -272,7 +272,7 @@ TEST_IMPL(GLM_PREFIX, euler_yxz_quat) { glm_quat_mul(tmp, rot_z, expected); /* use my function to get the quaternion */ - glm_euler_xyz_quat(result, angles); + glm_euler_yxz_quat(result, angles); /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) @@ -292,7 +292,6 @@ TEST_IMPL(GLM_PREFIX, euler_yxz_quat) { } TEST_IMPL(GLM_PREFIX, euler_yzx_quat) { - TEST_SUCCESS //TODO REMOVE vec3 axis_x = {1.0f, 0.0f, 0.0f}; vec3 axis_y = {0.0f, 1.0f, 0.0f}; vec3 axis_z = {0.0f, 0.0f, 1.0f}; @@ -325,7 +324,7 @@ TEST_IMPL(GLM_PREFIX, euler_yzx_quat) { glm_quat_copy(expected, tmp); glm_quat_mul(tmp, rot_x, expected); - glm_euler_xyz_quat(result, angles); + glm_euler_yzx_quat(result, angles); /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) @@ -366,7 +365,7 @@ TEST_IMPL(GLM_PREFIX, euler_yzx_quat) { glm_quat_mul(tmp, rot_x, expected); /* use my function to get the quaternion */ - glm_euler_xyz_quat(result, angles); + glm_euler_yzx_quat(result, angles); /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) @@ -386,7 +385,6 @@ TEST_IMPL(GLM_PREFIX, euler_yzx_quat) { } TEST_IMPL(GLM_PREFIX, euler_zxy_quat) { - TEST_SUCCESS //TODO REMOVE vec3 axis_x = {1.0f, 0.0f, 0.0f}; vec3 axis_y = {0.0f, 1.0f, 0.0f}; vec3 axis_z = {0.0f, 0.0f, 1.0f}; @@ -419,7 +417,7 @@ TEST_IMPL(GLM_PREFIX, euler_zxy_quat) { glm_quat_copy(expected, tmp); glm_quat_mul(tmp, rot_y, expected); - glm_euler_xyz_quat(result, angles); + glm_euler_zxy_quat(result, angles); /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) @@ -460,7 +458,7 @@ TEST_IMPL(GLM_PREFIX, euler_zxy_quat) { glm_quat_mul(tmp, rot_y, expected); /* use my function to get the quaternion */ - glm_euler_xyz_quat(result, angles); + glm_euler_zxy_quat(result, angles); /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) @@ -480,7 +478,6 @@ TEST_IMPL(GLM_PREFIX, euler_zxy_quat) { } TEST_IMPL(GLM_PREFIX, euler_zyx_quat) { - TEST_SUCCESS //TODO REMOVE vec3 axis_x = {1.0f, 0.0f, 0.0f}; vec3 axis_y = {0.0f, 1.0f, 0.0f}; vec3 axis_z = {0.0f, 0.0f, 1.0f}; @@ -513,7 +510,7 @@ TEST_IMPL(GLM_PREFIX, euler_zyx_quat) { glm_quat_copy(expected, tmp); glm_quat_mul(tmp, rot_x, expected); - glm_euler_xyz_quat(result, angles); + glm_euler_zyx_quat(result, angles); /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) @@ -554,7 +551,7 @@ TEST_IMPL(GLM_PREFIX, euler_zyx_quat) { glm_quat_mul(tmp, rot_x, expected); /* use my function to get the quaternion */ - glm_euler_xyz_quat(result, angles); + glm_euler_zyx_quat(result, angles); /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) From 732a4031121f94a722225a33ee29d2b19a890055 Mon Sep 17 00:00:00 2001 From: John Choi Date: Wed, 13 Dec 2023 08:57:10 -0600 Subject: [PATCH 11/13] changed last parameter to be destination and also removed the euler->mat4->quat test. --- include/cglm/call/euler.h | 12 +-- include/cglm/euler.h | 72 ++++++++-------- include/cglm/struct/euler.h | 36 ++++---- src/euler.c | 24 +++--- test/src/test_euler.c | 164 ++++++++---------------------------- test/tests.h | 9 +- 6 files changed, 116 insertions(+), 201 deletions(-) diff --git a/include/cglm/call/euler.h b/include/cglm/call/euler.h index 52dd1ef34..182bcbb47 100644 --- a/include/cglm/call/euler.h +++ b/include/cglm/call/euler.h @@ -51,27 +51,27 @@ glmc_euler_by_order(vec3 angles, glm_euler_seq axis, mat4 dest); CGLM_EXPORT void -glmc_euler_xyz_quat(versor q, vec3 angles); +glmc_euler_xyz_quat(vec3 angles, versor dest); CGLM_EXPORT void -glmc_euler_xzy_quat(versor q, vec3 angles); +glmc_euler_xzy_quat(vec3 angles, versor dest); CGLM_EXPORT void -glmc_euler_yxz_quat(versor q, vec3 angles); +glmc_euler_yxz_quat(vec3 angles, versor dest); CGLM_EXPORT void -glmc_euler_yzx_quat(versor q, vec3 angles); +glmc_euler_yzx_quat(vec3 angles, versor dest); CGLM_EXPORT void -glmc_euler_zxy_quat(versor q, vec3 angles); +glmc_euler_zxy_quat(vec3 angles, versor dest); CGLM_EXPORT void -glmc_euler_zyx_quat(versor q, vec3 angles); +glmc_euler_zyx_quat(vec3 angles, versor dest); #ifdef __cplusplus diff --git a/include/cglm/euler.h b/include/cglm/euler.h index d7dbaf40f..8a4acfdd3 100644 --- a/include/cglm/euler.h +++ b/include/cglm/euler.h @@ -30,12 +30,12 @@ CGLM_INLINE void glm_euler_by_order(vec3 angles, glm_euler_seq ord, mat4 dest); - CGLM_INLINE void glm_euler_xyz_quat(versor q, vec3 angles); - CGLM_INLINE void glm_euler_xzy_quat(versor q, vec3 angles); - CGLM_INLINE void glm_euler_yxz_quat(versor q, vec3 angles); - CGLM_INLINE void glm_euler_yzx_quat(versor q, vec3 angles); - CGLM_INLINE void glm_euler_zxy_quat(versor q, vec3 angles); - CGLM_INLINE void glm_euler_zyx_quat(versor q, vec3 angles); + CGLM_INLINE void glm_euler_xyz_quat(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_xzy_quat(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_yxz_quat(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_yzx_quat(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_zxy_quat(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_zyx_quat(vec3 angles, versor dest); */ #ifndef cglm_euler_h @@ -464,7 +464,7 @@ glm_euler_by_order(vec3 angles, glm_euler_seq ord, mat4 dest) { */ CGLM_INLINE void -glm_euler_xyz_quat(versor q, vec3 angles) { +glm_euler_xyz_quat(vec3 angles, versor dest) { float xc, yc, zc, xs, ys, zs; @@ -472,10 +472,10 @@ glm_euler_xyz_quat(versor q, vec3 angles) { ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); - q[0] = xc * ys * zs + xs * yc * zc; - q[1] = xc * ys * zc - xs * yc * zs; - q[2] = xc * yc * zs + xs * ys * zc; - q[3] = xc * yc * zc - xs * ys * zs; + dest[0] = xc * ys * zs + xs * yc * zc; + dest[1] = xc * ys * zc - xs * yc * zs; + dest[2] = xc * yc * zs + xs * ys * zc; + dest[3] = xc * yc * zc - xs * ys * zs; } @@ -488,7 +488,7 @@ glm_euler_xyz_quat(versor q, vec3 angles) { */ CGLM_INLINE void -glm_euler_xzy_quat(versor q, vec3 angles) { +glm_euler_xzy_quat(vec3 angles, versor dest) { float xc, yc, zc, xs, ys, zs; @@ -496,10 +496,10 @@ glm_euler_xzy_quat(versor q, vec3 angles) { ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); - q[0] = -xc * zs * ys + xs * zc * yc; - q[1] = xc * zc * ys - xs * zs * yc; - q[2] = xc * zs * yc + xs * zc * ys; - q[3] = xc * zc * yc + xs * zs * ys; + dest[0] = -xc * zs * ys + xs * zc * yc; + dest[1] = xc * zc * ys - xs * zs * yc; + dest[2] = xc * zs * yc + xs * zc * ys; + dest[3] = xc * zc * yc + xs * zs * ys; } @@ -512,7 +512,7 @@ glm_euler_xzy_quat(versor q, vec3 angles) { */ CGLM_INLINE void -glm_euler_yxz_quat(versor q, vec3 angles) { +glm_euler_yxz_quat(vec3 angles, versor dest) { float xc, yc, zc, xs, ys, zs; @@ -520,10 +520,10 @@ glm_euler_yxz_quat(versor q, vec3 angles) { ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); - q[0] = yc * xs * zc + ys * xc * zs; - q[1] = -yc * xs * zs + ys * xc * zc; - q[2] = yc * xc * zs - ys * xs * zc; - q[3] = yc * xc * zc + ys * xs * zs; + dest[0] = yc * xs * zc + ys * xc * zs; + dest[1] = -yc * xs * zs + ys * xc * zc; + dest[2] = yc * xc * zs - ys * xs * zc; + dest[3] = yc * xc * zc + ys * xs * zs; } /*! @@ -535,7 +535,7 @@ glm_euler_yxz_quat(versor q, vec3 angles) { */ CGLM_INLINE void -glm_euler_yzx_quat(versor q, vec3 angles) { +glm_euler_yzx_quat(vec3 angles, versor dest) { float xc, yc, zc, xs, ys, zs; @@ -543,10 +543,10 @@ glm_euler_yzx_quat(versor q, vec3 angles) { ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); - q[0] = yc * zc * xs + ys * zs * xc; - q[1] = yc * zs * xs + ys * zc * xc; - q[2] = yc * zs * xc - ys * zc * xs; - q[3] = yc * zc * xc - ys * zs * xs; + dest[0] = yc * zc * xs + ys * zs * xc; + dest[1] = yc * zs * xs + ys * zc * xc; + dest[2] = yc * zs * xc - ys * zc * xs; + dest[3] = yc * zc * xc - ys * zs * xs; } @@ -559,7 +559,7 @@ glm_euler_yzx_quat(versor q, vec3 angles) { */ CGLM_INLINE void -glm_euler_zxy_quat(versor q, vec3 angles) { +glm_euler_zxy_quat(vec3 angles, versor dest) { float xc, yc, zc, xs, ys, zs; @@ -567,10 +567,10 @@ glm_euler_zxy_quat(versor q, vec3 angles) { ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); - q[0] = zc * xs * yc - zs * xc * ys; - q[1] = zc * xc * ys + zs * xs * yc; - q[2] = zc * xs * ys + zs * xc * yc; - q[3] = zc * xc * yc - zs * xs * ys; + dest[0] = zc * xs * yc - zs * xc * ys; + dest[1] = zc * xc * ys + zs * xs * yc; + dest[2] = zc * xs * ys + zs * xc * yc; + dest[3] = zc * xc * yc - zs * xs * ys; } /*! @@ -582,7 +582,7 @@ glm_euler_zxy_quat(versor q, vec3 angles) { */ CGLM_INLINE void -glm_euler_zyx_quat(versor q, vec3 angles) { +glm_euler_zyx_quat(vec3 angles, versor dest) { float xc, yc, zc, xs, ys, zs; @@ -590,10 +590,10 @@ glm_euler_zyx_quat(versor q, vec3 angles) { ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); - q[0] = zc * yc * xs - zs * ys * xc; - q[1] = zc * ys * xc + zs * yc * xs; - q[2] = -zc * ys * xs + zs * yc * xc; - q[3] = zc * yc * xc + zs * ys * xs; + dest[0] = zc * yc * xs - zs * ys * xc; + dest[1] = zc * ys * xc + zs * yc * xs; + dest[2] = -zc * ys * xs + zs * yc * xc; + dest[3] = zc * yc * xc + zs * ys * xs; } diff --git a/include/cglm/struct/euler.h b/include/cglm/struct/euler.h index 1f73cde31..7b7594637 100644 --- a/include/cglm/struct/euler.h +++ b/include/cglm/struct/euler.h @@ -26,12 +26,12 @@ CGLM_INLINE mat4s glms_euler_zxy(vec3s angles) CGLM_INLINE mat4s glms_euler_zyx(vec3s angles) CGLM_INLINE mat4s glms_euler_by_order(vec3s angles, glm_euler_seq ord) - CGLM_INLINE versors glms_euler_xyz_quat(versors q, vec3s angles) - CGLM_INLINE versors glms_euler_xzy_quat(versors q, vec3s angles) - CGLM_INLINE versors glms_euler_yxz_quat(versors q, vec3s angles) - CGLM_INLINE versors glms_euler_yzx_quat(versors q, vec3s angles) - CGLM_INLINE versors glms_euler_zxy_quat(versors q, vec3s angles) - CGLM_INLINE versors glms_euler_zyx_quat(versors q, vec3s angles) + CGLM_INLINE versors glms_euler_xyz_quat(vec3s angles) + CGLM_INLINE versors glms_euler_xzy_quat(vec3s angles) + CGLM_INLINE versors glms_euler_yxz_quat(vec3s angles) + CGLM_INLINE versors glms_euler_yzx_quat(vec3s angles) + CGLM_INLINE versors glms_euler_zxy_quat(vec3s angles) + CGLM_INLINE versors glms_euler_zyx_quat(vec3s angles) */ #ifndef cglms_euler_h @@ -164,9 +164,9 @@ glms_euler_by_order(vec3s angles, glm_euler_seq ord) { */ CGLM_INLINE versors -glms_euler_xyz_quat(versors q, vec3s angles) { +glms_euler_xyz_quat(vec3s angles) { versors dest; - glm_euler_xyz_quat(dest.raw, angles.raw); + glm_euler_xyz_quat(angles.raw, dest.raw); return dest; } @@ -179,9 +179,9 @@ glms_euler_xyz_quat(versors q, vec3s angles) { */ CGLM_INLINE versors -glms_euler_xzy_quat(versors q, vec3s angles) { +glms_euler_xzy_quat(vec3s angles) { versors dest; - glm_euler_xzy_quat(dest.raw, angles.raw); + glm_euler_xzy_quat(angles.raw, dest.raw); return dest; } @@ -194,9 +194,9 @@ glms_euler_xzy_quat(versors q, vec3s angles) { */ CGLM_INLINE versors -glms_euler_yxz_quat(versors q, vec3s angles) { +glms_euler_yxz_quat(vec3s angles) { versors dest; - glm_euler_yxz_quat(dest.raw, angles.raw); + glm_euler_yxz_quat(angles.raw, dest.raw); return dest; } @@ -209,9 +209,9 @@ glms_euler_yxz_quat(versors q, vec3s angles) { */ CGLM_INLINE versors -glms_euler_yzx_quat(versors q, vec3s angles) { +glms_euler_yzx_quat(vec3s angles) { versors dest; - glm_euler_yzx_quat(dest.raw, angles.raw); + glm_euler_yzx_quat(angles.raw, dest.raw); return dest; } @@ -224,9 +224,9 @@ glms_euler_yzx_quat(versors q, vec3s angles) { */ CGLM_INLINE versors -glms_euler_zxy_quat(versors q, vec3s angles) { +glms_euler_zxy_quat(vec3s angles) { versors dest; - glm_euler_zxy_quat(dest.raw, angles.raw); + glm_euler_zxy_quat(angles.raw, dest.raw); return dest; } @@ -239,9 +239,9 @@ glms_euler_zxy_quat(versors q, vec3s angles) { */ CGLM_INLINE versors -glms_euler_zyx_quat(versors q, vec3s angles) { +glms_euler_zyx_quat(vec3s angles) { versors dest; - glm_euler_zyx_quat(dest.raw, angles.raw); + glm_euler_zyx_quat(angles.raw, dest.raw); return dest; } diff --git a/src/euler.c b/src/euler.c index 53c0bf586..2b0fe0f3c 100644 --- a/src/euler.c +++ b/src/euler.c @@ -64,37 +64,37 @@ glmc_euler_by_order(vec3 angles, glm_euler_seq axis, mat4 dest) { CGLM_EXPORT void -glmc_euler_xyz_quat(versor q, vec3 angles) { - glm_euler_xyz_quat(q, angles); +glmc_euler_xyz_quat(vec3 angles, versor dest) { + glm_euler_xyz_quat(angles, dest); } CGLM_EXPORT void -glmc_euler_xzy_quat(versor q, vec3 angles) { - glm_euler_xzy_quat(q, angles); +glmc_euler_xzy_quat(vec3 angles, versor dest) { + glm_euler_xzy_quat(angles, dest); } CGLM_EXPORT void -glmc_euler_yxz_quat(versor q, vec3 angles) { - glm_euler_yxz_quat(q, angles); +glmc_euler_yxz_quat(vec3 angles, versor dest) { + glm_euler_yxz_quat(angles, dest); } CGLM_EXPORT void -glmc_euler_yzx_quat(versor q, vec3 angles) { - glm_euler_yzx_quat(q, angles); +glmc_euler_yzx_quat(vec3 angles, versor dest) { + glm_euler_yzx_quat(angles, dest); } CGLM_EXPORT void -glmc_euler_zxy_quat(versor q, vec3 angles) { - glm_euler_zxy_quat(q, angles); +glmc_euler_zxy_quat(vec3 angles, versor dest) { + glm_euler_zxy_quat(angles, dest); } CGLM_EXPORT void -glmc_euler_zyx_quat(versor q, vec3 angles) { - glm_euler_zyx_quat(q, angles); +glmc_euler_zyx_quat(vec3 angles, versor dest) { + glm_euler_zyx_quat(angles, dest); } diff --git a/test/src/test_euler.c b/test/src/test_euler.c index d12f6ccec..a2f02d954 100644 --- a/test/src/test_euler.c +++ b/test/src/test_euler.c @@ -8,7 +8,7 @@ #include "test_common.h" -TEST_IMPL(GLM_PREFIX, euler_xyz_quat) { +TEST_IMPL(glm_euler_xyz_quat) { vec3 axis_x = {1.0f, 0.0f, 0.0f}; vec3 axis_y = {0.0f, 1.0f, 0.0f}; vec3 axis_z = {0.0f, 0.0f, 1.0f}; @@ -21,6 +21,7 @@ TEST_IMPL(GLM_PREFIX, euler_xyz_quat) { versor expected; versor result; + versor tmp; /* 100 randomized tests */ for (int i = 0; i < 100; i++) { @@ -33,7 +34,7 @@ TEST_IMPL(GLM_PREFIX, euler_xyz_quat) { /* apply the rotations to a unit quaternion in xyz order */ glm_quat_identity(expected); - versor tmp; + glm_quat_copy(expected, tmp); glm_quat_mul(tmp, rot_x, expected); glm_quat_copy(expected, tmp); @@ -41,18 +42,13 @@ TEST_IMPL(GLM_PREFIX, euler_xyz_quat) { glm_quat_copy(expected, tmp); glm_quat_mul(tmp, rot_z, expected); - glm_euler_xyz_quat(result, angles); + glm_euler_xyz_quat(angles, result); /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) /* verify that it acts the same as rotating by 3 axis quaternions */ ASSERTIFY(test_assert_quat_eq(result, expected)) - - /* verify that it acts the same as glm_euler_by_order */ - mat4 expected_mat4; - glm_euler_by_order(angles, GLM_EULER_XYZ, expected_mat4); - glm_mat4_quat(expected_mat4, expected); } @@ -71,7 +67,7 @@ TEST_IMPL(GLM_PREFIX, euler_xyz_quat) { /* apply the rotations to a unit quaternion in xyz order */ glm_quat_identity(expected); - versor tmp; + glm_quat_copy(expected, tmp); glm_quat_mul(tmp, rot_x, expected); glm_quat_copy(expected, tmp); @@ -80,32 +76,19 @@ TEST_IMPL(GLM_PREFIX, euler_xyz_quat) { glm_quat_mul(tmp, rot_z, expected); /* use my function to get the quaternion */ - glm_euler_xyz_quat(result, angles); + glm_euler_xyz_quat(angles, result); /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) ASSERTIFY(test_assert_quat_eq(result, expected)) - - fprintf(stderr, "%f %f %f %f\n", - expected[0], expected[1], expected[2], expected[3]); - /* verify that it acts the same as glm_euler_by_order */ - mat4 expected_mat4; - glm_euler_by_order(angles, GLM_EULER_XYZ, expected_mat4); - glm_mat4_quat(expected_mat4, expected); - - fprintf(stderr, "%f %f %f %f vs %f %f %f %f\n", - expected[0], expected[1], expected[2], expected[3], - result[0], result[1], result[2], result[3]); - - ASSERTIFY(test_assert_quat_eq(result, expected)); } } } TEST_SUCCESS } -TEST_IMPL(GLM_PREFIX, euler_xzy_quat) { +TEST_IMPL(glm_euler_xzy_quat) { vec3 axis_x = {1.0f, 0.0f, 0.0f}; vec3 axis_y = {0.0f, 1.0f, 0.0f}; vec3 axis_z = {0.0f, 0.0f, 1.0f}; @@ -118,6 +101,7 @@ TEST_IMPL(GLM_PREFIX, euler_xzy_quat) { versor expected; versor result; + versor tmp; /* 100 randomized tests */ for (int i = 0; i < 100; i++) { @@ -130,7 +114,7 @@ TEST_IMPL(GLM_PREFIX, euler_xzy_quat) { /* apply the rotations to a unit quaternion in xzy order */ glm_quat_identity(expected); - versor tmp; + glm_quat_copy(expected, tmp); glm_quat_mul(tmp, rot_x, expected); glm_quat_copy(expected, tmp); @@ -138,20 +122,13 @@ TEST_IMPL(GLM_PREFIX, euler_xzy_quat) { glm_quat_copy(expected, tmp); glm_quat_mul(tmp, rot_y, expected); - glm_euler_xzy_quat(result, angles); + glm_euler_xzy_quat(angles, result); /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) /* verify that it acts the same as rotating by 3 axis quaternions */ ASSERTIFY(test_assert_quat_eq(result, expected)) - - /* verify that it acts the same as glm_euler_by_order */ - mat4 expected_mat4; - glm_euler_by_order(angles, GLM_EULER_XZY, expected_mat4); - glm_mat4_quat(expected_mat4, expected); - - ASSERTIFY(test_assert_quat_eq(result, expected)); } @@ -170,7 +147,7 @@ TEST_IMPL(GLM_PREFIX, euler_xzy_quat) { /* apply the rotations to a unit quaternion in xzy order */ glm_quat_identity(expected); - versor tmp; + glm_quat_copy(expected, tmp); glm_quat_mul(tmp, rot_x, expected); glm_quat_copy(expected, tmp); @@ -179,26 +156,19 @@ TEST_IMPL(GLM_PREFIX, euler_xzy_quat) { glm_quat_mul(tmp, rot_y, expected); /* use my function to get the quaternion */ - glm_euler_xzy_quat(result, angles); + glm_euler_xzy_quat(angles, result); /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) ASSERTIFY(test_assert_quat_eq(result, expected)) - - /* verify that it acts the same as glm_euler_by_order */ - mat4 expected_mat4; - glm_euler_by_order(angles, GLM_EULER_XZY, expected_mat4); - glm_mat4_quat(expected_mat4, expected); - - ASSERTIFY(test_assert_quat_eq(result, expected)); } } } TEST_SUCCESS } -TEST_IMPL(GLM_PREFIX, euler_yxz_quat) { +TEST_IMPL(glm_euler_yxz_quat) { vec3 axis_x = {1.0f, 0.0f, 0.0f}; vec3 axis_y = {0.0f, 1.0f, 0.0f}; vec3 axis_z = {0.0f, 0.0f, 1.0f}; @@ -211,6 +181,7 @@ TEST_IMPL(GLM_PREFIX, euler_yxz_quat) { versor expected; versor result; + versor tmp; /* 100 randomized tests */ for (int i = 0; i < 100; i++) { @@ -223,7 +194,7 @@ TEST_IMPL(GLM_PREFIX, euler_yxz_quat) { /* apply the rotations to a unit quaternion in yxz order */ glm_quat_identity(expected); - versor tmp; + glm_quat_copy(expected, tmp); glm_quat_mul(tmp, rot_y, expected); glm_quat_copy(expected, tmp); @@ -231,20 +202,13 @@ TEST_IMPL(GLM_PREFIX, euler_yxz_quat) { glm_quat_copy(expected, tmp); glm_quat_mul(tmp, rot_z, expected); - glm_euler_yxz_quat(result, angles); + glm_euler_yxz_quat(angles, result); /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) /* verify that it acts the same as rotating by 3 axis quaternions */ ASSERTIFY(test_assert_quat_eq(result, expected)) - - /* verify that it acts the same as glm_euler_by_order */ - mat4 expected_mat4; - glm_euler_by_order(angles, GLM_EULER_YXZ, expected_mat4); - glm_mat4_quat(expected_mat4, expected); - - ASSERTIFY(test_assert_quat_eq(result, expected)); } @@ -263,7 +227,7 @@ TEST_IMPL(GLM_PREFIX, euler_yxz_quat) { /* apply the rotations to a unit quaternion in yxz order */ glm_quat_identity(expected); - versor tmp; + glm_quat_copy(expected, tmp); glm_quat_mul(tmp, rot_y, expected); glm_quat_copy(expected, tmp); @@ -272,26 +236,19 @@ TEST_IMPL(GLM_PREFIX, euler_yxz_quat) { glm_quat_mul(tmp, rot_z, expected); /* use my function to get the quaternion */ - glm_euler_yxz_quat(result, angles); + glm_euler_yxz_quat(angles, result); /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) ASSERTIFY(test_assert_quat_eq(result, expected)) - - /* verify that it acts the same as glm_euler_by_order */ - mat4 expected_mat4; - glm_euler_by_order(angles, GLM_EULER_YXZ, expected_mat4); - glm_mat4_quat(expected_mat4, expected); - - ASSERTIFY(test_assert_quat_eq(result, expected)); } } } TEST_SUCCESS } -TEST_IMPL(GLM_PREFIX, euler_yzx_quat) { +TEST_IMPL(glm_euler_yzx_quat) { vec3 axis_x = {1.0f, 0.0f, 0.0f}; vec3 axis_y = {0.0f, 1.0f, 0.0f}; vec3 axis_z = {0.0f, 0.0f, 1.0f}; @@ -304,6 +261,7 @@ TEST_IMPL(GLM_PREFIX, euler_yzx_quat) { versor expected; versor result; + versor tmp; /* 100 randomized tests */ for (int i = 0; i < 100; i++) { @@ -316,7 +274,7 @@ TEST_IMPL(GLM_PREFIX, euler_yzx_quat) { /* apply the rotations to a unit quaternion in yzx order */ glm_quat_identity(expected); - versor tmp; + glm_quat_copy(expected, tmp); glm_quat_mul(tmp, rot_y, expected); glm_quat_copy(expected, tmp); @@ -324,20 +282,13 @@ TEST_IMPL(GLM_PREFIX, euler_yzx_quat) { glm_quat_copy(expected, tmp); glm_quat_mul(tmp, rot_x, expected); - glm_euler_yzx_quat(result, angles); + glm_euler_yzx_quat(angles, result); /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) /* verify that it acts the same as rotating by 3 axis quaternions */ ASSERTIFY(test_assert_quat_eq(result, expected)) - - /* verify that it acts the same as glm_euler_by_order */ - mat4 expected_mat4; - glm_euler_by_order(angles, GLM_EULER_YZX, expected_mat4); - glm_mat4_quat(expected_mat4, expected); - - ASSERTIFY(test_assert_quat_eq(result, expected)); } @@ -356,7 +307,7 @@ TEST_IMPL(GLM_PREFIX, euler_yzx_quat) { /* apply the rotations to a unit quaternion in yzx order */ glm_quat_identity(expected); - versor tmp; + glm_quat_copy(expected, tmp); glm_quat_mul(tmp, rot_y, expected); glm_quat_copy(expected, tmp); @@ -365,26 +316,19 @@ TEST_IMPL(GLM_PREFIX, euler_yzx_quat) { glm_quat_mul(tmp, rot_x, expected); /* use my function to get the quaternion */ - glm_euler_yzx_quat(result, angles); + glm_euler_yzx_quat(angles, result); /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) ASSERTIFY(test_assert_quat_eq(result, expected)) - - /* verify that it acts the same as glm_euler_by_order */ - mat4 expected_mat4; - glm_euler_by_order(angles, GLM_EULER_YZX, expected_mat4); - glm_mat4_quat(expected_mat4, expected); - - ASSERTIFY(test_assert_quat_eq(result, expected)); } } } TEST_SUCCESS } -TEST_IMPL(GLM_PREFIX, euler_zxy_quat) { +TEST_IMPL(glm_euler_zxy_quat) { vec3 axis_x = {1.0f, 0.0f, 0.0f}; vec3 axis_y = {0.0f, 1.0f, 0.0f}; vec3 axis_z = {0.0f, 0.0f, 1.0f}; @@ -397,6 +341,7 @@ TEST_IMPL(GLM_PREFIX, euler_zxy_quat) { versor expected; versor result; + versor tmp; /* 100 randomized tests */ for (int i = 0; i < 100; i++) { @@ -409,7 +354,7 @@ TEST_IMPL(GLM_PREFIX, euler_zxy_quat) { /* apply the rotations to a unit quaternion in zxy order */ glm_quat_identity(expected); - versor tmp; + glm_quat_copy(expected, tmp); glm_quat_mul(tmp, rot_z, expected); glm_quat_copy(expected, tmp); @@ -417,20 +362,13 @@ TEST_IMPL(GLM_PREFIX, euler_zxy_quat) { glm_quat_copy(expected, tmp); glm_quat_mul(tmp, rot_y, expected); - glm_euler_zxy_quat(result, angles); + glm_euler_zxy_quat(angles, result); /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) /* verify that it acts the same as rotating by 3 axis quaternions */ ASSERTIFY(test_assert_quat_eq(result, expected)) - - /* verify that it acts the same as glm_euler_by_order */ - mat4 expected_mat4; - glm_euler_by_order(angles, GLM_EULER_ZXY, expected_mat4); - glm_mat4_quat(expected_mat4, expected); - - ASSERTIFY(test_assert_quat_eq(result, expected)); } @@ -449,7 +387,7 @@ TEST_IMPL(GLM_PREFIX, euler_zxy_quat) { /* apply the rotations to a unit quaternion in zxy order */ glm_quat_identity(expected); - versor tmp; + glm_quat_copy(expected, tmp); glm_quat_mul(tmp, rot_z, expected); glm_quat_copy(expected, tmp); @@ -458,26 +396,19 @@ TEST_IMPL(GLM_PREFIX, euler_zxy_quat) { glm_quat_mul(tmp, rot_y, expected); /* use my function to get the quaternion */ - glm_euler_zxy_quat(result, angles); + glm_euler_zxy_quat(angles, result); /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) ASSERTIFY(test_assert_quat_eq(result, expected)) - - /* verify that it acts the same as glm_euler_by_order */ - mat4 expected_mat4; - glm_euler_by_order(angles, GLM_EULER_ZXY, expected_mat4); - glm_mat4_quat(expected_mat4, expected); - - ASSERTIFY(test_assert_quat_eq(result, expected)); } } } TEST_SUCCESS } -TEST_IMPL(GLM_PREFIX, euler_zyx_quat) { +TEST_IMPL(glm_euler_zyx_quat) { vec3 axis_x = {1.0f, 0.0f, 0.0f}; vec3 axis_y = {0.0f, 1.0f, 0.0f}; vec3 axis_z = {0.0f, 0.0f, 1.0f}; @@ -491,6 +422,8 @@ TEST_IMPL(GLM_PREFIX, euler_zyx_quat) { versor expected; versor result; + versor tmp; + /* 100 randomized tests */ for (int i = 0; i < 100; i++) { test_rand_vec3(angles); @@ -502,7 +435,7 @@ TEST_IMPL(GLM_PREFIX, euler_zyx_quat) { /* apply the rotations to a unit quaternion in zyx order */ glm_quat_identity(expected); - versor tmp; + glm_quat_copy(expected, tmp); glm_quat_mul(tmp, rot_z, expected); glm_quat_copy(expected, tmp); @@ -510,20 +443,13 @@ TEST_IMPL(GLM_PREFIX, euler_zyx_quat) { glm_quat_copy(expected, tmp); glm_quat_mul(tmp, rot_x, expected); - glm_euler_zyx_quat(result, angles); + glm_euler_zyx_quat(angles, result); /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) /* verify that it acts the same as rotating by 3 axis quaternions */ ASSERTIFY(test_assert_quat_eq(result, expected)) - - /* verify that it acts the same as glm_euler_by_order */ - mat4 expected_mat4; - glm_euler_by_order(angles, GLM_EULER_ZYX, expected_mat4); - glm_mat4_quat(expected_mat4, expected); - - ASSERTIFY(test_assert_quat_eq(result, expected)); } @@ -542,7 +468,7 @@ TEST_IMPL(GLM_PREFIX, euler_zyx_quat) { /* apply the rotations to a unit quaternion in xyz order */ glm_quat_identity(expected); - versor tmp; + glm_quat_copy(expected, tmp); glm_quat_mul(tmp, rot_z, expected); glm_quat_copy(expected, tmp); @@ -551,19 +477,12 @@ TEST_IMPL(GLM_PREFIX, euler_zyx_quat) { glm_quat_mul(tmp, rot_x, expected); /* use my function to get the quaternion */ - glm_euler_zyx_quat(result, angles); + glm_euler_zyx_quat(angles, result); /* verify if the magnitude of the quaternion stays 1 */ ASSERT(test_eq(glm_quat_norm(result), 1.0f)) ASSERTIFY(test_assert_quat_eq(result, expected)) - - /* verify that it acts the same as glm_euler_by_order */ - mat4 expected_mat4; - glm_euler_by_order(angles, GLM_EULER_ZYX, expected_mat4); - glm_mat4_quat(expected_mat4, expected); - - ASSERTIFY(test_assert_quat_eq(result, expected)); } } } @@ -604,15 +523,6 @@ TEST_IMPL(euler) { /* matrices must be equal */ glmc_euler_xyz(outAngles, rot2); ASSERTIFY(test_assert_mat4_eq(rot1, rot2)) - - /* somehow when I try to make tests outside of this thing, - it won't work. So they stay here for now */ - ASSERTIFY(test_GLM_PREFIXeuler_xyz_quat()); - ASSERTIFY(test_GLM_PREFIXeuler_xzy_quat()); - ASSERTIFY(test_GLM_PREFIXeuler_yxz_quat()); - ASSERTIFY(test_GLM_PREFIXeuler_yzx_quat()); - ASSERTIFY(test_GLM_PREFIXeuler_zxy_quat()); - ASSERTIFY(test_GLM_PREFIXeuler_zyx_quat()); TEST_SUCCESS } diff --git a/test/tests.h b/test/tests.h index addc2ef4c..c707ce924 100644 --- a/test/tests.h +++ b/test/tests.h @@ -360,13 +360,13 @@ TEST_DECLARE(glmc_plane_normalize) TEST_DECLARE(clamp) /* euler */ -TEST_DECLARE(euler) TEST_DECLARE(glm_euler_xyz_quat) TEST_DECLARE(glm_euler_xzy_quat) TEST_DECLARE(glm_euler_yxz_quat) TEST_DECLARE(glm_euler_yzx_quat) TEST_DECLARE(glm_euler_zxy_quat) TEST_DECLARE(glm_euler_zyx_quat) +TEST_DECLARE(euler) /* ray */ TEST_DECLARE(glm_ray_triangle) @@ -1361,8 +1361,13 @@ TEST_LIST { TEST_ENTRY(clamp) /* euler */ + TEST_ENTRY(glm_euler_xyz_quat) + TEST_ENTRY(glm_euler_xzy_quat) + TEST_ENTRY(glm_euler_yxz_quat) + TEST_ENTRY(glm_euler_yzx_quat) + TEST_ENTRY(glm_euler_zxy_quat) + TEST_ENTRY(glm_euler_zyx_quat) TEST_ENTRY(euler) - /* ray */ TEST_ENTRY(glm_ray_triangle) From 42b5e834d1e5e85c6ea9cc195aba940c8a6a68fd Mon Sep 17 00:00:00 2001 From: John Choi Date: Thu, 14 Dec 2023 12:00:58 -0600 Subject: [PATCH 12/13] re-added the euler->mat4->quat tests --- test/src/test_euler.c | 90 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 86 insertions(+), 4 deletions(-) diff --git a/test/src/test_euler.c b/test/src/test_euler.c index a2f02d954..8a98091b8 100644 --- a/test/src/test_euler.c +++ b/test/src/test_euler.c @@ -7,7 +7,6 @@ #include "test_common.h" - TEST_IMPL(glm_euler_xyz_quat) { vec3 axis_x = {1.0f, 0.0f, 0.0f}; vec3 axis_y = {0.0f, 1.0f, 0.0f}; @@ -23,6 +22,8 @@ TEST_IMPL(glm_euler_xyz_quat) { versor result; versor tmp; + mat4 expected_mat4; + /* 100 randomized tests */ for (int i = 0; i < 100; i++) { test_rand_vec3(angles); @@ -34,7 +35,7 @@ TEST_IMPL(glm_euler_xyz_quat) { /* apply the rotations to a unit quaternion in xyz order */ glm_quat_identity(expected); - + glm_quat_copy(expected, tmp); glm_quat_mul(tmp, rot_x, expected); glm_quat_copy(expected, tmp); @@ -49,6 +50,12 @@ TEST_IMPL(glm_euler_xyz_quat) { /* verify that it acts the same as rotating by 3 axis quaternions */ ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + glm_euler_by_order(angles, GLM_EULER_XYZ, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq_abs(result, expected)); } @@ -82,6 +89,12 @@ TEST_IMPL(glm_euler_xyz_quat) { ASSERT(test_eq(glm_quat_norm(result), 1.0f)) ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + glm_euler_by_order(angles, GLM_EULER_XYZ, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq_abs(result, expected)); } } } @@ -103,6 +116,8 @@ TEST_IMPL(glm_euler_xzy_quat) { versor result; versor tmp; + mat4 expected_mat4; + /* 100 randomized tests */ for (int i = 0; i < 100; i++) { test_rand_vec3(angles); @@ -129,6 +144,12 @@ TEST_IMPL(glm_euler_xzy_quat) { /* verify that it acts the same as rotating by 3 axis quaternions */ ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + glm_euler_by_order(angles, GLM_EULER_XZY, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq_abs(result, expected)); } @@ -162,6 +183,12 @@ TEST_IMPL(glm_euler_xzy_quat) { ASSERT(test_eq(glm_quat_norm(result), 1.0f)) ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + glm_euler_by_order(angles, GLM_EULER_XZY, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq_abs(result, expected)); } } } @@ -183,6 +210,8 @@ TEST_IMPL(glm_euler_yxz_quat) { versor result; versor tmp; + mat4 expected_mat4; + /* 100 randomized tests */ for (int i = 0; i < 100; i++) { test_rand_vec3(angles); @@ -209,6 +238,12 @@ TEST_IMPL(glm_euler_yxz_quat) { /* verify that it acts the same as rotating by 3 axis quaternions */ ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + glm_euler_by_order(angles, GLM_EULER_YXZ, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq_abs(result, expected)); } @@ -242,6 +277,12 @@ TEST_IMPL(glm_euler_yxz_quat) { ASSERT(test_eq(glm_quat_norm(result), 1.0f)) ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + glm_euler_by_order(angles, GLM_EULER_YXZ, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq_abs(result, expected)); } } } @@ -263,6 +304,8 @@ TEST_IMPL(glm_euler_yzx_quat) { versor result; versor tmp; + mat4 expected_mat4; + /* 100 randomized tests */ for (int i = 0; i < 100; i++) { test_rand_vec3(angles); @@ -289,6 +332,12 @@ TEST_IMPL(glm_euler_yzx_quat) { /* verify that it acts the same as rotating by 3 axis quaternions */ ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + glm_euler_by_order(angles, GLM_EULER_YZX, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq_abs(result, expected)); } @@ -322,6 +371,12 @@ TEST_IMPL(glm_euler_yzx_quat) { ASSERT(test_eq(glm_quat_norm(result), 1.0f)) ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + glm_euler_by_order(angles, GLM_EULER_YZX, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq_abs(result, expected)); } } } @@ -343,6 +398,8 @@ TEST_IMPL(glm_euler_zxy_quat) { versor result; versor tmp; + mat4 expected_mat4; + /* 100 randomized tests */ for (int i = 0; i < 100; i++) { test_rand_vec3(angles); @@ -369,6 +426,12 @@ TEST_IMPL(glm_euler_zxy_quat) { /* verify that it acts the same as rotating by 3 axis quaternions */ ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + glm_euler_by_order(angles, GLM_EULER_ZXY, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq_abs(result, expected)); } @@ -402,6 +465,12 @@ TEST_IMPL(glm_euler_zxy_quat) { ASSERT(test_eq(glm_quat_norm(result), 1.0f)) ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + glm_euler_by_order(angles, GLM_EULER_ZXY, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq_abs(result, expected)); } } } @@ -421,9 +490,10 @@ TEST_IMPL(glm_euler_zyx_quat) { versor expected; versor result; - versor tmp; + mat4 expected_mat4; + /* 100 randomized tests */ for (int i = 0; i < 100; i++) { test_rand_vec3(angles); @@ -450,6 +520,12 @@ TEST_IMPL(glm_euler_zyx_quat) { /* verify that it acts the same as rotating by 3 axis quaternions */ ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + glm_euler_by_order(angles, GLM_EULER_ZYX, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq_abs(result, expected)); } @@ -483,6 +559,12 @@ TEST_IMPL(glm_euler_zyx_quat) { ASSERT(test_eq(glm_quat_norm(result), 1.0f)) ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + glm_euler_by_order(angles, GLM_EULER_ZYX, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq_abs(result, expected)); } } } @@ -523,6 +605,6 @@ TEST_IMPL(euler) { /* matrices must be equal */ glmc_euler_xyz(outAngles, rot2); ASSERTIFY(test_assert_mat4_eq(rot1, rot2)) - + TEST_SUCCESS } From 39c0c1e7848b6692aa9ef695479f0862fd915aba Mon Sep 17 00:00:00 2001 From: John Choi Date: Sun, 24 Dec 2023 23:58:29 -0600 Subject: [PATCH 13/13] added handed folder and also made rh tests for the euler->quat functions. Still deciding on what to name the macro for lefthanded stuff --- include/cglm/euler.h | 102 ++--- include/cglm/handed/euler_to_quat_rh.h | 165 +++++++ test/src/test_euler.c | 565 ------------------------ test/src/test_euler_to_quat_rh.h | 575 +++++++++++++++++++++++++ test/src/tests.c | 2 + test/tests.h | 24 +- 6 files changed, 786 insertions(+), 647 deletions(-) create mode 100644 include/cglm/handed/euler_to_quat_rh.h create mode 100644 test/src/test_euler_to_quat_rh.h diff --git a/include/cglm/euler.h b/include/cglm/euler.h index 8a4acfdd3..fb4adc043 100644 --- a/include/cglm/euler.h +++ b/include/cglm/euler.h @@ -43,6 +43,8 @@ #include "common.h" +#include "handed/euler_to_quat_rh.h" + /*! * if you have axis order like vec3 orderVec = [0, 1, 2] or [0, 2, 1]... * vector then you can convert it to this enum by doing this: @@ -194,7 +196,6 @@ glm_euler_xzy(vec3 angles, mat4 dest) { dest[3][3] = 1.0f; } - /*! * @brief build rotation matrix from euler angles * @@ -465,18 +466,11 @@ glm_euler_by_order(vec3 angles, glm_euler_seq ord, mat4 dest) { CGLM_INLINE void glm_euler_xyz_quat(vec3 angles, versor dest) { - float xc, yc, zc, - xs, ys, zs; - - xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); - ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); - zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); - - dest[0] = xc * ys * zs + xs * yc * zc; - dest[1] = xc * ys * zc - xs * yc * zs; - dest[2] = xc * yc * zs + xs * ys * zc; - dest[3] = xc * yc * zc - xs * ys * zs; - +#ifdef CGLM_FORCE_LEFT_HANDED + glm_euler_xyz_quat_lh(angles, dest); +#else + glm_euler_xyz_quat_rh(angles, dest); +#endif } /*! @@ -489,18 +483,11 @@ glm_euler_xyz_quat(vec3 angles, versor dest) { CGLM_INLINE void glm_euler_xzy_quat(vec3 angles, versor dest) { - float xc, yc, zc, - xs, ys, zs; - - xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); - ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); - zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); - - dest[0] = -xc * zs * ys + xs * zc * yc; - dest[1] = xc * zc * ys - xs * zs * yc; - dest[2] = xc * zs * yc + xs * zc * ys; - dest[3] = xc * zc * yc + xs * zs * ys; - +#ifdef CGLM_FORCE_LEFT_HANDED + glm_euler_xzy_quat_lh(angles, dest); +#else + glm_euler_xzy_quat_rh(angles, dest); +#endif } /*! @@ -513,17 +500,11 @@ glm_euler_xzy_quat(vec3 angles, versor dest) { CGLM_INLINE void glm_euler_yxz_quat(vec3 angles, versor dest) { - float xc, yc, zc, - xs, ys, zs; - - xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); - ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); - zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); - - dest[0] = yc * xs * zc + ys * xc * zs; - dest[1] = -yc * xs * zs + ys * xc * zc; - dest[2] = yc * xc * zs - ys * xs * zc; - dest[3] = yc * xc * zc + ys * xs * zs; +#ifdef CGLM_FORCE_LEFT_HANDED + glm_euler_yxz_quat_lh(angles, dest); +#else + glm_euler_yxz_quat_rh(angles, dest); +#endif } /*! @@ -536,18 +517,11 @@ glm_euler_yxz_quat(vec3 angles, versor dest) { CGLM_INLINE void glm_euler_yzx_quat(vec3 angles, versor dest) { - float xc, yc, zc, - xs, ys, zs; - - xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); - ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); - zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); - - dest[0] = yc * zc * xs + ys * zs * xc; - dest[1] = yc * zs * xs + ys * zc * xc; - dest[2] = yc * zs * xc - ys * zc * xs; - dest[3] = yc * zc * xc - ys * zs * xs; - +#ifdef CGLM_FORCE_LEFT_HANDED + glm_euler_yzx_quat_lh(angles, dest); +#else + glm_euler_yzx_quat_rh(angles, dest); +#endif } /*! @@ -560,17 +534,11 @@ glm_euler_yzx_quat(vec3 angles, versor dest) { CGLM_INLINE void glm_euler_zxy_quat(vec3 angles, versor dest) { - float xc, yc, zc, - xs, ys, zs; - - xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); - ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); - zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); - - dest[0] = zc * xs * yc - zs * xc * ys; - dest[1] = zc * xc * ys + zs * xs * yc; - dest[2] = zc * xs * ys + zs * xc * yc; - dest[3] = zc * xc * yc - zs * xs * ys; +#ifdef CGLM_FORCE_LEFT_HANDED + glm_euler_zxy_quat_lh(angles, dest); +#else + glm_euler_zxy_quat_rh(angles, dest); +#endif } /*! @@ -583,17 +551,11 @@ glm_euler_zxy_quat(vec3 angles, versor dest) { CGLM_INLINE void glm_euler_zyx_quat(vec3 angles, versor dest) { - float xc, yc, zc, - xs, ys, zs; - - xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); - ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); - zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); - - dest[0] = zc * yc * xs - zs * ys * xc; - dest[1] = zc * ys * xc + zs * yc * xs; - dest[2] = -zc * ys * xs + zs * yc * xc; - dest[3] = zc * yc * xc + zs * ys * xs; +#ifdef CGLM_FORCE_LEFT_HANDED + glm_euler_zyx_quat_lh(angles, dest); +#else + glm_euler_zyx_quat_rh(angles, dest); +#endif } diff --git a/include/cglm/handed/euler_to_quat_rh.h b/include/cglm/handed/euler_to_quat_rh.h new file mode 100644 index 000000000..b65108c96 --- /dev/null +++ b/include/cglm/handed/euler_to_quat_rh.h @@ -0,0 +1,165 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_euler_xyz_quat_rh(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_xzy_quat_rh(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_yxz_quat_rh(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_yzx_quat_rh(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_zxy_quat_rh(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_zyx_quat_rh(vec3 angles, versor dest); + */ + +#ifndef cglm_euler_to_quat_rh_h +#define cglm_euler_to_quat_rh_h + +#include "../common.h" + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in x y z order in right hand (roll pitch yaw) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +void +glm_euler_xyz_quat_rh(vec3 angles, versor dest) { + float xc, yc, zc, + xs, ys, zs; + + xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); + ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); + zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); + + dest[0] = xc * ys * zs + xs * yc * zc; + dest[1] = xc * ys * zc - xs * yc * zs; + dest[2] = xc * yc * zs + xs * ys * zc; + dest[3] = xc * yc * zc - xs * ys * zs; + +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in x z y order in right hand (roll yaw pitch) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +void +glm_euler_xzy_quat_rh(vec3 angles, versor dest) { + float xc, yc, zc, + xs, ys, zs; + + xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); + ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); + zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); + + dest[0] = -xc * zs * ys + xs * zc * yc; + dest[1] = xc * zc * ys - xs * zs * yc; + dest[2] = xc * zs * yc + xs * zc * ys; + dest[3] = xc * zc * yc + xs * zs * ys; + +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in y x z order in right hand (pitch roll yaw) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +void +glm_euler_yxz_quat_rh(vec3 angles, versor dest) { + float xc, yc, zc, + xs, ys, zs; + + xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); + ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); + zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); + + dest[0] = yc * xs * zc + ys * xc * zs; + dest[1] = -yc * xs * zs + ys * xc * zc; + dest[2] = yc * xc * zs - ys * xs * zc; + dest[3] = yc * xc * zc + ys * xs * zs; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in y z x order in right hand (pitch yaw roll) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +void +glm_euler_yzx_quat_rh(vec3 angles, versor dest) { + float xc, yc, zc, + xs, ys, zs; + + xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); + ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); + zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); + + dest[0] = yc * zc * xs + ys * zs * xc; + dest[1] = yc * zs * xs + ys * zc * xc; + dest[2] = yc * zs * xc - ys * zc * xs; + dest[3] = yc * zc * xc - ys * zs * xs; + +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in z x y order in right hand (yaw roll pitch) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +void +glm_euler_zxy_quat_rh(vec3 angles, versor dest) { + float xc, yc, zc, + xs, ys, zs; + + xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); + ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); + zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); + + dest[0] = zc * xs * yc - zs * xc * ys; + dest[1] = zc * xc * ys + zs * xs * yc; + dest[2] = zc * xs * ys + zs * xc * yc; + dest[3] = zc * xc * yc - zs * xs * ys; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in z y x order in right hand (yaw pitch roll) + * + * @param[out] q quaternion + * @param[in] angle angles x y z (radians) + */ +CGLM_INLINE +void +glm_euler_zyx_quat_rh(vec3 angles, versor dest) { + float xc, yc, zc, + xs, ys, zs; + + xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); + ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); + zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); + + dest[0] = zc * yc * xs - zs * ys * xc; + dest[1] = zc * ys * xc + zs * yc * xs; + dest[2] = -zc * ys * xs + zs * yc * xc; + dest[3] = zc * yc * xc + zs * ys * xs; +} + + +#endif /*cglm_euler_to_quat_rh_h*/ diff --git a/test/src/test_euler.c b/test/src/test_euler.c index 8a98091b8..b71e0f049 100644 --- a/test/src/test_euler.c +++ b/test/src/test_euler.c @@ -7,571 +7,6 @@ #include "test_common.h" -TEST_IMPL(glm_euler_xyz_quat) { - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; - - /* random angles for testing */ - vec3 angles; - - /* quaternion representations for rotations */ - versor rot_x, rot_y, rot_z; - - versor expected; - versor result; - versor tmp; - - mat4 expected_mat4; - - /* 100 randomized tests */ - for (int i = 0; i < 100; i++) { - test_rand_vec3(angles); - - /* create the rotation quaternions using the angles and axises */ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); - - /* apply the rotations to a unit quaternion in xyz order */ - glm_quat_identity(expected); - - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_x, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_y, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_z, expected); - - glm_euler_xyz_quat(angles, result); - - /* verify if the magnitude of the quaternion stays 1 */ - ASSERT(test_eq(glm_quat_norm(result), 1.0f)) - - /* verify that it acts the same as rotating by 3 axis quaternions */ - ASSERTIFY(test_assert_quat_eq(result, expected)) - - /* verify that it acts the same as glm_euler_by_order */ - glm_euler_by_order(angles, GLM_EULER_XYZ, expected_mat4); - glm_mat4_quat(expected_mat4, expected); - - ASSERTIFY(test_assert_quat_eq_abs(result, expected)); - } - - - /* Start gimbal lock tests */ - for (float x = -90.0f; x <= 90.0f; x += 90.0f) { - for (float y = -90.0f; y <= 90.0f; y += 90.0f) { - for (float z = -90.0f; z <= 90.0f; z += 90.0f) { - angles[0] = x; - angles[1] = y; - angles[2] = z; - - /* create the rotation quaternions using the angles and axises */ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); - - /* apply the rotations to a unit quaternion in xyz order */ - glm_quat_identity(expected); - - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_x, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_y, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_z, expected); - - /* use my function to get the quaternion */ - glm_euler_xyz_quat(angles, result); - - /* verify if the magnitude of the quaternion stays 1 */ - ASSERT(test_eq(glm_quat_norm(result), 1.0f)) - - ASSERTIFY(test_assert_quat_eq(result, expected)) - - /* verify that it acts the same as glm_euler_by_order */ - glm_euler_by_order(angles, GLM_EULER_XYZ, expected_mat4); - glm_mat4_quat(expected_mat4, expected); - - ASSERTIFY(test_assert_quat_eq_abs(result, expected)); - } - } - } - TEST_SUCCESS -} - -TEST_IMPL(glm_euler_xzy_quat) { - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; - - /* random angles for testing */ - vec3 angles; - - /* quaternion representations for rotations */ - versor rot_x, rot_y, rot_z; - - versor expected; - versor result; - versor tmp; - - mat4 expected_mat4; - - /* 100 randomized tests */ - for (int i = 0; i < 100; i++) { - test_rand_vec3(angles); - - /* create the rotation quaternions using the angles and axises */ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); - - /* apply the rotations to a unit quaternion in xzy order */ - glm_quat_identity(expected); - - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_x, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_z, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_y, expected); - - glm_euler_xzy_quat(angles, result); - - /* verify if the magnitude of the quaternion stays 1 */ - ASSERT(test_eq(glm_quat_norm(result), 1.0f)) - - /* verify that it acts the same as rotating by 3 axis quaternions */ - ASSERTIFY(test_assert_quat_eq(result, expected)) - - /* verify that it acts the same as glm_euler_by_order */ - glm_euler_by_order(angles, GLM_EULER_XZY, expected_mat4); - glm_mat4_quat(expected_mat4, expected); - - ASSERTIFY(test_assert_quat_eq_abs(result, expected)); - } - - - /* Start gimbal lock tests */ - for (float x = -90.0f; x <= 90.0f; x += 90.0f) { - for (float y = -90.0f; y <= 90.0f; y += 90.0f) { - for (float z = -90.0f; z <= 90.0f; z += 90.0f) { - angles[0] = x; - angles[1] = y; - angles[2] = z; - - /* create the rotation quaternions using the angles and axises */ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); - - /* apply the rotations to a unit quaternion in xzy order */ - glm_quat_identity(expected); - - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_x, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_z, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_y, expected); - - /* use my function to get the quaternion */ - glm_euler_xzy_quat(angles, result); - - /* verify if the magnitude of the quaternion stays 1 */ - ASSERT(test_eq(glm_quat_norm(result), 1.0f)) - - ASSERTIFY(test_assert_quat_eq(result, expected)) - - /* verify that it acts the same as glm_euler_by_order */ - glm_euler_by_order(angles, GLM_EULER_XZY, expected_mat4); - glm_mat4_quat(expected_mat4, expected); - - ASSERTIFY(test_assert_quat_eq_abs(result, expected)); - } - } - } - TEST_SUCCESS -} - -TEST_IMPL(glm_euler_yxz_quat) { - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; - - /* random angles for testing */ - vec3 angles; - - /* quaternion representations for rotations */ - versor rot_x, rot_y, rot_z; - - versor expected; - versor result; - versor tmp; - - mat4 expected_mat4; - - /* 100 randomized tests */ - for (int i = 0; i < 100; i++) { - test_rand_vec3(angles); - - /* create the rotation quaternions using the angles and axises */ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); - - /* apply the rotations to a unit quaternion in yxz order */ - glm_quat_identity(expected); - - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_y, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_x, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_z, expected); - - glm_euler_yxz_quat(angles, result); - - /* verify if the magnitude of the quaternion stays 1 */ - ASSERT(test_eq(glm_quat_norm(result), 1.0f)) - - /* verify that it acts the same as rotating by 3 axis quaternions */ - ASSERTIFY(test_assert_quat_eq(result, expected)) - - /* verify that it acts the same as glm_euler_by_order */ - glm_euler_by_order(angles, GLM_EULER_YXZ, expected_mat4); - glm_mat4_quat(expected_mat4, expected); - - ASSERTIFY(test_assert_quat_eq_abs(result, expected)); - } - - - /* Start gimbal lock tests */ - for (float x = -90.0f; x <= 90.0f; x += 90.0f) { - for (float y = -90.0f; y <= 90.0f; y += 90.0f) { - for (float z = -90.0f; z <= 90.0f; z += 90.0f) { - angles[0] = x; - angles[1] = y; - angles[2] = z; - - /* create the rotation quaternions using the angles and axises */ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); - - /* apply the rotations to a unit quaternion in yxz order */ - glm_quat_identity(expected); - - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_y, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_x, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_z, expected); - - /* use my function to get the quaternion */ - glm_euler_yxz_quat(angles, result); - - /* verify if the magnitude of the quaternion stays 1 */ - ASSERT(test_eq(glm_quat_norm(result), 1.0f)) - - ASSERTIFY(test_assert_quat_eq(result, expected)) - - /* verify that it acts the same as glm_euler_by_order */ - glm_euler_by_order(angles, GLM_EULER_YXZ, expected_mat4); - glm_mat4_quat(expected_mat4, expected); - - ASSERTIFY(test_assert_quat_eq_abs(result, expected)); - } - } - } - TEST_SUCCESS -} - -TEST_IMPL(glm_euler_yzx_quat) { - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; - - /* random angles for testing */ - vec3 angles; - - /* quaternion representations for rotations */ - versor rot_x, rot_y, rot_z; - - versor expected; - versor result; - versor tmp; - - mat4 expected_mat4; - - /* 100 randomized tests */ - for (int i = 0; i < 100; i++) { - test_rand_vec3(angles); - - /* create the rotation quaternions using the angles and axises */ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); - - /* apply the rotations to a unit quaternion in yzx order */ - glm_quat_identity(expected); - - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_y, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_z, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_x, expected); - - glm_euler_yzx_quat(angles, result); - - /* verify if the magnitude of the quaternion stays 1 */ - ASSERT(test_eq(glm_quat_norm(result), 1.0f)) - - /* verify that it acts the same as rotating by 3 axis quaternions */ - ASSERTIFY(test_assert_quat_eq(result, expected)) - - /* verify that it acts the same as glm_euler_by_order */ - glm_euler_by_order(angles, GLM_EULER_YZX, expected_mat4); - glm_mat4_quat(expected_mat4, expected); - - ASSERTIFY(test_assert_quat_eq_abs(result, expected)); - } - - - /* Start gimbal lock tests */ - for (float x = -90.0f; x <= 90.0f; x += 90.0f) { - for (float y = -90.0f; y <= 90.0f; y += 90.0f) { - for (float z = -90.0f; z <= 90.0f; z += 90.0f) { - angles[0] = x; - angles[1] = y; - angles[2] = z; - - /* create the rotation quaternions using the angles and axises */ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); - - /* apply the rotations to a unit quaternion in yzx order */ - glm_quat_identity(expected); - - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_y, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_z, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_x, expected); - - /* use my function to get the quaternion */ - glm_euler_yzx_quat(angles, result); - - /* verify if the magnitude of the quaternion stays 1 */ - ASSERT(test_eq(glm_quat_norm(result), 1.0f)) - - ASSERTIFY(test_assert_quat_eq(result, expected)) - - /* verify that it acts the same as glm_euler_by_order */ - glm_euler_by_order(angles, GLM_EULER_YZX, expected_mat4); - glm_mat4_quat(expected_mat4, expected); - - ASSERTIFY(test_assert_quat_eq_abs(result, expected)); - } - } - } - TEST_SUCCESS -} - -TEST_IMPL(glm_euler_zxy_quat) { - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; - - /* random angles for testing */ - vec3 angles; - - /* quaternion representations for rotations */ - versor rot_x, rot_y, rot_z; - - versor expected; - versor result; - versor tmp; - - mat4 expected_mat4; - - /* 100 randomized tests */ - for (int i = 0; i < 100; i++) { - test_rand_vec3(angles); - - /* create the rotation quaternions using the angles and axises */ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); - - /* apply the rotations to a unit quaternion in zxy order */ - glm_quat_identity(expected); - - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_z, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_x, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_y, expected); - - glm_euler_zxy_quat(angles, result); - - /* verify if the magnitude of the quaternion stays 1 */ - ASSERT(test_eq(glm_quat_norm(result), 1.0f)) - - /* verify that it acts the same as rotating by 3 axis quaternions */ - ASSERTIFY(test_assert_quat_eq(result, expected)) - - /* verify that it acts the same as glm_euler_by_order */ - glm_euler_by_order(angles, GLM_EULER_ZXY, expected_mat4); - glm_mat4_quat(expected_mat4, expected); - - ASSERTIFY(test_assert_quat_eq_abs(result, expected)); - } - - - /* Start gimbal lock tests */ - for (float x = -90.0f; x <= 90.0f; x += 90.0f) { - for (float y = -90.0f; y <= 90.0f; y += 90.0f) { - for (float z = -90.0f; z <= 90.0f; z += 90.0f) { - angles[0] = x; - angles[1] = y; - angles[2] = z; - - /* create the rotation quaternions using the angles and axises */ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); - - /* apply the rotations to a unit quaternion in zxy order */ - glm_quat_identity(expected); - - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_z, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_x, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_y, expected); - - /* use my function to get the quaternion */ - glm_euler_zxy_quat(angles, result); - - /* verify if the magnitude of the quaternion stays 1 */ - ASSERT(test_eq(glm_quat_norm(result), 1.0f)) - - ASSERTIFY(test_assert_quat_eq(result, expected)) - - /* verify that it acts the same as glm_euler_by_order */ - glm_euler_by_order(angles, GLM_EULER_ZXY, expected_mat4); - glm_mat4_quat(expected_mat4, expected); - - ASSERTIFY(test_assert_quat_eq_abs(result, expected)); - } - } - } - TEST_SUCCESS -} - -TEST_IMPL(glm_euler_zyx_quat) { - vec3 axis_x = {1.0f, 0.0f, 0.0f}; - vec3 axis_y = {0.0f, 1.0f, 0.0f}; - vec3 axis_z = {0.0f, 0.0f, 1.0f}; - - /* random angles for testing */ - vec3 angles; - - /* quaternion representations for rotations */ - versor rot_x, rot_y, rot_z; - - versor expected; - versor result; - versor tmp; - - mat4 expected_mat4; - - /* 100 randomized tests */ - for (int i = 0; i < 100; i++) { - test_rand_vec3(angles); - - /* create the rotation quaternions using the angles and axises */ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); - - /* apply the rotations to a unit quaternion in zyx order */ - glm_quat_identity(expected); - - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_z, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_y, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_x, expected); - - glm_euler_zyx_quat(angles, result); - - /* verify if the magnitude of the quaternion stays 1 */ - ASSERT(test_eq(glm_quat_norm(result), 1.0f)) - - /* verify that it acts the same as rotating by 3 axis quaternions */ - ASSERTIFY(test_assert_quat_eq(result, expected)) - - /* verify that it acts the same as glm_euler_by_order */ - glm_euler_by_order(angles, GLM_EULER_ZYX, expected_mat4); - glm_mat4_quat(expected_mat4, expected); - - ASSERTIFY(test_assert_quat_eq_abs(result, expected)); - } - - - /* Start gimbal lock tests */ - for (float x = -90.0f; x <= 90.0f; x += 90.0f) { - for (float y = -90.0f; y <= 90.0f; y += 90.0f) { - for (float z = -90.0f; z <= 90.0f; z += 90.0f) { - angles[0] = x; - angles[1] = y; - angles[2] = z; - - /* create the rotation quaternions using the angles and axises */ - glm_quatv(rot_x, angles[0], axis_x); - glm_quatv(rot_y, angles[1], axis_y); - glm_quatv(rot_z, angles[2], axis_z); - - /* apply the rotations to a unit quaternion in xyz order */ - glm_quat_identity(expected); - - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_z, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_y, expected); - glm_quat_copy(expected, tmp); - glm_quat_mul(tmp, rot_x, expected); - - /* use my function to get the quaternion */ - glm_euler_zyx_quat(angles, result); - - /* verify if the magnitude of the quaternion stays 1 */ - ASSERT(test_eq(glm_quat_norm(result), 1.0f)) - - ASSERTIFY(test_assert_quat_eq(result, expected)) - - /* verify that it acts the same as glm_euler_by_order */ - glm_euler_by_order(angles, GLM_EULER_ZYX, expected_mat4); - glm_mat4_quat(expected_mat4, expected); - - ASSERTIFY(test_assert_quat_eq_abs(result, expected)); - } - } - } - TEST_SUCCESS -} - - TEST_IMPL(euler) { mat4 rot1, rot2; vec3 inAngles, outAngles; diff --git a/test/src/test_euler_to_quat_rh.h b/test/src/test_euler_to_quat_rh.h new file mode 100644 index 000000000..221192e53 --- /dev/null +++ b/test/src/test_euler_to_quat_rh.h @@ -0,0 +1,575 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#include "test_common.h" +#include "../../include/cglm/handed/euler_to_quat_rh.h" + +TEST_IMPL(GLM_PREFIX, euler_xyz_quat_rh) { + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + /* random angles for testing */ + vec3 angles; + + /* quaternion representations for rotations */ + versor rot_x, rot_y, rot_z; + + versor expected; + versor result; + versor tmp; + + mat4 expected_mat4; + + /* 100 randomized tests */ + for (int i = 0; i < 100; i++) { + test_rand_vec3(angles); + + /* create the rotation quaternions using the angles and axises */ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /* apply the rotations to a unit quaternion in xyz order */ + glm_quat_identity(expected); + + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_x, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_y, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_z, expected); + + glm_euler_xyz_quat_rh(angles, result); + + /* verify if the magnitude of the quaternion stays 1 */ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + + /* verify that it acts the same as rotating by 3 axis quaternions */ + ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + glm_euler_by_order(angles, GLM_EULER_XYZ, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq_abs(result, expected)); + } + + + /* Start gimbal lock tests */ + for (float x = -90.0f; x <= 90.0f; x += 90.0f) { + for (float y = -90.0f; y <= 90.0f; y += 90.0f) { + for (float z = -90.0f; z <= 90.0f; z += 90.0f) { + angles[0] = x; + angles[1] = y; + angles[2] = z; + + /* create the rotation quaternions using the angles and axises */ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /* apply the rotations to a unit quaternion in xyz order */ + glm_quat_identity(expected); + + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_x, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_y, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_z, expected); + + /* use my function to get the quaternion */ + glm_euler_xyz_quat_rh(angles, result); + + /* verify if the magnitude of the quaternion stays 1 */ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + + ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + glm_euler_by_order(angles, GLM_EULER_XYZ, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq_abs(result, expected)); + } + } + } + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, euler_xzy_quat_rh) { + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + /* random angles for testing */ + vec3 angles; + + /* quaternion representations for rotations */ + versor rot_x, rot_y, rot_z; + + versor expected; + versor result; + versor tmp; + + mat4 expected_mat4; + + /* 100 randomized tests */ + for (int i = 0; i < 100; i++) { + test_rand_vec3(angles); + + /* create the rotation quaternions using the angles and axises */ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /* apply the rotations to a unit quaternion in xzy order */ + glm_quat_identity(expected); + + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_x, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_z, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_y, expected); + + glm_euler_xzy_quat_rh(angles, result); + + /* verify if the magnitude of the quaternion stays 1 */ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + + /* verify that it acts the same as rotating by 3 axis quaternions */ + ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + glm_euler_by_order(angles, GLM_EULER_XZY, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq_abs(result, expected)); + } + + + /* Start gimbal lock tests */ + for (float x = -90.0f; x <= 90.0f; x += 90.0f) { + for (float y = -90.0f; y <= 90.0f; y += 90.0f) { + for (float z = -90.0f; z <= 90.0f; z += 90.0f) { + angles[0] = x; + angles[1] = y; + angles[2] = z; + + /* create the rotation quaternions using the angles and axises */ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /* apply the rotations to a unit quaternion in xzy order */ + glm_quat_identity(expected); + + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_x, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_z, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_y, expected); + + /* use my function to get the quaternion */ + glm_euler_xzy_quat_rh(angles, result); + + /* verify if the magnitude of the quaternion stays 1 */ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + + ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + glm_euler_by_order(angles, GLM_EULER_XZY, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq_abs(result, expected)); + } + } + } + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, euler_yxz_quat_rh) { + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + /* random angles for testing */ + vec3 angles; + + /* quaternion representations for rotations */ + versor rot_x, rot_y, rot_z; + + versor expected; + versor result; + versor tmp; + + mat4 expected_mat4; + + /* 100 randomized tests */ + for (int i = 0; i < 100; i++) { + test_rand_vec3(angles); + + /* create the rotation quaternions using the angles and axises */ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /* apply the rotations to a unit quaternion in yxz order */ + glm_quat_identity(expected); + + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_y, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_x, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_z, expected); + + glm_euler_yxz_quat_rh(angles, result); + + /* verify if the magnitude of the quaternion stays 1 */ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + + /* verify that it acts the same as rotating by 3 axis quaternions */ + ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + glm_euler_by_order(angles, GLM_EULER_YXZ, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq_abs(result, expected)); + } + + + /* Start gimbal lock tests */ + for (float x = -90.0f; x <= 90.0f; x += 90.0f) { + for (float y = -90.0f; y <= 90.0f; y += 90.0f) { + for (float z = -90.0f; z <= 90.0f; z += 90.0f) { + angles[0] = x; + angles[1] = y; + angles[2] = z; + + /* create the rotation quaternions using the angles and axises */ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /* apply the rotations to a unit quaternion in yxz order */ + glm_quat_identity(expected); + + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_y, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_x, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_z, expected); + + /* use my function to get the quaternion */ + glm_euler_yxz_quat_rh(angles, result); + + /* verify if the magnitude of the quaternion stays 1 */ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + + ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + glm_euler_by_order(angles, GLM_EULER_YXZ, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq_abs(result, expected)); + } + } + } + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, euler_yzx_quat_rh) { + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + /* random angles for testing */ + vec3 angles; + + /* quaternion representations for rotations */ + versor rot_x, rot_y, rot_z; + + versor expected; + versor result; + versor tmp; + + mat4 expected_mat4; + + /* 100 randomized tests */ + for (int i = 0; i < 100; i++) { + test_rand_vec3(angles); + + /* create the rotation quaternions using the angles and axises */ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /* apply the rotations to a unit quaternion in yzx order */ + glm_quat_identity(expected); + + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_y, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_z, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_x, expected); + + glm_euler_yzx_quat_rh(angles, result); + + /* verify if the magnitude of the quaternion stays 1 */ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + + /* verify that it acts the same as rotating by 3 axis quaternions */ + ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + glm_euler_by_order(angles, GLM_EULER_YZX, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq_abs(result, expected)); + } + + + /* Start gimbal lock tests */ + for (float x = -90.0f; x <= 90.0f; x += 90.0f) { + for (float y = -90.0f; y <= 90.0f; y += 90.0f) { + for (float z = -90.0f; z <= 90.0f; z += 90.0f) { + angles[0] = x; + angles[1] = y; + angles[2] = z; + + /* create the rotation quaternions using the angles and axises */ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /* apply the rotations to a unit quaternion in yzx order */ + glm_quat_identity(expected); + + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_y, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_z, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_x, expected); + + /* use my function to get the quaternion */ + glm_euler_yzx_quat_rh(angles, result); + + /* verify if the magnitude of the quaternion stays 1 */ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + + ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + glm_euler_by_order(angles, GLM_EULER_YZX, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq_abs(result, expected)); + } + } + } + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, euler_zxy_quat_rh) { + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + /* random angles for testing */ + vec3 angles; + + /* quaternion representations for rotations */ + versor rot_x, rot_y, rot_z; + + versor expected; + versor result; + versor tmp; + + mat4 expected_mat4; + + /* 100 randomized tests */ + for (int i = 0; i < 100; i++) { + test_rand_vec3(angles); + + /* create the rotation quaternions using the angles and axises */ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /* apply the rotations to a unit quaternion in zxy order */ + glm_quat_identity(expected); + + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_z, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_x, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_y, expected); + + glm_euler_zxy_quat_rh(angles, result); + + /* verify if the magnitude of the quaternion stays 1 */ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + + /* verify that it acts the same as rotating by 3 axis quaternions */ + ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + glm_euler_by_order(angles, GLM_EULER_ZXY, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq_abs(result, expected)); + } + + + /* Start gimbal lock tests */ + for (float x = -90.0f; x <= 90.0f; x += 90.0f) { + for (float y = -90.0f; y <= 90.0f; y += 90.0f) { + for (float z = -90.0f; z <= 90.0f; z += 90.0f) { + angles[0] = x; + angles[1] = y; + angles[2] = z; + + /* create the rotation quaternions using the angles and axises */ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /* apply the rotations to a unit quaternion in zxy order */ + glm_quat_identity(expected); + + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_z, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_x, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_y, expected); + + /* use my function to get the quaternion */ + glm_euler_zxy_quat_rh(angles, result); + + /* verify if the magnitude of the quaternion stays 1 */ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + + ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + glm_euler_by_order(angles, GLM_EULER_ZXY, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq_abs(result, expected)); + } + } + } + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, euler_zyx_quat_rh) { + vec3 axis_x = {1.0f, 0.0f, 0.0f}; + vec3 axis_y = {0.0f, 1.0f, 0.0f}; + vec3 axis_z = {0.0f, 0.0f, 1.0f}; + + /* random angles for testing */ + vec3 angles; + + /* quaternion representations for rotations */ + versor rot_x, rot_y, rot_z; + + versor expected; + versor result; + versor tmp; + + mat4 expected_mat4; + + /* 100 randomized tests */ + for (int i = 0; i < 100; i++) { + test_rand_vec3(angles); + + /* create the rotation quaternions using the angles and axises */ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /* apply the rotations to a unit quaternion in zyx order */ + glm_quat_identity(expected); + + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_z, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_y, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_x, expected); + + glm_euler_zyx_quat_rh(angles, result); + + /* verify if the magnitude of the quaternion stays 1 */ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + + /* verify that it acts the same as rotating by 3 axis quaternions */ + ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + glm_euler_by_order(angles, GLM_EULER_ZYX, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq_abs(result, expected)); + } + + + /* Start gimbal lock tests */ + for (float x = -90.0f; x <= 90.0f; x += 90.0f) { + for (float y = -90.0f; y <= 90.0f; y += 90.0f) { + for (float z = -90.0f; z <= 90.0f; z += 90.0f) { + angles[0] = x; + angles[1] = y; + angles[2] = z; + + /* create the rotation quaternions using the angles and axises */ + glm_quatv(rot_x, angles[0], axis_x); + glm_quatv(rot_y, angles[1], axis_y); + glm_quatv(rot_z, angles[2], axis_z); + + /* apply the rotations to a unit quaternion in xyz order */ + glm_quat_identity(expected); + + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_z, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_y, expected); + glm_quat_copy(expected, tmp); + glm_quat_mul(tmp, rot_x, expected); + + /* use my function to get the quaternion */ + glm_euler_zyx_quat_rh(angles, result); + + /* verify if the magnitude of the quaternion stays 1 */ + ASSERT(test_eq(glm_quat_norm(result), 1.0f)) + + ASSERTIFY(test_assert_quat_eq(result, expected)) + + /* verify that it acts the same as glm_euler_by_order */ + glm_euler_by_order(angles, GLM_EULER_ZYX, expected_mat4); + glm_mat4_quat(expected_mat4, expected); + + ASSERTIFY(test_assert_quat_eq_abs(result, expected)); + } + } + } + TEST_SUCCESS +} + + diff --git a/test/src/tests.c b/test/src/tests.c index 4d1e2c986..274f7e09c 100644 --- a/test/src/tests.c +++ b/test/src/tests.c @@ -39,6 +39,7 @@ #include "test_cam_lh_zo.h" #include "test_cam_rh_no.h" #include "test_cam_rh_zo.h" +#include "test_euler_to_quat_rh.h" #undef GLM #undef GLM_PREFIX @@ -76,6 +77,7 @@ #include "test_cam_lh_zo.h" #include "test_cam_rh_no.h" #include "test_cam_rh_zo.h" +#include "test_euler_to_quat_rh.h" #undef GLM #undef GLM_PREFIX diff --git a/test/tests.h b/test/tests.h index c707ce924..48d135e2e 100644 --- a/test/tests.h +++ b/test/tests.h @@ -360,12 +360,12 @@ TEST_DECLARE(glmc_plane_normalize) TEST_DECLARE(clamp) /* euler */ -TEST_DECLARE(glm_euler_xyz_quat) -TEST_DECLARE(glm_euler_xzy_quat) -TEST_DECLARE(glm_euler_yxz_quat) -TEST_DECLARE(glm_euler_yzx_quat) -TEST_DECLARE(glm_euler_zxy_quat) -TEST_DECLARE(glm_euler_zyx_quat) +TEST_DECLARE(glm_euler_xyz_quat_rh) +TEST_DECLARE(glm_euler_xzy_quat_rh) +TEST_DECLARE(glm_euler_yxz_quat_rh) +TEST_DECLARE(glm_euler_yzx_quat_rh) +TEST_DECLARE(glm_euler_zxy_quat_rh) +TEST_DECLARE(glm_euler_zyx_quat_rh) TEST_DECLARE(euler) /* ray */ @@ -1361,12 +1361,12 @@ TEST_LIST { TEST_ENTRY(clamp) /* euler */ - TEST_ENTRY(glm_euler_xyz_quat) - TEST_ENTRY(glm_euler_xzy_quat) - TEST_ENTRY(glm_euler_yxz_quat) - TEST_ENTRY(glm_euler_yzx_quat) - TEST_ENTRY(glm_euler_zxy_quat) - TEST_ENTRY(glm_euler_zyx_quat) + TEST_ENTRY(glm_euler_xyz_quat_rh) + TEST_ENTRY(glm_euler_xzy_quat_rh) + TEST_ENTRY(glm_euler_yxz_quat_rh) + TEST_ENTRY(glm_euler_yzx_quat_rh) + TEST_ENTRY(glm_euler_zxy_quat_rh) + TEST_ENTRY(glm_euler_zyx_quat_rh) TEST_ENTRY(euler) /* ray */