From 58f004341706867d1c7af1ed1cbd8aea1cd7ac1f Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 6 Apr 2018 22:57:24 +0300 Subject: [PATCH 01/98] vector utils: isnan and isinf * a vector which has least one NaN or INF member, is assumed not valid vector. --- include/cglm/vec3-ext.h | 36 ++++++++++++++++++++++++++++++++++++ include/cglm/vec4-ext.h | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/include/cglm/vec3-ext.h b/include/cglm/vec3-ext.h index 99e778a..7890c33 100644 --- a/include/cglm/vec3-ext.h +++ b/include/cglm/vec3-ext.h @@ -160,4 +160,40 @@ glm_vec_min(vec3 v) { return min; } +/*! + * @brief check if all items are NaN (not a number) + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glm_vec_isnan(vec3 v) { + return !(isnan(v[0]) || isnan(v[1]) || isnan(v[2])); +} + +/*! + * @brief check if all items are INFINITY + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glm_vec_isinf(vec3 v) { + return !(isinf(v[0]) || isinf(v[1]) || isinf(v[2])); +} + +/*! + * @brief check if all items are valid number + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glm_vec_isvalid(vec3 v) { + return !glm_vec_isnan(v) && !glm_vec_isinf(v); +} + #endif /* cglm_vec3_ext_h */ diff --git a/include/cglm/vec4-ext.h b/include/cglm/vec4-ext.h index ca697af..c290477 100644 --- a/include/cglm/vec4-ext.h +++ b/include/cglm/vec4-ext.h @@ -174,5 +174,41 @@ glm_vec4_min(vec4 v) { return min; } +/*! + * @brief check if all items are NaN (not a number) + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glm_vec4_isnan(vec4 v) { + return !(isnan(v[0]) || isnan(v[1]) || isnan(v[2]) || isnan(v[3])); +} + +/*! + * @brief check if all items are INFINITY + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glm_vec4_isinf(vec4 v) { + return !(isinf(v[0]) || isinf(v[1]) || isinf(v[2]) || isinf(v[3])); +} + +/*! + * @brief check if all items are valid number + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glm_vec4_isvalid(vec4 v) { + return !glm_vec4_isnan(v) && !glm_vec4_isinf(v); +} + #endif /* cglm_vec4_ext_h */ From 11430559b45b773e8b3a7868bc88a053010740e8 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sat, 7 Apr 2018 08:28:37 +0300 Subject: [PATCH 02/98] fix isnan and isinf --- include/cglm/vec3-ext.h | 4 ++-- include/cglm/vec4-ext.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/cglm/vec3-ext.h b/include/cglm/vec3-ext.h index 7890c33..8a9226f 100644 --- a/include/cglm/vec3-ext.h +++ b/include/cglm/vec3-ext.h @@ -169,7 +169,7 @@ glm_vec_min(vec3 v) { CGLM_INLINE bool glm_vec_isnan(vec3 v) { - return !(isnan(v[0]) || isnan(v[1]) || isnan(v[2])); + return isnan(v[0]) || isnan(v[1]) || isnan(v[2]); } /*! @@ -181,7 +181,7 @@ glm_vec_isnan(vec3 v) { CGLM_INLINE bool glm_vec_isinf(vec3 v) { - return !(isinf(v[0]) || isinf(v[1]) || isinf(v[2])); + return isinf(v[0]) || isinf(v[1]) || isinf(v[2]); } /*! diff --git a/include/cglm/vec4-ext.h b/include/cglm/vec4-ext.h index c290477..2859588 100644 --- a/include/cglm/vec4-ext.h +++ b/include/cglm/vec4-ext.h @@ -183,7 +183,7 @@ glm_vec4_min(vec4 v) { CGLM_INLINE bool glm_vec4_isnan(vec4 v) { - return !(isnan(v[0]) || isnan(v[1]) || isnan(v[2]) || isnan(v[3])); + return isnan(v[0]) || isnan(v[1]) || isnan(v[2]) || isnan(v[3]); } /*! @@ -195,7 +195,7 @@ glm_vec4_isnan(vec4 v) { CGLM_INLINE bool glm_vec4_isinf(vec4 v) { - return !(isinf(v[0]) || isinf(v[1]) || isinf(v[2]) || isinf(v[3])); + return isinf(v[0]) || isinf(v[1]) || isinf(v[2]) || isinf(v[3]); } /*! From ae06c51746e3a00f89205a5a57ee286befc9eb4e Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sat, 7 Apr 2018 13:22:44 +0300 Subject: [PATCH 03/98] improve glm_mat4_mulN for non-DEBUG environment --- include/cglm/call/mat4.h | 2 +- include/cglm/mat4.h | 18 +++++++++--------- src/mat4.c | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/cglm/call/mat4.h b/include/cglm/call/mat4.h index 6ea81e4..5c8ff38 100644 --- a/include/cglm/call/mat4.h +++ b/include/cglm/call/mat4.h @@ -47,7 +47,7 @@ glmc_mat4_mul(mat4 m1, mat4 m2, mat4 dest); CGLM_EXPORT void -glmc_mat4_mulN(mat4 * __restrict matrices[], int len, mat4 dest); +glmc_mat4_mulN(mat4 * __restrict matrices[], uint32_t len, mat4 dest); CGLM_EXPORT void diff --git a/include/cglm/mat4.h b/include/cglm/mat4.h index 45f54b4..02fde18 100644 --- a/include/cglm/mat4.h +++ b/include/cglm/mat4.h @@ -58,7 +58,9 @@ # include "simd/neon/mat4.h" #endif -#include +#ifdef DEBUG +# include +#endif #define GLM_MAT4_IDENTITY_INIT {{1.0f, 0.0f, 0.0f, 0.0f}, \ {0.0f, 1.0f, 0.0f, 0.0f}, \ @@ -281,19 +283,17 @@ glm_mat4_mul(mat4 m1, mat4 m2, mat4 dest) { */ CGLM_INLINE void -glm_mat4_mulN(mat4 * __restrict matrices[], int len, mat4 dest) { - int i; +glm_mat4_mulN(mat4 * __restrict matrices[], uint32_t len, mat4 dest) { + uint32_t i; +#ifdef DEBUG assert(len > 1 && "there must be least 2 matrices to go!"); +#endif - glm_mat4_mul(*matrices[0], - *matrices[1], - dest); + glm_mat4_mul(*matrices[0], *matrices[1], dest); for (i = 2; i < len; i++) - glm_mat4_mul(dest, - *matrices[i], - dest); + glm_mat4_mul(dest, *matrices[i], dest); } /*! diff --git a/src/mat4.c b/src/mat4.c index 838b52d..0b1ccee 100644 --- a/src/mat4.c +++ b/src/mat4.c @@ -52,7 +52,7 @@ glmc_mat4_mul(mat4 m1, mat4 m2, mat4 dest) { CGLM_EXPORT void -glmc_mat4_mulN(mat4 * __restrict matrices[], int len, mat4 dest) { +glmc_mat4_mulN(mat4 * __restrict matrices[], uint32_t len, mat4 dest) { glm_mat4_mulN(matrices, len, dest); } From 9b8748acc459fb6d8252e0454c088aa3174c2017 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sat, 7 Apr 2018 13:27:40 +0300 Subject: [PATCH 04/98] quat: quaternion to mat3 --- include/cglm/call/quat.h | 4 ++++ include/cglm/quat.h | 36 ++++++++++++++++++++++++++++++++++++ src/quat.c | 6 ++++++ 3 files changed, 46 insertions(+) diff --git a/include/cglm/call/quat.h b/include/cglm/call/quat.h index 0dff506..e40bcdf 100644 --- a/include/cglm/call/quat.h +++ b/include/cglm/call/quat.h @@ -51,6 +51,10 @@ CGLM_EXPORT void glmc_quat_mat4(versor q, mat4 dest); +CGLM_EXPORT +void +glmc_quat_mat3(versor q, mat3 dest); + CGLM_EXPORT void glmc_quat_slerp(versor q, diff --git a/include/cglm/quat.h b/include/cglm/quat.h index 63236b1..1a2cfe3 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -216,6 +216,42 @@ glm_quat_mat4(versor q, mat4 dest) { dest[3][3] = 1.0f; } +/*! + * @brief convert quaternion to mat3 + * + * @param[in] q quaternion + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_quat_mat3(versor q, mat3 dest) { + float w, x, y, z; + float xx, yy, zz; + float xy, yz, xz; + float wx, wy, wz; + + w = q[0]; + x = q[1]; + y = q[2]; + z = q[3]; + + xx = 2.0f * x * x; xy = 2.0f * x * y; wx = 2.0f * w * x; + yy = 2.0f * y * y; yz = 2.0f * y * z; wy = 2.0f * w * y; + zz = 2.0f * z * z; xz = 2.0f * x * z; wz = 2.0f * w * z; + + dest[0][0] = 1.0f - yy - zz; + dest[1][1] = 1.0f - xx - zz; + dest[2][2] = 1.0f - xx - yy; + + dest[0][1] = xy + wz; + dest[1][2] = yz + wx; + dest[2][0] = xz + wy; + + dest[1][0] = xy - wz; + dest[2][1] = yz - wx; + dest[0][2] = xz - wy; +} + /*! * @brief interpolates between two quaternions * using spherical linear interpolation (SLERP) diff --git a/src/quat.c b/src/quat.c index b26d112..9955ce1 100644 --- a/src/quat.c +++ b/src/quat.c @@ -62,6 +62,12 @@ glmc_quat_mat4(versor q, mat4 dest) { glm_quat_mat4(q, dest); } +CGLM_EXPORT +void +glmc_quat_mat3(versor q, mat3 dest) { + glm_quat_mat3(q, dest); +} + CGLM_EXPORT void glmc_quat_slerp(versor q, From 619ecdc5a4652598fa9034a39eb770b23a425c1a Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sat, 7 Apr 2018 13:46:46 +0300 Subject: [PATCH 05/98] quat: improve normalize --- include/cglm/quat.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/cglm/quat.h b/include/cglm/quat.h index 1a2cfe3..a9a3649 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -133,11 +133,12 @@ void glm_quat_normalize(versor q) { float sum; - sum = q[0] * q[0] + q[1] * q[1] - + q[2] * q[2] + q[3] * q[3]; + sum = glm_vec4_norm2(q); - if (fabs(1.0f - sum) < 0.0001f) + if (sum <= 0.0f) { + glm_quat_identity(q); return; + } glm_vec4_scale(q, 1.0f / sqrtf(sum), q); } From f5140ea00504bc388f61965bc9f9676047cbae20 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sat, 7 Apr 2018 13:47:20 +0300 Subject: [PATCH 06/98] quat: mat4_mul_quat helper * the quaternion is used as right matrix --- include/cglm/mat4.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/cglm/mat4.h b/include/cglm/mat4.h index 02fde18..eddfe6b 100644 --- a/include/cglm/mat4.h +++ b/include/cglm/mat4.h @@ -45,6 +45,7 @@ #define cglm_mat_h #include "common.h" +#include "quat.h" #ifdef CGLM_SSE_FP # include "simd/sse2/mat4.h" @@ -318,6 +319,21 @@ glm_mat4_mulv(mat4 m, vec4 v, vec4 dest) { #endif } +/*! + * @brief multiply mat4 with quaternion and store in dest vector + * + * @param[in] m left matrix + * @param[in] q quaternion as right matrix + * @param[out] dest destination matrix + */ +CGLM_INLINE +void +glm_mat4_mulq(mat4 m, versor q, mat4 dest) { + mat4 rot; + glm_quat_mat4(q, rot); + glm_mat4_mul(m, rot, dest); +} + /*! * @brief multiply vector with mat4's mat3 part(rotation) * From 257c57d41ff56905b25b0fcc5449f1319843cb85 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sat, 7 Apr 2018 19:46:46 +0300 Subject: [PATCH 07/98] mat4 to quaternion --- .gitignore | 3 ++- include/cglm/call/mat4.h | 8 ++++++++ include/cglm/mat4.h | 30 ++++++++++++++++++++++++++++++ makefile.am | 4 ++-- src/mat4.c | 12 ++++++++++++ test/src/test_common.c | 38 +++++++++++++++++++++++++++++++++++++- test/src/test_common.h | 12 ++++++++++++ test/src/test_main.c | 5 ++++- test/src/test_quat.c | 22 ++++++++++++++++++++++ test/src/test_tests.h | 3 +++ 10 files changed, 132 insertions(+), 5 deletions(-) create mode 100644 test/src/test_quat.c diff --git a/.gitignore b/.gitignore index 180c5d9..37f68c8 100644 --- a/.gitignore +++ b/.gitignore @@ -59,4 +59,5 @@ cglm_test_ios/* cglm_test_iosTests/* docs/build/* win/cglm_test_* -* copy.* +* copy.* +*.o diff --git a/include/cglm/call/mat4.h b/include/cglm/call/mat4.h index 5c8ff38..35b9f66 100644 --- a/include/cglm/call/mat4.h +++ b/include/cglm/call/mat4.h @@ -53,6 +53,14 @@ CGLM_EXPORT void glmc_mat4_mulv(mat4 m, vec4 v, vec4 dest); +CGLM_EXPORT +void +glmc_mat4_mulq(mat4 m, versor q, mat4 dest); + +CGLM_EXPORT +void +glmc_mat4_quat(mat4 m, versor dest); + CGLM_EXPORT void glmc_mat4_transpose_to(mat4 m, mat4 dest); diff --git a/include/cglm/mat4.h b/include/cglm/mat4.h index eddfe6b..ec7ac39 100644 --- a/include/cglm/mat4.h +++ b/include/cglm/mat4.h @@ -334,6 +334,36 @@ glm_mat4_mulq(mat4 m, versor q, mat4 dest) { glm_mat4_mul(m, rot, dest); } +/*! + * @brief convert mat4's rotation part to quaternion + * + * @param[in] m left matrix + * @param[out] dest destination quaternion + */ +CGLM_INLINE +void +glm_mat4_quat(mat4 m, versor dest) { + versor q; + float m00, m10, m20, + m01, m11, m21, + m02, m12, m22; + + m00 = m[0][0]; m10 = m[1][0]; m20 = m[2][0]; + m01 = m[0][1]; m11 = m[1][1]; m21 = m[2][1]; + m02 = m[0][2]; m12 = m[1][2]; m22 = m[2][2]; + + q[0] = sqrtf(glm_max(0.0f, 1.0f + m00 + m11 + m22)) * 0.5f; /* w */ + q[1] = sqrtf(glm_max(0.0f, 1.0f + m00 - m11 - m22)) * 0.5f; /* x */ + q[2] = sqrtf(glm_max(0.0f, 1.0f - m00 + m11 - m22)) * 0.5f; /* y */ + q[3] = sqrtf(glm_max(0.0f, 1.0f - m00 - m11 + m22)) * 0.5f; /* z */ + + q[1] *= glm_signf(m12 - m21); + q[2] *= glm_signf(m20 - m02); + q[3] *= glm_signf(m01 - m10); + + glm_vec4_copy(q, dest); +} + /*! * @brief multiply vector with mat4's mat3 part(rotation) * diff --git a/makefile.am b/makefile.am index 217fff3..436973c 100644 --- a/makefile.am +++ b/makefile.am @@ -108,7 +108,7 @@ test_tests_SOURCES=\ test/src/test_cam.c \ test/src/test_project.c \ test/src/test_clamp.c \ - test/src/test_euler.c - + test/src/test_euler.c \ + test/src/test_quat.c all-local: sh ./post-build.sh diff --git a/src/mat4.c b/src/mat4.c index 0b1ccee..8b2a2d0 100644 --- a/src/mat4.c +++ b/src/mat4.c @@ -62,6 +62,18 @@ glmc_mat4_mulv(mat4 m, vec4 v, vec4 dest) { glm_mat4_mulv(m, v, dest); } +CGLM_EXPORT +void +glmc_mat4_mulq(mat4 m, versor q, mat4 dest) { + glm_mat4_mulq(m, q, dest); +} + +CGLM_EXPORT +void +glmc_mat4_quat(mat4 m, versor dest) { + glm_mat4_quat(m, dest); +} + CGLM_EXPORT void glmc_mat4_transpose_to(mat4 m, mat4 dest) { diff --git a/test/src/test_common.c b/test/src/test_common.c index 23f2b50..c38c474 100644 --- a/test/src/test_common.c +++ b/test/src/test_common.c @@ -27,6 +27,33 @@ test_rand_mat4(mat4 dest) { /* glm_scale(dest, (vec3){drand48(), drand48(), drand48()}); */ } +void +test_rand_vec3(vec3 dest) { + srand((unsigned int)time(NULL)); + + dest[0] = drand48(); + dest[1] = drand48(); + dest[2] = drand48(); +} + +float +test_rand_angle(void) { + srand((unsigned int)time(NULL)); + return drand48(); +} + +void +test_rand_quat(versor q) { + srand((unsigned int)time(NULL)); + + q[0] = drand48(); + q[1] = drand48(); + q[2] = drand48(); + q[3] = drand48(); + + glm_quat_normalize(q); +} + void test_assert_mat4_eq(mat4 m1, mat4 m2) { int i, j, k; @@ -53,7 +80,16 @@ 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[0] - v2[0]) <= 0.0000009); /* rounding errors */ assert_true(fabsf(v1[1] - v2[1]) <= 0.0000009); assert_true(fabsf(v1[2] - v2[2]) <= 0.0000009); } + +void +test_assert_quat_eq(versor v1, versor v2) { + assert_true(fabsf(v1[0] - v2[0]) <= 0.0009); /* rounding errors */ + assert_true(fabsf(v1[1] - v2[1]) <= 0.0009); + assert_true(fabsf(v1[2] - v2[2]) <= 0.0009); + assert_true(fabsf(v1[3] - v2[3]) <= 0.0009); +} + diff --git a/test/src/test_common.h b/test/src/test_common.h index aeea4d6..f692483 100644 --- a/test/src/test_common.h +++ b/test/src/test_common.h @@ -34,4 +34,16 @@ test_assert_mat4_eq2(mat4 m1, mat4 m2, float eps); void test_assert_vec3_eq(vec3 v1, vec3 v2); +void +test_assert_quat_eq(versor v1, versor v2); + +void +test_rand_vec3(vec3 dest); + +float +test_rand_angle(void); + +void +test_rand_quat(versor q); + #endif /* test_common_h */ diff --git a/test/src/test_main.c b/test/src/test_main.c index 5c1a647..384250f 100644 --- a/test/src/test_main.c +++ b/test/src/test_main.c @@ -23,7 +23,10 @@ main(int argc, const char * argv[]) { cmocka_unit_test(test_clamp), /* euler */ - cmocka_unit_test(test_euler) + cmocka_unit_test(test_euler), + + /* quaternion */ + cmocka_unit_test(test_quat) }; return cmocka_run_group_tests(tests, NULL, NULL); diff --git a/test/src/test_quat.c b/test/src/test_quat.c new file mode 100644 index 0000000..1a328de --- /dev/null +++ b/test/src/test_quat.c @@ -0,0 +1,22 @@ +/* + * 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_quat(void **state) { + mat4 rot; + versor inQuat, outQuat; + int i; + + for (i = 0; i < 10000; i++) { + test_rand_quat(inQuat); + glmc_quat_mat4(inQuat, rot); + glm_mat4_quat(rot, outQuat); + test_assert_quat_eq(inQuat, outQuat); + } +} diff --git a/test/src/test_tests.h b/test/src/test_tests.h index 7234782..398caa3 100644 --- a/test/src/test_tests.h +++ b/test/src/test_tests.h @@ -25,4 +25,7 @@ test_clamp(void **state); void test_euler(void **state); +void +test_quat(void **state); + #endif /* test_tests_h */ From 12c53074473f50a2a7fc4eea660a661d911fda6c Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sat, 7 Apr 2018 21:53:22 +0300 Subject: [PATCH 08/98] vec3 and vec4 sign helper --- include/cglm/vec3-ext.h | 16 ++++++++++++++++ include/cglm/vec4-ext.h | 30 +++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/include/cglm/vec3-ext.h b/include/cglm/vec3-ext.h index 8a9226f..e119900 100644 --- a/include/cglm/vec3-ext.h +++ b/include/cglm/vec3-ext.h @@ -26,6 +26,7 @@ #define cglm_vec3_ext_h #include "common.h" +#include "util.h" #include #include #include @@ -196,4 +197,19 @@ glm_vec_isvalid(vec3 v) { return !glm_vec_isnan(v) && !glm_vec_isinf(v); } +/*! + * @brief get sign of 32 bit float as +1, -1, 0 + * + * Important: It returns 0 for zero/NaN input + * + * @param v vector + */ +CGLM_INLINE +void +glm_vec_sign(vec3 v, vec3 dest) { + dest[0] = glm_signf(v[0]); + dest[1] = glm_signf(v[1]); + dest[2] = glm_signf(v[2]); +} + #endif /* cglm_vec3_ext_h */ diff --git a/include/cglm/vec4-ext.h b/include/cglm/vec4-ext.h index 2859588..f6cbe04 100644 --- a/include/cglm/vec4-ext.h +++ b/include/cglm/vec4-ext.h @@ -210,5 +210,33 @@ glm_vec4_isvalid(vec4 v) { return !glm_vec4_isnan(v) && !glm_vec4_isinf(v); } -#endif /* cglm_vec4_ext_h */ +/*! + * @brief get sign of 32 bit float as +1, -1, 0 + * + * Important: It returns 0 for zero/NaN input + * + * @param v vector + */ +CGLM_INLINE +void +glm_vec4_sign(vec4 v, vec4 dest) { +#if defined( __SSE2__ ) || defined( __SSE2__ ) + __m128 x0, x1, x2, x3, x4; + x0 = _mm_load_ps(v); + x1 = _mm_set_ps(0.0f, 0.0f, 1.0f, -1.0f); + x2 = _mm_shuffle1_ps1(x1, 2); + + x3 = _mm_and_ps(_mm_cmpgt_ps(x0, x2), _mm_shuffle1_ps1(x1, 1)); + x4 = _mm_and_ps(_mm_cmplt_ps(x0, x2), _mm_shuffle1_ps1(x1, 0)); + + _mm_store_ps(dest, _mm_or_ps(x3, x4)); +#else + dest[0] = glm_signf(v[0]); + dest[1] = glm_signf(v[1]); + dest[2] = glm_signf(v[2]); + dest[3] = glm_signf(v[3]); +#endif +} + +#endif /* cglm_vec4_ext_h */ From b27603c26839ba0e40ce657c38e6007a7087653f Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sun, 8 Apr 2018 00:09:40 +0300 Subject: [PATCH 09/98] normalize quaternion before converting to matrix * because it must be unit quaternion and didn't specified this in docs. * we must provide alternative func for unit quat --- include/cglm/quat.h | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/include/cglm/quat.h b/include/cglm/quat.h index a9a3649..e9e986e 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -182,15 +182,17 @@ glm_quat_mulv(versor q1, versor q2, versor dest) { CGLM_INLINE void glm_quat_mat4(versor q, mat4 dest) { - float w, x, y, z; - float xx, yy, zz; - float xy, yz, xz; - float wx, wy, wz; + float w, x, y, z, + xx, yy, zz, + xy, yz, xz, + wx, wy, wz, norm; - w = q[0]; - x = q[1]; - y = q[2]; - z = q[3]; + norm = 1.0f / glm_quat_norm(q); + + w = q[0] * norm; + x = q[1] * norm; + y = q[2] * norm; + z = q[3] * norm; xx = 2.0f * x * x; xy = 2.0f * x * y; wx = 2.0f * w * x; yy = 2.0f * y * y; yz = 2.0f * y * z; wy = 2.0f * w * y; @@ -226,15 +228,17 @@ glm_quat_mat4(versor q, mat4 dest) { CGLM_INLINE void glm_quat_mat3(versor q, mat3 dest) { - float w, x, y, z; - float xx, yy, zz; - float xy, yz, xz; - float wx, wy, wz; + float w, x, y, z, + xx, yy, zz, + xy, yz, xz, + wx, wy, wz, norm; - w = q[0]; - x = q[1]; - y = q[2]; - z = q[3]; + norm = 1.0f / glm_quat_norm(q); + + w = q[0] * norm; + x = q[1] * norm; + y = q[2] * norm; + z = q[3] * norm; xx = 2.0f * x * x; xy = 2.0f * x * y; wx = 2.0f * w * x; yy = 2.0f * y * y; yz = 2.0f * y * z; wy = 2.0f * w * y; From 81bda7439dd89eef31cf0d65e4ac90c70562e9a5 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sun, 8 Apr 2018 12:30:15 +0300 Subject: [PATCH 10/98] vector square root --- include/cglm/vec3-ext.h | 14 ++++++++++++++ include/cglm/vec4-ext.h | 19 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/include/cglm/vec3-ext.h b/include/cglm/vec3-ext.h index e119900..afc853e 100644 --- a/include/cglm/vec3-ext.h +++ b/include/cglm/vec3-ext.h @@ -212,4 +212,18 @@ glm_vec_sign(vec3 v, vec3 dest) { dest[2] = glm_signf(v[2]); } +/*! + * @brief square root of each vector item + * + * @param[in] v vector + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec_sqrt(vec4 v, vec4 dest) { + dest[0] = sqrtf(v[0]); + dest[1] = sqrtf(v[1]); + dest[2] = sqrtf(v[2]); +} + #endif /* cglm_vec3_ext_h */ diff --git a/include/cglm/vec4-ext.h b/include/cglm/vec4-ext.h index f6cbe04..77ba1fa 100644 --- a/include/cglm/vec4-ext.h +++ b/include/cglm/vec4-ext.h @@ -239,4 +239,23 @@ glm_vec4_sign(vec4 v, vec4 dest) { #endif } +/*! + * @brief square root of each vector item + * + * @param[in] v vector + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec4_sqrt(vec4 v, vec4 dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(dest, _mm_sqrt_ps(_mm_load_ps(v))); +#else + dest[0] = sqrtf(v[0]); + dest[1] = sqrtf(v[1]); + dest[2] = sqrtf(v[2]); + dest[3] = sqrtf(v[3]); +#endif +} + #endif /* cglm_vec4_ext_h */ From 932f638d5a6b3bcb0897b059b74ddace2a204308 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sun, 8 Apr 2018 12:31:32 +0300 Subject: [PATCH 11/98] optimize mat4 to quaternion * add SSE2 version and optimize scalar version --- include/cglm/mat4.h | 34 +++++++++++++++-------- include/cglm/simd/sse2/mat4.h | 51 +++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 11 deletions(-) diff --git a/include/cglm/mat4.h b/include/cglm/mat4.h index ec7ac39..782a24b 100644 --- a/include/cglm/mat4.h +++ b/include/cglm/mat4.h @@ -343,25 +343,38 @@ glm_mat4_mulq(mat4 m, versor q, mat4 dest) { CGLM_INLINE void glm_mat4_quat(mat4 m, versor dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + glm_mat4_quat_sse2(m, dest); +#else + vec4 vsgn, vzero = GLM_VEC4_ZERO_INIT; versor q; float m00, m10, m20, m01, m11, m21, m02, m12, m22; - m00 = m[0][0]; m10 = m[1][0]; m20 = m[2][0]; - m01 = m[0][1]; m11 = m[1][1]; m21 = m[2][1]; - m02 = m[0][2]; m12 = m[1][2]; m22 = m[2][2]; + m00 = m[0][0]; m01 = m[0][1]; m02 = m[0][2]; + m10 = m[1][0]; m11 = m[1][1]; m12 = m[1][2]; + m20 = m[2][0]; m21 = m[2][1]; m22 = m[2][2]; - q[0] = sqrtf(glm_max(0.0f, 1.0f + m00 + m11 + m22)) * 0.5f; /* w */ - q[1] = sqrtf(glm_max(0.0f, 1.0f + m00 - m11 - m22)) * 0.5f; /* x */ - q[2] = sqrtf(glm_max(0.0f, 1.0f - m00 + m11 - m22)) * 0.5f; /* y */ - q[3] = sqrtf(glm_max(0.0f, 1.0f - m00 - m11 + m22)) * 0.5f; /* z */ + q[0] = 1.0f + m00 + m11 + m22; /* w */ + q[1] = 1.0f + m00 - m11 - m22; /* x */ + q[2] = 1.0f - m00 + m11 - m22; /* y */ + q[3] = 1.0f - m00 - m11 + m22; /* z */ - q[1] *= glm_signf(m12 - m21); - q[2] *= glm_signf(m20 - m02); - q[3] *= glm_signf(m01 - m10); + glm_vec4_maxv(q, vzero, q); + glm_vec4_sqrt(q, q); + glm_vec4_scale(q, 0.5f, q); + + vsgn[0] = 1.0f; + vsgn[1] = m12 - m21; + vsgn[2] = m20 - m02; + vsgn[3] = m01 - m10; + + glm_vec4_sign(vsgn, vsgn); + glm_vec4_mulv(q, vsgn, q); glm_vec4_copy(q, dest); +#endif } /*! @@ -614,5 +627,4 @@ glm_mat4_swap_row(mat4 mat, int row1, int row2) { mat[3][row2] = tmp[3]; } -#else #endif /* cglm_mat_h */ diff --git a/include/cglm/simd/sse2/mat4.h b/include/cglm/simd/sse2/mat4.h index 77874a8..0476176 100644 --- a/include/cglm/simd/sse2/mat4.h +++ b/include/cglm/simd/sse2/mat4.h @@ -102,6 +102,57 @@ glm_mat4_mulv_sse2(mat4 m, vec4 v, vec4 dest) { _mm_store_ps(dest, _mm_add_ps(x1, x2)); } +CGLM_INLINE +void +glm_mat4_quat_sse2(mat4 m, versor dest) { + __m128 c0, c1, c2, x0, x1, x2, x3, m00, m11, m22, r; + __m128 zero, one, half, ngone; + + c0 = _mm_load_ps(m[0]); + c1 = _mm_load_ps(m[1]); + c2 = _mm_load_ps(m[2]); + + m00 = _mm_xor_ps(_mm_shuffle1_ps1(c0, 0), _mm_set_ps(-0.f, -0.f, 0.f, 0.f)); + m11 = _mm_xor_ps(_mm_shuffle1_ps1(c1, 1), _mm_set_ps(-0.f, 0.f, -0.f, 0.f)); + m22 = _mm_xor_ps(_mm_shuffle1_ps1(c2, 2), _mm_set_ps( 0.f, -0.f, -0.f, 0.f)); + + x0 = _mm_set_ps(-1.0f, 0.0f, 0.5, 1.0f); + one = _mm_shuffle1_ps1(x0, 0); + half = _mm_shuffle1_ps1(x0, 1); + zero = _mm_shuffle1_ps1(x0, 2); + ngone = _mm_shuffle1_ps1(x0, 3); + + /* + q[0] = sqrtf(glm_max(0.0f, 1.0f + m00 + m11 + m22)) * 0.5f; + q[1] = sqrtf(glm_max(0.0f, 1.0f + m00 - m11 - m22)) * 0.5f; + q[2] = sqrtf(glm_max(0.0f, 1.0f - m00 + m11 - m22)) * 0.5f; + q[3] = sqrtf(glm_max(0.0f, 1.0f - m00 - m11 + m22)) * 0.5f; + */ + x0 = _mm_add_ps(one, _mm_add_ps(_mm_add_ps(m00, m11), m22)); + r = _mm_mul_ps(_mm_sqrt_ps(_mm_max_ps(zero, x0)), half); + + /* + q[1] *= glm_signf(m12 - m21); + q[2] *= glm_signf(m20 - m02); + q[3] *= glm_signf(m01 - m10); + */ + x1 = _mm_shuffle_ps(c1, c2, _MM_SHUFFLE(0, 0, 2, 2)); /* m20 m20 m12 m12 */ + x1 = _mm_shuffle_ps(x1, c0, _MM_SHUFFLE(1, 1, 2, 0)); /* m01 m01 m20 m12 */ + + x2 = _mm_shuffle_ps(c2, c0, _MM_SHUFFLE(2, 2, 1, 1)); /* m02 m02 m21 m21 */ + x2 = _mm_shuffle_ps(x2, c1, _MM_SHUFFLE(0, 0, 2, 0)); /* m10 m10 m02 m21 */ + + x1 = _mm_sub_ps(x1, x2); + x2 = _mm_or_ps(_mm_and_ps(_mm_cmpgt_ps(x1, zero), one), + _mm_and_ps(_mm_cmplt_ps(x1, zero), ngone)); + x2 = _mm_shuffle1_ps(x2, 2, 1, 0, 0); + + x3 = _mm_shuffle_ps(one, x2, _MM_SHUFFLE(0, 0, 0, 0)); /* q1 q1 1 1 */ + x3 = _mm_shuffle_ps(x3, x2, _MM_SHUFFLE(3, 2, 2, 0)); /* q3 q2 q1 1 */ + + _mm_store_ps(dest, _mm_mul_ps(r, x3)); +} + CGLM_INLINE float glm_mat4_det_sse2(mat4 mat) { From e4e0fa623c78e93bb9b141d9f890308eb056aa60 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sun, 8 Apr 2018 18:27:54 +0300 Subject: [PATCH 12/98] sse2 version of vec4 dot product * use this for normalizing vector --- include/cglm/vec4.h | 9 ++++++++- makefile.am | 4 +++- test/src/test_common.c | 10 ++++++++++ test/src/test_common.h | 3 +++ test/src/test_main.c | 5 ++++- test/src/test_tests.h | 3 +++ test/src/test_vec4.c | 30 ++++++++++++++++++++++++++++++ 7 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 test/src/test_vec4.c diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index 95bab09..97df6d4 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -122,7 +122,14 @@ glm_vec4_copy(vec4 v, vec4 dest) { CGLM_INLINE float glm_vec4_dot(vec4 a, vec4 b) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + __m128 x0; + x0 = _mm_mul_ps(_mm_load_ps(a), _mm_load_ps(b)); + x0 = _mm_add_ps(x0, _mm_shuffle1_ps(x0, 1, 0, 3, 2)); + return _mm_cvtss_f32(_mm_add_ss(x0, _mm_shuffle1_ps(x0, 0, 1, 0, 1))); +#else return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; +#endif } /*! @@ -139,7 +146,7 @@ glm_vec4_dot(vec4 a, vec4 b) { CGLM_INLINE float glm_vec4_norm2(vec4 v) { - return v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]; + return glm_vec_dot(v, v); } /*! diff --git a/makefile.am b/makefile.am index 436973c..2922373 100644 --- a/makefile.am +++ b/makefile.am @@ -109,6 +109,8 @@ test_tests_SOURCES=\ test/src/test_project.c \ test/src/test_clamp.c \ test/src/test_euler.c \ - test/src/test_quat.c + test/src/test_quat.c \ + test/src/test_vec4.c + all-local: sh ./post-build.sh diff --git a/test/src/test_common.c b/test/src/test_common.c index c38c474..c13ac0e 100644 --- a/test/src/test_common.c +++ b/test/src/test_common.c @@ -36,6 +36,16 @@ test_rand_vec3(vec3 dest) { dest[2] = drand48(); } +void +test_rand_vec4(vec4 dest) { + srand((unsigned int)time(NULL)); + + dest[0] = drand48(); + dest[1] = drand48(); + dest[2] = drand48(); + dest[3] = drand48(); +} + float test_rand_angle(void) { srand((unsigned int)time(NULL)); diff --git a/test/src/test_common.h b/test/src/test_common.h index f692483..477e59d 100644 --- a/test/src/test_common.h +++ b/test/src/test_common.h @@ -40,6 +40,9 @@ test_assert_quat_eq(versor v1, versor v2); void test_rand_vec3(vec3 dest); +void +test_rand_vec4(vec4 dest) ; + float test_rand_angle(void); diff --git a/test/src/test_main.c b/test/src/test_main.c index 384250f..7995a5a 100644 --- a/test/src/test_main.c +++ b/test/src/test_main.c @@ -26,7 +26,10 @@ main(int argc, const char * argv[]) { cmocka_unit_test(test_euler), /* quaternion */ - cmocka_unit_test(test_quat) + cmocka_unit_test(test_quat), + + /* vec4 */ + cmocka_unit_test(test_vec4) }; return cmocka_run_group_tests(tests, NULL, NULL); diff --git a/test/src/test_tests.h b/test/src/test_tests.h index 398caa3..1dfbb5f 100644 --- a/test/src/test_tests.h +++ b/test/src/test_tests.h @@ -28,4 +28,7 @@ test_euler(void **state); void test_quat(void **state); +void +test_vec4(void **state); + #endif /* test_tests_h */ diff --git a/test/src/test_vec4.c b/test/src/test_vec4.c new file mode 100644 index 0000000..a45a700 --- /dev/null +++ b/test/src/test_vec4.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" + +CGLM_INLINE +float +test_vec4_dot(vec4 a, vec4 b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; +} + +void +test_vec4(void **state) { + vec4 v; + int i; + float d1, d2; + + /* test SSE/SIMD dot product */ + for (i = 0; i < 100; i++) { + test_rand_vec4(v); + d1 = glm_vec4_dot(v, v); + d2 = test_vec4_dot(v, v); + + assert_true(fabsf(d1 - d2) <= 0.000009); + } +} From 381b2fdcc0afdde2d8fe9f7abab62e1e7581000e Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Mon, 9 Apr 2018 00:01:56 +0300 Subject: [PATCH 13/98] fix vec4_norm2, use dot for vec3_norm2 --- include/cglm/vec3.h | 2 +- include/cglm/vec4.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index e2108f3..873c172 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -147,7 +147,7 @@ glm_vec_cross(vec3 a, vec3 b, vec3 d) { CGLM_INLINE float glm_vec_norm2(vec3 v) { - return v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; + return glm_vec_dot(v, v); } /*! diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index 97df6d4..adf5fb9 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -146,7 +146,7 @@ glm_vec4_dot(vec4 a, vec4 b) { CGLM_INLINE float glm_vec4_norm2(vec4 v) { - return glm_vec_dot(v, v); + return glm_vec4_dot(v, v); } /*! From f0daaca58b57bb290ac52de927d626adef967a83 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Mon, 9 Apr 2018 00:46:00 +0300 Subject: [PATCH 14/98] improve matrix to quaternion --- include/cglm/mat3.h | 48 +++++++++++++++++++++++++++++ include/cglm/mat4.h | 58 +++++++++++++++++++---------------- include/cglm/simd/sse2/mat4.h | 51 ------------------------------ test/src/test_common.c | 6 +--- test/src/test_quat.c | 10 +++--- 5 files changed, 86 insertions(+), 87 deletions(-) diff --git a/include/cglm/mat3.h b/include/cglm/mat3.h index 61c4f3d..e7f8bcc 100644 --- a/include/cglm/mat3.h +++ b/include/cglm/mat3.h @@ -186,6 +186,54 @@ glm_mat3_mulv(mat3 m, vec3 v, vec3 dest) { dest[2] = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2]; } + +/*! + * @brief convert mat4's rotation part to quaternion + * + * @param[in] m left matrix + * @param[out] dest destination quaternion + */ +CGLM_INLINE +void +glm_mat3_quat(mat3 m, versor dest) { + float trace, r, rinv; + + trace = m[0][0] + m[1][1] + m[2][2]; + if (trace >= 0.0f) { + r = 2.0f * sqrtf(1 + trace); + rinv = 1.0f / r; + + dest[1] = rinv * (m[1][2] - m[2][1]); + dest[2] = rinv * (m[2][0] - m[0][2]); + dest[3] = rinv * (m[0][1] - m[1][0]); + dest[0] = r * 0.25f; + } else if (m[0][0] >= m[1][1] && m[0][0] >= m[2][2]) { + r = 2.0f * sqrtf(1 - m[1][1] - m[2][2] + m[0][0]); + rinv = 1.0f / r; + + dest[1] = r * 0.25f; + dest[2] = rinv * (m[0][1] + m[1][0]); + dest[3] = rinv * (m[0][2] + m[2][0]); + dest[0] = rinv * (m[1][2] - m[2][1]); + } else if (m[1][1] >= m[2][2]) { + r = 2.0f * sqrtf(1 - m[0][0] - m[2][2] + m[1][1]); + rinv = 1.0f / r; + + dest[1] = rinv * (m[0][1] + m[1][0]); + dest[2] = r * 0.25f; + dest[3] = rinv * (m[1][2] + m[2][1]); + dest[0] = rinv * (m[2][0] - m[0][2]); + } else { + r = 2.0f * sqrtf(1 - m[0][0] - m[1][1] + m[2][2]); + rinv = 1.0f / r; + + dest[1] = rinv * (m[0][2] + m[2][0]); + dest[2] = rinv * (m[1][2] + m[2][1]); + dest[3] = r * 0.25f; + dest[0] = rinv * (m[0][1] - m[1][0]); + } +} + /*! * @brief scale (multiply with scalar) matrix * diff --git a/include/cglm/mat4.h b/include/cglm/mat4.h index 782a24b..05aac60 100644 --- a/include/cglm/mat4.h +++ b/include/cglm/mat4.h @@ -343,38 +343,42 @@ glm_mat4_mulq(mat4 m, versor q, mat4 dest) { CGLM_INLINE void glm_mat4_quat(mat4 m, versor dest) { -#if defined( __SSE__ ) || defined( __SSE2__ ) - glm_mat4_quat_sse2(m, dest); -#else - vec4 vsgn, vzero = GLM_VEC4_ZERO_INIT; - versor q; - float m00, m10, m20, - m01, m11, m21, - m02, m12, m22; + float trace, r, rinv; - m00 = m[0][0]; m01 = m[0][1]; m02 = m[0][2]; - m10 = m[1][0]; m11 = m[1][1]; m12 = m[1][2]; - m20 = m[2][0]; m21 = m[2][1]; m22 = m[2][2]; + trace = m[0][0] + m[1][1] + m[2][2]; + if (trace >= 0.0f) { + r = 2.0f * sqrtf(1 + trace); + rinv = 1.0f / r; - q[0] = 1.0f + m00 + m11 + m22; /* w */ - q[1] = 1.0f + m00 - m11 - m22; /* x */ - q[2] = 1.0f - m00 + m11 - m22; /* y */ - q[3] = 1.0f - m00 - m11 + m22; /* z */ + dest[1] = rinv * (m[1][2] - m[2][1]); + dest[2] = rinv * (m[2][0] - m[0][2]); + dest[3] = rinv * (m[0][1] - m[1][0]); + dest[0] = r * 0.25f; + } else if (m[0][0] >= m[1][1] && m[0][0] >= m[2][2]) { + r = 2.0f * sqrtf(1 - m[1][1] - m[2][2] + m[0][0]); + rinv = 1.0f / r; - glm_vec4_maxv(q, vzero, q); - glm_vec4_sqrt(q, q); - glm_vec4_scale(q, 0.5f, q); + dest[1] = r * 0.25f; + dest[2] = rinv * (m[0][1] + m[1][0]); + dest[3] = rinv * (m[0][2] + m[2][0]); + dest[0] = rinv * (m[1][2] - m[2][1]); + } else if (m[1][1] >= m[2][2]) { + r = 2.0f * sqrtf(1 - m[0][0] - m[2][2] + m[1][1]); + rinv = 1.0f / r; - vsgn[0] = 1.0f; - vsgn[1] = m12 - m21; - vsgn[2] = m20 - m02; - vsgn[3] = m01 - m10; + dest[1] = rinv * (m[0][1] + m[1][0]); + dest[2] = r * 0.25f; + dest[3] = rinv * (m[1][2] + m[2][1]); + dest[0] = rinv * (m[2][0] - m[0][2]); + } else { + r = 2.0f * sqrtf(1 - m[0][0] - m[1][1] + m[2][2]); + rinv = 1.0f / r; - glm_vec4_sign(vsgn, vsgn); - glm_vec4_mulv(q, vsgn, q); - - glm_vec4_copy(q, dest); -#endif + dest[1] = rinv * (m[0][2] + m[2][0]); + dest[2] = rinv * (m[1][2] + m[2][1]); + dest[3] = r * 0.25f; + dest[0] = rinv * (m[0][1] - m[1][0]); + } } /*! diff --git a/include/cglm/simd/sse2/mat4.h b/include/cglm/simd/sse2/mat4.h index 0476176..77874a8 100644 --- a/include/cglm/simd/sse2/mat4.h +++ b/include/cglm/simd/sse2/mat4.h @@ -102,57 +102,6 @@ glm_mat4_mulv_sse2(mat4 m, vec4 v, vec4 dest) { _mm_store_ps(dest, _mm_add_ps(x1, x2)); } -CGLM_INLINE -void -glm_mat4_quat_sse2(mat4 m, versor dest) { - __m128 c0, c1, c2, x0, x1, x2, x3, m00, m11, m22, r; - __m128 zero, one, half, ngone; - - c0 = _mm_load_ps(m[0]); - c1 = _mm_load_ps(m[1]); - c2 = _mm_load_ps(m[2]); - - m00 = _mm_xor_ps(_mm_shuffle1_ps1(c0, 0), _mm_set_ps(-0.f, -0.f, 0.f, 0.f)); - m11 = _mm_xor_ps(_mm_shuffle1_ps1(c1, 1), _mm_set_ps(-0.f, 0.f, -0.f, 0.f)); - m22 = _mm_xor_ps(_mm_shuffle1_ps1(c2, 2), _mm_set_ps( 0.f, -0.f, -0.f, 0.f)); - - x0 = _mm_set_ps(-1.0f, 0.0f, 0.5, 1.0f); - one = _mm_shuffle1_ps1(x0, 0); - half = _mm_shuffle1_ps1(x0, 1); - zero = _mm_shuffle1_ps1(x0, 2); - ngone = _mm_shuffle1_ps1(x0, 3); - - /* - q[0] = sqrtf(glm_max(0.0f, 1.0f + m00 + m11 + m22)) * 0.5f; - q[1] = sqrtf(glm_max(0.0f, 1.0f + m00 - m11 - m22)) * 0.5f; - q[2] = sqrtf(glm_max(0.0f, 1.0f - m00 + m11 - m22)) * 0.5f; - q[3] = sqrtf(glm_max(0.0f, 1.0f - m00 - m11 + m22)) * 0.5f; - */ - x0 = _mm_add_ps(one, _mm_add_ps(_mm_add_ps(m00, m11), m22)); - r = _mm_mul_ps(_mm_sqrt_ps(_mm_max_ps(zero, x0)), half); - - /* - q[1] *= glm_signf(m12 - m21); - q[2] *= glm_signf(m20 - m02); - q[3] *= glm_signf(m01 - m10); - */ - x1 = _mm_shuffle_ps(c1, c2, _MM_SHUFFLE(0, 0, 2, 2)); /* m20 m20 m12 m12 */ - x1 = _mm_shuffle_ps(x1, c0, _MM_SHUFFLE(1, 1, 2, 0)); /* m01 m01 m20 m12 */ - - x2 = _mm_shuffle_ps(c2, c0, _MM_SHUFFLE(2, 2, 1, 1)); /* m02 m02 m21 m21 */ - x2 = _mm_shuffle_ps(x2, c1, _MM_SHUFFLE(0, 0, 2, 0)); /* m10 m10 m02 m21 */ - - x1 = _mm_sub_ps(x1, x2); - x2 = _mm_or_ps(_mm_and_ps(_mm_cmpgt_ps(x1, zero), one), - _mm_and_ps(_mm_cmplt_ps(x1, zero), ngone)); - x2 = _mm_shuffle1_ps(x2, 2, 1, 0, 0); - - x3 = _mm_shuffle_ps(one, x2, _MM_SHUFFLE(0, 0, 0, 0)); /* q1 q1 1 1 */ - x3 = _mm_shuffle_ps(x3, x2, _MM_SHUFFLE(3, 2, 2, 0)); /* q3 q2 q1 1 */ - - _mm_store_ps(dest, _mm_mul_ps(r, x3)); -} - CGLM_INLINE float glm_mat4_det_sse2(mat4 mat) { diff --git a/test/src/test_common.c b/test/src/test_common.c index c13ac0e..b824b37 100644 --- a/test/src/test_common.c +++ b/test/src/test_common.c @@ -55,12 +55,8 @@ test_rand_angle(void) { void test_rand_quat(versor q) { srand((unsigned int)time(NULL)); - - q[0] = drand48(); - q[1] = drand48(); - q[2] = drand48(); - q[3] = drand48(); + glm_quat(q, drand48(), drand48(), drand48(), drand48()); glm_quat_normalize(q); } diff --git a/test/src/test_quat.c b/test/src/test_quat.c index 1a328de..36d2ef5 100644 --- a/test/src/test_quat.c +++ b/test/src/test_quat.c @@ -9,14 +9,16 @@ void test_quat(void **state) { - mat4 rot; + mat4 inRot, outRot; versor inQuat, outQuat; int i; - for (i = 0; i < 10000; i++) { + for (i = 0; i < 1000; i++) { test_rand_quat(inQuat); - glmc_quat_mat4(inQuat, rot); - glm_mat4_quat(rot, outQuat); + glmc_quat_mat4(inQuat, inRot); + glmc_mat4_quat(inRot, outQuat); + glmc_quat_mat4(outQuat, outRot); test_assert_quat_eq(inQuat, outQuat); + test_assert_mat4_eq2(inRot, outRot, 0.000009); /* almost equal */ } } From 7615f785acc2759b1a27e88ecf9ad6dffd4e9b8c Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Mon, 9 Apr 2018 00:53:14 +0300 Subject: [PATCH 15/98] improve quaternion to matrix --- include/cglm/quat.h | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/include/cglm/quat.h b/include/cglm/quat.h index e9e986e..bbad5f2 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -185,18 +185,19 @@ glm_quat_mat4(versor q, mat4 dest) { float w, x, y, z, xx, yy, zz, xy, yz, xz, - wx, wy, wz, norm; + wx, wy, wz, norm, s; - norm = 1.0f / glm_quat_norm(q); + norm = glm_quat_norm(q); + s = norm > 0.0f ? 2.0f / norm : 0.0f; - w = q[0] * norm; - x = q[1] * norm; - y = q[2] * norm; - z = q[3] * norm; + w = q[0]; + x = q[1]; + y = q[2]; + z = q[3]; - xx = 2.0f * x * x; xy = 2.0f * x * y; wx = 2.0f * w * x; - yy = 2.0f * y * y; yz = 2.0f * y * z; wy = 2.0f * w * y; - zz = 2.0f * z * z; xz = 2.0f * x * z; wz = 2.0f * w * z; + xx = s * x * x; xy = s * x * y; wx = s * w * x; + yy = s * y * y; yz = s * y * z; wy = s * w * y; + zz = s * z * z; xz = s * x * z; wz = s * w * z; dest[0][0] = 1.0f - yy - zz; dest[1][1] = 1.0f - xx - zz; @@ -210,8 +211,8 @@ glm_quat_mat4(versor q, mat4 dest) { dest[2][1] = yz - wx; dest[0][2] = xz - wy; - dest[1][3] = 0.0f; 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; @@ -231,18 +232,19 @@ glm_quat_mat3(versor q, mat3 dest) { float w, x, y, z, xx, yy, zz, xy, yz, xz, - wx, wy, wz, norm; + wx, wy, wz, norm, s; - norm = 1.0f / glm_quat_norm(q); + norm = glm_quat_norm(q); + s = norm > 0.0f ? 2.0f / norm : 0.0f; - w = q[0] * norm; - x = q[1] * norm; - y = q[2] * norm; - z = q[3] * norm; + w = q[0]; + x = q[1]; + y = q[2]; + z = q[3]; - xx = 2.0f * x * x; xy = 2.0f * x * y; wx = 2.0f * w * x; - yy = 2.0f * y * y; yz = 2.0f * y * z; wy = 2.0f * w * y; - zz = 2.0f * z * z; xz = 2.0f * x * z; wz = 2.0f * w * z; + xx = s * x * x; xy = s * x * y; wx = s * w * x; + yy = s * y * y; yz = s * y * z; wy = s * w * y; + zz = s * z * z; xz = s * x * z; wz = s * w * z; dest[0][0] = 1.0f - yy - zz; dest[1][1] = 1.0f - xx - zz; From 3dc93c56e8696a25e1e5d21fba5cdeefc8f9ab42 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Mon, 9 Apr 2018 18:49:12 +0300 Subject: [PATCH 16/98] convert quaterinon to xyzw order (part 1) --- include/cglm/call/quat.h | 15 ++----- include/cglm/mat3.h | 52 +++++++++++----------- include/cglm/mat4.h | 52 +++++++++++----------- include/cglm/quat.h | 95 +++++++++++++++++++++------------------- include/cglm/vec3.h | 4 +- src/quat.c | 12 ++--- 6 files changed, 112 insertions(+), 118 deletions(-) diff --git a/include/cglm/call/quat.h b/include/cglm/call/quat.h index e40bcdf..576f43b 100644 --- a/include/cglm/call/quat.h +++ b/include/cglm/call/quat.h @@ -19,17 +19,11 @@ glmc_quat_identity(versor q); CGLM_EXPORT void -glmc_quat(versor q, - float angle, - float x, - float y, - float z); +glmc_quat(versor q, float angle, float x, float y, float z); CGLM_EXPORT void -glmc_quatv(versor q, - float angle, - vec3 v); +glmc_quatv(versor q, float angle, vec3 v); CGLM_EXPORT float @@ -57,10 +51,7 @@ glmc_quat_mat3(versor q, mat3 dest); CGLM_EXPORT void -glmc_quat_slerp(versor q, - versor r, - float t, - versor dest); +glmc_quat_slerp(versor q, versor r, float t, versor dest); #ifdef __cplusplus } diff --git a/include/cglm/mat3.h b/include/cglm/mat3.h index e7f8bcc..9512aef 100644 --- a/include/cglm/mat3.h +++ b/include/cglm/mat3.h @@ -198,39 +198,41 @@ void glm_mat3_quat(mat3 m, versor dest) { float trace, r, rinv; + /* it seems using like m12 instead of m[1][2] causes extra instructions */ + trace = m[0][0] + m[1][1] + m[2][2]; if (trace >= 0.0f) { - r = 2.0f * sqrtf(1 + trace); - rinv = 1.0f / r; + r = sqrtf(1.0f + trace); + rinv = 0.5f / r; - dest[1] = rinv * (m[1][2] - m[2][1]); - dest[2] = rinv * (m[2][0] - m[0][2]); - dest[3] = rinv * (m[0][1] - m[1][0]); - dest[0] = r * 0.25f; - } else if (m[0][0] >= m[1][1] && m[0][0] >= m[2][2]) { - r = 2.0f * sqrtf(1 - m[1][1] - m[2][2] + m[0][0]); - rinv = 1.0f / r; - - dest[1] = r * 0.25f; - dest[2] = rinv * (m[0][1] + m[1][0]); - dest[3] = rinv * (m[0][2] + m[2][0]); dest[0] = rinv * (m[1][2] - m[2][1]); - } else if (m[1][1] >= m[2][2]) { - r = 2.0f * sqrtf(1 - m[0][0] - m[2][2] + m[1][1]); - rinv = 1.0f / r; + dest[1] = rinv * (m[2][0] - m[0][2]); + dest[2] = rinv * (m[0][1] - m[1][0]); + dest[3] = r * 0.5f; + } else if (m[0][0] >= m[1][1] && m[0][0] >= m[2][2]) { + r = sqrtf(1.0f - m[1][1] - m[2][2] + m[0][0]); + rinv = 0.5f / r; + dest[0] = r * 0.5f; dest[1] = rinv * (m[0][1] + m[1][0]); - dest[2] = r * 0.25f; - dest[3] = rinv * (m[1][2] + m[2][1]); - dest[0] = rinv * (m[2][0] - m[0][2]); - } else { - r = 2.0f * sqrtf(1 - m[0][0] - m[1][1] + m[2][2]); - rinv = 1.0f / r; + dest[2] = rinv * (m[0][2] + m[2][0]); + dest[3] = rinv * (m[1][2] - m[2][1]); + } else if (m[1][1] >= m[2][2]) { + r = sqrtf(1.0f - m[0][0] - m[2][2] + m[1][1]); + rinv = 0.5f / r; - dest[1] = rinv * (m[0][2] + m[2][0]); + dest[0] = rinv * (m[0][1] + m[1][0]); + dest[1] = r * 0.5f; dest[2] = rinv * (m[1][2] + m[2][1]); - dest[3] = r * 0.25f; - dest[0] = rinv * (m[0][1] - m[1][0]); + dest[3] = rinv * (m[2][0] - m[0][2]); + } else { + r = sqrtf(1.0f - m[0][0] - m[1][1] + m[2][2]); + rinv = 0.5f / r; + + dest[0] = rinv * (m[0][2] + m[2][0]); + dest[1] = rinv * (m[1][2] + m[2][1]); + dest[2] = r * 0.5f; + dest[3] = rinv * (m[0][1] - m[1][0]); } } diff --git a/include/cglm/mat4.h b/include/cglm/mat4.h index 05aac60..fd7a340 100644 --- a/include/cglm/mat4.h +++ b/include/cglm/mat4.h @@ -345,39 +345,41 @@ void glm_mat4_quat(mat4 m, versor dest) { float trace, r, rinv; + /* it seems using like m12 instead of m[1][2] causes extra instructions */ + trace = m[0][0] + m[1][1] + m[2][2]; if (trace >= 0.0f) { - r = 2.0f * sqrtf(1 + trace); - rinv = 1.0f / r; + r = sqrtf(1.0f + trace); + rinv = 0.5f / r; - dest[1] = rinv * (m[1][2] - m[2][1]); - dest[2] = rinv * (m[2][0] - m[0][2]); - dest[3] = rinv * (m[0][1] - m[1][0]); - dest[0] = r * 0.25f; - } else if (m[0][0] >= m[1][1] && m[0][0] >= m[2][2]) { - r = 2.0f * sqrtf(1 - m[1][1] - m[2][2] + m[0][0]); - rinv = 1.0f / r; - - dest[1] = r * 0.25f; - dest[2] = rinv * (m[0][1] + m[1][0]); - dest[3] = rinv * (m[0][2] + m[2][0]); dest[0] = rinv * (m[1][2] - m[2][1]); - } else if (m[1][1] >= m[2][2]) { - r = 2.0f * sqrtf(1 - m[0][0] - m[2][2] + m[1][1]); - rinv = 1.0f / r; + dest[1] = rinv * (m[2][0] - m[0][2]); + dest[2] = rinv * (m[0][1] - m[1][0]); + dest[3] = r * 0.5f; + } else if (m[0][0] >= m[1][1] && m[0][0] >= m[2][2]) { + r = sqrtf(1.0f - m[1][1] - m[2][2] + m[0][0]); + rinv = 0.5f / r; + dest[0] = r * 0.5f; dest[1] = rinv * (m[0][1] + m[1][0]); - dest[2] = r * 0.25f; - dest[3] = rinv * (m[1][2] + m[2][1]); - dest[0] = rinv * (m[2][0] - m[0][2]); - } else { - r = 2.0f * sqrtf(1 - m[0][0] - m[1][1] + m[2][2]); - rinv = 1.0f / r; + dest[2] = rinv * (m[0][2] + m[2][0]); + dest[3] = rinv * (m[1][2] - m[2][1]); + } else if (m[1][1] >= m[2][2]) { + r = sqrtf(1.0f - m[0][0] - m[2][2] + m[1][1]); + rinv = 0.5f / r; - dest[1] = rinv * (m[0][2] + m[2][0]); + dest[0] = rinv * (m[0][1] + m[1][0]); + dest[1] = r * 0.5f; dest[2] = rinv * (m[1][2] + m[2][1]); - dest[3] = r * 0.25f; - dest[0] = rinv * (m[0][1] - m[1][0]); + dest[3] = rinv * (m[2][0] - m[0][2]); + } else { + r = sqrtf(1.0f - m[0][0] - m[1][1] + m[2][2]); + rinv = 0.5f / r; + + dest[0] = rinv * (m[0][2] + m[2][0]); + dest[1] = rinv * (m[1][2] + m[2][1]); + dest[2] = r * 0.5f; + dest[3] = rinv * (m[0][1] - m[1][0]); } } diff --git a/include/cglm/quat.h b/include/cglm/quat.h index bbad5f2..4d6ee5d 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -13,7 +13,7 @@ Functions: CGLM_INLINE void glm_quat_identity(versor q); CGLM_INLINE void glm_quat(versor q, float angle, float x, float y, float z); - CGLM_INLINE void glm_quatv(versor q, float angle, vec3 v); + CGLM_INLINE void glm_quatv(versor q, float angle, vec3 axis); CGLM_INLINE float glm_quat_norm(versor q); CGLM_INLINE void glm_quat_normalize(versor q); CGLM_INLINE float glm_quat_dot(versor q, versor r); @@ -33,19 +33,16 @@ #endif /* - * IMPORTANT! cglm stores quat as [w, x, y, z] + * IMPORTANT: + * ---------------------------------------------------------------------------- + * cglm stores quat as [x, y, z, w] since v0.3.6 * - * Possible changes (these may be changed in the future): - * - versor is identity quat, we can define new type for quat. - * it can't be quat or quaternion becuase someone can use that name for - * variable name. maybe just vec4. - * - it stores [w, x, y, z] but it may change to [x, y, z, w] if we get enough - * feedback to change it. - * - in general we use last param as dest, but this header used first param - * as dest this may be changed but decided yet + * it was [w, x, y, z] before v0.3.6 it has been changed to [x, y, z, w] + * with v0.3.6 version. + * ---------------------------------------------------------------------------- */ -#define GLM_QUAT_IDENTITY_INIT {1.0f, 0.0f, 0.0f, 0.0f} +#define GLM_QUAT_IDENTITY_INIT {0.0f, 0.0f, 0.0f, 1.0f} #define GLM_QUAT_IDENTITY ((versor)GLM_QUAT_IDENTITY_INIT) /*! @@ -60,6 +57,24 @@ glm_quat_identity(versor q) { glm_vec4_copy(v, q); } +/*! + * @brief inits quaterion with raw values + * + * @param[out] q quaternion + * @param[in] x x + * @param[in] y y + * @param[in] z z + * @param[in] w w (real part) + */ +CGLM_INLINE +void +glm_quat_init(versor q, float x, float y, float z, float w) { + q[0] = x; + q[1] = y; + q[2] = z; + q[3] = w; +} + /*! * @brief creates NEW quaternion with individual axis components * @@ -71,21 +86,17 @@ glm_quat_identity(versor q) { */ CGLM_INLINE void -glm_quat(versor q, - float angle, - float x, - float y, - float z) { +glm_quat(versor q, float angle, float x, float y, float z) { float a, c, s; a = angle * 0.5f; c = cosf(a); s = sinf(a); - q[0] = c; - q[1] = s * x; - q[2] = s * y; - q[3] = s * z; + q[0] = s * x; + q[1] = s * y; + q[2] = s * z; + q[3] = c; } /*! @@ -93,23 +104,21 @@ glm_quat(versor q, * * @param[out] q quaternion * @param[in] angle angle (radians) - * @param[in] v axis + * @param[in] axis axis */ CGLM_INLINE void -glm_quatv(versor q, - float angle, - vec3 v) { +glm_quatv(versor q, float angle, vec3 axis) { float a, c, s; a = angle * 0.5f; c = cosf(a); s = sinf(a); - q[0] = c; - q[1] = s * v[0]; - q[2] = s * v[1]; - q[3] = s * v[2]; + q[0] = s * axis[0]; + q[1] = s * axis[1]; + q[2] = s * axis[2]; + q[3] = c; } /*! @@ -146,13 +155,13 @@ glm_quat_normalize(versor q) { /*! * @brief dot product of two quaternion * - * @param[in] q quaternion 1 - * @param[in] r quaternion 2 + * @param[in] q1 quaternion 1 + * @param[in] q2 quaternion 2 */ CGLM_INLINE float -glm_quat_dot(versor q, versor r) { - return glm_vec4_dot(q, r); +glm_quat_dot(versor q1, versor q2) { + return glm_vec4_dot(q1, q2); } /*! @@ -190,10 +199,10 @@ glm_quat_mat4(versor q, mat4 dest) { norm = glm_quat_norm(q); s = norm > 0.0f ? 2.0f / norm : 0.0f; - w = q[0]; - x = q[1]; - y = q[2]; - z = q[3]; + x = q[0]; + y = q[1]; + z = q[2]; + w = q[3]; xx = s * x * x; xy = s * x * y; wx = s * w * x; yy = s * y * y; yz = s * y * z; wy = s * w * y; @@ -237,10 +246,10 @@ glm_quat_mat3(versor q, mat3 dest) { norm = glm_quat_norm(q); s = norm > 0.0f ? 2.0f / norm : 0.0f; - w = q[0]; - x = q[1]; - y = q[2]; - z = q[3]; + x = q[0]; + y = q[1]; + z = q[2]; + w = q[3]; xx = s * x * x; xy = s * x * y; wx = s * w * x; yy = s * y * y; yz = s * y * z; wy = s * w * y; @@ -270,10 +279,8 @@ glm_quat_mat3(versor q, mat3 dest) { */ CGLM_INLINE void -glm_quat_slerp(versor q, - versor r, - float t, - versor dest) { +glm_quat_slerp(versor q, versor r, float t, versor dest) { + /* https://en.wikipedia.org/wiki/Slerp */ #if defined( __SSE__ ) || defined( __SSE2__ ) glm_quat_slerp_sse2(q, r, t, dest); diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index 873c172..65fe0ba 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -327,9 +327,7 @@ glm_vec_angle(vec3 v1, vec3 v2) { CGLM_INLINE void -glm_quatv(versor q, - float angle, - vec3 v); +glm_quatv(versor q, float angle, vec3 axis); /*! * @brief rotate vec3 around axis by angle using Rodrigues' rotation formula diff --git a/src/quat.c b/src/quat.c index 9955ce1..35ec890 100644 --- a/src/quat.c +++ b/src/quat.c @@ -16,19 +16,13 @@ glmc_quat_identity(versor q) { CGLM_EXPORT void -glmc_quat(versor q, - float angle, - float x, - float y, - float z) { +glmc_quat(versor q, float angle, float x, float y, float z) { glm_quat(q, angle, x, y, z); } CGLM_EXPORT void -glmc_quatv(versor q, - float angle, - vec3 v) { +glmc_quatv(versor q, float angle, vec3 v) { glm_quatv(q, angle, v); } @@ -53,7 +47,7 @@ glmc_quat_dot(versor q, versor r) { CGLM_EXPORT void glmc_quat_mulv(versor q1, versor q2, versor dest) { - glm_quat_mulv(q1, q2, dest); + glm_quat_mul(q1, q2, dest); } CGLM_EXPORT From d79e58486d21f5c2406e6fa7fbc55d73b03ecab7 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Mon, 9 Apr 2018 21:54:35 +0300 Subject: [PATCH 17/98] update credits file --- CREDITS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CREDITS b/CREDITS index 810f0b4..66604eb 100644 --- a/CREDITS +++ b/CREDITS @@ -43,3 +43,6 @@ https://github.com/erich666/GraphicsGems/blob/master/gems/TransBox.c 6. Cull frustum http://www.txutxi.com/?p=584 http://old.cescg.org/CESCG-2002/DSykoraJJelinek/ + +7. Quaternions +Initial mat4_quat is borrowed from Apple's simd library From 76e9f740208305fffd4f027c0bed186a12857027 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Mon, 9 Apr 2018 21:54:53 +0300 Subject: [PATCH 18/98] conjugate of quaternion --- include/cglm/quat.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/include/cglm/quat.h b/include/cglm/quat.h index 4d6ee5d..f824010 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -182,6 +182,20 @@ glm_quat_mulv(versor q1, versor q2, versor dest) { glm_quat_normalize(dest); } +/*! + * @brief conjugate of quaternion + * + * @param[in] q quaternion + * @param[out] dest conjugate + */ +CGLM_INLINE +void +glm_quat_conjugate(versor q, versor dest) { + glm_vec4_copy(q, dest); + glm_vec4_flipsign(dest); + dest[3] = -dest[3]; +} + /*! * @brief convert quaternion to mat4 * From b21df8fc37ce40cb43c88615ef7471075b61a968 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Mon, 9 Apr 2018 22:26:23 +0300 Subject: [PATCH 19/98] inverse of quaternion --- include/cglm/quat.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/include/cglm/quat.h b/include/cglm/quat.h index f824010..a2556dd 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -196,6 +196,20 @@ glm_quat_conjugate(versor q, versor dest) { dest[3] = -dest[3]; } +/*! + * @brief inverse of non-zero quaternion + * + * @param[in] q quaternion + * @param[out] dest inverse quaternion + */ +CGLM_INLINE +void +glm_quat_inv(versor q, versor dest) { + versor conj; + glm_quat_conjugate(q, conj); + glm_vec_scale(conj, glm_vec4_norm2(q), dest); +} + /*! * @brief convert quaternion to mat4 * From cc1d3b53ea4a09ae8ef285c22100dc2353da784d Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Mon, 9 Apr 2018 22:32:55 +0300 Subject: [PATCH 20/98] quat: implement add, sub, real and imag helpers --- include/cglm/quat.h | 50 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/include/cglm/quat.h b/include/cglm/quat.h index a2556dd..efea541 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -210,6 +210,56 @@ glm_quat_inv(versor q, versor dest) { glm_vec_scale(conj, glm_vec4_norm2(q), dest); } +/*! + * @brief add (componentwise) two quaternions and store result in dest + * + * @param[in] p quaternion 1 + * @param[in] q quaternion 2 + * @param[out] dest result quaternion + */ +CGLM_INLINE +void +glm_quat_add(versor p, versor q, versor dest) { + glm_vec4_add(p, q, dest); +} + +/*! + * @brief subtract (componentwise) two quaternions and store result in dest + * + * @param[in] p quaternion 1 + * @param[in] q quaternion 2 + * @param[out] dest result quaternion + */ +CGLM_INLINE +void +glm_quat_sub(versor p, versor q, versor dest) { + glm_vec4_sub(p, q, dest); +} + +/*! + * @brief returns real part of quaternion + * + * @param[in] q quaternion + */ +CGLM_INLINE +float +glm_quat_real(versor q) { + return q[3]; +} + +/*! + * @brief returns imaginary part of quaternion + * + * @param[in] q quaternion + */ +CGLM_INLINE +void +glm_quat_imag(versor q, vec3 dest) { + dest[0] = q[0]; + dest[1] = q[1]; + dest[2] = q[2]; +} + /*! * @brief convert quaternion to mat4 * From 93a08fce17155addc14fc526644d9e24320d1a67 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Mon, 9 Apr 2018 23:12:44 +0300 Subject: [PATCH 21/98] quat: axis angle of quaternion --- include/cglm/quat.h | 50 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/include/cglm/quat.h b/include/cglm/quat.h index efea541..e73bf8b 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -260,6 +260,56 @@ glm_quat_imag(versor q, vec3 dest) { dest[2] = q[2]; } +/*! + * @brief returns normalized imaginary part of quaternion + * + * @param[in] q quaternion + */ +CGLM_INLINE +void +glm_quat_imagn(versor q, vec3 dest) { + glm_normalize_to(q, dest); +} + +/*! + * @brief returns length of imaginary part of quaternion + * + * @param[in] q quaternion + */ +CGLM_INLINE +float +glm_quat_imaglen(versor q) { + return glm_vec_norm(q); +} + +/*! + * @brief returns angle of quaternion + * + * @param[in] q quaternion + */ +CGLM_INLINE +float +glm_quat_angle(versor q) { + /* + sin(theta / 2) = length(x*x + y*y + z*z) + cos(theta / 2) = w + theta = 2 * atan(sin(theta / 2) / cos(theta / 2)) + */ + return 2.0f * atan2f(glm_quat_imaglen(q), glm_quat_real(q)); +} + +/*! + * @brief axis of quaternion + * + * @param[in] q quaternion + * @param[out] dest axis of quaternion + */ +CGLM_INLINE +void +glm_quat_axis(versor q, versor dest) { + glm_quat_imagn(q, dest); +} + /*! * @brief convert quaternion to mat4 * From 6f69da361b91d27d5784abc2c2f799536efd309b Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Mon, 9 Apr 2018 23:56:09 +0300 Subject: [PATCH 22/98] quaternion multiplication * convert quaternion multiplication to xyzw * previous implementation may be wrong, wikipedia version implemented * implement SSE version --- include/cglm/call/quat.h | 2 +- include/cglm/quat.h | 77 +++++++++++++++++++++++------------ include/cglm/simd/sse2/quat.h | 29 +++++++++++++ src/quat.c | 9 ++-- test/src/test_common.c | 18 +++++--- test/src/test_common.h | 3 ++ test/src/test_quat.c | 18 +++++++- 7 files changed, 116 insertions(+), 40 deletions(-) diff --git a/include/cglm/call/quat.h b/include/cglm/call/quat.h index 576f43b..ee45f0c 100644 --- a/include/cglm/call/quat.h +++ b/include/cglm/call/quat.h @@ -39,7 +39,7 @@ glmc_quat_dot(versor q, versor r); CGLM_EXPORT void -glmc_quat_mulv(versor q1, versor q2, versor dest); +glmc_quat_mul(versor p, versor q, versor dest); CGLM_EXPORT void diff --git a/include/cglm/quat.h b/include/cglm/quat.h index e73bf8b..e1112d5 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -11,15 +11,27 @@ GLM_QUAT_IDENTITY Functions: - CGLM_INLINE void glm_quat_identity(versor q); - CGLM_INLINE void glm_quat(versor q, float angle, float x, float y, float z); - CGLM_INLINE void glm_quatv(versor q, float angle, vec3 axis); + CGLM_INLINE void glm_quat_identity(versor q); + CGLM_INLINE void glm_quat_init(versor q, float x, float y, float z, float w); + CGLM_INLINE void glm_quat(versor q, float angle, float x, float y, float z); + CGLM_INLINE void glm_quatv(versor q, float angle, vec3 axis); CGLM_INLINE float glm_quat_norm(versor q); - CGLM_INLINE void glm_quat_normalize(versor q); - CGLM_INLINE float glm_quat_dot(versor q, versor r); - CGLM_INLINE void glm_quat_mulv(versor q1, versor q2, versor dest); - CGLM_INLINE void glm_quat_mat4(versor q, mat4 dest); - CGLM_INLINE void glm_quat_slerp(versor q, versor r, float t, versor dest); + CGLM_INLINE void glm_quat_normalize(versor q); + CGLM_INLINE float glm_quat_dot(versor q1, versor q2); + CGLM_INLINE void glm_quat_conjugate(versor q, versor dest); + CGLM_INLINE void glm_quat_inv(versor q, versor dest); + CGLM_INLINE void glm_quat_add(versor p, versor q, versor dest); + CGLM_INLINE void glm_quat_sub(versor p, versor q, versor dest); + CGLM_INLINE float glm_quat_real(versor q); + CGLM_INLINE void glm_quat_imag(versor q, vec3 dest); + CGLM_INLINE void glm_quat_imagn(versor q, vec3 dest); + CGLM_INLINE float glm_quat_imaglen(versor q); + CGLM_INLINE float glm_quat_angle(versor q); + CGLM_INLINE void glm_quat_axis(versor q, versor dest); + CGLM_INLINE void glm_quat_mul(versor p, versor q, versor dest); + CGLM_INLINE void glm_quat_mat4(versor q, mat4 dest); + CGLM_INLINE void glm_quat_mat3(versor q, mat3 dest) + CGLM_INLINE void glm_quat_slerp(versor q, versor r, float t, versor dest); */ #ifndef cglm_quat_h @@ -164,24 +176,6 @@ glm_quat_dot(versor q1, versor q2) { return glm_vec4_dot(q1, q2); } -/*! - * @brief multiplies two quaternion and stores result in dest - * - * @param[in] q1 quaternion 1 - * @param[in] q2 quaternion 2 - * @param[out] dest result quaternion - */ -CGLM_INLINE -void -glm_quat_mulv(versor q1, versor q2, versor dest) { - dest[0] = q2[0] * q1[0] - q2[1] * q1[1] - q2[2] * q1[2] - q2[3] * q1[3]; - dest[1] = q2[0] * q1[1] + q2[1] * q1[0] - q2[2] * q1[3] + q2[3] * q1[2]; - dest[2] = q2[0] * q1[2] + q2[1] * q1[3] + q2[2] * q1[0] - q2[3] * q1[1]; - dest[3] = q2[0] * q1[3] - q2[1] * q1[2] + q2[2] * q1[1] + q2[3] * q1[0]; - - glm_quat_normalize(dest); -} - /*! * @brief conjugate of quaternion * @@ -310,6 +304,37 @@ glm_quat_axis(versor q, versor dest) { glm_quat_imagn(q, dest); } +/*! + * @brief multiplies two quaternion and stores result in dest + * this is also called Hamilton Product + * + * According to WikiPedia: + * The product of two rotation quaternions [clarification needed] will be + * equivalent to the rotation q followed by the rotation p + * + * @param[in] p quaternion 1 + * @param[in] q quaternion 2 + * @param[out] dest result quaternion + */ +CGLM_INLINE +void +glm_quat_mul(versor p, versor q, versor dest) { + /* + + (a1 b2 + b1 a2 + c1 d2 − d1 c2)i + + (a1 c2 − b1 d2 + c1 a2 + d1 b2)j + + (a1 d2 + b1 c2 − c1 b2 + d1 a2)k + a1 a2 − b1 b2 − c1 c2 − d1 d2 + */ +#if defined( __SSE__ ) || defined( __SSE2__ ) + glm_quat_mul_sse2(p, q, dest); +#else + dest[0] = p[3] * q[0] + p[0] * q[3] + p[1] * q[2] - p[2] * q[1]; + dest[1] = p[3] * q[1] - p[0] * q[2] + p[1] * q[3] + p[2] * q[0]; + dest[2] = p[3] * q[2] + p[0] * q[1] - p[1] * q[0] + p[2] * q[3]; + dest[3] = p[3] * q[3] - p[0] * q[0] - p[1] * q[1] - p[2] * q[2]; +#endif +} + /*! * @brief convert quaternion to mat4 * diff --git a/include/cglm/simd/sse2/quat.h b/include/cglm/simd/sse2/quat.h index b3420a7..59438f4 100644 --- a/include/cglm/simd/sse2/quat.h +++ b/include/cglm/simd/sse2/quat.h @@ -12,6 +12,35 @@ #include "../../common.h" #include "../intrin.h" +CGLM_INLINE +void +glm_quat_mul_sse2(versor p, versor q, versor dest) { + /* + + (a1 b2 + b1 a2 + c1 d2 − d1 c2)i + + (a1 c2 − b1 d2 + c1 a2 + d1 b2)j + + (a1 d2 + b1 c2 − c1 b2 + d1 a2)k + a1 a2 − b1 b2 − c1 c2 − d1 d2 + */ + + __m128 xp, xq, x0, r; + + xp = _mm_load_ps(p); /* 3 2 1 0 */ + xq = _mm_load_ps(q); + + r = _mm_mul_ps(_mm_shuffle1_ps1(xp, 3), xq); + + x0 = _mm_xor_ps(_mm_shuffle1_ps1(xp, 0), _mm_set_ps(-0.f, 0.f, -0.f, 0.f)); + r = _mm_add_ps(r, _mm_mul_ps(x0, _mm_shuffle1_ps(xq, 0, 1, 2, 3))); + + x0 = _mm_xor_ps(_mm_shuffle1_ps1(xp, 1), _mm_set_ps(-0.f, -0.f, 0.f, 0.f)); + r = _mm_add_ps(r, _mm_mul_ps(x0, _mm_shuffle1_ps(xq, 1, 0, 3, 2))); + + x0 = _mm_xor_ps(_mm_shuffle1_ps1(xp, 2), _mm_set_ps(-0.f, 0.f, 0.f, -0.f)); + r = _mm_add_ps(r, _mm_mul_ps(x0, _mm_shuffle1_ps(xq, 2, 3, 0, 1))); + + _mm_store_ps(dest, r); +} + CGLM_INLINE void glm_quat_slerp_sse2(versor q, diff --git a/src/quat.c b/src/quat.c index 35ec890..b1cfe90 100644 --- a/src/quat.c +++ b/src/quat.c @@ -46,8 +46,8 @@ glmc_quat_dot(versor q, versor r) { CGLM_EXPORT void -glmc_quat_mulv(versor q1, versor q2, versor dest) { - glm_quat_mul(q1, q2, dest); +glmc_quat_mul(versor p, versor q, versor dest) { + glm_quat_mul(p, q, dest); } CGLM_EXPORT @@ -64,9 +64,6 @@ glmc_quat_mat3(versor q, mat3 dest) { CGLM_EXPORT void -glmc_quat_slerp(versor q, - versor r, - float t, - versor dest) { +glmc_quat_slerp(versor q, versor r, float t, versor dest) { glm_quat_slerp(q, r, t, dest); } diff --git a/test/src/test_common.c b/test/src/test_common.c index b824b37..bd6deaf 100644 --- a/test/src/test_common.c +++ b/test/src/test_common.c @@ -92,10 +92,18 @@ test_assert_vec3_eq(vec3 v1, vec3 v2) { } void -test_assert_quat_eq(versor v1, versor v2) { - assert_true(fabsf(v1[0] - v2[0]) <= 0.0009); /* rounding errors */ - assert_true(fabsf(v1[1] - v2[1]) <= 0.0009); - assert_true(fabsf(v1[2] - v2[2]) <= 0.0009); - assert_true(fabsf(v1[3] - v2[3]) <= 0.0009); +test_assert_quat_eq_abs(versor v1, versor v2) { + assert_true(fabsf(fabsf(v1[0]) - fabsf(v2[0])) <= 0.0009); /* rounding errors */ + assert_true(fabsf(fabsf(v1[1]) - fabsf(v2[1])) <= 0.0009); + assert_true(fabsf(fabsf(v1[2]) - fabsf(v2[2])) <= 0.0009); + assert_true(fabsf(fabsf(v1[3]) - fabsf(v2[3])) <= 0.0009); +} + +void +test_assert_quat_eq(versor v1, versor v2) { + assert_true(fabsf(v1[0] - v2[0]) <= 0.0000009); /* rounding errors */ + assert_true(fabsf(v1[1] - v2[1]) <= 0.0000009); + assert_true(fabsf(v1[2] - v2[2]) <= 0.0000009); + assert_true(fabsf(v1[3] - v2[3]) <= 0.0000009); } diff --git a/test/src/test_common.h b/test/src/test_common.h index 477e59d..c95405e 100644 --- a/test/src/test_common.h +++ b/test/src/test_common.h @@ -37,6 +37,9 @@ test_assert_vec3_eq(vec3 v1, vec3 v2); void test_assert_quat_eq(versor v1, versor v2); +void +test_assert_quat_eq_abs(versor v1, versor v2); + void test_rand_vec3(vec3 dest); diff --git a/test/src/test_quat.c b/test/src/test_quat.c index 36d2ef5..723dea1 100644 --- a/test/src/test_quat.c +++ b/test/src/test_quat.c @@ -7,10 +7,19 @@ #include "test_common.h" +CGLM_INLINE +void +test_quat_mul_raw(versor p, versor q, versor dest) { + dest[0] = p[3] * q[0] + p[0] * q[3] + p[1] * q[2] - p[2] * q[1]; + dest[1] = p[3] * q[1] - p[0] * q[2] + p[1] * q[3] + p[2] * q[0]; + dest[2] = p[3] * q[2] + p[0] * q[1] - p[1] * q[0] + p[2] * q[3]; + dest[3] = p[3] * q[3] - p[0] * q[0] - p[1] * q[1] - p[2] * q[2]; +} + void test_quat(void **state) { mat4 inRot, outRot; - versor inQuat, outQuat; + versor inQuat, outQuat, q3, q4; int i; for (i = 0; i < 1000; i++) { @@ -18,7 +27,12 @@ test_quat(void **state) { glmc_quat_mat4(inQuat, inRot); glmc_mat4_quat(inRot, outQuat); glmc_quat_mat4(outQuat, outRot); - test_assert_quat_eq(inQuat, outQuat); + test_assert_quat_eq_abs(inQuat, outQuat); test_assert_mat4_eq2(inRot, outRot, 0.000009); /* almost equal */ + + test_quat_mul_raw(inQuat, outQuat, q3); + glm_quat_mul_sse2(inQuat, outQuat, q4); + + test_assert_quat_eq(q3, q4); } } From 591c881376f5e4c99b459d5c17014b61ed1d79ca Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 10 Apr 2018 10:46:45 +0300 Subject: [PATCH 23/98] vec: extend flip sign to store result in another vector --- include/cglm/vec3.h | 14 ++++++++++++++ include/cglm/vec4.h | 20 ++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index 65fe0ba..13b4920 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -242,6 +242,20 @@ glm_vec_flipsign(vec3 v) { v[2] = -v[2]; } +/*! + * @brief flip sign of all vec3 members and store result in dest + * + * @param[in] v vector + * @param[out] dest vector + */ +CGLM_INLINE +void +glm_vec_flipsign_to(vec3 v, vec3 dest) { + dest[0] = -v[0]; + dest[1] = -v[1]; + dest[2] = -v[2]; +} + /*! * @brief make vector as inverse/opposite of itself * diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index adf5fb9..1c4ce13 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -268,6 +268,26 @@ glm_vec4_flipsign(vec4 v) { #endif } +/*! + * @brief flip sign of all vec4 members and store result in dest + * + * @param[in] v vector + * @param[out] dest vector + */ +CGLM_INLINE +void +glm_vec4_flipsign_to(vec4 v, vec4 dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(dest, _mm_xor_ps(_mm_load_ps(v), + _mm_set1_ps(-0.0f))); +#else + dest[0] = -v[0]; + dest[1] = -v[1]; + dest[2] = -v[2]; + dest[3] = -v[3]; +#endif +} + /*! * @brief make vector as inverse/opposite of itself * From 1fb82a1922b4ac8f6c0207d9a45b0a9d3de460df Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 10 Apr 2018 10:47:55 +0300 Subject: [PATCH 24/98] quat: use vector functions for available operations * provide quat_copy function --- include/cglm/quat.h | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/include/cglm/quat.h b/include/cglm/quat.h index e1112d5..32367ac 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -133,6 +133,18 @@ glm_quatv(versor q, float angle, vec3 axis) { q[3] = c; } +/*! + * @brief copy quaternion to another one + * + * @param[in] q quaternion + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_quat_copy(versor q, versor dest) { + glm_vec4_copy(q, dest); +} + /*! * @brief returns norm (magnitude) of quaternion * @@ -185,8 +197,7 @@ glm_quat_dot(versor q1, versor q2) { CGLM_INLINE void glm_quat_conjugate(versor q, versor dest) { - glm_vec4_copy(q, dest); - glm_vec4_flipsign(dest); + glm_vec4_flipsign_to(q, dest); dest[3] = -dest[3]; } @@ -442,23 +453,16 @@ glm_quat_slerp(versor q, versor r, float t, versor dest) { cosTheta = glm_quat_dot(q, r); if (cosTheta < 0.0f) { - q[0] *= -1.0f; - q[1] *= -1.0f; - q[2] *= -1.0f; - q[3] *= -1.0f; - + glm_vec4_flipsign(q); cosTheta = -cosTheta; } if (fabs(cosTheta) >= 1.0f) { - dest[0] = q[0]; - dest[1] = q[1]; - dest[2] = q[2]; - dest[3] = q[3]; + glm_quat_copy(q, dest); return; } - sinTheta = sqrt(1.0f - cosTheta * cosTheta); + sinTheta = sqrtf(1.0f - cosTheta * cosTheta); c = 1.0f - t; From 416e2f4452f8d7245ca9ec98d8417ede35fdd965 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 10 Apr 2018 11:44:16 +0300 Subject: [PATCH 25/98] vec: lerp for vec3 and vec4 --- include/cglm/util.h | 15 +++++++++++++++ include/cglm/vec3.h | 22 ++++++++++++++++++++++ include/cglm/vec4.h | 22 ++++++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/include/cglm/util.h b/include/cglm/util.h index 85fc789..b272d44 100644 --- a/include/cglm/util.h +++ b/include/cglm/util.h @@ -143,4 +143,19 @@ glm_clamp(float val, float minVal, float maxVal) { return glm_min(glm_max(val, minVal), maxVal); } +/*! + * @brief linear interpolation between two number + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + */ +CGLM_INLINE +float +glm_lerp(float from, float to, float t) { + return from + glm_clamp(t, 0.0f, 1.0f) * (to - from); +} + #endif /* cglm_util_h */ diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index 13b4920..cb94909 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -506,6 +506,28 @@ glm_vec_clamp(vec3 v, float minVal, float maxVal) { v[2] = glm_clamp(v[2], minVal, maxVal); } +/*! + * @brief linear interpolation between two vector + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec_lerp(vec3 from, vec3 to, float t, vec3 dest) { + vec3 s, v; + + /* from + s * (to - from) */ + glm_vec_broadcast(glm_clamp(t, 0.0f, 1.0f), s); + glm_vec_sub(to, from, v); + glm_vec_mulv(s, v, v); + glm_vec_add(from, v, dest); +} + /*! * @brief vec3 cross product * diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index 1c4ce13..eaa4eaf 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -417,4 +417,26 @@ glm_vec4_clamp(vec4 v, float minVal, float maxVal) { v[3] = glm_clamp(v[3], minVal, maxVal); } +/*! + * @brief linear interpolation between two vector + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest) { + vec4 s, v; + + /* from + s * (to - from) */ + glm_vec4_broadcast(glm_clamp(t, 0.0f, 1.0f), s); + glm_vec4_sub(to, from, v); + glm_vec4_mulv(s, v, v); + glm_vec4_add(from, v, dest); +} + #endif /* cglm_vec4_h */ From 290bcf134c661df5d8409f49756dda1e3bad534c Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 10 Apr 2018 12:38:54 +0300 Subject: [PATCH 26/98] quat: add lerp and improve slerp --- include/cglm/quat.h | 66 +++++++++++++++++++---------------- include/cglm/simd/sse2/quat.h | 52 --------------------------- 2 files changed, 35 insertions(+), 83 deletions(-) diff --git a/include/cglm/quat.h b/include/cglm/quat.h index 32367ac..f48d3b0 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -432,60 +432,64 @@ glm_quat_mat3(versor q, mat3 dest) { dest[0][2] = xz - wy; } +/*! + * @brief interpolates between two quaternions + * using linear interpolation (LERP) + * + * @param[in] from from + * @param[in] to to + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @param[out] dest result quaternion + */ +CGLM_INLINE +void +glm_quat_lerp(versor from, versor to, float t, versor dest) { + glm_vec4_lerp(from, to, t, dest); +} + /*! * @brief interpolates between two quaternions * using spherical linear interpolation (SLERP) * - * @param[in] q from - * @param[in] r to + * @param[in] from from + * @param[in] to to * @param[in] t amout * @param[out] dest result quaternion */ CGLM_INLINE void -glm_quat_slerp(versor q, versor r, float t, versor dest) { +glm_quat_slerp(versor from, versor to, float t, versor dest) { + vec4 q1, q2; + float cosTheta, sinTheta, angle; - /* https://en.wikipedia.org/wiki/Slerp */ -#if defined( __SSE__ ) || defined( __SSE2__ ) - glm_quat_slerp_sse2(q, r, t, dest); -#else - float cosTheta, sinTheta, angle, a, b, c; + cosTheta = glm_quat_dot(from, to); + glm_quat_copy(from, q1); - cosTheta = glm_quat_dot(q, r); - if (cosTheta < 0.0f) { - glm_vec4_flipsign(q); - cosTheta = -cosTheta; + if (fabsf(cosTheta) >= 1.0f) { + glm_quat_copy(q1, dest); + return; } - if (fabs(cosTheta) >= 1.0f) { - glm_quat_copy(q, dest); - return; + if (cosTheta < 0.0f) { + glm_vec4_flipsign(q1); + cosTheta = -cosTheta; } sinTheta = sqrtf(1.0f - cosTheta * cosTheta); - c = 1.0f - t; - - /* LERP */ - /* TODO: FLT_EPSILON vs 0.001? */ - if (sinTheta < 0.001f) { - dest[0] = c * q[0] + t * r[0]; - dest[1] = c * q[1] + t * r[1]; - dest[2] = c * q[2] + t * r[2]; - dest[3] = c * q[3] + t * r[3]; + /* LERP to avoid zero division */ + if (fabsf(sinTheta) < 0.001f) { + glm_quat_lerp(from, to, t, dest); return; } /* SLERP */ angle = acosf(cosTheta); - a = sinf(c * angle); - b = sinf(t * angle); + glm_vec4_scale(q1, sinf((1.0f - t) * angle), q1); + glm_vec4_scale(to, sinf(t * angle), q2); - dest[0] = (q[0] * a + r[0] * b) / sinTheta; - dest[1] = (q[1] * a + r[1] * b) / sinTheta; - dest[2] = (q[2] * a + r[2] * b) / sinTheta; - dest[3] = (q[3] * a + r[3] * b) / sinTheta; -#endif + glm_vec4_add(q1, q2, q1); + glm_vec4_scale(q1, 1.0f / sinTheta, dest); } #endif /* cglm_quat_h */ diff --git a/include/cglm/simd/sse2/quat.h b/include/cglm/simd/sse2/quat.h index 59438f4..5dbf759 100644 --- a/include/cglm/simd/sse2/quat.h +++ b/include/cglm/simd/sse2/quat.h @@ -41,58 +41,6 @@ glm_quat_mul_sse2(versor p, versor q, versor dest) { _mm_store_ps(dest, r); } -CGLM_INLINE -void -glm_quat_slerp_sse2(versor q, - versor r, - float t, - versor dest) { - /* https://en.wikipedia.org/wiki/Slerp */ - float cosTheta, sinTheta, angle, a, b, c; - - __m128 xmm_q; - - xmm_q = _mm_load_ps(q); - - cosTheta = glm_vec4_dot(q, r); - if (cosTheta < 0.0f) { - _mm_store_ps(q, - _mm_xor_ps(xmm_q, - _mm_set1_ps(-0.f))) ; - - cosTheta = -cosTheta; - } - - if (cosTheta >= 1.0f) { - _mm_store_ps(dest, xmm_q); - return; - } - - sinTheta = sqrtf(1.0f - cosTheta * cosTheta); - - c = 1.0f - t; - - /* LERP */ - if (sinTheta < 0.001f) { - _mm_store_ps(dest, _mm_add_ps(_mm_mul_ps(_mm_set1_ps(c), - xmm_q), - _mm_mul_ps(_mm_set1_ps(t), - _mm_load_ps(r)))); - return; - } - - /* SLERP */ - angle = acosf(cosTheta); - a = sinf(c * angle); - b = sinf(t * angle); - - _mm_store_ps(dest, - _mm_div_ps(_mm_add_ps(_mm_mul_ps(_mm_set1_ps(a), - xmm_q), - _mm_mul_ps(_mm_set1_ps(b), - _mm_load_ps(r))), - _mm_set1_ps(sinTheta))); -} #endif #endif /* cglm_quat_simd_h */ From f0a51b35ad8d37d0c8aeccc4b1e6ed8b6008ab33 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 10 Apr 2018 15:41:09 +0300 Subject: [PATCH 27/98] quat: transposed/inverted version of quat2mat --- include/cglm/quat.h | 86 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/include/cglm/quat.h b/include/cglm/quat.h index f48d3b0..ff3c38c 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -393,6 +393,53 @@ glm_quat_mat4(versor q, mat4 dest) { dest[3][3] = 1.0f; } +/*! + * @brief convert quaternion to mat4 (transposed) + * + * @param[in] q quaternion + * @param[out] dest result matrix as transposed + */ +CGLM_INLINE +void +glm_quat_mat4t(versor q, mat4 dest) { + float w, x, y, z, + xx, yy, zz, + xy, yz, xz, + wx, wy, wz, norm, s; + + norm = glm_quat_norm(q); + s = norm > 0.0f ? 2.0f / norm : 0.0f; + + x = q[0]; + y = q[1]; + z = q[2]; + w = q[3]; + + xx = s * x * x; xy = s * x * y; wx = s * w * x; + yy = s * y * y; yz = s * y * z; wy = s * w * y; + zz = s * z * z; xz = s * x * z; wz = s * w * z; + + dest[0][0] = 1.0f - yy - zz; + dest[1][1] = 1.0f - xx - zz; + dest[2][2] = 1.0f - xx - yy; + + dest[1][0] = xy + wz; + dest[2][1] = yz + wx; + dest[0][2] = xz + wy; + + dest[0][1] = xy - wz; + dest[1][2] = yz - wx; + dest[2][0] = xz - wy; + + 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 convert quaternion to mat3 * @@ -432,6 +479,45 @@ glm_quat_mat3(versor q, mat3 dest) { dest[0][2] = xz - wy; } +/*! + * @brief convert quaternion to mat3 (transposed) + * + * @param[in] q quaternion + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_quat_mat3t(versor q, mat3 dest) { + float w, x, y, z, + xx, yy, zz, + xy, yz, xz, + wx, wy, wz, norm, s; + + norm = glm_quat_norm(q); + s = norm > 0.0f ? 2.0f / norm : 0.0f; + + x = q[0]; + y = q[1]; + z = q[2]; + w = q[3]; + + xx = s * x * x; xy = s * x * y; wx = s * w * x; + yy = s * y * y; yz = s * y * z; wy = s * w * y; + zz = s * z * z; xz = s * x * z; wz = s * w * z; + + dest[0][0] = 1.0f - yy - zz; + dest[1][1] = 1.0f - xx - zz; + dest[2][2] = 1.0f - xx - yy; + + dest[1][0] = xy + wz; + dest[2][1] = yz + wx; + dest[0][2] = xz + wy; + + dest[0][1] = xy - wz; + dest[1][2] = yz - wx; + dest[2][0] = xz - wy; +} + /*! * @brief interpolates between two quaternions * using linear interpolation (LERP) From 9466182c10f31882168240879a2c160913e86e54 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 10 Apr 2018 16:01:23 +0300 Subject: [PATCH 28/98] quat: create view wmatrix with quaternion helper --- include/cglm/quat.h | 27 +++++++++++++++++++++++++++ test/src/test_quat.c | 15 ++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/include/cglm/quat.h b/include/cglm/quat.h index ff3c38c..fa760b7 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -39,6 +39,8 @@ #include "common.h" #include "vec4.h" +#include "mat4.h" +#include "mat3.h" #ifdef CGLM_SSE_FP # include "simd/sse2/quat.h" @@ -578,4 +580,29 @@ glm_quat_slerp(versor from, versor to, float t, versor dest) { glm_vec4_scale(q1, 1.0f / sinTheta, dest); } +CGLM_INLINE +void +glm_mat4_mulv(mat4 m, vec4 v, vec4 dest); + +/*! + * @brief creates view matrix using quaternion as camera orientation + * + * @param[in] eye eye + * @param[in] ori orientation in world space as quaternion + * @param[out] dest view matrix + */ +CGLM_INLINE +void +glm_quat_look(vec3 eye, versor ori, mat4 dest) { + vec4 t; + + /* orientation */ + glm_quat_mat4t(ori, dest); + + /* translate */ + glm_vec4(eye, 1.0f, t); + glm_mat4_mulv(dest, t, t); + glm_vec_flipsign_to(t, dest[3]); +} + #endif /* cglm_quat_h */ diff --git a/test/src/test_quat.c b/test/src/test_quat.c index 723dea1..b5db10f 100644 --- a/test/src/test_quat.c +++ b/test/src/test_quat.c @@ -18,8 +18,9 @@ test_quat_mul_raw(versor p, versor q, versor dest) { void test_quat(void **state) { - mat4 inRot, outRot; + mat4 inRot, outRot, view1, view2; versor inQuat, outQuat, q3, q4; + vec3 eye; int i; for (i = 0; i < 1000; i++) { @@ -35,4 +36,16 @@ test_quat(void **state) { test_assert_quat_eq(q3, q4); } + + /* test lookat */ + test_rand_vec3(eye); + glm_quatv(q3, glm_rad(-90.0f), GLM_YUP); + + /* now X axis must be forward axis, Z must be right axis */ + glm_look(eye, GLM_XUP, GLM_YUP, view1); + + /* create view matrix with quaternion */ + glm_quat_look(eye, q3, view2); + + test_assert_mat4_eq2(view1, view2, 0.000009); } From 18ef0d7af187552eec187c5dfd38c74d5ebd1558 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 10 Apr 2018 16:52:52 +0300 Subject: [PATCH 29/98] quat: quaternion for look rotation ( from source point to dest point ) --- include/cglm/quat.h | 48 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/include/cglm/quat.h b/include/cglm/quat.h index fa760b7..fabce2d 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -605,4 +605,52 @@ glm_quat_look(vec3 eye, versor ori, mat4 dest) { glm_vec_flipsign_to(t, dest[3]); } +/*! + * @brief creates look rotation quaternion + * + * @param[in] fwd forward vector + * @param[in] up up vector + * @param[out] dest destination quaternion + */ +CGLM_INLINE +void +glm_quat_for(vec3 dir, vec3 fwd, vec3 up, versor dest) { + vec3 axis; + float dot, angle; + + dot = glm_vec_dot(dir, fwd); + if (fabsf(dot + 1.0f) < 0.000001f) { + glm_quat_init(dest, up[0], up[1], up[2], CGLM_PI); + return; + } + + if (fabsf(dot - 1.0f) < 0.000001f) { + glm_quat_identity(dest); + return; + } + + angle = acosf(dot); + glm_cross(fwd, dir, axis); + glm_normalize(axis); + + glm_quatv(dest, angle, axis); +} + +/*! + * @brief creates look rotation quaternion using source and + * destination positions p suffix stands for position + * + * @param[in] from source point + * @param[in] to destination point + * @param[in] up up vector + * @param[out] dest destination quaternion + */ +CGLM_INLINE +void +glm_quat_forp(vec3 from, vec3 to, vec3 fwd, vec3 up, versor dest) { + vec3 dir; + glm_vec_sub(to, from, dir); + glm_quat_for(dir, fwd, up, dest); +} + #endif /* cglm_quat_h */ From 4c79fee5d354ca12e18f2c31c6c2afaca20c7cb8 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 10 Apr 2018 17:16:31 +0300 Subject: [PATCH 30/98] quat: additional tests for angle, axis, mul (hamilton product) --- test/src/test_quat.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/test/src/test_quat.c b/test/src/test_quat.c index b5db10f..8f3909c 100644 --- a/test/src/test_quat.c +++ b/test/src/test_quat.c @@ -18,11 +18,12 @@ test_quat_mul_raw(versor p, versor q, versor dest) { void test_quat(void **state) { - mat4 inRot, outRot, view1, view2; - versor inQuat, outQuat, q3, q4; - vec3 eye; + mat4 inRot, outRot, view1, view2, rot1, rot2; + versor inQuat, outQuat, q3, q4, q5; + vec3 eye, axis; int i; + /* 1. test quat to mat and mat to quat */ for (i = 0; i < 1000; i++) { test_rand_quat(inQuat); glmc_quat_mat4(inQuat, inRot); @@ -37,7 +38,7 @@ test_quat(void **state) { test_assert_quat_eq(q3, q4); } - /* test lookat */ + /* 2. test lookat */ test_rand_vec3(eye); glm_quatv(q3, glm_rad(-90.0f), GLM_YUP); @@ -48,4 +49,32 @@ test_quat(void **state) { glm_quat_look(eye, q3, view2); test_assert_mat4_eq2(view1, view2, 0.000009); + + /* 5. test quaternion rotation matrix result */ + test_rand_quat(q3); + glm_quat_mat4(q3, rot1); + + /* 5.1 test axis and angle of quat */ + glm_quat_axis(q3, axis); + glm_rotate_make(rot2, glm_quat_angle(q3), axis); + + test_assert_mat4_eq2(rot1, rot2, 0.000009); + + /* 6. test quaternion multiplication, first rotation + second = final */ + test_rand_quat(q3); + test_rand_quat(q4); + + glm_quat_mul(q3, q4, q5); + + glm_quat_axis(q3, axis); + glm_rotate_make(rot1, glm_quat_angle(q3), axis); + + glm_quat_axis(q4, axis); + glm_rotate(rot1, glm_quat_angle(q4), axis); + + /* rot2 is combine of two rotation now test with quaternion result */ + glm_quat_mat4(q5, rot2); + + /* result must be same (almost) */ + test_assert_mat4_eq2(rot1, rot2, 0.000009); } From 5dec68823c850e59b4261d03ff7433045d4458f7 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 10 Apr 2018 17:41:25 +0300 Subject: [PATCH 31/98] add additional tests and comments to quat tests --- test/src/test_quat.c | 72 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 6 deletions(-) diff --git a/test/src/test_quat.c b/test/src/test_quat.c index 8f3909c..1c1502d 100644 --- a/test/src/test_quat.c +++ b/test/src/test_quat.c @@ -20,25 +20,34 @@ void test_quat(void **state) { mat4 inRot, outRot, view1, view2, rot1, rot2; versor inQuat, outQuat, q3, q4, q5; - vec3 eye, axis; + vec3 eye, axis, imag; int i; + /* 0. test identiy quat */ + glm_quat_identity(q4); + assert_true(glm_quat_real(q4) == cosf(glm_rad(0.0f) * 0.5f)); + /* 1. test quat to mat and mat to quat */ for (i = 0; i < 1000; i++) { test_rand_quat(inQuat); + glmc_quat_mat4(inQuat, inRot); glmc_mat4_quat(inRot, outQuat); glmc_quat_mat4(outQuat, outRot); + + /* 2. test first quat and generated one equality */ test_assert_quat_eq_abs(inQuat, outQuat); + + /* 3. test first rot and second rotation */ test_assert_mat4_eq2(inRot, outRot, 0.000009); /* almost equal */ + /* 4. test SSE mul and raw mul */ test_quat_mul_raw(inQuat, outQuat, q3); glm_quat_mul_sse2(inQuat, outQuat, q4); - test_assert_quat_eq(q3, q4); } - /* 2. test lookat */ + /* 5. test lookat */ test_rand_vec3(eye); glm_quatv(q3, glm_rad(-90.0f), GLM_YUP); @@ -50,17 +59,19 @@ test_quat(void **state) { test_assert_mat4_eq2(view1, view2, 0.000009); - /* 5. test quaternion rotation matrix result */ + /* 6. test quaternion rotation matrix result */ test_rand_quat(q3); glm_quat_mat4(q3, rot1); - /* 5.1 test axis and angle of quat */ + /* 6.1 test axis and angle of quat */ glm_quat_axis(q3, axis); glm_rotate_make(rot2, glm_quat_angle(q3), axis); test_assert_mat4_eq2(rot1, rot2, 0.000009); - /* 6. test quaternion multiplication, first rotation + second = final */ + /* 7. test quaternion multiplication (hamilton product), + final rotation = first rotation + second = quat1 * quat2 + */ test_rand_quat(q3); test_rand_quat(q4); @@ -77,4 +88,53 @@ test_quat(void **state) { /* result must be same (almost) */ test_assert_mat4_eq2(rot1, rot2, 0.000009); + + /* 8. test quaternion for look rotation */ + + /* 8.1 same direction */ + /* look at from 0, 0, 1 to zero, direction = 0, 0, -1 */ + glm_quat_for((vec3){0, 0, -1}, (vec3){0, 0, -1}, GLM_YUP, q3); + + /* result must be identity */ + glm_quat_identity(q4); + test_assert_quat_eq(q3, q4); + + /* look at from 0, 0, 1 to zero, direction = 0, 0, -1 */ + glm_quat_forp(GLM_ZUP, GLM_VEC3_ZERO, (vec3){0, 0, -1}, GLM_YUP, q3); + + /* result must be identity */ + glm_quat_identity(q4); + test_assert_quat_eq(q3, q4); + + /* 8.2 perpendicular */ + glm_quat_for(GLM_XUP, (vec3){0, 0, -1}, GLM_YUP, q3); + + /* result must be -90 */ + glm_quatv(q4, glm_rad(-90.0f), GLM_YUP); + test_assert_quat_eq(q3, q4); + + /* 9. test imag, real */ + + /* 9.1 real */ + assert_true(glm_quat_real(q4) == cosf(glm_rad(-90.0f) * 0.5f)); + + /* 9.1 imag */ + glm_quat_imag(q4, imag); + + /* axis = Y_UP * sinf(angle * 0.5), YUP = 0, 1, 0 */ + axis[0] = 0.0f; + axis[1] = sinf(glm_rad(-90.0f) * 0.5f) * 1.0f; + axis[2] = 0.0f; + + assert_true(glm_vec_eqv_eps(imag, axis)); + + /* 9.2 axis */ + glm_quat_axis(q4, axis); + imag[0] = 0.0f; + imag[1] = -1.0f; + imag[2] = 0.0f; + + assert_true(glm_vec_eqv_eps(imag, axis)); + + /* TODO: add tests for slerp, lerp */ } From 010dcc9837b2ebf5a9b0c4272ac87e5c307bd610 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Wed, 11 Apr 2018 00:17:41 +0300 Subject: [PATCH 32/98] optimize normalize quaternion with SIMD * provide _to version for storing into another quat --- include/cglm/quat.h | 48 ++++++++++++++++++++++++++++++-------- include/cglm/simd/intrin.h | 10 ++++++++ 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/include/cglm/quat.h b/include/cglm/quat.h index fabce2d..970b7f6 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -158,6 +158,43 @@ glm_quat_norm(versor q) { return glm_vec4_norm(q); } +/*! + * @brief normalize quaternion and store result in dest + * + * @param[in] q quaternion to normalze + * @param[out] dest destination quaternion + */ +CGLM_INLINE +void +glm_quat_normalize_to(versor q, versor dest) { +#if defined( __SSE2__ ) || defined( __SSE2__ ) + __m128 xdot, x0; + float dot; + + x0 = _mm_load_ps(q); + xdot = glm_simd_dot(x0, x0); + dot = _mm_cvtss_f32(xdot); + + if (dot <= 0.0f) { + glm_quat_identity(dest); + return; + } + + _mm_store_ps(dest, _mm_div_ps(x0, _mm_sqrt_ps(xdot))); +#else + float dot; + + dot = glm_vec4_norm2(q); + + if (dot <= 0.0f) { + glm_quat_identity(q); + return; + } + + glm_vec4_scale(q, 1.0f / sqrtf(dot), dest); +#endif +} + /*! * @brief normalize quaternion * @@ -166,16 +203,7 @@ glm_quat_norm(versor q) { CGLM_INLINE void glm_quat_normalize(versor q) { - float sum; - - sum = glm_vec4_norm2(q); - - if (sum <= 0.0f) { - glm_quat_identity(q); - return; - } - - glm_vec4_scale(q, 1.0f / sqrtf(sum), q); + glm_quat_normalize_to(q, q); } /*! diff --git a/include/cglm/simd/intrin.h b/include/cglm/simd/intrin.h index c0f2e53..4c27d90 100644 --- a/include/cglm/simd/intrin.h +++ b/include/cglm/simd/intrin.h @@ -30,6 +30,16 @@ # define _mm_shuffle2_ps(a, b, z0, y0, x0, w0, z1, y1, x1, w1) \ _mm_shuffle1_ps(_mm_shuffle_ps(a, b, _MM_SHUFFLE(z0, y0, x0, w0)), \ z1, y1, x1, w1) + +CGLM_INLINE +__m128 +glm_simd_dot(__m128 a, __m128 b) { + __m128 x0; + x0 = _mm_mul_ps(a, b); + x0 = _mm_add_ps(x0, _mm_shuffle1_ps(x0, 1, 0, 3, 2)); + return _mm_add_ps(x0, _mm_shuffle1_ps(x0, 0, 1, 0, 1)); +} + #endif /* x86, x64 */ From b1fa7ff597e8610d4b6e400dac0dfc28193bb021 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Wed, 11 Apr 2018 00:36:39 +0300 Subject: [PATCH 33/98] normalize axis quaternion axis-angle constructor --- include/cglm/quat.h | 59 +++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 32 deletions(-) diff --git a/include/cglm/quat.h b/include/cglm/quat.h index 970b7f6..effebae 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -89,6 +89,31 @@ glm_quat_init(versor q, float x, float y, float z, float w) { q[3] = w; } +/*! + * @brief creates NEW quaternion with axis vector + * + * @param[out] q quaternion + * @param[in] angle angle (radians) + * @param[in] axis axis + */ +CGLM_INLINE +void +glm_quatv(versor q, float angle, vec3 axis) { + vec3 k; + float a, c, s; + + a = angle * 0.5f; + c = cosf(a); + s = sinf(a); + + glm_normalize_to(axis, k); + + q[0] = s * k[0]; + q[1] = s * k[1]; + q[2] = s * k[2]; + q[3] = c; +} + /*! * @brief creates NEW quaternion with individual axis components * @@ -101,38 +126,8 @@ glm_quat_init(versor q, float x, float y, float z, float w) { CGLM_INLINE void glm_quat(versor q, float angle, float x, float y, float z) { - float a, c, s; - - a = angle * 0.5f; - c = cosf(a); - s = sinf(a); - - q[0] = s * x; - q[1] = s * y; - q[2] = s * z; - q[3] = c; -} - -/*! - * @brief creates NEW quaternion with axis vector - * - * @param[out] q quaternion - * @param[in] angle angle (radians) - * @param[in] axis axis - */ -CGLM_INLINE -void -glm_quatv(versor q, float angle, vec3 axis) { - float a, c, s; - - a = angle * 0.5f; - c = cosf(a); - s = sinf(a); - - q[0] = s * axis[0]; - q[1] = s * axis[1]; - q[2] = s * axis[2]; - q[3] = c; + vec3 axis = {x, y, z}; + glm_quatv(q, angle, axis); } /*! From d447876c70cc0cc4b9ab54595332a0e42d1a887a Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Wed, 11 Apr 2018 00:46:23 +0300 Subject: [PATCH 34/98] improve glm_vec_rotate --- include/cglm/vec3.h | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index cb94909..1cbf508 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -339,10 +339,6 @@ glm_vec_angle(vec3 v1, vec3 v2) { return acosf(glm_vec_dot(v1, v2) * norm); } -CGLM_INLINE -void -glm_quatv(versor q, float angle, vec3 axis); - /*! * @brief rotate vec3 around axis by angle using Rodrigues' rotation formula * @@ -353,31 +349,26 @@ glm_quatv(versor q, float angle, vec3 axis); CGLM_INLINE void glm_vec_rotate(vec3 v, float angle, vec3 axis) { - versor q; - vec3 v1, v2, v3; + vec3 v1, v2, k; float c, s; c = cosf(angle); s = sinf(angle); + glm_vec_normalize_to(axis, k); + /* Right Hand, Rodrigues' rotation formula: v = v*cos(t) + (kxv)sin(t) + k*(k.v)(1 - cos(t)) */ - - /* quaternion */ - glm_quatv(q, angle, v); - glm_vec_scale(v, c, v1); - glm_vec_cross(axis, v, v2); + glm_vec_cross(k, v, v2); glm_vec_scale(v2, s, v2); - glm_vec_scale(axis, - glm_vec_dot(axis, v) * (1.0f - c), - v3); - glm_vec_add(v1, v2, v1); - glm_vec_add(v1, v3, v); + + glm_vec_scale(k, glm_vec_dot(k, v) * (1.0f - c), v2); + glm_vec_add(v1, v2, v); } /*! From 80d255e6d9cce5b472b2b2f95ed4ef3be594e8c0 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Wed, 11 Apr 2018 00:47:11 +0300 Subject: [PATCH 35/98] rotate vector using quaternion --- CREDITS | 4 ++++ include/cglm/quat.h | 30 +++++++++++++++++++++++++++++- test/src/test_common.c | 14 +++++++------- test/src/test_quat.c | 22 ++++++++++++++++++++-- 4 files changed, 60 insertions(+), 10 deletions(-) diff --git a/CREDITS b/CREDITS index 66604eb..44e55a8 100644 --- a/CREDITS +++ b/CREDITS @@ -46,3 +46,7 @@ http://old.cescg.org/CESCG-2002/DSykoraJJelinek/ 7. Quaternions Initial mat4_quat is borrowed from Apple's simd library + + +8. Vector Rotation using Quaternion +https://gamedev.stackexchange.com/questions/28395/rotating-vector3-by-a-quaternion diff --git a/include/cglm/quat.h b/include/cglm/quat.h index effebae..664a069 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -168,7 +168,7 @@ glm_quat_normalize_to(versor q, versor dest) { x0 = _mm_load_ps(q); xdot = glm_simd_dot(x0, x0); - dot = _mm_cvtss_f32(xdot); + dot = _mm_cvtss_f32(xdot); if (dot <= 0.0f) { glm_quat_identity(dest); @@ -676,4 +676,32 @@ glm_quat_forp(vec3 from, vec3 to, vec3 fwd, vec3 up, versor dest) { glm_quat_for(dir, fwd, up, dest); } +/*! + * @brief rotate existing transform matrix using quaternion + * + * @param[in] q quaternion + * @param[in] v vector to rotate + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_quat_rotatev(versor q, vec3 v, vec3 dest) { + versor p; + vec3 u, v1, v2; + float s; + + glm_quat_normalize_to(q, p); + glm_quat_imag(p, u); + s = glm_quat_real(p); + + glm_vec_scale(u, 2.0f * glm_vec_dot(u, v), v1); + glm_vec_scale(v, s * s - glm_vec_dot(u, u), v2); + glm_vec_add(v1, v2, v1); + + glm_vec_cross(u, v, v2); + glm_vec_scale(v2, 2.0f * s, v2); + + glm_vec_add(v1, v2, dest); +} + #endif /* cglm_quat_h */ diff --git a/test/src/test_common.c b/test/src/test_common.c index bd6deaf..514c006 100644 --- a/test/src/test_common.c +++ b/test/src/test_common.c @@ -86,9 +86,9 @@ 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); /* rounding errors */ - assert_true(fabsf(v1[1] - v2[1]) <= 0.0000009); - assert_true(fabsf(v1[2] - v2[2]) <= 0.0000009); + assert_true(fabsf(v1[0] - v2[0]) <= 0.000009); /* rounding errors */ + assert_true(fabsf(v1[1] - v2[1]) <= 0.000009); + assert_true(fabsf(v1[2] - v2[2]) <= 0.000009); } void @@ -101,9 +101,9 @@ test_assert_quat_eq_abs(versor v1, versor v2) { void test_assert_quat_eq(versor v1, versor v2) { - assert_true(fabsf(v1[0] - v2[0]) <= 0.0000009); /* rounding errors */ - assert_true(fabsf(v1[1] - v2[1]) <= 0.0000009); - assert_true(fabsf(v1[2] - v2[2]) <= 0.0000009); - assert_true(fabsf(v1[3] - v2[3]) <= 0.0000009); + assert_true(fabsf(v1[0] - v2[0]) <= 0.000009); /* rounding errors */ + assert_true(fabsf(v1[1] - v2[1]) <= 0.000009); + assert_true(fabsf(v1[2] - v2[2]) <= 0.000009); + assert_true(fabsf(v1[3] - v2[3]) <= 0.000009); } diff --git a/test/src/test_quat.c b/test/src/test_quat.c index 1c1502d..43dbdb2 100644 --- a/test/src/test_quat.c +++ b/test/src/test_quat.c @@ -20,7 +20,7 @@ void test_quat(void **state) { mat4 inRot, outRot, view1, view2, rot1, rot2; versor inQuat, outQuat, q3, q4, q5; - vec3 eye, axis, imag; + vec3 eye, axis, imag, v1, v2; int i; /* 0. test identiy quat */ @@ -134,7 +134,25 @@ test_quat(void **state) { imag[1] = -1.0f; imag[2] = 0.0f; - assert_true(glm_vec_eqv_eps(imag, axis)); + test_assert_vec3_eq(imag, axis); + + /* 10. test rotate vector using quat */ + /* (0,0,-1) around (1,0,0) must give (0,1,0) */ + v1[0] = 0.0f; v1[1] = 0.0f; v1[2] = -1.0f; + v2[0] = 0.0f; v2[1] = 0.0f; v2[2] = -1.0f; + + glm_vec_rotate(v1, glm_rad(90.0f), (vec3){1.0f, 0.0f, 0.0f}); + glm_quatv(q3, glm_rad(90.0f), (vec3){1.0f, 0.0f, 0.0f}); + + glm_vec4_scale(q3, 1.5, q3); + glm_quat_rotatev(q3, v2, v2); + + /* result must be : (0,1,0) */ + assert_true(fabsf(v1[0]) <= 0.00009f + && fabsf(v1[1] - 1.0f) <= 0.00009f + && fabsf(v1[2]) <= 0.00009f); + + test_assert_vec3_eq(v1, v2); /* TODO: add tests for slerp, lerp */ } From fdea13507bbf63dd24d93294aee7a1dc21b9249e Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Wed, 11 Apr 2018 10:49:53 +0300 Subject: [PATCH 36/98] replace mat4_mulq with glm_quat_rotate * glm_quat_rotate is better name to rotate transform matrix using quaternion. * we may use mat4_mulq in the future for another purpose e.g. left multiplication quat with matrix --- include/cglm/call/mat4.h | 4 ---- include/cglm/mat4.h | 15 -------------- include/cglm/quat.h | 45 ++++++++++++++++++++++++++++++++++------ src/mat4.c | 6 ------ test/src/test_quat.c | 30 +++++++++++++++++++++++++++ 5 files changed, 69 insertions(+), 31 deletions(-) diff --git a/include/cglm/call/mat4.h b/include/cglm/call/mat4.h index 35b9f66..c9ad796 100644 --- a/include/cglm/call/mat4.h +++ b/include/cglm/call/mat4.h @@ -53,10 +53,6 @@ CGLM_EXPORT void glmc_mat4_mulv(mat4 m, vec4 v, vec4 dest); -CGLM_EXPORT -void -glmc_mat4_mulq(mat4 m, versor q, mat4 dest); - CGLM_EXPORT void glmc_mat4_quat(mat4 m, versor dest); diff --git a/include/cglm/mat4.h b/include/cglm/mat4.h index fd7a340..27ebe05 100644 --- a/include/cglm/mat4.h +++ b/include/cglm/mat4.h @@ -319,21 +319,6 @@ glm_mat4_mulv(mat4 m, vec4 v, vec4 dest) { #endif } -/*! - * @brief multiply mat4 with quaternion and store in dest vector - * - * @param[in] m left matrix - * @param[in] q quaternion as right matrix - * @param[out] dest destination matrix - */ -CGLM_INLINE -void -glm_mat4_mulq(mat4 m, versor q, mat4 dest) { - mat4 rot; - glm_quat_mat4(q, rot); - glm_mat4_mul(m, rot, dest); -} - /*! * @brief convert mat4's rotation part to quaternion * diff --git a/include/cglm/quat.h b/include/cglm/quat.h index 664a069..95a768e 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -15,8 +15,10 @@ CGLM_INLINE void glm_quat_init(versor q, float x, float y, float z, float w); CGLM_INLINE void glm_quat(versor q, float angle, float x, float y, float z); CGLM_INLINE void glm_quatv(versor q, float angle, vec3 axis); + CGLM_INLINE void glm_quat_copy(versor q, versor dest); CGLM_INLINE float glm_quat_norm(versor q); CGLM_INLINE void glm_quat_normalize(versor q); + CGLM_INLINE void glm_quat_normalize_to(versor q, versor dest); CGLM_INLINE float glm_quat_dot(versor q1, versor q2); CGLM_INLINE void glm_quat_conjugate(versor q, versor dest); CGLM_INLINE void glm_quat_inv(versor q, versor dest); @@ -30,8 +32,20 @@ CGLM_INLINE void glm_quat_axis(versor q, versor dest); CGLM_INLINE void glm_quat_mul(versor p, versor q, versor dest); CGLM_INLINE void glm_quat_mat4(versor q, mat4 dest); - CGLM_INLINE void glm_quat_mat3(versor q, mat3 dest) + CGLM_INLINE void glm_quat_mat4t(versor q, mat4 dest); + CGLM_INLINE void glm_quat_mat3(versor q, mat3 dest); + CGLM_INLINE void glm_quat_mat3t(versor q, mat3 dest); + CGLM_INLINE void glm_quat_lerp(versor from, versor to, float t, versor dest); CGLM_INLINE void glm_quat_slerp(versor q, versor r, float t, versor dest); + CGLM_INLINE void glm_quat_look(vec3 eye, versor ori, mat4 dest); + CGLM_INLINE void glm_quat_for(vec3 dir, vec3 fwd, vec3 up, versor dest); + CGLM_INLINE void glm_quat_forp(vec3 from, + vec3 to, + vec3 fwd, + vec3 up, + versor dest); + CGLM_INLINE void glm_quat_rotatev(versor q, vec3 v, vec3 dest); + CGLM_INLINE void glm_quat_rotate(mat4 m, versor q, mat4 dest); */ #ifndef cglm_quat_h @@ -46,6 +60,14 @@ # include "simd/sse2/quat.h" #endif +CGLM_INLINE +void +glm_mat4_mulv(mat4 m, vec4 v, vec4 dest); + +CGLM_INLINE +void +glm_mat4_mul(mat4 m1, mat4 m2, mat4 dest); + /* * IMPORTANT: * ---------------------------------------------------------------------------- @@ -603,10 +625,6 @@ glm_quat_slerp(versor from, versor to, float t, versor dest) { glm_vec4_scale(q1, 1.0f / sinTheta, dest); } -CGLM_INLINE -void -glm_mat4_mulv(mat4 m, vec4 v, vec4 dest); - /*! * @brief creates view matrix using quaternion as camera orientation * @@ -677,7 +695,7 @@ glm_quat_forp(vec3 from, vec3 to, vec3 fwd, vec3 up, versor dest) { } /*! - * @brief rotate existing transform matrix using quaternion + * @brief rotate vector using using quaternion * * @param[in] q quaternion * @param[in] v vector to rotate @@ -704,4 +722,19 @@ glm_quat_rotatev(versor q, vec3 v, vec3 dest) { glm_vec_add(v1, v2, dest); } +/*! + * @brief rotate existing transform matrix using quaternion + * + * @param[in] m existing transform matrix + * @param[in] q quaternion + * @param[out] dest destination matrix + */ +CGLM_INLINE +void +glm_quat_rotate(mat4 m, versor q, mat4 dest) { + mat4 rot; + glm_quat_mat4(q, rot); + glm_mat4_mul(m, rot, dest); +} + #endif /* cglm_quat_h */ diff --git a/src/mat4.c b/src/mat4.c index 8b2a2d0..9407684 100644 --- a/src/mat4.c +++ b/src/mat4.c @@ -62,12 +62,6 @@ glmc_mat4_mulv(mat4 m, vec4 v, vec4 dest) { glm_mat4_mulv(m, v, dest); } -CGLM_EXPORT -void -glmc_mat4_mulq(mat4 m, versor q, mat4 dest) { - glm_mat4_mulq(m, q, dest); -} - CGLM_EXPORT void glmc_mat4_quat(mat4 m, versor dest) { diff --git a/test/src/test_quat.c b/test/src/test_quat.c index 43dbdb2..fec8dae 100644 --- a/test/src/test_quat.c +++ b/test/src/test_quat.c @@ -154,5 +154,35 @@ test_quat(void **state) { test_assert_vec3_eq(v1, v2); + /* 11. test rotate transform */ + glm_translate_make(rot1, (vec3){-10.0, 45.0f, 8.0f}); + glm_rotate(rot1, glm_rad(-90), GLM_ZUP); + + glm_quatv(q3, glm_rad(-90.0f), GLM_ZUP); + glm_translate_make(rot2, (vec3){-10.0, 45.0f, 8.0f}); + glm_quat_rotate(rot2, q3, rot2); + + /* result must be same (almost) */ + test_assert_mat4_eq2(rot1, rot2, 0.000009); + + glm_rotate_make(rot1, glm_rad(-90), GLM_ZUP); + glm_translate(rot1, (vec3){-10.0, 45.0f, 8.0f}); + + glm_quatv(q3, glm_rad(-90.0f), GLM_ZUP); + glm_mat4_identity(rot2); + glm_quat_rotate(rot2, q3, rot2); + glm_translate(rot2, (vec3){-10.0, 45.0f, 8.0f}); + + /* result must be same (almost) */ + test_assert_mat4_eq2(rot1, rot2, 0.000009); + + /* reverse */ + glm_rotate_make(rot1, glm_rad(-90), GLM_ZUP); + glm_quatv(q3, glm_rad(90.0f), GLM_ZUP); + glm_quat_rotate(rot1, q3, rot1); + + /* result must be identity */ + test_assert_mat4_eq2(rot1, GLM_MAT4_IDENTITY, 0.000009); + /* TODO: add tests for slerp, lerp */ } From 51278b26b4ea5c9c8734777c7709da5b9bc65ef8 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Wed, 11 Apr 2018 11:19:13 +0300 Subject: [PATCH 37/98] quat: update call versions of quaternion --- include/cglm/call/quat.h | 88 +++++++++++++++++++++++- include/cglm/quat.h | 4 +- src/quat.c | 141 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 222 insertions(+), 11 deletions(-) diff --git a/include/cglm/call/quat.h b/include/cglm/call/quat.h index ee45f0c..d250f52 100644 --- a/include/cglm/call/quat.h +++ b/include/cglm/call/quat.h @@ -17,25 +17,77 @@ CGLM_EXPORT void glmc_quat_identity(versor q); +CGLM_EXPORT +void +glmc_quat_init(versor q, float x, float y, float z, float w); + CGLM_EXPORT void glmc_quat(versor q, float angle, float x, float y, float z); CGLM_EXPORT void -glmc_quatv(versor q, float angle, vec3 v); +glmc_quatv(versor q, float angle, vec3 axis); + +CGLM_EXPORT +void +glmc_quat_copy(versor q, versor dest); CGLM_EXPORT float glmc_quat_norm(versor q); +CGLM_EXPORT +void +glmc_quat_normalize_to(versor q, versor dest); + CGLM_EXPORT void glmc_quat_normalize(versor q); CGLM_EXPORT float -glmc_quat_dot(versor q, versor r); +glmc_quat_dot(versor p, versor q); + +CGLM_EXPORT +void +glmc_quat_conjugate(versor q, versor dest); + +CGLM_EXPORT +void +glmc_quat_inv(versor q, versor dest); + +CGLM_EXPORT +void +glmc_quat_add(versor p, versor q, versor dest); + +CGLM_EXPORT +void +glmc_quat_sub(versor p, versor q, versor dest); + +CGLM_EXPORT +float +glmc_quat_real(versor q); + +CGLM_EXPORT +void +glmc_quat_imag(versor q, vec3 dest); + +CGLM_EXPORT +void +glmc_quat_imagn(versor q, vec3 dest); + +CGLM_EXPORT +float +glmc_quat_imaglen(versor q); + +CGLM_EXPORT +float +glmc_quat_angle(versor q); + +CGLM_EXPORT +void +glmc_quat_axis(versor q, versor dest); CGLM_EXPORT void @@ -45,14 +97,46 @@ CGLM_EXPORT void glmc_quat_mat4(versor q, mat4 dest); +CGLM_EXPORT +void +glmc_quat_mat4t(versor q, mat4 dest); + CGLM_EXPORT void glmc_quat_mat3(versor q, mat3 dest); +CGLM_EXPORT +void +glmc_quat_mat3t(versor q, mat3 dest); + +CGLM_EXPORT +void +glmc_quat_lerp(versor from, versor to, float t, versor dest); + CGLM_EXPORT void glmc_quat_slerp(versor q, versor r, float t, versor dest); +CGLM_EXPORT +void +glmc_quat_look(vec3 eye, versor ori, mat4 dest); + +CGLM_EXPORT +void +glmc_quat_for(vec3 dir, vec3 fwd, vec3 up, versor dest); + +CGLM_EXPORT +void +glmc_quat_forp(vec3 from, vec3 to, vec3 fwd, vec3 up, versor dest); + +CGLM_EXPORT +void +glmc_quat_rotatev(versor from, vec3 to, vec3 dest); + +CGLM_EXPORT +void +glmc_quat_rotate(mat4 m, versor q, mat4 dest); + #ifdef __cplusplus } #endif diff --git a/include/cglm/quat.h b/include/cglm/quat.h index 95a768e..c9927bb 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -231,8 +231,8 @@ glm_quat_normalize(versor q) { */ CGLM_INLINE float -glm_quat_dot(versor q1, versor q2) { - return glm_vec4_dot(q1, q2); +glm_quat_dot(versor p, versor q) { + return glm_vec4_dot(p, q); } /*! diff --git a/src/quat.c b/src/quat.c index b1cfe90..8a9a463 100644 --- a/src/quat.c +++ b/src/quat.c @@ -8,12 +8,19 @@ #include "../include/cglm/cglm.h" #include "../include/cglm/call.h" + CGLM_EXPORT void glmc_quat_identity(versor q) { glm_quat_identity(q); } +CGLM_EXPORT +void +glmc_quat_init(versor q, float x, float y, float z, float w) { + glm_quat_init(q, x, y, z, w); +} + CGLM_EXPORT void glmc_quat(versor q, float angle, float x, float y, float z) { @@ -22,8 +29,14 @@ glmc_quat(versor q, float angle, float x, float y, float z) { CGLM_EXPORT void -glmc_quatv(versor q, float angle, vec3 v) { - glm_quatv(q, angle, v); +glmc_quatv(versor q, float angle, vec3 axis) { + glm_quatv(q, angle, axis); +} + +CGLM_EXPORT +void +glmc_quat_copy(versor q, versor dest) { + glm_quat_copy(q, dest); } CGLM_EXPORT @@ -32,16 +45,82 @@ glmc_quat_norm(versor q) { return glm_quat_norm(q); } +CGLM_EXPORT +void +glmc_quat_normalize_to(versor q, versor dest) { + glm_quat_normalize_to(q, dest); +} + CGLM_EXPORT void glmc_quat_normalize(versor q) { - glm_quat_normalize(q); + glm_quat_norm(q); } CGLM_EXPORT float -glmc_quat_dot(versor q, versor r) { - return glm_quat_dot(q, r); +glmc_quat_dot(versor p, versor q) { + return glm_quat_dot(p, q); +} + +CGLM_EXPORT +void +glmc_quat_conjugate(versor q, versor dest) { + glm_quat_conjugate(q, dest); +} + +CGLM_EXPORT +void +glmc_quat_inv(versor q, versor dest) { + glm_quat_inv(q, dest); +} + +CGLM_EXPORT +void +glmc_quat_add(versor p, versor q, versor dest) { + glm_quat_add(p, q, dest); +} + +CGLM_EXPORT +void +glmc_quat_sub(versor p, versor q, versor dest) { + glm_quat_sub(p, q, dest); +} + +CGLM_EXPORT +float +glmc_quat_real(versor q) { + return glm_quat_real(q); +} + +CGLM_EXPORT +void +glmc_quat_imag(versor q, vec3 dest) { + glm_quat_imag(q, dest); +} + +CGLM_EXPORT +void +glmc_quat_imagn(versor q, vec3 dest) { + glm_quat_imagn(q, dest); +} + +CGLM_EXPORT +float +glmc_quat_imaglen(versor q) { + return glm_quat_imaglen(q); +} + +CGLM_EXPORT +float +glmc_quat_angle(versor q) { + return glm_quat_angle(q); +} + +CGLM_EXPORT +void +glmc_quat_axis(versor q, versor dest) { + glm_quat_axis(q, dest); } CGLM_EXPORT @@ -56,6 +135,12 @@ glmc_quat_mat4(versor q, mat4 dest) { glm_quat_mat4(q, dest); } +CGLM_EXPORT +void +glmc_quat_mat4t(versor q, mat4 dest) { + glm_quat_mat4t(q, dest); +} + CGLM_EXPORT void glmc_quat_mat3(versor q, mat3 dest) { @@ -64,6 +149,48 @@ glmc_quat_mat3(versor q, mat3 dest) { CGLM_EXPORT void -glmc_quat_slerp(versor q, versor r, float t, versor dest) { - glm_quat_slerp(q, r, t, dest); +glmc_quat_mat3t(versor q, mat3 dest) { + glm_quat_mat3t(q, dest); +} + +CGLM_EXPORT +void +glmc_quat_lerp(versor from, versor to, float t, versor dest) { + glm_quat_lerp(from, to, t, dest); +} + +CGLM_EXPORT +void +glmc_quat_slerp(versor from, versor to, float t, versor dest) { + glm_quat_slerp(from, to, t, dest); +} + +CGLM_EXPORT +void +glmc_quat_look(vec3 eye, versor ori, mat4 dest) { + glm_quat_look(eye, ori, dest); +} + +CGLM_EXPORT +void +glmc_quat_for(vec3 dir, vec3 fwd, vec3 up, versor dest) { + glm_quat_for(dir, fwd, up, dest); +} + +CGLM_EXPORT +void +glmc_quat_forp(vec3 from, vec3 to, vec3 fwd, vec3 up, versor dest) { + glm_quat_forp(from, to, fwd, up, dest); +} + +CGLM_EXPORT +void +glmc_quat_rotatev(versor q, vec3 v, vec3 dest) { + glm_quat_rotatev(q, v, dest); +} + +CGLM_EXPORT +void +glmc_quat_rotate(mat4 m, versor q, mat4 dest) { + glm_quat_rotate(m, q, dest); } From de5585013657d91b4268a362eade2c73f7b9d298 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Wed, 11 Apr 2018 12:31:29 +0300 Subject: [PATCH 38/98] add call version of vector extensions --- include/cglm/call/vec3.h | 74 ++++++++++++++++++++++++++ include/cglm/call/vec4.h | 70 +++++++++++++++++++++++++ include/cglm/vec3-ext.h | 2 +- src/vec3.c | 110 +++++++++++++++++++++++++++++++++++++++ src/vec4.c | 104 ++++++++++++++++++++++++++++++++++++ 5 files changed, 359 insertions(+), 1 deletion(-) diff --git a/include/cglm/call/vec3.h b/include/cglm/call/vec3.h index 461de0b..e79ec8f 100644 --- a/include/cglm/call/vec3.h +++ b/include/cglm/call/vec3.h @@ -16,6 +16,10 @@ extern "C" { /* DEPRECATED! use _copy, _ucopy versions */ #define glmc_vec_dup(v, dest) glmc_vec_copy(v, dest) +CGLM_EXPORT +void +glmc_vec3(vec4 v4, vec3 dest); + CGLM_EXPORT void glmc_vec_copy(vec3 a, vec3 dest); @@ -64,6 +68,10 @@ CGLM_EXPORT void glmc_vec_flipsign(vec3 v); +CGLM_EXPORT +void +glmc_vec_flipsign_to(vec3 v, vec3 dest); + CGLM_EXPORT void glmc_vec_inv(vec3 v); @@ -108,6 +116,72 @@ CGLM_EXPORT void glmc_vec_clamp(vec3 v, float minVal, float maxVal); +CGLM_EXPORT +void +glmc_vec_ortho(vec3 v, vec3 dest); + +CGLM_EXPORT +void +glmc_vec_lerp(vec3 from, vec3 to, float t, vec3 dest); + +/* ext */ + +CGLM_EXPORT +void +glmc_vec_mulv(vec3 a, vec3 b, vec3 d); + +CGLM_EXPORT +void +glmc_vec_broadcast(float val, vec3 d); + +CGLM_EXPORT +bool +glmc_vec_eq(vec3 v, float val); + +CGLM_EXPORT +bool +glmc_vec_eq_eps(vec3 v, float val); + +CGLM_EXPORT +bool +glmc_vec_eq_all(vec3 v); + +CGLM_EXPORT +bool +glmc_vec_eqv(vec3 v1, vec3 v2); + +CGLM_EXPORT +bool +glmc_vec_eqv_eps(vec3 v1, vec3 v2); + +CGLM_EXPORT +float +glmc_vec_max(vec3 v); + +CGLM_EXPORT +float +glmc_vec_min(vec3 v); + +CGLM_EXPORT +bool +glmc_vec_isnan(vec3 v); + +CGLM_EXPORT +bool +glmc_vec_isinf(vec3 v); + +CGLM_EXPORT +bool +glmc_vec_isvalid(vec3 v); + +CGLM_EXPORT +void +glmc_vec_sign(vec3 v, vec3 dest); + +CGLM_EXPORT +void +glmc_vec_sqrt(vec3 v, vec3 dest); + #ifdef __cplusplus } #endif diff --git a/include/cglm/call/vec4.h b/include/cglm/call/vec4.h index b63af80..ad915e6 100644 --- a/include/cglm/call/vec4.h +++ b/include/cglm/call/vec4.h @@ -17,6 +17,10 @@ extern "C" { #define glmc_vec4_dup3(v, dest) glmc_vec4_copy3(v, dest) #define glmc_vec4_dup(v, dest) glmc_vec4_copy(v, dest) +CGLM_EXPORT +void +glmc_vec4(vec3 v3, float last, vec4 dest); + CGLM_EXPORT void glmc_vec4_copy3(vec4 a, vec3 dest); @@ -65,6 +69,10 @@ CGLM_EXPORT void glmc_vec4_flipsign(vec4 v); +CGLM_EXPORT +void +glmc_vec4_flipsign_to(vec4 v, vec4 dest); + CGLM_EXPORT void glmc_vec4_inv(vec4 v); @@ -89,6 +97,68 @@ CGLM_EXPORT void glmc_vec4_clamp(vec4 v, float minVal, float maxVal); +CGLM_EXPORT +void +glmc_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest); + +/* ext */ + +CGLM_EXPORT +void +glmc_vec4_mulv(vec4 a, vec4 b, vec4 d); + +CGLM_EXPORT +void +glmc_vec4_broadcast(float val, vec4 d); + +CGLM_EXPORT +bool +glmc_vec4_eq(vec4 v, float val); + +CGLM_EXPORT +bool +glmc_vec4_eq_eps(vec4 v, float val); + +CGLM_EXPORT +bool +glmc_vec4_eq_all(vec4 v); + +CGLM_EXPORT +bool +glmc_vec4_eqv(vec4 v1, vec4 v2); + +CGLM_EXPORT +bool +glmc_vec4_eqv_eps(vec4 v1, vec4 v2); + +CGLM_EXPORT +float +glmc_vec4_max(vec4 v); + +CGLM_EXPORT +float +glmc_vec4_min(vec4 v); + +CGLM_EXPORT +bool +glmc_vec4_isnan(vec4 v); + +CGLM_EXPORT +bool +glmc_vec4_isinf(vec4 v); + +CGLM_EXPORT +bool +glmc_vec4_isvalid(vec4 v); + +CGLM_EXPORT +void +glmc_vec4_sign(vec4 v, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_sqrt(vec4 v, vec4 dest); + #ifdef __cplusplus } #endif diff --git a/include/cglm/vec3-ext.h b/include/cglm/vec3-ext.h index afc853e..fb2a687 100644 --- a/include/cglm/vec3-ext.h +++ b/include/cglm/vec3-ext.h @@ -220,7 +220,7 @@ glm_vec_sign(vec3 v, vec3 dest) { */ CGLM_INLINE void -glm_vec_sqrt(vec4 v, vec4 dest) { +glm_vec_sqrt(vec3 v, vec3 dest) { dest[0] = sqrtf(v[0]); dest[1] = sqrtf(v[1]); dest[2] = sqrtf(v[2]); diff --git a/src/vec3.c b/src/vec3.c index ebc677d..f7e2692 100644 --- a/src/vec3.c +++ b/src/vec3.c @@ -8,6 +8,12 @@ #include "../include/cglm/cglm.h" #include "../include/cglm/call.h" +CGLM_EXPORT +void +glmc_vec3(vec4 v4, vec3 dest) { + glm_vec3(v4, dest); +} + CGLM_EXPORT void glmc_vec_copy(vec3 a, vec3 dest) { @@ -80,6 +86,12 @@ glmc_vec_flipsign(vec3 v) { glm_vec_flipsign(v); } +CGLM_EXPORT +void +glmc_vec_flipsign_to(vec3 v, vec3 dest) { + glm_vec_flipsign_to(v, dest); +} + CGLM_EXPORT void glmc_vec_inv(vec3 v) { @@ -145,3 +157,101 @@ void glmc_vec_clamp(vec3 v, float minVal, float maxVal) { glm_vec_clamp(v, minVal, maxVal); } + +CGLM_EXPORT +void +glmc_vec_ortho(vec3 v, vec3 dest) { + glm_vec_ortho(v, dest); +} + +CGLM_EXPORT +void +glmc_vec_lerp(vec3 from, vec3 to, float t, vec3 dest) { + glm_vec_lerp(from, to, t, dest); +} + +/* ext */ + +CGLM_EXPORT +void +glmc_vec_mulv(vec3 a, vec3 b, vec3 d) { + glm_vec_mulv(a, b, d); +} + +CGLM_EXPORT +void +glmc_vec_broadcast(float val, vec3 d) { + glm_vec_broadcast(val, d); +} + +CGLM_EXPORT +bool +glmc_vec_eq(vec3 v, float val) { + return glm_vec_eq(v, val); +} + +CGLM_EXPORT +bool +glmc_vec_eq_eps(vec3 v, float val) { + return glm_vec_eq_eps(v, val); +} + +CGLM_EXPORT +bool +glmc_vec_eq_all(vec3 v) { + return glm_vec_eq_all(v); +} + +CGLM_EXPORT +bool +glmc_vec_eqv(vec3 v1, vec3 v2) { + return glm_vec_eqv(v1, v2); +} + +CGLM_EXPORT +bool +glmc_vec_eqv_eps(vec3 v1, vec3 v2) { + return glm_vec_eqv_eps(v1, v2); +} + +CGLM_EXPORT +float +glmc_vec_max(vec3 v) { + return glm_vec_max(v); +} + +CGLM_EXPORT +float +glmc_vec_min(vec3 v) { + return glm_vec_min(v); +} + +CGLM_EXPORT +bool +glmc_vec_isnan(vec3 v) { + return glm_vec_isnan(v); +} + +CGLM_EXPORT +bool +glmc_vec_isinf(vec3 v) { + return glm_vec_isinf(v); +} + +CGLM_EXPORT +bool +glmc_vec_isvalid(vec3 v) { + return glm_vec_isvalid(v); +} + +CGLM_EXPORT +void +glmc_vec_sign(vec3 v, vec3 dest) { + glm_vec_sign(v, dest); +} + +CGLM_EXPORT +void +glmc_vec_sqrt(vec3 v, vec3 dest) { + glm_vec_sqrt(v, dest); +} diff --git a/src/vec4.c b/src/vec4.c index f5f6a06..7228070 100644 --- a/src/vec4.c +++ b/src/vec4.c @@ -8,6 +8,12 @@ #include "../include/cglm/cglm.h" #include "../include/cglm/call.h" +CGLM_EXPORT +void +glmc_vec4(vec3 v3, float last, vec4 dest) { + glm_vec4(v3, last, dest); +} + CGLM_EXPORT void glmc_vec4_copy3(vec4 a, vec3 dest) { @@ -80,6 +86,12 @@ glmc_vec4_flipsign(vec4 v) { glm_vec4_flipsign(v); } +CGLM_EXPORT +void +glmc_vec4_flipsign_to(vec4 v, vec4 dest) { + glm_vec4_flipsign_to(v, dest); +} + CGLM_EXPORT void glmc_vec4_inv(vec4 v) { @@ -115,3 +127,95 @@ void glmc_vec4_clamp(vec4 v, float minVal, float maxVal) { glm_vec4_clamp(v, minVal, maxVal); } + +CGLM_EXPORT +void +glmc_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest) { + glm_vec4_lerp(from, to, t, dest); +} + +/* ext */ + +CGLM_EXPORT +void +glmc_vec4_mulv(vec4 a, vec4 b, vec4 d) { + glm_vec4_mulv(a, b, d); +} + +CGLM_EXPORT +void +glmc_vec4_broadcast(float val, vec4 d) { + glm_vec4_broadcast(val, d); +} + +CGLM_EXPORT +bool +glmc_vec4_eq(vec4 v, float val) { + return glm_vec4_eq(v, val); +} + +CGLM_EXPORT +bool +glmc_vec4_eq_eps(vec4 v, float val) { + return glm_vec4_eq_eps(v, val); +} + +CGLM_EXPORT +bool +glmc_vec4_eq_all(vec4 v) { + return glm_vec4_eq_all(v); +} + +CGLM_EXPORT +bool +glmc_vec4_eqv(vec4 v1, vec4 v2) { + return glm_vec4_eqv(v1, v2); +} + +CGLM_EXPORT +bool +glmc_vec4_eqv_eps(vec4 v1, vec4 v2) { + return glm_vec4_eqv_eps(v1, v2); +} + +CGLM_EXPORT +float +glmc_vec4_max(vec4 v) { + return glm_vec4_max(v); +} + +CGLM_EXPORT +float +glmc_vec4_min(vec4 v) { + return glm_vec4_min(v); +} + +CGLM_EXPORT +bool +glmc_vec4_isnan(vec4 v) { + return glm_vec4_isnan(v); +} + +CGLM_EXPORT +bool +glmc_vec4_isinf(vec4 v) { + return glm_vec4_isinf(v); +} + +CGLM_EXPORT +bool +glmc_vec4_isvalid(vec4 v) { + return glm_vec4_isvalid(v); +} + +CGLM_EXPORT +void +glmc_vec4_sign(vec4 v, vec4 dest) { + glm_vec4_sign(v, dest); +} + +CGLM_EXPORT +void +glmc_vec4_sqrt(vec4 v, vec4 dest) { + glm_vec4_sqrt(v, dest); +} From 0e63c245d437a8d192d7892e60a3405fcef4a020 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Wed, 11 Apr 2018 12:34:20 +0300 Subject: [PATCH 39/98] update docs --- docs/source/quat.rst | 274 ++++++++++++++++++++++++++++++++++++--- docs/source/util.rst | 15 +++ docs/source/vec3-ext.rst | 45 +++++++ docs/source/vec3.rst | 26 +++- docs/source/vec4-ext.rst | 40 ++++++ docs/source/vec4.rst | 27 ++++ include/cglm/quat.h | 11 +- include/cglm/vec3.h | 2 +- include/cglm/vec4-ext.h | 4 +- 9 files changed, 414 insertions(+), 30 deletions(-) diff --git a/docs/source/quat.rst b/docs/source/quat.rst index 863eed5..ab99838 100644 --- a/docs/source/quat.rst +++ b/docs/source/quat.rst @@ -5,17 +5,16 @@ quaternions Header: cglm/quat.h - **Important:** *cglm* stores quaternion as [w, x, y, z] in memory, don't - forget that when changing quaternion items manually. For instance *quat[3]* - is *quat.z* and *quat[0*] is *quat.w*. This may change in the future if *cglm* - will got enough request to do that. Probably it will not be changed in near - future + **Important:** *cglm* stores quaternion as **[x, y, z, w]** in memory + since **v0.4.0** it was **[w, x, y, z]** + before v0.4.0 ( **v0.3.5 and earlier** ). w is real part. -There are some TODOs for quaternions check TODO list to see them. +What you can do with quaternions with existing functions is (Some of them): -Also **versor** is identity quaternion so the type may change to **vec4** or -something else. This will not affect existing functions for your engine because -*versor* is alias of *vec4* +- You can rotate transform matrix using quaterion +- You can rotate vector using quaterion +- You can create view matrix using quaterion +- You can create a lookrotation (from source point to dest) Table of contents (click to go): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -28,14 +27,35 @@ Macros: Functions: 1. :c:func:`glm_quat_identity` +#. :c:func:`glm_quat_init` #. :c:func:`glm_quat` #. :c:func:`glm_quatv` +#. :c:func:`glm_quat_copy` #. :c:func:`glm_quat_norm` #. :c:func:`glm_quat_normalize` +#. :c:func:`glm_quat_normalize_to` #. :c:func:`glm_quat_dot` -#. :c:func:`glm_quat_mulv` +#. :c:func:`glm_quat_conjugate` +#. :c:func:`glm_quat_inv` +#. :c:func:`glm_quat_add` +#. :c:func:`glm_quat_sub` +#. :c:func:`glm_quat_real` +#. :c:func:`glm_quat_imag` +#. :c:func:`glm_quat_imagn` +#. :c:func:`glm_quat_imaglen` +#. :c:func:`glm_quat_angle` +#. :c:func:`glm_quat_axis` +#. :c:func:`glm_quat_mul` #. :c:func:`glm_quat_mat4` +#. :c:func:`glm_quat_mat4t` +#. :c:func:`glm_quat_mat3` +#. :c:func:`glm_quat_mat3t` +#. :c:func:`glm_quat_lerp` #. :c:func:`glm_quat_slerp` +#. :c:func:`glm_quat_look` +#. :c:func:`glm_quat_for` +#. :c:func:`glm_quat_forp` +#. :c:func:`glm_quat_rotatev` Functions documentation ~~~~~~~~~~~~~~~~~~~~~~~ @@ -47,10 +67,23 @@ Functions documentation Parameters: | *[in, out]* **q** quaternion +.. c:function:: void glm_quat_init(versor q, float x, float y, float z, float w) + + | inits quaternion with given values + + Parameters: + | *[out]* **q** quaternion + | *[in]* **x** imag.x + | *[in]* **y** imag.y + | *[in]* **z** imag.z + | *[in]* **w** w (real part) + .. c:function:: void glm_quat(versor q, float angle, float x, float y, float z) | creates NEW quaternion with individual axis components + | given axis will be normalized + Parameters: | *[out]* **q** quaternion | *[in]* **angle** angle (radians) @@ -58,14 +91,24 @@ Functions documentation | *[in]* **y** axis.y | *[in]* **z** axis.z -.. c:function:: void glm_quatv(versor q, float angle, vec3 v) +.. c:function:: void glm_quatv(versor q, float angle, vec3 axis) | creates NEW quaternion with axis vector + | given axis will be normalized + Parameters: | *[out]* **q** quaternion | *[in]* **angle** angle (radians) - | *[in]* **v** axis + | *[in]* **axis** axis (will be normalized) + +.. c:function:: void glm_quat_copy(versor q, versor dest) + + | copy quaternion to another one + + Parameters: + | *[in]* **q** source quaternion + | *[out]* **dest** destination quaternion .. c:function:: float glm_quat_norm(versor q) @@ -77,6 +120,14 @@ Functions documentation Returns: norm (magnitude) +.. c:function:: void glm_quat_normalize_to(versor q, versor dest) + + | normalize quaternion and store result in dest, original one will not be normalized + + Parameters: + | *[in]* **q** quaternion to normalize into + | *[out]* **dest** destination quaternion + .. c:function:: void glm_quat_normalize(versor q) | normalize quaternion @@ -84,24 +135,118 @@ Functions documentation Parameters: | *[in, out]* **q** quaternion -.. c:function:: float glm_quat_dot(versor q, versor r) +.. c:function:: float glm_quat_dot(versor p, versor q) dot product of two quaternion Parameters: - | *[in]* **q1** quaternion 1 - | *[in]* **q2** quaternion 2 + | *[in]* **p** quaternion 1 + | *[in]* **q** quaternion 2 Returns: dot product -.. c:function:: void glm_quat_mulv(versor q1, versor q2, versor dest) +.. c:function:: void glm_quat_conjugate(versor q, versor dest) + + conjugate of quaternion + + Parameters: + | *[in]* **q** quaternion + | *[in]* **dest** conjugate + +.. c:function:: void glm_quat_inv(versor q, versor dest) + + inverse of non-zero quaternion + + Parameters: + | *[in]* **q** quaternion + | *[in]* **dest** inverse quaternion + +.. c:function:: void glm_quat_add(versor p, versor q, versor dest) + + add (componentwise) two quaternions and store result in dest + + Parameters: + | *[in]* **p** quaternion 1 + | *[in]* **q** quaternion 2 + | *[in]* **dest** result quaternion + +.. c:function:: void glm_quat_sub(versor p, versor q, versor dest) + + subtract (componentwise) two quaternions and store result in dest + + Parameters: + | *[in]* **p** quaternion 1 + | *[in]* **q** quaternion 2 + | *[in]* **dest** result quaternion + +.. c:function:: float glm_quat_real(versor q) + + returns real part of quaternion + + Parameters: + | *[in]* **q** quaternion + + Returns: + real part (quat.w) + +.. c:function:: void glm_quat_imag(versor q, vec3 dest) + + returns imaginary part of quaternion + + Parameters: + | *[in]* **q** quaternion + | *[out]* **dest** imag + +.. c:function:: void glm_quat_imagn(versor q, vec3 dest) + + returns normalized imaginary part of quaternion + + Parameters: + | *[in]* **q** quaternion + | *[out]* **dest** imag + +.. c:function:: float glm_quat_imaglen(versor q) + + returns length of imaginary part of quaternion + + Parameters: + | *[in]* **q** quaternion + + Returns: + norm of imaginary part + +.. c:function:: float glm_quat_angle(versor q) + + returns angle of quaternion + + Parameters: + | *[in]* **q** quaternion + + Returns: + angles of quat (radians) + +.. c:function:: void glm_quat_axis(versor q, versor dest) + + axis of quaternion + + Parameters: + | *[in]* **p** quaternion + | *[out]* **dest** axis of quaternion + +.. c:function:: void glm_quat_mul(versor p, versor q, versor dest) | multiplies two quaternion and stores result in dest + | this is also called Hamilton Product + + | According to WikiPedia: + | The product of two rotation quaternions [clarification needed] will be + equivalent to the rotation q followed by the rotation p + Parameters: - | *[in]* **q1** quaternion 1 - | *[in]* **q2** quaternion 2 + | *[in]* **p** quaternion 1 (first rotation) + | *[in]* **q** quaternion 2 (second rotation) | *[out]* **dest** result quaternion .. c:function:: void glm_quat_mat4(versor q, mat4 dest) @@ -112,13 +257,100 @@ Functions documentation | *[in]* **q** quaternion | *[out]* **dest** result matrix +.. c:function:: void glm_quat_mat4t(versor q, mat4 dest) + + | convert quaternion to mat4 (transposed). This is transposed version of glm_quat_mat4 + + Parameters: + | *[in]* **q** quaternion + | *[out]* **dest** result matrix + +.. c:function:: void glm_quat_mat3(versor q, mat3 dest) + + | convert quaternion to mat3 + + Parameters: + | *[in]* **q** quaternion + | *[out]* **dest** result matrix + +.. c:function:: void glm_quat_mat3t(versor q, mat3 dest) + + | convert quaternion to mat3 (transposed). This is transposed version of glm_quat_mat3 + + Parameters: + | *[in]* **q** quaternion + | *[out]* **dest** result matrix + +.. c:function:: void glm_quat_lerp(versor from, versor to, float t, versor dest) + + | interpolates between two quaternions + | using spherical linear interpolation (LERP) + + Parameters: + | *[in]* **from** from + | *[in]* **to** to + | *[in]* **t** interpolant (amount) clamped between 0 and 1 + | *[out]* **dest** result quaternion + .. c:function:: void glm_quat_slerp(versor q, versor r, float t, versor dest) | interpolates between two quaternions | using spherical linear interpolation (SLERP) Parameters: - | *[in]* **q** from - | *[in]* **r** to - | *[in]* **t** amout + | *[in]* **from** from + | *[in]* **to** to + | *[in]* **t** interpolant (amount) clamped between 0 and 1 | *[out]* **dest** result quaternion + +.. c:function:: void glm_quat_look(vec3 eye, versor ori, mat4 dest) + + | creates view matrix using quaternion as camera orientation + + Parameters: + | *[in]* **eye** eye + | *[in]* **ori** orientation in world space as quaternion + | *[out]* **dest** result matrix + +.. c:function:: void glm_quat_for(vec3 dir, vec3 fwd, vec3 up, versor dest) + + | creates look rotation quaternion + + Parameters: + | *[in]* **dir** direction to look + | *[in]* **fwd** forward vector + | *[in]* **up** up vector + | *[out]* **dest** result matrix + +.. c:function:: void glm_quat_forp(vec3 from, vec3 to, vec3 fwd, vec3 up, versor dest) + + | creates look rotation quaternion using source and destination positions p suffix stands for position + + | this is similar to glm_quat_for except this computes direction for glm_quat_for for you. + + Parameters: + | *[in]* **from** source point + | *[in]* **to** destination point + | *[in]* **fwd** forward vector + | *[in]* **up** up vector + | *[out]* **dest** result matrix + +.. c:function:: void glm_quat_rotatev(versor q, vec3 v, vec3 dest) + + | crotate vector using using quaternion + + Parameters: + | *[in]* **q** quaternion + | *[in]* **v** vector to rotate + | *[out]* **dest** rotated vector + +.. c:function:: void glm_quat_rotate(mat4 m, versor q, mat4 dest) + + | rotate existing transform matrix using quaternion + + instead of passing identity matrix, consider to use quat_mat4 functions + + Parameters: + | *[in]* **m** existing transform matrix to rotate + | *[in]* **q** quaternion + | *[out]* **dest** rotated matrix/transform diff --git a/docs/source/util.rst b/docs/source/util.rst index a9f4066..f8dbac4 100644 --- a/docs/source/util.rst +++ b/docs/source/util.rst @@ -22,6 +22,7 @@ Functions: #. :c:func:`glm_min` #. :c:func:`glm_max` #. :c:func:`glm_clamp` +#. :c:func:`glm_lerp` Functions documentation ~~~~~~~~~~~~~~~~~~~~~~~ @@ -121,3 +122,17 @@ Functions documentation Returns: clamped value + +.. c:function:: float glm_lerp(float from, float to, float t) + + linear interpolation between two number + + | formula: from + s * (to - from) + + Parameters: + | *[in]* **from** from value + | *[in]* **to** to value + | *[in]* **t** interpolant (amount) clamped between 0 and 1 + + Returns: + interpolated value diff --git a/docs/source/vec3-ext.rst b/docs/source/vec3-ext.rst index e632de9..c2c0bfc 100644 --- a/docs/source/vec3-ext.rst +++ b/docs/source/vec3-ext.rst @@ -23,6 +23,11 @@ Functions: #. :c:func:`glm_vec_eqv_eps` #. :c:func:`glm_vec_max` #. :c:func:`glm_vec_min` +#. :c:func:`glm_vec_isnan` +#. :c:func:`glm_vec_isinf` +#. :c:func:`glm_vec_isvalid` +#. :c:func:`glm_vec_sign` +#. :c:func:`glm_vec_sqrt` Functions documentation ~~~~~~~~~~~~~~~~~~~~~~~ @@ -96,3 +101,43 @@ Functions documentation Parameters: | *[in]* **v** vector + +.. c:function:: bool glm_vec_isnan(vec3 v) + + | check if one of items is NaN (not a number) + | you should only use this in DEBUG mode or very critical asserts + + Parameters: + | *[in]* **v** vector + +.. c:function:: bool glm_vec_isinf(vec3 v) + + | check if one of items is INFINITY + | you should only use this in DEBUG mode or very critical asserts + + Parameters: + | *[in]* **v** vector + +.. c:function:: bool glm_vec_isvalid(vec3 v) + + | check if all items are valid number + | you should only use this in DEBUG mode or very critical asserts + + Parameters: + | *[in]* **v** vector + +.. c:function:: void glm_vec_sign(vec3 v, vec3 dest) + + get sign of 32 bit float as +1, -1, 0 + + Parameters: + | *[in]* **v** vector + | *[out]* **dest** sign vector (only keeps signs as -1, 0, -1) + +.. c:function:: void glm_vec_sqrt(vec3 v, vec3 dest) + + square root of each vector item + + Parameters: + | *[in]* **v** vector + | *[out]* **dest** destination vector (sqrt(v)) diff --git a/docs/source/vec3.rst b/docs/source/vec3.rst index 355178d..8529333 100644 --- a/docs/source/vec3.rst +++ b/docs/source/vec3.rst @@ -40,6 +40,7 @@ Functions: #. :c:func:`glm_vec_scale` #. :c:func:`glm_vec_scale_as` #. :c:func:`glm_vec_flipsign` +#. :c:func:`glm_vec_flipsign_to` #. :c:func:`glm_vec_inv` #. :c:func:`glm_vec_inv_to` #. :c:func:`glm_vec_normalize` @@ -54,6 +55,7 @@ Functions: #. :c:func:`glm_vec_minv` #. :c:func:`glm_vec_ortho` #. :c:func:`glm_vec_clamp` +#. :c:func:`glm_vec_lerp` Functions documentation ~~~~~~~~~~~~~~~~~~~~~~~ @@ -157,7 +159,15 @@ Functions documentation flip sign of all vec3 members Parameters: - | *[in, out]* **v** vector + | *[in, out]* **v** vector + +.. c:function:: void glm_vec_flipsign_to(vec3 v, vec3 dest) + + flip sign of all vec3 members and store result in dest + + Parameters: + | *[in]* **v** vector + | *[out]* **dest** negated vector .. c:function:: void glm_vec_inv(vec3 v) @@ -206,7 +216,7 @@ Functions documentation Parameters: | *[in, out]* **v** vector - | *[in]* **axis** axis vector (must be unit vector) + | *[in]* **axis** axis vector (will be normalized) | *[out]* **angle** angle (radians) .. c:function:: void glm_vec_rotate_m4(mat4 m, vec3 v, vec3 dest) @@ -281,3 +291,15 @@ Functions documentation | *[in, out]* **v** vector | *[in]* **minVal** minimum value | *[in]* **maxVal** maximum value + +.. c:function:: void glm_vec_lerp(vec3 from, vec3 to, float t, vec3 dest) + + linear interpolation between two vector + + | formula: from + s * (to - from) + + Parameters: + | *[in]* **from** from value + | *[in]* **to** to value + | *[in]* **t** interpolant (amount) clamped between 0 and 1 + | *[out]* **dest** destination diff --git a/docs/source/vec4-ext.rst b/docs/source/vec4-ext.rst index 11613ad..722424e 100644 --- a/docs/source/vec4-ext.rst +++ b/docs/source/vec4-ext.rst @@ -96,3 +96,43 @@ Functions documentation Parameters: | *[in]* **v** vector + +.. c:function:: bool glm_vec4_isnan(vec4 v) + + | check if one of items is NaN (not a number) + | you should only use this in DEBUG mode or very critical asserts + + Parameters: + | *[in]* **v** vector + +.. c:function:: bool glm_vec4_isinf(vec4 v) + + | check if one of items is INFINITY + | you should only use this in DEBUG mode or very critical asserts + + Parameters: + | *[in]* **v** vector + +.. c:function:: bool glm_vec4_isvalid(vec4 v) + + | check if all items are valid number + | you should only use this in DEBUG mode or very critical asserts + + Parameters: + | *[in]* **v** vector + +.. c:function:: void glm_vec4_sign(vec4 v, vec4 dest) + + get sign of 32 bit float as +1, -1, 0 + + Parameters: + | *[in]* **v** vector + | *[out]* **dest** sign vector (only keeps signs as -1, 0, -1) + +.. c:function:: void glm_vec4_sqrt(vec4 v, vec4 dest) + + square root of each vector item + + Parameters: + | *[in]* **v** vector + | *[out]* **dest** destination vector (sqrt(v)) diff --git a/docs/source/vec4.rst b/docs/source/vec4.rst index ac1b9c5..6955246 100644 --- a/docs/source/vec4.rst +++ b/docs/source/vec4.rst @@ -32,6 +32,7 @@ Functions: #. :c:func:`glm_vec4_scale` #. :c:func:`glm_vec4_scale_as` #. :c:func:`glm_vec4_flipsign` +#. :c:func:`glm_vec_flipsign_to` #. :c:func:`glm_vec4_inv` #. :c:func:`glm_vec4_inv_to` #. :c:func:`glm_vec4_normalize` @@ -40,6 +41,12 @@ Functions: #. :c:func:`glm_vec4_maxv` #. :c:func:`glm_vec4_minv` #. :c:func:`glm_vec4_clamp` +#. :c:func:`glm_vec4_lerp` +#. :c:func:`glm_vec4_isnan` +#. :c:func:`glm_vec4_isinf` +#. :c:func:`glm_vec4_isvalid` +#. :c:func:`glm_vec4_sign` +#. :c:func:`glm_vec4_sqrt` Functions documentation ~~~~~~~~~~~~~~~~~~~~~~~ @@ -146,6 +153,14 @@ Functions documentation Parameters: | *[in, out]* **v** vector +.. c:function:: void glm_vec4_flipsign_to(vec4 v, vec4 dest) + + flip sign of all vec4 members and store result in dest + + Parameters: + | *[in]* **v** vector + | *[out]* **dest** negated vector + .. c:function:: void glm_vec4_inv(vec4 v) make vector as inverse/opposite of itself @@ -213,3 +228,15 @@ Functions documentation | *[in, out]* **v** vector | *[in]* **minVal** minimum value | *[in]* **maxVal** maximum value + +.. c:function:: void glm_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest) + + linear interpolation between two vector + + | formula: from + s * (to - from) + + Parameters: + | *[in]* **from** from value + | *[in]* **to** to value + | *[in]* **t** interpolant (amount) clamped between 0 and 1 + | *[out]* **dest** destination diff --git a/include/cglm/quat.h b/include/cglm/quat.h index c9927bb..d82a301 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -226,8 +226,8 @@ glm_quat_normalize(versor q) { /*! * @brief dot product of two quaternion * - * @param[in] q1 quaternion 1 - * @param[in] q2 quaternion 2 + * @param[in] p quaternion 1 + * @param[in] q quaternion 2 */ CGLM_INLINE float @@ -303,6 +303,7 @@ glm_quat_real(versor q) { * @brief returns imaginary part of quaternion * * @param[in] q quaternion + * @param[out] dest imag */ CGLM_INLINE void @@ -649,6 +650,7 @@ glm_quat_look(vec3 eye, versor ori, mat4 dest) { /*! * @brief creates look rotation quaternion * + * @param[in] dir direction to look * @param[in] fwd forward vector * @param[in] up up vector * @param[out] dest destination quaternion @@ -683,6 +685,7 @@ glm_quat_for(vec3 dir, vec3 fwd, vec3 up, versor dest) { * * @param[in] from source point * @param[in] to destination point + * @param[in] fwd forward vector * @param[in] up up vector * @param[out] dest destination quaternion */ @@ -699,7 +702,7 @@ glm_quat_forp(vec3 from, vec3 to, vec3 fwd, vec3 up, versor dest) { * * @param[in] q quaternion * @param[in] v vector to rotate - * @param[out] dest destination vector + * @param[out] dest rotated vector */ CGLM_INLINE void @@ -727,7 +730,7 @@ glm_quat_rotatev(versor q, vec3 v, vec3 dest) { * * @param[in] m existing transform matrix * @param[in] q quaternion - * @param[out] dest destination matrix + * @param[out] dest rotated matrix/transform */ CGLM_INLINE void diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index 1cbf508..714165b 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -246,7 +246,7 @@ glm_vec_flipsign(vec3 v) { * @brief flip sign of all vec3 members and store result in dest * * @param[in] v vector - * @param[out] dest vector + * @param[out] dest result vector */ CGLM_INLINE void diff --git a/include/cglm/vec4-ext.h b/include/cglm/vec4-ext.h index 77ba1fa..53b02a8 100644 --- a/include/cglm/vec4-ext.h +++ b/include/cglm/vec4-ext.h @@ -175,7 +175,7 @@ glm_vec4_min(vec4 v) { } /*! - * @brief check if all items are NaN (not a number) + * @brief check if one of items is NaN (not a number) * you should only use this in DEBUG mode or very critical asserts * * @param[in] v vector @@ -187,7 +187,7 @@ glm_vec4_isnan(vec4 v) { } /*! - * @brief check if all items are INFINITY + * @brief check if one of items is INFINITY * you should only use this in DEBUG mode or very critical asserts * * @param[in] v vector From 9ae8da3e0aa8bcee6faaa397313f2f332a172596 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Wed, 11 Apr 2018 12:36:39 +0300 Subject: [PATCH 40/98] update version to v0.4.0 --- configure.ac | 2 +- include/cglm/version.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index afb694b..6e22248 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ #***************************************************************************** AC_PREREQ([2.69]) -AC_INIT([cglm], [0.3.6], [info@recp.me]) +AC_INIT([cglm], [0.4.0], [info@recp.me]) AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/include/cglm/version.h b/include/cglm/version.h index c27a26e..9a54b03 100644 --- a/include/cglm/version.h +++ b/include/cglm/version.h @@ -9,7 +9,7 @@ #define cglm_version_h #define CGLM_VERSION_MAJOR 0 -#define CGLM_VERSION_MINOR 3 -#define CGLM_VERSION_PATCH 6 +#define CGLM_VERSION_MINOR 4 +#define CGLM_VERSION_PATCH 0 #endif /* cglm_version_h */ From 2d77123999be1ee902bed2f02c88aa29e4875bfe Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Wed, 11 Apr 2018 16:50:37 +0300 Subject: [PATCH 41/98] quat: fix quaternion inverse and tests about it * multiplication quaternion and its inverse must be identity --- include/cglm/quat.h | 2 +- test/src/test_quat.c | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/include/cglm/quat.h b/include/cglm/quat.h index d82a301..fa356d4 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -259,7 +259,7 @@ void glm_quat_inv(versor q, versor dest) { versor conj; glm_quat_conjugate(q, conj); - glm_vec_scale(conj, glm_vec4_norm2(q), dest); + glm_vec4_scale(conj, 1.0f / glm_vec4_norm2(q), dest); } /*! diff --git a/test/src/test_quat.c b/test/src/test_quat.c index fec8dae..74d12b5 100644 --- a/test/src/test_quat.c +++ b/test/src/test_quat.c @@ -26,6 +26,8 @@ test_quat(void **state) { /* 0. test identiy quat */ glm_quat_identity(q4); assert_true(glm_quat_real(q4) == cosf(glm_rad(0.0f) * 0.5f)); + glm_quat_mat4(q4, rot1); + test_assert_mat4_eq2(rot1, GLM_MAT4_IDENTITY, 0.000009); /* 1. test quat to mat and mat to quat */ for (i = 0; i < 1000; i++) { @@ -184,5 +186,14 @@ test_quat(void **state) { /* result must be identity */ test_assert_mat4_eq2(rot1, GLM_MAT4_IDENTITY, 0.000009); + test_rand_quat(q3); + + /* 12. inverse of quat, multiplication must be IDENTITY */ + glm_quat_inv(q3, q4); + glm_quat_mul(q3, q4, q5); + + glm_quat_identity(q3); + test_assert_quat_eq(q3, q5); + /* TODO: add tests for slerp, lerp */ } From c8ed8acbed9c43245a08e74de0fdb922fd1eed0a Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Thu, 12 Apr 2018 14:47:14 +0300 Subject: [PATCH 42/98] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index dc9f736..15f434c 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,9 @@ 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 +- **[bugfix]** euler angles was implemented in reverse order (extrinsic) it was fixed, now they are intrinsic. Make sure that +you have the latest version +- **[major change]** by starting v0.4.0, quaternions are stored as [x, y, z, w], it was [w, x, y, z] in v0.3.5 and earlier versions #### Note for C++ developers: If you don't aware about original GLM library yet, you may also want to look at: From 44728c536b6245c5c7ddd22f579cdb061d424392 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Thu, 12 Apr 2018 15:52:06 +0300 Subject: [PATCH 43/98] ci: update travis ci --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index af4e37f..c2c0c84 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,7 +49,7 @@ script: after_success: - if [[ "$CC" == "gcc" && "$CODE_COVERAGE" == "ON" ]]; then - pip install --user cpp-coveralls + pip install --user cpp-coveralls && coveralls --build-root . --exclude lib From 0eb37da8bbcefc722ad4098b47b742d615c85fb1 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 13 Apr 2018 11:01:07 +0300 Subject: [PATCH 44/98] vec4: optimize vec4 normalize with SIMD --- include/cglm/vec4.h | 48 ++++++++++++++++++++++++------------------ test/src/test_common.c | 8 +++++++ test/src/test_common.h | 3 +++ test/src/test_vec4.c | 29 +++++++++++++++++++++++-- 4 files changed, 66 insertions(+), 22 deletions(-) diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index eaa4eaf..0ef6bff 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -312,26 +312,6 @@ glm_vec4_inv_to(vec4 v, vec4 dest) { glm_vec4_flipsign(dest); } -/*! - * @brief normalize vec4 and store result in same vec - * - * @param[in, out] v vector - */ -CGLM_INLINE -void -glm_vec4_normalize(vec4 v) { - float norm; - - norm = glm_vec4_norm(v); - - if (norm == 0.0f) { - v[0] = v[1] = v[2] = v[3] = 0.0f; - return; - } - - glm_vec4_scale(v, 1.0f / norm, v); -} - /*! * @brief normalize vec4 to dest * @@ -341,16 +321,44 @@ glm_vec4_normalize(vec4 v) { CGLM_INLINE void glm_vec4_normalize_to(vec4 vec, vec4 dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + __m128 xdot, x0; + float dot; + + x0 = _mm_load_ps(vec); + xdot = glm_simd_dot(x0, x0); + dot = _mm_cvtss_f32(xdot); + + if (dot == 0.0f) { + _mm_store_ps(dest, _mm_setzero_ps()); + return; + } + + _mm_store_ps(dest, _mm_div_ps(x0, _mm_sqrt_ps(xdot))); +#else float norm; norm = glm_vec4_norm(vec); if (norm == 0.0f) { dest[0] = dest[1] = dest[2] = dest[3] = 0.0f; + glm_vec4_broadcast(0.0f, dest); return; } glm_vec4_scale(vec, 1.0f / norm, dest); +#endif +} + +/*! + * @brief normalize vec4 and store result in same vec + * + * @param[in, out] v vector + */ +CGLM_INLINE +void +glm_vec4_normalize(vec4 v) { + glm_vec4_normalize_to(v, v); } /** diff --git a/test/src/test_common.c b/test/src/test_common.c index 514c006..a559087 100644 --- a/test/src/test_common.c +++ b/test/src/test_common.c @@ -91,6 +91,14 @@ test_assert_vec3_eq(vec3 v1, vec3 v2) { assert_true(fabsf(v1[2] - v2[2]) <= 0.000009); } +void +test_assert_vec4_eq(vec4 v1, vec4 v2) { + assert_true(fabsf(v1[0] - v2[0]) <= 0.000009); /* rounding errors */ + assert_true(fabsf(v1[1] - v2[1]) <= 0.000009); + assert_true(fabsf(v1[2] - v2[2]) <= 0.000009); + assert_true(fabsf(v1[3] - v2[3]) <= 0.000009); +} + void test_assert_quat_eq_abs(versor v1, versor v2) { assert_true(fabsf(fabsf(v1[0]) - fabsf(v2[0])) <= 0.0009); /* rounding errors */ diff --git a/test/src/test_common.h b/test/src/test_common.h index c95405e..50e84d6 100644 --- a/test/src/test_common.h +++ b/test/src/test_common.h @@ -34,6 +34,9 @@ test_assert_mat4_eq2(mat4 m1, mat4 m2, float eps); void test_assert_vec3_eq(vec3 v1, vec3 v2); +void +test_assert_vec4_eq(vec4 v1, vec4 v2); + void test_assert_quat_eq(versor v1, versor v2); diff --git a/test/src/test_vec4.c b/test/src/test_vec4.c index a45a700..994bab7 100644 --- a/test/src/test_vec4.c +++ b/test/src/test_vec4.c @@ -13,18 +13,43 @@ test_vec4_dot(vec4 a, vec4 b) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; } +CGLM_INLINE +void +test_vec4_normalize_to(vec4 vec, vec4 dest) { + float norm; + + norm = glm_vec4_norm(vec); + + if (norm == 0.0f) { + dest[0] = dest[1] = dest[2] = dest[3] = 0.0f; + return; + } + + glm_vec4_scale(vec, 1.0f / norm, dest); +} + void test_vec4(void **state) { - vec4 v; + vec4 v, v1, v2; int i; float d1, d2; - /* test SSE/SIMD dot product */ + for (i = 0; i < 100; i++) { + /* 1. test SSE/SIMD dot product */ test_rand_vec4(v); d1 = glm_vec4_dot(v, v); d2 = test_vec4_dot(v, v); assert_true(fabsf(d1 - d2) <= 0.000009); + + /* 2. test SIMD normalize */ + test_vec4_normalize_to(v, v1); + glm_vec4_normalize_to(v, v2); + glm_vec4_normalize(v); + + /* all must be same */ + test_assert_vec4_eq(v1, v2); + test_assert_vec4_eq(v, v2); } } From 79f8b1ebf85040e19a0a2eeb4b750dc57e948db5 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 13 Apr 2018 11:18:42 +0300 Subject: [PATCH 45/98] vec4: optimize vec4 norm and norm2 --- include/cglm/vec4.h | 16 +++++++++++++++- test/src/test_common.c | 5 +++++ test/src/test_common.h | 3 +++ test/src/test_vec4.c | 20 +++++++++++++++++++- 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index 0ef6bff..c50b4f9 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -146,7 +146,15 @@ glm_vec4_dot(vec4 a, vec4 b) { CGLM_INLINE float glm_vec4_norm2(vec4 v) { - return glm_vec4_dot(v, v); +#if defined( __SSE__ ) || defined( __SSE2__ ) + __m128 x0; + x0 = _mm_load_ps(v); + x0 = _mm_mul_ps(x0, x0); + x0 = _mm_add_ps(x0, _mm_shuffle1_ps(x0, 1, 0, 3, 2)); + return _mm_cvtss_f32(_mm_add_ss(x0, _mm_shuffle1_ps(x0, 0, 1, 0, 1))); +#else + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; +#endif } /*! @@ -159,7 +167,13 @@ glm_vec4_norm2(vec4 v) { CGLM_INLINE float glm_vec4_norm(vec4 vec) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + __m128 x0; + x0 = _mm_load_ps(vec); + return _mm_cvtss_f32(_mm_sqrt_ss(glm_simd_dot(x0, x0))); +#else return sqrtf(glm_vec4_norm2(vec)); +#endif } /*! diff --git a/test/src/test_common.c b/test/src/test_common.c index a559087..60baac3 100644 --- a/test/src/test_common.c +++ b/test/src/test_common.c @@ -84,6 +84,11 @@ test_assert_mat4_eq2(mat4 m1, mat4 m2, float eps) { } } +void +test_assert_eqf(float a, float b) { + assert_true(fabsf(a - b) <= 0.000009); /* rounding errors */ +} + void test_assert_vec3_eq(vec3 v1, vec3 v2) { assert_true(fabsf(v1[0] - v2[0]) <= 0.000009); /* rounding errors */ diff --git a/test/src/test_common.h b/test/src/test_common.h index 50e84d6..db113a4 100644 --- a/test/src/test_common.h +++ b/test/src/test_common.h @@ -25,6 +25,9 @@ void test_rand_mat4(mat4 dest); +void +test_assert_eqf(float a, float b); + void test_assert_mat4_eq(mat4 m1, mat4 m2); diff --git a/test/src/test_vec4.c b/test/src/test_vec4.c index 994bab7..51986f1 100644 --- a/test/src/test_vec4.c +++ b/test/src/test_vec4.c @@ -28,6 +28,16 @@ test_vec4_normalize_to(vec4 vec, vec4 dest) { glm_vec4_scale(vec, 1.0f / norm, dest); } +float +test_vec4_norm2(vec4 vec) { + return test_vec4_dot(vec, vec); +} + +float +test_vec4_norm(vec4 vec) { + return sqrtf(test_vec4_dot(vec, vec)); +} + void test_vec4(void **state) { vec4 v, v1, v2; @@ -35,7 +45,7 @@ test_vec4(void **state) { float d1, d2; - for (i = 0; i < 100; i++) { + for (i = 0; i < 1000; i++) { /* 1. test SSE/SIMD dot product */ test_rand_vec4(v); d1 = glm_vec4_dot(v, v); @@ -51,5 +61,13 @@ test_vec4(void **state) { /* all must be same */ test_assert_vec4_eq(v1, v2); test_assert_vec4_eq(v, v2); + + /* 3. test SIMD norm */ + test_rand_vec4(v); + test_assert_eqf(test_vec4_norm(v), glm_vec4_norm(v)); + + /* 3. test SIMD norm2 */ + test_rand_vec4(v); + test_assert_eqf(test_vec4_norm2(v), glm_vec4_norm2(v)); } } From c489955b0079d4c8c9a599fb14d9a2ca15a9363e Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 13 Apr 2018 11:39:14 +0300 Subject: [PATCH 46/98] add simd norm helper --- include/cglm/simd/intrin.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/cglm/simd/intrin.h b/include/cglm/simd/intrin.h index 4c27d90..c396686 100644 --- a/include/cglm/simd/intrin.h +++ b/include/cglm/simd/intrin.h @@ -40,6 +40,12 @@ glm_simd_dot(__m128 a, __m128 b) { return _mm_add_ps(x0, _mm_shuffle1_ps(x0, 0, 1, 0, 1)); } +CGLM_INLINE +__m128 +glm_simd_norm(__m128 a) { + return _mm_sqrt_ps(glm_simd_dot(a, a)); +} + #endif /* x86, x64 */ From 25fc3d028486c000f242588f735885cb9afad2bd Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 13 Apr 2018 11:57:14 +0300 Subject: [PATCH 47/98] vec: add one and zero helpers for vectors --- docs/source/vec3.rst | 16 ++++++++++++++++ docs/source/vec4.rst | 9 +++++++++ include/cglm/call/vec3.h | 8 ++++++++ include/cglm/call/vec4.h | 8 ++++++++ include/cglm/vec3.h | 26 ++++++++++++++++++++++++++ include/cglm/vec4.h | 36 ++++++++++++++++++++++++++++++++++++ makefile.am | 3 ++- src/vec3.c | 12 ++++++++++++ src/vec4.c | 12 ++++++++++++ test/src/test_main.c | 5 ++++- test/src/test_tests.h | 3 +++ test/src/test_vec3.c | 21 +++++++++++++++++++++ test/src/test_vec4.c | 8 ++++++++ 13 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 test/src/test_vec3.c diff --git a/docs/source/vec3.rst b/docs/source/vec3.rst index 8529333..0c5d590 100644 --- a/docs/source/vec3.rst +++ b/docs/source/vec3.rst @@ -31,6 +31,8 @@ Functions: 1. :c:func:`glm_vec3` #. :c:func:`glm_vec_copy` +#. :c:func:`glm_vec_zero` +#. :c:func:`glm_vec_one` #. :c:func:`glm_vec_dot` #. :c:func:`glm_vec_cross` #. :c:func:`glm_vec_norm2` @@ -76,6 +78,20 @@ Functions documentation | *[in]* **a** source | *[out]* **dest** destination +.. c:function:: void glm_vec_zero(vec3 v) + + makes all members 0.0f (zero) + + Parameters: + | *[in, out]* **v** vector + +.. c:function:: void glm_vec_one(vec3 v) + + makes all members 1.0f (one) + + Parameters: + | *[in, out]* **v** vector + .. c:function:: float glm_vec_dot(vec3 a, vec3 b) dot product of vec3 diff --git a/docs/source/vec4.rst b/docs/source/vec4.rst index 6955246..8deed35 100644 --- a/docs/source/vec4.rst +++ b/docs/source/vec4.rst @@ -24,6 +24,8 @@ Functions: 1. :c:func:`glm_vec4` #. :c:func:`glm_vec4_copy3` #. :c:func:`glm_vec4_copy` +#. :c:func:`glm_vec4_zero` +#. :c:func:`glm_vec4_one` #. :c:func:`glm_vec4_dot` #. :c:func:`glm_vec4_norm2` #. :c:func:`glm_vec4_norm` @@ -78,6 +80,13 @@ Functions documentation | *[in]* **v** source | *[in]* **dest** destination +.. c:function:: void glm_vec4_zero(vec4 v) + + makes all members zero + + Parameters: + | *[in, out]* **v** vector + .. c:function:: float glm_vec4_dot(vec4 a, vec4 b) dot product of vec4 diff --git a/include/cglm/call/vec3.h b/include/cglm/call/vec3.h index e79ec8f..396972f 100644 --- a/include/cglm/call/vec3.h +++ b/include/cglm/call/vec3.h @@ -24,6 +24,14 @@ CGLM_EXPORT void glmc_vec_copy(vec3 a, vec3 dest); +CGLM_EXPORT +void +glmc_vec_zero(vec3 v); + +CGLM_EXPORT +void +glmc_vec_one(vec3 v); + CGLM_EXPORT float glmc_vec_dot(vec3 a, vec3 b); diff --git a/include/cglm/call/vec4.h b/include/cglm/call/vec4.h index ad915e6..95f91e2 100644 --- a/include/cglm/call/vec4.h +++ b/include/cglm/call/vec4.h @@ -21,6 +21,14 @@ CGLM_EXPORT void glmc_vec4(vec3 v3, float last, vec4 dest); +CGLM_EXPORT +void +glmc_vec4_zero(vec4 v); + +CGLM_EXPORT +void +glmc_vec4_one(vec4 v); + CGLM_EXPORT void glmc_vec4_copy3(vec4 a, vec3 dest); diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index 714165b..6f42855 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -103,6 +103,32 @@ glm_vec_copy(vec3 a, vec3 dest) { dest[2] = a[2]; } +/*! + * @brief make vector zero + * + * @param[in, out] v vector + */ +CGLM_INLINE +void +glm_vec_zero(vec4 v) { + v[0] = 0.0f; + v[1] = 0.0f; + v[2] = 0.0f; +} + +/*! + * @brief make vector one + * + * @param[in, out] v vector + */ +CGLM_INLINE +void +glm_vec_one(vec4 v) { + v[0] = 1.0f; + v[1] = 1.0f; + v[2] = 1.0f; +} + /*! * @brief vec3 dot product * diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index c50b4f9..44c6a31 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -111,6 +111,42 @@ glm_vec4_copy(vec4 v, vec4 dest) { #endif } +/*! + * @brief make vector zero + * + * @param[in, out] v vector + */ +CGLM_INLINE +void +glm_vec4_zero(vec4 v) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(v, _mm_setzero_ps()); +#else + v[0] = 0.0f; + v[1] = 0.0f; + v[2] = 0.0f; + v[3] = 0.0f; +#endif +} + +/*! + * @brief make vector one + * + * @param[in, out] v vector + */ +CGLM_INLINE +void +glm_vec4_one(vec4 v) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(v, _mm_set1_ps(1.0f)); +#else + v[0] = 1.0f; + v[1] = 1.0f; + v[2] = 1.0f; + v[3] = 1.0f; +#endif +} + /*! * @brief vec4 dot product * diff --git a/makefile.am b/makefile.am index 2922373..00800c0 100644 --- a/makefile.am +++ b/makefile.am @@ -110,7 +110,8 @@ test_tests_SOURCES=\ test/src/test_clamp.c \ test/src/test_euler.c \ test/src/test_quat.c \ - test/src/test_vec4.c + test/src/test_vec4.c \ + test/src/test_vec3.c all-local: sh ./post-build.sh diff --git a/src/vec3.c b/src/vec3.c index f7e2692..f7c890e 100644 --- a/src/vec3.c +++ b/src/vec3.c @@ -20,6 +20,18 @@ glmc_vec_copy(vec3 a, vec3 dest) { glm_vec_copy(a, dest); } +CGLM_EXPORT +void +glmc_vec_zero(vec3 v) { + glm_vec_zero(v); +} + +CGLM_EXPORT +void +glmc_vec_one(vec3 v) { + glm_vec_one(v); +} + CGLM_EXPORT float glmc_vec_dot(vec3 a, vec3 b) { diff --git a/src/vec4.c b/src/vec4.c index 7228070..df93556 100644 --- a/src/vec4.c +++ b/src/vec4.c @@ -14,6 +14,18 @@ glmc_vec4(vec3 v3, float last, vec4 dest) { glm_vec4(v3, last, dest); } +CGLM_EXPORT +void +glmc_vec4_zero(vec4 v) { + glm_vec4_zero(v); +} + +CGLM_EXPORT +void +glmc_vec4_one(vec4 v) { + glm_vec4_one(v); +} + CGLM_EXPORT void glmc_vec4_copy3(vec4 a, vec3 dest) { diff --git a/test/src/test_main.c b/test/src/test_main.c index 7995a5a..b0649cd 100644 --- a/test/src/test_main.c +++ b/test/src/test_main.c @@ -29,7 +29,10 @@ main(int argc, const char * argv[]) { cmocka_unit_test(test_quat), /* vec4 */ - cmocka_unit_test(test_vec4) + cmocka_unit_test(test_vec4), + + /* vec3 */ + cmocka_unit_test(test_vec3) }; return cmocka_run_group_tests(tests, NULL, NULL); diff --git a/test/src/test_tests.h b/test/src/test_tests.h index 1dfbb5f..224d943 100644 --- a/test/src/test_tests.h +++ b/test/src/test_tests.h @@ -31,4 +31,7 @@ test_quat(void **state); void test_vec4(void **state); +void +test_vec3(void **state); + #endif /* test_tests_h */ diff --git a/test/src/test_vec3.c b/test/src/test_vec3.c new file mode 100644 index 0000000..5a3a4c8 --- /dev/null +++ b/test/src/test_vec3.c @@ -0,0 +1,21 @@ +/* + * 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_vec3(void **state) { + vec3 v; + + /* test zero */ + glm_vec_zero(v); + test_assert_vec3_eq(GLM_VEC3_ZERO, v); + + /* test one */ + glm_vec_one(v); + test_assert_vec3_eq(GLM_VEC3_ONE, v); +} diff --git a/test/src/test_vec4.c b/test/src/test_vec4.c index 51986f1..a80d9c7 100644 --- a/test/src/test_vec4.c +++ b/test/src/test_vec4.c @@ -70,4 +70,12 @@ test_vec4(void **state) { test_rand_vec4(v); test_assert_eqf(test_vec4_norm2(v), glm_vec4_norm2(v)); } + + /* test zero */ + glm_vec4_zero(v); + test_assert_vec4_eq(GLM_VEC4_ZERO, v); + + /* test one */ + glm_vec4_one(v); + test_assert_vec4_eq(GLM_VEC4_ONE, v); } From af5a2627b4566eabd44058d219f31dd8debb1e58 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 13 Apr 2018 11:57:34 +0300 Subject: [PATCH 48/98] fix scale_as for zero length vector * return zero if vector length is zero --- include/cglm/vec3.h | 4 ++-- include/cglm/vec4.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index 6f42855..2be7173 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -247,8 +247,8 @@ glm_vec_scale_as(vec3 v, float s, vec3 dest) { float norm; norm = glm_vec_norm(v); - if (norm == 0) { - glm_vec_copy(v, dest); + if (norm == 0.0f) { + glm_vec_zero(dest); return; } diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index 44c6a31..b28d9fd 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -291,8 +291,8 @@ glm_vec4_scale_as(vec4 v, float s, vec4 dest) { float norm; norm = glm_vec4_norm(v); - if (norm == 0) { - glm_vec4_copy(v, dest); + if (norm == 0.0f) { + glm_vec4_zero(dest); return; } From d841f8809d7da5f1e4afe6d06b67cb0ba4397b6b Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 13 Apr 2018 15:12:56 +0300 Subject: [PATCH 49/98] vec: add some new functions for vector * _mul: multiply two vector (replacement for _mulv) * _div: div two vector * _divs: div vector with scalar * adds: add scalar to each components of vec * subs: sub scalar from each components of vec --- docs/source/vec3.rst | 64 +++++++++++++++-- docs/source/vec4.rst | 66 ++++++++++++++--- include/cglm/call/vec3.h | 22 +++++- include/cglm/call/vec4.h | 24 ++++++- include/cglm/vec3-ext.h | 2 +- include/cglm/vec3.h | 114 ++++++++++++++++++++++++----- include/cglm/vec4-ext.h | 2 +- include/cglm/vec4.h | 152 +++++++++++++++++++++++++++++++-------- src/vec3.c | 34 ++++++++- src/vec4.c | 38 ++++++++-- test/src/test_vec3.c | 33 ++++++++- test/src/test_vec4.c | 31 ++++++++ 12 files changed, 510 insertions(+), 72 deletions(-) diff --git a/docs/source/vec3.rst b/docs/source/vec3.rst index 0c5d590..86f17e4 100644 --- a/docs/source/vec3.rst +++ b/docs/source/vec3.rst @@ -38,9 +38,14 @@ Functions: #. :c:func:`glm_vec_norm2` #. :c:func:`glm_vec_norm` #. :c:func:`glm_vec_add` +#. :c:func:`glm_vec_adds` #. :c:func:`glm_vec_sub` +#. :c:func:`glm_vec_subs` +#. :c:func:`glm_vec_mul` #. :c:func:`glm_vec_scale` #. :c:func:`glm_vec_scale_as` +#. :c:func:`glm_vec_div` +#. :c:func:`glm_vec_divs` #. :c:func:`glm_vec_flipsign` #. :c:func:`glm_vec_flipsign_to` #. :c:func:`glm_vec_inv` @@ -133,24 +138,51 @@ Functions documentation Parameters: | *[in]* **vec** vector -.. c:function:: void glm_vec_add(vec3 v1, vec3 v2, vec3 dest) +.. c:function:: void glm_vec_add(vec3 a, vec3 b, vec3 dest) - add v2 vector to v1 vector store result in dest + add a vector to b vector store result in dest Parameters: - | *[in]* **v1** vector1 - | *[in]* **v2** vector2 + | *[in]* **a** vector1 + | *[in]* **b** vector2 + | *[out]* **dest** destination vector + +.. c:function:: void glm_vec_adds(vec3 a, float s, vec3 dest) + + add scalar to v vector store result in dest (d = v + vec(s)) + + Parameters: + | *[in]* **v** vector + | *[in]* **s** scalar | *[out]* **dest** destination vector .. c:function:: void glm_vec_sub(vec3 v1, vec3 v2, vec3 dest) - subtract v2 vector from v1 vector store result in dest + subtract b vector from a vector store result in dest (d = v1 - v2) Parameters: - | *[in]* **v1** vector1 - | *[in]* **v2** vector2 + | *[in]* **a** vector1 + | *[in]* **b** vector2 | *[out]* **dest** destination vector +.. c:function:: void glm_vec_subs(vec3 v, float s, vec3 dest) + + subtract scalar from v vector store result in dest (d = v - vec(s)) + + Parameters: + | *[in]* **v** vector + | *[in]* **s** scalar + | *[out]* **dest** destination vector + +.. c:function:: void glm_vec_mul(vec3 a, vec3 b, vec3 d) + + multiply two vector (component-wise multiplication) + + Parameters: + | *[in]* **a** vector + | *[in]* **b** scalar + | *[out]* **d** result = (a[0] * b[0], a[1] * b[1], a[2] * b[2]) + .. c:function:: void glm_vec_scale(vec3 v, float s, vec3 dest) multiply/scale vec3 vector with scalar: result = v * s @@ -170,6 +202,24 @@ Functions documentation | *[in]* **s** scalar | *[out]* **dest** destination vector +.. c:function:: void glm_vec_div(vec3 a, vec3 b, vec3 dest) + + div vector with another component-wise division: d = a / b + + Parameters: + | *[in]* **a** vector 1 + | *[in]* **b** vector 2 + | *[out]* **dest** result = (a[0] / b[0], a[1] / b[1], a[2] / b[2]) + +.. c:function:: void glm_vec_divs(vec3 v, float s, vec3 dest) + + div vector with scalar: d = v / s + + Parameters: + | *[in]* **v** vector + | *[in]* **s** scalar + | *[out]* **dest** result = (a[0] / s, a[1] / s, a[2] / s]) + .. c:function:: void glm_vec_flipsign(vec3 v) flip sign of all vec3 members diff --git a/docs/source/vec4.rst b/docs/source/vec4.rst index 8deed35..89ac5c2 100644 --- a/docs/source/vec4.rst +++ b/docs/source/vec4.rst @@ -30,9 +30,14 @@ Functions: #. :c:func:`glm_vec4_norm2` #. :c:func:`glm_vec4_norm` #. :c:func:`glm_vec4_add` +#. :c:func:`glm_vec4_adds` #. :c:func:`glm_vec4_sub` +#. :c:func:`glm_vec4_subs` +#. :c:func:`glm_vec4_mul` #. :c:func:`glm_vec4_scale` #. :c:func:`glm_vec4_scale_as` +#. :c:func:`glm_vec4_div` +#. :c:func:`glm_vec4_divs` #. :c:func:`glm_vec4_flipsign` #. :c:func:`glm_vec_flipsign_to` #. :c:func:`glm_vec4_inv` @@ -119,24 +124,51 @@ Functions documentation Parameters: | *[in]* **vec** vector -.. c:function:: void glm_vec4_add(vec4 v1, vec4 v2, vec4 dest) +.. c:function:: void glm_vec4_add(vec4 a, vec4 b, vec4 dest) - add v2 vector to v1 vector store result in dest + add a vector to b vector store result in dest Parameters: - | *[in]* **v1** vector1 - | *[in]* **v2** vector2 + | *[in]* **a** vector1 + | *[in]* **b** vector2 | *[out]* **dest** destination vector -.. c:function:: void glm_vec4_sub(vec4 v1, vec4 v2, vec4 dest) +.. c:function:: void glm_vec4_adds(vec4 v, float s, vec4 dest) - subtract v2 vector from v1 vector store result in dest + add scalar to v vector store result in dest (d = v + vec(s)) Parameters: - | *[in]* **v1** vector1 - | *[in]* **v2** vector2 + | *[in]* **v** vector + | *[in]* **s** scalar | *[out]* **dest** destination vector +.. c:function:: void glm_vec4_sub(vec4 a, vec4 b, vec4 dest) + + subtract b vector from a vector store result in dest (d = v1 - v2) + + Parameters: + | *[in]* **a** vector1 + | *[in]* **b** vector2 + | *[out]* **dest** destination vector + +.. c:function:: void glm_vec4_subs(vec4 v, float s, vec4 dest) + + subtract scalar from v vector store result in dest (d = v - vec(s)) + + Parameters: + | *[in]* **v** vector + | *[in]* **s** scalar + | *[out]* **dest** destination vector + +.. c:function:: void glm_vec4_mul(vec4 a, vec4 b, vec4 d) + + multiply two vector (component-wise multiplication) + + Parameters: + | *[in]* **a** vector1 + | *[in]* **b** vector2 + | *[out]* **dest** result = (a[0] * b[0], a[1] * b[1], a[2] * b[2], a[3] * b[3]) + .. c:function:: void glm_vec4_scale(vec4 v, float s, vec4 dest) multiply/scale vec4 vector with scalar: result = v * s @@ -155,6 +187,24 @@ Functions documentation | *[in]* **s** scalar | *[out]* **dest** destination vector +.. c:function:: void glm_vec4_div(vec4 a, vec4 b, vec4 dest) + + div vector with another component-wise division: d = v1 / v2 + + Parameters: + | *[in]* **a** vector1 + | *[in]* **b** vector2 + | *[out]* **dest** result = (a[0] / b[0], a[1] / b[1], a[2] / b[2], a[3] / b[3]) + +.. c:function:: void glm_vec4_divs(vec4 v, float s, vec4 dest) + + div vector with scalar: d = v / s + + Parameters: + | *[in]* **v** vector + | *[in]* **s** scalar + | *[out]* **dest** result = (a[0] / s, a[1] / s, a[2] / s, a[3] / s) + .. c:function:: void glm_vec4_flipsign(vec4 v) flip sign of all vec4 members diff --git a/include/cglm/call/vec3.h b/include/cglm/call/vec3.h index 396972f..b2374e6 100644 --- a/include/cglm/call/vec3.h +++ b/include/cglm/call/vec3.h @@ -62,7 +62,19 @@ glmc_vec_add(vec3 v1, vec3 v2, vec3 dest); CGLM_EXPORT void -glmc_vec_sub(vec3 v1, vec3 v2, vec3 dest); +glmc_vec_adds(vec3 v, float s, vec3 dest); + +CGLM_EXPORT +void +glmc_vec_sub(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec_subs(vec3 v, float s, vec3 dest); + +CGLM_EXPORT +void +glmc_vec_mul(vec3 a, vec3 b, vec3 d); CGLM_EXPORT void @@ -72,6 +84,14 @@ CGLM_EXPORT void glmc_vec_scale_as(vec3 v, float s, vec3 dest); +CGLM_EXPORT +void +glmc_vec_div(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec_divs(vec3 a, float s, vec3 dest); + CGLM_EXPORT void glmc_vec_flipsign(vec3 v); diff --git a/include/cglm/call/vec4.h b/include/cglm/call/vec4.h index 95f91e2..b460962 100644 --- a/include/cglm/call/vec4.h +++ b/include/cglm/call/vec4.h @@ -59,11 +59,23 @@ glmc_vec4_normalize(vec4 v); CGLM_EXPORT void -glmc_vec4_add(vec4 v1, vec4 v2, vec4 dest); +glmc_vec4_add(vec4 a, vec4 b, vec4 dest); CGLM_EXPORT void -glmc_vec4_sub(vec4 v1, vec4 v2, vec4 dest); +glmc_vec4_adds(vec4 v, float s, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_sub(vec4 a, vec4 b, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_subs(vec4 v, float s, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_mul(vec4 a, vec4 b, vec4 d); CGLM_EXPORT void @@ -73,6 +85,14 @@ CGLM_EXPORT void glmc_vec4_scale_as(vec3 v, float s, vec3 dest); +CGLM_EXPORT +void +glmc_vec4_div(vec4 a, vec4 b, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_divs(vec4 v, float s, vec4 dest); + CGLM_EXPORT void glmc_vec4_flipsign(vec4 v); diff --git a/include/cglm/vec3-ext.h b/include/cglm/vec3-ext.h index fb2a687..e12c133 100644 --- a/include/cglm/vec3-ext.h +++ b/include/cglm/vec3-ext.h @@ -32,7 +32,7 @@ #include /*! - * @brief multiplies individual items, just for convenient like SIMD + * @brief DEPRECATED! use glm_vec_mul * * @param[in] a vec1 * @param[in] b vec2 diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index 2be7173..b3012b6 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -28,10 +28,15 @@ CGLM_INLINE void glm_vec_cross(vec3 a, vec3 b, vec3 d); CGLM_INLINE float glm_vec_norm2(vec3 v); CGLM_INLINE float glm_vec_norm(vec3 vec); - CGLM_INLINE void glm_vec_add(vec3 v1, vec3 v2, vec3 dest); - CGLM_INLINE void glm_vec_sub(vec3 v1, vec3 v2, vec3 dest); + CGLM_INLINE void glm_vec_add(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec_adds(vec3 a, float s, vec3 dest); + CGLM_INLINE void glm_vec_sub(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec_subs(vec3 a, float s, vec3 dest); + CGLM_INLINE void glm_vec_mul(vec3 a, vec3 b, vec3 dest); CGLM_INLINE void glm_vec_scale(vec3 v, float s, vec3 dest); CGLM_INLINE void glm_vec_scale_as(vec3 v, float s, vec3 dest); + CGLM_INLINE void glm_vec_div(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec_divs(vec3 a, float s, vec3 dest); CGLM_INLINE void glm_vec_flipsign(vec3 v); CGLM_INLINE void glm_vec_inv(vec3 v); CGLM_INLINE void glm_vec_inv_to(vec3 v, vec3 dest); @@ -110,7 +115,7 @@ glm_vec_copy(vec3 a, vec3 dest) { */ CGLM_INLINE void -glm_vec_zero(vec4 v) { +glm_vec_zero(vec3 v) { v[0] = 0.0f; v[1] = 0.0f; v[2] = 0.0f; @@ -123,7 +128,7 @@ glm_vec_zero(vec4 v) { */ CGLM_INLINE void -glm_vec_one(vec4 v) { +glm_vec_one(vec3 v) { v[0] = 1.0f; v[1] = 1.0f; v[2] = 1.0f; @@ -190,33 +195,78 @@ glm_vec_norm(vec3 vec) { } /*! - * @brief add v2 vector to v1 vector store result in dest + * @brief add a vector to b vector store result in dest * - * @param[in] v1 vector1 - * @param[in] v2 vector2 + * @param[in] a vector1 + * @param[in] b vector2 * @param[out] dest destination vector */ CGLM_INLINE void -glm_vec_add(vec3 v1, vec3 v2, vec3 dest) { - dest[0] = v1[0] + v2[0]; - dest[1] = v1[1] + v2[1]; - dest[2] = v1[2] + v2[2]; +glm_vec_add(vec3 a, vec3 b, vec3 dest) { + dest[0] = a[0] + b[0]; + dest[1] = a[1] + b[1]; + dest[2] = a[2] + b[2]; +} + +/*! + * @brief add scalar to v vector store result in dest (d = v + s) + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec_adds(vec3 v, float s, vec3 dest) { + dest[0] = v[0] + s; + dest[1] = v[1] + s; + dest[2] = v[2] + s; } /*! * @brief subtract v2 vector from v1 vector store result in dest * - * @param[in] v1 vector1 - * @param[in] v2 vector2 + * @param[in] a vector1 + * @param[in] b vector2 * @param[out] dest destination vector */ CGLM_INLINE void -glm_vec_sub(vec3 v1, vec3 v2, vec3 dest) { - dest[0] = v1[0] - v2[0]; - dest[1] = v1[1] - v2[1]; - dest[2] = v1[2] - v2[2]; +glm_vec_sub(vec3 a, vec3 b, vec3 dest) { + dest[0] = a[0] - b[0]; + dest[1] = a[1] - b[1]; + dest[2] = a[2] - b[2]; +} + +/*! + * @brief subtract scalar from v vector store result in dest (d = v - s) + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec_subs(vec3 v, float s, vec3 dest) { + dest[0] = v[0] - s; + dest[1] = v[1] - s; + dest[2] = v[2] - s; +} + +/*! + * @brief multiply two vector (component-wise multiplication) + * + * @param a v1 + * @param b v2 + * @param d v3 = (a[0] * b[0], a[1] * b[1], a[2] * b[2]) + */ +CGLM_INLINE +void +glm_vec_mul(vec3 a, vec3 b, vec3 d) { + d[0] = a[0] * b[0]; + d[1] = a[1] * b[1]; + d[2] = a[2] * b[2]; } /*! @@ -255,6 +305,36 @@ glm_vec_scale_as(vec3 v, float s, vec3 dest) { glm_vec_scale(v, s / norm, dest); } +/*! + * @brief div vector with another component-wise division: d = a / b + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest result = (a[0]/b[0], a[1]/b[1], a[2]/b[2]) + */ +CGLM_INLINE +void +glm_vec_div(vec3 a, vec3 b, vec3 dest) { + dest[0] = a[0] / b[0]; + dest[1] = a[1] / b[1]; + dest[2] = a[2] / b[2]; +} + +/*! + * @brief div vector with scalar: d = v / s + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest result = (a[0]/s, a[1]/s, a[2]/s) + */ +CGLM_INLINE +void +glm_vec_divs(vec3 v, float s, vec3 dest) { + dest[0] = v[0] / s; + dest[1] = v[1] / s; + dest[2] = v[2] / s; +} + /*! * @brief flip sign of all vec3 members * diff --git a/include/cglm/vec4-ext.h b/include/cglm/vec4-ext.h index 53b02a8..7a6cb3d 100644 --- a/include/cglm/vec4-ext.h +++ b/include/cglm/vec4-ext.h @@ -32,7 +32,7 @@ #include /*! - * @brief multiplies individual items, just for convenient like SIMD + * @brief DEPRECATED! use glm_vec4_mul * * @param a v1 * @param b v2 diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index b28d9fd..e1319b9 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -28,10 +28,15 @@ CGLM_INLINE float glm_vec4_dot(vec4 a, vec4 b); CGLM_INLINE float glm_vec4_norm2(vec4 v); CGLM_INLINE float glm_vec4_norm(vec4 vec); - CGLM_INLINE void glm_vec4_add(vec4 v1, vec4 v2, vec4 dest); - CGLM_INLINE void glm_vec4_sub(vec4 v1, vec4 v2, vec4 dest); + CGLM_INLINE void glm_vec4_add(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_adds(vec4 v, float s, vec4 dest); + CGLM_INLINE void glm_vec4_sub(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_subs(vec4 v, float s, vec4 dest); + CGLM_INLINE void glm_vec4_mul(vec4 a, vec4 b, vec4 dest); CGLM_INLINE void glm_vec4_scale(vec4 v, float s, vec4 dest); CGLM_INLINE void glm_vec4_scale_as(vec4 v, float s, vec4 dest); + CGLM_INLINE void glm_vec4_div(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_divs(vec4 v, float s, vec4 dest); CGLM_INLINE void glm_vec4_flipsign(vec4 v); CGLM_INLINE void glm_vec4_inv(vec4 v); CGLM_INLINE void glm_vec4_inv_to(vec4 v, vec4 dest); @@ -41,6 +46,7 @@ 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); + CGLM_INLINE void glm_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest) */ #ifndef cglm_vec4_h @@ -215,44 +221,100 @@ glm_vec4_norm(vec4 vec) { /*! * @brief add v2 vector to v1 vector store result in dest * - * @param[in] v1 vector1 - * @param[in] v2 vector2 + * @param[in] a vector1 + * @param[in] b vector2 * @param[out] dest destination vector */ CGLM_INLINE void -glm_vec4_add(vec4 v1, vec4 v2, vec4 dest) { +glm_vec4_add(vec4 a, vec4 b, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, - _mm_add_ps(_mm_load_ps(v1), - _mm_load_ps(v2))); + _mm_store_ps(dest, _mm_add_ps(_mm_load_ps(a), _mm_load_ps(b))); #else - dest[0] = v1[0] + v2[0]; - dest[1] = v1[1] + v2[1]; - dest[2] = v1[2] + v2[2]; - dest[3] = v1[3] + v2[3]; + dest[0] = a[0] + b[0]; + dest[1] = a[1] + b[1]; + dest[2] = a[2] + b[2]; + dest[3] = a[3] + b[3]; #endif } /*! - * @brief subtract v2 vector from v1 vector store result in dest + * @brief add scalar to v vector store result in dest (d = v + vec(s)) * - * @param[in] v1 vector1 - * @param[in] v2 vector2 + * @param[in] v vector + * @param[in] s scalar * @param[out] dest destination vector */ CGLM_INLINE void -glm_vec4_sub(vec4 v1, vec4 v2, vec4 dest) { +glm_vec4_adds(vec4 v, float s, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, - _mm_sub_ps(_mm_load_ps(v1), - _mm_load_ps(v2))); + _mm_store_ps(dest, _mm_add_ps(_mm_load_ps(v), _mm_set1_ps(s))); #else - dest[0] = v1[0] - v2[0]; - dest[1] = v1[1] - v2[1]; - dest[2] = v1[2] - v2[2]; - dest[3] = v1[3] - v2[3]; + dest[0] = v1[0] + s; + dest[1] = v1[1] + s; + dest[2] = v1[2] + s; + dest[3] = v1[3] + s; +#endif +} + +/*! + * @brief subtract b vector from a vector store result in dest (d = v1 - v2) + * + * @param[in] a vector1 + * @param[in] b vector2 + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec4_sub(vec4 a, vec4 b, vec4 dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(dest, _mm_sub_ps(_mm_load_ps(a), _mm_load_ps(b))); +#else + dest[0] = a[0] - b[0]; + dest[1] = a[1] - b[1]; + dest[2] = a[2] - b[2]; + dest[3] = a[3] - b[3]; +#endif +} + +/*! + * @brief subtract scalar from v vector store result in dest (d = v - vec(s)) + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec4_subs(vec4 v, float s, vec4 dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(dest, _mm_sub_ps(_mm_load_ps(v), _mm_set1_ps(s))); +#else + dest[0] = v1[0] - s; + dest[1] = v1[1] - s; + dest[2] = v1[2] - s; + dest[3] = v1[3] - s; +#endif +} + +/*! + * @brief multiply two vector (component-wise multiplication) + * + * @param a v1 + * @param b v2 + * @param d v3 = (a[0] * b[0], a[1] * b[1], a[2] * b[2], a[3] * b[3]) + */ +CGLM_INLINE +void +glm_vec4_mul(vec4 a, vec4 b, vec4 d) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(d, _mm_mul_ps(_mm_load_ps(a), _mm_load_ps(b))); +#else + d[0] = a[0] * b[0]; + d[1] = a[1] * b[1]; + d[2] = a[2] * b[2]; + d[3] = a[3] * b[3]; #endif } @@ -267,9 +329,7 @@ CGLM_INLINE void glm_vec4_scale(vec4 v, float s, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, - _mm_mul_ps(_mm_load_ps(v), - _mm_set1_ps(s))); + _mm_store_ps(dest, _mm_mul_ps(_mm_load_ps(v), _mm_set1_ps(s))); #else dest[0] = v[0] * s; dest[1] = v[1] * s; @@ -299,6 +359,43 @@ glm_vec4_scale_as(vec4 v, float s, vec4 dest) { glm_vec4_scale(v, s / norm, dest); } +/*! + * @brief div vector with another component-wise division: d = v1 / v2 + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest result = (a[0]/b[0], a[1]/b[1], a[2]/b[2], a[3]/b[3]) + */ +CGLM_INLINE +void +glm_vec4_div(vec4 a, vec4 b, vec4 dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(dest, _mm_div_ps(_mm_load_ps(a), _mm_load_ps(b))); +#else + dest[0] = a[0] / b[0]; + dest[1] = a[1] / b[1]; + dest[2] = a[2] / b[2]; + dest[3] = a[3] / b[3]; +#endif +} + +/*! + * @brief div vec4 vector with scalar: d = v / s + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec4_divs(vec4 v, float s, vec4 dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(dest, _mm_div_ps(_mm_load_ps(v), _mm_set1_ps(s))); +#else + glm_vec4_scale(v, 1.0f / s, dest); +#endif +} + /*! * @brief flip sign of all vec4 members * @@ -308,8 +405,7 @@ CGLM_INLINE void glm_vec4_flipsign(vec4 v) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(v, _mm_xor_ps(_mm_load_ps(v), - _mm_set1_ps(-0.0f))); + _mm_store_ps(v, _mm_xor_ps(_mm_load_ps(v), _mm_set1_ps(-0.0f))); #else v[0] = -v[0]; v[1] = -v[1]; diff --git a/src/vec3.c b/src/vec3.c index f7c890e..b8553ec 100644 --- a/src/vec3.c +++ b/src/vec3.c @@ -76,8 +76,26 @@ glmc_vec_add(vec3 v1, vec3 v2, vec3 dest) { CGLM_EXPORT void -glmc_vec_sub(vec3 v1, vec3 v2, vec3 dest) { - glm_vec_sub(v1, v2, dest); +glmc_vec_adds(vec3 v, float s, vec3 dest) { + glm_vec_adds(v, s, dest); +} + +CGLM_EXPORT +void +glmc_vec_sub(vec3 a, vec3 b, vec3 dest) { + glm_vec_sub(a, b, dest); +} + +CGLM_EXPORT +void +glmc_vec_subs(vec3 v, float s, vec3 dest) { + glm_vec_subs(v, s, dest); +} + +CGLM_EXPORT +void +glmc_vec_mul(vec3 a, vec3 b, vec3 d) { + glm_vec_mul(a, b, d); } CGLM_EXPORT @@ -92,6 +110,18 @@ glmc_vec_scale_as(vec3 v, float s, vec3 dest) { glm_vec_scale_as(v, s, dest); } +CGLM_EXPORT +void +glmc_vec_div(vec3 a, vec3 b, vec3 dest) { + glm_vec_div(a, b, dest); +} + +CGLM_EXPORT +void +glmc_vec_divs(vec3 a, float s, vec3 dest) { + glm_vec_divs(a, s, dest); +} + CGLM_EXPORT void glmc_vec_flipsign(vec3 v) { diff --git a/src/vec4.c b/src/vec4.c index df93556..282712c 100644 --- a/src/vec4.c +++ b/src/vec4.c @@ -70,14 +70,32 @@ glmc_vec4_norm2(vec4 vec) { CGLM_EXPORT void -glmc_vec4_add(vec4 v1, vec4 v2, vec4 dest) { - glm_vec4_add(v1, v2, dest); +glmc_vec4_add(vec4 a, vec4 b, vec4 dest) { + glm_vec4_add(a, b, dest); } CGLM_EXPORT void -glmc_vec4_sub(vec4 v1, vec4 v2, vec4 dest) { - glm_vec4_sub(v1, v2, dest); +glmc_vec4_adds(vec4 v, float s, vec4 dest) { + glm_vec4_adds(v, s, dest); +} + +CGLM_EXPORT +void +glmc_vec4_sub(vec4 a, vec4 b, vec4 dest) { + glm_vec4_sub(a, b, dest); +} + +CGLM_EXPORT +void +glmc_vec4_subs(vec4 v, float s, vec4 dest) { + glm_vec4_subs(v, s, dest); +} + +CGLM_EXPORT +void +glmc_vec4_mul(vec4 a, vec4 b, vec4 d) { + glm_vec4_mul(a, b, d); } CGLM_EXPORT @@ -92,6 +110,18 @@ glmc_vec4_scale_as(vec3 v, float s, vec3 dest) { glm_vec4_scale_as(v, s, dest); } +CGLM_EXPORT +void +glmc_vec4_div(vec4 a, vec4 b, vec4 dest) { + glm_vec4_div(a, b, dest); +} + +CGLM_EXPORT +void +glmc_vec4_divs(vec4 v, float s, vec4 dest) { + glm_vec4_divs(v, s, dest); +} + CGLM_EXPORT void glmc_vec4_flipsign(vec4 v) { diff --git a/test/src/test_vec3.c b/test/src/test_vec3.c index 5a3a4c8..c33e5ec 100644 --- a/test/src/test_vec3.c +++ b/test/src/test_vec3.c @@ -9,7 +9,7 @@ void test_vec3(void **state) { - vec3 v; + vec3 v, v1; /* test zero */ glm_vec_zero(v); @@ -18,4 +18,35 @@ test_vec3(void **state) { /* test one */ glm_vec_one(v); test_assert_vec3_eq(GLM_VEC3_ONE, v); + + /* adds, subs, div, divs, mul */ + glm_vec_add(v, GLM_VEC3_ONE, v); + assert_true(glmc_vec_eq_eps(v, 2)); + + glm_vec_adds(v, 10, v); + assert_true(glmc_vec_eq_eps(v, 12)); + + glm_vec_sub(v, GLM_VEC3_ONE, v); + assert_true(glmc_vec_eq_eps(v, 11)); + + glm_vec_subs(v, 1, v); + assert_true(glmc_vec_eq_eps(v, 10)); + + glm_vec_broadcast(2, v1); + glm_vec_div(v, v1, v); + assert_true(glmc_vec_eq_eps(v, 5)); + + glm_vec_divs(v, 0.5, v); + assert_true(glmc_vec_eq_eps(v, 10)); + + glm_vec_mul(v, v1, v); + assert_true(glmc_vec_eq_eps(v, 20)); + + glm_vec_scale(v, 0.5, v); + assert_true(glmc_vec_eq_eps(v, 10)); + + glm_vec_normalize_to(v, v1); + glm_vec_scale(v1, 0.8, v1); + glm_vec_scale_as(v, 0.8, v); + test_assert_vec3_eq(v1, v); } diff --git a/test/src/test_vec4.c b/test/src/test_vec4.c index a80d9c7..60772a9 100644 --- a/test/src/test_vec4.c +++ b/test/src/test_vec4.c @@ -78,4 +78,35 @@ test_vec4(void **state) { /* test one */ glm_vec4_one(v); test_assert_vec4_eq(GLM_VEC4_ONE, v); + + /* adds, subs, div, divs, mul */ + glm_vec4_add(v, GLM_VEC4_ONE, v); + assert_true(glmc_vec4_eq_eps(v, 2)); + + glm_vec4_adds(v, 10, v); + assert_true(glmc_vec4_eq_eps(v, 12)); + + glm_vec4_sub(v, GLM_VEC4_ONE, v); + assert_true(glmc_vec4_eq_eps(v, 11)); + + glm_vec4_subs(v, 1, v); + assert_true(glmc_vec4_eq_eps(v, 10)); + + glm_vec4_broadcast(2, v1); + glm_vec4_div(v, v1, v); + assert_true(glmc_vec4_eq_eps(v, 5)); + + glm_vec4_divs(v, 0.5, v); + assert_true(glmc_vec4_eq_eps(v, 10)); + + glm_vec4_mul(v, v1, v); + assert_true(glmc_vec4_eq_eps(v, 20)); + + glm_vec4_scale(v, 0.5, v); + assert_true(glmc_vec4_eq_eps(v, 10)); + + glm_vec4_normalize_to(v, v1); + glm_vec4_scale(v1, 0.8, v1); + glm_vec4_scale_as(v, 0.8, v); + test_assert_vec4_eq(v1, v); } From c05f58a1699307c4ace5733dad8f6fa93f3801c2 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 13 Apr 2018 15:46:43 +0300 Subject: [PATCH 50/98] vec: add addadd, subadd and muladd helpers --- docs/source/vec3.rst | 33 +++++++++++++++++ docs/source/vec4.rst | 33 +++++++++++++++++ include/cglm/call/vec3.h | 12 +++++++ include/cglm/call/vec4.h | 12 +++++++ include/cglm/vec3.h | 54 ++++++++++++++++++++++++++++ include/cglm/vec4.h | 76 ++++++++++++++++++++++++++++++++++++++++ src/vec3.c | 18 ++++++++++ src/vec4.c | 20 ++++++++++- test/src/test_vec3.c | 16 ++++++++- test/src/test_vec4.c | 14 ++++++++ 10 files changed, 286 insertions(+), 2 deletions(-) diff --git a/docs/source/vec3.rst b/docs/source/vec3.rst index 86f17e4..1397700 100644 --- a/docs/source/vec3.rst +++ b/docs/source/vec3.rst @@ -46,6 +46,9 @@ Functions: #. :c:func:`glm_vec_scale_as` #. :c:func:`glm_vec_div` #. :c:func:`glm_vec_divs` +#. :c:func:`glm_vec_addadd` +#. :c:func:`glm_vec_subadd` +#. :c:func:`glm_vec_muladd` #. :c:func:`glm_vec_flipsign` #. :c:func:`glm_vec_flipsign_to` #. :c:func:`glm_vec_inv` @@ -220,6 +223,36 @@ Functions documentation | *[in]* **s** scalar | *[out]* **dest** result = (a[0] / s, a[1] / s, a[2] / s]) +.. c:function:: void glm_vec_addadd(vec3 a, vec3 b, vec3 dest) + + | add two vectors and add result to sum + | it applies += operator so dest must be initialized + + Parameters: + | *[in]* **a** vector 1 + | *[in]* **b** vector 2 + | *[out]* **dest** dest += (a + b) + +.. c:function:: void glm_vec_subadd(vec3 a, vec3 b, vec3 dest) + + | sub two vectors and add result to sum + | it applies += operator so dest must be initialized + + Parameters: + | *[in]* **a** vector 1 + | *[in]* **b** vector 2 + | *[out]* **dest** dest += (a - b) + +.. c:function:: void glm_vec_muladd(vec3 a, vec3 b, vec3 dest) + + | mul two vectors and add result to sum + | it applies += operator so dest must be initialized + + Parameters: + | *[in]* **a** vector 1 + | *[in]* **b** vector 2 + | *[out]* **dest** dest += (a * b) + .. c:function:: void glm_vec_flipsign(vec3 v) flip sign of all vec3 members diff --git a/docs/source/vec4.rst b/docs/source/vec4.rst index 89ac5c2..bd27978 100644 --- a/docs/source/vec4.rst +++ b/docs/source/vec4.rst @@ -38,6 +38,9 @@ Functions: #. :c:func:`glm_vec4_scale_as` #. :c:func:`glm_vec4_div` #. :c:func:`glm_vec4_divs` +#. :c:func:`glm_vec4_addadd` +#. :c:func:`glm_vec4_subadd` +#. :c:func:`glm_vec4_muladd` #. :c:func:`glm_vec4_flipsign` #. :c:func:`glm_vec_flipsign_to` #. :c:func:`glm_vec4_inv` @@ -205,6 +208,36 @@ Functions documentation | *[in]* **s** scalar | *[out]* **dest** result = (a[0] / s, a[1] / s, a[2] / s, a[3] / s) +.. c:function:: void glm_vec4_addadd(vec4 a, vec4 b, vec4 dest) + + | add two vectors and add result to sum + | it applies += operator so dest must be initialized + + Parameters: + | *[in]* **a** vector 1 + | *[in]* **b** vector 2 + | *[out]* **dest** dest += (a + b) + +.. c:function:: void glm_vec4_subadd(vec4 a, vec4 b, vec4 dest) + + | sub two vectors and add result to sum + | it applies += operator so dest must be initialized + + Parameters: + | *[in]* **a** vector 1 + | *[in]* **b** vector 2 + | *[out]* **dest** dest += (a - b) + +.. c:function:: void glm_vec4_muladd(vec4 a, vec4 b, vec4 dest) + + | mul two vectors and add result to sum + | it applies += operator so dest must be initialized + + Parameters: + | *[in]* **a** vector 1 + | *[in]* **b** vector 2 + | *[out]* **dest** dest += (a * b) + .. c:function:: void glm_vec4_flipsign(vec4 v) flip sign of all vec4 members diff --git a/include/cglm/call/vec3.h b/include/cglm/call/vec3.h index b2374e6..495ad0b 100644 --- a/include/cglm/call/vec3.h +++ b/include/cglm/call/vec3.h @@ -92,6 +92,18 @@ CGLM_EXPORT void glmc_vec_divs(vec3 a, float s, vec3 dest); +CGLM_EXPORT +void +glmc_vec_addadd(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec_subadd(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec_muladd(vec3 a, vec3 b, vec3 dest); + CGLM_EXPORT void glmc_vec_flipsign(vec3 v); diff --git a/include/cglm/call/vec4.h b/include/cglm/call/vec4.h index b460962..0fea5bf 100644 --- a/include/cglm/call/vec4.h +++ b/include/cglm/call/vec4.h @@ -93,6 +93,18 @@ CGLM_EXPORT void glmc_vec4_divs(vec4 v, float s, vec4 dest); +CGLM_EXPORT +void +glmc_vec4_addadd(vec4 a, vec4 b, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_subadd(vec4 a, vec4 b, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_muladd(vec4 a, vec4 b, vec4 dest); + CGLM_EXPORT void glmc_vec4_flipsign(vec4 v); diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index b3012b6..f803af6 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -37,6 +37,9 @@ CGLM_INLINE void glm_vec_scale_as(vec3 v, float s, vec3 dest); CGLM_INLINE void glm_vec_div(vec3 a, vec3 b, vec3 dest); CGLM_INLINE void glm_vec_divs(vec3 a, float s, vec3 dest); + CGLM_INLINE void glm_vec_addadd(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec_subadd(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec_muladd(vec3 a, vec3 b, vec3 dest); CGLM_INLINE void glm_vec_flipsign(vec3 v); CGLM_INLINE void glm_vec_inv(vec3 v); CGLM_INLINE void glm_vec_inv_to(vec3 v, vec3 dest); @@ -335,6 +338,57 @@ glm_vec_divs(vec3 v, float s, vec3 dest) { dest[2] = v[2] / s; } +/*! + * @brief add two vectors and add result to sum + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += (a + b) + */ +CGLM_INLINE +void +glm_vec_addadd(vec3 a, vec3 b, vec3 dest) { + dest[0] += a[0] + b[0]; + dest[1] += a[1] + b[1]; + dest[2] += a[2] + b[2]; +} + +/*! + * @brief sub two vectors and add result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += (a + b) + */ +CGLM_INLINE +void +glm_vec_subadd(vec3 a, vec3 b, vec3 dest) { + dest[0] += a[0] - b[0]; + dest[1] += a[1] - b[1]; + dest[2] += a[2] - b[2]; +} + +/*! + * @brief mul two vectors and add result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += (a * b) + */ +CGLM_INLINE +void +glm_vec_muladd(vec3 a, vec3 b, vec3 dest) { + dest[0] += a[0] * b[0]; + dest[1] += a[1] * b[1]; + dest[2] += a[2] * b[2]; +} + /*! * @brief flip sign of all vec3 members * diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index e1319b9..c07a45e 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -37,6 +37,9 @@ CGLM_INLINE void glm_vec4_scale_as(vec4 v, float s, vec4 dest); CGLM_INLINE void glm_vec4_div(vec4 a, vec4 b, vec4 dest); CGLM_INLINE void glm_vec4_divs(vec4 v, float s, vec4 dest); + CGLM_INLINE void glm_vec4_addadd(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_subadd(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_muladd(vec4 a, vec4 b, vec4 dest); CGLM_INLINE void glm_vec4_flipsign(vec4 v); CGLM_INLINE void glm_vec4_inv(vec4 v); CGLM_INLINE void glm_vec4_inv_to(vec4 v, vec4 dest); @@ -396,6 +399,79 @@ glm_vec4_divs(vec4 v, float s, vec4 dest) { #endif } + +/*! + * @brief add two vectors and add result to sum + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += (a + b) + */ +CGLM_INLINE +void +glm_vec4_addadd(vec4 a, vec4 b, vec4 dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(dest, _mm_add_ps(_mm_load_ps(dest), + _mm_add_ps(_mm_load_ps(a), + _mm_load_ps(b)))); +#else + dest[0] += a[0] + b[0]; + dest[1] += a[1] + b[1]; + dest[2] += a[2] + b[2]; + dest[3] += a[3] + b[3]; +#endif +} + +/*! + * @brief sub two vectors and add result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += (a - b) + */ +CGLM_INLINE +void +glm_vec4_subadd(vec4 a, vec4 b, vec4 dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(dest, _mm_add_ps(_mm_load_ps(dest), + _mm_sub_ps(_mm_load_ps(a), + _mm_load_ps(b)))); +#else + dest[0] += a[0] - b[0]; + dest[1] += a[1] - b[1]; + dest[2] += a[2] - b[2]; + dest[3] += a[3] - b[3]; +#endif +} + +/*! + * @brief mul two vectors and add result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += (a * b) + */ +CGLM_INLINE +void +glm_vec4_muladd(vec4 a, vec4 b, vec4 dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(dest, _mm_add_ps(_mm_load_ps(dest), + _mm_mul_ps(_mm_load_ps(a), + _mm_load_ps(b)))); +#else + dest[0] += a[0] * b[0]; + dest[1] += a[1] * b[1]; + dest[2] += a[2] * b[2]; + dest[3] += a[3] * b[3]; +#endif +} + /*! * @brief flip sign of all vec4 members * diff --git a/src/vec3.c b/src/vec3.c index b8553ec..d484446 100644 --- a/src/vec3.c +++ b/src/vec3.c @@ -122,6 +122,24 @@ glmc_vec_divs(vec3 a, float s, vec3 dest) { glm_vec_divs(a, s, dest); } +CGLM_EXPORT +void +glmc_vec_addadd(vec3 a, vec3 b, vec3 dest) { + glm_vec_addadd(a, b, dest); +} + +CGLM_EXPORT +void +glmc_vec_subadd(vec3 a, vec3 b, vec3 dest) { + glm_vec_subadd(a, b, dest); +} + +CGLM_EXPORT +void +glmc_vec_muladd(vec3 a, vec3 b, vec3 dest) { + glm_vec_muladd(a, b, dest); +} + CGLM_EXPORT void glmc_vec_flipsign(vec3 v) { diff --git a/src/vec4.c b/src/vec4.c index 282712c..c3df5d2 100644 --- a/src/vec4.c +++ b/src/vec4.c @@ -106,7 +106,7 @@ glmc_vec4_scale(vec4 v, float s, vec4 dest) { CGLM_EXPORT void -glmc_vec4_scale_as(vec3 v, float s, vec3 dest) { +glmc_vec4_scale_as(vec4 v, float s, vec4 dest) { glm_vec4_scale_as(v, s, dest); } @@ -122,6 +122,24 @@ glmc_vec4_divs(vec4 v, float s, vec4 dest) { glm_vec4_divs(v, s, dest); } +CGLM_EXPORT +void +glmc_vec4_addadd(vec4 a, vec4 b, vec4 dest) { + glm_vec4_addadd(a, b, dest); +} + +CGLM_EXPORT +void +glmc_vec4_subadd(vec4 a, vec4 b, vec4 dest) { + glm_vec4_subadd(a, b, dest); +} + +CGLM_EXPORT +void +glmc_vec4_muladd(vec4 a, vec4 b, vec4 dest) { + glm_vec4_muladd(a, b, dest); +} + CGLM_EXPORT void glmc_vec4_flipsign(vec4 v) { diff --git a/test/src/test_vec3.c b/test/src/test_vec3.c index c33e5ec..7c85d1f 100644 --- a/test/src/test_vec3.c +++ b/test/src/test_vec3.c @@ -9,7 +9,7 @@ void test_vec3(void **state) { - vec3 v, v1; + vec3 v, v1, v2; /* test zero */ glm_vec_zero(v); @@ -49,4 +49,18 @@ test_vec3(void **state) { glm_vec_scale(v1, 0.8, v1); glm_vec_scale_as(v, 0.8, v); test_assert_vec3_eq(v1, v); + + /* addadd, subadd, muladd */ + glm_vec_one(v); + + glm_vec_addadd(GLM_VEC3_ONE, GLM_VEC3_ONE, v); + assert_true(glmc_vec_eq_eps(v, 3)); + + glm_vec_subadd(GLM_VEC3_ONE, GLM_VEC3_ZERO, v); + assert_true(glmc_vec_eq_eps(v, 4)); + + glm_vec_broadcast(2, v1); + glm_vec_broadcast(3, v2); + glm_vec_muladd(v1, v2, v); + assert_true(glmc_vec_eq_eps(v, 10)); } diff --git a/test/src/test_vec4.c b/test/src/test_vec4.c index 60772a9..93ce9f7 100644 --- a/test/src/test_vec4.c +++ b/test/src/test_vec4.c @@ -109,4 +109,18 @@ test_vec4(void **state) { glm_vec4_scale(v1, 0.8, v1); glm_vec4_scale_as(v, 0.8, v); test_assert_vec4_eq(v1, v); + + /* addadd, subadd, muladd */ + glm_vec4_one(v); + + glm_vec4_addadd(GLM_VEC4_ONE, GLM_VEC4_ONE, v); + assert_true(glmc_vec4_eq_eps(v, 3)); + + glm_vec4_subadd(GLM_VEC4_ONE, GLM_VEC4_ZERO, v); + assert_true(glmc_vec4_eq_eps(v, 4)); + + glm_vec4_broadcast(2, v1); + glm_vec4_broadcast(3, v2); + glm_vec4_muladd(v1, v2, v); + assert_true(glmc_vec4_eq_eps(v, 10)); } From 725fac75d03863904c4295bbd638aa38dc7c0317 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 13 Apr 2018 15:47:45 +0300 Subject: [PATCH 51/98] now working on v0.4.1 --- configure.ac | 2 +- include/cglm/version.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 6e22248..814f776 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ #***************************************************************************** AC_PREREQ([2.69]) -AC_INIT([cglm], [0.4.0], [info@recp.me]) +AC_INIT([cglm], [0.4.1], [info@recp.me]) AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/include/cglm/version.h b/include/cglm/version.h index 9a54b03..94fed8a 100644 --- a/include/cglm/version.h +++ b/include/cglm/version.h @@ -10,6 +10,6 @@ #define CGLM_VERSION_MAJOR 0 #define CGLM_VERSION_MINOR 4 -#define CGLM_VERSION_PATCH 0 +#define CGLM_VERSION_PATCH 1 #endif /* cglm_version_h */ From 13345f06c131572d8bdc265a33b8993e916ca238 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 13 Apr 2018 15:50:05 +0300 Subject: [PATCH 52/98] fix vec4 scalar ops --- include/cglm/vec4.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index c07a45e..26247c7 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -198,7 +198,7 @@ glm_vec4_norm2(vec4 v) { x0 = _mm_add_ps(x0, _mm_shuffle1_ps(x0, 1, 0, 3, 2)); return _mm_cvtss_f32(_mm_add_ss(x0, _mm_shuffle1_ps(x0, 0, 1, 0, 1))); #else - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; + return v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]; #endif } @@ -254,10 +254,10 @@ glm_vec4_adds(vec4 v, float s, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) _mm_store_ps(dest, _mm_add_ps(_mm_load_ps(v), _mm_set1_ps(s))); #else - dest[0] = v1[0] + s; - dest[1] = v1[1] + s; - dest[2] = v1[2] + s; - dest[3] = v1[3] + s; + dest[0] = v[0] + s; + dest[1] = v[1] + s; + dest[2] = v[2] + s; + dest[3] = v[3] + s; #endif } @@ -294,10 +294,10 @@ glm_vec4_subs(vec4 v, float s, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) _mm_store_ps(dest, _mm_sub_ps(_mm_load_ps(v), _mm_set1_ps(s))); #else - dest[0] = v1[0] - s; - dest[1] = v1[1] - s; - dest[2] = v1[2] - s; - dest[3] = v1[3] - s; + dest[0] = v[0] - s; + dest[1] = v[1] - s; + dest[2] = v[2] - s; + dest[3] = v[3] - s; #endif } From 7f7007574b11c9fc4d03f138d2fd16555c24e4bc Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 13 Apr 2018 22:30:44 +0300 Subject: [PATCH 53/98] vec: implement muladd's scalar version --- docs/source/vec3.rst | 11 +++++++++++ docs/source/vec4.rst | 11 +++++++++++ include/cglm/call/vec3.h | 4 ++++ include/cglm/call/vec4.h | 4 ++++ include/cglm/vec3.h | 17 +++++++++++++++++ include/cglm/vec4.h | 24 ++++++++++++++++++++++++ src/vec3.c | 6 ++++++ src/vec4.c | 6 ++++++ 8 files changed, 83 insertions(+) diff --git a/docs/source/vec3.rst b/docs/source/vec3.rst index 1397700..77aebb6 100644 --- a/docs/source/vec3.rst +++ b/docs/source/vec3.rst @@ -49,6 +49,7 @@ Functions: #. :c:func:`glm_vec_addadd` #. :c:func:`glm_vec_subadd` #. :c:func:`glm_vec_muladd` +#. :c:func:`glm_vec_muladds` #. :c:func:`glm_vec_flipsign` #. :c:func:`glm_vec_flipsign_to` #. :c:func:`glm_vec_inv` @@ -253,6 +254,16 @@ Functions documentation | *[in]* **b** vector 2 | *[out]* **dest** dest += (a * b) +.. c:function:: void glm_vec_muladds(vec3 a, float s, vec3 dest) + + | mul vector with scalar and add result to sum + | it applies += operator so dest must be initialized + + Parameters: + | *[in]* **a** vector + | *[in]* **s** scalar + | *[out]* **dest** dest += (a * b) + .. c:function:: void glm_vec_flipsign(vec3 v) flip sign of all vec3 members diff --git a/docs/source/vec4.rst b/docs/source/vec4.rst index bd27978..a1b7250 100644 --- a/docs/source/vec4.rst +++ b/docs/source/vec4.rst @@ -41,6 +41,7 @@ Functions: #. :c:func:`glm_vec4_addadd` #. :c:func:`glm_vec4_subadd` #. :c:func:`glm_vec4_muladd` +#. :c:func:`glm_vec4_muladds` #. :c:func:`glm_vec4_flipsign` #. :c:func:`glm_vec_flipsign_to` #. :c:func:`glm_vec4_inv` @@ -238,6 +239,16 @@ Functions documentation | *[in]* **b** vector 2 | *[out]* **dest** dest += (a * b) +.. c:function:: void glm_vec4_muladds(vec4 a, float s, vec4 dest) + + | mul vector with scalar and add result to sum + | it applies += operator so dest must be initialized + + Parameters: + | *[in]* **a** vector + | *[in]* **s** scalar + | *[out]* **dest** dest += (a * b) + .. c:function:: void glm_vec4_flipsign(vec4 v) flip sign of all vec4 members diff --git a/include/cglm/call/vec3.h b/include/cglm/call/vec3.h index 495ad0b..8fcee4f 100644 --- a/include/cglm/call/vec3.h +++ b/include/cglm/call/vec3.h @@ -104,6 +104,10 @@ CGLM_EXPORT void glmc_vec_muladd(vec3 a, vec3 b, vec3 dest); +CGLM_EXPORT +void +glmc_vec_muladds(vec3 a, float s, vec3 dest); + CGLM_EXPORT void glmc_vec_flipsign(vec3 v); diff --git a/include/cglm/call/vec4.h b/include/cglm/call/vec4.h index 0fea5bf..adcfc94 100644 --- a/include/cglm/call/vec4.h +++ b/include/cglm/call/vec4.h @@ -105,6 +105,10 @@ CGLM_EXPORT void glmc_vec4_muladd(vec4 a, vec4 b, vec4 dest); +CGLM_EXPORT +void +glmc_vec4_muladds(vec4 a, float s, vec4 dest); + CGLM_EXPORT void glmc_vec4_flipsign(vec4 v); diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index f803af6..9add4c3 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -389,6 +389,23 @@ glm_vec_muladd(vec3 a, vec3 b, vec3 dest) { dest[2] += a[2] * b[2]; } +/*! + * @brief mul vector with scalar and add result to sum + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest += (a * b) + */ +CGLM_INLINE +void +glm_vec_muladds(vec3 a, float s, vec3 dest) { + dest[0] += a[0] * s; + dest[1] += a[1] * s; + dest[2] += a[2] * s; +} + /*! * @brief flip sign of all vec3 members * diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index 26247c7..1824357 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -472,6 +472,30 @@ glm_vec4_muladd(vec4 a, vec4 b, vec4 dest) { #endif } +/*! + * @brief mul vector with scalar and add result to sum + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest += (a * b) + */ +CGLM_INLINE +void +glm_vec4_muladds(vec4 a, float s, vec4 dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(dest, _mm_add_ps(_mm_load_ps(dest), + _mm_mul_ps(_mm_load_ps(a), + _mm_set1_ps(s)))); +#else + dest[0] += a[0] * s; + dest[1] += a[1] * s; + dest[2] += a[2] * s; + dest[3] += a[3] * s; +#endif +} + /*! * @brief flip sign of all vec4 members * diff --git a/src/vec3.c b/src/vec3.c index d484446..28fda51 100644 --- a/src/vec3.c +++ b/src/vec3.c @@ -140,6 +140,12 @@ glmc_vec_muladd(vec3 a, vec3 b, vec3 dest) { glm_vec_muladd(a, b, dest); } +CGLM_EXPORT +void +glmc_vec_muladds(vec3 a, float s, vec3 dest) { + glm_vec_muladds(a, s, dest); +} + CGLM_EXPORT void glmc_vec_flipsign(vec3 v) { diff --git a/src/vec4.c b/src/vec4.c index c3df5d2..fb22796 100644 --- a/src/vec4.c +++ b/src/vec4.c @@ -140,6 +140,12 @@ glmc_vec4_muladd(vec4 a, vec4 b, vec4 dest) { glm_vec4_muladd(a, b, dest); } +CGLM_EXPORT +void +glmc_vec4_muladds(vec4 a, float s, vec4 dest) { + glm_vec4_muladds(a, s, dest); +} + CGLM_EXPORT void glmc_vec4_flipsign(vec4 v) { From d6395d4fb8dbfb90864ab8a6fd3456165236a956 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 13 Apr 2018 22:33:32 +0300 Subject: [PATCH 54/98] vec: optimize rotate vector using matrix * add mat3 version --- docs/source/vec3.rst | 10 +++++++++ include/cglm/vec3.h | 50 +++++++++++++++++++++++++++++++++++++------- test/src/test_vec3.c | 12 +++++++++++ 3 files changed, 64 insertions(+), 8 deletions(-) diff --git a/docs/source/vec3.rst b/docs/source/vec3.rst index 77aebb6..fcbfbfb 100644 --- a/docs/source/vec3.rst +++ b/docs/source/vec3.rst @@ -60,6 +60,7 @@ Functions: #. :c:func:`glm_vec_angle` #. :c:func:`glm_vec_rotate` #. :c:func:`glm_vec_rotate_m4` +#. :c:func:`glm_vec_rotate_m3` #. :c:func:`glm_vec_proj` #. :c:func:`glm_vec_center` #. :c:func:`glm_vec_maxv` @@ -338,6 +339,15 @@ Functions documentation | *[in]* **v** vector | *[out]* **dest** rotated vector +.. c:function:: void glm_vec_rotate_m3(mat3 m, vec3 v, vec3 dest) + + apply rotation matrix to vector + + Parameters: + | *[in]* **m** affine matrix or rot matrix + | *[in]* **v** vector + | *[out]* **dest** rotated vector + .. c:function:: void glm_vec_proj(vec3 a, vec3 b, vec3 dest) project a vector onto b vector diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index 9add4c3..9976ad9 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -67,6 +67,7 @@ #define cglm_vec3_h #include "common.h" +#include "vec4.h" #include "vec3-ext.h" #include "util.h" @@ -551,6 +552,12 @@ glm_vec_rotate(vec3 v, float angle, vec3 axis) { /*! * @brief apply rotation matrix to vector * + * matrix format should be (no perspective): + * a b c x + * e f g y + * i j k z + * 0 0 0 w + * * @param[in] m affine matrix or rot matrix * @param[in] v vector * @param[out] dest rotated vector @@ -558,17 +565,44 @@ glm_vec_rotate(vec3 v, float angle, vec3 axis) { CGLM_INLINE void glm_vec_rotate_m4(mat4 m, vec3 v, vec3 dest) { - vec3 res, x, y, z; + vec4 x, y, z, res; - glm_vec_normalize_to(m[0], x); - glm_vec_normalize_to(m[1], y); - glm_vec_normalize_to(m[2], z); + glm_vec4_normalize_to(m[0], x); + glm_vec4_normalize_to(m[1], y); + glm_vec4_normalize_to(m[2], z); - res[0] = x[0] * v[0] + y[0] * v[1] + z[0] * v[2]; - res[1] = x[1] * v[0] + y[1] * v[1] + z[1] * v[2]; - res[2] = x[2] * v[0] + y[2] * v[1] + z[2] * v[2]; + glm_vec4_scale(x, v[0], res); + glm_vec4_muladds(y, v[1], res); + glm_vec4_muladds(y, v[2], res); - glm_vec_copy(res, dest); + glm_vec3(res, dest); +} + +/*! + * @brief apply rotation matrix to vector + * + * @param[in] m affine matrix or rot matrix + * @param[in] v vector + * @param[out] dest rotated vector + */ +CGLM_INLINE +void +glm_vec_rotate_m3(mat3 m, vec3 v, vec3 dest) { + vec4 res, x, y, z; + + glm_vec4(m[0], 0.0f, x); + glm_vec4(m[1], 0.0f, y); + glm_vec4(m[2], 0.0f, z); + + glm_vec4_normalize(x); + glm_vec4_normalize(y); + glm_vec4_normalize(z); + + glm_vec4_scale(x, v[0], res); + glm_vec4_muladds(y, v[1], res); + glm_vec4_muladds(y, v[2], res); + + glm_vec3(res, dest); } /*! diff --git a/test/src/test_vec3.c b/test/src/test_vec3.c index 7c85d1f..dd0c55d 100644 --- a/test/src/test_vec3.c +++ b/test/src/test_vec3.c @@ -9,6 +9,8 @@ void test_vec3(void **state) { + mat3 rot1m3; + mat4 rot1; vec3 v, v1, v2; /* test zero */ @@ -63,4 +65,14 @@ test_vec3(void **state) { glm_vec_broadcast(3, v2); glm_vec_muladd(v1, v2, v); assert_true(glmc_vec_eq_eps(v, 10)); + + /* rotate */ + glm_vec_copy(GLM_YUP, v); + glm_rotate_make(rot1, glm_rad(90), GLM_XUP); + glm_vec_rotate_m4(rot1, v, v1); + glm_mat4_pick3(rot1, rot1m3); + glm_vec_rotate_m3(rot1m3, v, v2); + + test_assert_vec3_eq(v1, v2); + test_assert_vec3_eq(v1, GLM_ZUP); } From 429aff087fb4a36e103de3ca95fb1ed113369637 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sat, 14 Apr 2018 11:35:28 +0300 Subject: [PATCH 55/98] optimize min and max for vec4 --- include/cglm/vec4.h | 8 ++++++++ test/src/test_vec4.c | 30 +++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index 1824357..f52fd6a 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -633,10 +633,14 @@ glm_vec4_distance(vec4 v1, vec4 v2) { CGLM_INLINE void glm_vec4_maxv(vec4 v1, vec4 v2, vec4 dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(dest, _mm_max_ps(_mm_load_ps(v1), _mm_load_ps(v2))); +#else dest[0] = glm_max(v1[0], v2[0]); dest[1] = glm_max(v1[1], v2[1]); dest[2] = glm_max(v1[2], v2[2]); dest[3] = glm_max(v1[3], v2[3]); +#endif } /*! @@ -649,10 +653,14 @@ glm_vec4_maxv(vec4 v1, vec4 v2, vec4 dest) { CGLM_INLINE void glm_vec4_minv(vec4 v1, vec4 v2, vec4 dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(dest, _mm_min_ps(_mm_load_ps(v1), _mm_load_ps(v2))); +#else dest[0] = glm_min(v1[0], v2[0]); dest[1] = glm_min(v1[1], v2[1]); dest[2] = glm_min(v1[2], v2[2]); dest[3] = glm_min(v1[3], v2[3]); +#endif } /*! diff --git a/test/src/test_vec4.c b/test/src/test_vec4.c index 93ce9f7..b9fb2ab 100644 --- a/test/src/test_vec4.c +++ b/test/src/test_vec4.c @@ -38,9 +38,25 @@ test_vec4_norm(vec4 vec) { return sqrtf(test_vec4_dot(vec, vec)); } +void +test_vec4_maxv(vec4 v1, vec4 v2, vec4 dest) { + dest[0] = glm_max(v1[0], v2[0]); + dest[1] = glm_max(v1[1], v2[1]); + dest[2] = glm_max(v1[2], v2[2]); + dest[3] = glm_max(v1[3], v2[3]); +} + +void +test_vec4_minv(vec4 v1, vec4 v2, vec4 dest) { + dest[0] = glm_min(v1[0], v2[0]); + dest[1] = glm_min(v1[1], v2[1]); + dest[2] = glm_min(v1[2], v2[2]); + dest[3] = glm_min(v1[3], v2[3]); +} + void test_vec4(void **state) { - vec4 v, v1, v2; + vec4 v, v1, v2, v3, v4; int i; float d1, d2; @@ -123,4 +139,16 @@ test_vec4(void **state) { glm_vec4_broadcast(3, v2); glm_vec4_muladd(v1, v2, v); assert_true(glmc_vec4_eq_eps(v, 10)); + + /* min, max */ + test_rand_vec4(v1); + test_rand_vec4(v2); + + glm_vec4_maxv(v1, v2, v3); + test_vec4_maxv(v1, v2, v4); + test_assert_vec4_eq(v3, v4); + + glm_vec4_minv(v1, v2, v3); + test_vec4_minv(v1, v2, v4); + test_assert_vec4_eq(v3, v4); } From 59aacee968d55e4af179fe88dd8bd7c6df5bef89 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sat, 14 Apr 2018 12:49:37 +0300 Subject: [PATCH 56/98] optimize clamp for vec4 --- include/cglm/vec4.h | 5 +++++ test/src/test_vec4.c | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index f52fd6a..aebef4a 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -673,10 +673,15 @@ glm_vec4_minv(vec4 v1, vec4 v2, vec4 dest) { CGLM_INLINE void glm_vec4_clamp(vec4 v, float minVal, float maxVal) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(v, _mm_min_ps(_mm_max_ps(_mm_load_ps(v), _mm_set1_ps(minVal)), + _mm_set1_ps(maxVal))); +#else 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 } /*! diff --git a/test/src/test_vec4.c b/test/src/test_vec4.c index b9fb2ab..8e4fda5 100644 --- a/test/src/test_vec4.c +++ b/test/src/test_vec4.c @@ -54,6 +54,14 @@ test_vec4_minv(vec4 v1, vec4 v2, vec4 dest) { dest[3] = glm_min(v1[3], v2[3]); } +void +test_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); +} + void test_vec4(void **state) { vec4 v, v1, v2, v3, v4; @@ -151,4 +159,20 @@ test_vec4(void **state) { glm_vec4_minv(v1, v2, v3); test_vec4_minv(v1, v2, v4); test_assert_vec4_eq(v3, v4); + + glm_vec4_print(v3, stderr); + glm_vec4_print(v4, stderr); + + /* clamp */ + glm_vec4_clamp(v3, 0.1, 0.8); + test_vec4_clamp(v4, 0.1, 0.8); + test_assert_vec4_eq(v3, v4); + + glm_vec4_print(v3, stderr); + glm_vec4_print(v4, stderr); + + assert_true(v3[0] >= 0.0999 && v3[0] <= 0.80001); /* rounding erros */ + assert_true(v3[1] >= 0.0999 && v3[1] <= 0.80001); + assert_true(v3[2] >= 0.0999 && v3[2] <= 0.80001); + assert_true(v3[3] >= 0.0999 && v3[3] <= 0.80001); } From b09b5f260b0f5fd5f0259804a568e0444c4b0014 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sun, 15 Apr 2018 12:44:50 +0300 Subject: [PATCH 57/98] vec: fix rotate vector using mat4 and mat3 rotation matrices --- include/cglm/vec3.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index 9976ad9..9bb9379 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -573,7 +573,7 @@ glm_vec_rotate_m4(mat4 m, vec3 v, vec3 dest) { glm_vec4_scale(x, v[0], res); glm_vec4_muladds(y, v[1], res); - glm_vec4_muladds(y, v[2], res); + glm_vec4_muladds(z, v[2], res); glm_vec3(res, dest); } @@ -600,7 +600,7 @@ glm_vec_rotate_m3(mat3 m, vec3 v, vec3 dest) { glm_vec4_scale(x, v[0], res); glm_vec4_muladds(y, v[1], res); - glm_vec4_muladds(y, v[2], res); + glm_vec4_muladds(z, v[2], res); glm_vec3(res, dest); } From 826ddf0f5bf87a37d507c8cc122047c07383ebef Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sun, 15 Apr 2018 12:46:29 +0300 Subject: [PATCH 58/98] improve normalize vectors --- include/cglm/vec3.h | 2 +- include/cglm/vec4.h | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index 9bb9379..50636a1 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -492,7 +492,7 @@ glm_vec_normalize_to(vec3 vec, vec3 dest) { norm = glm_vec_norm(vec); if (norm == 0.0f) { - dest[0] = dest[1] = dest[2] = 0.0f; + glm_vec_zero(dest); return; } diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index aebef4a..2e9ca45 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -587,8 +587,7 @@ glm_vec4_normalize_to(vec4 vec, vec4 dest) { norm = glm_vec4_norm(vec); if (norm == 0.0f) { - dest[0] = dest[1] = dest[2] = dest[3] = 0.0f; - glm_vec4_broadcast(0.0f, dest); + glm_vec4_zero(dest); return; } From 007ae62e066d100fba598e4918d1c2fcfe06068e Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sun, 15 Apr 2018 13:10:07 +0300 Subject: [PATCH 59/98] update docs version --- docs/source/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 7ad96a1..616edfd 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -62,9 +62,9 @@ author = u'Recep Aslantas' # built documents. # # The short X.Y version. -version = u'0.3.4' +version = u'0.4.1' # The full version, including alpha/beta/rc tags. -release = u'0.3.4' +release = u'0.4.1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. From f0a27d0ce2833dc99cd49a151aad59da3fc41646 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sun, 15 Apr 2018 20:46:46 +0300 Subject: [PATCH 60/98] now working on v0.4.2 --- configure.ac | 2 +- include/cglm/version.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 814f776..0fc55a8 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ #***************************************************************************** AC_PREREQ([2.69]) -AC_INIT([cglm], [0.4.1], [info@recp.me]) +AC_INIT([cglm], [0.4.2], [info@recp.me]) AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/include/cglm/version.h b/include/cglm/version.h index 94fed8a..328a4d2 100644 --- a/include/cglm/version.h +++ b/include/cglm/version.h @@ -10,6 +10,6 @@ #define CGLM_VERSION_MAJOR 0 #define CGLM_VERSION_MINOR 4 -#define CGLM_VERSION_PATCH 1 +#define CGLM_VERSION_PATCH 2 #endif /* cglm_version_h */ From 821c79572f3f2631738c0cb9c5583349fdbf0d9a Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sun, 15 Apr 2018 20:47:38 +0300 Subject: [PATCH 61/98] test: add some tests for mat3 --- makefile.am | 3 ++- test/src/test_common.c | 23 +++++++++++++++++ test/src/test_common.h | 6 +++++ test/src/test_main.c | 3 +++ test/src/test_mat3.c | 58 ++++++++++++++++++++++++++++++++++++++++++ test/src/test_tests.h | 3 +++ 6 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 test/src/test_mat3.c diff --git a/makefile.am b/makefile.am index 00800c0..1a27132 100644 --- a/makefile.am +++ b/makefile.am @@ -111,7 +111,8 @@ test_tests_SOURCES=\ test/src/test_euler.c \ test/src/test_quat.c \ test/src/test_vec4.c \ - test/src/test_vec3.c + test/src/test_vec3.c \ + test/src/test_mat3.c all-local: sh ./post-build.sh diff --git a/test/src/test_common.c b/test/src/test_common.c index 60baac3..405000d 100644 --- a/test/src/test_common.c +++ b/test/src/test_common.c @@ -27,6 +27,17 @@ test_rand_mat4(mat4 dest) { /* glm_scale(dest, (vec3){drand48(), drand48(), drand48()}); */ } +void +test_rand_mat3(mat3 dest) { + mat4 m4; + + srand((unsigned int)time(NULL)); + + /* random rotatation around random axis with random angle */ + glm_rotate_make(m4, drand48(), (vec3){drand48(), drand48(), drand48()}); + glm_mat4_pick3(m4, dest); +} + void test_rand_vec3(vec3 dest) { srand((unsigned int)time(NULL)); @@ -84,6 +95,18 @@ test_assert_mat4_eq2(mat4 m1, mat4 m2, float eps) { } } +void +test_assert_mat3_eq(mat3 m1, mat3 m2) { + int i, j, k; + + for (i = 0; i < 3; i++) { + for (j = 0; j < 3; j++) { + for (k = 0; k < 3; k++) + assert_true(fabsf(m1[i][j] - m2[i][j]) <= 0.0000009); + } + } +} + void test_assert_eqf(float a, float b) { assert_true(fabsf(a - b) <= 0.000009); /* rounding errors */ diff --git a/test/src/test_common.h b/test/src/test_common.h index db113a4..7881e7a 100644 --- a/test/src/test_common.h +++ b/test/src/test_common.h @@ -25,6 +25,9 @@ void test_rand_mat4(mat4 dest); +void +test_rand_mat3(mat3 dest); + void test_assert_eqf(float a, float b); @@ -34,6 +37,9 @@ test_assert_mat4_eq(mat4 m1, mat4 m2); void test_assert_mat4_eq2(mat4 m1, mat4 m2, float eps); +void +test_assert_mat3_eq(mat3 m1, mat3 m2); + void test_assert_vec3_eq(vec3 v1, vec3 v2); diff --git a/test/src/test_main.c b/test/src/test_main.c index b0649cd..9e4f5aa 100644 --- a/test/src/test_main.c +++ b/test/src/test_main.c @@ -12,6 +12,9 @@ main(int argc, const char * argv[]) { /* mat4 */ cmocka_unit_test(test_mat4), + /* mat3 */ + cmocka_unit_test(test_mat3), + /* camera */ cmocka_unit_test(test_camera_lookat), cmocka_unit_test(test_camera_decomp), diff --git a/test/src/test_mat3.c b/test/src/test_mat3.c new file mode 100644 index 0000000..d97d1f5 --- /dev/null +++ b/test/src/test_mat3.c @@ -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 + */ + +#include "test_common.h" + +#define m 3 +#define n 3 + +void +test_mat3(void **state) { + mat3 m1 = GLM_MAT3_IDENTITY_INIT; + mat3 m2 = GLM_MAT3_IDENTITY_INIT; + mat3 m3; + mat3 m4 = GLM_MAT3_ZERO_INIT; + mat3 m5; + int i, j, k; + + /* test identity matrix multiplication */ + glmc_mat3_mul(m1, m2, m3); + for (i = 0; i < m; i++) { + for (j = 0; j < n; j++) { + if (i == j) + assert_true(m3[i][j] == 1.0f); + else + assert_true(m3[i][j] == 0.0f); + } + } + + /* test random matrices */ + /* random matrices */ + test_rand_mat3(m1); + test_rand_mat3(m2); + + glmc_mat3_mul(m1, m2, m3); + for (i = 0; i < m; i++) { + for (j = 0; j < n; j++) { + for (k = 0; k < m; k++) + /* column-major */ + m4[i][j] += m1[k][j] * m2[i][k]; + } + } + + test_assert_mat3_eq(m3, m4); + + for (i = 0; i < 100000; i++) { + test_rand_mat3(m3); + test_rand_mat3(m4); + + /* test inverse precise */ + glmc_mat3_inv(m3, m4); + glmc_mat3_inv(m4, m5); + test_assert_mat3_eq(m3, m5); + } +} diff --git a/test/src/test_tests.h b/test/src/test_tests.h index 224d943..dea8860 100644 --- a/test/src/test_tests.h +++ b/test/src/test_tests.h @@ -9,6 +9,9 @@ /* mat4 */ void test_mat4(void **state); +/* mat3 */ +void test_mat3(void **state); + /* camera */ void test_camera_lookat(void **state); From cefd5fb53d50e0b3089ab075fc220c8c3ae630a1 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 17 Apr 2018 10:33:52 +0300 Subject: [PATCH 62/98] test: add some tests for affine transforms --- makefile.am | 3 +- test/src/test_affine.c | 104 +++++++++++++++++++++++++++++++++++++++++ test/src/test_main.c | 5 +- test/src/test_tests.h | 3 ++ 4 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 test/src/test_affine.c diff --git a/makefile.am b/makefile.am index 1a27132..a0c06a9 100644 --- a/makefile.am +++ b/makefile.am @@ -112,7 +112,8 @@ test_tests_SOURCES=\ test/src/test_quat.c \ test/src/test_vec4.c \ test/src/test_vec3.c \ - test/src/test_mat3.c + test/src/test_mat3.c \ + test/src/test_affine.c all-local: sh ./post-build.sh diff --git a/test/src/test_affine.c b/test/src/test_affine.c new file mode 100644 index 0000000..4ce4a42 --- /dev/null +++ b/test/src/test_affine.c @@ -0,0 +1,104 @@ +/* + * 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_affine(void **state) { + mat4 t1, t2, t3, t4, t5; + + /* test translate is postmultiplied */ + glmc_rotate_make(t1, M_PI_4, GLM_YUP); + glm_translate_make(t2, (vec3){34, 57, 36}); + + glmc_mat4_mul(t1, t2, t3); /* R * T */ + + glm_translate(t1, (vec3){34, 57, 36}); + test_assert_mat4_eq(t1, t3); + + /* test rotate is postmultiplied */ + glmc_rotate_make(t1, M_PI_4, GLM_YUP); + glm_translate_make(t2, (vec3){34, 57, 36}); + + glmc_mat4_mul(t2, t1, t3); /* T * R */ + + glm_rotate(t2, M_PI_4, GLM_YUP); + test_assert_mat4_eq(t2, t3); + + /* test scale is postmultiplied */ + glmc_rotate_make(t1, M_PI_4, GLM_YUP); + glm_translate_make(t2, (vec3){34, 57, 36}); + glm_scale_make(t4, (vec3){3, 5, 6}); + + glmc_mat4_mul(t2, t1, t3); /* T * R */ + glmc_mat4_mul(t3, t4, t5); /* T * R * S */ + + glm_scale(t3, (vec3){3, 5, 6}); + test_assert_mat4_eq(t3, t5); + + /* test translate_x */ + glmc_rotate_make(t1, M_PI_4, GLM_YUP); + glm_translate_make(t2, (vec3){34, 0, 0}); + + glmc_mat4_mul(t1, t2, t3); /* R * T */ + glm_translate_x(t1, 34); + test_assert_mat4_eq(t1, t3); + + /* test translate_y */ + glmc_rotate_make(t1, M_PI_4, GLM_YUP); + glm_translate_make(t2, (vec3){0, 57, 0}); + + glmc_mat4_mul(t1, t2, t3); /* R * T */ + glm_translate_y(t1, 57); + test_assert_mat4_eq(t1, t3); + + /* test translate_z */ + glmc_rotate_make(t1, M_PI_4, GLM_YUP); + glm_translate_make(t2, (vec3){0, 0, 36}); + + glmc_mat4_mul(t1, t2, t3); /* R * T */ + glm_translate_z(t1, 36); + test_assert_mat4_eq(t1, t3); + + /* test rotate_x */ + glmc_rotate_make(t1, M_PI_4, (vec3){1, 0, 0}); + glm_translate_make(t2, (vec3){34, 57, 36}); + + glmc_mat4_mul(t2, t1, t3); /* T * R */ + + glm_rotate_x(t2, M_PI_4, t2); + test_assert_mat4_eq(t2, t3); + + /* test rotate_y */ + glmc_rotate_make(t1, M_PI_4, (vec3){0, 1, 0}); + glm_translate_make(t2, (vec3){34, 57, 36}); + + glmc_mat4_mul(t2, t1, t3); /* T * R */ + + glm_rotate_y(t2, M_PI_4, t2); + test_assert_mat4_eq(t2, t3); + + /* test rotate_z */ + glmc_rotate_make(t1, M_PI_4, (vec3){0, 0, 1}); + glm_translate_make(t2, (vec3){34, 57, 36}); + + glmc_mat4_mul(t2, t1, t3); /* T * R */ + + glm_rotate_z(t2, M_PI_4, t2); + test_assert_mat4_eq(t2, t3); + + /* test scale_uni */ + glmc_rotate_make(t1, M_PI_4, GLM_YUP); + glm_translate_make(t2, (vec3){34, 57, 36}); + glm_scale_make(t4, (vec3){3, 3, 3}); + + glmc_mat4_mul(t2, t1, t3); /* T * R */ + glmc_mat4_mul(t3, t4, t5); /* T * R * S */ + + glm_scale_uni(t3, 3); + test_assert_mat4_eq(t3, t5); +} diff --git a/test/src/test_main.c b/test/src/test_main.c index 9e4f5aa..ff77b02 100644 --- a/test/src/test_main.c +++ b/test/src/test_main.c @@ -35,7 +35,10 @@ main(int argc, const char * argv[]) { cmocka_unit_test(test_vec4), /* vec3 */ - cmocka_unit_test(test_vec3) + cmocka_unit_test(test_vec3), + + /* affine */ + cmocka_unit_test(test_affine) }; return cmocka_run_group_tests(tests, NULL, NULL); diff --git a/test/src/test_tests.h b/test/src/test_tests.h index dea8860..7b9cf0a 100644 --- a/test/src/test_tests.h +++ b/test/src/test_tests.h @@ -37,4 +37,7 @@ test_vec4(void **state); void test_vec3(void **state); +void +test_affine(void **state); + #endif /* test_tests_h */ From a2792178dba99301e4524a30be4338673930d12c Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 17 Apr 2018 11:07:57 +0300 Subject: [PATCH 63/98] add missing call funcs for affine transforms --- include/cglm/call/affine.h | 16 ++++++++++++++++ src/affine.c | 24 ++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/include/cglm/call/affine.h b/include/cglm/call/affine.h index 3d462ee..65dfae0 100644 --- a/include/cglm/call/affine.h +++ b/include/cglm/call/affine.h @@ -13,6 +13,10 @@ extern "C" { #include "../cglm.h" +CGLM_EXPORT +void +glmc_translate_make(mat4 m, vec3 v); + CGLM_EXPORT void glmc_translate_to(mat4 m, vec3 v, mat4 dest); @@ -33,6 +37,10 @@ CGLM_EXPORT void glmc_translate_z(mat4 m, float to); +CGLM_EXPORT +void +glmc_scale_make(mat4 m, vec3 v); + CGLM_EXPORT void glmc_scale_to(mat4 m, vec3 v, mat4 dest); @@ -45,6 +53,10 @@ CGLM_EXPORT void glmc_scale1(mat4 m, float s); +CGLM_EXPORT +void +glmc_scale_uni(mat4 m, float s); + CGLM_EXPORT void glmc_rotate_x(mat4 m, float rad, mat4 dest); @@ -77,6 +89,10 @@ CGLM_EXPORT void glmc_decompose_scalev(mat4 m, vec3 s); +CGLM_EXPORT +bool +glmc_uniscaled(mat4 m); + CGLM_EXPORT void glmc_decompose_rs(mat4 m, mat4 r, vec3 s); diff --git a/src/affine.c b/src/affine.c index df591df..056947f 100644 --- a/src/affine.c +++ b/src/affine.c @@ -8,6 +8,12 @@ #include "../include/cglm/cglm.h" #include "../include/cglm/call.h" +CGLM_EXPORT +void +glmc_translate_make(mat4 m, vec3 v) { + glm_translate_make(m, v); +} + CGLM_EXPORT void glmc_translate_to(mat4 m, vec3 v, mat4 dest) { @@ -38,6 +44,12 @@ glmc_translate_z(mat4 m, float to) { glm_translate_z(m, to); } +CGLM_EXPORT +void +glmc_scale_make(mat4 m, vec3 v) { + glm_scale_make(m, v); +} + CGLM_EXPORT void glmc_scale_to(mat4 m, vec3 v, mat4 dest) { @@ -56,6 +68,12 @@ glmc_scale1(mat4 m, float s) { glm_scale1(m, s); } +CGLM_EXPORT +void +glmc_scale_uni(mat4 m, float s) { + glm_scale_uni(m, s); +} + CGLM_EXPORT void glmc_rotate_x(mat4 m, float rad, mat4 dest) { @@ -104,6 +122,12 @@ glmc_decompose_scalev(mat4 m, vec3 s) { glm_decompose_scalev(m, s); } +CGLM_EXPORT +bool +glmc_uniscaled(mat4 m) { + return glm_uniscaled(m); +} + CGLM_EXPORT void glmc_decompose_rs(mat4 m, mat4 r, vec3 s) { From c63c6c90aceb7e8ead996775dc9c83f699f60514 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 17 Apr 2018 11:12:18 +0300 Subject: [PATCH 64/98] implement rotate_at --- include/cglm/affine.h | 24 ++++++++++++++++++++++-- include/cglm/call/affine.h | 4 ++++ src/affine.c | 6 ++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/include/cglm/affine.h b/include/cglm/affine.h index 10f190f..39c4290 100644 --- a/include/cglm/affine.h +++ b/include/cglm/affine.h @@ -400,7 +400,7 @@ glm_rotate_make(mat4 m, float angle, vec3 axis) { } /*! - * @brief rotate existing transform matrix around Z axis by angle and axis + * @brief rotate existing transform matrix around given axis by angle * * this name may change in the future, axis must be normalized. * @@ -439,7 +439,7 @@ glm_rotate_ndc(mat4 m, float angle, vec3 axis_ndc) { } /*! - * @brief rotate existing transform matrix around Z axis by angle and axis + * @brief rotate existing transform matrix around given axis by angle * * @param[in, out] m affine transfrom * @param[in] angle angle (radians) @@ -454,6 +454,26 @@ glm_rotate(mat4 m, float angle, vec3 axis) { glm_rotate_ndc(m, angle, axis_ndc); } +/*! + * @brief rotate existing transform + * around given axis by angle at given pivot point (rotation center) + * + * @param[in, out] m affine transfrom + * @param[in] angle angle (radians) + * @param[in] axis axis + */ +CGLM_INLINE +void +glm_rotate_at(mat4 model, vec3 pivot, float angle, vec3 axis) { + vec3 pivotInv; + + glm_vec_inv_to(pivot, pivotInv); + + glm_translate(model, pivot); + glm_rotate(model, angle, axis); + glm_translate(model, pivotInv); +} + /*! * @brief decompose scale vector * diff --git a/include/cglm/call/affine.h b/include/cglm/call/affine.h index 65dfae0..6d6b872 100644 --- a/include/cglm/call/affine.h +++ b/include/cglm/call/affine.h @@ -85,6 +85,10 @@ CGLM_EXPORT void glmc_rotate(mat4 m, float angle, vec3 axis); +CGLM_EXPORT +void +glmc_rotate_at(mat4 model, vec3 pivot, float angle, vec3 axis); + CGLM_EXPORT void glmc_decompose_scalev(mat4 m, vec3 s); diff --git a/src/affine.c b/src/affine.c index 056947f..793d8ee 100644 --- a/src/affine.c +++ b/src/affine.c @@ -116,6 +116,12 @@ glmc_rotate(mat4 m, float angle, vec3 axis) { glm_rotate(m, angle, axis); } +CGLM_EXPORT +void +glmc_rotate_at(mat4 model, vec3 pivot, float angle, vec3 axis) { + glm_rotate_at(model, pivot, angle, axis); +} + CGLM_EXPORT void glmc_decompose_scalev(mat4 m, vec3 s) { From 33e951fe2e738cf8a6c8185c181a285ac6964102 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 17 Apr 2018 12:17:04 +0300 Subject: [PATCH 65/98] implement rotate_at for quat and provide make version --- include/cglm/affine.h | 40 ++++++++++++++++++++++++++--- include/cglm/call/affine.h | 6 ++++- include/cglm/call/quat.h | 8 ++++++ include/cglm/quat.h | 52 ++++++++++++++++++++++++++++++++++++++ src/affine.c | 10 ++++++-- src/quat.c | 12 +++++++++ 6 files changed, 121 insertions(+), 7 deletions(-) diff --git a/include/cglm/affine.h b/include/cglm/affine.h index 39c4290..a5abbb6 100644 --- a/include/cglm/affine.h +++ b/include/cglm/affine.h @@ -38,6 +38,11 @@ #include "vec4.h" #include "affine-mat.h" #include "util.h" +#include "mat4.h" + +CGLM_INLINE +void +glm_mat4_mul(mat4 m1, mat4 m2, mat4 dest); /*! * @brief translate existing transform matrix by v vector @@ -459,19 +464,46 @@ glm_rotate(mat4 m, float angle, vec3 axis) { * around given axis by angle at given pivot point (rotation center) * * @param[in, out] m affine transfrom + * @param[in] pivot rotation center * @param[in] angle angle (radians) * @param[in] axis axis */ CGLM_INLINE void -glm_rotate_at(mat4 model, vec3 pivot, float angle, vec3 axis) { +glm_rotate_at(mat4 m, vec3 pivot, float angle, vec3 axis) { vec3 pivotInv; glm_vec_inv_to(pivot, pivotInv); - glm_translate(model, pivot); - glm_rotate(model, angle, axis); - glm_translate(model, pivotInv); + glm_translate(m, pivot); + glm_rotate(m, angle, axis); + glm_translate(m, pivotInv); +} + +/*! + * @brief creates NEW rotation matrix by angle and axis at given point + * + * this creates rotation matrix, it assumes you don't have a matrix + * + * this should work faster than glm_rotate_at because it reduces + * one glm_translate. + * + * @param[out] m affine transfrom + * @param[in] pivot rotation center + * @param[in] angle angle (radians) + * @param[in] axis axis + */ +CGLM_INLINE +void +glm_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis) { + vec3 pivotInv; + + glm_vec_inv_to(pivot, pivotInv); + + glm_mat4_identity(m); + glm_vec_copy(pivot, m[3]); + glm_rotate(m, angle, axis); + glm_translate(m, pivotInv); } /*! diff --git a/include/cglm/call/affine.h b/include/cglm/call/affine.h index 6d6b872..a9982c2 100644 --- a/include/cglm/call/affine.h +++ b/include/cglm/call/affine.h @@ -87,7 +87,11 @@ glmc_rotate(mat4 m, float angle, vec3 axis); CGLM_EXPORT void -glmc_rotate_at(mat4 model, vec3 pivot, float angle, vec3 axis); +glmc_rotate_at(mat4 m, vec3 pivot, float angle, vec3 axis); + +CGLM_EXPORT +void +glmc_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis); CGLM_EXPORT void diff --git a/include/cglm/call/quat.h b/include/cglm/call/quat.h index d250f52..ae4c9ef 100644 --- a/include/cglm/call/quat.h +++ b/include/cglm/call/quat.h @@ -137,6 +137,14 @@ CGLM_EXPORT void glmc_quat_rotate(mat4 m, versor q, mat4 dest); +CGLM_EXPORT +void +glmc_quat_rotate_at(mat4 model, versor q, vec3 pivot); + +CGLM_EXPORT +void +glmc_quat_rotate_atm(mat4 m, versor q, vec3 pivot); + #ifdef __cplusplus } #endif diff --git a/include/cglm/quat.h b/include/cglm/quat.h index fa356d4..1139c1d 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -60,6 +60,10 @@ # include "simd/sse2/quat.h" #endif +CGLM_INLINE +void +glm_mat4_identity(mat4 mat); + CGLM_INLINE void glm_mat4_mulv(mat4 m, vec4 v, vec4 dest); @@ -68,6 +72,10 @@ CGLM_INLINE void glm_mat4_mul(mat4 m1, mat4 m2, mat4 dest); +CGLM_INLINE +void +glm_translate(mat4 m, vec3 v); + /* * IMPORTANT: * ---------------------------------------------------------------------------- @@ -740,4 +748,48 @@ glm_quat_rotate(mat4 m, versor q, mat4 dest) { glm_mat4_mul(m, rot, dest); } +/*! + * @brief rotate existing transform matrix using quaternion at pivot point + * + * @param[in, out] m existing transform matrix + * @param[in] q quaternion + * @param[out] pivot pivot + */ +CGLM_INLINE +void +glm_quat_rotate_at(mat4 model, versor q, vec3 pivot) { + vec3 pivotInv; + + glm_vec_inv_to(pivot, pivotInv); + + glm_translate(model, pivot); + glm_quat_rotate(model, q, model); + glm_translate(model, pivotInv); +} + +/*! + * @brief rotate NEW transform matrix using quaternion at pivot point + * + * this creates rotation matrix, it assumes you don't have a matrix + * + * this should work faster than glm_quat_rotate_at because it reduces + * one glm_translate. + * + * @param[out] m existing transform matrix + * @param[in] q quaternion + * @param[in] pivot pivot + */ +CGLM_INLINE +void +glm_quat_rotate_atm(mat4 m, versor q, vec3 pivot) { + vec3 pivotInv; + + glm_vec_inv_to(pivot, pivotInv); + + glm_mat4_identity(m); + glm_vec_copy(pivot, m[3]); + glm_quat_rotate(m, q, m); + glm_translate(m, pivotInv); +} + #endif /* cglm_quat_h */ diff --git a/src/affine.c b/src/affine.c index 793d8ee..1da12d6 100644 --- a/src/affine.c +++ b/src/affine.c @@ -118,8 +118,14 @@ glmc_rotate(mat4 m, float angle, vec3 axis) { CGLM_EXPORT void -glmc_rotate_at(mat4 model, vec3 pivot, float angle, vec3 axis) { - glm_rotate_at(model, pivot, angle, axis); +glmc_rotate_at(mat4 m, vec3 pivot, float angle, vec3 axis) { + glm_rotate_at(m, pivot, angle, axis); +} + +CGLM_EXPORT +void +glmc_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis) { + glm_rotate_atm(m, pivot, angle, axis); } CGLM_EXPORT diff --git a/src/quat.c b/src/quat.c index 8a9a463..c47761d 100644 --- a/src/quat.c +++ b/src/quat.c @@ -194,3 +194,15 @@ void glmc_quat_rotate(mat4 m, versor q, mat4 dest) { glm_quat_rotate(m, q, dest); } + +CGLM_EXPORT +void +glmc_quat_rotate_at(mat4 model, versor q, vec3 pivot) { + glm_quat_rotate_at(model, q, pivot); +} + +CGLM_EXPORT +void +glmc_quat_rotate_atm(mat4 m, versor q, vec3 pivot) { + glm_quat_rotate_atm(m, q, pivot); +} From 27ab6a7dd0c268df32f0d7b57aa6eca5c7d6d970 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 17 Apr 2018 15:42:24 +0300 Subject: [PATCH 66/98] update docs, add clarifications for affine transforms --- docs/source/affine.rst | 117 +++++++++++++++++++++++++++++++++++++++++ docs/source/quat.rst | 24 +++++++++ include/cglm/affine.h | 4 +- include/cglm/quat.h | 8 +-- 4 files changed, 148 insertions(+), 5 deletions(-) diff --git a/docs/source/affine.rst b/docs/source/affine.rst index c34921f..8eaf01c 100644 --- a/docs/source/affine.rst +++ b/docs/source/affine.rst @@ -5,6 +5,8 @@ affine transforms Header: cglm/affine.h +Initialize Transform Matrices +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Functions with **_make** prefix expect you don't have a matrix and they create a matrix for you. You don't need to pass identity matrix. @@ -15,6 +17,96 @@ before sending to transfrom functions. There are also functions to decompose transform matrix. These functions can't decompose matrix after projected. +Rotation Center +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Rotating functions uses origin as rotation center (pivot/anchor point), +since scale factors are stored in rotation matrix, same may also true for scalling. +cglm provides some functions for rotating around at given point e.g. +**glm_rotate_at**, **glm_quat_rotate_at**. Use them or follow next section for algorihm ("Rotate or Scale around specific Point (Pivot Point / Anchor Point)"). + +Rotate or Scale around specific Point (Anchor Point) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you want to rotate model around arbibtrary point follow these steps: + +1. Move model from pivot point to origin: **translate(-pivot.x, -pivot.y, -pivot.z)** +2. Apply rotation (or scaling maybe) +3. Move model back from origin to pivot (reverse of step-1): **translate(pivot.x, pivot.y, pivot.z)** + +**glm_rotate_at**, **glm_quat_rotate_at** and their helper functions works that way. + +Transforms Order +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It is important to understand this part especially if you call transform +functions multiple times + +`glm_translate`, `glm_rotate`, `glm_scale` and `glm_quat_rotate` and their +helpers functions works like this (cglm may provide reverse order too as alternative in the future): + +.. code-block:: c + :linenos: + + TransformMatrix = TransformMatrix * TraslateMatrix; // glm_translate() + TransformMatrix = TransformMatrix * RotateMatrix; // glm_rotate(), glm_quat_rotate() + TransformMatrix = TransformMatrix * ScaleMatrix; // glm_scale() + +As you can see it is multipled as right matrix. For instance what will happen if you call `glm_translate` twice? + +.. code-block:: c + :linenos: + + glm_translate(transform, translate1); /* transform = transform * translate1 */ + glm_translate(transform, translate2); /* transform = transform * translate2 */ + glm_rotate(transform, angle, axis) /* transform = transform * rotation */ + +Now lets try to understand this: + +1. You call translate using `translate1` and you expect it will be first transform +because you call it first, do you? + +Result will be **`transform = transform * translate1`** + +2. Then you call translate using `translate2` and you expect it will be second transform, really? + +Result will be **`transform = transform * translate2`**. Now lets expand transform, +it was `transform * translate1` before second call. + +Now it is **`transform = transform * translate1 * translate2`**, now do you understand what I say? + +3. After last call transform will be: + +**`transform = transform * translate1 * translate2 * rotation`** + +The order will be; **rotation will be applied first**, then **translate2** then **translate1** + +It is all about matrix multiplication order. It is similar to MVP matrix: +`MVP = Projection * View * Model`, model will be applied first, then view then projection. + +**Confused?** + +As alternative way, you can create transform matrices individually then combine manually, +but don't forget that `glm_translate`, `glm_rotate`, `glm_scale`... are optimized and should be faster (an smaller assembly output) than manual multiplication + +.. code-block:: c + :linenos: + + mat4 transform1, transform2, transform3, finalTransform; + + glm_translate_make(transform1, translate1); + glm_translate_make(transform2, translate2); + glm_rotate_make(transform3, angle, axis); + + /* first apply transform1, then transform2, thentransform3 */ + glm_mat4_mulN((mat4 *[]){&transform3, &transform2, &transform1}, 3, finalTransform); + + /* if you don't want to use mulN, same as above */ + glm_mat4_mul(transform3, transform2, finalTransform); + glm_mat4_mul(finalTransform, transform1, finalTransform); + +Now transform1 will be applied first, then transform2 then transform3 + Table of contents (click to go): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -38,6 +130,8 @@ Functions: #. :c:func:`glm_rotate_make` #. :c:func:`glm_rotate_ndc` #. :c:func:`glm_rotate` +#. :c:func:`glm_rotate_at` +#. :c:func:`glm_rotate_atm` #. :c:func:`glm_decompose_scalev` #. :c:func:`glm_uniscaled` #. :c:func:`glm_decompose_rs` @@ -204,6 +298,29 @@ Functions documentation | *[in]* **angle** angle (radians) | *[in]* **axis** axis +.. c:function:: void glm_rotate_at(mat4 m, vec3 pivot, float angle, vec3 axis) + + rotate existing transform around given axis by angle at given pivot point (rotation center) + + Parameters: + | *[in, out]* **m** affine transfrom + | *[in]* **pivot** pivot, anchor point, rotation center + | *[in]* **angle** angle (radians) + | *[in]* **axis** axis + +.. c:function:: void glm_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis) + + | creates NEW rotation matrix by angle and axis at given point + | this creates rotation matrix, it assumes you don't have a matrix + + | this should work faster than glm_rotate_at because it reduces one glm_translate. + + Parameters: + | *[in, out]* **m** affine transfrom + | *[in]* **pivot** pivot, anchor point, rotation center + | *[in]* **angle** angle (radians) + | *[in]* **axis** axis + .. c:function:: void glm_decompose_scalev(mat4 m, vec3 s) decompose scale vector diff --git a/docs/source/quat.rst b/docs/source/quat.rst index ab99838..d9b4680 100644 --- a/docs/source/quat.rst +++ b/docs/source/quat.rst @@ -56,6 +56,9 @@ Functions: #. :c:func:`glm_quat_for` #. :c:func:`glm_quat_forp` #. :c:func:`glm_quat_rotatev` +#. :c:func:`glm_quat_rotate` +#. :c:func:`glm_quat_rotate_at` +#. :c:func:`glm_quat_rotate_atm` Functions documentation ~~~~~~~~~~~~~~~~~~~~~~~ @@ -354,3 +357,24 @@ Functions documentation | *[in]* **m** existing transform matrix to rotate | *[in]* **q** quaternion | *[out]* **dest** rotated matrix/transform + +.. c:function:: void glm_quat_rotate_at(mat4 m, versor q, vec3 pivot) + + | rotate existing transform matrix using quaternion at pivot point + + Parameters: + | *[in, out]* **m** existing transform matrix to rotate + | *[in]* **q** quaternion + | *[in]* **pivot** pivot + +.. c:function:: void glm_quat_rotate(mat4 m, versor q, mat4 dest) + + | rotate NEW transform matrix using quaternion at pivot point + | this creates rotation matrix, it assumes you don't have a matrix + + | this should work faster than glm_quat_rotate_at because it reduces one glm_translate. + + Parameters: + | *[in, out]* **m** existing transform matrix to rotate + | *[in]* **q** quaternion + | *[in]* **pivot** pivot diff --git a/include/cglm/affine.h b/include/cglm/affine.h index a5abbb6..f855399 100644 --- a/include/cglm/affine.h +++ b/include/cglm/affine.h @@ -25,6 +25,8 @@ CGLM_INLINE void glm_rotate_make(mat4 m, float angle, vec3 axis); CGLM_INLINE void glm_rotate_ndc(mat4 m, float angle, vec3 axis); CGLM_INLINE void glm_rotate(mat4 m, float angle, vec3 axis); + CGLM_INLINE void glm_rotate_at(mat4 m, vec3 pivot, float angle, vec3 axis); + CGLM_INLINE void glm_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis); CGLM_INLINE void glm_decompose_scalev(mat4 m, vec3 s); CGLM_INLINE bool glm_uniscaled(mat4 m); CGLM_INLINE void glm_decompose_rs(mat4 m, mat4 r, vec3 s); @@ -521,7 +523,7 @@ glm_decompose_scalev(mat4 m, vec3 s) { } /*! - * @brief returns true if matrix is uniform scaled. This is helpful for + * @brief returns true if matrix is uniform scaled. This is helpful for * creating normal matrix. * * @param[in] m m diff --git a/include/cglm/quat.h b/include/cglm/quat.h index 1139c1d..d1da27f 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -757,14 +757,14 @@ glm_quat_rotate(mat4 m, versor q, mat4 dest) { */ CGLM_INLINE void -glm_quat_rotate_at(mat4 model, versor q, vec3 pivot) { +glm_quat_rotate_at(mat4 m, versor q, vec3 pivot) { vec3 pivotInv; glm_vec_inv_to(pivot, pivotInv); - glm_translate(model, pivot); - glm_quat_rotate(model, q, model); - glm_translate(model, pivotInv); + glm_translate(m, pivot); + glm_quat_rotate(m, q, m); + glm_translate(m, pivotInv); } /*! From f163fcd043d3cf99fd44724c53df5966a88634f1 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Wed, 18 Apr 2018 00:00:47 +0300 Subject: [PATCH 67/98] simd: load vec3 helpers for sse/sse2 --- include/cglm/simd/intrin.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/include/cglm/simd/intrin.h b/include/cglm/simd/intrin.h index c396686..7fdfc2a 100644 --- a/include/cglm/simd/intrin.h +++ b/include/cglm/simd/intrin.h @@ -46,6 +46,25 @@ glm_simd_norm(__m128 a) { return _mm_sqrt_ps(glm_simd_dot(a, a)); } +static inline +__m128 +glm_simd_load_v3(vec3 v) { + __m128i xy; + __m128 z; + + xy = _mm_loadl_epi64((const __m128i *)v); + z = _mm_load_ss(&v[2]); + + return _mm_movelh_ps(_mm_castsi128_ps(xy), z); +} + +static inline +void +glm_simd_store_v3(__m128 vx, vec3 v) { + _mm_storel_pi((__m64 *)&v[0], vx); + _mm_store_ss(&v[2], _mm_shuffle1_ps(vx, 2, 2, 2, 2)); +} + #endif /* x86, x64 */ From d648f5772def2fa28ec39650982e9768db16fa81 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Wed, 18 Apr 2018 10:57:35 +0300 Subject: [PATCH 68/98] affine: drop rotate_ndc functions --- include/cglm/affine.h | 93 ++++++++++---------------------------- include/cglm/call/affine.h | 8 ---- src/affine.c | 12 ----- 3 files changed, 23 insertions(+), 90 deletions(-) diff --git a/include/cglm/affine.h b/include/cglm/affine.h index f855399..f7b3942 100644 --- a/include/cglm/affine.h +++ b/include/cglm/affine.h @@ -21,9 +21,7 @@ CGLM_INLINE void glm_rotate_x(mat4 m, float angle, mat4 dest); CGLM_INLINE void glm_rotate_y(mat4 m, float angle, mat4 dest); CGLM_INLINE void glm_rotate_z(mat4 m, float angle, mat4 dest); - CGLM_INLINE void glm_rotate_ndc_make(mat4 m, float angle, vec3 axis_ndc); CGLM_INLINE void glm_rotate_make(mat4 m, float angle, vec3 axis); - CGLM_INLINE void glm_rotate_ndc(mat4 m, float angle, vec3 axis); CGLM_INLINE void glm_rotate(mat4 m, float angle, vec3 axis); CGLM_INLINE void glm_rotate_at(mat4 m, vec3 pivot, float angle, vec3 axis); CGLM_INLINE void glm_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis); @@ -346,48 +344,6 @@ glm_rotate_z(mat4 m, float angle, mat4 dest) { glm_mat4_mul(m, t, dest); } -/*! - * @brief creates NEW rotation matrix by angle and axis - * - * this name may change in the future. axis must be is normalized - * - * @param[out] m affine transfrom - * @param[in] angle angle (radians) - * @param[in] axis_ndc normalized axis - */ -CGLM_INLINE -void -glm_rotate_ndc_make(mat4 m, float angle, vec3 axis_ndc) { - /* https://www.opengl.org/sdk/docs/man2/xhtml/glRotate.xml */ - - vec3 v, vs; - float c; - - c = cosf(angle); - - glm_vec_scale(axis_ndc, 1.0f - c, v); - glm_vec_scale(axis_ndc, sinf(angle), vs); - - glm_vec_scale(axis_ndc, v[0], m[0]); - glm_vec_scale(axis_ndc, v[1], m[1]); - glm_vec_scale(axis_ndc, v[2], m[2]); - - m[0][0] += c; - m[0][1] += vs[2]; - m[0][2] -= vs[1]; - - m[1][0] -= vs[2]; - m[1][1] += c; - m[1][2] += vs[0]; - - m[2][0] += vs[1]; - m[2][1] -= vs[0]; - m[2][2] += c; - - m[0][3] = m[1][3] = m[2][3] = m[3][0] = m[3][1] = m[3][2] = 0.0f; - m[3][3] = 1.0f; -} - /*! * @brief creates NEW rotation matrix by angle and axis * @@ -400,27 +356,40 @@ glm_rotate_ndc_make(mat4 m, float angle, vec3 axis_ndc) { CGLM_INLINE void glm_rotate_make(mat4 m, float angle, vec3 axis) { - vec3 axis_ndc; + vec3 axisn, v, vs; + float c; - glm_vec_normalize_to(axis, axis_ndc); - glm_rotate_ndc_make(m, angle, axis_ndc); + c = cosf(angle); + + glm_vec_normalize_to(axis, axisn); + glm_vec_scale(axisn, 1.0f - c, v); + glm_vec_scale(axisn, sinf(angle), vs); + + glm_vec_scale(axisn, v[0], m[0]); + glm_vec_scale(axisn, v[1], m[1]); + glm_vec_scale(axisn, v[2], m[2]); + + m[0][0] += c; m[1][0] -= vs[2]; m[2][0] += vs[1]; + m[0][1] += vs[2]; m[1][1] += c; m[2][1] -= vs[0]; + m[0][2] -= vs[1]; m[1][2] += vs[0]; m[2][2] += c; + + m[0][3] = m[1][3] = m[2][3] = m[3][0] = m[3][1] = m[3][2] = 0.0f; + m[3][3] = 1.0f; } /*! * @brief rotate existing transform matrix around given axis by angle * - * this name may change in the future, axis must be normalized. - * - * @param[in, out] m affine transfrom - * @param[in] angle angle (radians) - * @param[in] axis_ndc normalized axis + * @param[in, out] m affine transfrom + * @param[in] angle angle (radians) + * @param[in] axis axis */ CGLM_INLINE void -glm_rotate_ndc(mat4 m, float angle, vec3 axis_ndc) { +glm_rotate(mat4 m, float angle, vec3 axis) { mat4 rot, tmp; - glm_rotate_ndc_make(rot, angle, axis_ndc); + glm_rotate_make(rot, angle, axis); glm_vec4_scale(m[0], rot[0][0], tmp[1]); glm_vec4_scale(m[1], rot[0][1], tmp[0]); @@ -445,22 +414,6 @@ glm_rotate_ndc(mat4 m, float angle, vec3 axis_ndc) { glm_vec4_copy(tmp[3], m[2]); } -/*! - * @brief rotate existing transform matrix around given axis by angle - * - * @param[in, out] m affine transfrom - * @param[in] angle angle (radians) - * @param[in] axis axis - */ -CGLM_INLINE -void -glm_rotate(mat4 m, float angle, vec3 axis) { - vec3 axis_ndc; - - glm_vec_normalize_to(axis, axis_ndc); - glm_rotate_ndc(m, angle, axis_ndc); -} - /*! * @brief rotate existing transform * around given axis by angle at given pivot point (rotation center) diff --git a/include/cglm/call/affine.h b/include/cglm/call/affine.h index a9982c2..4e30fff 100644 --- a/include/cglm/call/affine.h +++ b/include/cglm/call/affine.h @@ -69,18 +69,10 @@ CGLM_EXPORT void glmc_rotate_z(mat4 m, float rad, mat4 dest); -CGLM_EXPORT -void -glmc_rotate_ndc_make(mat4 m, float angle, vec3 axis_ndc); - CGLM_EXPORT void glmc_rotate_make(mat4 m, float angle, vec3 axis); -CGLM_EXPORT -void -glmc_rotate_ndc(mat4 m, float angle, vec3 axis_ndc); - CGLM_EXPORT void glmc_rotate(mat4 m, float angle, vec3 axis); diff --git a/src/affine.c b/src/affine.c index 1da12d6..0c028ba 100644 --- a/src/affine.c +++ b/src/affine.c @@ -92,24 +92,12 @@ glmc_rotate_z(mat4 m, float rad, mat4 dest) { glm_rotate_z(m, rad, dest); } -CGLM_EXPORT -void -glmc_rotate_ndc_make(mat4 m, float angle, vec3 axis_ndc) { - glm_rotate_ndc_make(m, angle, axis_ndc); -} - CGLM_EXPORT void glmc_rotate_make(mat4 m, float angle, vec3 axis) { glm_rotate_make(m, angle, axis); } -CGLM_EXPORT -void -glmc_rotate_ndc(mat4 m, float angle, vec3 axis_ndc) { - glm_rotate_ndc(m, angle, axis_ndc); -} - CGLM_EXPORT void glmc_rotate(mat4 m, float angle, vec3 axis) { From be0e3fc9f2c5b50d4370522d54051cbf79a047ca Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Wed, 18 Apr 2018 14:05:09 +0300 Subject: [PATCH 69/98] new matrix multiplication helper for rotation matrices --- include/cglm/affine-mat.h | 54 +++++++++++++++++++++++++++++++++ include/cglm/simd/sse2/affine.h | 32 +++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/include/cglm/affine-mat.h b/include/cglm/affine-mat.h index 3fd19ef..e015591 100644 --- a/include/cglm/affine-mat.h +++ b/include/cglm/affine-mat.h @@ -81,6 +81,60 @@ glm_mul(mat4 m1, mat4 m2, mat4 dest) { #endif } +/*! + * @brief this is similar to glm_mat4_mul but specialized to affine transform + * + * Right Matrix format should be: + * R R R 0 + * R R R 0 + * R R R 0 + * 0 0 0 1 + * + * this reduces some multiplications. It should be faster than mat4_mul. + * if you are not sure about matrix format then DON'T use this! use mat4_mul + * + * @param[in] m1 affine matrix 1 + * @param[in] m2 affine matrix 2 + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_mul_rot(mat4 m1, mat4 m2, mat4 dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + glm_mul_rot_sse2(m1, m2, dest); +#else + float a00 = m1[0][0], a01 = m1[0][1], a02 = m1[0][2], a03 = m1[0][3], + a10 = m1[1][0], a11 = m1[1][1], a12 = m1[1][2], a13 = m1[1][3], + a20 = m1[2][0], a21 = m1[2][1], a22 = m1[2][2], a23 = m1[2][3], + a30 = m1[3][0], a31 = m1[3][1], a32 = m1[3][2], a33 = m1[3][3], + + b00 = m2[0][0], b01 = m2[0][1], b02 = m2[0][2], + b10 = m2[1][0], b11 = m2[1][1], b12 = m2[1][2], + b20 = m2[2][0], b21 = m2[2][1], b22 = m2[2][2], + b33 = m2[3][3]; + + dest[0][0] = a00 * b00 + a10 * b01 + a20 * b02; + dest[0][1] = a01 * b00 + a11 * b01 + a21 * b02; + dest[0][2] = a02 * b00 + a12 * b01 + a22 * b02; + dest[0][3] = a03 * b00 + a13 * b01 + a23 * b02; + + dest[1][0] = a00 * b10 + a10 * b11 + a20 * b12; + dest[1][1] = a01 * b10 + a11 * b11 + a21 * b12; + dest[1][2] = a02 * b10 + a12 * b11 + a22 * b12; + dest[1][3] = a03 * b10 + a13 * b11 + a23 * b12; + + dest[2][0] = a00 * b20 + a10 * b21 + a20 * b22; + dest[2][1] = a01 * b20 + a11 * b21 + a21 * b22; + dest[2][2] = a02 * b20 + a12 * b21 + a22 * b22; + dest[2][3] = a03 * b20 + a13 * b21 + a23 * b22; + + dest[3][0] = a30; + dest[3][1] = a31; + dest[3][2] = a32; + dest[3][3] = a33; +#endif +} + /*! * @brief inverse orthonormal rotation + translation matrix (ridig-body) * diff --git a/include/cglm/simd/sse2/affine.h b/include/cglm/simd/sse2/affine.h index 3ec8f5f..b746d0f 100644 --- a/include/cglm/simd/sse2/affine.h +++ b/include/cglm/simd/sse2/affine.h @@ -49,6 +49,38 @@ glm_mul_sse2(mat4 m1, mat4 m2, mat4 dest) { _mm_mul_ps(_mm_shuffle1_ps1(r, 3), l3)))); } +CGLM_INLINE +void +glm_mul_rot_sse2(mat4 m1, mat4 m2, mat4 dest) { + /* D = R * L (Column-Major) */ + __m128 l0, l1, l2, l3, r; + + l0 = _mm_load_ps(m1[0]); + l1 = _mm_load_ps(m1[1]); + l2 = _mm_load_ps(m1[2]); + l3 = _mm_load_ps(m1[3]); + + r = _mm_load_ps(m2[0]); + _mm_store_ps(dest[0], + _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), + _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), + _mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2))); + + r = _mm_load_ps(m2[1]); + _mm_store_ps(dest[1], + _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), + _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), + _mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2))); + + r = _mm_load_ps(m2[2]); + _mm_store_ps(dest[2], + _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), + _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), + _mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2))); + + _mm_store_ps(dest[3], l3); +} + CGLM_INLINE void glm_inv_tr_sse2(mat4 mat) { From 4dbcd28fdba604ecc4d4432f15b862a709cdfe17 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Wed, 18 Apr 2018 14:12:56 +0300 Subject: [PATCH 70/98] use mul_rot for rotations to make thrm faster --- include/cglm/affine.h | 77 ++++++++++++++---------------------------- include/cglm/types.h | 4 +-- test/src/test_affine.c | 9 +++++ 3 files changed, 37 insertions(+), 53 deletions(-) diff --git a/include/cglm/affine.h b/include/cglm/affine.h index f7b3942..953b31c 100644 --- a/include/cglm/affine.h +++ b/include/cglm/affine.h @@ -277,19 +277,18 @@ glm_scale_uni(mat4 m, float s) { CGLM_INLINE void glm_rotate_x(mat4 m, float angle, mat4 dest) { - float cosVal; - float sinVal; mat4 t = GLM_MAT4_IDENTITY_INIT; + float c, s; - cosVal = cosf(angle); - sinVal = sinf(angle); + c = cosf(angle); + s = sinf(angle); - t[1][1] = cosVal; - t[1][2] = sinVal; - t[2][1] = -sinVal; - t[2][2] = cosVal; + t[1][1] = c; + t[1][2] = s; + t[2][1] = -s; + t[2][2] = c; - glm_mat4_mul(m, t, dest); + glm_mul_rot(m, t, dest); } /*! @@ -303,19 +302,18 @@ glm_rotate_x(mat4 m, float angle, mat4 dest) { CGLM_INLINE void glm_rotate_y(mat4 m, float angle, mat4 dest) { - float cosVal; - float sinVal; mat4 t = GLM_MAT4_IDENTITY_INIT; + float c, s; - cosVal = cosf(angle); - sinVal = sinf(angle); + c = cosf(angle); + s = sinf(angle); - t[0][0] = cosVal; - t[0][2] = -sinVal; - t[2][0] = sinVal; - t[2][2] = cosVal; + t[0][0] = c; + t[0][2] = -s; + t[2][0] = s; + t[2][2] = c; - glm_mat4_mul(m, t, dest); + glm_mul_rot(m, t, dest); } /*! @@ -329,19 +327,18 @@ glm_rotate_y(mat4 m, float angle, mat4 dest) { CGLM_INLINE void glm_rotate_z(mat4 m, float angle, mat4 dest) { - float cosVal; - float sinVal; mat4 t = GLM_MAT4_IDENTITY_INIT; + float c, s; - cosVal = cosf(angle); - sinVal = sinf(angle); + c = cosf(angle); + s = sinf(angle); - t[0][0] = cosVal; - t[0][1] = sinVal; - t[1][0] = -sinVal; - t[1][1] = cosVal; + t[0][0] = c; + t[0][1] = s; + t[1][0] = -s; + t[1][1] = c; - glm_mat4_mul(m, t, dest); + glm_mul_rot(m, t, dest); } /*! @@ -387,31 +384,9 @@ glm_rotate_make(mat4 m, float angle, vec3 axis) { CGLM_INLINE void glm_rotate(mat4 m, float angle, vec3 axis) { - mat4 rot, tmp; - + mat4 rot; glm_rotate_make(rot, angle, axis); - - glm_vec4_scale(m[0], rot[0][0], tmp[1]); - glm_vec4_scale(m[1], rot[0][1], tmp[0]); - glm_vec4_add(tmp[1], tmp[0], tmp[1]); - glm_vec4_scale(m[2], rot[0][2], tmp[0]); - glm_vec4_add(tmp[1], tmp[0], tmp[1]); - - glm_vec4_scale(m[0], rot[1][0], tmp[2]); - glm_vec4_scale(m[1], rot[1][1], tmp[0]); - glm_vec4_add(tmp[2], tmp[0], tmp[2]); - glm_vec4_scale(m[2], rot[1][2], tmp[0]); - glm_vec4_add(tmp[2], tmp[0], tmp[2]); - - glm_vec4_scale(m[0], rot[2][0], tmp[3]); - glm_vec4_scale(m[1], rot[2][1], tmp[0]); - glm_vec4_add(tmp[3], tmp[0], tmp[3]); - glm_vec4_scale(m[2], rot[2][2], tmp[0]); - glm_vec4_add(tmp[3], tmp[0], tmp[3]); - - glm_vec4_copy(tmp[1], m[0]); - glm_vec4_copy(tmp[2], m[1]); - glm_vec4_copy(tmp[3], m[2]); + glm_mul_rot(m, rot, m); } /*! diff --git a/include/cglm/types.h b/include/cglm/types.h index c411d8b..5d39a55 100644 --- a/include/cglm/types.h +++ b/include/cglm/types.h @@ -15,12 +15,12 @@ #endif typedef float vec2[2]; -typedef float vec3[3]; +typedef CGLM_ALIGN(8) float vec3[3]; typedef int ivec3[3]; typedef CGLM_ALIGN(16) float vec4[4]; typedef vec3 mat3[3]; -typedef vec4 mat4[4]; +typedef CGLM_ALIGN(16) vec4 mat4[4]; typedef vec4 versor; diff --git a/test/src/test_affine.c b/test/src/test_affine.c index 4ce4a42..a625a30 100644 --- a/test/src/test_affine.c +++ b/test/src/test_affine.c @@ -91,6 +91,15 @@ test_affine(void **state) { glm_rotate_z(t2, M_PI_4, t2); test_assert_mat4_eq(t2, t3); + /* test rotate */ + glmc_rotate_make(t1, M_PI_4, (vec3){0, 0, 1}); + glm_translate_make(t2, (vec3){34, 57, 36}); + + glmc_mat4_mul(t2, t1, t3); /* T * R */ + glmc_rotate(t2, M_PI_4, (vec3){0, 0, 1}); + + test_assert_mat4_eq(t3, t2); + /* test scale_uni */ glmc_rotate_make(t1, M_PI_4, GLM_YUP); glm_translate_make(t2, (vec3){34, 57, 36}); From 065f93ab3cd0e202974377cae8d019d178d5502a Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Wed, 18 Apr 2018 14:30:44 +0300 Subject: [PATCH 71/98] update docs, drop scale1 --- docs/source/affine-mat.rst | 22 +++++++++++++++++++++ docs/source/affine.rst | 40 ++++++++++++-------------------------- include/cglm/affine.h | 11 ----------- include/cglm/call/affine.h | 4 ---- src/affine.c | 6 ------ 5 files changed, 34 insertions(+), 49 deletions(-) diff --git a/docs/source/affine-mat.rst b/docs/source/affine-mat.rst index 0c0fcaa..43740cf 100644 --- a/docs/source/affine-mat.rst +++ b/docs/source/affine-mat.rst @@ -33,6 +33,7 @@ Table of contents (click func go): Functions: 1. :c:func:`glm_mul` +#. :c:func:`glm_mul_rot` #. :c:func:`glm_inv_tr` Functions documentation @@ -59,6 +60,27 @@ Functions documentation | *[in]* **m2** affine matrix 2 | *[out]* **dest** result matrix +.. c:function:: void glm_mul_rot(mat4 m1, mat4 m2, mat4 dest) + + | this is similar to glm_mat4_mul but specialized to rotation matrix + + Right Matrix format should be (left is free): + + .. code-block:: text + + R R R 0 + R R R 0 + R R R 0 + 0 0 0 1 + + this reduces some multiplications. It should be faster than mat4_mul. + if you are not sure about matrix format then DON'T use this! use mat4_mul + + Parameters: + | *[in]* **m1** affine matrix 1 + | *[in]* **m2** affine matrix 2 + | *[out]* **dest** result matrix + .. c:function:: void glm_inv_tr(mat4 mat) | inverse orthonormal rotation + translation matrix (ridig-body) diff --git a/docs/source/affine.rst b/docs/source/affine.rst index 8eaf01c..8ded38d 100644 --- a/docs/source/affine.rst +++ b/docs/source/affine.rst @@ -36,6 +36,15 @@ If you want to rotate model around arbibtrary point follow these steps: **glm_rotate_at**, **glm_quat_rotate_at** and their helper functions works that way. +The implementation would be: + +.. code-block:: c + :linenos: + + glm_translate(m, pivot); + glm_rotate(m, angle, axis); + glm_translate(m, pivotInv); /* pivotInv = -pivot */ + Transforms Order ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -68,7 +77,7 @@ because you call it first, do you? Result will be **`transform = transform * translate1`** -2. Then you call translate using `translate2` and you expect it will be second transform, really? +2. Then you call translate using `translate2` and you expect it will be second transform? Result will be **`transform = transform * translate2`**. Now lets expand transform, it was `transform * translate1` before second call. @@ -86,6 +95,8 @@ It is all about matrix multiplication order. It is similar to MVP matrix: **Confused?** +In the end the last function call applied first in shaders. + As alternative way, you can create transform matrices individually then combine manually, but don't forget that `glm_translate`, `glm_rotate`, `glm_scale`... are optimized and should be faster (an smaller assembly output) than manual multiplication @@ -121,14 +132,11 @@ Functions: #. :c:func:`glm_scale_to` #. :c:func:`glm_scale_make` #. :c:func:`glm_scale` -#. :c:func:`glm_scale1` #. :c:func:`glm_scale_uni` #. :c:func:`glm_rotate_x` #. :c:func:`glm_rotate_y` #. :c:func:`glm_rotate_z` -#. :c:func:`glm_rotate_ndc_make` #. :c:func:`glm_rotate_make` -#. :c:func:`glm_rotate_ndc` #. :c:func:`glm_rotate` #. :c:func:`glm_rotate_at` #. :c:func:`glm_rotate_atm` @@ -216,10 +224,6 @@ Functions documentation | *[in, out]* **m** affine transfrom | *[in]* **v** scale vector [x, y, z] -.. c:function:: void glm_scale1(mat4 m, float s) - - DEPRECATED! Use glm_scale_uni - .. c:function:: void glm_scale_uni(mat4 m, float s) applies uniform scale to existing transform matrix v = [s, s, s] @@ -259,16 +263,6 @@ Functions documentation | *[in]* **angle** angle (radians) | *[out]* **dest** rotated matrix -.. c:function:: void glm_rotate_ndc_make(mat4 m, float angle, vec3 axis_ndc) - - creates NEW rotation matrix by angle and axis - this name may change in the future. axis must be is normalized - - Parameters: - | *[out]* **m** affine transfrom - | *[in]* **angle** angle (radians) - | *[in]* **axis_ndc** normalized axis - .. c:function:: void glm_rotate_make(mat4 m, float angle, vec3 axis) creates NEW rotation matrix by angle and axis, @@ -279,16 +273,6 @@ Functions documentation | *[in]* **axis** angle (radians) | *[in]* **axis** axis -.. c:function:: void glm_rotate_ndc(mat4 m, float angle, vec3 axis_ndc) - - rotate existing transform matrix around Z axis by angle and axis - this name may change in the future, axis must be normalized. - - Parameters: - | *[out]* **m** affine transfrom - | *[in]* **angle** angle (radians) - | *[in]* **axis_ndc** normalized axis - .. c:function:: void glm_rotate(mat4 m, float angle, vec3 axis) rotate existing transform matrix around Z axis by angle and axis diff --git a/include/cglm/affine.h b/include/cglm/affine.h index 953b31c..95d60b7 100644 --- a/include/cglm/affine.h +++ b/include/cglm/affine.h @@ -16,7 +16,6 @@ CGLM_INLINE void glm_scale_to(mat4 m, vec3 v, mat4 dest); CGLM_INLINE void glm_scale_make(mat4 m, vec3 v); CGLM_INLINE void glm_scale(mat4 m, vec3 v); - CGLM_INLINE void glm_scale1(mat4 m, float s); CGLM_INLINE void glm_scale_uni(mat4 m, float s); CGLM_INLINE void glm_rotate_x(mat4 m, float angle, mat4 dest); CGLM_INLINE void glm_rotate_y(mat4 m, float angle, mat4 dest); @@ -242,16 +241,6 @@ glm_scale(mat4 m, vec3 v) { glm_scale_to(m, v, m); } -/*! - * @brief DEPRECATED! Use glm_scale_uni - */ -CGLM_INLINE -void -glm_scale1(mat4 m, float s) { - vec3 v = { s, s, s }; - glm_scale_to(m, v, m); -} - /*! * @brief applies uniform scale to existing transform matrix v = [s, s, s] * and stores result in same matrix diff --git a/include/cglm/call/affine.h b/include/cglm/call/affine.h index 4e30fff..4d3834b 100644 --- a/include/cglm/call/affine.h +++ b/include/cglm/call/affine.h @@ -49,10 +49,6 @@ CGLM_EXPORT void glmc_scale(mat4 m, vec3 v); -CGLM_EXPORT -void -glmc_scale1(mat4 m, float s); - CGLM_EXPORT void glmc_scale_uni(mat4 m, float s); diff --git a/src/affine.c b/src/affine.c index 0c028ba..a271f9f 100644 --- a/src/affine.c +++ b/src/affine.c @@ -62,12 +62,6 @@ glmc_scale(mat4 m, vec3 v) { glm_scale(m, v); } -CGLM_EXPORT -void -glmc_scale1(mat4 m, float s) { - glm_scale1(m, s); -} - CGLM_EXPORT void glmc_scale_uni(mat4 m, float s) { From a723ecdb7ec862b38dce7975563631b1162f7cb9 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Wed, 18 Apr 2018 15:11:06 +0300 Subject: [PATCH 72/98] add troubleshooting to docs --- docs/source/index.rst | 1 + docs/source/troubleshooting.rst | 76 +++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 docs/source/troubleshooting.rst diff --git a/docs/source/index.rst b/docs/source/index.rst index 25e7cb3..32e7b48 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -40,6 +40,7 @@ Also currently only **float** type is supported for most operations. getting_started opengl api + troubleshooting Indices and tables ================== diff --git a/docs/source/troubleshooting.rst b/docs/source/troubleshooting.rst new file mode 100644 index 0000000..d0cc9d5 --- /dev/null +++ b/docs/source/troubleshooting.rst @@ -0,0 +1,76 @@ +.. default-domain:: C + +Troubleshooting +================================================================================ + +It is possible that sometimes you may get crashes or wrong results. +Follow these topics + +Memory Allocation: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Again, **cglm** doesn't alloc any memory on heap. +cglm functions works like memcpy; it copies data from src, +makes calculations then copy the result to dest. + +You are responsible for allocation of **src** and **dest** parameters. + +Aligment: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**vec4** and **mat4** types requires 16 byte aligment aligment. +These types are marked with align attribute to let compiler know about this +requirement. + +But since MSVC (Windows) throws the error: + +**"formal parameter with requested alignment of 16 won't be aligned"** + +The aligment attribute has been commented for MSVC + +.. code-block:: c + + #if defined(_MSC_VER) + # define CGLM_ALIGN(X) /* __declspec(align(X)) */ + #else + # define CGLM_ALIGN(X) __attribute((aligned(X))) + #endif. + +So MSVC may not know about aligment requirements when creating variables. +The interesting thing is that, if I remember correctly Visual Studio 2017 +doesn't throw the above error. So we may uncomment that line for Visual Studio 2017, +you may do it yourself. + +**This MSVC issue is still in TODOs.** + +Crashes, Invalid Memory Access: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Probably you are trying to write to invalid memory location. + +You may used wrong function for what you want to do. + +For instance you may called **glm_vec4_** functions for **vec3** data type. +It will try to write 32 byte but since **vec3** is 24 byte it should throw +memory access error or exit the app without saying anything. + +Wrong Results: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Again, you may used wrong function. + +For instance if you use **glm_normalize()** or **glm_vec_normalize()** for **vec4**, +it will assume that passed param is **vec3** and will normalize it for **vec3**. +Since you need to **vec4** to be normalized in your case, you will get wrong results. + +Accessing vec4 type with vec3 functions is valid, you will not get any error, exception or crash. +You only get wrong results if you don't know what you are doing! + +So be carefull, when your IDE (Xcode, Visual Studio ...) tried to autocomplete function names, READ IT :) + +**Also implementation may be wrong please let us know by creating an issue on Github.** + +Other Issues? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Please let us know by creating an issue on Github.** From 63966ee5c0c40b585fb5548ed5b7c4a04d270f4a Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Wed, 18 Apr 2018 15:16:24 +0300 Subject: [PATCH 73/98] quat: use the new "glm_mul_rot" for quaternion * this should be faster than mat4_mul --- include/cglm/quat.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/cglm/quat.h b/include/cglm/quat.h index d1da27f..6f0e87d 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -55,6 +55,7 @@ #include "vec4.h" #include "mat4.h" #include "mat3.h" +#include "affine-mat.h" #ifdef CGLM_SSE_FP # include "simd/sse2/quat.h" @@ -70,7 +71,7 @@ glm_mat4_mulv(mat4 m, vec4 v, vec4 dest); CGLM_INLINE void -glm_mat4_mul(mat4 m1, mat4 m2, mat4 dest); +glm_mul_rot(mat4 m1, mat4 m2, mat4 dest); CGLM_INLINE void @@ -745,7 +746,7 @@ void glm_quat_rotate(mat4 m, versor q, mat4 dest) { mat4 rot; glm_quat_mat4(q, rot); - glm_mat4_mul(m, rot, dest); + glm_mul_rot(m, rot, dest); } /*! From e28cf1d3f6ce21d4ae0bd5ec9fd0481f0e2bd9b6 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Wed, 18 Apr 2018 15:23:07 +0300 Subject: [PATCH 74/98] remove unused variable --- include/cglm/affine-mat.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/cglm/affine-mat.h b/include/cglm/affine-mat.h index e015591..b320509 100644 --- a/include/cglm/affine-mat.h +++ b/include/cglm/affine-mat.h @@ -110,8 +110,7 @@ glm_mul_rot(mat4 m1, mat4 m2, mat4 dest) { b00 = m2[0][0], b01 = m2[0][1], b02 = m2[0][2], b10 = m2[1][0], b11 = m2[1][1], b12 = m2[1][2], - b20 = m2[2][0], b21 = m2[2][1], b22 = m2[2][2], - b33 = m2[3][3]; + b20 = m2[2][0], b21 = m2[2][1], b22 = m2[2][2]; dest[0][0] = a00 * b00 + a10 * b01 + a20 * b02; dest[0][1] = a01 * b00 + a11 * b01 + a21 * b02; From 22b699174c9a8bb6f2483f8a678b09146ba6ce5e Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Wed, 18 Apr 2018 21:47:53 +0300 Subject: [PATCH 75/98] build: improve calling libtoolize --- autogen.sh | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/autogen.sh b/autogen.sh index f8d13c8..b3b8d82 100644 --- a/autogen.sh +++ b/autogen.sh @@ -8,17 +8,14 @@ cd $(dirname "$0") -if [ "$(uname)" = "Darwin" ]; then -libtoolBin=$(which glibtoolize) -libtoolBinDir=$(dirname "${libtoolBin}") - -if [ ! -f "${libtoolBinDir}/libtoolize" ]; then -ln -s $libtoolBin "${libtoolBinDir}/libtoolize" -fi -fi - autoheader -libtoolize + +if [ "$(uname)" = "Darwin" ]; then + glibtoolize +else + libtoolize +fi + aclocal -I m4 autoconf automake --add-missing --copy From 6202179c23b04125c0084c6446ff3d05fe5835fe Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Wed, 18 Apr 2018 22:30:20 +0300 Subject: [PATCH 76/98] update version --- configure.ac | 2 +- docs/source/conf.py | 4 ++-- include/cglm/version.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 0fc55a8..42cdd05 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ #***************************************************************************** AC_PREREQ([2.69]) -AC_INIT([cglm], [0.4.2], [info@recp.me]) +AC_INIT([cglm], [0.4.3], [info@recp.me]) AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/docs/source/conf.py b/docs/source/conf.py index 616edfd..b75537c 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -62,9 +62,9 @@ author = u'Recep Aslantas' # built documents. # # The short X.Y version. -version = u'0.4.1' +version = u'0.4.3' # The full version, including alpha/beta/rc tags. -release = u'0.4.1' +release = u'0.4.3' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/include/cglm/version.h b/include/cglm/version.h index 328a4d2..b9da46c 100644 --- a/include/cglm/version.h +++ b/include/cglm/version.h @@ -10,6 +10,6 @@ #define CGLM_VERSION_MAJOR 0 #define CGLM_VERSION_MINOR 4 -#define CGLM_VERSION_PATCH 2 +#define CGLM_VERSION_PATCH 3 #endif /* cglm_version_h */ From a6a37995e9377fb01efc6a50fb71f2fbe57bac44 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Wed, 18 Apr 2018 23:02:15 +0300 Subject: [PATCH 77/98] build: update automake sources --- makefile.am | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/makefile.am b/makefile.am index a0c06a9..1999b3d 100644 --- a/makefile.am +++ b/makefile.am @@ -54,7 +54,8 @@ cglm_HEADERS = include/cglm/version.h \ include/cglm/plane.h \ include/cglm/frustum.h \ include/cglm/box.h \ - include/cglm/color.h + include/cglm/color.h \ + include/cglm/project.h cglm_calldir=$(includedir)/cglm/call cglm_call_HEADERS = include/cglm/call/mat4.h \ @@ -68,7 +69,8 @@ cglm_call_HEADERS = include/cglm/call/mat4.h \ include/cglm/call/euler.h \ include/cglm/call/plane.h \ include/cglm/call/frustum.h \ - include/cglm/call/box.h + include/cglm/call/box.h \ + include/cglm/call/project.h cglm_simddir=$(includedir)/cglm/simd cglm_simd_HEADERS = include/cglm/simd/intrin.h From 3c7a729729097325e3824ce48739c13879a5efaf Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 20 Apr 2018 15:15:57 +0300 Subject: [PATCH 78/98] build: remove making symbolic link for libtoolize --- build-deps.sh | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/build-deps.sh b/build-deps.sh index 74b1cfa..20365ba 100644 --- a/build-deps.sh +++ b/build-deps.sh @@ -9,19 +9,8 @@ # check if deps are pulled git submodule update --init --recursive -# fix glibtoolize - cd $(dirname "$0") -if [ "$(uname)" = "Darwin" ]; then - libtoolBin=$(which glibtoolize) - libtoolBinDir=$(dirname "${libtoolBin}") - - if [ ! -f "${libtoolBinDir}/libtoolize" ]; then - ln -s $libtoolBin "${libtoolBinDir}/libtoolize" - fi -fi - # general deps: gcc make autoconf automake libtool cmake # test - cmocka From 498a33fac5f6cce134720fd5fbcad18206c8d285 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sat, 21 Apr 2018 22:36:25 +0300 Subject: [PATCH 79/98] fix public header's includes --- include/cglm/affine.h | 5 +++-- include/cglm/box.h | 1 + include/cglm/frustum.h | 3 +++ include/cglm/mat3.h | 1 + include/cglm/mat4.h | 2 ++ include/cglm/plane.h | 2 -- include/cglm/project.h | 2 +- include/cglm/quat.h | 1 + 8 files changed, 12 insertions(+), 5 deletions(-) diff --git a/include/cglm/affine.h b/include/cglm/affine.h index 95d60b7..8124930 100644 --- a/include/cglm/affine.h +++ b/include/cglm/affine.h @@ -34,10 +34,11 @@ #define cglm_affine_h #include "common.h" -#include "vec4.h" -#include "affine-mat.h" #include "util.h" +#include "vec3.h" +#include "vec4.h" #include "mat4.h" +#include "affine-mat.h" CGLM_INLINE void diff --git a/include/cglm/box.h b/include/cglm/box.h index 7032339..31b0ec2 100644 --- a/include/cglm/box.h +++ b/include/cglm/box.h @@ -11,6 +11,7 @@ #include "common.h" #include "vec3.h" #include "vec4.h" +#include "util.h" /*! * @brief apply transform to Axis-Aligned Bounding Box diff --git a/include/cglm/frustum.h b/include/cglm/frustum.h index 4f8aff4..d4e8d47 100644 --- a/include/cglm/frustum.h +++ b/include/cglm/frustum.h @@ -10,6 +10,9 @@ #include "common.h" #include "plane.h" +#include "vec3.h" +#include "vec4.h" +#include "mat4.h" #define GLM_LBN 0 /* left bottom near */ #define GLM_LTN 1 /* left top near */ diff --git a/include/cglm/mat3.h b/include/cglm/mat3.h index 9512aef..87bf9b1 100644 --- a/include/cglm/mat3.h +++ b/include/cglm/mat3.h @@ -31,6 +31,7 @@ #define cglm_mat3_h #include "common.h" +#include "vec3.h" #ifdef CGLM_SSE_FP # include "simd/sse2/mat3.h" diff --git a/include/cglm/mat4.h b/include/cglm/mat4.h index 27ebe05..1b254a2 100644 --- a/include/cglm/mat4.h +++ b/include/cglm/mat4.h @@ -46,6 +46,8 @@ #include "common.h" #include "quat.h" +#include "vec4.h" +#include "vec3.h" #ifdef CGLM_SSE_FP # include "simd/sse2/mat4.h" diff --git a/include/cglm/plane.h b/include/cglm/plane.h index 9faac9c..e0faed5 100644 --- a/include/cglm/plane.h +++ b/include/cglm/plane.h @@ -9,9 +9,7 @@ #define cglm_plane_h #include "common.h" -#include "mat4.h" #include "vec4.h" -#include "vec3.h" /* Plane equation: Ax + By + Cz + D = 0; diff --git a/include/cglm/project.h b/include/cglm/project.h index fea44b0..c71e735 100644 --- a/include/cglm/project.h +++ b/include/cglm/project.h @@ -8,9 +8,9 @@ #ifndef cglm_project_h #define cglm_project_h -#include "mat4.h" #include "vec3.h" #include "vec4.h" +#include "mat4.h" /*! * @brief maps the specified viewport coordinates into specified space [1] diff --git a/include/cglm/quat.h b/include/cglm/quat.h index 6f0e87d..f6dc86e 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -52,6 +52,7 @@ #define cglm_quat_h #include "common.h" +#include "vec3.h" #include "vec4.h" #include "mat4.h" #include "mat3.h" From cef97fca3ec7a7e89066ec0df3e3226a13f4713a Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sun, 22 Apr 2018 01:03:17 +0300 Subject: [PATCH 80/98] add cocoapods spec --- cglm.podspec | 29 +++++++++++++++++++++++++++++ configure.ac | 2 +- docs/source/conf.py | 4 ++-- include/cglm/version.h | 2 +- 4 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 cglm.podspec diff --git a/cglm.podspec b/cglm.podspec new file mode 100644 index 0000000..d9faadb --- /dev/null +++ b/cglm.podspec @@ -0,0 +1,29 @@ +Pod::Spec.new do |s| + + # Description + s.name = "cglm" + s.version = "0.4.4" + s.summary = "📽 Optimized OpenGL/Graphics Math (glm) for C" + s.description = <<-DESC +cglm is math library for graphics programming for C. It is similar to original glm but it is written for C instead of C++ (you can use here too). See the documentation or README for all features. + DESC + + s.documentation_url = "http://cglm.readthedocs.io" + + # Home + s.homepage = "https://github.com/recp/cglm" + s.license = { :type => "MIT", :file => "LICENSE" } + s.author = { "Recep Aslantas" => "recp@acm.org" } + + # Sources + s.source = { :git => "https://github.com/recp/cglm.git", :tag => "v#{s.version}" } + s.source_files = "src", "include/cglm/**/*.h" + s.public_header_files = "include", "include/cglm/**/*.h" + s.private_header_files = "src/**/*.h" + s.exclude_files = "src/win/*", "src/dllmain.c" + s.preserve_path = "include" + s.header_mappings_dir = "include" + + # Linking + s.library = "m" +end diff --git a/configure.ac b/configure.ac index 42cdd05..120ac02 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ #***************************************************************************** AC_PREREQ([2.69]) -AC_INIT([cglm], [0.4.3], [info@recp.me]) +AC_INIT([cglm], [0.4.4], [info@recp.me]) AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/docs/source/conf.py b/docs/source/conf.py index b75537c..6ea46ac 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -62,9 +62,9 @@ author = u'Recep Aslantas' # built documents. # # The short X.Y version. -version = u'0.4.3' +version = u'0.4.4' # The full version, including alpha/beta/rc tags. -release = u'0.4.3' +release = u'0.4.4' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/include/cglm/version.h b/include/cglm/version.h index b9da46c..3ed79fb 100644 --- a/include/cglm/version.h +++ b/include/cglm/version.h @@ -10,6 +10,6 @@ #define CGLM_VERSION_MAJOR 0 #define CGLM_VERSION_MINOR 4 -#define CGLM_VERSION_PATCH 3 +#define CGLM_VERSION_PATCH 4 #endif /* cglm_version_h */ From ada69a7c43a6ea405e871cf4f6eefe3522bf39b2 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sun, 22 Apr 2018 10:14:17 +0300 Subject: [PATCH 81/98] fix cocoapods validation errors --- cglm.podspec | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cglm.podspec b/cglm.podspec index d9faadb..150ca86 100644 --- a/cglm.podspec +++ b/cglm.podspec @@ -19,9 +19,8 @@ cglm is math library for graphics programming for C. It is similar to original g s.source = { :git => "https://github.com/recp/cglm.git", :tag => "v#{s.version}" } s.source_files = "src", "include/cglm/**/*.h" s.public_header_files = "include", "include/cglm/**/*.h" - s.private_header_files = "src/**/*.h" - s.exclude_files = "src/win/*", "src/dllmain.c" - s.preserve_path = "include" + s.exclude_files = "src/win/*", "src/dllmain.c", "src/**/*.h" + s.preserve_paths = "include", "src" s.header_mappings_dir = "include" # Linking From 6c01eff056af1f54b63e12b46b0a78f3ce7502a4 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Mon, 30 Apr 2018 10:59:40 +0300 Subject: [PATCH 82/98] now working on v0.4.5 --- configure.ac | 2 +- docs/source/conf.py | 4 ++-- include/cglm/version.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 120ac02..76c6123 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ #***************************************************************************** AC_PREREQ([2.69]) -AC_INIT([cglm], [0.4.4], [info@recp.me]) +AC_INIT([cglm], [0.4.5], [info@recp.me]) AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/docs/source/conf.py b/docs/source/conf.py index 6ea46ac..ef9619a 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -62,9 +62,9 @@ author = u'Recep Aslantas' # built documents. # # The short X.Y version. -version = u'0.4.4' +version = u'0.4.5' # The full version, including alpha/beta/rc tags. -release = u'0.4.4' +release = u'0.4.5' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/include/cglm/version.h b/include/cglm/version.h index 3ed79fb..8e405bd 100644 --- a/include/cglm/version.h +++ b/include/cglm/version.h @@ -10,6 +10,6 @@ #define CGLM_VERSION_MAJOR 0 #define CGLM_VERSION_MINOR 4 -#define CGLM_VERSION_PATCH 4 +#define CGLM_VERSION_PATCH 5 #endif /* cglm_version_h */ From 94d6036c388f764cf2697095b088ac076bef65e1 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Mon, 30 Apr 2018 11:09:42 +0300 Subject: [PATCH 83/98] suppress warnings for Mingw --- include/cglm/simd/intrin.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/cglm/simd/intrin.h b/include/cglm/simd/intrin.h index 7fdfc2a..1938cb2 100644 --- a/include/cglm/simd/intrin.h +++ b/include/cglm/simd/intrin.h @@ -10,9 +10,13 @@ #if defined( _WIN32 ) # if (defined(_M_AMD64) || defined(_M_X64)) || _M_IX86_FP == 2 -# define __SSE2__ +# ifndef __SSE2__ +# define __SSE2__ +# endif # elif _M_IX86_FP == 1 -# define __SSE__ +# ifndef __SSE__ +# define __SSE__ +# endif # endif #endif From 064209c917be86d5ffda7a871a2447af7ad0411a Mon Sep 17 00:00:00 2001 From: Federico Santamorena Date: Mon, 30 Apr 2018 17:13:16 +0200 Subject: [PATCH 84/98] replaced _WIN32 with _MSC_VER --- include/cglm/simd/intrin.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/cglm/simd/intrin.h b/include/cglm/simd/intrin.h index 1938cb2..cf6753f 100644 --- a/include/cglm/simd/intrin.h +++ b/include/cglm/simd/intrin.h @@ -8,7 +8,7 @@ #ifndef cglm_intrin_h #define cglm_intrin_h -#if defined( _WIN32 ) +#if defined( _MSC_VER ) # if (defined(_M_AMD64) || defined(_M_X64)) || _M_IX86_FP == 2 # ifndef __SSE2__ # define __SSE2__ From 7c0e9e99c67ddc63ff95d10c8c2885d1105c2bf0 Mon Sep 17 00:00:00 2001 From: Federico Santamorena Date: Mon, 30 Apr 2018 17:17:06 +0200 Subject: [PATCH 85/98] _WIN32 to _MSC_VER --- include/cglm/common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/cglm/common.h b/include/cglm/common.h index f0eb965..199bfda 100644 --- a/include/cglm/common.h +++ b/include/cglm/common.h @@ -14,7 +14,7 @@ #include #include -#if defined(_WIN32) +#if defined(_MSC_VER) # ifdef CGLM_DLL # define CGLM_EXPORT __declspec(dllexport) # else From a9d56f2daeb9781fe279880997456872cc6697e2 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 4 May 2018 00:50:56 +0300 Subject: [PATCH 86/98] docs: fix typos --- docs/source/getting_started.rst | 6 +++--- docs/source/troubleshooting.rst | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst index 89c231c..a152371 100644 --- a/docs/source/getting_started.rst +++ b/docs/source/getting_started.rst @@ -21,17 +21,17 @@ Types: As you can see types don't store extra informations in favor of space. You can send these values e.g. matrix to OpenGL directly without casting or calling a function like *value_ptr* -Aligment is Required: +Alignment is Required: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -**vec4** and **mat4** requires 16 byte aligment because vec4 and mat4 operations are +**vec4** and **mat4** requires 16 byte alignment because vec4 and mat4 operations are vectorized by SIMD instructions (SSE/AVX). Allocations: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *cglm* doesn't alloc any memory on heap. So it doesn't provide any allocator. You must allocate memory yourself. You should alloc memory for out parameters too if you pass pointer of memory location. -When allocating memory don't forget that **vec4** and **mat4** requires aligment. +When allocating memory don't forget that **vec4** and **mat4** requires alignment. **NOTE:** Unaligned vec4 and unaligned mat4 operations will be supported in the future. Check todo list. Because you may want to multiply a CGLM matrix with external matrix. diff --git a/docs/source/troubleshooting.rst b/docs/source/troubleshooting.rst index d0cc9d5..d599c7d 100644 --- a/docs/source/troubleshooting.rst +++ b/docs/source/troubleshooting.rst @@ -15,10 +15,10 @@ makes calculations then copy the result to dest. You are responsible for allocation of **src** and **dest** parameters. -Aligment: +Alignment: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -**vec4** and **mat4** types requires 16 byte aligment aligment. +**vec4** and **mat4** types requires 16 byte alignment. These types are marked with align attribute to let compiler know about this requirement. @@ -26,7 +26,7 @@ But since MSVC (Windows) throws the error: **"formal parameter with requested alignment of 16 won't be aligned"** -The aligment attribute has been commented for MSVC +The alignment attribute has been commented for MSVC .. code-block:: c @@ -36,7 +36,7 @@ The aligment attribute has been commented for MSVC # define CGLM_ALIGN(X) __attribute((aligned(X))) #endif. -So MSVC may not know about aligment requirements when creating variables. +So MSVC may not know about alignment requirements when creating variables. The interesting thing is that, if I remember correctly Visual Studio 2017 doesn't throw the above error. So we may uncomment that line for Visual Studio 2017, you may do it yourself. @@ -61,7 +61,7 @@ Again, you may used wrong function. For instance if you use **glm_normalize()** or **glm_vec_normalize()** for **vec4**, it will assume that passed param is **vec3** and will normalize it for **vec3**. -Since you need to **vec4** to be normalized in your case, you will get wrong results. +Since you need to **vec4** to be normalized in your case, you will get wrong results. Accessing vec4 type with vec3 functions is valid, you will not get any error, exception or crash. You only get wrong results if you don't know what you are doing! From 0f339c5c03f73b6751ffeb00e6e9f4a8620bae42 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Mon, 7 May 2018 21:12:29 +0300 Subject: [PATCH 87/98] fix header dependencies --- include/cglm/affine-mat.h | 1 + include/cglm/mat4.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/include/cglm/affine-mat.h b/include/cglm/affine-mat.h index b320509..62bfce1 100644 --- a/include/cglm/affine-mat.h +++ b/include/cglm/affine-mat.h @@ -16,6 +16,7 @@ #include "common.h" #include "mat4.h" +#include "mat3.h" #ifdef CGLM_SSE_FP # include "simd/sse2/affine.h" diff --git a/include/cglm/mat4.h b/include/cglm/mat4.h index 1b254a2..d1a72cb 100644 --- a/include/cglm/mat4.h +++ b/include/cglm/mat4.h @@ -45,7 +45,6 @@ #define cglm_mat_h #include "common.h" -#include "quat.h" #include "vec4.h" #include "vec3.h" From 252bf925fc4ecd9cd939992f3651df15fc84e0c3 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 8 May 2018 15:25:23 +0300 Subject: [PATCH 88/98] simd, sse2: make alignment optional for load operations --- include/cglm/affine.h | 34 ++++++++--------- include/cglm/mat4.h | 8 ++-- include/cglm/quat.h | 2 +- include/cglm/simd/intrin.h | 12 +++++- include/cglm/simd/sse2/affine.h | 38 +++++++++---------- include/cglm/simd/sse2/mat4.h | 66 ++++++++++++++++----------------- include/cglm/simd/sse2/quat.h | 4 +- include/cglm/vec4-ext.h | 6 +-- include/cglm/vec4.h | 58 ++++++++++++++--------------- 9 files changed, 118 insertions(+), 110 deletions(-) diff --git a/include/cglm/affine.h b/include/cglm/affine.h index 8124930..b200f30 100644 --- a/include/cglm/affine.h +++ b/include/cglm/affine.h @@ -59,18 +59,18 @@ glm_translate_to(mat4 m, vec3 v, mat4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) _mm_store_ps(dest[3], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_load_ps(t[0]), + _mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_load(t[0]), _mm_set1_ps(v[0])), - _mm_mul_ps(_mm_load_ps(t[1]), + _mm_mul_ps(glmm_load(t[1]), _mm_set1_ps(v[1]))), - _mm_add_ps(_mm_mul_ps(_mm_load_ps(t[2]), + _mm_add_ps(_mm_mul_ps(glmm_load(t[2]), _mm_set1_ps(v[2])), - _mm_load_ps(t[3])))) + glmm_load(t[3])))) ; - _mm_store_ps(dest[0], _mm_load_ps(m[0])); - _mm_store_ps(dest[1], _mm_load_ps(m[1])); - _mm_store_ps(dest[2], _mm_load_ps(m[2])); + _mm_store_ps(dest[0], glmm_load(m[0])); + _mm_store_ps(dest[1], glmm_load(m[1])); + _mm_store_ps(dest[2], glmm_load(m[2])); #else vec4 v1, v2, v3; @@ -98,13 +98,13 @@ void glm_translate(mat4 m, vec3 v) { #if defined( __SSE__ ) || defined( __SSE2__ ) _mm_store_ps(m[3], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_load_ps(m[0]), + _mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_load(m[0]), _mm_set1_ps(v[0])), - _mm_mul_ps(_mm_load_ps(m[1]), + _mm_mul_ps(glmm_load(m[1]), _mm_set1_ps(v[1]))), - _mm_add_ps(_mm_mul_ps(_mm_load_ps(m[2]), + _mm_add_ps(_mm_mul_ps(glmm_load(m[2]), _mm_set1_ps(v[2])), - _mm_load_ps(m[3])))) + glmm_load(m[3])))) ; #else vec4 v1, v2, v3; @@ -130,9 +130,9 @@ void glm_translate_x(mat4 m, float x) { #if defined( __SSE__ ) || defined( __SSE2__ ) _mm_store_ps(m[3], - _mm_add_ps(_mm_mul_ps(_mm_load_ps(m[0]), + _mm_add_ps(_mm_mul_ps(glmm_load(m[0]), _mm_set1_ps(x)), - _mm_load_ps(m[3]))) + glmm_load(m[3]))) ; #else vec4 v1; @@ -152,9 +152,9 @@ void glm_translate_y(mat4 m, float y) { #if defined( __SSE__ ) || defined( __SSE2__ ) _mm_store_ps(m[3], - _mm_add_ps(_mm_mul_ps(_mm_load_ps(m[1]), + _mm_add_ps(_mm_mul_ps(glmm_load(m[1]), _mm_set1_ps(y)), - _mm_load_ps(m[3]))) + glmm_load(m[3]))) ; #else vec4 v1; @@ -174,9 +174,9 @@ void glm_translate_z(mat4 m, float z) { #if defined( __SSE__ ) || defined( __SSE2__ ) _mm_store_ps(m[3], - _mm_add_ps(_mm_mul_ps(_mm_load_ps(m[2]), + _mm_add_ps(_mm_mul_ps(glmm_load(m[2]), _mm_set1_ps(z)), - _mm_load_ps(m[3]))) + glmm_load(m[3]))) ; #else vec4 v1; diff --git a/include/cglm/mat4.h b/include/cglm/mat4.h index d1a72cb..8cafb7c 100644 --- a/include/cglm/mat4.h +++ b/include/cglm/mat4.h @@ -113,10 +113,10 @@ glm_mat4_copy(mat4 mat, mat4 dest) { _mm256_store_ps(dest[0], _mm256_load_ps(mat[0])); _mm256_store_ps(dest[2], _mm256_load_ps(mat[2])); #elif defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest[0], _mm_load_ps(mat[0])); - _mm_store_ps(dest[1], _mm_load_ps(mat[1])); - _mm_store_ps(dest[2], _mm_load_ps(mat[2])); - _mm_store_ps(dest[3], _mm_load_ps(mat[3])); + _mm_store_ps(dest[0], glmm_load(mat[0])); + _mm_store_ps(dest[1], glmm_load(mat[1])); + _mm_store_ps(dest[2], glmm_load(mat[2])); + _mm_store_ps(dest[3], glmm_load(mat[3])); #else glm_mat4_ucopy(mat, dest); #endif diff --git a/include/cglm/quat.h b/include/cglm/quat.h index f6dc86e..6bff527 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -198,7 +198,7 @@ glm_quat_normalize_to(versor q, versor dest) { __m128 xdot, x0; float dot; - x0 = _mm_load_ps(q); + x0 = glmm_load(q); xdot = glm_simd_dot(x0, x0); dot = _mm_cvtss_f32(xdot); diff --git a/include/cglm/simd/intrin.h b/include/cglm/simd/intrin.h index cf6753f..bf1db60 100644 --- a/include/cglm/simd/intrin.h +++ b/include/cglm/simd/intrin.h @@ -35,7 +35,7 @@ _mm_shuffle1_ps(_mm_shuffle_ps(a, b, _MM_SHUFFLE(z0, y0, x0, w0)), \ z1, y1, x1, w1) -CGLM_INLINE +static inline __m128 glm_simd_dot(__m128 a, __m128 b) { __m128 x0; @@ -44,7 +44,7 @@ glm_simd_dot(__m128 a, __m128 b) { return _mm_add_ps(x0, _mm_shuffle1_ps(x0, 0, 1, 0, 1)); } -CGLM_INLINE +static inline __m128 glm_simd_norm(__m128 a) { return _mm_sqrt_ps(glm_simd_dot(a, a)); @@ -69,6 +69,14 @@ glm_simd_store_v3(__m128 vx, vec3 v) { _mm_store_ss(&v[2], _mm_shuffle1_ps(vx, 2, 2, 2, 2)); } +#ifdef CGLM_ALL_UNALIGNED +#define glmm_load(p) _mm_loadu_ps(p) +#define glmm_store(p, a) _mm_storeu_ps(p, a) +#else +#define glmm_load(p) _mm_load_ps(p) +#define glmm_store(p, a) _mm_store_ps(p, a) +#endif + #endif /* x86, x64 */ diff --git a/include/cglm/simd/sse2/affine.h b/include/cglm/simd/sse2/affine.h index b746d0f..df8c166 100644 --- a/include/cglm/simd/sse2/affine.h +++ b/include/cglm/simd/sse2/affine.h @@ -18,30 +18,30 @@ glm_mul_sse2(mat4 m1, mat4 m2, mat4 dest) { /* D = R * L (Column-Major) */ __m128 l0, l1, l2, l3, r; - l0 = _mm_load_ps(m1[0]); - l1 = _mm_load_ps(m1[1]); - l2 = _mm_load_ps(m1[2]); - l3 = _mm_load_ps(m1[3]); + l0 = glmm_load(m1[0]); + l1 = glmm_load(m1[1]); + l2 = glmm_load(m1[2]); + l3 = glmm_load(m1[3]); - r = _mm_load_ps(m2[0]); + r = glmm_load(m2[0]); _mm_store_ps(dest[0], _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), _mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2))); - r = _mm_load_ps(m2[1]); + r = glmm_load(m2[1]); _mm_store_ps(dest[1], _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), _mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2))); - r = _mm_load_ps(m2[2]); + r = glmm_load(m2[2]); _mm_store_ps(dest[2], _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), _mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2))); - r = _mm_load_ps(m2[3]); + r = glmm_load(m2[3]); _mm_store_ps(dest[3], _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), @@ -55,24 +55,24 @@ glm_mul_rot_sse2(mat4 m1, mat4 m2, mat4 dest) { /* D = R * L (Column-Major) */ __m128 l0, l1, l2, l3, r; - l0 = _mm_load_ps(m1[0]); - l1 = _mm_load_ps(m1[1]); - l2 = _mm_load_ps(m1[2]); - l3 = _mm_load_ps(m1[3]); + l0 = glmm_load(m1[0]); + l1 = glmm_load(m1[1]); + l2 = glmm_load(m1[2]); + l3 = glmm_load(m1[3]); - r = _mm_load_ps(m2[0]); + r = glmm_load(m2[0]); _mm_store_ps(dest[0], _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), _mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2))); - r = _mm_load_ps(m2[1]); + r = glmm_load(m2[1]); _mm_store_ps(dest[1], _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), _mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2))); - r = _mm_load_ps(m2[2]); + r = glmm_load(m2[2]); _mm_store_ps(dest[2], _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), @@ -86,10 +86,10 @@ void glm_inv_tr_sse2(mat4 mat) { __m128 r0, r1, r2, r3, x0, x1; - r0 = _mm_load_ps(mat[0]); - r1 = _mm_load_ps(mat[1]); - r2 = _mm_load_ps(mat[2]); - r3 = _mm_load_ps(mat[3]); + r0 = glmm_load(mat[0]); + r1 = glmm_load(mat[1]); + r2 = glmm_load(mat[2]); + r3 = glmm_load(mat[3]); x1 = _mm_set_ps(1.0f, 0.0f, 0.0f, 0.0f); _MM_TRANSPOSE4_PS(r0, r1, r2, x1); diff --git a/include/cglm/simd/sse2/mat4.h b/include/cglm/simd/sse2/mat4.h index 77874a8..404b496 100644 --- a/include/cglm/simd/sse2/mat4.h +++ b/include/cglm/simd/sse2/mat4.h @@ -20,10 +20,10 @@ glm_mat4_scale_sse2(mat4 m, float s){ __m128 x0; x0 = _mm_set1_ps(s); - _mm_store_ps(m[0], _mm_mul_ps(_mm_load_ps(m[0]), x0)); - _mm_store_ps(m[1], _mm_mul_ps(_mm_load_ps(m[1]), x0)); - _mm_store_ps(m[2], _mm_mul_ps(_mm_load_ps(m[2]), x0)); - _mm_store_ps(m[3], _mm_mul_ps(_mm_load_ps(m[3]), x0)); + _mm_store_ps(m[0], _mm_mul_ps(glmm_load(m[0]), x0)); + _mm_store_ps(m[1], _mm_mul_ps(glmm_load(m[1]), x0)); + _mm_store_ps(m[2], _mm_mul_ps(glmm_load(m[2]), x0)); + _mm_store_ps(m[3], _mm_mul_ps(glmm_load(m[3]), x0)); } CGLM_INLINE @@ -31,10 +31,10 @@ void glm_mat4_transp_sse2(mat4 m, mat4 dest){ __m128 r0, r1, r2, r3; - r0 = _mm_load_ps(m[0]); - r1 = _mm_load_ps(m[1]); - r2 = _mm_load_ps(m[2]); - r3 = _mm_load_ps(m[3]); + r0 = glmm_load(m[0]); + r1 = glmm_load(m[1]); + r2 = glmm_load(m[2]); + r3 = glmm_load(m[3]); _MM_TRANSPOSE4_PS(r0, r1, r2, r3); @@ -51,31 +51,31 @@ glm_mat4_mul_sse2(mat4 m1, mat4 m2, mat4 dest) { __m128 l0, l1, l2, l3, r; - l0 = _mm_load_ps(m1[0]); - l1 = _mm_load_ps(m1[1]); - l2 = _mm_load_ps(m1[2]); - l3 = _mm_load_ps(m1[3]); + l0 = glmm_load(m1[0]); + l1 = glmm_load(m1[1]); + l2 = glmm_load(m1[2]); + l3 = glmm_load(m1[3]); - r = _mm_load_ps(m2[0]); + r = glmm_load(m2[0]); _mm_store_ps(dest[0], _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), _mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2), _mm_mul_ps(_mm_shuffle1_ps1(r, 3), l3)))); - r = _mm_load_ps(m2[1]); + r = glmm_load(m2[1]); _mm_store_ps(dest[1], _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), _mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2), _mm_mul_ps(_mm_shuffle1_ps1(r, 3), l3)))); - r = _mm_load_ps(m2[2]); + r = glmm_load(m2[2]); _mm_store_ps(dest[2], _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), _mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2), _mm_mul_ps(_mm_shuffle1_ps1(r, 3), l3)))); - r = _mm_load_ps(m2[3]); + r = glmm_load(m2[3]); _mm_store_ps(dest[3], _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), @@ -88,15 +88,15 @@ void glm_mat4_mulv_sse2(mat4 m, vec4 v, vec4 dest) { __m128 x0, x1, x2; - x0 = _mm_load_ps(v); - x1 = _mm_add_ps(_mm_mul_ps(_mm_load_ps(m[0]), + x0 = glmm_load(v); + x1 = _mm_add_ps(_mm_mul_ps(glmm_load(m[0]), _mm_shuffle1_ps1(x0, 0)), - _mm_mul_ps(_mm_load_ps(m[1]), + _mm_mul_ps(glmm_load(m[1]), _mm_shuffle1_ps1(x0, 1))); - x2 = _mm_add_ps(_mm_mul_ps(_mm_load_ps(m[2]), + x2 = _mm_add_ps(_mm_mul_ps(glmm_load(m[2]), _mm_shuffle1_ps1(x0, 2)), - _mm_mul_ps(_mm_load_ps(m[3]), + _mm_mul_ps(glmm_load(m[3]), _mm_shuffle1_ps1(x0, 3))); _mm_store_ps(dest, _mm_add_ps(x1, x2)); @@ -108,10 +108,10 @@ glm_mat4_det_sse2(mat4 mat) { __m128 r0, r1, r2, r3, x0, x1, x2; /* 127 <- 0, [square] det(A) = det(At) */ - r0 = _mm_load_ps(mat[0]); /* d c b a */ - r1 = _mm_load_ps(mat[1]); /* h g f e */ - r2 = _mm_load_ps(mat[2]); /* l k j i */ - r3 = _mm_load_ps(mat[3]); /* p o n m */ + r0 = glmm_load(mat[0]); /* d c b a */ + r1 = glmm_load(mat[1]); /* h g f e */ + r2 = glmm_load(mat[2]); /* l k j i */ + r3 = glmm_load(mat[3]); /* p o n m */ /* t[1] = j * p - n * l; @@ -166,10 +166,10 @@ glm_mat4_inv_fast_sse2(mat4 mat, mat4 dest) { x0, x1, x2, x3, x4, x5, x6, x7; /* 127 <- 0 */ - r0 = _mm_load_ps(mat[0]); /* d c b a */ - r1 = _mm_load_ps(mat[1]); /* h g f e */ - r2 = _mm_load_ps(mat[2]); /* l k j i */ - r3 = _mm_load_ps(mat[3]); /* p o n m */ + r0 = glmm_load(mat[0]); /* d c b a */ + r1 = glmm_load(mat[1]); /* h g f e */ + r2 = glmm_load(mat[2]); /* l k j i */ + r3 = glmm_load(mat[3]); /* p o n m */ x0 = _mm_shuffle_ps(r2, r3, _MM_SHUFFLE(3, 2, 3, 2)); /* p o l k */ x1 = _mm_shuffle1_ps(x0, 1, 3, 3, 3); /* l p p p */ @@ -290,10 +290,10 @@ glm_mat4_inv_sse2(mat4 mat, mat4 dest) { x0, x1, x2, x3, x4, x5, x6, x7; /* 127 <- 0 */ - r0 = _mm_load_ps(mat[0]); /* d c b a */ - r1 = _mm_load_ps(mat[1]); /* h g f e */ - r2 = _mm_load_ps(mat[2]); /* l k j i */ - r3 = _mm_load_ps(mat[3]); /* p o n m */ + r0 = glmm_load(mat[0]); /* d c b a */ + r1 = glmm_load(mat[1]); /* h g f e */ + r2 = glmm_load(mat[2]); /* l k j i */ + r3 = glmm_load(mat[3]); /* p o n m */ x0 = _mm_shuffle_ps(r2, r3, _MM_SHUFFLE(3, 2, 3, 2)); /* p o l k */ x1 = _mm_shuffle1_ps(x0, 1, 3, 3, 3); /* l p p p */ diff --git a/include/cglm/simd/sse2/quat.h b/include/cglm/simd/sse2/quat.h index 5dbf759..4970eff 100644 --- a/include/cglm/simd/sse2/quat.h +++ b/include/cglm/simd/sse2/quat.h @@ -24,8 +24,8 @@ glm_quat_mul_sse2(versor p, versor q, versor dest) { __m128 xp, xq, x0, r; - xp = _mm_load_ps(p); /* 3 2 1 0 */ - xq = _mm_load_ps(q); + xp = glmm_load(p); /* 3 2 1 0 */ + xq = glmm_load(q); r = _mm_mul_ps(_mm_shuffle1_ps1(xp, 3), xq); diff --git a/include/cglm/vec4-ext.h b/include/cglm/vec4-ext.h index 7a6cb3d..1055ebe 100644 --- a/include/cglm/vec4-ext.h +++ b/include/cglm/vec4-ext.h @@ -42,7 +42,7 @@ CGLM_INLINE void glm_vec4_mulv(vec4 a, vec4 b, vec4 d) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(d, _mm_mul_ps(_mm_load_ps(a), _mm_load_ps(b))); + _mm_store_ps(d, _mm_mul_ps(glmm_load(a), glmm_load(b))); #else d[0] = a[0] * b[0]; d[1] = a[1] * b[1]; @@ -223,7 +223,7 @@ glm_vec4_sign(vec4 v, vec4 dest) { #if defined( __SSE2__ ) || defined( __SSE2__ ) __m128 x0, x1, x2, x3, x4; - x0 = _mm_load_ps(v); + x0 = glmm_load(v); x1 = _mm_set_ps(0.0f, 0.0f, 1.0f, -1.0f); x2 = _mm_shuffle1_ps1(x1, 2); @@ -249,7 +249,7 @@ CGLM_INLINE void glm_vec4_sqrt(vec4 v, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_sqrt_ps(_mm_load_ps(v))); + _mm_store_ps(dest, _mm_sqrt_ps(glmm_load(v))); #else dest[0] = sqrtf(v[0]); dest[1] = sqrtf(v[1]); diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index 2e9ca45..b2a9b97 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -111,7 +111,7 @@ CGLM_INLINE void glm_vec4_copy(vec4 v, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_load_ps(v)); + _mm_store_ps(dest, glmm_load(v)); #else dest[0] = v[0]; dest[1] = v[1]; @@ -169,7 +169,7 @@ float glm_vec4_dot(vec4 a, vec4 b) { #if defined( __SSE__ ) || defined( __SSE2__ ) __m128 x0; - x0 = _mm_mul_ps(_mm_load_ps(a), _mm_load_ps(b)); + x0 = _mm_mul_ps(glmm_load(a), glmm_load(b)); x0 = _mm_add_ps(x0, _mm_shuffle1_ps(x0, 1, 0, 3, 2)); return _mm_cvtss_f32(_mm_add_ss(x0, _mm_shuffle1_ps(x0, 0, 1, 0, 1))); #else @@ -193,7 +193,7 @@ float glm_vec4_norm2(vec4 v) { #if defined( __SSE__ ) || defined( __SSE2__ ) __m128 x0; - x0 = _mm_load_ps(v); + x0 = glmm_load(v); x0 = _mm_mul_ps(x0, x0); x0 = _mm_add_ps(x0, _mm_shuffle1_ps(x0, 1, 0, 3, 2)); return _mm_cvtss_f32(_mm_add_ss(x0, _mm_shuffle1_ps(x0, 0, 1, 0, 1))); @@ -214,7 +214,7 @@ float glm_vec4_norm(vec4 vec) { #if defined( __SSE__ ) || defined( __SSE2__ ) __m128 x0; - x0 = _mm_load_ps(vec); + x0 = glmm_load(vec); return _mm_cvtss_f32(_mm_sqrt_ss(glm_simd_dot(x0, x0))); #else return sqrtf(glm_vec4_norm2(vec)); @@ -232,7 +232,7 @@ CGLM_INLINE void glm_vec4_add(vec4 a, vec4 b, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_add_ps(_mm_load_ps(a), _mm_load_ps(b))); + _mm_store_ps(dest, _mm_add_ps(glmm_load(a), glmm_load(b))); #else dest[0] = a[0] + b[0]; dest[1] = a[1] + b[1]; @@ -252,7 +252,7 @@ CGLM_INLINE void glm_vec4_adds(vec4 v, float s, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_add_ps(_mm_load_ps(v), _mm_set1_ps(s))); + _mm_store_ps(dest, _mm_add_ps(glmm_load(v), _mm_set1_ps(s))); #else dest[0] = v[0] + s; dest[1] = v[1] + s; @@ -272,7 +272,7 @@ CGLM_INLINE void glm_vec4_sub(vec4 a, vec4 b, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_sub_ps(_mm_load_ps(a), _mm_load_ps(b))); + _mm_store_ps(dest, _mm_sub_ps(glmm_load(a), glmm_load(b))); #else dest[0] = a[0] - b[0]; dest[1] = a[1] - b[1]; @@ -292,7 +292,7 @@ CGLM_INLINE void glm_vec4_subs(vec4 v, float s, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_sub_ps(_mm_load_ps(v), _mm_set1_ps(s))); + _mm_store_ps(dest, _mm_sub_ps(glmm_load(v), _mm_set1_ps(s))); #else dest[0] = v[0] - s; dest[1] = v[1] - s; @@ -312,7 +312,7 @@ CGLM_INLINE void glm_vec4_mul(vec4 a, vec4 b, vec4 d) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(d, _mm_mul_ps(_mm_load_ps(a), _mm_load_ps(b))); + _mm_store_ps(d, _mm_mul_ps(glmm_load(a), glmm_load(b))); #else d[0] = a[0] * b[0]; d[1] = a[1] * b[1]; @@ -332,7 +332,7 @@ CGLM_INLINE void glm_vec4_scale(vec4 v, float s, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_mul_ps(_mm_load_ps(v), _mm_set1_ps(s))); + _mm_store_ps(dest, _mm_mul_ps(glmm_load(v), _mm_set1_ps(s))); #else dest[0] = v[0] * s; dest[1] = v[1] * s; @@ -373,7 +373,7 @@ CGLM_INLINE void glm_vec4_div(vec4 a, vec4 b, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_div_ps(_mm_load_ps(a), _mm_load_ps(b))); + _mm_store_ps(dest, _mm_div_ps(glmm_load(a), glmm_load(b))); #else dest[0] = a[0] / b[0]; dest[1] = a[1] / b[1]; @@ -393,7 +393,7 @@ CGLM_INLINE void glm_vec4_divs(vec4 v, float s, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_div_ps(_mm_load_ps(v), _mm_set1_ps(s))); + _mm_store_ps(dest, _mm_div_ps(glmm_load(v), _mm_set1_ps(s))); #else glm_vec4_scale(v, 1.0f / s, dest); #endif @@ -413,9 +413,9 @@ CGLM_INLINE void glm_vec4_addadd(vec4 a, vec4 b, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_add_ps(_mm_load_ps(dest), - _mm_add_ps(_mm_load_ps(a), - _mm_load_ps(b)))); + _mm_store_ps(dest, _mm_add_ps(glmm_load(dest), + _mm_add_ps(glmm_load(a), + glmm_load(b)))); #else dest[0] += a[0] + b[0]; dest[1] += a[1] + b[1]; @@ -437,9 +437,9 @@ CGLM_INLINE void glm_vec4_subadd(vec4 a, vec4 b, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_add_ps(_mm_load_ps(dest), - _mm_sub_ps(_mm_load_ps(a), - _mm_load_ps(b)))); + _mm_store_ps(dest, _mm_add_ps(glmm_load(dest), + _mm_sub_ps(glmm_load(a), + glmm_load(b)))); #else dest[0] += a[0] - b[0]; dest[1] += a[1] - b[1]; @@ -461,9 +461,9 @@ CGLM_INLINE void glm_vec4_muladd(vec4 a, vec4 b, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_add_ps(_mm_load_ps(dest), - _mm_mul_ps(_mm_load_ps(a), - _mm_load_ps(b)))); + _mm_store_ps(dest, _mm_add_ps(glmm_load(dest), + _mm_mul_ps(glmm_load(a), + glmm_load(b)))); #else dest[0] += a[0] * b[0]; dest[1] += a[1] * b[1]; @@ -485,8 +485,8 @@ CGLM_INLINE void glm_vec4_muladds(vec4 a, float s, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_add_ps(_mm_load_ps(dest), - _mm_mul_ps(_mm_load_ps(a), + _mm_store_ps(dest, _mm_add_ps(glmm_load(dest), + _mm_mul_ps(glmm_load(a), _mm_set1_ps(s)))); #else dest[0] += a[0] * s; @@ -505,7 +505,7 @@ CGLM_INLINE void glm_vec4_flipsign(vec4 v) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(v, _mm_xor_ps(_mm_load_ps(v), _mm_set1_ps(-0.0f))); + _mm_store_ps(v, _mm_xor_ps(glmm_load(v), _mm_set1_ps(-0.0f))); #else v[0] = -v[0]; v[1] = -v[1]; @@ -524,7 +524,7 @@ CGLM_INLINE void glm_vec4_flipsign_to(vec4 v, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_xor_ps(_mm_load_ps(v), + _mm_store_ps(dest, _mm_xor_ps(glmm_load(v), _mm_set1_ps(-0.0f))); #else dest[0] = -v[0]; @@ -571,7 +571,7 @@ glm_vec4_normalize_to(vec4 vec, vec4 dest) { __m128 xdot, x0; float dot; - x0 = _mm_load_ps(vec); + x0 = glmm_load(vec); xdot = glm_simd_dot(x0, x0); dot = _mm_cvtss_f32(xdot); @@ -633,7 +633,7 @@ CGLM_INLINE void glm_vec4_maxv(vec4 v1, vec4 v2, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_max_ps(_mm_load_ps(v1), _mm_load_ps(v2))); + _mm_store_ps(dest, _mm_max_ps(glmm_load(v1), glmm_load(v2))); #else dest[0] = glm_max(v1[0], v2[0]); dest[1] = glm_max(v1[1], v2[1]); @@ -653,7 +653,7 @@ CGLM_INLINE void glm_vec4_minv(vec4 v1, vec4 v2, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_min_ps(_mm_load_ps(v1), _mm_load_ps(v2))); + _mm_store_ps(dest, _mm_min_ps(glmm_load(v1), glmm_load(v2))); #else dest[0] = glm_min(v1[0], v2[0]); dest[1] = glm_min(v1[1], v2[1]); @@ -673,7 +673,7 @@ CGLM_INLINE void glm_vec4_clamp(vec4 v, float minVal, float maxVal) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(v, _mm_min_ps(_mm_max_ps(_mm_load_ps(v), _mm_set1_ps(minVal)), + _mm_store_ps(v, _mm_min_ps(_mm_max_ps(glmm_load(v), _mm_set1_ps(minVal)), _mm_set1_ps(maxVal))); #else v[0] = glm_clamp(v[0], minVal, maxVal); From 568001d26a5b047a2e1ac438497e8a778048fb8f Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 8 May 2018 15:31:09 +0300 Subject: [PATCH 89/98] simd, sse2: make alignment optional for store operations --- include/cglm/affine.h | 62 +++++++++++++-------------- include/cglm/mat4.h | 8 ++-- include/cglm/quat.h | 2 +- include/cglm/simd/sse2/affine.h | 68 +++++++++++++++--------------- include/cglm/simd/sse2/mat4.h | 74 ++++++++++++++++----------------- include/cglm/simd/sse2/quat.h | 2 +- include/cglm/vec4-ext.h | 8 ++-- include/cglm/vec4.h | 63 ++++++++++++++-------------- 8 files changed, 143 insertions(+), 144 deletions(-) diff --git a/include/cglm/affine.h b/include/cglm/affine.h index b200f30..dd7dbd1 100644 --- a/include/cglm/affine.h +++ b/include/cglm/affine.h @@ -58,19 +58,19 @@ glm_translate_to(mat4 m, vec3 v, mat4 dest) { mat4 t = GLM_MAT4_IDENTITY_INIT; #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest[3], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_load(t[0]), - _mm_set1_ps(v[0])), - _mm_mul_ps(glmm_load(t[1]), - _mm_set1_ps(v[1]))), - _mm_add_ps(_mm_mul_ps(glmm_load(t[2]), - _mm_set1_ps(v[2])), - glmm_load(t[3])))) + glmm_store(dest[3], + _mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_load(t[0]), + _mm_set1_ps(v[0])), + _mm_mul_ps(glmm_load(t[1]), + _mm_set1_ps(v[1]))), + _mm_add_ps(_mm_mul_ps(glmm_load(t[2]), + _mm_set1_ps(v[2])), + glmm_load(t[3])))) ; - _mm_store_ps(dest[0], glmm_load(m[0])); - _mm_store_ps(dest[1], glmm_load(m[1])); - _mm_store_ps(dest[2], glmm_load(m[2])); + glmm_store(dest[0], glmm_load(m[0])); + glmm_store(dest[1], glmm_load(m[1])); + glmm_store(dest[2], glmm_load(m[2])); #else vec4 v1, v2, v3; @@ -97,14 +97,14 @@ CGLM_INLINE void glm_translate(mat4 m, vec3 v) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(m[3], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_load(m[0]), - _mm_set1_ps(v[0])), - _mm_mul_ps(glmm_load(m[1]), - _mm_set1_ps(v[1]))), - _mm_add_ps(_mm_mul_ps(glmm_load(m[2]), - _mm_set1_ps(v[2])), - glmm_load(m[3])))) + glmm_store(m[3], + _mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_load(m[0]), + _mm_set1_ps(v[0])), + _mm_mul_ps(glmm_load(m[1]), + _mm_set1_ps(v[1]))), + _mm_add_ps(_mm_mul_ps(glmm_load(m[2]), + _mm_set1_ps(v[2])), + glmm_load(m[3])))) ; #else vec4 v1, v2, v3; @@ -129,10 +129,10 @@ CGLM_INLINE void glm_translate_x(mat4 m, float x) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(m[3], - _mm_add_ps(_mm_mul_ps(glmm_load(m[0]), - _mm_set1_ps(x)), - glmm_load(m[3]))) + glmm_store(m[3], + _mm_add_ps(_mm_mul_ps(glmm_load(m[0]), + _mm_set1_ps(x)), + glmm_load(m[3]))) ; #else vec4 v1; @@ -151,10 +151,10 @@ CGLM_INLINE void glm_translate_y(mat4 m, float y) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(m[3], - _mm_add_ps(_mm_mul_ps(glmm_load(m[1]), - _mm_set1_ps(y)), - glmm_load(m[3]))) + glmm_store(m[3], + _mm_add_ps(_mm_mul_ps(glmm_load(m[1]), + _mm_set1_ps(y)), + glmm_load(m[3]))) ; #else vec4 v1; @@ -173,10 +173,10 @@ CGLM_INLINE void glm_translate_z(mat4 m, float z) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(m[3], - _mm_add_ps(_mm_mul_ps(glmm_load(m[2]), - _mm_set1_ps(z)), - glmm_load(m[3]))) + glmm_store(m[3], + _mm_add_ps(_mm_mul_ps(glmm_load(m[2]), + _mm_set1_ps(z)), + glmm_load(m[3]))) ; #else vec4 v1; diff --git a/include/cglm/mat4.h b/include/cglm/mat4.h index 8cafb7c..88563cb 100644 --- a/include/cglm/mat4.h +++ b/include/cglm/mat4.h @@ -113,10 +113,10 @@ glm_mat4_copy(mat4 mat, mat4 dest) { _mm256_store_ps(dest[0], _mm256_load_ps(mat[0])); _mm256_store_ps(dest[2], _mm256_load_ps(mat[2])); #elif defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest[0], glmm_load(mat[0])); - _mm_store_ps(dest[1], glmm_load(mat[1])); - _mm_store_ps(dest[2], glmm_load(mat[2])); - _mm_store_ps(dest[3], glmm_load(mat[3])); + glmm_store(dest[0], glmm_load(mat[0])); + glmm_store(dest[1], glmm_load(mat[1])); + glmm_store(dest[2], glmm_load(mat[2])); + glmm_store(dest[3], glmm_load(mat[3])); #else glm_mat4_ucopy(mat, dest); #endif diff --git a/include/cglm/quat.h b/include/cglm/quat.h index 6bff527..0ba2cf6 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -207,7 +207,7 @@ glm_quat_normalize_to(versor q, versor dest) { return; } - _mm_store_ps(dest, _mm_div_ps(x0, _mm_sqrt_ps(xdot))); + glmm_store(dest, _mm_div_ps(x0, _mm_sqrt_ps(xdot))); #else float dot; diff --git a/include/cglm/simd/sse2/affine.h b/include/cglm/simd/sse2/affine.h index df8c166..c0c9c04 100644 --- a/include/cglm/simd/sse2/affine.h +++ b/include/cglm/simd/sse2/affine.h @@ -24,29 +24,29 @@ glm_mul_sse2(mat4 m1, mat4 m2, mat4 dest) { l3 = glmm_load(m1[3]); r = glmm_load(m2[0]); - _mm_store_ps(dest[0], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), - _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), - _mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2))); + glmm_store(dest[0], + _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), + _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), + _mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2))); r = glmm_load(m2[1]); - _mm_store_ps(dest[1], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), - _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), - _mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2))); + glmm_store(dest[1], + _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), + _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), + _mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2))); r = glmm_load(m2[2]); - _mm_store_ps(dest[2], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), - _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), - _mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2))); + glmm_store(dest[2], + _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), + _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), + _mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2))); r = glmm_load(m2[3]); - _mm_store_ps(dest[3], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), - _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), - _mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2), - _mm_mul_ps(_mm_shuffle1_ps1(r, 3), l3)))); + glmm_store(dest[3], + _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), + _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), + _mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2), + _mm_mul_ps(_mm_shuffle1_ps1(r, 3), l3)))); } CGLM_INLINE @@ -61,24 +61,24 @@ glm_mul_rot_sse2(mat4 m1, mat4 m2, mat4 dest) { l3 = glmm_load(m1[3]); r = glmm_load(m2[0]); - _mm_store_ps(dest[0], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), - _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), - _mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2))); + glmm_store(dest[0], + _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), + _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), + _mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2))); r = glmm_load(m2[1]); - _mm_store_ps(dest[1], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), - _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), - _mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2))); + glmm_store(dest[1], + _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), + _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), + _mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2))); r = glmm_load(m2[2]); - _mm_store_ps(dest[2], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), - _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), - _mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2))); + glmm_store(dest[2], + _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), + _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), + _mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2))); - _mm_store_ps(dest[3], l3); + glmm_store(dest[3], l3); } CGLM_INLINE @@ -101,10 +101,10 @@ glm_inv_tr_sse2(mat4 mat) { x0 = _mm_add_ps(x0, x1); - _mm_store_ps(mat[0], r0); - _mm_store_ps(mat[1], r1); - _mm_store_ps(mat[2], r2); - _mm_store_ps(mat[3], x0); + glmm_store(mat[0], r0); + glmm_store(mat[1], r1); + glmm_store(mat[2], r2); + glmm_store(mat[3], x0); } #endif diff --git a/include/cglm/simd/sse2/mat4.h b/include/cglm/simd/sse2/mat4.h index 404b496..1f82c08 100644 --- a/include/cglm/simd/sse2/mat4.h +++ b/include/cglm/simd/sse2/mat4.h @@ -20,10 +20,10 @@ glm_mat4_scale_sse2(mat4 m, float s){ __m128 x0; x0 = _mm_set1_ps(s); - _mm_store_ps(m[0], _mm_mul_ps(glmm_load(m[0]), x0)); - _mm_store_ps(m[1], _mm_mul_ps(glmm_load(m[1]), x0)); - _mm_store_ps(m[2], _mm_mul_ps(glmm_load(m[2]), x0)); - _mm_store_ps(m[3], _mm_mul_ps(glmm_load(m[3]), x0)); + glmm_store(m[0], _mm_mul_ps(glmm_load(m[0]), x0)); + glmm_store(m[1], _mm_mul_ps(glmm_load(m[1]), x0)); + glmm_store(m[2], _mm_mul_ps(glmm_load(m[2]), x0)); + glmm_store(m[3], _mm_mul_ps(glmm_load(m[3]), x0)); } CGLM_INLINE @@ -38,10 +38,10 @@ glm_mat4_transp_sse2(mat4 m, mat4 dest){ _MM_TRANSPOSE4_PS(r0, r1, r2, r3); - _mm_store_ps(dest[0], r0); - _mm_store_ps(dest[1], r1); - _mm_store_ps(dest[2], r2); - _mm_store_ps(dest[3], r3); + glmm_store(dest[0], r0); + glmm_store(dest[1], r1); + glmm_store(dest[2], r2); + glmm_store(dest[3], r3); } CGLM_INLINE @@ -57,30 +57,30 @@ glm_mat4_mul_sse2(mat4 m1, mat4 m2, mat4 dest) { l3 = glmm_load(m1[3]); r = glmm_load(m2[0]); - _mm_store_ps(dest[0], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), - _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), - _mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2), - _mm_mul_ps(_mm_shuffle1_ps1(r, 3), l3)))); + glmm_store(dest[0], + _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), + _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), + _mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2), + _mm_mul_ps(_mm_shuffle1_ps1(r, 3), l3)))); r = glmm_load(m2[1]); - _mm_store_ps(dest[1], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), - _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), - _mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2), - _mm_mul_ps(_mm_shuffle1_ps1(r, 3), l3)))); + glmm_store(dest[1], + _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), + _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), + _mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2), + _mm_mul_ps(_mm_shuffle1_ps1(r, 3), l3)))); r = glmm_load(m2[2]); - _mm_store_ps(dest[2], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), - _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), - _mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2), - _mm_mul_ps(_mm_shuffle1_ps1(r, 3), l3)))); + glmm_store(dest[2], + _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), + _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), + _mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2), + _mm_mul_ps(_mm_shuffle1_ps1(r, 3), l3)))); r = glmm_load(m2[3]); - _mm_store_ps(dest[3], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), - _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), - _mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2), - _mm_mul_ps(_mm_shuffle1_ps1(r, 3), l3)))); + glmm_store(dest[3], + _mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), + _mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), + _mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2), + _mm_mul_ps(_mm_shuffle1_ps1(r, 3), l3)))); } CGLM_INLINE @@ -99,7 +99,7 @@ glm_mat4_mulv_sse2(mat4 m, vec4 v, vec4 dest) { _mm_mul_ps(glmm_load(m[3]), _mm_shuffle1_ps1(x0, 3))); - _mm_store_ps(dest, _mm_add_ps(x1, x2)); + glmm_store(dest, _mm_add_ps(x1, x2)); } CGLM_INLINE @@ -275,10 +275,10 @@ glm_mat4_inv_fast_sse2(mat4 mat, mat4 dest) { x0 = _mm_add_ps(x0, _mm_shuffle1_ps(x0, 1, 0, 0, 1)); x0 = _mm_rcp_ps(x0); - _mm_store_ps(dest[0], _mm_mul_ps(v0, x0)); - _mm_store_ps(dest[1], _mm_mul_ps(v1, x0)); - _mm_store_ps(dest[2], _mm_mul_ps(v2, x0)); - _mm_store_ps(dest[3], _mm_mul_ps(v3, x0)); + glmm_store(dest[0], _mm_mul_ps(v0, x0)); + glmm_store(dest[1], _mm_mul_ps(v1, x0)); + glmm_store(dest[2], _mm_mul_ps(v2, x0)); + glmm_store(dest[3], _mm_mul_ps(v3, x0)); } CGLM_INLINE @@ -399,10 +399,10 @@ glm_mat4_inv_sse2(mat4 mat, mat4 dest) { x0 = _mm_add_ps(x0, _mm_shuffle1_ps(x0, 1, 0, 0, 1)); x0 = _mm_div_ps(_mm_set1_ps(1.0f), x0); - _mm_store_ps(dest[0], _mm_mul_ps(v0, x0)); - _mm_store_ps(dest[1], _mm_mul_ps(v1, x0)); - _mm_store_ps(dest[2], _mm_mul_ps(v2, x0)); - _mm_store_ps(dest[3], _mm_mul_ps(v3, x0)); + glmm_store(dest[0], _mm_mul_ps(v0, x0)); + glmm_store(dest[1], _mm_mul_ps(v1, x0)); + glmm_store(dest[2], _mm_mul_ps(v2, x0)); + glmm_store(dest[3], _mm_mul_ps(v3, x0)); } #endif diff --git a/include/cglm/simd/sse2/quat.h b/include/cglm/simd/sse2/quat.h index 4970eff..a8b517c 100644 --- a/include/cglm/simd/sse2/quat.h +++ b/include/cglm/simd/sse2/quat.h @@ -38,7 +38,7 @@ glm_quat_mul_sse2(versor p, versor q, versor dest) { x0 = _mm_xor_ps(_mm_shuffle1_ps1(xp, 2), _mm_set_ps(-0.f, 0.f, 0.f, -0.f)); r = _mm_add_ps(r, _mm_mul_ps(x0, _mm_shuffle1_ps(xq, 2, 3, 0, 1))); - _mm_store_ps(dest, r); + glmm_store(dest, r); } diff --git a/include/cglm/vec4-ext.h b/include/cglm/vec4-ext.h index 1055ebe..94150da 100644 --- a/include/cglm/vec4-ext.h +++ b/include/cglm/vec4-ext.h @@ -42,7 +42,7 @@ CGLM_INLINE void glm_vec4_mulv(vec4 a, vec4 b, vec4 d) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(d, _mm_mul_ps(glmm_load(a), glmm_load(b))); + glmm_store(d, _mm_mul_ps(glmm_load(a), glmm_load(b))); #else d[0] = a[0] * b[0]; d[1] = a[1] * b[1]; @@ -61,7 +61,7 @@ CGLM_INLINE void glm_vec4_broadcast(float val, vec4 d) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(d, _mm_set1_ps(val)); + glmm_store(d, _mm_set1_ps(val)); #else d[0] = d[1] = d[2] = d[3] = val; #endif @@ -230,7 +230,7 @@ glm_vec4_sign(vec4 v, vec4 dest) { x3 = _mm_and_ps(_mm_cmpgt_ps(x0, x2), _mm_shuffle1_ps1(x1, 1)); x4 = _mm_and_ps(_mm_cmplt_ps(x0, x2), _mm_shuffle1_ps1(x1, 0)); - _mm_store_ps(dest, _mm_or_ps(x3, x4)); + glmm_store(dest, _mm_or_ps(x3, x4)); #else dest[0] = glm_signf(v[0]); dest[1] = glm_signf(v[1]); @@ -249,7 +249,7 @@ CGLM_INLINE void glm_vec4_sqrt(vec4 v, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_sqrt_ps(glmm_load(v))); + glmm_store(dest, _mm_sqrt_ps(glmm_load(v))); #else dest[0] = sqrtf(v[0]); dest[1] = sqrtf(v[1]); diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index b2a9b97..912932f 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -111,7 +111,7 @@ CGLM_INLINE void glm_vec4_copy(vec4 v, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, glmm_load(v)); + glmm_store(dest, glmm_load(v)); #else dest[0] = v[0]; dest[1] = v[1]; @@ -129,7 +129,7 @@ CGLM_INLINE void glm_vec4_zero(vec4 v) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(v, _mm_setzero_ps()); + glmm_store(v, _mm_setzero_ps()); #else v[0] = 0.0f; v[1] = 0.0f; @@ -147,7 +147,7 @@ CGLM_INLINE void glm_vec4_one(vec4 v) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(v, _mm_set1_ps(1.0f)); + glmm_store(v, _mm_set1_ps(1.0f)); #else v[0] = 1.0f; v[1] = 1.0f; @@ -232,7 +232,7 @@ CGLM_INLINE void glm_vec4_add(vec4 a, vec4 b, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_add_ps(glmm_load(a), glmm_load(b))); + glmm_store(dest, _mm_add_ps(glmm_load(a), glmm_load(b))); #else dest[0] = a[0] + b[0]; dest[1] = a[1] + b[1]; @@ -252,7 +252,7 @@ CGLM_INLINE void glm_vec4_adds(vec4 v, float s, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_add_ps(glmm_load(v), _mm_set1_ps(s))); + glmm_store(dest, _mm_add_ps(glmm_load(v), _mm_set1_ps(s))); #else dest[0] = v[0] + s; dest[1] = v[1] + s; @@ -272,7 +272,7 @@ CGLM_INLINE void glm_vec4_sub(vec4 a, vec4 b, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_sub_ps(glmm_load(a), glmm_load(b))); + glmm_store(dest, _mm_sub_ps(glmm_load(a), glmm_load(b))); #else dest[0] = a[0] - b[0]; dest[1] = a[1] - b[1]; @@ -292,7 +292,7 @@ CGLM_INLINE void glm_vec4_subs(vec4 v, float s, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_sub_ps(glmm_load(v), _mm_set1_ps(s))); + glmm_store(dest, _mm_sub_ps(glmm_load(v), _mm_set1_ps(s))); #else dest[0] = v[0] - s; dest[1] = v[1] - s; @@ -312,7 +312,7 @@ CGLM_INLINE void glm_vec4_mul(vec4 a, vec4 b, vec4 d) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(d, _mm_mul_ps(glmm_load(a), glmm_load(b))); + glmm_store(d, _mm_mul_ps(glmm_load(a), glmm_load(b))); #else d[0] = a[0] * b[0]; d[1] = a[1] * b[1]; @@ -332,7 +332,7 @@ CGLM_INLINE void glm_vec4_scale(vec4 v, float s, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_mul_ps(glmm_load(v), _mm_set1_ps(s))); + glmm_store(dest, _mm_mul_ps(glmm_load(v), _mm_set1_ps(s))); #else dest[0] = v[0] * s; dest[1] = v[1] * s; @@ -373,7 +373,7 @@ CGLM_INLINE void glm_vec4_div(vec4 a, vec4 b, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_div_ps(glmm_load(a), glmm_load(b))); + glmm_store(dest, _mm_div_ps(glmm_load(a), glmm_load(b))); #else dest[0] = a[0] / b[0]; dest[1] = a[1] / b[1]; @@ -393,7 +393,7 @@ CGLM_INLINE void glm_vec4_divs(vec4 v, float s, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_div_ps(glmm_load(v), _mm_set1_ps(s))); + glmm_store(dest, _mm_div_ps(glmm_load(v), _mm_set1_ps(s))); #else glm_vec4_scale(v, 1.0f / s, dest); #endif @@ -413,9 +413,9 @@ CGLM_INLINE void glm_vec4_addadd(vec4 a, vec4 b, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_add_ps(glmm_load(dest), - _mm_add_ps(glmm_load(a), - glmm_load(b)))); + glmm_store(dest, _mm_add_ps(glmm_load(dest), + _mm_add_ps(glmm_load(a), + glmm_load(b)))); #else dest[0] += a[0] + b[0]; dest[1] += a[1] + b[1]; @@ -437,9 +437,9 @@ CGLM_INLINE void glm_vec4_subadd(vec4 a, vec4 b, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_add_ps(glmm_load(dest), - _mm_sub_ps(glmm_load(a), - glmm_load(b)))); + glmm_store(dest, _mm_add_ps(glmm_load(dest), + _mm_sub_ps(glmm_load(a), + glmm_load(b)))); #else dest[0] += a[0] - b[0]; dest[1] += a[1] - b[1]; @@ -461,9 +461,9 @@ CGLM_INLINE void glm_vec4_muladd(vec4 a, vec4 b, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_add_ps(glmm_load(dest), - _mm_mul_ps(glmm_load(a), - glmm_load(b)))); + glmm_store(dest, _mm_add_ps(glmm_load(dest), + _mm_mul_ps(glmm_load(a), + glmm_load(b)))); #else dest[0] += a[0] * b[0]; dest[1] += a[1] * b[1]; @@ -485,9 +485,9 @@ CGLM_INLINE void glm_vec4_muladds(vec4 a, float s, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_add_ps(glmm_load(dest), - _mm_mul_ps(glmm_load(a), - _mm_set1_ps(s)))); + glmm_store(dest, _mm_add_ps(glmm_load(dest), + _mm_mul_ps(glmm_load(a), + _mm_set1_ps(s)))); #else dest[0] += a[0] * s; dest[1] += a[1] * s; @@ -505,7 +505,7 @@ CGLM_INLINE void glm_vec4_flipsign(vec4 v) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(v, _mm_xor_ps(glmm_load(v), _mm_set1_ps(-0.0f))); + glmm_store(v, _mm_xor_ps(glmm_load(v), _mm_set1_ps(-0.0f))); #else v[0] = -v[0]; v[1] = -v[1]; @@ -524,8 +524,7 @@ CGLM_INLINE void glm_vec4_flipsign_to(vec4 v, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_xor_ps(glmm_load(v), - _mm_set1_ps(-0.0f))); + glmm_store(dest, _mm_xor_ps(glmm_load(v), _mm_set1_ps(-0.0f))); #else dest[0] = -v[0]; dest[1] = -v[1]; @@ -576,11 +575,11 @@ glm_vec4_normalize_to(vec4 vec, vec4 dest) { dot = _mm_cvtss_f32(xdot); if (dot == 0.0f) { - _mm_store_ps(dest, _mm_setzero_ps()); + glmm_store(dest, _mm_setzero_ps()); return; } - _mm_store_ps(dest, _mm_div_ps(x0, _mm_sqrt_ps(xdot))); + glmm_store(dest, _mm_div_ps(x0, _mm_sqrt_ps(xdot))); #else float norm; @@ -633,7 +632,7 @@ CGLM_INLINE void glm_vec4_maxv(vec4 v1, vec4 v2, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_max_ps(glmm_load(v1), glmm_load(v2))); + glmm_store(dest, _mm_max_ps(glmm_load(v1), glmm_load(v2))); #else dest[0] = glm_max(v1[0], v2[0]); dest[1] = glm_max(v1[1], v2[1]); @@ -653,7 +652,7 @@ CGLM_INLINE void glm_vec4_minv(vec4 v1, vec4 v2, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, _mm_min_ps(glmm_load(v1), glmm_load(v2))); + glmm_store(dest, _mm_min_ps(glmm_load(v1), glmm_load(v2))); #else dest[0] = glm_min(v1[0], v2[0]); dest[1] = glm_min(v1[1], v2[1]); @@ -673,8 +672,8 @@ CGLM_INLINE void glm_vec4_clamp(vec4 v, float minVal, float maxVal) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(v, _mm_min_ps(_mm_max_ps(glmm_load(v), _mm_set1_ps(minVal)), - _mm_set1_ps(maxVal))); + glmm_store(v, _mm_min_ps(_mm_max_ps(glmm_load(v), _mm_set1_ps(minVal)), + _mm_set1_ps(maxVal))); #else v[0] = glm_clamp(v[0], minVal, maxVal); v[1] = glm_clamp(v[1], minVal, maxVal); From 56f0bb0928e127ed993ec6e46aef9ad7d8cfd819 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 8 May 2018 15:35:17 +0300 Subject: [PATCH 90/98] simd, avx: make alignment optional for load/store operations --- include/cglm/mat4.h | 4 ++-- include/cglm/simd/avx/affine.h | 26 +++++++++++++------------- include/cglm/simd/avx/mat4.h | 28 ++++++++++++++-------------- include/cglm/simd/intrin.h | 17 +++++++++++++---- 4 files changed, 42 insertions(+), 33 deletions(-) diff --git a/include/cglm/mat4.h b/include/cglm/mat4.h index 88563cb..f0b6736 100644 --- a/include/cglm/mat4.h +++ b/include/cglm/mat4.h @@ -110,8 +110,8 @@ CGLM_INLINE void glm_mat4_copy(mat4 mat, mat4 dest) { #ifdef __AVX__ - _mm256_store_ps(dest[0], _mm256_load_ps(mat[0])); - _mm256_store_ps(dest[2], _mm256_load_ps(mat[2])); + glmm_store256(dest[0], glmm_load256(mat[0])); + glmm_store256(dest[2], glmm_load256(mat[2])); #elif defined( __SSE__ ) || defined( __SSE2__ ) glmm_store(dest[0], glmm_load(mat[0])); glmm_store(dest[1], glmm_load(mat[1])); diff --git a/include/cglm/simd/avx/affine.h b/include/cglm/simd/avx/affine.h index 1b0dcea..5c7f71c 100644 --- a/include/cglm/simd/avx/affine.h +++ b/include/cglm/simd/avx/affine.h @@ -21,11 +21,11 @@ glm_mul_avx(mat4 m1, mat4 m2, mat4 dest) { __m256 y0, y1, y2, y3, y4, y5, y6, y7, y8, y9; - y0 = _mm256_load_ps(m2[0]); /* h g f e d c b a */ - y1 = _mm256_load_ps(m2[2]); /* p o n m l k j i */ + y0 = glmm_load256(m2[0]); /* h g f e d c b a */ + y1 = glmm_load256(m2[2]); /* p o n m l k j i */ - y2 = _mm256_load_ps(m1[0]); /* h g f e d c b a */ - y3 = _mm256_load_ps(m1[2]); /* p o n m l k j i */ + y2 = glmm_load256(m1[0]); /* h g f e d c b a */ + y3 = glmm_load256(m1[2]); /* p o n m l k j i */ y4 = _mm256_permute2f128_ps(y2, y2, 0b00000011); /* d c b a h g f e */ y5 = _mm256_permute2f128_ps(y3, y3, 0b00000000); /* l k j i l k j i */ @@ -37,10 +37,10 @@ glm_mul_avx(mat4 m1, mat4 m2, mat4 dest) { y6 = _mm256_permutevar_ps(y0, _mm256_set_epi32(1, 1, 1, 1, 0, 0, 0, 0)); y8 = _mm256_permutevar_ps(y0, _mm256_set_epi32(0, 0, 0, 0, 1, 1, 1, 1)); - _mm256_store_ps(dest[0], - _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6), - _mm256_mul_ps(y4, y8)), - _mm256_mul_ps(y5, y7))); + glmm_store256(dest[0], + _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6), + _mm256_mul_ps(y4, y8)), + _mm256_mul_ps(y5, y7))); /* n n n n i i i i */ @@ -52,11 +52,11 @@ glm_mul_avx(mat4 m1, mat4 m2, mat4 dest) { y8 = _mm256_permutevar_ps(y1, _mm256_set_epi32(0, 0, 0, 0, 1, 1, 1, 1)); y9 = _mm256_permutevar_ps(y1, _mm256_set_epi32(2, 2, 2, 2, 3, 3, 3, 3)); - _mm256_store_ps(dest[2], - _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6), - _mm256_mul_ps(y3, y7)), - _mm256_add_ps(_mm256_mul_ps(y4, y8), - _mm256_mul_ps(y5, y9)))); + glmm_store256(dest[2], + _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6), + _mm256_mul_ps(y3, y7)), + _mm256_add_ps(_mm256_mul_ps(y4, y8), + _mm256_mul_ps(y5, y9)))); } #endif diff --git a/include/cglm/simd/avx/mat4.h b/include/cglm/simd/avx/mat4.h index e2ef9da..b5859a7 100644 --- a/include/cglm/simd/avx/mat4.h +++ b/include/cglm/simd/avx/mat4.h @@ -21,11 +21,11 @@ glm_mat4_mul_avx(mat4 m1, mat4 m2, mat4 dest) { __m256 y0, y1, y2, y3, y4, y5, y6, y7, y8, y9; - y0 = _mm256_load_ps(m2[0]); /* h g f e d c b a */ - y1 = _mm256_load_ps(m2[2]); /* p o n m l k j i */ + y0 = glmm_load256(m2[0]); /* h g f e d c b a */ + y1 = glmm_load256(m2[2]); /* p o n m l k j i */ - y2 = _mm256_load_ps(m1[0]); /* h g f e d c b a */ - y3 = _mm256_load_ps(m1[2]); /* p o n m l k j i */ + y2 = glmm_load256(m1[0]); /* h g f e d c b a */ + y3 = glmm_load256(m1[2]); /* p o n m l k j i */ y4 = _mm256_permute2f128_ps(y2, y2, 0b00000011); /* d c b a h g f e */ y5 = _mm256_permute2f128_ps(y3, y3, 0b00000011); /* l k j i p o n m */ @@ -39,11 +39,11 @@ glm_mat4_mul_avx(mat4 m1, mat4 m2, mat4 dest) { y8 = _mm256_permutevar_ps(y0, _mm256_set_epi32(0, 0, 0, 0, 1, 1, 1, 1)); y9 = _mm256_permutevar_ps(y0, _mm256_set_epi32(2, 2, 2, 2, 3, 3, 3, 3)); - _mm256_store_ps(dest[0], - _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6), - _mm256_mul_ps(y3, y7)), - _mm256_add_ps(_mm256_mul_ps(y4, y8), - _mm256_mul_ps(y5, y9)))); + glmm_store256(dest[0], + _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6), + _mm256_mul_ps(y3, y7)), + _mm256_add_ps(_mm256_mul_ps(y4, y8), + _mm256_mul_ps(y5, y9)))); /* n n n n i i i i */ /* p p p p k k k k */ @@ -54,11 +54,11 @@ glm_mat4_mul_avx(mat4 m1, mat4 m2, mat4 dest) { y8 = _mm256_permutevar_ps(y1, _mm256_set_epi32(0, 0, 0, 0, 1, 1, 1, 1)); y9 = _mm256_permutevar_ps(y1, _mm256_set_epi32(2, 2, 2, 2, 3, 3, 3, 3)); - _mm256_store_ps(dest[2], - _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6), - _mm256_mul_ps(y3, y7)), - _mm256_add_ps(_mm256_mul_ps(y4, y8), - _mm256_mul_ps(y5, y9)))); + glmm_store256(dest[2], + _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6), + _mm256_mul_ps(y3, y7)), + _mm256_add_ps(_mm256_mul_ps(y4, y8), + _mm256_mul_ps(y5, y9)))); } #endif diff --git a/include/cglm/simd/intrin.h b/include/cglm/simd/intrin.h index bf1db60..8fd1526 100644 --- a/include/cglm/simd/intrin.h +++ b/include/cglm/simd/intrin.h @@ -70,11 +70,11 @@ glm_simd_store_v3(__m128 vx, vec3 v) { } #ifdef CGLM_ALL_UNALIGNED -#define glmm_load(p) _mm_loadu_ps(p) -#define glmm_store(p, a) _mm_storeu_ps(p, a) +# define glmm_load(p) _mm_loadu_ps(p) +# define glmm_store(p, a) _mm_storeu_ps(p, a) #else -#define glmm_load(p) _mm_load_ps(p) -#define glmm_store(p, a) _mm_store_ps(p, a) +# define glmm_load(p) _mm_load_ps(p) +# define glmm_store(p, a) _mm_store_ps(p, a) #endif #endif @@ -86,6 +86,15 @@ glm_simd_store_v3(__m128 vx, vec3 v) { #ifdef __AVX__ # define CGLM_AVX_FP 1 + +#ifdef CGLM_ALL_UNALIGNED +# define glmm_load256(p) _mm256_loadu_ps(p) +# define glmm_store256(p, a) _mm256_storeu_ps(p, a) +#else +# define glmm_load256(p) _mm256_load_ps(p) +# define glmm_store256(p, a) _mm256_store_ps(p, a) +#endif + #endif /* ARM Neon */ From 5dbbd0826d1cd18f6722d193447d2b720aea9bdd Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 8 May 2018 15:55:36 +0300 Subject: [PATCH 91/98] simd: replace glm_simd_ with glmm_ * now glmm_ is used as global simd namescape --- include/cglm/quat.h | 2 +- include/cglm/simd/intrin.h | 10 +++++----- include/cglm/vec4.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/cglm/quat.h b/include/cglm/quat.h index 0ba2cf6..eac853b 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -199,7 +199,7 @@ glm_quat_normalize_to(versor q, versor dest) { float dot; x0 = glmm_load(q); - xdot = glm_simd_dot(x0, x0); + xdot = glmm_dot(x0, x0); dot = _mm_cvtss_f32(xdot); if (dot <= 0.0f) { diff --git a/include/cglm/simd/intrin.h b/include/cglm/simd/intrin.h index 8fd1526..c9ab352 100644 --- a/include/cglm/simd/intrin.h +++ b/include/cglm/simd/intrin.h @@ -37,7 +37,7 @@ static inline __m128 -glm_simd_dot(__m128 a, __m128 b) { +glmm_dot(__m128 a, __m128 b) { __m128 x0; x0 = _mm_mul_ps(a, b); x0 = _mm_add_ps(x0, _mm_shuffle1_ps(x0, 1, 0, 3, 2)); @@ -46,13 +46,13 @@ glm_simd_dot(__m128 a, __m128 b) { static inline __m128 -glm_simd_norm(__m128 a) { - return _mm_sqrt_ps(glm_simd_dot(a, a)); +glmm_norm(__m128 a) { + return _mm_sqrt_ps(glmm_dot(a, a)); } static inline __m128 -glm_simd_load_v3(vec3 v) { +glmm_load3(vec3 v) { __m128i xy; __m128 z; @@ -64,7 +64,7 @@ glm_simd_load_v3(vec3 v) { static inline void -glm_simd_store_v3(__m128 vx, vec3 v) { +glmm_store3(__m128 vx, vec3 v) { _mm_storel_pi((__m64 *)&v[0], vx); _mm_store_ss(&v[2], _mm_shuffle1_ps(vx, 2, 2, 2, 2)); } diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index 912932f..b98190b 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -215,7 +215,7 @@ glm_vec4_norm(vec4 vec) { #if defined( __SSE__ ) || defined( __SSE2__ ) __m128 x0; x0 = glmm_load(vec); - return _mm_cvtss_f32(_mm_sqrt_ss(glm_simd_dot(x0, x0))); + return _mm_cvtss_f32(_mm_sqrt_ss(glmm_dot(x0, x0))); #else return sqrtf(glm_vec4_norm2(vec)); #endif @@ -571,7 +571,7 @@ glm_vec4_normalize_to(vec4 vec, vec4 dest) { float dot; x0 = glmm_load(vec); - xdot = glm_simd_dot(x0, x0); + xdot = glmm_dot(x0, x0); dot = _mm_cvtss_f32(xdot); if (dot == 0.0f) { From 835cec2ccb0aaf872c5b10c24feecbd5ae099023 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 8 May 2018 16:26:33 +0300 Subject: [PATCH 92/98] drop alignment requirement if CGLM_ALL_UNALIGNED defined * bring alignment back for visual studio 2017 --- include/cglm/simd/intrin.h | 4 ++-- include/cglm/types.h | 26 +++++++++++++++++++------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/include/cglm/simd/intrin.h b/include/cglm/simd/intrin.h index c9ab352..9fef5a1 100644 --- a/include/cglm/simd/intrin.h +++ b/include/cglm/simd/intrin.h @@ -52,7 +52,7 @@ glmm_norm(__m128 a) { static inline __m128 -glmm_load3(vec3 v) { +glmm_load3(float v[3]) { __m128i xy; __m128 z; @@ -64,7 +64,7 @@ glmm_load3(vec3 v) { static inline void -glmm_store3(__m128 vx, vec3 v) { +glmm_store3(__m128 vx, float v[3]) { _mm_storel_pi((__m64 *)&v[0], vx); _mm_store_ss(&v[2], _mm_shuffle1_ps(vx, 2, 2, 2, 2)); } diff --git a/include/cglm/types.h b/include/cglm/types.h index 5d39a55..ad4eb02 100644 --- a/include/cglm/types.h +++ b/include/cglm/types.h @@ -9,20 +9,32 @@ #define cglm_types_h #if defined(_MSC_VER) -# define CGLM_ALIGN(X) /* __declspec(align(X)) */ +#if _MSC_VER < 1914 /* Visual Studio 2017 version 15.7 */ +# define CGLM_ALL_UNALIGNED +/* do not use alignment for older visual studio versions */ +# define CGLM_ALIGN(X) /* __declspec(align(X)) */ +#else +# define CGLM_ALIGN(X) __declspec(align(X)) +#endif #else # define CGLM_ALIGN(X) __attribute((aligned(X))) #endif -typedef float vec2[2]; -typedef CGLM_ALIGN(8) float vec3[3]; -typedef int ivec3[3]; -typedef CGLM_ALIGN(16) float vec4[4]; +#ifndef CGLM_ALL_UNALIGNED +# define CGLM_ALIGN_IF(X) CGLM_ALIGN(X) +#else +# define CGLM_ALIGN_IF(X) /* no alignment */ +#endif + +typedef float vec2[2]; +typedef CGLM_ALIGN_IF(8) float vec3[3]; +typedef int ivec3[3]; +typedef CGLM_ALIGN_IF(16) float vec4[4]; typedef vec3 mat3[3]; -typedef CGLM_ALIGN(16) vec4 mat4[4]; +typedef CGLM_ALIGN_IF(16) vec4 mat4[4]; -typedef vec4 versor; +typedef vec4 versor; #define CGLM_PI (float)M_PI #define CGLM_PI_2 (float)M_PI_2 From b27735780057fabc5375d2da3b78104deed972d7 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 8 May 2018 18:28:31 +0300 Subject: [PATCH 93/98] update gitignore --- .gitignore | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.gitignore b/.gitignore index 37f68c8..d500b97 100644 --- a/.gitignore +++ b/.gitignore @@ -61,3 +61,11 @@ docs/build/* win/cglm_test_* * copy.* *.o +*.obj +*codeanalysis.*.xml +*codeanalysis.xml +*.lib +*.tlog +win/x64 +win/x85 +win/Debug From 0e49e951618544ec802f27314c7652264f8c3751 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 8 May 2018 18:29:02 +0300 Subject: [PATCH 94/98] win: update visual studio version for align requirement --- include/cglm/types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/cglm/types.h b/include/cglm/types.h index ad4eb02..4a7d019 100644 --- a/include/cglm/types.h +++ b/include/cglm/types.h @@ -9,7 +9,7 @@ #define cglm_types_h #if defined(_MSC_VER) -#if _MSC_VER < 1914 /* Visual Studio 2017 version 15.7 */ +#if _MSC_VER < 1913 /* Visual Studio 2017 version 15.6 */ # define CGLM_ALL_UNALIGNED /* do not use alignment for older visual studio versions */ # define CGLM_ALIGN(X) /* __declspec(align(X)) */ From f774925e8a3182c3699f21b70948ba5c8b6d4ce5 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Wed, 9 May 2018 15:30:54 +0300 Subject: [PATCH 95/98] win, simd: make sure that CGLM_ALL_UNALIGNED is defined for older visual studios --- include/cglm/simd/intrin.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/cglm/simd/intrin.h b/include/cglm/simd/intrin.h index 9fef5a1..3d5682d 100644 --- a/include/cglm/simd/intrin.h +++ b/include/cglm/simd/intrin.h @@ -18,6 +18,10 @@ # define __SSE__ # endif # endif +/* do not use alignment for older visual studio versions */ +# if _MSC_VER < 1913 /* Visual Studio 2017 version 15.6 */ +# define CGLM_ALL_UNALIGNED +# endif #endif #if defined( __SSE__ ) || defined( __SSE2__ ) From 94b286f1f92f42cfea8fea88f8ad6a8de793584b Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Wed, 9 May 2018 16:35:15 +0300 Subject: [PATCH 96/98] docs: add new alignment option to docs --- docs/source/getting_started.rst | 7 +++++++ docs/source/index.rst | 1 + docs/source/opt.rst | 36 +++++++++++++++++++++++++++++++++ docs/source/troubleshooting.rst | 3 +++ include/cglm/types.h | 6 +++--- 5 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 docs/source/opt.rst diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst index a152371..05c4440 100644 --- a/docs/source/getting_started.rst +++ b/docs/source/getting_started.rst @@ -27,6 +27,13 @@ Alignment is Required: **vec4** and **mat4** requires 16 byte alignment because vec4 and mat4 operations are vectorized by SIMD instructions (SSE/AVX). +**UPDATE:** + By starting v0.4.5 cglm provides an option to disable alignment requirement, it is enabled as default + + | Check :doc:`opt` page for more details + + Also alignment is disabled for older msvc verisons as default. Now alignment only is required in Visual Studio 2017 version 15.6+ if CGLM_ALL_UNALIGNED macro is not defined. + Allocations: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *cglm* doesn't alloc any memory on heap. So it doesn't provide any allocator. diff --git a/docs/source/index.rst b/docs/source/index.rst index 32e7b48..cfdf220 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -40,6 +40,7 @@ Also currently only **float** type is supported for most operations. getting_started opengl api + opt troubleshooting Indices and tables diff --git a/docs/source/opt.rst b/docs/source/opt.rst new file mode 100644 index 0000000..c614e42 --- /dev/null +++ b/docs/source/opt.rst @@ -0,0 +1,36 @@ +.. default-domain:: C + +Options +=============================================================================== + +A few options are provided via macros. + +Alignment +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +As default, cglm requires types to be aligned. Alignment requirements: + +vec3: 8 byte +vec4: 16 byte +mat4: 16 byte +versor: 16 byte + +By starting **v0.4.5** cglm provides an option to disable alignment requirement. +To enable this option define **CGLM_ALL_UNALIGNED** macro before all headers. +You can define it in Xcode, Visual Studio (or other IDEs) or you can also prefer +to define it in build system. If you use pre-compiled verisons then you +have to compile cglm with **CGLM_ALL_UNALIGNED** macro. + +**VERY VERY IMPORTANT:** If you use cglm in multiple projects and + those projects are depends on each other, then + + | *ALWAYS* or *NEVER USE* **CGLM_ALL_UNALIGNED** macro in linked projects + + if you do not know what you are doing. Because a cglm header included + via 'project A' may force types to be aligned and another cglm header + included via 'project B' may not require alignment. In this case + cglm functions will read from and write to **INVALID MEMORY LOCATIONs**. + + ALWAYS USE SAME CONFIGURATION / OPTION for **cglm** if you have multiple projects. + + For instance if you set CGLM_ALL_UNALIGNED in a project then set it in other projects too diff --git a/docs/source/troubleshooting.rst b/docs/source/troubleshooting.rst index d599c7d..7c416b0 100644 --- a/docs/source/troubleshooting.rst +++ b/docs/source/troubleshooting.rst @@ -43,6 +43,9 @@ you may do it yourself. **This MSVC issue is still in TODOs.** +**UPDATE:** By starting v0.4.5 cglm provides an option to disable alignment requirement. +Also alignment is disabled for older msvc verisons as default. Now alignment only is required in Visual Studio 2017 version 15.6+ if CGLM_ALL_UNALIGNED macro is defined. + Crashes, Invalid Memory Access: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/include/cglm/types.h b/include/cglm/types.h index 4a7d019..99226df 100644 --- a/include/cglm/types.h +++ b/include/cglm/types.h @@ -9,10 +9,10 @@ #define cglm_types_h #if defined(_MSC_VER) -#if _MSC_VER < 1913 /* Visual Studio 2017 version 15.6 */ -# define CGLM_ALL_UNALIGNED /* do not use alignment for older visual studio versions */ -# define CGLM_ALIGN(X) /* __declspec(align(X)) */ +#if _MSC_VER < 1913 /* Visual Studio 2017 version 15.6 */ +# define CGLM_ALL_UNALIGNED +# define CGLM_ALIGN(X) /* no alignment */ #else # define CGLM_ALIGN(X) __declspec(align(X)) #endif From c6d07bb6eb036742c25bdad9b8ccb6d74871cb64 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Thu, 10 May 2018 12:18:54 +0300 Subject: [PATCH 97/98] surround PI with parentheses + code style + update docs --- docs/source/getting_started.rst | 4 ++-- docs/source/troubleshooting.rst | 2 +- include/cglm/simd/sse2/affine.h | 2 +- include/cglm/types.h | 10 +++++----- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst index 05c4440..2f8511c 100644 --- a/docs/source/getting_started.rst +++ b/docs/source/getting_started.rst @@ -28,11 +28,11 @@ Alignment is Required: vectorized by SIMD instructions (SSE/AVX). **UPDATE:** - By starting v0.4.5 cglm provides an option to disable alignment requirement, it is enabled as default + By starting v0.4.5 cglm provides an option to disable alignment requirement, it is enabled as default | Check :doc:`opt` page for more details - Also alignment is disabled for older msvc verisons as default. Now alignment only is required in Visual Studio 2017 version 15.6+ if CGLM_ALL_UNALIGNED macro is not defined. + Also alignment is disabled for older msvc verisons as default. Now alignment is only required in Visual Studio 2017 version 15.6+ if CGLM_ALL_UNALIGNED macro is not defined. Allocations: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/source/troubleshooting.rst b/docs/source/troubleshooting.rst index 7c416b0..c897dc2 100644 --- a/docs/source/troubleshooting.rst +++ b/docs/source/troubleshooting.rst @@ -44,7 +44,7 @@ you may do it yourself. **This MSVC issue is still in TODOs.** **UPDATE:** By starting v0.4.5 cglm provides an option to disable alignment requirement. -Also alignment is disabled for older msvc verisons as default. Now alignment only is required in Visual Studio 2017 version 15.6+ if CGLM_ALL_UNALIGNED macro is defined. +Also alignment is disabled for older msvc verisons as default. Now alignment is only required in Visual Studio 2017 version 15.6+ if CGLM_ALL_UNALIGNED macro is not defined. Crashes, Invalid Memory Access: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/include/cglm/simd/sse2/affine.h b/include/cglm/simd/sse2/affine.h index c0c9c04..8a644d3 100644 --- a/include/cglm/simd/sse2/affine.h +++ b/include/cglm/simd/sse2/affine.h @@ -90,7 +90,7 @@ glm_inv_tr_sse2(mat4 mat) { r1 = glmm_load(mat[1]); r2 = glmm_load(mat[2]); r3 = glmm_load(mat[3]); - x1 = _mm_set_ps(1.0f, 0.0f, 0.0f, 0.0f); + x1 = _mm_set_ps(1.0f, 0.0f, 0.0f, 0.0f); _MM_TRANSPOSE4_PS(r0, r1, r2, x1); diff --git a/include/cglm/types.h b/include/cglm/types.h index 99226df..d470e7b 100644 --- a/include/cglm/types.h +++ b/include/cglm/types.h @@ -27,17 +27,17 @@ #endif typedef float vec2[2]; -typedef CGLM_ALIGN_IF(8) float vec3[3]; +typedef CGLM_ALIGN_IF(8) float vec3[3]; typedef int ivec3[3]; typedef CGLM_ALIGN_IF(16) float vec4[4]; -typedef vec3 mat3[3]; +typedef vec3 mat3[3]; typedef CGLM_ALIGN_IF(16) vec4 mat4[4]; typedef vec4 versor; -#define CGLM_PI (float)M_PI -#define CGLM_PI_2 (float)M_PI_2 -#define CGLM_PI_4 (float)M_PI_4 +#define CGLM_PI ((float)M_PI) +#define CGLM_PI_2 ((float)M_PI_2) +#define CGLM_PI_4 ((float)M_PI_4) #endif /* cglm_types_h */ From 464bd917d094d79b886248596f75fdae9a545865 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Thu, 10 May 2018 12:21:33 +0300 Subject: [PATCH 98/98] update readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 15f434c..ff1b4df 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,8 @@ Complete documentation: http://cglm.readthedocs.io - **[bugfix]** euler angles was implemented in reverse order (extrinsic) it was fixed, now they are intrinsic. Make sure that you have the latest version - **[major change]** by starting v0.4.0, quaternions are stored as [x, y, z, w], it was [w, x, y, z] in v0.3.5 and earlier versions +- **[api rename]** by starting v0.4.5, **glm_simd** functions are renamed to **glmm_** +- **[new option]** by starting v0.4.5, you can disable alignment requirement, check options in docs. #### Note for C++ developers: If you don't aware about original GLM library yet, you may also want to look at: