| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 |
- .. 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]
|