diff --git a/docs/source/util.rst b/docs/source/util.rst index 048be70..43a9d49 100644 --- a/docs/source/util.rst +++ b/docs/source/util.rst @@ -18,6 +18,9 @@ Functions: #. :c:func:`glm_make_rad` #. :c:func:`glm_make_deg` #. :c:func:`glm_pow2` +#. :c:func:`glm_min` +#. :c:func:`glm_max` +#. :c:func:`glm_clamp` Functions documentation ~~~~~~~~~~~~~~~~~~~~~~~ @@ -91,3 +94,15 @@ Functions documentation Returns: maximum value + +.. c:function:: void glm_clamp(float val, float minVal, float maxVal) + + constrain a value to lie between two further values + + Parameters: + | *[in]* **val** input value + | *[in]* **minVal** minimum value + | *[in]* **maxVal** maximum value + + Returns: + clamped value diff --git a/docs/source/vec3.rst b/docs/source/vec3.rst index 2ae95f0..355178d 100644 --- a/docs/source/vec3.rst +++ b/docs/source/vec3.rst @@ -53,6 +53,7 @@ Functions: #. :c:func:`glm_vec_maxv` #. :c:func:`glm_vec_minv` #. :c:func:`glm_vec_ortho` +#. :c:func:`glm_vec_clamp` Functions documentation ~~~~~~~~~~~~~~~~~~~~~~~ @@ -271,3 +272,12 @@ Functions documentation Parameters: | *[in]* **mat** vector | *[out]* **dest** orthogonal/perpendicular vector + +.. c:function:: void glm_vec_clamp(vec3 v, float minVal, float maxVal) + + constrain a value to lie between two further values + + Parameters: + | *[in, out]* **v** vector + | *[in]* **minVal** minimum value + | *[in]* **maxVal** maximum value diff --git a/docs/source/vec4.rst b/docs/source/vec4.rst index 60be7fa..ac1b9c5 100644 --- a/docs/source/vec4.rst +++ b/docs/source/vec4.rst @@ -39,6 +39,7 @@ Functions: #. :c:func:`glm_vec4_distance` #. :c:func:`glm_vec4_maxv` #. :c:func:`glm_vec4_minv` +#. :c:func:`glm_vec4_clamp` Functions documentation ~~~~~~~~~~~~~~~~~~~~~~~ @@ -203,3 +204,12 @@ Functions documentation | *[in]* **v1** vector1 | *[in]* **v2** vector2 | *[out]* **dest** destination + +.. c:function:: void glm_vec4_clamp(vec4 v, float minVal, float maxVal) + + constrain a value to lie between two further values + + Parameters: + | *[in, out]* **v** vector + | *[in]* **minVal** minimum value + | *[in]* **maxVal** maximum value diff --git a/include/cglm/call/vec3.h b/include/cglm/call/vec3.h index a637d7e..461de0b 100644 --- a/include/cglm/call/vec3.h +++ b/include/cglm/call/vec3.h @@ -104,6 +104,10 @@ CGLM_EXPORT void glmc_vec_minv(vec3 v1, vec3 v2, vec3 dest); +CGLM_EXPORT +void +glmc_vec_clamp(vec3 v, float minVal, float maxVal); + #ifdef __cplusplus } #endif diff --git a/include/cglm/call/vec4.h b/include/cglm/call/vec4.h index 084fce2..b63af80 100644 --- a/include/cglm/call/vec4.h +++ b/include/cglm/call/vec4.h @@ -85,6 +85,10 @@ CGLM_EXPORT void glmc_vec4_minv(vec4 v1, vec4 v2, vec4 dest); +CGLM_EXPORT +void +glmc_vec4_clamp(vec4 v, float minVal, float maxVal); + #ifdef __cplusplus } #endif diff --git a/include/cglm/util.h b/include/cglm/util.h index 12db1a2..20b4c67 100644 --- a/include/cglm/util.h +++ b/include/cglm/util.h @@ -115,4 +115,17 @@ glm_max(float a, float b) { return b; } +/*! + * @brief clamp a number between min and max + * + * @param[in] val value to clamp + * @param[in] minVal minimum value + * @param[in] maxVal maximum value + */ +CGLM_INLINE +float +glm_clamp(float val, float minVal, float maxVal) { + return glm_min(glm_max(val, minVal), maxVal); +} + #endif /* cglm_util_h */ diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index 26adf7d..e2108f3 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -46,6 +46,7 @@ CGLM_INLINE void glm_vec_maxv(vec3 v1, vec3 v2, vec3 dest); CGLM_INLINE void glm_vec_minv(vec3 v1, vec3 v2, vec3 dest); CGLM_INLINE void glm_vec_ortho(vec3 v, vec3 dest); + CGLM_INLINE void glm_vec_clamp(vec3 v, float minVal, float maxVal); Convenient: CGLM_INLINE void glm_cross(vec3 a, vec3 b, vec3 d); @@ -478,6 +479,21 @@ glm_vec_ortho(vec3 v, vec3 dest) { dest[2] = v[0] - v[1]; } +/*! + * @brief clamp vector's individual members between min and max values + * + * @param[in, out] v vector + * @param[in] minVal minimum value + * @param[in] maxVal maximum value + */ +CGLM_INLINE +void +glm_vec_clamp(vec3 v, float minVal, float maxVal) { + v[0] = glm_clamp(v[0], minVal, maxVal); + v[1] = glm_clamp(v[1], minVal, maxVal); + v[2] = glm_clamp(v[2], minVal, maxVal); +} + /*! * @brief vec3 cross product * diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index a656166..95bab09 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -40,6 +40,7 @@ CGLM_INLINE float glm_vec4_distance(vec4 v1, vec4 v2); CGLM_INLINE void glm_vec4_maxv(vec4 v1, vec4 v2, vec4 dest); CGLM_INLINE void glm_vec4_minv(vec4 v1, vec4 v2, vec4 dest); + CGLM_INLINE void glm_vec4_clamp(vec4 v, float minVal, float maxVal); */ #ifndef cglm_vec4_h @@ -373,4 +374,20 @@ glm_vec4_minv(vec4 v1, vec4 v2, vec4 dest) { dest[3] = glm_min(v1[3], v2[3]); } +/*! + * @brief clamp vector's individual members between min and max values + * + * @param[in, out] v vector + * @param[in] minVal minimum value + * @param[in] maxVal maximum value + */ +CGLM_INLINE +void +glm_vec4_clamp(vec4 v, float minVal, float maxVal) { + v[0] = glm_clamp(v[0], minVal, maxVal); + v[1] = glm_clamp(v[1], minVal, maxVal); + v[2] = glm_clamp(v[2], minVal, maxVal); + v[3] = glm_clamp(v[3], minVal, maxVal); +} + #endif /* cglm_vec4_h */ diff --git a/makefile.am b/makefile.am index f6d1471..0767008 100644 --- a/makefile.am +++ b/makefile.am @@ -104,7 +104,8 @@ test_tests_SOURCES=\ test/src/test_common.c \ test/src/test_main.c \ test/src/test_mat4.c \ - test/src/test_cam.c + test/src/test_cam.c \ + test/src/test_clamp.c all-local: sh ./post-build.sh diff --git a/src/vec3.c b/src/vec3.c index f377d88..ebc677d 100644 --- a/src/vec3.c +++ b/src/vec3.c @@ -139,3 +139,9 @@ void glmc_vec_minv(vec3 v1, vec3 v2, vec3 dest) { glm_vec_maxv(v1, v2, dest); } + +CGLM_EXPORT +void +glmc_vec_clamp(vec3 v, float minVal, float maxVal) { + glm_vec_clamp(v, minVal, maxVal); +} diff --git a/src/vec4.c b/src/vec4.c index 279652d..f5f6a06 100644 --- a/src/vec4.c +++ b/src/vec4.c @@ -109,3 +109,9 @@ void glmc_vec4_minv(vec4 v1, vec4 v2, vec4 dest) { glm_vec4_maxv(v1, v2, dest); } + +CGLM_EXPORT +void +glmc_vec4_clamp(vec4 v, float minVal, float maxVal) { + glm_vec4_clamp(v, minVal, maxVal); +} diff --git a/test/src/test_clamp.c b/test/src/test_clamp.c new file mode 100644 index 0000000..ee98958 --- /dev/null +++ b/test/src/test_clamp.c @@ -0,0 +1,30 @@ +/* + * 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_clamp(void **state) { + vec3 v3 = {15.07, 0.4, 17.3}; + vec4 v4 = {5.07, 2.3, 1.3, 1.4}; + + assert_true(glm_clamp(1.6f, 0.0f, 1.0f) == 1.0f); + assert_true(glm_clamp(-1.6f, 0.0f, 1.0f) == 0.0f); + assert_true(glm_clamp(0.6f, 0.0f, 1.0f) == 0.6f); + + glm_vec_clamp(v3, 0.0, 1.0); + glm_vec4_clamp(v4, 1.5, 3.0); + + assert_true(v3[0] == 1.0f); + assert_true(v3[1] == 0.4f); + assert_true(v3[2] == 1.0f); + + assert_true(v4[0] == 3.0f); + assert_true(v4[1] == 2.3f); + assert_true(v4[2] == 1.5f); + assert_true(v4[3] == 1.5f); +} diff --git a/test/src/test_main.c b/test/src/test_main.c index 5d59cfd..4de5184 100644 --- a/test/src/test_main.c +++ b/test/src/test_main.c @@ -14,7 +14,10 @@ main(int argc, const char * argv[]) { /* camera */ cmocka_unit_test(test_camera_lookat), - cmocka_unit_test(test_camera_decomp) + cmocka_unit_test(test_camera_decomp), + + /* vector */ + cmocka_unit_test(test_clamp) }; return cmocka_run_group_tests(tests, NULL, NULL); diff --git a/test/src/test_tests.h b/test/src/test_tests.h index a4e5adb..fb9771e 100644 --- a/test/src/test_tests.h +++ b/test/src/test_tests.h @@ -16,4 +16,7 @@ test_camera_lookat(void **state); void test_camera_decomp(void **state); +void +test_clamp(void **state); + #endif /* test_tests_h */