From 797c4581ee1101905b7a8c721dba6d28173ccec9 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Thu, 4 Jan 2018 11:16:09 +0300 Subject: [PATCH 1/5] extract fovy and aspect for perpective matrix --- include/cglm/cam.h | 25 +++++++++++++++++++++++++ makefile.am | 3 ++- test/src/test_cam.c | 25 +++++++++++++++++++++++++ test/src/test_main.c | 3 +++ test/src/test_tests.h | 4 ++++ 5 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 test/src/test_cam.c diff --git a/include/cglm/cam.h b/include/cglm/cam.h index 5d39ef2..d69de83 100644 --- a/include/cglm/cam.h +++ b/include/cglm/cam.h @@ -426,6 +426,31 @@ glm_persp_decomp_near(mat4 proj, float * __restrict nearVal) { *nearVal = proj[3][2] / (proj[2][2] - 1); } +/*! + * @brief returns field of view angle along the Y-axis (in radians) + * + * if you need to degrees, use glm_deg to convert it or use this: + * fovy_deg = glm_deg(glm_persp_fovy(projMatrix)) + * + * @param[in] proj perspective projection matrix + */ +CGLM_INLINE +float +glm_persp_fovy(mat4 proj) { + return 2.0 * atan(1.0 / proj[1][1]); +} + +/*! + * @brief returns aspect ratio of perspective projection + * + * @param[in] proj perspective projection matrix + */ +CGLM_INLINE +float +glm_persp_aspect(mat4 proj) { + return proj[1][1] / proj[0][0]; +} + /*! * @brief extracts view frustum planes * diff --git a/makefile.am b/makefile.am index f1dadfc..5830700 100644 --- a/makefile.am +++ b/makefile.am @@ -93,7 +93,8 @@ libcglm_la_SOURCES=\ test_tests_SOURCES=\ test/src/test_common.c \ test/src/test_main.c \ - test/src/test_mat4.c + test/src/test_mat4.c \ + test/src/test_cam.c all-local: sh ./post-build.sh diff --git a/test/src/test_cam.c b/test/src/test_cam.c new file mode 100644 index 0000000..cfa7747 --- /dev/null +++ b/test/src/test_cam.c @@ -0,0 +1,25 @@ +/* + * 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_camera_decomp(void **state) { + mat4 proj; + float aspect, fovy, nearVal, farVal; + + aspect = 0.782f; + fovy = glm_rad(49.984f); + nearVal = 0.1f; + farVal = 100.0f; + + glm_perspective(fovy, aspect, nearVal, farVal, proj); + assert_true(fabsf(aspect - glm_persp_aspect(proj)) < FLT_EPSILON); + assert_true(fabsf(fovy - glm_persp_fovy(proj)) < FLT_EPSILON); + assert_true(fabsf(49.984f - glm_deg(glm_persp_fovy(proj))) < FLT_EPSILON); +} + diff --git a/test/src/test_main.c b/test/src/test_main.c index 4578997..25c7d17 100644 --- a/test/src/test_main.c +++ b/test/src/test_main.c @@ -11,6 +11,9 @@ main(int argc, const char * argv[]) { const struct CMUnitTest tests[] = { /* mat4 */ cmocka_unit_test(test_mat4), + + /* camera */ + cmocka_unit_test(test_camera_decomp) }; return cmocka_run_group_tests(tests, diff --git a/test/src/test_tests.h b/test/src/test_tests.h index 7e8fe20..a6a8a58 100644 --- a/test/src/test_tests.h +++ b/test/src/test_tests.h @@ -9,4 +9,8 @@ /* mat4 */ void test_mat4(void **state); +/* camera */ +void +test_camera_decomp(void **state); + #endif /* test_tests_h */ From d53f95314db83b7acec08b5ce84ac16c4aa9a8a4 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Thu, 4 Jan 2018 13:52:35 +0300 Subject: [PATCH 2/5] apply optimizations --- include/cglm/cam.h | 75 +++++++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 24 deletions(-) diff --git a/include/cglm/cam.h b/include/cglm/cam.h index d69de83..00e1acb 100644 --- a/include/cglm/cam.h +++ b/include/cglm/cam.h @@ -323,12 +323,28 @@ glm_persp_decomp(mat4 proj, float * __restrict bottom, float * __restrict left, float * __restrict right) { - *nearVal = proj[3][2] / (proj[2][2] - 1); - *farVal = proj[3][2] / (proj[2][2] + 1); - *bottom = *nearVal * (proj[2][1] - 1) / proj[1][1]; - *top = *nearVal * (proj[2][1] + 1) / proj[1][1]; - *left = *nearVal * (proj[2][0] - 1) / proj[0][0]; - *right = *nearVal * (proj[2][0] + 1) / proj[0][0]; + float m00, m11, m20, m21, m22, m32, n, f; + float n_m11, n_m00; + + m00 = proj[0][0]; + m11 = proj[1][1]; + m20 = proj[2][0]; + m21 = proj[2][1]; + m22 = proj[2][2]; + m32 = proj[3][2]; + + f = m32 / (m22 - 1); + n = m32 / (m22 + 1); + + n_m11 = n / m11; + n_m00 = n / m00; + + *nearVal = f; + *farVal = n; + *bottom = n_m11 * (m21 - 1); + *top = n_m11 * (m21 + 1); + *left = n_m00 * (m20 - 1); + *right = n_m00 * (m20 + 1); } /*! @@ -358,11 +374,14 @@ void glm_persp_decomp_x(mat4 proj, float * __restrict left, float * __restrict right) { - float nearVal; + float nearVal, m20, m00; + + m00 = proj[0][0]; + m20 = proj[2][0]; nearVal = proj[3][2] / (proj[3][3] - 1); - *left = nearVal * (proj[2][0] - 1) / proj[0][0]; - *right = nearVal * (proj[2][0] + 1) / proj[0][0]; + *left = nearVal * (m20 - 1) / m00; + *right = nearVal * (m20 + 1) / m00; } /*! @@ -378,11 +397,14 @@ void glm_persp_decomp_y(mat4 proj, float * __restrict top, float * __restrict bottom) { - float nearVal; + float nearVal, m21, m11; + + m21 = proj[2][1]; + m11 = proj[1][1]; nearVal = proj[3][2] / (proj[3][3] - 1); - *bottom = nearVal * (proj[2][1] - 1) / proj[1][1]; - *top = nearVal * (proj[2][1] + 1) / proj[1][1]; + *bottom = nearVal * (m21 - 1) / m11; + *top = nearVal * (m21 + 1) / m11; } /*! @@ -398,8 +420,13 @@ void glm_persp_decomp_z(mat4 proj, float * __restrict nearVal, float * __restrict farVal) { - *nearVal = proj[3][2] / (proj[2][2] - 1); - *farVal = proj[3][2] / (proj[2][2] + 1); + float m32, m22; + + m32 = proj[3][2]; + m22 = proj[2][2]; + + *nearVal = m32 / (m22 - 1); + *farVal = m32 / (m22 + 1); } /*! @@ -437,7 +464,7 @@ glm_persp_decomp_near(mat4 proj, float * __restrict nearVal) { CGLM_INLINE float glm_persp_fovy(mat4 proj) { - return 2.0 * atan(1.0 / proj[1][1]); + return 2.0f * atanf(1.0f / proj[1][1]); } /*! @@ -510,7 +537,7 @@ CGLM_INLINE void glm_frustum_corners(mat4 invMat, vec4 dest[8]) { vec4 c[8]; - vec4 ndcCorners[8] = { + vec4 csCoords[8] = { {-1.0f, -1.0f, -1.0f, 1.0f}, {-1.0f, 1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, -1.0f, 1.0f}, @@ -521,14 +548,14 @@ glm_frustum_corners(mat4 invMat, vec4 dest[8]) { { 1.0f, 1.0f, 1.0f, 1.0f} }; - glm_mat4_mulv(invMat, ndcCorners[0], c[0]); - glm_mat4_mulv(invMat, ndcCorners[1], c[1]); - glm_mat4_mulv(invMat, ndcCorners[2], c[2]); - glm_mat4_mulv(invMat, ndcCorners[3], c[3]); - glm_mat4_mulv(invMat, ndcCorners[4], c[4]); - glm_mat4_mulv(invMat, ndcCorners[5], c[5]); - glm_mat4_mulv(invMat, ndcCorners[6], c[6]); - glm_mat4_mulv(invMat, ndcCorners[7], c[7]); + glm_mat4_mulv(invMat, csCoords[0], c[0]); + glm_mat4_mulv(invMat, csCoords[1], c[1]); + glm_mat4_mulv(invMat, csCoords[2], c[2]); + glm_mat4_mulv(invMat, csCoords[3], c[3]); + glm_mat4_mulv(invMat, csCoords[4], c[4]); + glm_mat4_mulv(invMat, csCoords[5], c[5]); + glm_mat4_mulv(invMat, csCoords[6], c[6]); + glm_mat4_mulv(invMat, csCoords[7], c[7]); glm_vec4_scale(c[1], 1.0f / c[1][3], dest[1]); glm_vec4_scale(c[2], 1.0f / c[2][3], dest[2]); From 642cc8d603f85874e47f9025363af0e4c463b6ea Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Thu, 4 Jan 2018 13:54:35 +0300 Subject: [PATCH 3/5] perspective sizes --- include/cglm/cam.h | 26 ++++++++++++++++++++++++++ test/src/test_cam.c | 15 ++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/include/cglm/cam.h b/include/cglm/cam.h index 00e1acb..ea97bbb 100644 --- a/include/cglm/cam.h +++ b/include/cglm/cam.h @@ -478,6 +478,32 @@ glm_persp_aspect(mat4 proj) { return proj[1][1] / proj[0][0]; } +/*! + * @brief returns aspect ratio of perspective projection + * + * if you don't have fovy then use glm_persp_fovy(proj) to get it + * or pass directly: glm_persp_sizes(proj, glm_persp_fovy(proj), sizes); + * + * @param[in] proj perspective projection matrix + * @param[in] fovy fovy (see brief) + * @param[out] dest sizes order: [Wnear, Hnear, Wfar, Hfar] + */ +CGLM_INLINE +void +glm_persp_sizes(mat4 proj, float fovy, vec4 dest) { + float t, a, nearVal, farVal; + + t = 2.0f * tanf(fovy * 0.5f); + a = glm_persp_aspect(proj); + + glm_persp_decomp_z(proj, &nearVal, &farVal); + + dest[1] = t * nearVal; + dest[3] = t * farVal; + dest[0] = a * dest[1]; + dest[2] = a * dest[3]; +} + /*! * @brief extracts view frustum planes * diff --git a/test/src/test_cam.c b/test/src/test_cam.c index cfa7747..9df4b53 100644 --- a/test/src/test_cam.c +++ b/test/src/test_cam.c @@ -9,7 +9,8 @@ void test_camera_decomp(void **state) { - mat4 proj; + mat4 proj, proj2; + vec4 sizes; float aspect, fovy, nearVal, farVal; aspect = 0.782f; @@ -21,5 +22,17 @@ test_camera_decomp(void **state) { assert_true(fabsf(aspect - glm_persp_aspect(proj)) < FLT_EPSILON); assert_true(fabsf(fovy - glm_persp_fovy(proj)) < FLT_EPSILON); assert_true(fabsf(49.984f - glm_deg(glm_persp_fovy(proj))) < FLT_EPSILON); + + glm_persp_sizes(proj, fovy, sizes); + + glm_frustum(-sizes[0] * 0.5, + sizes[0] * 0.5, + -sizes[1] * 0.5, + sizes[1] * 0.5, + nearVal, + farVal, + proj2); + + test_assert_mat4_eq(proj, proj2); } From b3c3e3a034072d97169e4f01870bf7fa221bac94 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Mon, 8 Jan 2018 16:03:53 +0300 Subject: [PATCH 4/5] fix variable names --- include/cglm/cam.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/cglm/cam.h b/include/cglm/cam.h index ea97bbb..4e3d888 100644 --- a/include/cglm/cam.h +++ b/include/cglm/cam.h @@ -333,14 +333,14 @@ glm_persp_decomp(mat4 proj, m22 = proj[2][2]; m32 = proj[3][2]; - f = m32 / (m22 - 1); - n = m32 / (m22 + 1); + n = m32 / (m22 - 1); + f = m32 / (m22 + 1); n_m11 = n / m11; n_m00 = n / m00; - *nearVal = f; - *farVal = n; + *nearVal = n; + *farVal = f; *bottom = n_m11 * (m21 - 1); *top = n_m11 * (m21 + 1); *left = n_m00 * (m20 - 1); @@ -438,7 +438,7 @@ glm_persp_decomp_z(mat4 proj, CGLM_INLINE void glm_persp_decomp_far(mat4 proj, float * __restrict farVal) { - *farVal = proj[3][2] / (proj[2][2] + 1); + *farVal = proj[3][2] / (proj[2][2] + 1.0f); } /*! @@ -450,7 +450,7 @@ glm_persp_decomp_far(mat4 proj, float * __restrict farVal) { CGLM_INLINE void glm_persp_decomp_near(mat4 proj, float * __restrict nearVal) { - *nearVal = proj[3][2] / (proj[2][2] - 1); + *nearVal = proj[3][2] / (proj[2][2] - 1.0f); } /*! From 42743e3b82aace1cedc310d4d46c3975e88c879e Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Wed, 10 Jan 2018 00:01:06 +0300 Subject: [PATCH 5/5] use float literal suffix for numbers --- include/cglm/cam.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/include/cglm/cam.h b/include/cglm/cam.h index 4e3d888..a65847c 100644 --- a/include/cglm/cam.h +++ b/include/cglm/cam.h @@ -333,18 +333,18 @@ glm_persp_decomp(mat4 proj, m22 = proj[2][2]; m32 = proj[3][2]; - n = m32 / (m22 - 1); - f = m32 / (m22 + 1); + n = m32 / (m22 - 1.0f); + f = m32 / (m22 + 1.0f); n_m11 = n / m11; n_m00 = n / m00; *nearVal = n; *farVal = f; - *bottom = n_m11 * (m21 - 1); - *top = n_m11 * (m21 + 1); - *left = n_m00 * (m20 - 1); - *right = n_m00 * (m20 + 1); + *bottom = n_m11 * (m21 - 1.0f); + *top = n_m11 * (m21 + 1.0f); + *left = n_m00 * (m20 - 1.0f); + *right = n_m00 * (m20 + 1.0f); } /*! @@ -379,9 +379,9 @@ glm_persp_decomp_x(mat4 proj, m00 = proj[0][0]; m20 = proj[2][0]; - nearVal = proj[3][2] / (proj[3][3] - 1); - *left = nearVal * (m20 - 1) / m00; - *right = nearVal * (m20 + 1) / m00; + nearVal = proj[3][2] / (proj[3][3] - 1.0f); + *left = nearVal * (m20 - 1.0f) / m00; + *right = nearVal * (m20 + 1.0f) / m00; } /*! @@ -402,7 +402,7 @@ glm_persp_decomp_y(mat4 proj, m21 = proj[2][1]; m11 = proj[1][1]; - nearVal = proj[3][2] / (proj[3][3] - 1); + nearVal = proj[3][2] / (proj[3][3] - 1.0f); *bottom = nearVal * (m21 - 1) / m11; *top = nearVal * (m21 + 1) / m11; } @@ -425,8 +425,8 @@ glm_persp_decomp_z(mat4 proj, m32 = proj[3][2]; m22 = proj[2][2]; - *nearVal = m32 / (m22 - 1); - *farVal = m32 / (m22 + 1); + *nearVal = m32 / (m22 - 1.0f); + *farVal = m32 / (m22 + 1.0f); } /*!