# 3D Affine TransformsÂ¶

Header: cglm/affine.h

Before starting, **cglm** provides two kind of transform functions; pre and post.

Pre functions (Tâ€™ = Tnew * T) are like glm_translate, glm_rotate which means it will translate the vector first and then apply the model transformation. Post functions (Tâ€™ = T * Tnew) are like glm_translated, glm_rotated which means it will apply the model transformation first and then translate the vector.

glm_translate, glm_rotate are pre functions and are similar to C++ **glm** which you are familiar with.

In new versions of **cglm** we added glm_translated, glm_rotatedâ€¦ which are post functions,
they are useful in some cases, e.g. append transform to existing transform (apply/append transform as last transfrom Tâ€™ = T * Tnew).

Post functions are named after pre functions with ed suffix, e.g. glm_translate -> glm_translated. So donâ€™t mix them up.

## 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)â€ť).

Also **cglm** provides `glm_spin()`

and `glm_spinned()`

functions to rotate around itself. No need to give pivot.
These functions are useful for rotating around center of object.

## Rotate or Scale around specific Point (Anchor Point)Â¶

If you want to rotate model around arbibtrary point follow these steps:

- Move model from pivot point to origin:
**translate(-pivot.x, -pivot.y, -pivot.z)** - Apply rotation (or scaling maybe)
- 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.
So if you use them you donâ€™t need to do these steps manually which are done by **cglm**.

The implementation would be:

1 2 3 | ```
glm_translate(m, pivot);
glm_rotate(m, angle, axis);
glm_translate(m, pivotInv); /* pivotInv = -pivot */
``` |

or just:

1 | ```
glm_rotate_at(m, pivot, angle, axis);
``` |

## 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 provides reverse order as ed suffix e.g glm_translated, glm_rotated see post transforms):

1 2 3 | ```
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?

1 2 3 | ```
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`**

- 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?

- 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

1 2 3 4 5 6 7 8 9 10 11 12 | ```
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:

`glm_translate_to()`

`glm_translate()`

`glm_translate_x()`

`glm_translate_y()`

`glm_translate_z()`

`glm_translate_make()`

`glm_scale_to()`

`glm_scale_make()`

`glm_scale()`

`glm_scale_uni()`

`glm_rotate_x()`

`glm_rotate_y()`

`glm_rotate_z()`

`glm_rotate_make()`

`glm_rotate()`

`glm_rotate_at()`

`glm_rotate_atm()`

`glm_decompose_scalev()`

`glm_uniscaled()`

`glm_decompose_rs()`

`glm_decompose()`

Post functions (**NEW**):