diff --git a/README.md b/README.md
index 84b321e..4e7c4ef 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,11 @@
# 🎥 OpenGL Mathematics (glm) for `C`
[](https://travis-ci.org/recp/cglm)
-[](https://ci.appveyor.com/project/recp/cglm/branch/master)
+ [](https://ci.appveyor.com/project/recp/cglm/branch/master)
[](http://cglm.readthedocs.io/en/latest/?badge=latest)
[](https://coveralls.io/github/recp/cglm?branch=master)
[](https://www.codacy.com/app/recp/cglm?utm_source=github.com&utm_medium=referral&utm_content=recp/cglm&utm_campaign=Badge_Grade)
+[](#backers)
+[](#sponsors)
The original glm library is for C++ only (templates, namespaces, classes...), this library targeted to C99 but currently you can use it for C89 safely by language extensions e.g `__restrict`
@@ -17,6 +19,7 @@ Complete documentation: http://cglm.readthedocs.io
- _dup (duplicate) is changed to _copy. For instance `glm_vec_dup -> glm_vec_copy`
- OpenGL related functions are dropped to make this lib platform/third-party independent
- make sure you have latest version and feel free to report bugs, troubles
+- **[bugfix]** euler angles was implemented in reverse order (extrinsic) it was fixed, now they are intrinsic. Make sure that you have the latest version
#### Note for C++ developers:
If you don't aware about original GLM library yet, you may also want to look at:
@@ -114,6 +117,36 @@ glm_mul(T, R, modelMat);
glm_inv_tr(modelMat);
```
+## Contributors
+
+This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
+
+
+
+## Backers
+
+Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/cglm#backer)]
+
+
+
+
+## Sponsors
+
+Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/cglm#sponsor)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
## License
MIT. check the LICENSE file
@@ -161,7 +194,7 @@ If you want to use inline versions of funcstions then; include main header
```C
#include
```
-the haeder will include all headers. Then call func you want e.g. rotate vector by axis:
+the header will include all headers. Then call func you want e.g. rotate vector by axis:
```C
glm_vec_rotate(v1, glm_rad(45), (vec3){1.0f, 0.0f, 0.0f});
```
@@ -180,7 +213,7 @@ to call pre-compiled versions include header with `c` postfix, c means call. Pre
```C
#include
```
-this header will include all heaers with c postfix. You need to call functions with c posfix:
+this header will include all headers with c postfix. You need to call functions with c posfix:
```C
glmc_vec_normalize(vec);
```
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/configure.ac b/configure.ac
index 23e8a15..afb694b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,7 +7,7 @@
#*****************************************************************************
AC_PREREQ([2.69])
-AC_INIT([cglm], [0.3.5], [info@recp.me])
+AC_INIT([cglm], [0.3.6], [info@recp.me])
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
AC_CONFIG_MACRO_DIR([m4])
diff --git a/docs/source/box.rst b/docs/source/box.rst
index 84ba145..6aa4d62 100644
--- a/docs/source/box.rst
+++ b/docs/source/box.rst
@@ -24,6 +24,10 @@ Functions:
#. :c:func:`glm_aabb_crop`
#. :c:func:`glm_aabb_crop_until`
#. :c:func:`glm_aabb_frustum`
+#. :c:func:`glm_aabb_invalidate`
+#. :c:func:`glm_aabb_isvalid`
+#. :c:func:`glm_aabb_size`
+#. :c:func:`glm_aabb_radius`
Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~
@@ -91,3 +95,39 @@ Functions documentation
Parameters:
| *[in]* **box** bounding box
| *[out]* **planes** frustum planes
+
+.. c:function:: void glm_aabb_invalidate(vec3 box[2])
+
+ | invalidate AABB min and max values
+
+ | It fills *max* values with -FLT_MAX and *min* values with +FLT_MAX
+
+ Parameters:
+ | *[in, out]* **box** bounding box
+
+.. c:function:: bool glm_aabb_isvalid(vec3 box[2])
+
+ | check if AABB is valid or not
+
+ Parameters:
+ | *[in]* **box** bounding box
+
+ Returns:
+ returns true if aabb is valid otherwise false
+
+.. c:function:: float glm_aabb_size(vec3 box[2])
+
+ | distance between of min and max
+
+ Parameters:
+ | *[in]* **box** bounding box
+
+ Returns:
+ distance between min - max
+
+.. c:function:: float glm_aabb_radius(vec3 box[2])
+
+ | radius of sphere which surrounds AABB
+
+ Parameters:
+ | *[in]* **box** bounding box
diff --git a/docs/source/io.rst b/docs/source/io.rst
index 9cf8900..34fe696 100644
--- a/docs/source/io.rst
+++ b/docs/source/io.rst
@@ -39,6 +39,7 @@ Functions:
#. :c:func:`glm_vec3_print`
#. :c:func:`glm_ivec3_print`
#. :c:func:`glm_versor_print`
+#. :c:func:`glm_aabb_print`
Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~
@@ -90,3 +91,12 @@ Functions documentation
Parameters:
| *[in]* **vec** quaternion
| *[in]* **ostream** FILE to write
+
+.. c:function:: void glm_aabb_print(versor vec, const char * __restrict tag, FILE * __restrict ostream)
+
+ | print aabb to given stream
+
+ Parameters:
+ | *[in]* **vec** aabb (axis-aligned bounding box)
+ | *[in]* **tag** tag to find it more easly in logs
+ | *[in]* **ostream** FILE to write
diff --git a/docs/source/util.rst b/docs/source/util.rst
index 048be70..a9f4066 100644
--- a/docs/source/util.rst
+++ b/docs/source/util.rst
@@ -13,18 +13,24 @@ Table of contents (click to go):
Functions:
1. :c:func:`glm_sign`
+#. :c:func:`glm_signf`
#. :c:func:`glm_rad`
#. :c:func:`glm_deg`
#. :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
~~~~~~~~~~~~~~~~~~~~~~~
.. c:function:: int glm_sign(int val)
- | returns sign of 32 bit integer as +1 or -1
+ | returns sign of 32 bit integer as +1, -1, 0
+
+ | **Important**: It returns 0 for zero input
Parameters:
| *[in]* **val** an integer
@@ -32,6 +38,18 @@ Functions documentation
Returns:
sign of given number
+.. c:function:: float glm_signf(float val)
+
+ | returns sign of 32 bit integer as +1.0, -1.0, 0.0
+
+ | **Important**: It returns 0.0f for zero input
+
+ Parameters:
+ | *[in]* **val** a float
+
+ Returns:
+ sign of given number
+
.. c:function:: float glm_rad(float deg)
| convert degree to radians
@@ -91,3 +109,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/box.h b/include/cglm/box.h
index d7184c5..7032339 100644
--- a/include/cglm/box.h
+++ b/include/cglm/box.h
@@ -153,4 +153,50 @@ glm_aabb_frustum(vec3 box[2], vec4 planes[6]) {
return true;
}
+/*!
+ * @brief invalidate AABB min and max values
+ *
+ * @param[in, out] box bounding box
+ */
+CGLM_INLINE
+void
+glm_aabb_invalidate(vec3 box[2]) {
+ glm_vec_broadcast(FLT_MAX, box[0]);
+ glm_vec_broadcast(-FLT_MAX, box[1]);
+}
+
+/*!
+ * @brief check if AABB is valid or not
+ *
+ * @param[in] box bounding box
+ */
+CGLM_INLINE
+bool
+glm_aabb_isvalid(vec3 box[2]) {
+ return glm_vec_max(box[0]) != FLT_MAX
+ && glm_vec_min(box[1]) != -FLT_MAX;
+}
+
+/*!
+ * @brief distance between of min and max
+ *
+ * @param[in] box bounding box
+ */
+CGLM_INLINE
+float
+glm_aabb_size(vec3 box[2]) {
+ return glm_vec_distance(box[0], box[1]);
+}
+
+/*!
+ * @brief radius of sphere which surrounds AABB
+ *
+ * @param[in] box bounding box
+ */
+CGLM_INLINE
+float
+glm_aabb_radius(vec3 box[2]) {
+ return glm_aabb_size(box) * 0.5f;
+}
+
#endif /* cglm_box_h */
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/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/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/include/cglm/io.h b/include/cglm/io.h
index 2ee8ee8..f38fad7 100644
--- a/include/cglm/io.h
+++ b/include/cglm/io.h
@@ -171,4 +171,33 @@ glm_versor_print(versor vec,
#undef m
}
+CGLM_INLINE
+void
+glm_aabb_print(vec3 bbox[2],
+ const char * __restrict tag,
+ FILE * __restrict ostream) {
+ int i, j;
+
+#define m 3
+
+ fprintf(ostream, "AABB (%s):\n", tag ? tag: "float");
+
+ for (i = 0; i < 2; i++) {
+ fprintf(ostream, "\t|");
+
+ for (j = 0; j < m; j++) {
+ fprintf(ostream, "%0.4f", bbox[i][j]);
+
+ if (j != m - 1)
+ fprintf(ostream, "\t");
+ }
+
+ fprintf(ostream, "|\n");
+ }
+
+ fprintf(ostream, "\n");
+
+#undef m
+}
+
#endif /* cglm_io_h */
diff --git a/include/cglm/util.h b/include/cglm/util.h
index 12db1a2..2a9ece7 100644
--- a/include/cglm/util.h
+++ b/include/cglm/util.h
@@ -21,7 +21,9 @@
#include "common.h"
/*!
- * @brief get sign of 32 bit integer as +1 or -1
+ * @brief get sign of 32 bit integer as +1, -1, 0
+ *
+ * Important: It returns 0 for zero input
*
* @param val integer value
*/
@@ -31,6 +33,19 @@ glm_sign(int val) {
return ((val >> 31) - (-val >> 31));
}
+/*!
+ * @brief get sign of 32 bit float as +1, -1, 0
+ *
+ * Important: It returns 0 for zero/NaN input
+ *
+ * @param val float value
+ */
+CGLM_INLINE
+float
+glm_signf(float val) {
+ return (val > 0.0f) - (val < 0.0f);
+}
+
/*!
* @brief convert degree to radians
*
@@ -115,4 +130,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/include/cglm/version.h b/include/cglm/version.h
index a025ccb..c27a26e 100644
--- a/include/cglm/version.h
+++ b/include/cglm/version.h
@@ -10,6 +10,6 @@
#define CGLM_VERSION_MAJOR 0
#define CGLM_VERSION_MINOR 3
-#define CGLM_VERSION_PATCH 5
+#define CGLM_VERSION_PATCH 6
#endif /* cglm_version_h */
diff --git a/makefile.am b/makefile.am
index ff951c8..a81bdd5 100644
--- a/makefile.am
+++ b/makefile.am
@@ -16,7 +16,7 @@ AM_CFLAGS = -Wall \
-pedantic
lib_LTLIBRARIES = libcglm.la
-libcglm_la_LDFLAGS = -no-undefined -version-info 0:3:5
+libcglm_la_LDFLAGS = -no-undefined -version-info 0:1:0
checkLDFLAGS = -L./.libs \
-L./test/lib/cmocka/build/src \
@@ -104,7 +104,9 @@ 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 \
+ 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/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_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 61fa7d5..dad20f9 100644
--- a/test/src/test_main.c
+++ b/test/src/test_main.c
@@ -18,6 +18,12 @@ main(int argc, const char * argv[]) {
/* project */
cmocka_unit_test(test_project)
+
+ /* vector */
+ 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 26eb91d..7234782 100644
--- a/test/src/test_tests.h
+++ b/test/src/test_tests.h
@@ -19,4 +19,10 @@ test_camera_decomp(void **state);
void
test_project(void **state);
+void
+test_clamp(void **state);
+
+void
+test_euler(void **state);
+
#endif /* test_tests_h */