Skip to content

Commit 016c0a7

Browse files
authored
Merge pull request #46 from recp/affine
affine transform update
2 parents a279217 + e28cf1d commit 016c0a7

File tree

16 files changed

+537
-166
lines changed

16 files changed

+537
-166
lines changed

docs/source/affine-mat.rst

+22
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Table of contents (click func go):
3333
Functions:
3434

3535
1. :c:func:`glm_mul`
36+
#. :c:func:`glm_mul_rot`
3637
#. :c:func:`glm_inv_tr`
3738

3839
Functions documentation
@@ -59,6 +60,27 @@ Functions documentation
5960
| *[in]* **m2** affine matrix 2
6061
| *[out]* **dest** result matrix
6162
63+
.. c:function:: void glm_mul_rot(mat4 m1, mat4 m2, mat4 dest)
64+
65+
| this is similar to glm_mat4_mul but specialized to rotation matrix
66+
67+
Right Matrix format should be (left is free):
68+
69+
.. code-block:: text
70+
71+
R R R 0
72+
R R R 0
73+
R R R 0
74+
0 0 0 1
75+
76+
this reduces some multiplications. It should be faster than mat4_mul.
77+
if you are not sure about matrix format then DON'T use this! use mat4_mul
78+
79+
Parameters:
80+
| *[in]* **m1** affine matrix 1
81+
| *[in]* **m2** affine matrix 2
82+
| *[out]* **dest** result matrix
83+
6284
.. c:function:: void glm_inv_tr(mat4 mat)
6385
6486
| inverse orthonormal rotation + translation matrix (ridig-body)

docs/source/affine.rst

+125-24
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ affine transforms
55

66
Header: cglm/affine.h
77

8+
Initialize Transform Matrices
9+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
810
Functions with **_make** prefix expect you don't have a matrix and they create
911
a matrix for you. You don't need to pass identity matrix.
1012

@@ -15,6 +17,107 @@ before sending to transfrom functions.
1517
There are also functions to decompose transform matrix. These functions can't
1618
decompose matrix after projected.
1719

20+
Rotation Center
21+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22+
23+
Rotating functions uses origin as rotation center (pivot/anchor point),
24+
since scale factors are stored in rotation matrix, same may also true for scalling.
25+
cglm provides some functions for rotating around at given point e.g.
26+
**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)").
27+
28+
Rotate or Scale around specific Point (Anchor Point)
29+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
30+
31+
If you want to rotate model around arbibtrary point follow these steps:
32+
33+
1. Move model from pivot point to origin: **translate(-pivot.x, -pivot.y, -pivot.z)**
34+
2. Apply rotation (or scaling maybe)
35+
3. Move model back from origin to pivot (reverse of step-1): **translate(pivot.x, pivot.y, pivot.z)**
36+
37+
**glm_rotate_at**, **glm_quat_rotate_at** and their helper functions works that way.
38+
39+
The implementation would be:
40+
41+
.. code-block:: c
42+
:linenos:
43+
44+
glm_translate(m, pivot);
45+
glm_rotate(m, angle, axis);
46+
glm_translate(m, pivotInv); /* pivotInv = -pivot */
47+
48+
Transforms Order
49+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
50+
51+
It is important to understand this part especially if you call transform
52+
functions multiple times
53+
54+
`glm_translate`, `glm_rotate`, `glm_scale` and `glm_quat_rotate` and their
55+
helpers functions works like this (cglm may provide reverse order too as alternative in the future):
56+
57+
.. code-block:: c
58+
:linenos:
59+
60+
TransformMatrix = TransformMatrix * TraslateMatrix; // glm_translate()
61+
TransformMatrix = TransformMatrix * RotateMatrix; // glm_rotate(), glm_quat_rotate()
62+
TransformMatrix = TransformMatrix * ScaleMatrix; // glm_scale()
63+
64+
As you can see it is multipled as right matrix. For instance what will happen if you call `glm_translate` twice?
65+
66+
.. code-block:: c
67+
:linenos:
68+
69+
glm_translate(transform, translate1); /* transform = transform * translate1 */
70+
glm_translate(transform, translate2); /* transform = transform * translate2 */
71+
glm_rotate(transform, angle, axis) /* transform = transform * rotation */
72+
73+
Now lets try to understand this:
74+
75+
1. You call translate using `translate1` and you expect it will be first transform
76+
because you call it first, do you?
77+
78+
Result will be **`transform = transform * translate1`**
79+
80+
2. Then you call translate using `translate2` and you expect it will be second transform?
81+
82+
Result will be **`transform = transform * translate2`**. Now lets expand transform,
83+
it was `transform * translate1` before second call.
84+
85+
Now it is **`transform = transform * translate1 * translate2`**, now do you understand what I say?
86+
87+
3. After last call transform will be:
88+
89+
**`transform = transform * translate1 * translate2 * rotation`**
90+
91+
The order will be; **rotation will be applied first**, then **translate2** then **translate1**
92+
93+
It is all about matrix multiplication order. It is similar to MVP matrix:
94+
`MVP = Projection * View * Model`, model will be applied first, then view then projection.
95+
96+
**Confused?**
97+
98+
In the end the last function call applied first in shaders.
99+
100+
As alternative way, you can create transform matrices individually then combine manually,
101+
but don't forget that `glm_translate`, `glm_rotate`, `glm_scale`... are optimized and should be faster (an smaller assembly output) than manual multiplication
102+
103+
.. code-block:: c
104+
:linenos:
105+
106+
mat4 transform1, transform2, transform3, finalTransform;
107+
108+
glm_translate_make(transform1, translate1);
109+
glm_translate_make(transform2, translate2);
110+
glm_rotate_make(transform3, angle, axis);
111+
112+
/* first apply transform1, then transform2, thentransform3 */
113+
glm_mat4_mulN((mat4 *[]){&transform3, &transform2, &transform1}, 3, finalTransform);
114+
115+
/* if you don't want to use mulN, same as above */
116+
glm_mat4_mul(transform3, transform2, finalTransform);
117+
glm_mat4_mul(finalTransform, transform1, finalTransform);
118+
119+
Now transform1 will be applied first, then transform2 then transform3
120+
18121
Table of contents (click to go):
19122
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20123

