diff --git a/build-deps.sh b/build-deps.sh index 23bb9e9..74b1cfa 100644 --- a/build-deps.sh +++ b/build-deps.sh @@ -16,14 +16,18 @@ cd $(dirname "$0") if [ "$(uname)" = "Darwin" ]; then libtoolBin=$(which glibtoolize) libtoolBinDir=$(dirname "${libtoolBin}") - ln -s $libtoolBin "${libtoolBinDir}/libtoolize" + + if [ ! -f "${libtoolBinDir}/libtoolize" ]; then + ln -s $libtoolBin "${libtoolBinDir}/libtoolize" + fi fi # general deps: gcc make autoconf automake libtool cmake # test - cmocka cd ./test/lib/cmocka -mkdir build +rm -rf build +mkdir -p build cd build cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug .. make -j8 diff --git a/include/cglm/call/euler.h b/include/cglm/call/euler.h index 8cbea2b..9b85485 100644 --- a/include/cglm/call/euler.h +++ b/include/cglm/call/euler.h @@ -21,6 +21,10 @@ CGLM_EXPORT void glmc_euler(vec3 angles, mat4 dest); +CGLM_EXPORT +void +glmc_euler_xyz(vec3 angles, mat4 dest); + CGLM_EXPORT void glmc_euler_zyx(vec3 angles, mat4 dest); diff --git a/include/cglm/euler.h b/include/cglm/euler.h index 2289b04..5db7e66 100644 --- a/include/cglm/euler.h +++ b/include/cglm/euler.h @@ -5,6 +5,14 @@ * Full license can be found in the LICENSE file */ +/* + NOTE: + angles must be passed as [X-Angle, Y-Angle, Z-angle] order + For instance you don't pass angles as [Z-Angle, X-Angle, Y-angle] to + glm_euler_zxy funciton, All RELATED functions accept angles same order + which is [X, Y, Z]. + */ + /* Types: enum glm_euler_sq @@ -61,253 +69,283 @@ glm_euler_order(int ord[3]) { CGLM_INLINE void glm_euler_angles(mat4 m, vec3 dest) { - if (m[0][2] < 1.0f) { - if (m[0][2] > -1.0f) { - vec3 a[2]; - float cy1, cy2; - int path; + float m00, m01, m10, m11, m20, m21, m22; + float thetaX, thetaY, thetaZ; - a[0][1] = asinf(-m[0][2]); - a[1][1] = CGLM_PI - a[0][1]; + m00 = m[0][0]; m10 = m[1][0]; m20 = m[2][0]; + m01 = m[0][1]; m11 = m[1][1]; m21 = m[2][1]; + m22 = m[2][2]; - cy1 = cosf(a[0][1]); - cy2 = cosf(a[1][1]); - - a[0][0] = atan2f(m[1][2] / cy1, m[2][2] / cy1); - a[1][0] = atan2f(m[1][2] / cy2, m[2][2] / cy2); - - a[0][2] = atan2f(m[0][1] / cy1, m[0][0] / cy1); - a[1][2] = atan2f(m[0][1] / cy2, m[0][0] / cy2); - - path = (fabsf(a[0][0]) + fabsf(a[0][1]) + fabsf(a[0][2])) >= - (fabsf(a[1][0]) + fabsf(a[1][1]) + fabsf(a[1][2])); - - glm_vec_copy(a[path], dest); - } else { - dest[0] = atan2f(m[1][0], m[2][0]); - dest[1] = CGLM_PI_2; - dest[2] = 0.0f; + if (m20 < 1.0f) { + if (m20 > -1.0f) { + thetaY = asinf(m20); + thetaX = atan2f(-m21, m22); + thetaZ = atan2f(-m10, m00); + } else { /* m20 == -1 */ + /* Not a unique solution */ + thetaY = -CGLM_PI_2; + thetaX = -atan2f(m01, m11); + thetaZ = 0.0f; } - } else { - dest[0] = atan2f(-m[1][0], -m[2][0]); - dest[1] =-CGLM_PI_2; - dest[2] = 0.0f; + } else { /* m20 == +1 */ + thetaY = CGLM_PI_2; + thetaX = atan2f(m01, m11); + thetaZ = 0.0f; } + + dest[0] = thetaX; + dest[1] = thetaY; + dest[2] = thetaZ; } /*! * @brief build rotation matrix from euler angles * - * @param[in] angles angles as vector [Ex, Ey, Ez] + * @param[in] angles angles as vector [Xangle, Yangle, Zangle] + * @param[out] dest rotation matrix + */ +CGLM_INLINE +void +glm_euler_xyz(vec3 angles, mat4 dest) { + float cx, cy, cz, + sx, sy, sz, czsx, cxcz, sysz; + + sx = sinf(angles[0]); cx = cosf(angles[0]); + sy = sinf(angles[1]); cy = cosf(angles[1]); + sz = sinf(angles[2]); cz = cosf(angles[2]); + + czsx = cz * sx; + cxcz = cx * cz; + sysz = sy * sz; + + dest[0][0] = cy * cz; + dest[0][1] = czsx * sy + cx * sz; + dest[0][2] = -cxcz * sy + sx * sz; + dest[1][0] = -cy * sz; + dest[1][1] = cxcz - sx * sysz; + dest[1][2] = czsx + cx * sysz; + dest[2][0] = sy; + dest[2][1] = -cy * sx; + dest[2][2] = cx * cy; + dest[0][3] = 0.0f; + dest[1][3] = 0.0f; + dest[2][3] = 0.0f; + dest[3][0] = 0.0f; + dest[3][1] = 0.0f; + dest[3][2] = 0.0f; + dest[3][3] = 1.0f; +} + +/*! + * @brief build rotation matrix from euler angles + * + * @param[in] angles angles as vector [Xangle, Yangle, Zangle] * @param[out] dest rotation matrix */ CGLM_INLINE void glm_euler(vec3 angles, mat4 dest) { - float cx, cy, cz, - sx, sy, sz; - - sx = sinf(angles[0]); cx = cosf(angles[0]); - sy = sinf(angles[1]); cy = cosf(angles[1]); - sz = sinf(angles[2]); cz = cosf(angles[2]); - - dest[0][0] = cy * cz; - dest[0][1] = cy * sz; - dest[0][2] =-sy; - dest[1][0] = cz * sx * sy - cx * sz; - dest[1][1] = cx * cz + sx * sy * sz; - dest[1][2] = cy * sx; - dest[2][0] = cx * cz * sy + sx * sz; - dest[2][1] =-cz * sx + cx * sy * sz; - dest[2][2] = cx * cy; - dest[0][3] = 0.0f; - dest[1][3] = 0.0f; - dest[2][3] = 0.0f; - dest[3][0] = 0.0f; - dest[3][1] = 0.0f; - dest[3][2] = 0.0f; - dest[3][3] = 1.0f; + glm_euler_xyz(angles, dest); } /*! * @brief build rotation matrix from euler angles * - * @param[in] angles angles as vector [Ez, Ey, Ex] + * @param[in] angles angles as vector [Xangle, Yangle, Zangle] * @param[out] dest rotation matrix */ CGLM_INLINE void -glm_euler_zyx(vec3 angles, - mat4 dest) { +glm_euler_xzy(vec3 angles, mat4 dest) { float cx, cy, cz, - sx, sy, sz; + sx, sy, sz, sxsy, cysx, cxsy, cxcy; - sx = sinf(angles[0]); cx = cosf(angles[0]); - sy = sinf(angles[1]); cy = cosf(angles[1]); - sz = sinf(angles[2]); cz = cosf(angles[2]); + sx = sinf(angles[0]); cx = cosf(angles[0]); + sy = sinf(angles[1]); cy = cosf(angles[1]); + sz = sinf(angles[2]); cz = cosf(angles[2]); - dest[0][0] = cy * cz; - dest[0][1] = cz * sx * sy + cx * sz; - dest[0][2] =-cx * cz * sy + sx * sz; - dest[1][0] =-cy * sz; - dest[1][1] = cx * cz - sx * sy * sz; - dest[1][2] = cz * sx + cx * sy * sz; - dest[2][0] = sy; - dest[2][1] =-cy * sx; - dest[2][2] = cx * cy; - dest[0][3] = 0.0f; - dest[1][3] = 0.0f; - dest[2][3] = 0.0f; - dest[3][0] = 0.0f; - dest[3][1] = 0.0f; - dest[3][2] = 0.0f; - dest[3][3] = 1.0f; + sxsy = sx * sy; + cysx = cy * sx; + cxsy = cx * sy; + cxcy = cx * cy; + + dest[0][0] = cy * cz; + dest[0][1] = sxsy + cxcy * sz; + dest[0][2] = -cxsy + cysx * sz; + dest[1][0] = -sz; + dest[1][1] = cx * cz; + dest[1][2] = cz * sx; + dest[2][0] = cz * sy; + dest[2][1] = -cysx + cxsy * sz; + dest[2][2] = cxcy + sxsy * sz; + dest[0][3] = 0.0f; + dest[1][3] = 0.0f; + dest[2][3] = 0.0f; + dest[3][0] = 0.0f; + dest[3][1] = 0.0f; + dest[3][2] = 0.0f; + dest[3][3] = 1.0f; } + /*! * @brief build rotation matrix from euler angles * - * @param[in] angles angles as vector [Ez, Ex, Ey] + * @param[in] angles angles as vector [Xangle, Yangle, Zangle] * @param[out] dest rotation matrix */ CGLM_INLINE void -glm_euler_zxy(vec3 angles, - mat4 dest) { +glm_euler_yxz(vec3 angles, mat4 dest) { float cx, cy, cz, - sx, sy, sz; + sx, sy, sz, cycz, sysz, czsy, cysz; - sx = sinf(angles[0]); cx = cosf(angles[0]); - sy = sinf(angles[1]); cy = cosf(angles[1]); - sz = sinf(angles[2]); cz = cosf(angles[2]); + sx = sinf(angles[0]); cx = cosf(angles[0]); + sy = sinf(angles[1]); cy = cosf(angles[1]); + sz = sinf(angles[2]); cz = cosf(angles[2]); - dest[0][0] = cy * cz + sx * sy * sz; - dest[0][1] = cx * sz; - dest[0][2] =-cz * sy + cy * sx * sz; - dest[1][0] = cz * sx * sy - cy * sz; - dest[1][1] = cx * cz; - dest[1][2] = cy * cz * sx + sy * sz; - dest[2][0] = cx * sy; - dest[2][1] =-sx; - dest[2][2] = cx * cy; - dest[0][3] = 0.0f; - dest[1][3] = 0.0f; - dest[2][3] = 0.0f; - dest[3][0] = 0.0f; - dest[3][1] = 0.0f; - dest[3][2] = 0.0f; - dest[3][3] = 1.0f; + cycz = cy * cz; + sysz = sy * sz; + czsy = cz * sy; + cysz = cy * sz; + + dest[0][0] = cycz + sx * sysz; + dest[0][1] = cx * sz; + dest[0][2] = -czsy + cysz * sx; + dest[1][0] = -cysz + czsy * sx; + dest[1][1] = cx * cz; + dest[1][2] = cycz * sx + sysz; + dest[2][0] = cx * sy; + dest[2][1] = -sx; + dest[2][2] = cx * cy; + dest[0][3] = 0.0f; + dest[1][3] = 0.0f; + dest[2][3] = 0.0f; + dest[3][0] = 0.0f; + dest[3][1] = 0.0f; + dest[3][2] = 0.0f; + dest[3][3] = 1.0f; } /*! * @brief build rotation matrix from euler angles * - * @param[in] angles angles as vector [Ex, Ez, Ey] + * @param[in] angles angles as vector [Xangle, Yangle, Zangle] * @param[out] dest rotation matrix */ CGLM_INLINE void -glm_euler_xzy(vec3 angles, - mat4 dest) { +glm_euler_yzx(vec3 angles, mat4 dest) { float cx, cy, cz, - sx, sy, sz; + sx, sy, sz, sxsy, cxcy, cysx, cxsy; - sx = sinf(angles[0]); cx = cosf(angles[0]); - sy = sinf(angles[1]); cy = cosf(angles[1]); - sz = sinf(angles[2]); cz = cosf(angles[2]); + sx = sinf(angles[0]); cx = cosf(angles[0]); + sy = sinf(angles[1]); cy = cosf(angles[1]); + sz = sinf(angles[2]); cz = cosf(angles[2]); - dest[0][0] = cy * cz; - dest[0][1] = sz; - dest[0][2] =-cz * sy; - dest[1][0] = sx * sy - cx * cy * sz; - dest[1][1] = cx * cz; - dest[1][2] = cy * sx + cx * sy * sz; - dest[2][0] = cx * sy + cy * sx * sz; - dest[2][1] =-cz * sx; - dest[2][2] = cx * cy - sx * sy * sz; - dest[0][3] = 0.0f; - dest[1][3] = 0.0f; - dest[2][3] = 0.0f; - dest[3][0] = 0.0f; - dest[3][1] = 0.0f; - dest[3][2] = 0.0f; - dest[3][3] = 1.0f; + sxsy = sx * sy; + cxcy = cx * cy; + cysx = cy * sx; + cxsy = cx * sy; + + dest[0][0] = cy * cz; + dest[0][1] = sz; + dest[0][2] = -cz * sy; + dest[1][0] = sxsy - cxcy * sz; + dest[1][1] = cx * cz; + dest[1][2] = cysx + cxsy * sz; + dest[2][0] = cxsy + cysx * sz; + dest[2][1] = -cz * sx; + dest[2][2] = cxcy - sxsy * sz; + dest[0][3] = 0.0f; + dest[1][3] = 0.0f; + dest[2][3] = 0.0f; + dest[3][0] = 0.0f; + dest[3][1] = 0.0f; + dest[3][2] = 0.0f; + dest[3][3] = 1.0f; } /*! * @brief build rotation matrix from euler angles * - * @param[in] angles angles as vector [Ey, Ez, Ex] + * @param[in] angles angles as vector [Xangle, Yangle, Zangle] * @param[out] dest rotation matrix */ CGLM_INLINE void -glm_euler_yzx(vec3 angles, - mat4 dest) { +glm_euler_zxy(vec3 angles, mat4 dest) { float cx, cy, cz, - sx, sy, sz; + sx, sy, sz, cycz, sxsy, cysz; - sx = sinf(angles[0]); cx = cosf(angles[0]); - sy = sinf(angles[1]); cy = cosf(angles[1]); - sz = sinf(angles[2]); cz = cosf(angles[2]); + sx = sinf(angles[0]); cx = cosf(angles[0]); + sy = sinf(angles[1]); cy = cosf(angles[1]); + sz = sinf(angles[2]); cz = cosf(angles[2]); - dest[0][0] = cy * cz; - dest[0][1] = sx * sy + cx * cy * sz; - dest[0][2] =-cx * sy + cy * sx * sz; - dest[1][0] =-sz; - dest[1][1] = cx * cz; - dest[1][2] = cz * sx; - dest[2][0] = cz * sy; - dest[2][1] =-cy * sx + cx * sy * sz; - dest[2][2] = cx * cy + sx * sy * sz; - dest[0][3] = 0.0f; - dest[1][3] = 0.0f; - dest[2][3] = 0.0f; - dest[3][0] = 0.0f; - dest[3][1] = 0.0f; - dest[3][2] = 0.0f; - dest[3][3] = 1.0f; + cycz = cy * cz; + sxsy = sx * sy; + cysz = cy * sz; + + dest[0][0] = cycz - sxsy * sz; + dest[0][1] = cz * sxsy + cysz; + dest[0][2] = -cx * sy; + dest[1][0] = -cx * sz; + dest[1][1] = cx * cz; + dest[1][2] = sx; + dest[2][0] = cz * sy + cysz * sx; + dest[2][1] = -cycz * sx + sy * sz; + dest[2][2] = cx * cy; + dest[0][3] = 0.0f; + dest[1][3] = 0.0f; + dest[2][3] = 0.0f; + dest[3][0] = 0.0f; + dest[3][1] = 0.0f; + dest[3][2] = 0.0f; + dest[3][3] = 1.0f; } /*! * @brief build rotation matrix from euler angles * - * @param[in] angles angles as vector [Ey, Ex, Ez] + * @param[in] angles angles as vector [Xangle, Yangle, Zangle] * @param[out] dest rotation matrix */ CGLM_INLINE void -glm_euler_yxz(vec3 angles, - mat4 dest) { +glm_euler_zyx(vec3 angles, mat4 dest) { float cx, cy, cz, - sx, sy, sz; + sx, sy, sz, czsx, cxcz, sysz; - sx = sinf(angles[0]); cx = cosf(angles[0]); - sy = sinf(angles[1]); cy = cosf(angles[1]); - sz = sinf(angles[2]); cz = cosf(angles[2]); + sx = sinf(angles[0]); cx = cosf(angles[0]); + sy = sinf(angles[1]); cy = cosf(angles[1]); + sz = sinf(angles[2]); cz = cosf(angles[2]); - dest[0][0] = cy * cz - sx * sy * sz; - dest[0][1] = cz * sx * sy + cy * sz; - dest[0][2] =-cx * sy; - dest[1][0] =-cx * sz; - dest[1][1] = cx * cz; - dest[1][2] = sx; - dest[2][0] = cz * sy + cy * sx * sz; - dest[2][1] =-cy * cz * sx + sy * sz; - dest[2][2] = cx * cy; - dest[0][3] = 0.0f; - dest[1][3] = 0.0f; - dest[2][3] = 0.0f; - dest[3][0] = 0.0f; - dest[3][1] = 0.0f; - dest[3][2] = 0.0f; - dest[3][3] = 1.0f; + czsx = cz * sx; + cxcz = cx * cz; + sysz = sy * sz; + + dest[0][0] = cy * cz; + dest[0][1] = cy * sz; + dest[0][2] = -sy; + dest[1][0] = czsx * sy - cx * sz; + dest[1][1] = cxcz + sx * sysz; + dest[1][2] = cy * sx; + dest[2][0] = cxcz * sy + sx * sz; + dest[2][1] = -czsx + cx * sysz; + dest[2][2] = cx * cy; + dest[0][3] = 0.0f; + dest[1][3] = 0.0f; + dest[2][3] = 0.0f; + dest[3][0] = 0.0f; + dest[3][1] = 0.0f; + dest[3][2] = 0.0f; + dest[3][3] = 1.0f; } /*! * @brief build rotation matrix from euler angles * - * @param[in] angles angles as vector (ord parameter spceifies angles order) + * @param[in] angles angles as vector [Xangle, Yangle, Zangle] * @param[in] ord euler order * @param[out] dest rotation matrix */ @@ -332,71 +370,71 @@ glm_euler_by_order(vec3 angles, glm_euler_sq ord, mat4 dest) { sysz = sy * sz; switch (ord) { - case GLM_EULER_XYZ: - dest[0][0] = cycz; - dest[0][1] = cysz; - dest[0][2] =-sy; - dest[1][0] = czsx * sy - cxsz; - dest[1][1] = cxcz + sx * sysz; - dest[1][2] = cysx; - dest[2][0] = cx * czsy + sx * sz; - dest[2][1] =-czsx + cx * sysz; - dest[2][2] = cxcy; - break; case GLM_EULER_XZY: - dest[0][0] = cycz; - dest[0][1] = sz; - dest[0][2] =-czsy; - dest[1][0] = sx * sy - cx * cysz; - dest[1][1] = cxcz; - dest[1][2] = cysx + cx * sysz; - dest[2][0] = cx * sy + cysx * sz; - dest[2][1] =-czsx; - dest[2][2] = cxcy - sx * sysz; + dest[0][0] = cycz; + dest[0][1] = sx * sy + cx * cysz; + dest[0][2] = -cx * sy + cysx * sz; + dest[1][0] = -sz; + dest[1][1] = cxcz; + dest[1][2] = czsx; + dest[2][0] = czsy; + dest[2][1] = -cysx + cx * sysz; + dest[2][2] = cxcy + sx * sysz; break; - case GLM_EULER_ZXY: - dest[0][0] = cycz + sx * sysz; - dest[0][1] = cxsz; - dest[0][2] =-czsy + cysx * sz; - dest[1][0] = czsx * sy - cysz; - dest[1][1] = cxcz; - dest[1][2] = cycz * sx + sysz; - dest[2][0] = cx * sy; - dest[2][1] =-sx; - dest[2][2] = cxcy; - break; - case GLM_EULER_ZYX: - dest[0][0] = cycz; - dest[0][1] = czsx * sy + cxsz; - dest[0][2] =-cx * czsy + sx * sz; - dest[1][0] =-cysz; - dest[1][1] = cxcz - sx * sysz; - dest[1][2] = czsx + cx * sysz; - dest[2][0] = sy; - dest[2][1] =-cysx; - dest[2][2] = cxcy; + case GLM_EULER_XYZ: + dest[0][0] = cycz; + dest[0][1] = czsx * sy + cxsz; + dest[0][2] = -cx * czsy + sx * sz; + dest[1][0] = -cysz; + dest[1][1] = cxcz - sx * sysz; + dest[1][2] = czsx + cx * sysz; + dest[2][0] = sy; + dest[2][1] = -cysx; + dest[2][2] = cxcy; break; case GLM_EULER_YXZ: - dest[0][0] = cycz - sx * sysz; - dest[0][1] = czsx * sy + cysz; - dest[0][2] =-cx * sy; - dest[1][0] =-cxsz; - dest[1][1] = cxcz; - dest[1][2] = sx; - dest[2][0] = czsy + cysx * sz; - dest[2][1] =-cycz * sx + sysz; - dest[2][2] = cxcy; + dest[0][0] = cycz + sx * sysz; + dest[0][1] = cxsz; + dest[0][2] = -czsy + cysx * sz; + dest[1][0] = czsx * sy - cysz; + dest[1][1] = cxcz; + dest[1][2] = cycz * sx + sysz; + dest[2][0] = cx * sy; + dest[2][1] = -sx; + dest[2][2] = cxcy; break; case GLM_EULER_YZX: - dest[0][0] = cycz; - dest[0][1] = sx * sy + cx * cysz; - dest[0][2] =-cx * sy + cysx * sz; - dest[1][0] =-sz; - dest[1][1] = cxcz; - dest[1][2] = czsx; - dest[2][0] = czsy; - dest[2][1] =-cysx + cx * sysz; - dest[2][2] = cxcy + sx * sysz; + dest[0][0] = cycz; + dest[0][1] = sz; + dest[0][2] = -czsy; + dest[1][0] = sx * sy - cx * cysz; + dest[1][1] = cxcz; + dest[1][2] = cysx + cx * sysz; + dest[2][0] = cx * sy + cysx * sz; + dest[2][1] = -czsx; + dest[2][2] = cxcy - sx * sysz; + break; + case GLM_EULER_ZXY: + dest[0][0] = cycz - sx * sysz; + dest[0][1] = czsx * sy + cysz; + dest[0][2] = -cx * sy; + dest[1][0] = -cxsz; + dest[1][1] = cxcz; + dest[1][2] = sx; + dest[2][0] = czsy + cysx * sz; + dest[2][1] = -cycz * sx + sysz; + dest[2][2] = cxcy; + break; + case GLM_EULER_ZYX: + dest[0][0] = cycz; + dest[0][1] = cysz; + dest[0][2] = -sy; + dest[1][0] = czsx * sy - cxsz; + dest[1][1] = cxcz + sx * sysz; + dest[1][2] = cysx; + dest[2][0] = cx * czsy + sx * sz; + dest[2][1] = -czsx + cx * sysz; + dest[2][2] = cxcy; break; } diff --git a/makefile.am b/makefile.am index 0767008..a81bdd5 100644 --- a/makefile.am +++ b/makefile.am @@ -105,7 +105,8 @@ test_tests_SOURCES=\ test/src/test_main.c \ test/src/test_mat4.c \ test/src/test_cam.c \ - test/src/test_clamp.c + test/src/test_clamp.c \ + test/src/test_euler.c all-local: sh ./post-build.sh diff --git a/src/euler.c b/src/euler.c index 5c945e2..44d6edb 100644 --- a/src/euler.c +++ b/src/euler.c @@ -20,6 +20,12 @@ glmc_euler(vec3 angles, mat4 dest) { glm_euler(angles, dest); } +CGLM_EXPORT +void +glmc_euler_xyz(vec3 angles, mat4 dest) { + glm_euler_xyz(angles, dest); +} + CGLM_EXPORT void glmc_euler_zyx(vec3 angles, mat4 dest) { diff --git a/test/src/test_common.c b/test/src/test_common.c index e6f36ab..23f2b50 100644 --- a/test/src/test_common.c +++ b/test/src/test_common.c @@ -50,3 +50,10 @@ test_assert_mat4_eq2(mat4 m1, mat4 m2, float eps) { } } } + +void +test_assert_vec3_eq(vec3 v1, vec3 v2) { + assert_true(fabsf(v1[0] - v2[0]) <= 0.0000009); + assert_true(fabsf(v1[1] - v2[1]) <= 0.0000009); + assert_true(fabsf(v1[2] - v2[2]) <= 0.0000009); +} diff --git a/test/src/test_common.h b/test/src/test_common.h index 5fff3d7..aeea4d6 100644 --- a/test/src/test_common.h +++ b/test/src/test_common.h @@ -31,4 +31,7 @@ test_assert_mat4_eq(mat4 m1, mat4 m2); void test_assert_mat4_eq2(mat4 m1, mat4 m2, float eps); +void +test_assert_vec3_eq(vec3 v1, vec3 v2); + #endif /* test_common_h */ diff --git a/test/src/test_euler.c b/test/src/test_euler.c new file mode 100644 index 0000000..b71c4cb --- /dev/null +++ b/test/src/test_euler.c @@ -0,0 +1,44 @@ +/* + * 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" + +void +test_euler(void **state) { + mat4 rot1, rot2; + vec3 inAngles, outAngles; + + inAngles[0] = glm_rad(-45.0f); /* X angle */ + inAngles[1] = glm_rad(88.0f); /* Y angle */ + inAngles[2] = glm_rad(18.0f); /* Z angle */ + + glm_euler_xyz(inAngles, rot1); + + /* extract angles */ + glmc_euler_angles(rot1, outAngles); + + /* angles must be equal in that range */ + test_assert_vec3_eq(inAngles, outAngles); + + /* matrices must be equal */ + glmc_euler_xyz(outAngles, rot2); + test_assert_mat4_eq(rot1, rot2); + + /* change range */ + inAngles[0] = glm_rad(-145.0f); /* X angle */ + inAngles[1] = glm_rad(818.0f); /* Y angle */ + inAngles[2] = glm_rad(181.0f); /* Z angle */ + + glm_euler_xyz(inAngles, rot1); + glmc_euler_angles(rot1, outAngles); + + /* angles may not be equal but matrices MUST! */ + + /* matrices must be equal */ + glmc_euler_xyz(outAngles, rot2); + test_assert_mat4_eq(rot1, rot2); +} diff --git a/test/src/test_main.c b/test/src/test_main.c index 4de5184..38d2fe4 100644 --- a/test/src/test_main.c +++ b/test/src/test_main.c @@ -17,7 +17,10 @@ main(int argc, const char * argv[]) { cmocka_unit_test(test_camera_decomp), /* vector */ - cmocka_unit_test(test_clamp) + cmocka_unit_test(test_clamp), + + /* euler */ + cmocka_unit_test(test_euler) }; return cmocka_run_group_tests(tests, NULL, NULL); diff --git a/test/src/test_tests.h b/test/src/test_tests.h index fb9771e..b1288f7 100644 --- a/test/src/test_tests.h +++ b/test/src/test_tests.h @@ -19,4 +19,7 @@ test_camera_decomp(void **state); void test_clamp(void **state); +void +test_euler(void **state); + #endif /* test_tests_h */