diff --git a/Makefile.am b/Makefile.am index 0a36c72..88a93c6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -159,6 +159,8 @@ cglm_structdir=$(includedir)/cglm/struct cglm_struct_HEADERS = include/cglm/struct/mat4.h \ include/cglm/struct/mat3.h \ include/cglm/struct/mat2.h \ + include/cglm/struct/affine-pre.h \ + include/cglm/struct/affine-post.h \ include/cglm/struct/affine.h \ include/cglm/struct/affine2d.h \ include/cglm/struct/vec2.h \ diff --git a/docs/source/affine-common.rst b/docs/source/affine-common.rst new file mode 100644 index 0000000..b66352c --- /dev/null +++ b/docs/source/affine-common.rst @@ -0,0 +1,129 @@ +.. default-domain:: C + +3D Affine Transforms (common) +================================================================================ + +Common transfrom functions. + +Table of contents (click to go): +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Functions: + +1. :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_make` +#. :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_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_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_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] diff --git a/docs/source/affine-post.rst b/docs/source/affine-post.rst new file mode 100644 index 0000000..b1d268d --- /dev/null +++ b/docs/source/affine-post.rst @@ -0,0 +1,129 @@ +.. default-domain:: C + +3D Affine Transforms (post) +================================================================================ + +Post transfrom functions are similar to pre transform functions except order of application is reversed. +Post transform functions are applied after the object is transformed with given (model matrix) transfrom. + +Ther are named af + +Table of contents (click to go): +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Functions: + +1. :c:func:`glm_translated_to` +#. :c:func:`glm_translated` +#. :c:func:`glm_translated_x` +#. :c:func:`glm_translated_y` +#. :c:func:`glm_translated_z` +#. :c:func:`glm_rotated_x` +#. :c:func:`glm_rotated_y` +#. :c:func:`glm_rotated_z` +#. :c:func:`glm_rotated` +#. :c:func:`glm_rotated_at` +#. :c:func:`glm_spinned` + +Functions documentation +~~~~~~~~~~~~~~~~~~~~~~~ + +.. c:function:: void glm_translated_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_translated(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_translated_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_translated_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_translated_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_rotated_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_rotated_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_rotated_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_rotated(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_rotated_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_spinned(mat4 m, float angle, vec3 axis) + + | rotate existing transform matrix around given axis by angle around self (doesn't affected by position) + + Parameters: + | *[in, out]* **m** affine transfrom + | *[in]* **angle** angle (radians) + | *[in]* **axis** axis diff --git a/docs/source/affine-pre.rst b/docs/source/affine-pre.rst new file mode 100644 index 0000000..fe10205 --- /dev/null +++ b/docs/source/affine-pre.rst @@ -0,0 +1,240 @@ +.. default-domain:: C + +3D Affine Transforms (pre) +================================================================================ + +Pre transfrom functions which are regular transfrom functions. + +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` +#. :c:func:`glm_spin` + +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] + +.. c:function:: void glm_spin(mat4 m, float angle, vec3 axis) + + | rotate existing transform matrix around given axis by angle around self (doesn't affected by position) + + Parameters: + | *[in, out]* **m** affine transfrom + | *[in]* **angle** angle (radians) + | *[in]* **axis** axis diff --git a/docs/source/affine.rst b/docs/source/affine.rst index df2dcb7..722373c 100644 --- a/docs/source/affine.rst +++ b/docs/source/affine.rst @@ -5,6 +5,18 @@ 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 @@ -25,6 +37,9 @@ since scale factors are stored in rotation matrix, same may also true for scalli 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 :c:func:`glm_spin` and :c:func:`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) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -34,7 +49,8 @@ If you want to rotate model around arbibtrary point follow these steps: 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. +**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: @@ -45,6 +61,13 @@ The implementation would be: glm_rotate(m, angle, axis); glm_translate(m, pivotInv); /* pivotInv = -pivot */ +or just: + +.. code-block:: c + :linenos: + + glm_rotate_at(m, pivot, angle, axis); + .. _TransformsOrder: Transforms Order @@ -54,7 +77,7 @@ 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): +helpers functions works like this (cglm provides reverse order as `ed` suffix e.g `glm_translated`, `glm_rotated` see post transforms): .. code-block:: c :linenos: @@ -147,199 +170,27 @@ Functions: #. :c:func:`glm_decompose_rs` #. :c:func:`glm_decompose` +Post functions (**NEW**): + +1. :c:func:`glm_translated_to` +#. :c:func:`glm_translated` +#. :c:func:`glm_translated_x` +#. :c:func:`glm_translated_y` +#. :c:func:`glm_translated_z` +#. :c:func:`glm_rotated_x` +#. :c:func:`glm_rotated_y` +#. :c:func:`glm_rotated_z` +#. :c:func:`glm_rotated` +#. :c:func:`glm_rotated_at` +#. :c:func:`glm_spinned` + Functions documentation ~~~~~~~~~~~~~~~~~~~~~~~ -.. c:function:: void glm_translate_to(mat4 m, vec3 v, mat4 dest) +.. toctree:: + :maxdepth: 1 + :caption: Affine categories: - 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] + affine-common + affine-pre + affine-post diff --git a/docs/source/project.rst b/docs/source/project.rst index b31a86a..161a2a7 100644 --- a/docs/source/project.rst +++ b/docs/source/project.rst @@ -21,14 +21,14 @@ Functions: Functions documentation ~~~~~~~~~~~~~~~~~~~~~~~ -.. c:function:: void glm_unprojecti(vec3 pos, mat4 invMat, vec4 vp, vec3 dest) +.. c:function:: void glm_unprojecti(vec3 pos, mat4 invMat, vec4 vp, vec3 dest) | maps the specified viewport coordinates into specified space [1] the matrix should contain projection matrix. if you don't have ( and don't want to have ) an inverse matrix then use - glm_unproject version. You may use existing inverse of matrix in somewhere - else, this is why glm_unprojecti exists to save save inversion cost + :c:func:`glm_unproject` version. You may use existing inverse of matrix in somewhere + else, this is why **glm_unprojecti** exists to save inversion cost [1] space: - if m = invProj: View Space @@ -57,7 +57,7 @@ Functions documentation | maps the specified viewport coordinates into specified space [1] the matrix should contain projection matrix. - this is same as glm_unprojecti except this function get inverse matrix for + this is same as :c:func:`glm_unprojecti` except this function get inverse matrix for you. [1] space: @@ -80,7 +80,7 @@ Functions documentation | *[in]* **vp** viewport as [x, y, width, height] | *[out]* **dest** unprojected coordinates -.. c:function:: void glm_project(vec3 pos, mat4 m, vec4 vp, vec3 dest) +.. c:function:: void glm_project(vec3 pos, mat4 m, vec4 vp, vec3 dest) | map object coordinates to window coordinates @@ -91,12 +91,29 @@ Functions documentation glm_mat4_mul(proj, view, viewProj); glm_mat4_mul(viewProj, model, MVP); - this could be useful for gettng a bbox which fits with view frustum and - object bounding boxes. In this case you crop view frustum box with objects - box - Parameters: | *[in]* **pos** object coordinates | *[in]* **m** MVP matrix | *[in]* **vp** viewport as [x, y, width, height] | *[out]* **dest** projected coordinates + +.. c:function:: float glm_project_z(vec3 pos, mat4 m) + + | map object's z coordinate to window coordinates + + this is same as :c:func:`glm_project` except this function projects only Z coordinate + which reduces a few calculations and parameters. + + Computing MVP: + + .. code-block:: c + + glm_mat4_mul(proj, view, viewProj); + glm_mat4_mul(viewProj, model, MVP); + + Parameters: + | *[in]* **pos** object coordinates + | *[in]* **m** MVP matrix + + Returns: + projected z coordinate \ No newline at end of file diff --git a/include/cglm/affine-post.h b/include/cglm/affine-post.h new file mode 100644 index 0000000..7f52c5c --- /dev/null +++ b/include/cglm/affine-post.h @@ -0,0 +1,231 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_mul(mat4 m1, mat4 m2, mat4 dest); + CGLM_INLINE void glm_inv_tr(mat4 mat); + */ + +#ifndef cglm_affine_post_h +#define cglm_affine_post_h + +/* + Functions: + CGLM_INLINE void glm_translated_to(mat4 m, vec3 v, mat4 dest); + CGLM_INLINE void glm_translated(mat4 m, vec3 v); + CGLM_INLINE void glm_translated_x(mat4 m, float to); + CGLM_INLINE void glm_translated_y(mat4 m, float to); + CGLM_INLINE void glm_translated_z(mat4 m, float to); + CGLM_INLINE void glm_rotated_x(mat4 m, float angle, mat4 dest); + CGLM_INLINE void glm_rotated_y(mat4 m, float angle, mat4 dest); + CGLM_INLINE void glm_rotated_z(mat4 m, float angle, mat4 dest); + CGLM_INLINE void glm_rotated(mat4 m, float angle, vec3 axis); + CGLM_INLINE void glm_rotated_at(mat4 m, vec3 pivot, float angle, vec3 axis); + CGLM_INLINE void glm_spinned(mat4 m, float angle, vec3 axis); + */ + +#include "common.h" +#include "util.h" +#include "vec3.h" +#include "vec4.h" +#include "mat4.h" +#include "affine-mat.h" + +/*! + * @brief translate existing transform matrix by v vector + * and stores result in same matrix + * + * @param[in, out] m affine transfrom + * @param[in] v translate vector [x, y, z] + */ +CGLM_INLINE +void +glm_translated(mat4 m, vec3 v) { + glm_vec3_add(m[3], v, m[3]); +} + +/*! + * @brief translate existing transform matrix by v vector + * and store result in dest + * + * source matrix will remain same + * + * @param[in] m affine transfrom + * @param[in] v translate vector [x, y, z] + * @param[out] dest translated matrix + */ +CGLM_INLINE +void +glm_translated_to(mat4 m, vec3 v, mat4 dest) { + glm_mat4_copy(m, dest); + glm_translated(dest, v); +} + +/*! + * @brief translate existing transform matrix by x factor + * + * @param[in, out] m affine transfrom + * @param[in] x x factor + */ +CGLM_INLINE +void +glm_translated_x(mat4 m, float x) { + m[3][0] += x; +} + +/*! + * @brief translate existing transform matrix by y factor + * + * @param[in, out] m affine transfrom + * @param[in] y y factor + */ +CGLM_INLINE +void +glm_translated_y(mat4 m, float y) { + m[3][1] += y; +} + +/*! + * @brief translate existing transform matrix by z factor + * + * @param[in, out] m affine transfrom + * @param[in] z z factor + */ +CGLM_INLINE +void +glm_translated_z(mat4 m, float z) { + m[3][2] += z; +} + +/*! + * @brief rotate existing transform matrix around X axis by angle + * and store result in dest + * + * @param[in] m affine transfrom + * @param[in] angle angle (radians) + * @param[out] dest rotated matrix + */ +CGLM_INLINE +void +glm_rotated_x(mat4 m, float angle, mat4 dest) { + CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT; + float c, s; + + c = cosf(angle); + s = sinf(angle); + + t[1][1] = c; + t[1][2] = s; + t[2][1] = -s; + t[2][2] = c; + + glm_mul_rot(t, m, dest); +} + +/*! + * @brief rotate existing transform matrix around Y axis by angle + * and store result in dest + * + * @param[in] m affine transfrom + * @param[in] angle angle (radians) + * @param[out] dest rotated matrix + */ +CGLM_INLINE +void +glm_rotated_y(mat4 m, float angle, mat4 dest) { + CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT; + float c, s; + + c = cosf(angle); + s = sinf(angle); + + t[0][0] = c; + t[0][2] = -s; + t[2][0] = s; + t[2][2] = c; + + glm_mul_rot(t, m, dest); +} + +/*! + * @brief rotate existing transform matrix around Z axis by angle + * and store result in dest + * + * @param[in] m affine transfrom + * @param[in] angle angle (radians) + * @param[out] dest rotated matrix + */ +CGLM_INLINE +void +glm_rotated_z(mat4 m, float angle, mat4 dest) { + CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT; + float c, s; + + c = cosf(angle); + s = sinf(angle); + + t[0][0] = c; + t[0][1] = s; + t[1][0] = -s; + t[1][1] = c; + + glm_mul_rot(t, m, dest); +} + +/*! + * @brief rotate existing transform matrix around given axis by angle + * + * @param[in, out] m affine transfrom + * @param[in] angle angle (radians) + * @param[in] axis axis + */ +CGLM_INLINE +void +glm_rotated(mat4 m, float angle, vec3 axis) { + CGLM_ALIGN_MAT mat4 rot; + glm_rotate_make(rot, angle, axis); + glm_mul_rot(rot, m, m); +} + +/*! + * @brief rotate existing transform + * around given axis by angle at given pivot point (rotation center) + * + * @param[in, out] m affine transfrom + * @param[in] pivot rotation center + * @param[in] angle angle (radians) + * @param[in] axis axis + */ +CGLM_INLINE +void +glm_rotated_at(mat4 m, vec3 pivot, float angle, vec3 axis) { + CGLM_ALIGN(8) vec3 pivotInv; + + glm_vec3_negate_to(pivot, pivotInv); + + glm_translated(m, pivot); + glm_rotated(m, angle, axis); + glm_translated(m, pivotInv); +} + +/*! + * @brief rotate existing transform matrix around given axis by angle around self (doesn't affected by position) + * + * @param[in, out] m affine transfrom + * @param[in] angle angle (radians) + * @param[in] axis axis + */ +CGLM_INLINE +void +glm_spinned(mat4 m, float angle, vec3 axis) { + CGLM_ALIGN_MAT mat4 rot; + glm_rotate_atm(rot, m[3], angle, axis); + glm_mat4_mul(rot, m, m); +} + +#endif /* cglm_affine_post_h */ diff --git a/include/cglm/affine-pre.h b/include/cglm/affine-pre.h new file mode 100644 index 0000000..f4316a9 --- /dev/null +++ b/include/cglm/affine-pre.h @@ -0,0 +1,291 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_mul(mat4 m1, mat4 m2, mat4 dest); + CGLM_INLINE void glm_inv_tr(mat4 mat); + */ + +#ifndef cglm_affine_pre_h +#define cglm_affine_pre_h + +/* + Functions: + CGLM_INLINE void glm_translate_to(mat4 m, vec3 v, mat4 dest); + CGLM_INLINE void glm_translate(mat4 m, vec3 v); + CGLM_INLINE void glm_translate_x(mat4 m, float to); + CGLM_INLINE void glm_translate_y(mat4 m, float to); + CGLM_INLINE void glm_translate_z(mat4 m, float to); + CGLM_INLINE void glm_rotate_x(mat4 m, float angle, mat4 dest); + CGLM_INLINE void glm_rotate_y(mat4 m, float angle, mat4 dest); + CGLM_INLINE void glm_rotate_z(mat4 m, float angle, mat4 dest); + 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_spin(mat4 m, float angle, vec3 axis); + */ + +#include "common.h" +#include "util.h" +#include "vec3.h" +#include "vec4.h" +#include "mat4.h" +#include "affine-mat.h" + +/*! + * @brief translate existing transform matrix by v vector + * and stores result in same matrix + * + * @param[in, out] m affine transfrom + * @param[in] v translate vector [x, y, z] + */ +CGLM_INLINE +void +glm_translate(mat4 m, vec3 v) { +#if defined(CGLM_SIMD) + glmm_128 m0, m1, m2, m3; + + m0 = glmm_load(m[0]); + m1 = glmm_load(m[1]); + m2 = glmm_load(m[2]); + m3 = glmm_load(m[3]); + + glmm_store(m[3], + glmm_fmadd(m0, glmm_set1(v[0]), + glmm_fmadd(m1, glmm_set1(v[1]), + glmm_fmadd(m2, glmm_set1(v[2]), m3)))); +#else + glm_vec4_muladds(m[0], v[0], m[3]); + glm_vec4_muladds(m[1], v[1], m[3]); + glm_vec4_muladds(m[2], v[2], m[3]); +#endif +} + +/*! + * @brief translate existing transform matrix by v vector + * and store result in dest + * + * source matrix will remain same + * + * @param[in] m affine transfrom + * @param[in] v translate vector [x, y, z] + * @param[out] dest translated matrix + */ +CGLM_INLINE +void +glm_translate_to(mat4 m, vec3 v, mat4 dest) { + glm_mat4_copy(m, dest); + glm_translate(dest, v); +} + +/*! + * @brief translate existing transform matrix by x factor + * + * @param[in, out] m affine transfrom + * @param[in] x x factor + */ +CGLM_INLINE +void +glm_translate_x(mat4 m, float x) { +#if defined(CGLM_SIMD) + glmm_store(m[3], glmm_fmadd(glmm_load(m[0]), glmm_set1(x), glmm_load(m[3]))); +#else + vec4 v1; + glm_vec4_scale(m[0], x, v1); + glm_vec4_add(v1, m[3], m[3]); +#endif +} + +/*! + * @brief translate existing transform matrix by y factor + * + * @param[in, out] m affine transfrom + * @param[in] y y factor + */ +CGLM_INLINE +void +glm_translate_y(mat4 m, float y) { +#if defined(CGLM_SIMD) + glmm_store(m[3], glmm_fmadd(glmm_load(m[1]), glmm_set1(y), glmm_load(m[3]))); +#else + vec4 v1; + glm_vec4_scale(m[1], y, v1); + glm_vec4_add(v1, m[3], m[3]); +#endif +} + +/*! + * @brief translate existing transform matrix by z factor + * + * @param[in, out] m affine transfrom + * @param[in] z z factor + */ +CGLM_INLINE +void +glm_translate_z(mat4 m, float z) { +#if defined(CGLM_SIMD) + glmm_store(m[3], glmm_fmadd(glmm_load(m[2]), glmm_set1(z), glmm_load(m[3]))); +#else + vec4 v1; + glm_vec4_scale(m[2], z, v1); + glm_vec4_add(v1, m[3], m[3]); +#endif +} + +/*! + * @brief rotate existing transform matrix around X axis by angle + * and store result in dest + * + * @param[in] m affine transfrom + * @param[in] angle angle (radians) + * @param[out] dest rotated matrix + */ +CGLM_INLINE +void +glm_rotate_x(mat4 m, float angle, mat4 dest) { + CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT; + float c, s; + + c = cosf(angle); + s = sinf(angle); + + t[1][1] = c; + t[1][2] = s; + t[2][1] = -s; + t[2][2] = c; + + glm_mul_rot(m, t, dest); +} + +/*! + * @brief rotate existing transform matrix around Y axis by angle + * and store result in dest + * + * @param[in] m affine transfrom + * @param[in] angle angle (radians) + * @param[out] dest rotated matrix + */ +CGLM_INLINE +void +glm_rotate_y(mat4 m, float angle, mat4 dest) { + CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT; + float c, s; + + c = cosf(angle); + s = sinf(angle); + + t[0][0] = c; + t[0][2] = -s; + t[2][0] = s; + t[2][2] = c; + + glm_mul_rot(m, t, dest); +} + +/*! + * @brief rotate existing transform matrix around Z axis by angle + * and store result in dest + * + * @param[in] m affine transfrom + * @param[in] angle angle (radians) + * @param[out] dest rotated matrix + */ +CGLM_INLINE +void +glm_rotate_z(mat4 m, float angle, mat4 dest) { + CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT; + float c, s; + + c = cosf(angle); + s = sinf(angle); + + t[0][0] = c; + t[0][1] = s; + t[1][0] = -s; + t[1][1] = c; + + glm_mul_rot(m, t, dest); +} + +/*! + * @brief rotate existing transform matrix around given axis by angle + * + * @param[in, out] m affine transfrom + * @param[in] angle angle (radians) + * @param[in] axis axis + */ +CGLM_INLINE +void +glm_rotate(mat4 m, float angle, vec3 axis) { + CGLM_ALIGN_MAT mat4 rot; + glm_rotate_make(rot, angle, axis); + glm_mul_rot(m, rot, m); +} + +/*! + * @brief rotate existing transform + * around given axis by angle at given pivot point (rotation center) + * + * @param[in, out] m affine transfrom + * @param[in] pivot rotation center + * @param[in] angle angle (radians) + * @param[in] axis axis + */ +CGLM_INLINE +void +glm_rotate_at(mat4 m, vec3 pivot, float angle, vec3 axis) { + CGLM_ALIGN(8) vec3 pivotInv; + + glm_vec3_negate_to(pivot, pivotInv); + + glm_translate(m, pivot); + glm_rotate(m, angle, axis); + glm_translate(m, pivotInv); +} + +/*! + * @brief 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. + * + * @param[out] m affine transfrom + * @param[in] pivot rotation center + * @param[in] angle angle (radians) + * @param[in] axis axis + */ +CGLM_INLINE +void +glm_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis) { + CGLM_ALIGN(8) vec3 pivotInv; + + glm_vec3_negate_to(pivot, pivotInv); + + glm_translate_make(m, pivot); + glm_rotate(m, angle, axis); + glm_translate(m, pivotInv); +} + +/*! + * @brief rotate existing transform matrix around given axis by angle around self (doesn't affected by position) + * + * @param[in, out] m affine transfrom + * @param[in] angle angle (radians) + * @param[in] axis axis + */ +CGLM_INLINE +void +glm_spin(mat4 m, float angle, vec3 axis) { + CGLM_ALIGN_MAT mat4 rot; + glm_rotate_atm(rot, m[3], angle, axis); + glm_mat4_mul(m, rot, m); +} + +#endif /* cglm_affine_pre_h */ diff --git a/include/cglm/affine.h b/include/cglm/affine.h index d0e5bc9..78d7dbf 100644 --- a/include/cglm/affine.h +++ b/include/cglm/affine.h @@ -24,6 +24,7 @@ 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_spin(mat4 m, 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); @@ -40,106 +41,6 @@ #include "mat4.h" #include "affine-mat.h" -/*! - * @brief translate existing transform matrix by v vector - * and stores result in same matrix - * - * @param[in, out] m affine transfrom - * @param[in] v translate vector [x, y, z] - */ -CGLM_INLINE -void -glm_translate(mat4 m, vec3 v) { -#if defined(CGLM_SIMD) - glmm_128 m0, m1, m2, m3; - - m0 = glmm_load(m[0]); - m1 = glmm_load(m[1]); - m2 = glmm_load(m[2]); - m3 = glmm_load(m[3]); - - glmm_store(m[3], - glmm_fmadd(m0, glmm_set1(v[0]), - glmm_fmadd(m1, glmm_set1(v[1]), - glmm_fmadd(m2, glmm_set1(v[2]), m3)))); -#else - glm_vec4_muladds(m[0], v[0], m[3]); - glm_vec4_muladds(m[1], v[1], m[3]); - glm_vec4_muladds(m[2], v[2], m[3]); -#endif -} - -/*! - * @brief translate existing transform matrix by v vector - * and store result in dest - * - * source matrix will remain same - * - * @param[in] m affine transfrom - * @param[in] v translate vector [x, y, z] - * @param[out] dest translated matrix - */ -CGLM_INLINE -void -glm_translate_to(mat4 m, vec3 v, mat4 dest) { - glm_mat4_copy(m, dest); - glm_translate(dest, v); -} - -/*! - * @brief translate existing transform matrix by x factor - * - * @param[in, out] m affine transfrom - * @param[in] x x factor - */ -CGLM_INLINE -void -glm_translate_x(mat4 m, float x) { -#if defined(CGLM_SIMD) - glmm_store(m[3], glmm_fmadd(glmm_load(m[0]), glmm_set1(x), glmm_load(m[3]))); -#else - vec4 v1; - glm_vec4_scale(m[0], x, v1); - glm_vec4_add(v1, m[3], m[3]); -#endif -} - -/*! - * @brief translate existing transform matrix by y factor - * - * @param[in, out] m affine transfrom - * @param[in] y y factor - */ -CGLM_INLINE -void -glm_translate_y(mat4 m, float y) { -#if defined(CGLM_SIMD) - glmm_store(m[3], glmm_fmadd(glmm_load(m[1]), glmm_set1(y), glmm_load(m[3]))); -#else - vec4 v1; - glm_vec4_scale(m[1], y, v1); - glm_vec4_add(v1, m[3], m[3]); -#endif -} - -/*! - * @brief translate existing transform matrix by z factor - * - * @param[in, out] m affine transfrom - * @param[in] z z factor - */ -CGLM_INLINE -void -glm_translate_z(mat4 m, float z) { -#if defined(CGLM_SIMD) - glmm_store(m[3], glmm_fmadd(glmm_load(m[2]), glmm_set1(z), glmm_load(m[3]))); -#else - vec4 v1; - glm_vec4_scale(m[2], z, v1); - glm_vec4_add(v1, m[3], m[3]); -#endif -} - /*! * @brief creates NEW translate transform matrix by v vector * @@ -213,81 +114,6 @@ glm_scale_uni(mat4 m, float s) { glm_scale_to(m, v, m); } -/*! - * @brief rotate existing transform matrix around X axis by angle - * and store result in dest - * - * @param[in] m affine transfrom - * @param[in] angle angle (radians) - * @param[out] dest rotated matrix - */ -CGLM_INLINE -void -glm_rotate_x(mat4 m, float angle, mat4 dest) { - CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT; - float c, s; - - c = cosf(angle); - s = sinf(angle); - - t[1][1] = c; - t[1][2] = s; - t[2][1] = -s; - t[2][2] = c; - - glm_mul_rot(m, t, dest); -} - -/*! - * @brief rotate existing transform matrix around Y axis by angle - * and store result in dest - * - * @param[in] m affine transfrom - * @param[in] angle angle (radians) - * @param[out] dest rotated matrix - */ -CGLM_INLINE -void -glm_rotate_y(mat4 m, float angle, mat4 dest) { - CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT; - float c, s; - - c = cosf(angle); - s = sinf(angle); - - t[0][0] = c; - t[0][2] = -s; - t[2][0] = s; - t[2][2] = c; - - glm_mul_rot(m, t, dest); -} - -/*! - * @brief rotate existing transform matrix around Z axis by angle - * and store result in dest - * - * @param[in] m affine transfrom - * @param[in] angle angle (radians) - * @param[out] dest rotated matrix - */ -CGLM_INLINE -void -glm_rotate_z(mat4 m, float angle, mat4 dest) { - CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT; - float c, s; - - c = cosf(angle); - s = sinf(angle); - - t[0][0] = c; - t[0][1] = s; - t[1][0] = -s; - t[1][1] = c; - - glm_mul_rot(m, t, dest); -} - /*! * @brief creates NEW rotation matrix by angle and axis * @@ -321,67 +147,6 @@ glm_rotate_make(mat4 m, float angle, vec3 axis) { m[3][3] = 1.0f; } -/*! - * @brief rotate existing transform matrix around given axis by angle - * - * @param[in, out] m affine transfrom - * @param[in] angle angle (radians) - * @param[in] axis axis - */ -CGLM_INLINE -void -glm_rotate(mat4 m, float angle, vec3 axis) { - CGLM_ALIGN_MAT mat4 rot; - glm_rotate_make(rot, angle, axis); - glm_mul_rot(m, rot, m); -} - -/*! - * @brief rotate existing transform - * around given axis by angle at given pivot point (rotation center) - * - * @param[in, out] m affine transfrom - * @param[in] pivot rotation center - * @param[in] angle angle (radians) - * @param[in] axis axis - */ -CGLM_INLINE -void -glm_rotate_at(mat4 m, vec3 pivot, float angle, vec3 axis) { - CGLM_ALIGN(8) vec3 pivotInv; - - glm_vec3_negate_to(pivot, pivotInv); - - glm_translate(m, pivot); - glm_rotate(m, angle, axis); - glm_translate(m, pivotInv); -} - -/*! - * @brief 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. - * - * @param[out] m affine transfrom - * @param[in] pivot rotation center - * @param[in] angle angle (radians) - * @param[in] axis axis - */ -CGLM_INLINE -void -glm_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis) { - CGLM_ALIGN(8) vec3 pivotInv; - - glm_vec3_negate_to(pivot, pivotInv); - - glm_translate_make(m, pivot); - glm_rotate(m, angle, axis); - glm_translate(m, pivotInv); -} - /*! * @brief decompose scale vector * @@ -467,4 +232,7 @@ glm_decompose(mat4 m, vec4 t, mat4 r, vec3 s) { glm_decompose_rs(m, r, s); } +#include "affine-pre.h" +#include "affine-post.h" + #endif /* cglm_affine_h */ diff --git a/include/cglm/call/affine.h b/include/cglm/call/affine.h index c11405b..52b8501 100644 --- a/include/cglm/call/affine.h +++ b/include/cglm/call/affine.h @@ -81,6 +81,10 @@ CGLM_EXPORT void glmc_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis); +CGLM_EXPORT +void +glmc_spin(mat4 m, float angle, vec3 axis); + CGLM_EXPORT void glmc_decompose_scalev(mat4 m, vec3 s); @@ -97,6 +101,52 @@ CGLM_EXPORT void glmc_decompose(mat4 m, vec4 t, mat4 r, vec3 s); +/* affine-post */ + +CGLM_EXPORT +void +glmc_translated(mat4 m, vec3 v); + +CGLM_EXPORT +void +glmc_translated_to(mat4 m, vec3 v, mat4 dest); + +CGLM_EXPORT +void +glmc_translated_x(mat4 m, float x); + +CGLM_EXPORT +void +glmc_translated_y(mat4 m, float y); + +CGLM_EXPORT +void +glmc_translated_z(mat4 m, float z); + +CGLM_EXPORT +void +glmc_rotated_x(mat4 m, float angle, mat4 dest); + +CGLM_EXPORT +void +glmc_rotated_y(mat4 m, float angle, mat4 dest); + +CGLM_EXPORT +void +glmc_rotated_z(mat4 m, float angle, mat4 dest); + +CGLM_EXPORT +void +glmc_rotated(mat4 m, float angle, vec3 axis); + +CGLM_EXPORT +void +glmc_rotated_at(mat4 m, vec3 pivot, float angle, vec3 axis); + +CGLM_EXPORT +void +glmc_spinned(mat4 m, float angle, vec3 axis); + /* affine-mat */ CGLM_EXPORT diff --git a/include/cglm/call/clipspace/project_no.h b/include/cglm/call/clipspace/project_no.h index c62c37b..3cba860 100644 --- a/include/cglm/call/clipspace/project_no.h +++ b/include/cglm/call/clipspace/project_no.h @@ -21,6 +21,10 @@ CGLM_EXPORT void glmc_project_no(vec3 pos, mat4 m, vec4 vp, vec3 dest); +CGLM_EXPORT +float +glmc_project_z_no(vec3 pos, mat4 m); + #ifdef __cplusplus } #endif diff --git a/include/cglm/call/clipspace/project_zo.h b/include/cglm/call/clipspace/project_zo.h index a7137bd..d2a6c62 100644 --- a/include/cglm/call/clipspace/project_zo.h +++ b/include/cglm/call/clipspace/project_zo.h @@ -21,6 +21,10 @@ CGLM_EXPORT void glmc_project_zo(vec3 pos, mat4 m, vec4 vp, vec3 dest); +CGLM_EXPORT +float +glmc_project_z_zo(vec3 pos, mat4 m); + #ifdef __cplusplus } #endif diff --git a/include/cglm/call/project.h b/include/cglm/call/project.h index 991ba1d..fcfcf2b 100644 --- a/include/cglm/call/project.h +++ b/include/cglm/call/project.h @@ -25,6 +25,10 @@ CGLM_EXPORT void glmc_project(vec3 pos, mat4 m, vec4 vp, vec3 dest); +CGLM_EXPORT +float +glmc_project_z(vec3 pos, mat4 m); + CGLM_EXPORT void glmc_pickmatrix(vec2 center, vec2 size, vec4 vp, mat4 dest); diff --git a/include/cglm/clipspace/project_no.h b/include/cglm/clipspace/project_no.h index 7e74323..71fbc52 100644 --- a/include/cglm/clipspace/project_no.h +++ b/include/cglm/clipspace/project_no.h @@ -83,4 +83,27 @@ glm_project_no(vec3 pos, mat4 m, vec4 vp, vec3 dest) { dest[2] = pos4[2]; } +/*! + * @brief map object's z coordinate to window coordinates + * + * Computing MVP: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * + * @param[in] v object coordinates + * @param[in] m MVP matrix + * + * @returns projected z coordinate + */ +CGLM_INLINE +float +glm_project_z_no(vec3 v, mat4 m) { + float z, w; + + z = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2]; + w = m[0][3] * v[0] + m[1][3] * v[1] + m[2][3] * v[2] + m[3][3]; + + return 0.5f * (z / w) + 0.5f; +} + #endif /* cglm_project_no_h */ diff --git a/include/cglm/clipspace/project_zo.h b/include/cglm/clipspace/project_zo.h index 98e58af..dc32078 100644 --- a/include/cglm/clipspace/project_zo.h +++ b/include/cglm/clipspace/project_zo.h @@ -85,4 +85,27 @@ glm_project_zo(vec3 pos, mat4 m, vec4 vp, vec3 dest) { dest[1] = pos4[1] * vp[3] + vp[1]; } +/*! + * @brief map object's z coordinate to window coordinates + * + * Computing MVP: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * + * @param[in] v object coordinates + * @param[in] m MVP matrix + * + * @returns projected z coordinate + */ +CGLM_INLINE +float +glm_project_z_zo(vec3 v, mat4 m) { + float z, w; + + z = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2]; + w = m[0][3] * v[0] + m[1][3] * v[1] + m[2][3] * v[2] + m[3][3]; + + return z / w; +} + #endif /* cglm_project_zo_h */ diff --git a/include/cglm/project.h b/include/cglm/project.h index f52d3a0..1d0a4e5 100644 --- a/include/cglm/project.h +++ b/include/cglm/project.h @@ -114,6 +114,28 @@ glm_project(vec3 pos, mat4 m, vec4 vp, vec3 dest) { #endif } +/*! + * @brief map object's z coordinate to window coordinates + * + * Computing MVP: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * + * @param[in] v object coordinates + * @param[in] m MVP matrix + * + * @returns projected z coordinate + */ +CGLM_INLINE +float +glm_project_z(vec3 v, mat4 m) { +#if CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_ZO_BIT + return glm_project_z_zo(v, m); +#elif CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_NO_BIT + return glm_project_z_no(v, m); +#endif +} + /*! * @brief define a picking region * diff --git a/include/cglm/struct/affine.h b/include/cglm/struct/affine.h index cd23226..4176200 100644 --- a/include/cglm/struct/affine.h +++ b/include/cglm/struct/affine.h @@ -23,6 +23,7 @@ CGLM_INLINE mat4s glms_rotate(mat4s m, float angle, vec3s axis); CGLM_INLINE mat4s glms_rotate_at(mat4s m, vec3s pivot, float angle, vec3s axis); CGLM_INLINE mat4s glms_rotate_atm(mat4s m, vec3s pivot, float angle, vec3s axis); + CGLM_INLINE mat4s glms_spin(mat4s m, float angle, vec3s axis); CGLM_INLINE vec3s glms_decompose_scalev(mat4s m); CGLM_INLINE bool glms_uniscaled(mat4s m); CGLM_INLINE void glms_decompose_rs(mat4s m, mat4s * r, vec3s * s); @@ -226,7 +227,7 @@ glms_rotate_make(float angle, vec3s axis) { * @param[in] m affine transfrom * @param[in] angle angle (radians) * @param[in] axis axis - * @returns affine transfrom + * @returns affine transfrom */ CGLM_INLINE mat4s @@ -273,6 +274,21 @@ glms_rotate_atm(mat4s m, vec3s pivot, float angle, vec3s axis) { return m; } +/*! + * @brief rotate existing transform matrix around given axis by angle around self (doesn't affected by position) + * + * @param[in] m affine transfrom + * @param[in] angle angle (radians) + * @param[in] axis axis + * @returns affine transfrom + */ +CGLM_INLINE +mat4s +glms_spin(mat4s m, float angle, vec3s axis) { + glm_spin(m.raw, angle, axis.raw); + return m; +} + /*! * @brief decompose scale vector * diff --git a/include/cglm/struct/clipspace/project_no.h b/include/cglm/struct/clipspace/project_no.h index 4855a5e..a12fb61 100644 --- a/include/cglm/struct/clipspace/project_no.h +++ b/include/cglm/struct/clipspace/project_no.h @@ -43,6 +43,7 @@ * @param[in] pos point/position in viewport coordinates * @param[in] invMat matrix (see brief) * @param[in] vp viewport as [x, y, width, height] + * * @returns unprojected coordinates */ CGLM_INLINE @@ -63,6 +64,7 @@ glms_unprojecti_no(vec3s pos, mat4s invMat, vec4s vp, vec3 dest) { * @param[in] pos object coordinates * @param[in] m MVP matrix * @param[in] vp viewport as [x, y, width, height] + * * @returns projected coordinates */ CGLM_INLINE @@ -73,4 +75,22 @@ glms_project_no(vec3s pos, mat4s m, vec4s vp, vec3s dest) { return dest; } +/*! + * @brief map object's z coordinate to window coordinates + * + * Computing MVP: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * + * @param[in] v object coordinates + * @param[in] m MVP matrix + * + * @returns projected z coordinate + */ +CGLM_INLINE +vec3s +glms_project_z_no(vec3s v, mat4s m) { + return glm_project_z_no(v.raw, m.raw); +} + #endif /* cglms_project_rh_no_h */ diff --git a/include/cglm/struct/clipspace/project_zo.h b/include/cglm/struct/clipspace/project_zo.h index 93117e9..c510396 100644 --- a/include/cglm/struct/clipspace/project_zo.h +++ b/include/cglm/struct/clipspace/project_zo.h @@ -43,6 +43,7 @@ * @param[in] pos point/position in viewport coordinates * @param[in] invMat matrix (see brief) * @param[in] vp viewport as [x, y, width, height] + * * @returns unprojected coordinates */ CGLM_INLINE @@ -63,6 +64,7 @@ glms_unprojecti_zo(vec3s pos, mat4s invMat, vec4s vp, vec3 dest) { * @param[in] pos object coordinates * @param[in] m MVP matrix * @param[in] vp viewport as [x, y, width, height] + * * @returns projected coordinates */ CGLM_INLINE @@ -73,4 +75,22 @@ glms_project_zo(vec3s pos, mat4s m, vec4s vp, vec3 dest) { return dest; } +/*! + * @brief map object's z coordinate to window coordinates + * + * Computing MVP: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * + * @param[in] v object coordinates + * @param[in] m MVP matrix + * + * @returns projected z coordinate + */ +CGLM_INLINE +vec3s +glms_project_z_zo(vec3s v, mat4s m) { + return glm_project_z_zo(v.raw, m.raw); +} + #endif /* cglm_project_zo_h */ diff --git a/src/affine.c b/src/affine.c index a818bd1..6bba523 100644 --- a/src/affine.c +++ b/src/affine.c @@ -110,6 +110,12 @@ glmc_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis) { glm_rotate_atm(m, pivot, angle, axis); } +CGLM_EXPORT +void +glmc_spin(mat4 m, float angle, vec3 axis) { + glm_spin(m, angle, axis); +} + CGLM_EXPORT void glmc_decompose_scalev(mat4 m, vec3 s) { @@ -128,6 +134,72 @@ glmc_decompose_rs(mat4 m, mat4 r, vec3 s) { glm_decompose_rs(m, r, s); } +CGLM_EXPORT +void +glmc_translated(mat4 m, vec3 v) { + glm_translated(m, v); +} + +CGLM_EXPORT +void +glmc_translated_to(mat4 m, vec3 v, mat4 dest) { + glm_translated_to(m, v, dest); +} + +CGLM_EXPORT +void +glmc_translated_x(mat4 m, float x) { + glm_translated_x(m, x); +} + +CGLM_EXPORT +void +glmc_translated_y(mat4 m, float y) { + glm_translated_y(m, y); +} + +CGLM_EXPORT +void +glmc_translated_z(mat4 m, float z) { + glm_translated_z(m, z); +} + +CGLM_EXPORT +void +glmc_rotated_x(mat4 m, float angle, mat4 dest) { + glm_rotated_x(m, angle, dest); +} + +CGLM_EXPORT +void +glmc_rotated_y(mat4 m, float angle, mat4 dest) { + glm_rotated_y(m, angle, dest); +} + +CGLM_EXPORT +void +glmc_rotated_z(mat4 m, float angle, mat4 dest) { + glm_rotated_z(m, angle, dest); +} + +CGLM_EXPORT +void +glmc_rotated(mat4 m, float angle, vec3 axis) { + glm_rotated(m, angle, axis); +} + +CGLM_EXPORT +void +glmc_rotated_at(mat4 m, vec3 pivot, float angle, vec3 axis) { + glm_rotated_at(m, pivot, angle, axis); +} + +CGLM_EXPORT +void +glmc_spinned(mat4 m, float angle, vec3 axis) { + glm_spinned(m, angle, axis); +} + CGLM_EXPORT void glmc_decompose(mat4 m, vec4 t, mat4 r, vec3 s) { diff --git a/src/clipspace/project_no.c b/src/clipspace/project_no.c index 8352cba..93b1453 100644 --- a/src/clipspace/project_no.c +++ b/src/clipspace/project_no.c @@ -19,3 +19,9 @@ void glmc_project_no(vec3 pos, mat4 m, vec4 vp, vec3 dest) { glm_project_no(pos, m, vp, dest); } + +CGLM_EXPORT +float +glmc_project_z_no(vec3 pos, mat4 m) { + return glm_project_z_no(pos, m); +} diff --git a/src/clipspace/project_zo.c b/src/clipspace/project_zo.c index bc480a0..6699be9 100644 --- a/src/clipspace/project_zo.c +++ b/src/clipspace/project_zo.c @@ -19,3 +19,9 @@ void glmc_project_zo(vec3 pos, mat4 m, vec4 vp, vec3 dest) { glm_project_zo(pos, m, vp, dest); } + +CGLM_EXPORT +float +glmc_project_z_zo(vec3 pos, mat4 m) { + return glm_project_z_zo(pos, m); +} diff --git a/src/project.c b/src/project.c index 3e09ac6..4d22337 100644 --- a/src/project.c +++ b/src/project.c @@ -26,6 +26,12 @@ glmc_project(vec3 pos, mat4 m, vec4 vp, vec3 dest) { glm_project(pos, m, vp, dest); } +CGLM_EXPORT +float +glmc_project_z(vec3 pos, mat4 m) { + return glm_project_z(pos, m); +} + CGLM_EXPORT void glmc_pickmatrix(vec2 center, vec2 size, vec4 vp, mat4 dest) { diff --git a/win/cglm.vcxproj b/win/cglm.vcxproj index eeb0e78..225c240 100644 --- a/win/cglm.vcxproj +++ b/win/cglm.vcxproj @@ -60,6 +60,8 @@ + + diff --git a/win/cglm.vcxproj.filters b/win/cglm.vcxproj.filters index 7371322..ad73efd 100644 --- a/win/cglm.vcxproj.filters +++ b/win/cglm.vcxproj.filters @@ -591,5 +591,11 @@ include\cglm + + include\cglm + + + include\cglm + \ No newline at end of file