@@ -29,15 +132,14 @@ Functions:
29132
#. :c:func:`glm_scale_to`
30133
#. :c:func:`glm_scale_make`
31134
#. :c:func:`glm_scale`
32-
#. :c:func:`glm_scale1`
33135
#. :c:func:`glm_scale_uni`
34136
#. :c:func:`glm_rotate_x`
35137
#. :c:func:`glm_rotate_y`
36138
#. :c:func:`glm_rotate_z`
37-
#. :c:func:`glm_rotate_ndc_make`
38139
#. :c:func:`glm_rotate_make`
39-
#. :c:func:`glm_rotate_ndc`
40140
#. :c:func:`glm_rotate`
141+
#. :c:func:`glm_rotate_at`
142+
#. :c:func:`glm_rotate_atm`
41143
#. :c:func:`glm_decompose_scalev`
42144
#. :c:func:`glm_uniscaled`
43145
#. :c:func:`glm_decompose_rs`
@@ -122,10 +224,6 @@ Functions documentation
122224
| *[in, out]* **m** affine transfrom
123225
| *[in]* **v** scale vector [x, y, z]
124226
125-
.. c:function:: void glm_scale1(mat4 m, float s)
126-
127-
DEPRECATED! Use glm_scale_uni
128-
129227
.. c:function:: void glm_scale_uni(mat4 m, float s)
130228
131229
applies uniform scale to existing transform matrix v = [s, s, s]
@@ -165,16 +263,6 @@ Functions documentation
165263
| *[in]* **angle** angle (radians)
166264
| *[out]* **dest** rotated matrix
167265
168-
.. c:function:: void glm_rotate_ndc_make(mat4 m, float angle, vec3 axis_ndc)
169-
170-
creates NEW rotation matrix by angle and axis
171-
this name may change in the future. axis must be is normalized
172-
173-
Parameters:
174-
| *[out]* **m** affine transfrom
175-
| *[in]* **angle** angle (radians)
176-
| *[in]* **axis_ndc** normalized axis
177-
178266
.. c:function:: void glm_rotate_make(mat4 m, float angle, vec3 axis)
179267
180268
creates NEW rotation matrix by angle and axis,
@@ -185,22 +273,35 @@ Functions documentation
185273
| *[in]* **axis** angle (radians)
186274
| *[in]* **axis** axis
187275
188-
.. c:function:: void glm_rotate_ndc(mat4 m, float angle, vec3 axis_ndc)
276+
.. c:function:: void glm_rotate(mat4 m, float angle, vec3 axis)
189277
190278
rotate existing transform matrix around Z axis by angle and axis
191-
this name may change in the future, axis must be normalized.
192279
193280
Parameters:
194-
| *[out]* **m** affine transfrom
195-
| *[in]* **angle** angle (radians)
196-
| *[in]* **axis_ndc** normalized axis
281+
| *[in, out]* **m** affine transfrom
282+
| *[in]* **angle** angle (radians)
283+
| *[in]* **axis** axis
197284
198-
.. c:function:: void glm_rotate(mat4 m, float angle, vec3 axis)
285+
.. c:function:: void glm_rotate_at(mat4 m, vec3 pivot, float angle, vec3 axis)
199286
200-
rotate existing transform matrix around Z axis by angle and axis
287+
rotate existing transform around given axis by angle at given pivot point (rotation center)
288+
289+
Parameters:
290+
| *[in, out]* **m** affine transfrom
291+
| *[in]* **pivot** pivot, anchor point, rotation center
292+
| *[in]* **angle** angle (radians)
293+
| *[in]* **axis** axis
294+
295+
.. c:function:: void glm_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis)
296+
297+
| creates NEW rotation matrix by angle and axis at given point
298+
| this creates rotation matrix, it assumes you don't have a matrix
299+
300+
| this should work faster than glm_rotate_at because it reduces one glm_translate.
201301
202302
Parameters:
203303
| *[in, out]* **m** affine transfrom
304+
| *[in]* **pivot** pivot, anchor point, rotation center
204305
| *[in]* **angle** angle (radians)
205306
| *[in]* **axis** axis
206307

