From c63c6c90aceb7e8ead996775dc9c83f699f60514 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 17 Apr 2018 11:12:18 +0300 Subject: [PATCH 01/11] 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 02/11] 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 03/11] 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 04/11] 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 05/11] 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 06/11] 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 07/11] 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 08/11] 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 09/11] 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 10/11] 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 11/11] 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;