mirror of
https://github.com/recp/cglm.git
synced 2025-12-24 20:34:58 +00:00
update docs, add clarifications for affine transforms
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
Reference in New Issue
Block a user