docs/source/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Also currently only **float** type is supported for most operations.
4040
getting_started
4141
opengl
4242
api
43+
troubleshooting
4344

4445
Indices and tables
4546
==================

docs/source/quat.rst

+24
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ Functions:
5656
#. :c:func:`glm_quat_for`
5757
#. :c:func:`glm_quat_forp`
5858
#. :c:func:`glm_quat_rotatev`
59+
#. :c:func:`glm_quat_rotate`
60+
#. :c:func:`glm_quat_rotate_at`
61+
#. :c:func:`glm_quat_rotate_atm`
5962

6063
Functions documentation
6164
~~~~~~~~~~~~~~~~~~~~~~~
@@ -354,3 +357,24 @@ Functions documentation
354357
| *[in]* **m** existing transform matrix to rotate
355358
| *[in]* **q** quaternion
356359
| *[out]* **dest** rotated matrix/transform
360+
361+
.. c:function:: void glm_quat_rotate_at(mat4 m, versor q, vec3 pivot)
362+
363+
| rotate existing transform matrix using quaternion at pivot point
364+
365+
Parameters:
366+
| *[in, out]* **m** existing transform matrix to rotate
367+
| *[in]* **q** quaternion
368+
| *[in]* **pivot** pivot
369+
370+
.. c:function:: void glm_quat_rotate(mat4 m, versor q, mat4 dest)
371+
372+
| rotate NEW transform matrix using quaternion at pivot point
373+
| this creates rotation matrix, it assumes you don't have a matrix
374+
375+
| this should work faster than glm_quat_rotate_at because it reduces one glm_translate.
376+
377+
Parameters:
378+
| *[in, out]* **m** existing transform matrix to rotate
379+
| *[in]* **q** quaternion
380+
| *[in]* **pivot** pivot

docs/source/troubleshooting.rst

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
.. default-domain:: C
2+
3+
Troubleshooting
4+
================================================================================
5+
6+
It is possible that sometimes you may get crashes or wrong results.
7+
Follow these topics
8+
9+
Memory Allocation:
10+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11+
12+
Again, **cglm** doesn't alloc any memory on heap.
13+
cglm functions works like memcpy; it copies data from src,
14+
makes calculations then copy the result to dest.
15+
16+
You are responsible for allocation of **src** and **dest** parameters.
17+
18+
Aligment:
19+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20+
21+
**vec4** and **mat4** types requires 16 byte aligment aligment.
22+
These types are marked with align attribute to let compiler know about this
23+
requirement.
24+
25+
But since MSVC (Windows) throws the error:
26+
27+
**"formal parameter with requested alignment of 16 won't be aligned"**
28+
29+
The aligment attribute has been commented for MSVC
30+
31+
.. code-block:: c
32+
33+
#if defined(_MSC_VER)
34+
# define CGLM_ALIGN(X) /* __declspec(align(X)) */
35+
#else
36+
# define CGLM_ALIGN(X) __attribute((aligned(X)))
37+
#endif.
38+
39+
So MSVC may not know about aligment requirements when creating variables.
40+
The interesting thing is that, if I remember correctly Visual Studio 2017
41+
doesn't throw the above error. So we may uncomment that line for Visual Studio 2017,
42+
you may do it yourself.
43+
44+
**This MSVC issue is still in TODOs.**
45+
46+
Crashes, Invalid Memory Access:
47+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
48+
49+
Probably you are trying to write to invalid memory location.
50+
51+
You may used wrong function for what you want to do.
52+
53+
For instance you may called **glm_vec4_** functions for **vec3** data type.
54+
It will try to write 32 byte but since **vec3** is 24 byte it should throw
55+
memory access error or exit the app without saying anything.
56+
57+
Wrong Results:
58+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
59+
60+
Again, you may used wrong function.
61+
62+
For instance if you use **glm_normalize()** or **glm_vec_normalize()** for **vec4**,
63+
it will assume that passed param is **vec3** and will normalize it for **vec3**.
64+
Since you need to **vec4** to be normalized in your case, you will get wrong results.
65+
66+
Accessing vec4 type with vec3 functions is valid, you will not get any error, exception or crash.
67+
You only get wrong results if you don't know what you are doing!
68+
69+
So be carefull, when your IDE (Xcode, Visual Studio ...) tried to autocomplete function names, READ IT :)
70+
71+
**Also implementation may be wrong please let us know by creating an issue on Github.**
72+
73+
Other Issues?
74+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
75+
76+
**Please let us know by creating an issue on Github.**

0 commit comments

Comments
 (0)