From b3a18b8a1573baaec7f5d4362354ddd452de3501 Mon Sep 17 00:00:00 2001 From: michaelg Date: Thu, 29 Apr 2021 23:48:13 +0100 Subject: [PATCH] Add glm_perspective_rh_zo function + tests This commit adds the RH/ZO perspective function. It does so in the new file `cam_rh_zo.h` and further refactors the LH variant into new file `cam_lh_zo.h`. This creates some churn in the tests and configuration files as new test files were added as well, and all these changes found their way into the build files. Tests passing on Linux. --- CMakeLists.txt | 2 ++ Makefile.am | 6 ++++ include/cglm/cam.h | 33 ---------------------- include/cglm/cam_lh_zo.h | 57 ++++++++++++++++++++++++++++++++++++++ include/cglm/cam_rh_zo.h | 58 +++++++++++++++++++++++++++++++++++++++ include/cglm/cglm.h | 2 ++ src/cam_lh_zo.c | 24 ++++++++++++++++ src/cam_rh_zo.c | 24 ++++++++++++++++ test/CMakeLists.txt | 2 ++ test/glm_cmp/src/main.cpp | 17 +++++++++++- test/src/test_cam.c | 34 ----------------------- test/src/test_cam_lh_zo.c | 37 +++++++++++++++++++++++++ test/src/test_cam_rh_zo.c | 37 +++++++++++++++++++++++++ test/tests.h | 6 ++-- 14 files changed, 269 insertions(+), 70 deletions(-) create mode 100644 include/cglm/cam_lh_zo.h create mode 100644 include/cglm/cam_rh_zo.h create mode 100644 src/cam_lh_zo.c create mode 100644 src/cam_rh_zo.c create mode 100644 test/src/test_cam_lh_zo.c create mode 100644 test/src/test_cam_rh_zo.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 206da0c..e2048ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,8 @@ add_library(${PROJECT_NAME} src/io.c src/quat.c src/cam.c + src/cam_lh_zo.c + src/cam_rh_zo.c src/vec2.c src/vec3.c src/vec4.c diff --git a/Makefile.am b/Makefile.am index e85faa4..f0e2afb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -41,6 +41,8 @@ cglm_HEADERS = include/cglm/version.h \ include/cglm/call.h \ include/cglm/struct.h \ include/cglm/cam.h \ + include/cglm/cam_lh_zo.h \ + include/cglm/cam_rh_zo.h \ include/cglm/io.h \ include/cglm/mat4.h \ include/cglm/mat3.h \ @@ -144,6 +146,8 @@ libcglm_la_SOURCES=\ src/io.c \ src/quat.c \ src/cam.c \ + src/cam_lh_zo.c \ + src/cam_rh_zo.c \ src/vec2.c \ src/vec3.c \ src/vec4.c \ @@ -166,6 +170,8 @@ test_tests_SOURCES=\ test/src/test_common.c \ test/src/tests.c \ test/src/test_cam.c \ + test/src/test_cam_lh_zo.c \ + test/src/test_cam_rh_zo.c \ test/src/test_clamp.c \ test/src/test_euler.c \ test/src/test_bezier.c \ diff --git a/include/cglm/cam.h b/include/cglm/cam.h index 610c06d..e8f6595 100644 --- a/include/cglm/cam.h +++ b/include/cglm/cam.h @@ -248,39 +248,6 @@ glm_perspective(float fovy, float aspect, float nearZ, float farZ, mat4 dest) { dest[3][2] = 2.0f * nearZ * farZ * fn; } -/*! - * @brief set up perspective projection matrix with a left-hand coordinate - * system (suitable for DirectX, Metal and Vulkan) and a clip-space with - * depth values from zero to one. - * - * @param[in] fovy field of view angle - * @param[in] aspect aspect ratio ( width / height ) - * @param[in] nearVal near clipping plane - * @param[in] farVal far clipping planes - * @param[out] dest result matrix - */ -CGLM_INLINE -void -glm_perspective_lh_zo(float fovy, - float aspect, - float nearVal, - float farVal, - mat4 dest) { - /* Impl follows glm::perspectiveLH_ZO in glm/ext/matrix_clip_space.inl */ - float f, fn; - - glm_mat4_zero(dest); - - f = 1.0f / tanf(fovy * 0.5f); - fn = 1.0f / (farVal - nearVal); - - dest[0][0] = f / aspect; - dest[1][1] = f; - dest[2][2] = farVal * fn; - dest[2][3] = 1.0f; - dest[3][2] = -(farVal * nearVal * fn); -} - /*! * @brief extend perspective projection matrix's far distance * diff --git a/include/cglm/cam_lh_zo.h b/include/cglm/cam_lh_zo.h new file mode 100644 index 0000000..ca71ac3 --- /dev/null +++ b/include/cglm/cam_lh_zo.h @@ -0,0 +1,57 @@ +/* + * 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_perspective_lh_zo(float fovy, + float aspect, + float nearVal, + float farVal, + mat4 dest) + */ + +#ifndef cglm_cam_lh_zo_h +#define cglm_cam_lh_zo_h + +#include "common.h" +#include "plane.h" + + +/*! + * @brief set up perspective projection matrix with a left-hand coordinate + * system (suitable, apparently, for DirectX and Metal) and a clip-space with + * depth values from zero to one. + * + * @param[in] fovy field of view angle + * @param[in] aspect aspect ratio ( width / height ) + * @param[in] nearVal near clipping plane + * @param[in] farVal far clipping planes + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_perspective_lh_zo(float fovy, + float aspect, + float nearVal, + float farVal, + mat4 dest) { + /* Impl follows glm::perspectiveLH_ZO in glm/ext/matrix_clip_space.inl */ + float fl, fn; + + glm_mat4_zero(dest); + + fl = 1.0f / tanf(fovy * 0.5f); + fn = 1.0f / (farVal - nearVal); + + dest[0][0] = fl / aspect; + dest[1][1] = fl; + dest[2][2] = farVal * fn; + dest[2][3] = 1.0f; + dest[3][2] = -(farVal * nearVal * fn); +} + +#endif /*cglm_cam_lh_zo_h*/ diff --git a/include/cglm/cam_rh_zo.h b/include/cglm/cam_rh_zo.h new file mode 100644 index 0000000..5f8a81d --- /dev/null +++ b/include/cglm/cam_rh_zo.h @@ -0,0 +1,58 @@ +/* + * 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_perspective_rh_zo(float fovy, + float aspect, + float nearVal, + float farVal, + mat4 dest) + */ + +#ifndef cglm_cam_rh_zo_h +#define cglm_cam_rh_zo_h + +#include "common.h" +#include "plane.h" + +/*! + * @brief set up perspective projection matrix with a right-hand coordinate + * system (suitable for Vulkan) and a clip-space with depth values from zero + * to one. + * + * https://github.com/godlikepanos/anki-3d-engine/blob/317cb379ff3a7b09f9034f49c7bdab0f96a1c0b3/AnKi/Math/Mat.h#L1254 + * + * @param[in] fovy field of view angle + * @param[in] aspect aspect ratio ( width / height ) + * @param[in] nearVal near clipping plane + * @param[in] farVal far clipping planes + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_perspective_rh_zo(float fovy, + float aspect, + float nearVal, + float farVal, + mat4 dest) { + /* Impl follows glm::perspectiveRH_ZO in glm/ext/matrix_clip_space.inl */ + float fl, fn; + + glm_mat4_zero(dest); + + fl = 1.0f / tanf(fovy * 0.5f); + fn = 1.0f / (farVal - nearVal); + + dest[0][0] = fl / aspect; + dest[1][1] = fl; + dest[2][2] = -farVal * fn; + dest[2][3] = -1.0f; + dest[3][2] = -farVal * nearVal * fn; +} + +#endif /*cglm_cam_lh_zo_h*/ diff --git a/include/cglm/cglm.h b/include/cglm/cglm.h index 5ff3421..b069d1d 100644 --- a/include/cglm/cglm.h +++ b/include/cglm/cglm.h @@ -17,6 +17,8 @@ #include "mat2.h" #include "affine.h" #include "cam.h" +#include "cam_lh_zo.h" +#include "cam_rh_zo.h" #include "frustum.h" #include "quat.h" #include "euler.h" diff --git a/src/cam_lh_zo.c b/src/cam_lh_zo.c new file mode 100644 index 0000000..50f0ca7 --- /dev/null +++ b/src/cam_lh_zo.c @@ -0,0 +1,24 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#include "../include/cglm/cglm.h" +#include "../include/cglm/cam_lh_zo.h" + +CGLM_EXPORT +void +glmc_perspective_lh_zo(float fovy, + float aspect, + float nearVal, + float farVal, + mat4 dest) { + glm_perspective_lh_zo(fovy, + aspect, + nearVal, + farVal, + dest); +} + diff --git a/src/cam_rh_zo.c b/src/cam_rh_zo.c new file mode 100644 index 0000000..8c5712f --- /dev/null +++ b/src/cam_rh_zo.c @@ -0,0 +1,24 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#include "../include/cglm/cglm.h" +#include "../include/cglm/cam_rh_zo.h" + +CGLM_EXPORT +void +glmc_perspective_rh_zo(float fovy, + float aspect, + float nearVal, + float farVal, + mat4 dest) { + glm_perspective_rh_zo(fovy, + aspect, + nearVal, + farVal, + dest); +} + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b2a4fdc..2bf26a1 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -6,6 +6,8 @@ set(TESTFILES src/test_euler.c src/test_bezier.c src/test_cam.c + src/test_cam_lh_zo.c + src/test_cam_rh_zo.c src/test_struct.c src/test_clamp.c src/test_common.c diff --git a/test/glm_cmp/src/main.cpp b/test/glm_cmp/src/main.cpp index 3d1ab8b..c594c02 100644 --- a/test/glm_cmp/src/main.cpp +++ b/test/glm_cmp/src/main.cpp @@ -10,6 +10,21 @@ static void outputForPerspectiveLH_ZO() { const float near = 0.1f; const float far = 100.0f; glm::mat4 cmp = glm::perspectiveLH_ZO(fovy, aspect, near, far); + puts("/*reference test data for glm_perspective_lh_zo*/"); + puts("mat4 cmp = {0};"); + printf("cmp[0][0] = %0.7ff;\n", cmp[0][0]); + printf("cmp[1][1] = %0.7ff;\n", cmp[1][1]); + printf("cmp[2][2] = %0.7ff;\n", cmp[2][2]); + printf("cmp[2][3] = %0.7ff;\n", cmp[2][3]); + printf("cmp[3][2] = %0.7ff;\n", cmp[3][2]); +} +static void outputForPerspectiveRH_ZO() { + const float fovy = glm::radians(45.0f); + const float aspect = 640/480.0f; + const float near = 0.1f; + const float far = 100.0f; + glm::mat4 cmp = glm::perspectiveRH_ZO(fovy, aspect, near, far); + puts("/*reference test data for glm_perspective_rh_zo*/"); puts("mat4 cmp = {0};"); printf("cmp[0][0] = %0.7ff;\n", cmp[0][0]); printf("cmp[1][1] = %0.7ff;\n", cmp[1][1]); @@ -19,6 +34,6 @@ static void outputForPerspectiveLH_ZO() { } int main(int argc, char** argv) { - outputForPerspectiveLH_ZO(); + outputForPerspectiveRH_ZO(); return 0; } diff --git a/test/src/test_cam.c b/test/src/test_cam.c index 38a87fd..b5fbf2b 100644 --- a/test/src/test_cam.c +++ b/test/src/test_cam.c @@ -7,40 +7,6 @@ #include "test_common.h" -TEST_IMPL(perspective_lh_zo) { - mat4 dst; - const float fovy = glm_rad(45.0f); - const float aspect = 640/480.0f; - const float near = 0.1f; - const float far = 100.0f; - - glm_perspective_lh_zo(fovy, aspect, near, far, dst); - - /* Sanity mk. I */ - /* Longhand version of what the above function _should_ be doing */ - ASSERT(test_eq(dst[0][0], 1 / (tanf(fovy / 2) * aspect))) - ASSERT(test_eq(dst[1][1], 1 / tanf(fovy / 2))) - ASSERT(test_eq(dst[2][2], far / (far - near))) - ASSERT(test_eq(dst[2][3], 1.0f)) - ASSERT(test_eq(dst[3][2], -1 * far * near / (far - near))) - - /* Sanity mk. II */ - /* "Reference values" generated by GLM's glm::perspectiveLH_ZO */ - mat4 cmp = {0}; - cmp[0][0] = 1.8106601f; - cmp[1][1] = 2.4142134f; - cmp[2][2] = 1.0010010f; - cmp[2][3] = 1.0000000f; - cmp[3][2] = -0.1001001f; - - for (uint32_t i = 0 ; i < 16 ; i++) { - uint32_t r = i%4, c = i/4; - ASSERT(fabsf(dst[r][c] - cmp[r][c]) < GLM_FLT_EPSILON) - } - - TEST_SUCCESS -} - TEST_IMPL(camera_lookat) { mat4 view1, view2; vec3 center, diff --git a/test/src/test_cam_lh_zo.c b/test/src/test_cam_lh_zo.c new file mode 100644 index 0000000..418229b --- /dev/null +++ b/test/src/test_cam_lh_zo.c @@ -0,0 +1,37 @@ +/* + * 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" + +TEST_IMPL(perspective_lh_zo) { + mat4 dst; + const float fovy = glm_rad(45.0f); + const float aspect = 640/480.0f; + const float zNearVal = 0.1f; + const float zFarVal = 100.0f; + + glm_perspective_lh_zo(fovy, aspect, zNearVal, zFarVal, dst); + + /* Sanity mk. I */ + /* Longhand version of what the above function _should_ be doing */ + ASSERT(test_eq(dst[0][0], 1 / (tanf(fovy / 2) * aspect))) + ASSERT(test_eq(dst[1][1], 1 / tanf(fovy / 2))) + ASSERT(test_eq(dst[2][2], zFarVal / (zFarVal - zNearVal))) + ASSERT(test_eq(dst[2][3], 1.0f)) + ASSERT(test_eq(dst[3][2], -1 * zFarVal * zNearVal / (zFarVal - zNearVal))) + + /* Sanity mk. II */ + /* "Reference values" generated by GLM's glm::perspectiveLH_ZO */ + mat4 cmp = {0}; + cmp[0][0] = 1.8106601f; + cmp[1][1] = 2.4142134f; + cmp[2][2] = 1.0010010f; + cmp[2][3] = 1.0000000f; + cmp[3][2] = -0.1001001f; + + return (test_assert_mat4_eq(dst, cmp)); +} diff --git a/test/src/test_cam_rh_zo.c b/test/src/test_cam_rh_zo.c new file mode 100644 index 0000000..c2cb5ba --- /dev/null +++ b/test/src/test_cam_rh_zo.c @@ -0,0 +1,37 @@ +/* + * 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" + +TEST_IMPL(perspective_rh_zo) { + mat4 dst; + const float fovy = glm_rad(45.0f); + const float aspect = 640/480.0f; + const float zNearVal = 0.1f; + const float zFarVal = 100.0f; + + glm_perspective_rh_zo(fovy, aspect, zNearVal, zFarVal, dst); + + /* Sanity mk. I: longhand version */ + float focal_len = 1 / tanf(fovy / 2); + ASSERT(test_eq(dst[0][0], focal_len / aspect)) + ASSERT(test_eq(dst[1][1], focal_len)) + ASSERT(test_eq(dst[2][2], zFarVal / (zNearVal - zFarVal))) + ASSERT(test_eq(dst[2][3], -1.0f)) + ASSERT(test_eq(dst[3][2], -1 * zFarVal * zNearVal / (zFarVal - zNearVal))) + + /* Sanity mk. II */ + /*reference test data for glm_perspective_rh_zo*/ + mat4 cmp = {0}; + cmp[0][0] = 1.8106601f; + cmp[1][1] = 2.4142134f; + cmp[2][2] = -1.0010010f; + cmp[2][3] = -1.0000000f; + cmp[3][2] = -0.1001001f; + + return test_assert_mat4_eq(dst, cmp); +} diff --git a/test/tests.h b/test/tests.h index 79795a7..137d38d 100644 --- a/test/tests.h +++ b/test/tests.h @@ -222,8 +222,9 @@ TEST_DECLARE(glmc_mat2_swap_col) TEST_DECLARE(glmc_mat2_swap_row) TEST_DECLARE(glmc_mat2_rmc) -/* camera */ +/* camera (incl [LR]H cross [NZ]O) */ TEST_DECLARE(perspective_lh_zo) +TEST_DECLARE(perspective_rh_zo) TEST_DECLARE(camera_lookat) TEST_DECLARE(camera_decomp) @@ -947,8 +948,9 @@ TEST_LIST { TEST_ENTRY(glmc_mat2_swap_row) TEST_ENTRY(glmc_mat2_rmc) - /* camera */ + /* camera (incl [LR]H cross [NZ]O) */ TEST_ENTRY(perspective_lh_zo) + TEST_ENTRY(perspective_rh_zo) TEST_ENTRY(camera_lookat) TEST_ENTRY(camera_decomp)