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)