diff options
Diffstat (limited to 'libs/cglm/docs/source/affine.rst')
-rw-r--r-- | libs/cglm/docs/source/affine.rst | 345 |
1 files changed, 345 insertions, 0 deletions
diff --git a/libs/cglm/docs/source/affine.rst b/libs/cglm/docs/source/affine.rst new file mode 100644 index 0000000..df2dcb7 --- /dev/null +++ b/libs/cglm/docs/source/affine.rst @@ -0,0 +1,345 @@ +.. default-domain:: C + +3D 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. + +But other functions expect you have a matrix and you want to transform them. If +you didn't have any existing matrix you have to initialize matrix to identity +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. + +The implementation would be: + +.. code-block:: c + :linenos: + + glm_translate(m, pivot); + glm_rotate(m, angle, axis); + glm_translate(m, pivotInv); /* pivotInv = -pivot */ + +.. _TransformsOrder: + +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? + +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?** + +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 + +.. 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): +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Functions: + +1. :c:func:`glm_translate_to` +#. :c:func:`glm_translate` +#. :c:func:`glm_translate_x` +#. :c:func:`glm_translate_y` +#. :c:func:`glm_translate_z` +#. :c:func:`glm_translate_make` +#. :c:func:`glm_scale_to` +#. :c:func:`glm_scale_make` +#. :c:func:`glm_scale` +#. :c:func:`glm_scale_uni` +#. :c:func:`glm_rotate_x` +#. :c:func:`glm_rotate_y` +#. :c:func:`glm_rotate_z` +#. :c:func:`glm_rotate_make` +#. :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` +#. :c:func:`glm_decompose` + +Functions documentation +~~~~~~~~~~~~~~~~~~~~~~~ + +.. c:function:: void glm_translate_to(mat4 m, vec3 v, mat4 dest) + + translate existing transform matrix by *v* vector and store result in dest + + Parameters: + | *[in]* **m** affine transfrom + | *[in]* **v** translate vector [x, y, z] + | *[out]* **dest** translated matrix + +.. c:function:: void glm_translate(mat4 m, vec3 v) + + translate existing transform matrix by *v* vector + and stores result in same matrix + + Parameters: + | *[in, out]* **m** affine transfrom + | *[in]* **v** translate vector [x, y, z] + +.. c:function:: void glm_translate_x(mat4 m, float x) + + translate existing transform matrix by x factor + + Parameters: + | *[in, out]* **m** affine transfrom + | *[in]* **v** x factor + +.. c:function:: void glm_translate_y(mat4 m, float y) + + translate existing transform matrix by *y* factor + + Parameters: + | *[in, out]* **m** affine transfrom + | *[in]* **v** y factor + +.. c:function:: void glm_translate_z(mat4 m, float z) + + translate existing transform matrix by *z* factor + + Parameters: + | *[in, out]* **m** affine transfrom + | *[in]* **v** z factor + +.. c:function:: void glm_translate_make(mat4 m, vec3 v) + + creates NEW translate transform matrix by *v* vector. + + Parameters: + | *[in, out]* **m** affine transfrom + | *[in]* **v** translate vector [x, y, z] + +.. c:function:: void glm_scale_to(mat4 m, vec3 v, mat4 dest) + + scale existing transform matrix by *v* vector and store result in dest + + Parameters: + | *[in]* **m** affine transfrom + | *[in]* **v** scale vector [x, y, z] + | *[out]* **dest** scaled matrix + +.. c:function:: void glm_scale_make(mat4 m, vec3 v) + + creates NEW scale matrix by v vector + + Parameters: + | *[out]* **m** affine transfrom + | *[in]* **v** scale vector [x, y, z] + +.. c:function:: void glm_scale(mat4 m, vec3 v) + + scales existing transform matrix by v vector + and stores result in same matrix + + Parameters: + | *[in, out]* **m** affine transfrom + | *[in]* **v** scale vector [x, y, z] + +.. c:function:: void glm_scale_uni(mat4 m, float s) + + applies uniform scale to existing transform matrix v = [s, s, s] + and stores result in same matrix + + Parameters: + | *[in, out]* **m** affine transfrom + | *[in]* **v** scale factor + +.. c:function:: void glm_rotate_x(mat4 m, float angle, mat4 dest) + + rotate existing transform matrix around X axis by angle + and store result in dest + + Parameters: + | *[in]* **m** affine transfrom + | *[in]* **angle** angle (radians) + | *[out]* **dest** rotated matrix + +.. c:function:: void glm_rotate_y(mat4 m, float angle, mat4 dest) + + rotate existing transform matrix around Y axis by angle + and store result in dest + + Parameters: + | *[in]* **m** affine transfrom + | *[in]* **angle** angle (radians) + | *[out]* **dest** rotated matrix + +.. c:function:: void glm_rotate_z(mat4 m, float angle, mat4 dest) + + rotate existing transform matrix around Z axis by angle + and store result in dest + + Parameters: + | *[in]* **m** affine transfrom + | *[in]* **angle** angle (radians) + | *[out]* **dest** rotated matrix + +.. c:function:: void glm_rotate_make(mat4 m, float angle, vec3 axis) + + creates NEW rotation matrix by angle and axis, + axis will be normalized so you don't need to normalize it + + Parameters: + | *[out]* **m** affine transfrom + | *[in]* **axis** angle (radians) + | *[in]* **axis** axis + +.. c:function:: void glm_rotate(mat4 m, float angle, vec3 axis) + + rotate existing transform matrix around Z axis by angle and axis + + Parameters: + | *[in, out]* **m** affine transfrom + | *[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 + + Parameters: + | *[in]* **m** affine transform + | *[out]* **s** scale vector (Sx, Sy, Sz) + +.. c:function:: bool glm_uniscaled(mat4 m) + + returns true if matrix is uniform scaled. + This is helpful for creating normal matrix. + + Parameters: + | *[in]* **m** matrix + +.. c:function:: void glm_decompose_rs(mat4 m, mat4 r, vec3 s) + + decompose rotation matrix (mat4) and scale vector [Sx, Sy, Sz] + DON'T pass projected matrix here + + Parameters: + | *[in]* **m** affine transform + | *[out]* **r** rotation matrix + | *[out]* **s** scale matrix + +.. c:function:: void glm_decompose(mat4 m, vec4 t, mat4 r, vec3 s) + + decompose affine transform, TODO: extract shear factors. + DON'T pass projected matrix here + + Parameters: + | *[in]* **m** affine transfrom + | *[out]* **t** translation vector + | *[out]* **r** rotation matrix (mat4) + | *[out]* **s** scaling vector [X, Y, Z] |