Merge branch 'master' into swizzle

This commit is contained in:
Recep Aslantas
2019-06-06 12:58:55 +03:00
committed by GitHub
145 changed files with 17376 additions and 1853 deletions

8
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,8 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: cglm
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
custom: # Replace with a single custom sponsorship URL

12
.gitignore vendored
View File

@@ -59,4 +59,14 @@ cglm_test_ios/*
cglm_test_iosTests/*
docs/build/*
win/cglm_test_*
* copy.*
* copy.*
*.o
*.obj
*codeanalysis.*.xml
*codeanalysis.xml
*.lib
*.tlog
win/x64
win/x85
win/Debug
cglm-test-ios*

View File

@@ -49,7 +49,7 @@ script:
after_success:
- if [[ "$CC" == "gcc" && "$CODE_COVERAGE" == "ON" ]]; then
pip install --user cpp-coveralls
pip install --user cpp-coveralls &&
coveralls
--build-root .
--exclude lib
@@ -57,3 +57,6 @@ after_success:
--gcov-options '\-lp'
--verbose;
fi
after_failure:
- cat ./test-suite.log

63
CREDITS Normal file
View File

@@ -0,0 +1,63 @@
This library [initially] used some [piece of] implementations
(may include codes) from these open source projects/resources:
1. Initial Affine Transforms
The original glm repo (g-truc), url: https://github.com/g-truc/glm
LICENSE[S]:
The Happy Bunny License (Modified MIT License)
The MIT License
Copyright (c) 2005 - 2016 G-Truc Creation
FULL LICENSE: https://github.com/g-truc/glm/blob/master/copying.txt
2. Initial Quaternions
Anton's OpenGL 4 Tutorials book source code:
LICENSE:
OpenGL 4 Example Code.
Accompanies written series "Anton's OpenGL 4 Tutorials"
Email: anton at antongerdelan dot net
First version 27 Jan 2014
Copyright Dr Anton Gerdelan, Trinity College Dublin, Ireland.
3. Euler Angles
David Eberly
Geometric Tools, LLC http://www.geometrictools.com/
Copyright (c) 1998-2016. All Rights Reserved.
Computing Euler angles from a rotation matrix (euler.pdf)
Gregory G. Slabaugh
4. Extracting Planes
Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix
Authors:
Gil Gribb (ggribb@ravensoft.com)
Klaus Hartmann (k_hartmann@osnabrueck.netsurf.de)
5. Transform AABB
Transform Axis Aligned Bounding Boxes:
http://dev.theomader.com/transform-bounding-boxes/
https://github.com/erich666/GraphicsGems/blob/master/gems/TransBox.c
6. Cull frustum
http://www.txutxi.com/?p=584
http://old.cescg.org/CESCG-2002/DSykoraJJelinek/
7. Quaternions
Initial mat4_quat is borrowed from Apple's simd library
8. Vector Rotation using Quaternion
https://gamedev.stackexchange.com/questions/28395/rotating-vector3-by-a-quaternion
9. Sphere AABB intersect
https://github.com/erich666/GraphicsGems/blob/master/gems/BoxSphere.c
10. Horizontal add
https://stackoverflow.com/questions/6996764/fastest-way-to-do-horizontal-float-vector-sum-on-x86
11. de casteljau implementation and comments
https://forums.khronos.org/showthread.php/10264-Animations-in-1-4-1-release-notes-revision-A/page2?highlight=bezier
https://forums.khronos.org/showthread.php/10644-Animation-Bezier-interpolation
https://forums.khronos.org/showthread.php/10387-2D-Tangents-in-Bezier-Splines?p=34164&viewfull=1#post34164
https://forums.khronos.org/showthread.php/10651-Animation-TCB-Spline-Interpolation-in-COLLADA?highlight=bezier

48
LICENSE
View File

@@ -19,51 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-
This library [initially] used some [piece of] implementations
(may include codes) from these open source projects/resources:
1. Affine Transforms
The original glm repo (g-truc), url: https://github.com/g-truc/glm
LICENSE[S]:
The Happy Bunny License (Modified MIT License)
The MIT License
Copyright (c) 2005 - 2016 G-Truc Creation
FULL LICENSE: https://github.com/g-truc/glm/blob/master/copying.txt
2. Quaternions
Anton's OpenGL 4 Tutorials book source code:
LICENSE:
OpenGL 4 Example Code.
Accompanies written series "Anton's OpenGL 4 Tutorials"
Email: anton at antongerdelan dot net
First version 27 Jan 2014
Copyright Dr Anton Gerdelan, Trinity College Dublin, Ireland.
3. Euler Angles
David Eberly
Geometric Tools, LLC http://www.geometrictools.com/
Copyright (c) 1998-2016. All Rights Reserved.
Computing Euler angles from a rotation matrix (euler.pdf)
Gregory G. Slabaugh
4. Extracting Planes
Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix
Authors:
Gil Gribb (ggribb@ravensoft.com)
Klaus Hartmann (k_hartmann@osnabrueck.netsurf.de)
5. Transform AABB
Transform Axis Aligned Bounding Boxes:
http://dev.theomader.com/transform-bounding-boxes/
https://github.com/erich666/GraphicsGems/blob/master/gems/TransBox.c
6. Cull frustum
http://www.txutxi.com/?p=584
http://old.cescg.org/CESCG-2002/DSykoraJJelinek/

154
README.md
View File

@@ -1,21 +1,29 @@
# 🎥 OpenGL Mathematics (glm) for `C`
[![Build Status](https://travis-ci.org/recp/cglm.svg?branch=master)](https://travis-ci.org/recp/cglm)
[![Build status](https://ci.appveyor.com/api/projects/status/av7l3gc0yhfex8y4/branch/master?svg=true)](https://ci.appveyor.com/project/recp/cglm/branch/master)
[![Build status](https://ci.appveyor.com/api/projects/status/av7l3gc0yhfex8y4/branch/master?svg=true)](https://ci.appveyor.com/project/recp/cglm/branch/master)
[![Documentation Status](https://readthedocs.org/projects/cglm/badge/?version=latest)](http://cglm.readthedocs.io/en/latest/?badge=latest)
[![Coverage Status](https://coveralls.io/repos/github/recp/cglm/badge.svg?branch=master)](https://coveralls.io/github/recp/cglm?branch=master)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/6a62b37d5f214f178ebef269dc4a6bf1)](https://www.codacy.com/app/recp/cglm?utm_source=github.com&utm_medium=referral&utm_content=recp/cglm&utm_campaign=Badge_Grade)
The original glm library is for C++ only (templates, namespaces, classes...), this library targeted to C99 but currently you can use it for C89 safely by language extensions e.g `__restrict`
[![Backers on Open Collective](https://opencollective.com/cglm/backers/badge.svg)](#backers)
[![Sponsors on Open Collective](https://opencollective.com/cglm/sponsors/badge.svg)](#sponsors)
#### Documentation
Almost all functions (inline versions) and parameters are documented inside related headers. <br />
Complete documentation is in progress: http://cglm.readthedocs.io
Complete documentation: http://cglm.readthedocs.io
#### Note for previous versions:
- _dup (duplicate) is changed to _copy. For instance `glm_vec_dup -> glm_vec_copy`
- _dup (duplicate) is changed to _copy. For instance `glm_vec_dup -> glm_vec3_copy`
- OpenGL related functions are dropped to make this lib platform/third-party independent
- make sure you have latest version and feel free to report bugs, troubles
- **[bugfix]** euler angles was implemented in reverse order (extrinsic) it was fixed, now they are intrinsic. Make sure that
you have the latest version
- **[major change]** by starting v0.4.0, quaternions are stored as [x, y, z, w], it was [w, x, y, z] in v0.3.5 and earlier versions
- **[api rename]** by starting v0.4.5, **glm_simd** functions are renamed to **glmm_**
- **[new option]** by starting v0.4.5, you can disable alignment requirement, check options in docs.
- **[major change]** by starting v0.5.0, vec3 functions use **glm_vec3_** namespace, it was **glm_vec_** until v0.5.0
- **[major change]** by starting v0.5.1, built-in alignment is removed from **vec3** and **mat3** types
#### Note for C++ developers:
If you don't aware about original GLM library yet, you may also want to look at:
@@ -29,10 +37,17 @@ https://github.com/g-truc/glm
- Welcome!
#### Note for experienced developers:
- Since I'm testing this library in my projects, sometimes bugs occurs; finding that bug[s] and making improvements would be more easy with multiple developer/contributor and their projects or knowledge. Consider to make some tests if you suspect something is wrong and any feedbacks, contributions and bug reports are always welcome.
- Since I'm testing this library in my projects, sometimes bugs occurs; finding that bug[s] and making improvements would be more easy with multiple developer/contributor and their projects or knowledge. Consider to make some tests if you suspect something is wrong and any feedbacks, contributions and bug reports are always welcome.
#### Note for floating point errors:
I realized that floating point errors may occur is some operaitons especially decomposing matrices. cglm will support double later but I will try yo fix these errors by learning floating points standarts in more details. Currently it is just in my TODOs.
#### Allocations?
`cglm` doesn't alloc any memory on heap. So it doesn't provide any allocator. You should alloc memory for **out** parameters too if you pass pointer of memory location. Don't forget that **vec4** (also quat/**versor**) and **mat4** must be aligned (16-bytes), because *cglm* uses SIMD instructions to optimize most operations if available.
#### Returning vector or matrix... ?
**cglm** supports both *ARRAY API* and *STRUCT API*, so you can return structs if you you struct api (`glms_`).
#### Other APIs like Vulkan, Metal, Dx?
Currently *cglm* uses default clip space configuration (-1, 1) for camera functions (perspective, extract corners...), in the future other clip space configurations will be supported
<hr/>
@@ -52,6 +67,7 @@ I realized that floating point errors may occur is some operaitons especially de
</table>
## Features
- array api and struct api, you can use arrays or structs.
- general purpose matrix operations (mat4, mat3)
- chain matrix multiplication (square only)
- general purpose vector operations (cross, dot, rotate, proj, angle...)
@@ -66,6 +82,12 @@ I realized that floating point errors may occur is some operaitons especially de
- inline or pre-compiled function call
- frustum (extract view frustum planes, corners...)
- bounding box (AABB in Frustum (culling), crop, merge...)
- bounding sphere
- project, unproject
- easing functions
- curves
- curve interpolation helpers (S*M*C, deCasteljau...)
- and other...
<hr />
@@ -107,20 +129,19 @@ glm_mul(T, R, modelMat);
glm_inv_tr(modelMat);
```
## License
MIT. check the LICENSE file
## Build
### Unix (Autotools)
```text
$ sh ./build-deps.sh # run only once (dependencies)
```bash
$ sh ./build-deps.sh # run only once (dependencies) [Optional].
$ # You can pass this step if you don't want to run `make check` for tests.
$ # cglm uses cmocka for tests and it may reqiure cmake for building it
$
$ sh autogen.sh
$ ./configure
$ make
$ make install
$ make check # [Optional] (if you run `sh ./build-deps.sh`)
$ [sudo] make install
```
@@ -138,22 +159,31 @@ if `msbuild` won't work (because of multi version VS) then try to build with `de
$ devenv cglm.sln /Build Release
```
### Building Docs
First you need install Sphinx: http://www.sphinx-doc.org/en/master/usage/installation.html
then:
```bash
$ cd docs
$ sphinx-build source build
```
it will compile docs into build folder, you can run index.html inside that function.
## How to use
If you want to use inline versions of funcstions then; include main header
```C
#include <cglm/cglm.h>
```
the haeder will include all headers. Then call func you want e.g. rotate vector by axis:
the header will include all headers. Then call func you want e.g. rotate vector by axis:
```C
glm_vec_rotate(v1, glm_rad(45), (vec3){1.0f, 0.0f, 0.0f});
glm_vec3_rotate(v1, glm_rad(45), (vec3){1.0f, 0.0f, 0.0f});
```
some functions are overloaded :) e.g you can normalize vector:
```C
glm_vec_normalize(vec);
glm_vec3_normalize(vec);
```
this will normalize vec and store normalized vector into `vec` but if you will store normalized vector into another vector do this:
```C
glm_vec_normalize_to(vec, result);
glm_vec3_normalize_to(vec, result);
```
like this function you may see `_to` postfix, this functions store results to another variables and save temp memory
@@ -162,12 +192,60 @@ to call pre-compiled versions include header with `c` postfix, c means call. Pre
```C
#include <cglm/call.h>
```
this header will include all heaers with c postfix. You need to call functions with c posfix:
this header will include all headers with c postfix. You need to call functions with c posfix:
```C
glmc_vec_normalize(vec);
glmc_vec3_normalize(vec);
```
Function usage and parameters are documented inside related headers.
Function usage and parameters are documented inside related headers. You may see same parameter passed twice in some examples like this:
```C
glm_mat4_mul(m1, m2, m1);
/* or */
glm_mat4_mul(m1, m1, m1);
```
the first two parameter are **[in]** and the last one is **[out]** parameter. After multiplied *m1* and *m2* the result is stored in *m1*. This is why we send *m1* twice. You may store result in different matrix, this just an example.
### Example: Computing MVP matrix
#### Option 1
```C
mat4 proj, view, model, mvp;
/* init proj, view and model ... */
glm_mat4_mul(proj, view, viewProj);
glm_mat4_mul(viewProj, model, mvp);
```
#### Option 2
```C
mat4 proj, view, model, mvp;
/* init proj, view and model ... */
glm_mat4_mulN((mat4 *[]){&proj, &view, &model}, 3, mvp);
```
## How to send matrix to OpenGL
mat4 is array of vec4 and vec4 is array of floats. `glUniformMatrix4fv` functions accecpts `float*` as `value` (last param), so you can cast mat4 to float* or you can pass first column of matrix as beginning of memory of matrix:
Option 1: Send first column
```C
glUniformMatrix4fv(location, 1, GL_FALSE, matrix[0]);
/* array of matrices */
glUniformMatrix4fv(location, 1, GL_FALSE, matrix[0][0]);
```
Option 2: Cast matrix to pointer type (also valid for multiple dimensional arrays)
```C
glUniformMatrix4fv(location, 1, GL_FALSE, (float *)matrix);
```
You can pass same way to another APIs e.g. Vulkan, DX...
## Notes
- This library uses float types only, does not support Integers, Double... yet
@@ -178,5 +256,37 @@ Function usage and parameters are documented inside related headers.
- [ ] Unit tests for comparing cglm with glm results
- [x] Add version info
- [ ] Unaligned operations (e.g. `glm_umat4_mul`)
- [ ] Extra documentation
- [x] Extra documentation
- [ ] ARM Neon Arch (In Progress)
## Contributors
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
<a href="graphs/contributors"><img src="https://opencollective.com/cglm/contributors.svg?width=890&button=false" /></a>
## Backers
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/cglm#backer)]
<a href="https://opencollective.com/cglm#backers" target="_blank"><img src="https://opencollective.com/cglm/backers.svg?width=890"></a>
## Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/cglm#sponsor)]
<a href="https://opencollective.com/cglm/sponsor/0/website" target="_blank"><img src="https://opencollective.com/cglm/sponsor/0/avatar.svg"></a>
<a href="https://opencollective.com/cglm/sponsor/1/website" target="_blank"><img src="https://opencollective.com/cglm/sponsor/1/avatar.svg"></a>
<a href="https://opencollective.com/cglm/sponsor/2/website" target="_blank"><img src="https://opencollective.com/cglm/sponsor/2/avatar.svg"></a>
<a href="https://opencollective.com/cglm/sponsor/3/website" target="_blank"><img src="https://opencollective.com/cglm/sponsor/3/avatar.svg"></a>
<a href="https://opencollective.com/cglm/sponsor/4/website" target="_blank"><img src="https://opencollective.com/cglm/sponsor/4/avatar.svg"></a>
<a href="https://opencollective.com/cglm/sponsor/5/website" target="_blank"><img src="https://opencollective.com/cglm/sponsor/5/avatar.svg"></a>
<a href="https://opencollective.com/cglm/sponsor/6/website" target="_blank"><img src="https://opencollective.com/cglm/sponsor/6/avatar.svg"></a>
<a href="https://opencollective.com/cglm/sponsor/7/website" target="_blank"><img src="https://opencollective.com/cglm/sponsor/7/avatar.svg"></a>
<a href="https://opencollective.com/cglm/sponsor/8/website" target="_blank"><img src="https://opencollective.com/cglm/sponsor/8/avatar.svg"></a>
<a href="https://opencollective.com/cglm/sponsor/9/website" target="_blank"><img src="https://opencollective.com/cglm/sponsor/9/avatar.svg"></a>
## License
MIT. check the LICENSE file

View File

@@ -8,17 +8,14 @@
cd $(dirname "$0")
if [ "$(uname)" = "Darwin" ]; then
libtoolBin=$(which glibtoolize)
libtoolBinDir=$(dirname "${libtoolBin}")
if [ ! -f "${libtoolBinDir}/libtoolize" ]; then
ln -s $libtoolBin "${libtoolBinDir}/libtoolize"
fi
fi
autoheader
libtoolize
if [ "$(uname)" = "Darwin" ]; then
glibtoolize
else
libtoolize
fi
aclocal -I m4
autoconf
automake --add-missing --copy

View File

@@ -9,21 +9,14 @@
# check if deps are pulled
git submodule update --init --recursive
# fix glibtoolize
cd $(dirname "$0")
if [ "$(uname)" = "Darwin" ]; then
libtoolBin=$(which glibtoolize)
libtoolBinDir=$(dirname "${libtoolBin}")
ln -s $libtoolBin "${libtoolBinDir}/libtoolize"
fi
# general deps: gcc make autoconf automake libtool cmake
# test - cmocka
cd ./test/lib/cmocka
mkdir build
rm -rf build
mkdir -p build
cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug ..
make -j8

28
cglm.podspec Normal file
View File

@@ -0,0 +1,28 @@
Pod::Spec.new do |s|
# Description
s.name = "cglm"
s.version = "0.5.1"
s.summary = "📽 Optimized OpenGL/Graphics Math (glm) for C"
s.description = <<-DESC
cglm is math library for graphics programming for C. It is similar to original glm but it is written for C instead of C++ (you can use here too). See the documentation or README for all features.
DESC
s.documentation_url = "http://cglm.readthedocs.io"
# Home
s.homepage = "https://github.com/recp/cglm"
s.license = { :type => "MIT", :file => "LICENSE" }
s.author = { "Recep Aslantas" => "recp@acm.org" }
# Sources
s.source = { :git => "https://github.com/recp/cglm.git", :tag => "v#{s.version}" }
s.source_files = "src", "include/cglm/**/*.h"
s.public_header_files = "include", "include/cglm/**/*.h"
s.exclude_files = "src/win/*", "src/dllmain.c", "src/**/*.h"
s.preserve_paths = "include", "src"
s.header_mappings_dir = "include"
# Linking
s.library = "m"
end

View File

@@ -7,7 +7,7 @@
#*****************************************************************************
AC_PREREQ([2.69])
AC_INIT([cglm], [0.2.1], [info@recp.me])
AC_INIT([cglm], [0.6.0], [info@recp.me])
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
AC_CONFIG_MACRO_DIR([m4])
@@ -29,6 +29,7 @@ LT_INIT
# Checks for libraries.
AC_CHECK_LIB([m], [floor])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
AC_SYS_LARGEFILE
# Checks for header files.

View File

@@ -0,0 +1,99 @@
.. default-domain:: C
affine transform matrix (specialized functions)
================================================================================
Header: cglm/affine-mat.h
We mostly use glm_mat4_* for 4x4 general and transform matrices. **cglm**
provides optimized version of some functions. Because affine transform matrix is
a known format, for instance all last item of first three columns is zero.
You should be careful when using these functions. For instance :c:func:`glm_mul`
assumes matrix will be this format:
.. code-block:: text
R R R X
R R R Y
R R R Z
0 0 0 W
if you override zero values here then use :c:func:`glm_mat4_mul` version.
You cannot use :c:func:`glm_mul` anymore.
Same is also true for :c:func:`glm_inv_tr` if you only have rotation and
translation then it will work as expected, otherwise you cannot use that.
In the future it may accept scale factors too but currectly it does not.
Table of contents (click func go):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Functions:
1. :c:func:`glm_mul`
#. :c:func:`glm_mul_rot`
#. :c:func:`glm_inv_tr`
Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~
.. c:function:: void glm_mul(mat4 m1, mat4 m2, mat4 dest)
| this is similar to glm_mat4_mul but specialized to affine transform
Matrix format should be:
.. code-block:: text
R R R X
R R R Y
R R R Z
0 0 0 W
this reduces some multiplications. It should be faster than mat4_mul.
if you are not sure about matrix format then DON'T use this! use mat4_mul
Parameters:
| *[in]* **m1** affine matrix 1
| *[in]* **m2** affine matrix 2
| *[out]* **dest** result matrix
.. c:function:: void glm_mul_rot(mat4 m1, mat4 m2, mat4 dest)
| this is similar to glm_mat4_mul but specialized to rotation matrix
Right Matrix format should be (left is free):
.. code-block:: text
R R R 0
R R R 0
R R R 0
0 0 0 1
this reduces some multiplications. It should be faster than mat4_mul.
if you are not sure about matrix format then DON'T use this! use mat4_mul
Parameters:
| *[in]* **m1** affine matrix 1
| *[in]* **m2** affine matrix 2
| *[out]* **dest** result matrix
.. c:function:: void glm_inv_tr(mat4 mat)
| inverse orthonormal rotation + translation matrix (ridig-body)
.. code-block:: text
X = | R T | X' = | R' -R'T |
| 0 1 | | 0 1 |
use this if you only have rotation + translation, this should work faster
than :c:func:`glm_mat4_inv`
Don't use this if your matrix includes other things e.g. scale, shear...
Parameters:
| *[in,out]* **mat** affine matrix

343
docs/source/affine.rst Normal file
View File

@@ -0,0 +1,343 @@
.. default-domain:: C
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 */
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]

50
docs/source/api.rst Normal file
View File

@@ -0,0 +1,50 @@
API documentation
================================
Some functions may exist twice,
once for their namespace and once for global namespace
to make easier to write very common functions
For instance, in general we use :code:`glm_vec3_dot` to get dot product
of two **vec3**. Now we can also do this with :code:`glm_dot`,
same for *_cross* and so on...
The original function stays where it is, the function in global namespace
of same name is just an alias, so there is no call version of those functions.
e.g there is no func like :code:`glmc_dot` because *glm_dot* is just alias for
:code:`glm_vec3_dot`
By including **cglm/cglm.h** header you will include all inline version
of functions. Since functions in this header[s] are inline you don't need to
build or link *cglm* against your project.
But by including **cglm/call.h** header you will include all *non-inline*
version of functions. You need to build *cglm* and link it.
Follow the :doc:`build` documentation for this
.. toctree::
:maxdepth: 1
:caption: API categories:
affine
affine-mat
cam
frustum
box
quat
euler
mat4
mat3
vec3
vec3-ext
vec4
vec4-ext
color
plane
project
util
io
call
sphere
curve
bezier

89
docs/source/bezier.rst Normal file
View File

@@ -0,0 +1,89 @@
.. default-domain:: C
Bezier
================================================================================
Header: cglm/bezier.h
Common helpers for cubic bezier and similar curves.
Table of contents (click to go):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Functions:
1. :c:func:`glm_bezier`
2. :c:func:`glm_hermite`
3. :c:func:`glm_decasteljau`
Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~
.. c:function:: float glm_bezier(float s, float p0, float c0, float c1, float p1)
| cubic bezier interpolation
| formula:
.. code-block:: text
B(s) = P0*(1-s)^3 + 3*C0*s*(1-s)^2 + 3*C1*s^2*(1-s) + P1*s^3
| similar result using matrix:
.. code-block:: text
B(s) = glm_smc(t, GLM_BEZIER_MAT, (vec4){p0, c0, c1, p1})
| glm_eq(glm_smc(...), glm_bezier(...)) should return TRUE
Parameters:
| *[in]* **s** parameter between 0 and 1
| *[in]* **p0** begin point
| *[in]* **c0** control point 1
| *[in]* **c1** control point 2
| *[in]* **p1** end point
Returns:
B(s)
.. c:function:: float glm_hermite(float s, float p0, float t0, float t1, float p1)
| cubic hermite interpolation
| formula:
.. code-block:: text
H(s) = P0*(2*s^3 - 3*s^2 + 1) + T0*(s^3 - 2*s^2 + s) + P1*(-2*s^3 + 3*s^2) + T1*(s^3 - s^2)
| similar result using matrix:
.. code-block:: text
H(s) = glm_smc(t, GLM_HERMITE_MAT, (vec4){p0, p1, c0, c1})
| glm_eq(glm_smc(...), glm_hermite(...)) should return TRUE
Parameters:
| *[in]* **s** parameter between 0 and 1
| *[in]* **p0** begin point
| *[in]* **t0** tangent 1
| *[in]* **t1** tangent 2
| *[in]* **p1** end point
Returns:
B(s)
.. c:function:: float glm_decasteljau(float prm, float p0, float c0, float c1, float p1)
| iterative way to solve cubic equation
Parameters:
| *[in]* **prm** parameter between 0 and 1
| *[in]* **p0** begin point
| *[in]* **c0** control point 1
| *[in]* **c1** control point 2
| *[in]* **p1** end point
Returns:
parameter to use in cubic equation

181
docs/source/box.rst Normal file
View File

@@ -0,0 +1,181 @@
.. default-domain:: C
axis aligned bounding box (AABB)
================================================================================
Header: cglm/box.h
Some convenient functions provided for AABB.
**Definition of box:**
cglm defines box as two dimensional array of vec3.
The first element is **min** point and the second one is **max** point.
If you have another type e.g. struct or even another representation then you must
convert it before and after call cglm box function.
Table of contents (click to go):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Functions:
1. :c:func:`glm_aabb_transform`
#. :c:func:`glm_aabb_merge`
#. :c:func:`glm_aabb_crop`
#. :c:func:`glm_aabb_crop_until`
#. :c:func:`glm_aabb_frustum`
#. :c:func:`glm_aabb_invalidate`
#. :c:func:`glm_aabb_isvalid`
#. :c:func:`glm_aabb_size`
#. :c:func:`glm_aabb_radius`
#. :c:func:`glm_aabb_center`
#. :c:func:`glm_aabb_aabb`
#. :c:func:`glm_aabb_sphere`
#. :c:func:`glm_aabb_point`
#. :c:func:`glm_aabb_contains`
Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~
.. c:function:: void glm_aabb_transform(vec3 box[2], mat4 m, vec3 dest[2])
| apply transform to Axis-Aligned Bounding Box
Parameters:
| *[in]* **box** bounding box
| *[in]* **m** transform matrix
| *[out]* **dest** transformed bounding box
.. c:function:: void glm_aabb_merge(vec3 box1[2], vec3 box2[2], vec3 dest[2])
| merges two AABB bounding box and creates new one
two box must be in same space, if one of box is in different space then
you should consider to convert it's space by glm_box_space
Parameters:
| *[in]* **box1** bounding box 1
| *[in]* **box2** bounding box 2
| *[out]* **dest** merged bounding box
.. c:function:: void glm_aabb_crop(vec3 box[2], vec3 cropBox[2], vec3 dest[2])
| crops a bounding box with another one.
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]* **box** bounding box 1
| *[in]* **cropBox** crop box
| *[out]* **dest** cropped bounding box
.. c:function:: void glm_aabb_crop_until(vec3 box[2], vec3 cropBox[2], vec3 clampBox[2], vec3 dest[2])
| crops a bounding box with another one.
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]* **box** bounding box
| *[in]* **cropBox** crop box
| *[in]* **clampBox** miniumum box
| *[out]* **dest** cropped bounding box
.. c:function:: bool glm_aabb_frustum(vec3 box[2], vec4 planes[6])
| check if AABB intersects with frustum planes
this could be useful for frustum culling using AABB.
OPTIMIZATION HINT:
if planes order is similar to LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR
then this method should run even faster because it would only use two
planes if object is not inside the two planes
fortunately cglm extracts planes as this order! just pass what you got!
Parameters:
| *[in]* **box** bounding box
| *[out]* **planes** frustum planes
.. c:function:: void glm_aabb_invalidate(vec3 box[2])
| invalidate AABB min and max values
| It fills *max* values with -FLT_MAX and *min* values with +FLT_MAX
Parameters:
| *[in, out]* **box** bounding box
.. c:function:: bool glm_aabb_isvalid(vec3 box[2])
| check if AABB is valid or not
Parameters:
| *[in]* **box** bounding box
Returns:
returns true if aabb is valid otherwise false
.. c:function:: float glm_aabb_size(vec3 box[2])
| distance between of min and max
Parameters:
| *[in]* **box** bounding box
Returns:
distance between min - max
.. c:function:: float glm_aabb_radius(vec3 box[2])
| radius of sphere which surrounds AABB
Parameters:
| *[in]* **box** bounding box
.. c:function:: void glm_aabb_center(vec3 box[2], vec3 dest)
| computes center point of AABB
Parameters:
| *[in]* **box** bounding box
| *[out]* **dest** center of bounding box
.. c:function:: bool glm_aabb_aabb(vec3 box[2], vec3 other[2])
| check if two AABB intersects
Parameters:
| *[in]* **box** bounding box
| *[out]* **other** other bounding box
.. c:function:: bool glm_aabb_sphere(vec3 box[2], vec4 s)
| check if AABB intersects with sphere
| https://github.com/erich666/GraphicsGems/blob/master/gems/BoxSphere.c
| Solid Box - Solid Sphere test.
Parameters:
| *[in]* **box** solid bounding box
| *[out]* **s** solid sphere
.. c:function:: bool glm_aabb_point(vec3 box[2], vec3 point)
| check if point is inside of AABB
Parameters:
| *[in]* **box** bounding box
| *[out]* **point** point
.. c:function:: bool glm_aabb_contains(vec3 box[2], vec3 other[2])
| check if AABB contains other AABB
Parameters:
| *[in]* **box** bounding box
| *[out]* **other** other bounding box

View File

@@ -1,9 +1,7 @@
Building cglm
Build cglm
================================
| **cglm** does not have external dependencies except for unit testing.
| When you pulled cglm repo with submodules all dependencies will be pulled too.
| `build-deps.sh` will pull all dependencies/submodules and build for you.
| **cglm** does not have external dependencies except for unit testing. When you pulled **cglm** repo with submodules all dependencies will be pulled too. `build-deps.sh` will pull all dependencies/submodules and build for you.
External dependencies:
* cmocka - for unit testing
@@ -12,7 +10,8 @@ External dependencies:
If you only need to inline versions, you don't need to build **cglm**, you don't need to link it to your program.
Just import cglm to your project as dependency / external lib by copy-paste then use it as usual
**Unix (Autotools):**
Unix (Autotools):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: bash
:linenos:
@@ -26,11 +25,12 @@ Just import cglm to your project as dependency / external lib by copy-paste then
$ [sudo] make install # install to system (optional)
**make** will build cglm to **.libs** sub folder in project folder.
If you don't want to install cglm to your system's folder you can get static and dynamic libs in this folder.
If you don't want to install **cglm** to your system's folder you can get static and dynamic libs in this folder.
**Build dependencies (windows):**
Windows (MSBuild):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Windows related build files, project files are located in win folder,
Windows related build files, project files are located in `win` folder,
make sure you are inside in cglm/win folder.
Code Analysis are enabled, it may take awhile to build.
@@ -50,3 +50,19 @@ then try to build with *devenv*:
$ devenv cglm.sln /Build Release
Currently tests are not available on Windows.
Documentation (Sphinx):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**cglm** uses sphinx framework for documentation, it allows lot of formats for documentation. To see all options see sphinx build page:
https://www.sphinx-doc.org/en/master/man/sphinx-build.html
Example build:
.. code-block:: bash
:linenos:
$ cd cglm/docs
$ sphinx-build source build

19
docs/source/call.rst Normal file
View File

@@ -0,0 +1,19 @@
.. default-domain:: C
precompiled functions (call)
================================================================================
All funcitons in **glm_** namespace are forced to **inline**.
Most functions also have pre-compiled version.
Precompiled versions are in **glmc_** namespace. *c* in the namespace stands for
"call".
Since precompiled functions are just wrapper for inline verisons,
these functions are not documented individually.
It would be duplicate documentation also it
would be hard to sync documentation between inline and call verison for me.
By including **clgm/cglm.h** you include all inline verisons. To get precompiled
versions you need to include **cglm/call.h** header it also includes all
call versions plus *clgm/cglm.h* (inline verisons)

313
docs/source/cam.rst Normal file
View File

@@ -0,0 +1,313 @@
.. default-domain:: C
camera
======
Header: cglm/cam.h
There are many convenient functions for camera. For instance :c:func:`glm_look`
is just wrapper for :c:func:`glm_lookat`. Sometimes you only have direction
instead of target, so that makes easy to build view matrix using direction.
There is also :c:func:`glm_look_anyup` function which can help build view matrix
without providing UP axis. It uses :c:func:`glm_vec3_ortho` to get a UP axis and
builds view matrix.
You can also *_default* versions of ortho and perspective to build projection
fast if you don't care specific projection values.
*_decomp* means decompose; these function can help to decompose projection
matrices.
**NOTE**: Be careful when working with high range (very small near, very large
far) projection matrices. You may not get exact value you gave.
**float** type cannot store very high precision so you will lose precision.
Also your projection matrix will be inaccurate due to losing precision
Table of contents (click to go):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Functions:
1. :c:func:`glm_frustum`
#. :c:func:`glm_ortho`
#. :c:func:`glm_ortho_aabb`
#. :c:func:`glm_ortho_aabb_p`
#. :c:func:`glm_ortho_aabb_pz`
#. :c:func:`glm_ortho_default`
#. :c:func:`glm_ortho_default_s`
#. :c:func:`glm_perspective`
#. :c:func:`glm_persp_move_far`
#. :c:func:`glm_perspective_default`
#. :c:func:`glm_perspective_resize`
#. :c:func:`glm_lookat`
#. :c:func:`glm_look`
#. :c:func:`glm_look_anyup`
#. :c:func:`glm_persp_decomp`
#. :c:func:`glm_persp_decompv`
#. :c:func:`glm_persp_decomp_x`
#. :c:func:`glm_persp_decomp_y`
#. :c:func:`glm_persp_decomp_z`
#. :c:func:`glm_persp_decomp_far`
#. :c:func:`glm_persp_decomp_near`
#. :c:func:`glm_persp_fovy`
#. :c:func:`glm_persp_aspect`
#. :c:func:`glm_persp_sizes`
Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~
.. c:function:: void glm_frustum(float left, float right, float bottom, float top, float nearVal, float farVal, mat4 dest)
| set up perspective peprojection matrix
Parameters:
| *[in]* **left** viewport.left
| *[in]* **right** viewport.right
| *[in]* **bottom** viewport.bottom
| *[in]* **top** viewport.top
| *[in]* **nearVal** near clipping plane
| *[in]* **farVal** far clipping plane
| *[out]* **dest** result matrix
.. c:function:: void glm_ortho(float left, float right, float bottom, float top, float nearVal, float farVal, mat4 dest)
| set up orthographic projection matrix
Parameters:
| *[in]* **left** viewport.left
| *[in]* **right** viewport.right
| *[in]* **bottom** viewport.bottom
| *[in]* **top** viewport.top
| *[in]* **nearVal** near clipping plane
| *[in]* **farVal** far clipping plane
| *[out]* **dest** result matrix
.. c:function:: void glm_ortho_aabb(vec3 box[2], mat4 dest)
| set up orthographic projection matrix using bounding box
| bounding box (AABB) must be in view space
Parameters:
| *[in]* **box** AABB
| *[in]* **dest** result matrix
.. c:function:: void glm_ortho_aabb_p(vec3 box[2], float padding, mat4 dest)
| set up orthographic projection matrix using bounding box
| bounding box (AABB) must be in view space
this version adds padding to box
Parameters:
| *[in]* **box** AABB
| *[in]* **padding** padding
| *[out]* **d** result matrix
.. c:function:: void glm_ortho_aabb_pz(vec3 box[2], float padding, mat4 dest)
| set up orthographic projection matrix using bounding box
| bounding box (AABB) must be in view space
this version adds Z padding to box
Parameters:
| *[in]* **box** AABB
| *[in]* **padding** padding for near and far
| *[out]* **d** result matrix
Returns:
square of norm / magnitude
.. c:function:: void glm_ortho_default(float aspect, mat4 dest)
| set up unit orthographic projection matrix
Parameters:
| *[in]* **aspect** aspect ration ( width / height )
| *[out]* **dest** result matrix
.. c:function:: void glm_ortho_default_s(float aspect, float size, mat4 dest)
| set up orthographic projection matrix with given CUBE size
Parameters:
| *[in]* **aspect** aspect ration ( width / height )
| *[in]* **size** cube size
| *[out]* **dest** result matrix
.. c:function:: void glm_perspective(float fovy, float aspect, float nearVal, float farVal, mat4 dest)
| set up perspective projection matrix
Parameters:
| *[in]* **fovy** field of view angle
| *[in]* **aspect** aspect ratio ( width / height )
| *[in]* **nearVal** near clipping plane
| *[in]* **farVal** far clipping planes
| *[out]* **dest** result matrix
.. c:function:: void glm_persp_move_far(mat4 proj, float deltaFar)
| extend perspective projection matrix's far distance
| this function does not guarantee far >= near, be aware of that!
Parameters:
| *[in, out]* **proj** projection matrix to extend
| *[in]* **deltaFar** distance from existing far (negative to shink)
.. c:function:: void glm_perspective_default(float aspect, mat4 dest)
| set up perspective projection matrix with default near/far
and angle values
Parameters:
| *[in]* **aspect** aspect aspect ratio ( width / height )
| *[out]* **dest** result matrix
.. c:function:: void glm_perspective_resize(float aspect, mat4 proj)
| resize perspective matrix by aspect ratio ( width / height )
this makes very easy to resize proj matrix when window / viewport reized
Parameters:
| *[in]* **aspect** aspect ratio ( width / height )
| *[in, out]* **proj** perspective projection matrix
.. c:function:: void glm_lookat(vec3 eye, vec3 center, vec3 up, mat4 dest)
| set up view matrix
**NOTE:** The UP vector must not be parallel to the line of sight from the eye point to the reference point.
Parameters:
| *[in]* **eye** eye vector
| *[in]* **center** center vector
| *[in]* **up** up vector
| *[out]* **dest** result matrix
.. c:function:: void glm_look(vec3 eye, vec3 dir, vec3 up, mat4 dest)
| set up view matrix
convenient wrapper for :c:func:`glm_lookat`: if you only have direction not
target self then this might be useful. Because you need to get target
from direction.
**NOTE:** The UP vector must not be parallel to the line of sight from the eye point to the reference point.
Parameters:
| *[in]* **eye** eye vector
| *[in]* **center** direction vector
| *[in]* **up** up vector
| *[out]* **dest** result matrix
.. c:function:: void glm_look_anyup(vec3 eye, vec3 dir, mat4 dest)
| set up view matrix
convenient wrapper for :c:func:`glm_look` if you only have direction
and if you don't care what UP vector is then this might be useful
to create view matrix
Parameters:
| *[in]* **eye** eye vector
| *[in]* **center** direction vector
| *[out]* **dest** result matrix
.. c:function:: void glm_persp_decomp(mat4 proj, float *nearVal, float *farVal, float *top, float *bottom, float *left, float *right)
| decomposes frustum values of perspective projection.
Parameters:
| *[in]* **eye** perspective projection matrix
| *[out]* **nearVal** near
| *[out]* **farVal** far
| *[out]* **top** top
| *[out]* **bottom** bottom
| *[out]* **left** left
| *[out]* **right** right
.. c:function:: void glm_persp_decompv(mat4 proj, float dest[6])
| decomposes frustum values of perspective projection.
| this makes easy to get all values at once
Parameters:
| *[in]* **proj** perspective projection matrix
| *[out]* **dest** array
.. c:function:: void glm_persp_decomp_x(mat4 proj, float *left, float *right)
| decomposes left and right values of perspective projection.
| x stands for x axis (left / right axis)
Parameters:
| *[in]* **proj** perspective projection matrix
| *[out]* **left** left
| *[out]* **right** right
.. c:function:: void glm_persp_decomp_y(mat4 proj, float *top, float *bottom)
| decomposes top and bottom values of perspective projection.
| y stands for y axis (top / botom axis)
Parameters:
| *[in]* **proj** perspective projection matrix
| *[out]* **top** top
| *[out]* **bottom** bottom
.. c:function:: void glm_persp_decomp_z(mat4 proj, float *nearVal, float *farVal)
| decomposes near and far values of perspective projection.
| z stands for z axis (near / far axis)
Parameters:
| *[in]* **proj** perspective projection matrix
| *[out]* **nearVal** near
| *[out]* **farVal** far
.. c:function:: void glm_persp_decomp_far(mat4 proj, float * __restrict farVal)
| decomposes far value of perspective projection.
Parameters:
| *[in]* **proj** perspective projection matrix
| *[out]* **farVal** far
.. c:function:: void glm_persp_decomp_near(mat4 proj, float * __restrict nearVal)
| decomposes near value of perspective projection.
Parameters:
| *[in]* **proj** perspective projection matrix
| *[out]* **nearVal** near
.. c:function:: float glm_persp_fovy(mat4 proj)
| returns field of view angle along the Y-axis (in radians)
if you need to degrees, use glm_deg to convert it or use this:
fovy_deg = glm_deg(glm_persp_fovy(projMatrix))
Parameters:
| *[in]* **proj** perspective projection matrix
Returns:
| fovy in radians
.. c:function:: float glm_persp_aspect(mat4 proj)
| returns aspect ratio of perspective projection
Parameters:
| *[in]* **proj** perspective projection matrix
.. c:function:: void glm_persp_sizes(mat4 proj, float fovy, vec4 dest)
| returns sizes of near and far planes of perspective projection
Parameters:
| *[in]* **proj** perspective projection matrix
| *[in]* **fovy** fovy (see brief)
| *[out]* **dest** sizes order: [Wnear, Hnear, Wfar, Hfar]

BIN
docs/source/cglm-intro.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

34
docs/source/color.rst Normal file
View File

@@ -0,0 +1,34 @@
.. default-domain:: C
color
================================================================================
Header: cglm/color.h
Table of contents (click to go):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Functions:
1. :c:func:`glm_luminance`
Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~
.. c:function:: float glm_luminance(vec3 rgb)
| averages the color channels into one value
This function uses formula in COLLADA 1.5 spec which is
.. code-block:: text
luminance = (color.r * 0.212671) +
(color.g * 0.715160) +
(color.b * 0.072169)
It is based on the ISO/CIE color standards (see ITU-R Recommendation BT.709-4),
that averages the color channels into one value
Parameters:
| *[in]* **rgb** RGB color

View File

@@ -30,7 +30,15 @@
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = []
extensions = [
'sphinx.ext.doctest',
'sphinx.ext.todo',
'sphinx.ext.coverage',
'sphinx.ext.mathjax',
'sphinx.ext.ifconfig',
'sphinx.ext.viewcode',
'sphinx.ext.githubpages'
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@@ -54,9 +62,9 @@ author = u'Recep Aslantas'
# built documents.
#
# The short X.Y version.
version = u'0.2.1'
version = u'0.6.0'
# The full version, including alpha/beta/rc tags.
release = u'0.2.1'
release = u'0.6.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -82,7 +90,7 @@ todo_include_todos = False
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'alabaster'
html_theme = 'sphinx_rtd_theme'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
@@ -91,13 +99,13 @@ html_theme = 'alabaster'
# html_theme_options = {}
html_theme_options = {
'github_banner': 'true',
'github_button': 'true',
'github_user': 'recp',
'github_repo': 'cglm',
'travis_button': 'true',
'show_related': 'true',
'fixed_sidebar': 'true'
# 'github_banner': 'true',
# 'github_button': 'true',
# 'github_user': 'recp',
# 'github_repo': 'cglm',
# 'travis_button': 'true',
# 'show_related': 'true',
# 'fixed_sidebar': 'true'
}
# Add any paths that contain custom static files (such as style sheets) here,
@@ -161,3 +169,31 @@ texinfo_documents = [
author, 'cglm', 'One line description of project.',
'Miscellaneous'),
]
# -- Options for Epub output -------------------------------------------------
# Bibliographic Dublin Core info.
epub_title = project
epub_author = author
epub_publisher = author
epub_copyright = copyright
# The unique identifier of the text. This can be a ISBN number
# or the project homepage.
#
# epub_identifier = ''
# A unique identification for the text.
#
# epub_uid = ''
# A list of files that should not be packed into the epub file.
epub_exclude_files = ['search.html']
# -- Extension configuration -------------------------------------------------
# -- Options for todo extension ----------------------------------------------
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = True

41
docs/source/curve.rst Normal file
View File

@@ -0,0 +1,41 @@
.. default-domain:: C
Curve
================================================================================
Header: cglm/curve.h
Common helpers for common curves. For specific curve see its header/doc
e.g bezier
Table of contents (click to go):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Functions:
1. :c:func:`glm_smc`
Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~
.. c:function:: float glm_smc(float s, mat4 m, vec4 c)
| helper function to calculate **S** * **M** * **C** multiplication for curves
| this function does not encourage you to use SMC, instead it is a helper if you use SMC.
| if you want to specify S as vector then use more generic glm_mat4_rmc() func.
| Example usage:
.. code-block:: c
Bs = glm_smc(s, GLM_BEZIER_MAT, (vec4){p0, c0, c1, p1})
Parameters:
| *[in]* **s** parameter between 0 and 1 (this will be [s3, s2, s, 1])
| *[in]* **m** basis matrix
| *[out]* **c** position/control vector
Returns:
scalar value e.g. Bs

182
docs/source/euler.rst Normal file
View File

@@ -0,0 +1,182 @@
.. default-domain:: C
euler angles
============
Header: cglm/euler.h
You may wonder what **glm_euler_sq** type ( **_sq** stands for sequence ) and
:c:func:`glm_euler_by_order` do.
I used them to convert euler angles in one coordinate system to another. For
instance if you have **Z_UP** euler angles and if you want to convert it
to **Y_UP** axis then :c:func:`glm_euler_by_order` is your friend. For more
information check :c:func:`glm_euler_order` documentation
You must pass arrays as array, if you use C compiler then you can use something
like this:
.. code-block:: c
float pitch, yaw, roll;
mat4 rot;
/* pitch = ...; yaw = ...; roll = ... */
glm_euler((vec3){pitch, yaw, roll}, rot);
Rotation Conveniention
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Current *cglm*'s euler functions uses these convention:
* TaitBryan angles (x-y-z convention)
* Intrinsic rotations (pitch, yaw and roll).
This is reserve order of extrinsic (elevation, heading and bank) rotation
* Right hand rule (actually all rotations in *cglm* use **RH**)
* All angles used in *cglm* are **RADIANS** not degrees
**NOTE**: The default :c:func:`glm_euler` function is the short name of
:c:func:`glm_euler_xyz` this is why you can't see :c:func:`glm_euler_xyz`.
When you see an euler function which doesn't have any X, Y, Z suffix then
assume that uses **_xyz** (or instead it accept order as parameter).
If rotation doesn't work properly, your options:
1. If you use (or paste) degrees convert it to radians before calling an euler function
.. code-block:: c
float pitch, yaw, roll;
mat4 rot;
/* pitch = degrees; yaw = degrees; roll = degrees */
glm_euler((vec3){glm_rad(pitch), glm_rad(yaw), glm_rad(roll)}, rot);
2. Convention mismatch. You may have extrinsic angles,
if you do (if you must) then consider to use reverse order e.g if you have
**xyz** extrinsic then use **zyx**
3. *cglm* may implemented it wrong, consider to create an issue to report it
or pull request to fix it
Table of contents (click to go):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Types:
1. glm_euler_sq
Functions:
1. :c:func:`glm_euler_order`
#. :c:func:`glm_euler_angles`
#. :c:func:`glm_euler`
#. :c:func:`glm_euler_xyz`
#. :c:func:`glm_euler_zyx`
#. :c:func:`glm_euler_zxy`
#. :c:func:`glm_euler_xzy`
#. :c:func:`glm_euler_yzx`
#. :c:func:`glm_euler_yxz`
#. :c:func:`glm_euler_by_order`
Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~
.. c:function:: glm_euler_sq glm_euler_order(int ord[3])
| packs euler angles order to glm_euler_sq enum.
To use :c:func:`glm_euler_by_order` function you need *glm_euler_sq*. You
can get it with this function.
You can build param like this:
| X = 0, Y = 1, Z = 2
if you have ZYX order then you pass this: [2, 1, 0] = ZYX.
if you have YXZ order then you pass this: [1, 0, 2] = YXZ
As you can see first item specifies which axis will be first then the
second one specifies which one will be next an so on.
Parameters:
| *[in]* **ord** euler angles order [Angle1, Angle2, Angle2]
Returns:
packed euler order
.. c:function:: void glm_euler_angles(mat4 m, vec3 dest)
| extract euler angles (in radians) using xyz order
Parameters:
| *[in]* **m** affine transform
| *[out]* **dest** angles vector [x, y, z]
.. c:function:: void glm_euler(vec3 angles, mat4 dest)
| build rotation matrix from euler angles
this is alias of glm_euler_xyz function
Parameters:
| *[in]* **angles** angles as vector [Xangle, Yangle, Zangle]
| *[in]* **dest** rotation matrix
.. c:function:: void glm_euler_xyz(vec3 angles, mat4 dest)
| build rotation matrix from euler angles
Parameters:
| *[in]* **angles** angles as vector [Xangle, Yangle, Zangle]
| *[in]* **dest** rotation matrix
.. c:function:: void glm_euler_zyx(vec3 angles, mat4 dest)
| build rotation matrix from euler angles
Parameters:
| *[in]* **angles** angles as vector [Xangle, Yangle, Zangle]
| *[in]* **dest** rotation matrix
.. c:function:: void glm_euler_zxy(vec3 angles, mat4 dest)
| build rotation matrix from euler angles
Parameters:
| *[in]* **angles** angles as vector [Xangle, Yangle, Zangle]
| *[in]* **dest** rotation matrix
.. c:function:: void glm_euler_xzy(vec3 angles, mat4 dest)
| build rotation matrix from euler angles
Parameters:
| *[in]* **angles** angles as vector [Xangle, Yangle, Zangle]
| *[in]* **dest** rotation matrix
.. c:function:: void glm_euler_yzx(vec3 angles, mat4 dest)
build rotation matrix from euler angles
Parameters:
| *[in]* **angles** angles as vector [Xangle, Yangle, Zangle]
| *[in]* **dest** rotation matrix
.. c:function:: void glm_euler_yxz(vec3 angles, mat4 dest)
| build rotation matrix from euler angles
Parameters:
| *[in]* **angles** angles as vector [Xangle, Yangle, Zangle]
| *[in]* **dest** rotation matrix
.. c:function:: void glm_euler_by_order(vec3 angles, glm_euler_sq ord, mat4 dest)
| build rotation matrix from euler angles with given euler order.
Use :c:func:`glm_euler_order` function to build *ord* parameter
Parameters:
| *[in]* **angles** angles as vector [Xangle, Yangle, Zangle]
| *[in]* **ord** euler order
| *[in]* **dest** rotation matrix

23
docs/source/features.rst Normal file
View File

@@ -0,0 +1,23 @@
Features
================================================================================
* general purpose matrix operations (mat4, mat3)
* chain matrix multiplication (square only)
* general purpose vector operations (cross, dot, rotate, proj, angle...)
* affine transforms
* matrix decomposition (extract rotation, scaling factor)
* optimized affine transform matrices (mul, rigid-body inverse)
* camera (lookat)
* projections (ortho, perspective)
* quaternions
* euler angles / yaw-pitch-roll to matrix
* extract euler angles
* inline or pre-compiled function call
* frustum (extract view frustum planes, corners...)
* bounding box (AABB in Frustum (culling), crop, merge...)
* bounding sphere
* project, unproject
* easing functions
* curves
* curve interpolation helpers (SMC, deCasteljau...)
* and other...

168
docs/source/frustum.rst Normal file
View File

@@ -0,0 +1,168 @@
.. default-domain:: C
frustum
=============
Header: cglm/frustum.h
cglm provides convenient functions to extract frustum planes, corners...
All extracted corners are **vec4** so you must create array of **vec4**
not **vec3**. If you want to store them to save space you msut convert them
yourself.
**vec4** is used to speed up functions need to corners. This is why frustum
fucntions use *vec4* instead of *vec3*
Currenty related-functions use [-1, 1] clip space configuration to extract
corners but you can override it by prodiving **GLM_CUSTOM_CLIPSPACE** macro.
If you provide it then you have to all bottom macros as *vec4*
Current configuration:
.. code-block:: c
/* near */
GLM_CSCOORD_LBN {-1.0f, -1.0f, -1.0f, 1.0f}
GLM_CSCOORD_LTN {-1.0f, 1.0f, -1.0f, 1.0f}
GLM_CSCOORD_RTN { 1.0f, 1.0f, -1.0f, 1.0f}
GLM_CSCOORD_RBN { 1.0f, -1.0f, -1.0f, 1.0f}
/* far */
GLM_CSCOORD_LBF {-1.0f, -1.0f, 1.0f, 1.0f}
GLM_CSCOORD_LTF {-1.0f, 1.0f, 1.0f, 1.0f}
GLM_CSCOORD_RTF { 1.0f, 1.0f, 1.0f, 1.0f}
GLM_CSCOORD_RBF { 1.0f, -1.0f, 1.0f, 1.0f}
Explain of short names:
* **LBN**: left bottom near
* **LTN**: left top near
* **RTN**: right top near
* **RBN**: right bottom near
* **LBF**: left bottom far
* **LTF**: left top far
* **RTF**: right top far
* **RBF**: right bottom far
Table of contents (click to go):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Macros:
.. code-block:: c
GLM_LBN 0 /* left bottom near */
GLM_LTN 1 /* left top near */
GLM_RTN 2 /* right top near */
GLM_RBN 3 /* right bottom near */
GLM_LBF 4 /* left bottom far */
GLM_LTF 5 /* left top far */
GLM_RTF 6 /* right top far */
GLM_RBF 7 /* right bottom far */
GLM_LEFT 0
GLM_RIGHT 1
GLM_BOTTOM 2
GLM_TOP 3
GLM_NEAR 4
GLM_FAR 5
Functions:
1. :c:func:`glm_frustum_planes`
#. :c:func:`glm_frustum_corners`
#. :c:func:`glm_frustum_center`
#. :c:func:`glm_frustum_box`
#. :c:func:`glm_frustum_corners_at`
Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~
.. c:function:: void glm_frustum_planes(mat4 m, vec4 dest[6])
| extracts view frustum planes
planes' space:
- if m = proj: View Space
- if m = viewProj: World Space
- if m = MVP: Object Space
You probably want to extract planes in world space so use viewProj as m
Computing viewProj:
.. code-block:: c
glm_mat4_mul(proj, view, viewProj);
Exracted planes order: [left, right, bottom, top, near, far]
Parameters:
| *[in]* **m** matrix
| *[out]* **dest** exracted view frustum planes
.. c:function:: void glm_frustum_corners(mat4 invMat, vec4 dest[8])
| extracts view frustum corners using clip-space coordinates
corners' space:
- if m = invViewProj: World Space
- if m = invMVP: Object Space
You probably want to extract corners in world space so use **invViewProj**
Computing invViewProj:
.. code-block:: c
glm_mat4_mul(proj, view, viewProj);
...
glm_mat4_inv(viewProj, invViewProj);
if you have a near coord at **i** index,
you can get it's far coord by i + 4;
follow example below to understand that
For instance to find center coordinates between a near and its far coord:
.. code-block:: c
for (j = 0; j < 4; j++) {
glm_vec3_center(corners[i], corners[i + 4], centerCorners[i]);
}
corners[i + 4] is far of corners[i] point.
Parameters:
| *[in]* **invMat** matrix
| *[out]* **dest** exracted view frustum corners
.. c:function:: void glm_frustum_center(vec4 corners[8], vec4 dest)
| finds center of view frustum
Parameters:
| *[in]* **corners** view frustum corners
| *[out]* **dest** view frustum center
.. c:function:: void glm_frustum_box(vec4 corners[8], mat4 m, vec3 box[2])
| finds bounding box of frustum relative to given matrix e.g. view mat
Parameters:
| *[in]* **corners** view frustum corners
| *[in]* **m** matrix to convert existing conners
| *[out]* **box** bounding box as array [min, max]
.. c:function:: void glm_frustum_corners_at(vec4 corners[8], float splitDist, float farDist, vec4 planeCorners[4])
| finds planes corners which is between near and far planes (parallel)
this will be helpful if you want to split a frustum e.g. CSM/PSSM. This will
find planes' corners but you will need to one more plane.
Actually you have it, it is near, far or created previously with this func ;)
Parameters:
| *[in]* **corners** frustum corners
| *[in]* **splitDist** split distance
| *[in]* **farDist** far distance (zFar)
| *[out]* **planeCorners** plane corners [LB, LT, RT, RB]

View File

@@ -1,40 +1,79 @@
Getting Started
================================
Types:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**cglm** uses **glm** prefix for all functions e.g. glm_lookat. You can see supported types in common header file:
.. code-block:: c
:linenos:
typedef float vec3[3];
typedef int ivec3[3];
typedef CGLM_ALIGN(16) float vec4[4];
typedef float vec2[2];
typedef float vec3[3];
typedef int ivec3[3];
typedef CGLM_ALIGN_IF(16) float vec4[4];
typedef vec4 versor;
typedef vec3 mat3[3];
typedef vec3 mat3[3];
typedef vec4 mat4[4];
typedef vec4 versor;
#ifdef __AVX__
typedef CGLM_ALIGN_IF(32) vec4 mat4[4];
#else
typedef CGLM_ALIGN_IF(16) vec4 mat4[4];
#endif
As you can see types don't store extra informations in favor of space.
You can send these values e.g. matrix to OpenGL directly without casting or calling a function like *value_ptr*
*vec4* and *mat4* requires 16 byte aligment because vec4 and mat4 operations are
vectorized by SIMD instructions (SSE/AVX).
Alignment Is Required:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**NOTE:** Unaligned vec4 and unaligned mat4 operations will be supported in the future. Check todo list.
**vec4** and **mat4** requires 16 (32 for **mat4** if AVX is enabled) byte alignment because **vec4** and **mat4** operations are vectorized by SIMD instructions (SSE/AVX/NEON).
**UPDATE:**
By starting v0.4.5 cglm provides an option to disable alignment requirement, it is enabled as default
| Check :doc:`opt` page for more details
Also alignment is disabled for older msvc verisons as default. Now alignment is only required in Visual Studio 2017 version 15.6+ if CGLM_ALL_UNALIGNED macro is not defined.
Allocations:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*cglm* doesn't alloc any memory on heap. So it doesn't provide any allocator.
You must allocate memory yourself. You should alloc memory for out parameters too if you pass pointer of memory location. When allocating memory, don't forget that **vec4** and **mat4** require alignment.
**NOTE:** Unaligned **vec4** and unaligned **mat4** operations will be supported in the future. Check todo list.
Because you may want to multiply a CGLM matrix with external matrix.
There is no guarantee that non-CGLM matrix is aligned. Unaligned types will have *u* prefix e.g. **umat4**
Array vs Struct:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*cglm* uses arrays for vector and matrix types. So you can't access individual
elements like vec.x, vec.y, vec.z... You must use subscript to access vector elements
e.g. vec[0], vec[1], vec[2].
Also I think it is more meaningful to access matrix elements with subscript
e.g **matrix[2][3]** instead of **matrix._23**. Since matrix is array of vectors,
vectors are also defined as array. This makes types homogeneous.
**Return arrays?**
Since C doesn't support return arrays, cglm also doesn't support this feature.
Function design:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. image:: cglm-intro.png
:width: 492px
:height: 297px
:align: center
cglm provides a few way to call a function to do same operation.
* Inline - *glm_, glm_u*
* aligned
* unaligned (todo)
* Pre-compiled - *glmc_, glmc_u*
* aligned
* unaligned (todo)
For instance **glm_mat4_mul** is inline (all *glm_* functions are inline), to make it non-inline (pre-compiled)
For instance **glm_mat4_mul** is inline (all *glm_* functions are inline), to make it non-inline (pre-compiled),
call it as **glmc_mat4_mul** from library, to use unaligned version use **glm_umat4_mul** (todo).
Most functions have **dest** parameter for output. For instance mat4_mul func looks like this:

View File

@@ -3,39 +3,48 @@
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to cglm's documentation!
cglm Documentation
================================
**cglm** is optimized 3D math library written in C99 (compatible with C89).
It is similar to original **glm** library except this is mainly for **C**
This library stores matrices as row-major order but in the future column-major
This library stores matrices as column-major order but in the future row-major
is considered to be supported as optional.
Also currently only **float** type is supported for most operations.
**Features**
.. toctree::
:maxdepth: 2
:caption: Getting Started:
* general purpose matrix operations (mat4, mat3)
* chain matrix multiplication (square only)
* general purpose vector operations (cross, dot, rotate, proj, angle...)
* affine transforms
* matrix decomposition (extract rotation, scaling factor)
* optimized affine transform matrices (mul, rigid-body inverse)
* camera (lookat)
* projections (ortho, perspective)
* quaternions
* euler angles / yaw-pitch-roll to matrix
* extract euler angles
* inline or pre-compiled function call
* more features (todo)
features
build
getting_started
.. toctree::
:maxdepth: 2
:caption: Table Of Contents:
:caption: How To:
build
getting_started
opengl
.. toctree::
:maxdepth: 2
:caption: API:
api
.. toctree::
:maxdepth: 2
:caption: Options:
opt
.. toctree::
:maxdepth: 2
:caption: Troubleshooting:
troubleshooting
Indices and tables
==================

102
docs/source/io.rst Normal file
View File

@@ -0,0 +1,102 @@
.. default-domain:: C
io (input / output e.g. print)
================================================================================
Header: cglm/io.h
There are some built-in print functions which may save your time,
especially for debugging.
All functions accept **FILE** parameter which makes very flexible.
You can even print it to file on disk.
In general you will want to print them to console to see results.
You can use **stdout** and **stderr** to write results to console.
Some programs may occupy **stdout** but you can still use **stderr**.
Using **stderr** is suggested.
Example to print mat4 matrix:
.. code-block:: c
mat4 transform;
/* ... */
glm_mat4_print(transform, stderr);
**NOTE:** print functions use **%0.4f** precision if you need more
(you probably will in some cases), you can change it temporary.
cglm may provide precision parameter in the future
Table of contents (click to go):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Functions:
1. :c:func:`glm_mat4_print`
#. :c:func:`glm_mat3_print`
#. :c:func:`glm_vec4_print`
#. :c:func:`glm_vec3_print`
#. :c:func:`glm_ivec3_print`
#. :c:func:`glm_versor_print`
#. :c:func:`glm_aabb_print`
Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~
.. c:function:: void glm_mat4_print(mat4 matrix, FILE * __restrict ostream)
| print mat4 to given stream
Parameters:
| *[in]* **matrix** matrix
| *[in]* **ostream** FILE to write
.. c:function:: void glm_mat3_print(mat3 matrix, FILE * __restrict ostream)
| print mat3 to given stream
Parameters:
| *[in]* **matrix** matrix
| *[in]* **ostream** FILE to write
.. c:function:: void glm_vec4_print(vec4 vec, FILE * __restrict ostream)
| print vec4 to given stream
Parameters:
| *[in]* **vec** vector
| *[in]* **ostream** FILE to write
.. c:function:: void glm_vec3_print(vec3 vec, FILE * __restrict ostream)
| print vec3 to given stream
Parameters:
| *[in]* **vec** vector
| *[in]* **ostream** FILE to write
.. c:function:: void glm_ivec3_print(ivec3 vec, FILE * __restrict ostream)
| print ivec3 to given stream
Parameters:
| *[in]* **vec** vector
| *[in]* **ostream** FILE to write
.. c:function:: void glm_versor_print(versor vec, FILE * __restrict ostream)
| print quaternion to given stream
Parameters:
| *[in]* **vec** quaternion
| *[in]* **ostream** FILE to write
.. c:function:: void glm_aabb_print(versor vec, const char * __restrict tag, FILE * __restrict ostream)
| print aabb to given stream
Parameters:
| *[in]* **vec** aabb (axis-aligned bounding box)
| *[in]* **tag** tag to find it more easly in logs
| *[in]* **ostream** FILE to write

189
docs/source/mat3.rst Normal file
View File

@@ -0,0 +1,189 @@
.. default-domain:: C
mat3
====
Header: cglm/mat3.h
Table of contents (click to go):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Macros:
1. GLM_MAT3_IDENTITY_INIT
#. GLM_MAT3_ZERO_INIT
#. GLM_MAT3_IDENTITY
#. GLM_MAT3_ZERO
#. glm_mat3_dup(mat, dest)
Functions:
1. :c:func:`glm_mat3_copy`
#. :c:func:`glm_mat3_identity`
#. :c:func:`glm_mat3_identity_array`
#. :c:func:`glm_mat3_zero`
#. :c:func:`glm_mat3_mul`
#. :c:func:`glm_mat3_transpose_to`
#. :c:func:`glm_mat3_transpose`
#. :c:func:`glm_mat3_mulv`
#. :c:func:`glm_mat3_quat`
#. :c:func:`glm_mat3_scale`
#. :c:func:`glm_mat3_det`
#. :c:func:`glm_mat3_inv`
#. :c:func:`glm_mat3_trace`
#. :c:func:`glm_mat3_swap_col`
#. :c:func:`glm_mat3_swap_row`
#. :c:func:`glm_mat3_rmc`
Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~
.. c:function:: void glm_mat3_copy(mat3 mat, mat3 dest)
copy mat3 to another one (dest).
Parameters:
| *[in]* **mat** source
| *[out]* **dest** destination
.. c:function:: void glm_mat3_identity(mat3 mat)
copy identity mat3 to mat, or makes mat to identiy
Parameters:
| *[out]* **mat** matrix
.. c:function:: void glm_mat3_identity_array(mat3 * __restrict mat, size_t count)
make given matrix array's each element identity matrix
Parameters:
| *[in,out]* **mat** matrix array (must be aligned (16/32) if alignment is not disabled)
| *[in]* **count** count of matrices
.. c:function:: void glm_mat3_zero(mat3 mat)
make given matrix zero
Parameters:
| *[in,out]* **mat** matrix to
.. c:function:: void glm_mat3_mul(mat3 m1, mat3 m2, mat3 dest)
multiply m1 and m2 to dest
m1, m2 and dest matrices can be same matrix, it is possible to write this:
.. code-block:: c
mat3 m = GLM_MAT3_IDENTITY_INIT;
glm_mat3_mul(m, m, m);
Parameters:
| *[in]* **m1** left matrix
| *[in]* **m2** right matrix
| *[out]* **dest** destination matrix
.. c:function:: void glm_mat3_transpose_to(mat3 m, mat3 dest)
transpose mat4 and store in dest
source matrix will not be transposed unless dest is m
Parameters:
| *[in]* **mat** source
| *[out]* **dest** destination
.. c:function:: void glm_mat3_transpose(mat3 m)
tranpose mat3 and store result in same matrix
Parameters:
| *[in]* **mat** source
| *[out]* **dest** destination
.. c:function:: void glm_mat3_mulv(mat3 m, vec3 v, vec3 dest)
multiply mat4 with vec4 (column vector) and store in dest vector
Parameters:
| *[in]* **mat** mat3 (left)
| *[in]* **v** vec3 (right, column vector)
| *[out]* **dest** destination (result, column vector)
.. c:function:: void glm_mat3_quat(mat3 m, versor dest)
convert mat3 to quaternion
Parameters:
| *[in]* **m** rotation matrix
| *[out]* **dest** destination quaternion
.. c:function:: void glm_mat3_scale(mat3 m, float s)
multiply matrix with scalar
Parameters:
| *[in, out]* **mat** matrix
| *[in]* **dest** scalar
.. c:function:: float glm_mat3_det(mat3 mat)
returns mat3 determinant
Parameters:
| *[in]* **mat** matrix
Returns:
mat3 determinant
.. c:function:: void glm_mat3_inv(mat3 mat, mat3 dest)
inverse mat3 and store in dest
Parameters:
| *[in]* **mat** matrix
| *[out]* **dest** destination (inverse matrix)
.. c:function:: void glm_mat3_trace(mat3 m)
| sum of the elements on the main diagonal from upper left to the lower right
Parameters:
| *[in]* **m** matrix
Returns:
trace of matrix
.. c:function:: void glm_mat3_swap_col(mat3 mat, int col1, int col2)
swap two matrix columns
Parameters:
| *[in, out]* **mat** matrix
| *[in]* **col1** col1
| *[in]* **col2** col2
.. c:function:: void glm_mat3_swap_row(mat3 mat, int row1, int row2)
swap two matrix rows
Parameters:
| *[in, out]* **mat** matrix
| *[in]* **row1** row1
| *[in]* **row2** row2
.. c:function:: float glm_mat3_rmc(vec3 r, mat3 m, vec3 c)
| **rmc** stands for **Row** * **Matrix** * **Column**
| helper for R (row vector) * M (matrix) * C (column vector)
| the result is scalar because R * M = Matrix1x3 (row vector),
| then Matrix1x3 * Vec3 (column vector) = Matrix1x1 (Scalar)
Parameters:
| *[in]* **r** row vector or matrix1x3
| *[in]* **m** matrix3x3
| *[in]* **c** column vector or matrix3x1
Returns:
scalar value e.g. Matrix1x1

298
docs/source/mat4.rst Normal file
View File

@@ -0,0 +1,298 @@
.. default-domain:: C
mat4
====
Header: cglm/mat4.h
Important: :c:func:`glm_mat4_scale` multiplies mat4 with scalar, if you need to
apply scale transform use :c:func:`glm_scale` functions.
Table of contents (click to go):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Macros:
1. GLM_MAT4_IDENTITY_INIT
#. GLM_MAT4_ZERO_INIT
#. GLM_MAT4_IDENTITY
#. GLM_MAT4_ZERO
#. glm_mat4_udup(mat, dest)
#. glm_mat4_dup(mat, dest)
Functions:
1. :c:func:`glm_mat4_ucopy`
#. :c:func:`glm_mat4_copy`
#. :c:func:`glm_mat4_identity`
#. :c:func:`glm_mat4_identity_array`
#. :c:func:`glm_mat4_zero`
#. :c:func:`glm_mat4_pick3`
#. :c:func:`glm_mat4_pick3t`
#. :c:func:`glm_mat4_ins3`
#. :c:func:`glm_mat4_mul`
#. :c:func:`glm_mat4_mulN`
#. :c:func:`glm_mat4_mulv`
#. :c:func:`glm_mat4_mulv3`
#. :c:func:`glm_mat3_trace`
#. :c:func:`glm_mat3_trace3`
#. :c:func:`glm_mat4_quat`
#. :c:func:`glm_mat4_transpose_to`
#. :c:func:`glm_mat4_transpose`
#. :c:func:`glm_mat4_scale_p`
#. :c:func:`glm_mat4_scale`
#. :c:func:`glm_mat4_det`
#. :c:func:`glm_mat4_inv`
#. :c:func:`glm_mat4_inv_fast`
#. :c:func:`glm_mat4_swap_col`
#. :c:func:`glm_mat4_swap_row`
#. :c:func:`glm_mat4_rmc`
Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~
.. c:function:: void glm_mat4_ucopy(mat4 mat, mat4 dest)
copy mat4 to another one (dest). u means align is not required for dest
Parameters:
| *[in]* **mat** source
| *[out]* **dest** destination
.. c:function:: void glm_mat4_copy(mat4 mat, mat4 dest)
copy mat4 to another one (dest).
Parameters:
| *[in]* **mat** source
| *[out]* **dest** destination
.. c:function:: void glm_mat4_identity(mat4 mat)
copy identity mat4 to mat, or makes mat to identiy
Parameters:
| *[out]* **mat** matrix
.. c:function:: void glm_mat4_identity_array(mat4 * __restrict mat, size_t count)
make given matrix array's each element identity matrix
Parameters:
| *[in,out]* **mat** matrix array (must be aligned (16/32) if alignment is not disabled)
| *[in]* **count** count of matrices
.. c:function:: void glm_mat4_zero(mat4 mat)
make given matrix zero
Parameters:
| *[in,out]* **mat** matrix to
.. c:function:: void glm_mat4_pick3(mat4 mat, mat3 dest)
copy upper-left of mat4 to mat3
Parameters:
| *[in]* **mat** source
| *[out]* **dest** destination
.. c:function:: void glm_mat4_pick3t(mat4 mat, mat4 dest)
copy upper-left of mat4 to mat3 (transposed)
the postfix t stands for transpose
Parameters:
| *[in]* **mat** source
| *[out]* **dest** destination
.. c:function:: void glm_mat4_ins3(mat3 mat, mat4 dest)
copy mat3 to mat4's upper-left. this function does not fill mat4's other
elements. To do that use glm_mat4.
Parameters:
| *[in]* **mat** source
| *[out]* **dest** destination
.. c:function:: void glm_mat4_mul(mat4 m1, mat4 m2, mat4 dest)
multiply m1 and m2 to dest
m1, m2 and dest matrices can be same matrix, it is possible to write this:
.. code-block:: c
mat4 m = GLM_MAT4_IDENTITY_INIT;
glm_mat4_mul(m, m, m);
Parameters:
| *[in]* **m1** left matrix
| *[in]* **m2** right matrix
| *[out]* **dest** destination matrix
.. c:function:: void glm_mat4_mulN(mat4 * __restrict matrices[], int len, mat4 dest)
mupliply N mat4 matrices and store result in dest
| this function lets you multiply multiple (more than two or more...)
| matrices
| multiplication will be done in loop, this may reduce instructions
| size but if **len** is too small then compiler may unroll whole loop
.. code-block:: c
mat m1, m2, m3, m4, res;
glm_mat4_mulN((mat4 *[]){&m1, &m2, &m3, &m4}, 4, res);
Parameters:
| *[in]* **matrices** array of mat4
| *[in]* **len** matrices count
| *[out]* **dest** destination matrix
.. c:function:: void glm_mat4_mulv(mat4 m, vec4 v, vec4 dest)
multiply mat4 with vec4 (column vector) and store in dest vector
Parameters:
| *[in]* **m** mat4 (left)
| *[in]* **v** vec4 (right, column vector)
| *[out]* **dest** vec4 (result, column vector)
.. c:function:: void glm_mat4_mulv3(mat4 m, vec3 v, vec3 dest)
multiply vector with mat4's mat3 part(rotation)
Parameters:
| *[in]* **m** mat4 (left)
| *[in]* **v** vec3 (right, column vector)
| *[out]* **dest** vec3 (result, column vector)
.. c:function:: void glm_mat4_trace(mat4 m)
| sum of the elements on the main diagonal from upper left to the lower right
Parameters:
| *[in]* **m** matrix
Returns:
trace of matrix
.. c:function:: void glm_mat4_trace3(mat4 m)
| trace of matrix (rotation part)
| sum of the elements on the main diagonal from upper left to the lower right
Parameters:
| *[in]* **m** matrix
Returns:
trace of matrix
.. c:function:: void glm_mat4_quat(mat4 m, versor dest)
convert mat4's rotation part to quaternion
Parameters:
| *[in]* **m** affine matrix
| *[out]* **dest** destination quaternion
.. c:function:: void glm_mat4_transpose_to(mat4 m, mat4 dest)
transpose mat4 and store in dest
source matrix will not be transposed unless dest is m
Parameters:
| *[in]* **m** matrix
| *[out]* **dest** destination matrix
.. c:function:: void glm_mat4_transpose(mat4 m)
tranpose mat4 and store result in same matrix
Parameters:
| *[in]* **m** source
| *[out]* **dest** destination matrix
.. c:function:: void glm_mat4_scale_p(mat4 m, float s)
scale (multiply with scalar) matrix without simd optimization
Parameters:
| *[in, out]* **m** matrix
| *[in]* **s** scalar
.. c:function:: void glm_mat4_scale(mat4 m, float s)
scale (multiply with scalar) matrix
THIS IS NOT SCALE TRANSFORM, use glm_scale for that.
Parameters:
| *[in, out]* **m** matrix
| *[in]* **s** scalar
.. c:function:: float glm_mat4_det(mat4 mat)
mat4 determinant
Parameters:
| *[in]* **mat** matrix
Return:
| determinant
.. c:function:: void glm_mat4_inv(mat4 mat, mat4 dest)
inverse mat4 and store in dest
Parameters:
| *[in]* **mat** source
| *[out]* **dest** destination matrix (inverse matrix)
.. c:function:: void glm_mat4_inv_fast(mat4 mat, mat4 dest)
inverse mat4 and store in dest
| this func uses reciprocal approximation without extra corrections
| e.g Newton-Raphson. this should work faster than normal,
| to get more precise use glm_mat4_inv version.
| NOTE: You will lose precision, glm_mat4_inv is more accurate
Parameters:
| *[in]* **mat** source
| *[out]* **dest** destination
.. c:function:: void glm_mat4_swap_col(mat4 mat, int col1, int col2)
swap two matrix columns
Parameters:
| *[in, out]* **mat** matrix
| *[in]* **col1** col1
| *[in]* **col2** col2
.. c:function:: void glm_mat4_swap_row(mat4 mat, int row1, int row2)
swap two matrix rows
Parameters:
| *[in, out]* **mat** matrix
| *[in]* **row1** row1
| *[in]* **row2** row2
.. c:function:: float glm_mat4_rmc(vec4 r, mat4 m, vec4 c)
| **rmc** stands for **Row** * **Matrix** * **Column**
| helper for R (row vector) * M (matrix) * C (column vector)
| the result is scalar because R * M = Matrix1x4 (row vector),
| then Matrix1x4 * Vec4 (column vector) = Matrix1x1 (Scalar)
Parameters:
| *[in]* **r** row vector or matrix1x4
| *[in]* **m** matrix4x4
| *[in]* **c** column vector or matrix4x1
Returns:
scalar value e.g. Matrix1x1

61
docs/source/opengl.rst Normal file
View File

@@ -0,0 +1,61 @@
How to send vector or matrix to OpenGL like API
==================================================
*cglm*'s vector and matrix types are arrays. So you can send them directly to a
function which accecpts pointer. But you may got warnings for matrix because it is
two dimensional array.
Passing / Uniforming Matrix to OpenGL:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**glUniformMatrix4fv** accepts float pointer, you can pass matrix to that parameter
and it should work but with warnings. "You can pass" doesn't mean that you must pass like that.
**Correct options:**
Correct doesn't mean correct way to use OpenGL it is just shows correct way to pass cglm type to it.
1. Pass first column
---------------------
The goal is that pass address of matrix, first element of matrix is also address of matrix,
because it is array of vectors and vector is array of floats.
.. code-block:: c
mat4 matrix;
/* ... */
glUniformMatrix4fv(location, 1, GL_FALSE, matrix[0]);
array of matrices:
.. code-block:: c
mat4 matrix;
/* ... */
glUniformMatrix4fv(location, count, GL_FALSE, matrix[0][0]);
1. Cast matrix to pointer
--------------------------
.. code-block:: c
mat4 matrix;
/* ... */
glUniformMatrix4fv(location, count, GL_FALSE, (float *)matrix);
in this way, passing aray of matrices is same
Passing / Uniforming Vectors to OpenGL:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You don't need to do extra thing when passing cglm vectors to OpengL or other APIs.
Because a function like **glUniform4fv** accepts vector as pointer. cglm's vectors
are array of floats. So you can pass it directly ot those functions:
.. code-block:: c
vec4 vec;
/* ... */
glUniform4fv(location, 1, vec);
this show how to pass **vec4** others are same.

52
docs/source/opt.rst Normal file
View File

@@ -0,0 +1,52 @@
.. default-domain:: C
Options
===============================================================================
A few options are provided via macros.
Alignment Option
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
As default, cglm requires types to be aligned. Alignment requirements:
vec3: 8 byte
vec4: 16 byte
mat4: 16 byte
versor: 16 byte
By starting **v0.4.5** cglm provides an option to disable alignment requirement.
To enable this option define **CGLM_ALL_UNALIGNED** macro before all headers.
You can define it in Xcode, Visual Studio (or other IDEs) or you can also prefer
to define it in build system. If you use pre-compiled verisons then you
have to compile cglm with **CGLM_ALL_UNALIGNED** macro.
**VERY VERY IMPORTANT:** If you use cglm in multiple projects and
those projects are depends on each other, then
| *ALWAYS* or *NEVER USE* **CGLM_ALL_UNALIGNED** macro in linked projects
if you do not know what you are doing. Because a cglm header included
via 'project A' may force types to be aligned and another cglm header
included via 'project B' may not require alignment. In this case
cglm functions will read from and write to **INVALID MEMORY LOCATIONs**.
ALWAYS USE SAME CONFIGURATION / OPTION for **cglm** if you have multiple projects.
For instance if you set CGLM_ALL_UNALIGNED in a project then set it in other projects too
SSE and SSE2 Shuffle Option
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**_mm_shuffle_ps** generates **shufps** instruction even if registers are same.
You can force it to generate **pshufd** instruction by defining
**CGLM_USE_INT_DOMAIN** macro. As default it is not defined.
SSE3 and SSE4 Dot Product Options
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You have to extra options for dot product: **CGLM_SSE4_DOT** and **CGLM_SSE3_DOT**.
- If **SSE4** is enabled then you can define **CGLM_SSE4_DOT** to force cglm to use **_mm_dp_ps** instruction.
- If **SSE3** is enabled then you can define **CGLM_SSE3_DOT** to force cglm to use **_mm_hadd_ps** instructions.
otherwise cglm will use custom cglm's hadd functions which are optimized too.

33
docs/source/plane.rst Normal file
View File

@@ -0,0 +1,33 @@
.. default-domain:: C
plane
================================================================================
Header: cglm/plane.h
Plane extract functions are in frustum header and documented
in :doc:`frustum` page.
**Definition of plane:**
Plane equation: **Ax + By + Cz + D = 0**
Plan is stored in **vec4** as **[A, B, C, D]**. (A, B, C) is normal and D is distance
Table of contents (click to go):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Functions:
1. :c:func:`glm_plane_normalize`
Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~
.. c:function:: void glm_plane_normalize(vec4 plane)
| normalizes a plane
Parameters:
| *[in, out]* **plane** pnale to normalize

102
docs/source/project.rst Normal file
View File

@@ -0,0 +1,102 @@
.. default-domain:: C
Project / UnProject
================================================================================
Header: cglm/project.h
Viewport is required as *vec4* **[X, Y, Width, Height]** but this doesn't mean
that you should store it as **vec4**. You can convert your data representation
to vec4 before passing it to related functions.
Table of contents (click to go):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Functions:
1. :c:func:`glm_unprojecti`
#. :c:func:`glm_unproject`
#. :c:func:`glm_project`
Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~
.. 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
[1] space:
- if m = invProj: View Space
- if m = invViewProj: World Space
- if m = invMVP: Object Space
You probably want to map the coordinates into object space
so use invMVP as m
Computing viewProj:
.. code-block:: c
glm_mat4_mul(proj, view, viewProj);
glm_mat4_mul(viewProj, model, MVP);
glm_mat4_inv(viewProj, invMVP);
Parameters:
| *[in]* **pos** point/position in viewport coordinates
| *[in]* **invMat** matrix (see brief)
| *[in]* **vp** viewport as [x, y, width, height]
| *[out]* **dest** unprojected coordinates
.. c:function:: void glm_unproject(vec3 pos, mat4 m, vec4 vp, vec3 dest)
| 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
you.
[1] space:
- if m = proj: View Space
- if m = viewProj: World Space
- if m = MVP: Object Space
You probably want to map the coordinates into object space so use MVP as m
Computing viewProj and MVP:
.. code-block:: c
glm_mat4_mul(proj, view, viewProj);
glm_mat4_mul(viewProj, model, MVP);
Parameters:
| *[in]* **pos** point/position in viewport coordinates
| *[in]* **m** matrix (see brief)
| *[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)
| map object coordinates to window coordinates
Computing MVP:
.. code-block:: c
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

389
docs/source/quat.rst Normal file
View File

@@ -0,0 +1,389 @@
.. default-domain:: C
quaternions
===========
Header: cglm/quat.h
**Important:** *cglm* stores quaternion as **[x, y, z, w]** in memory
since **v0.4.0** it was **[w, x, y, z]**
before v0.4.0 ( **v0.3.5 and earlier** ). w is real part.
What you can do with quaternions with existing functions is (Some of them):
- You can rotate transform matrix using quaterion
- You can rotate vector using quaterion
- You can create view matrix using quaterion
- You can create a lookrotation (from source point to dest)
Table of contents (click to go):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Macros:
1. GLM_QUAT_IDENTITY_INIT
#. GLM_QUAT_IDENTITY
Functions:
1. :c:func:`glm_quat_identity`
#. :c:func:`glm_quat_identity_array`
#. :c:func:`glm_quat_init`
#. :c:func:`glm_quat`
#. :c:func:`glm_quatv`
#. :c:func:`glm_quat_copy`
#. :c:func:`glm_quat_norm`
#. :c:func:`glm_quat_normalize`
#. :c:func:`glm_quat_normalize_to`
#. :c:func:`glm_quat_dot`
#. :c:func:`glm_quat_conjugate`
#. :c:func:`glm_quat_inv`
#. :c:func:`glm_quat_add`
#. :c:func:`glm_quat_sub`
#. :c:func:`glm_quat_real`
#. :c:func:`glm_quat_imag`
#. :c:func:`glm_quat_imagn`
#. :c:func:`glm_quat_imaglen`
#. :c:func:`glm_quat_angle`
#. :c:func:`glm_quat_axis`
#. :c:func:`glm_quat_mul`
#. :c:func:`glm_quat_mat4`
#. :c:func:`glm_quat_mat4t`
#. :c:func:`glm_quat_mat3`
#. :c:func:`glm_quat_mat3t`
#. :c:func:`glm_quat_lerp`
#. :c:func:`glm_quat_slerp`
#. :c:func:`glm_quat_look`
#. :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
~~~~~~~~~~~~~~~~~~~~~~~
.. c:function:: void glm_quat_identity(versor q)
| makes given quat to identity
Parameters:
| *[in, out]* **q** quaternion
.. c:function:: void glm_quat_identity_array(versor * __restrict q, size_t count)
| make given quaternion array's each element identity quaternion
Parameters:
| *[in, out]* **q** quat array (must be aligned (16) if alignment is not disabled)
| *[in]* **count** count of quaternions
.. c:function:: void glm_quat_init(versor q, float x, float y, float z, float w)
| inits quaternion with given values
Parameters:
| *[out]* **q** quaternion
| *[in]* **x** imag.x
| *[in]* **y** imag.y
| *[in]* **z** imag.z
| *[in]* **w** w (real part)
.. c:function:: void glm_quat(versor q, float angle, float x, float y, float z)
| creates NEW quaternion with individual axis components
| given axis will be normalized
Parameters:
| *[out]* **q** quaternion
| *[in]* **angle** angle (radians)
| *[in]* **x** axis.x
| *[in]* **y** axis.y
| *[in]* **z** axis.z
.. c:function:: void glm_quatv(versor q, float angle, vec3 axis)
| creates NEW quaternion with axis vector
| given axis will be normalized
Parameters:
| *[out]* **q** quaternion
| *[in]* **angle** angle (radians)
| *[in]* **axis** axis (will be normalized)
.. c:function:: void glm_quat_copy(versor q, versor dest)
| copy quaternion to another one
Parameters:
| *[in]* **q** source quaternion
| *[out]* **dest** destination quaternion
.. c:function:: float glm_quat_norm(versor q)
| returns norm (magnitude) of quaternion
Parameters:
| *[in]* **a** quaternion
Returns:
norm (magnitude)
.. c:function:: void glm_quat_normalize_to(versor q, versor dest)
| normalize quaternion and store result in dest, original one will not be normalized
Parameters:
| *[in]* **q** quaternion to normalize into
| *[out]* **dest** destination quaternion
.. c:function:: void glm_quat_normalize(versor q)
| normalize quaternion
Parameters:
| *[in, out]* **q** quaternion
.. c:function:: float glm_quat_dot(versor p, versor q)
dot product of two quaternion
Parameters:
| *[in]* **p** quaternion 1
| *[in]* **q** quaternion 2
Returns:
dot product
.. c:function:: void glm_quat_conjugate(versor q, versor dest)
conjugate of quaternion
Parameters:
| *[in]* **q** quaternion
| *[in]* **dest** conjugate
.. c:function:: void glm_quat_inv(versor q, versor dest)
inverse of non-zero quaternion
Parameters:
| *[in]* **q** quaternion
| *[in]* **dest** inverse quaternion
.. c:function:: void glm_quat_add(versor p, versor q, versor dest)
add (componentwise) two quaternions and store result in dest
Parameters:
| *[in]* **p** quaternion 1
| *[in]* **q** quaternion 2
| *[in]* **dest** result quaternion
.. c:function:: void glm_quat_sub(versor p, versor q, versor dest)
subtract (componentwise) two quaternions and store result in dest
Parameters:
| *[in]* **p** quaternion 1
| *[in]* **q** quaternion 2
| *[in]* **dest** result quaternion
.. c:function:: float glm_quat_real(versor q)
returns real part of quaternion
Parameters:
| *[in]* **q** quaternion
Returns:
real part (quat.w)
.. c:function:: void glm_quat_imag(versor q, vec3 dest)
returns imaginary part of quaternion
Parameters:
| *[in]* **q** quaternion
| *[out]* **dest** imag
.. c:function:: void glm_quat_imagn(versor q, vec3 dest)
returns normalized imaginary part of quaternion
Parameters:
| *[in]* **q** quaternion
| *[out]* **dest** imag
.. c:function:: float glm_quat_imaglen(versor q)
returns length of imaginary part of quaternion
Parameters:
| *[in]* **q** quaternion
Returns:
norm of imaginary part
.. c:function:: float glm_quat_angle(versor q)
returns angle of quaternion
Parameters:
| *[in]* **q** quaternion
Returns:
angles of quat (radians)
.. c:function:: void glm_quat_axis(versor q, versor dest)
axis of quaternion
Parameters:
| *[in]* **p** quaternion
| *[out]* **dest** axis of quaternion
.. c:function:: void glm_quat_mul(versor p, versor q, versor dest)
| multiplies two quaternion and stores result in dest
| this is also called Hamilton Product
| According to WikiPedia:
| The product of two rotation quaternions [clarification needed] will be
equivalent to the rotation q followed by the rotation p
Parameters:
| *[in]* **p** quaternion 1 (first rotation)
| *[in]* **q** quaternion 2 (second rotation)
| *[out]* **dest** result quaternion
.. c:function:: void glm_quat_mat4(versor q, mat4 dest)
| convert quaternion to mat4
Parameters:
| *[in]* **q** quaternion
| *[out]* **dest** result matrix
.. c:function:: void glm_quat_mat4t(versor q, mat4 dest)
| convert quaternion to mat4 (transposed). This is transposed version of glm_quat_mat4
Parameters:
| *[in]* **q** quaternion
| *[out]* **dest** result matrix
.. c:function:: void glm_quat_mat3(versor q, mat3 dest)
| convert quaternion to mat3
Parameters:
| *[in]* **q** quaternion
| *[out]* **dest** result matrix
.. c:function:: void glm_quat_mat3t(versor q, mat3 dest)
| convert quaternion to mat3 (transposed). This is transposed version of glm_quat_mat3
Parameters:
| *[in]* **q** quaternion
| *[out]* **dest** result matrix
.. c:function:: void glm_quat_lerp(versor from, versor to, float t, versor dest)
| interpolates between two quaternions
| using spherical linear interpolation (LERP)
Parameters:
| *[in]* **from** from
| *[in]* **to** to
| *[in]* **t** interpolant (amount) clamped between 0 and 1
| *[out]* **dest** result quaternion
.. c:function:: void glm_quat_slerp(versor q, versor r, float t, versor dest)
| interpolates between two quaternions
| using spherical linear interpolation (SLERP)
Parameters:
| *[in]* **from** from
| *[in]* **to** to
| *[in]* **t** interpolant (amount) clamped between 0 and 1
| *[out]* **dest** result quaternion
.. c:function:: void glm_quat_look(vec3 eye, versor ori, mat4 dest)
| creates view matrix using quaternion as camera orientation
Parameters:
| *[in]* **eye** eye
| *[in]* **ori** orientation in world space as quaternion
| *[out]* **dest** result matrix
.. c:function:: void glm_quat_for(vec3 dir, vec3 fwd, vec3 up, versor dest)
| creates look rotation quaternion
Parameters:
| *[in]* **dir** direction to look
| *[in]* **fwd** forward vector
| *[in]* **up** up vector
| *[out]* **dest** result matrix
.. c:function:: void glm_quat_forp(vec3 from, vec3 to, vec3 fwd, vec3 up, versor dest)
| creates look rotation quaternion using source and destination positions p suffix stands for position
| this is similar to glm_quat_for except this computes direction for glm_quat_for for you.
Parameters:
| *[in]* **from** source point
| *[in]* **to** destination point
| *[in]* **fwd** forward vector
| *[in]* **up** up vector
| *[out]* **dest** result matrix
.. c:function:: void glm_quat_rotatev(versor q, vec3 v, vec3 dest)
| crotate vector using using quaternion
Parameters:
| *[in]* **q** quaternion
| *[in]* **v** vector to rotate
| *[out]* **dest** rotated vector
.. c:function:: void glm_quat_rotate(mat4 m, versor q, mat4 dest)
| rotate existing transform matrix using quaternion
instead of passing identity matrix, consider to use quat_mat4 functions
Parameters:
| *[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

74
docs/source/sphere.rst Normal file
View File

@@ -0,0 +1,74 @@
.. default-domain:: C
Sphere
================================================================================
Header: cglm/sphere.h
**Definition of sphere:**
Sphere Representation in cglm is *vec4*: **[center.x, center.y, center.z, radii]**
You can call any vec3 function by pasing sphere. Because first three elements
defines center of sphere.
Table of contents (click to go):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Functions:
1. :c:func:`glm_sphere_radii`
#. :c:func:`glm_sphere_transform`
#. :c:func:`glm_sphere_merge`
#. :c:func:`glm_sphere_sphere`
#. :c:func:`glm_sphere_point`
Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~
.. c:function:: float glm_sphere_radii(vec4 s)
| helper for getting sphere radius
Parameters:
| *[in]* **s** sphere
Returns:
returns radii
.. c:function:: void glm_sphere_transform(vec4 s, mat4 m, vec4 dest)
| apply transform to sphere, it is just wrapper for glm_mat4_mulv3
Parameters:
| *[in]* **s** sphere
| *[in]* **m** transform matrix
| *[out]* **dest** transformed sphere
.. c:function:: void glm_sphere_merge(vec4 s1, vec4 s2, vec4 dest)
| merges two spheres and creates a new one
two sphere must be in same space, for instance if one in world space then
the other must be in world space too, not in local space.
Parameters:
| *[in]* **s1** sphere 1
| *[in]* **s2** sphere 2
| *[out]* **dest** merged/extended sphere
.. c:function:: bool glm_sphere_sphere(vec4 s1, vec4 s2)
| check if two sphere intersects
Parameters:
| *[in]* **s1** sphere
| *[in]* **s2** other sphere
.. c:function:: bool glm_sphere_point(vec4 s, vec3 point)
| check if sphere intersects with point
Parameters:
| *[in]* **s** sphere
| *[in]* **point** point

View File

@@ -0,0 +1,79 @@
.. default-domain:: C
Troubleshooting
================================================================================
It is possible that sometimes you may get crashes or wrong results.
Follow these topics
Memory Allocation:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Again, **cglm** doesn't alloc any memory on heap.
cglm functions works like memcpy; it copies data from src,
makes calculations then copy the result to dest.
You are responsible for allocation of **src** and **dest** parameters.
Alignment:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**vec4** and **mat4** types requires 16 byte alignment.
These types are marked with align attribute to let compiler know about this
requirement.
But since MSVC (Windows) throws the error:
**"formal parameter with requested alignment of 16 won't be aligned"**
The alignment attribute has been commented for MSVC
.. code-block:: c
#if defined(_MSC_VER)
# define CGLM_ALIGN(X) /* __declspec(align(X)) */
#else
# define CGLM_ALIGN(X) __attribute((aligned(X)))
#endif.
So MSVC may not know about alignment requirements when creating variables.
The interesting thing is that, if I remember correctly Visual Studio 2017
doesn't throw the above error. So we may uncomment that line for Visual Studio 2017,
you may do it yourself.
**This MSVC issue is still in TODOs.**
**UPDATE:** By starting v0.4.5 cglm provides an option to disable alignment requirement.
Also alignment is disabled for older msvc verisons as default. Now alignment is only required in Visual Studio 2017 version 15.6+ if CGLM_ALL_UNALIGNED macro is not defined.
Crashes, Invalid Memory Access:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Probably you are trying to write to invalid memory location.
You may used wrong function for what you want to do.
For instance you may called **glm_vec4_** functions for **vec3** data type.
It will try to write 32 byte but since **vec3** is 24 byte it should throw
memory access error or exit the app without saying anything.
Wrong Results:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Again, you may used wrong function.
For instance if you use **glm_normalize()** or **glm_vec3_normalize()** for **vec4**,
it will assume that passed param is **vec3** and will normalize it for **vec3**.
Since you need to **vec4** to be normalized in your case, you will get wrong results.
Accessing vec4 type with vec3 functions is valid, you will not get any error, exception or crash.
You only get wrong results if you don't know what you are doing!
So be carefull, when your IDE (Xcode, Visual Studio ...) tried to autocomplete function names, READ IT :)
**Also implementation may be wrong please let us know by creating an issue on Github.**
Other Issues?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**Please let us know by creating an issue on Github.**

173
docs/source/util.rst Normal file
View File

@@ -0,0 +1,173 @@
.. default-domain:: C
utils / helpers
================================================================================
Header: cglm/util.h
Table of contents (click to go):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Functions:
1. :c:func:`glm_sign`
#. :c:func:`glm_signf`
#. :c:func:`glm_rad`
#. :c:func:`glm_deg`
#. :c:func:`glm_make_rad`
#. :c:func:`glm_make_deg`
#. :c:func:`glm_pow2`
#. :c:func:`glm_min`
#. :c:func:`glm_max`
#. :c:func:`glm_clamp`
#. :c:func:`glm_lerp`
Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~
.. c:function:: int glm_sign(int val)
| returns sign of 32 bit integer as +1, -1, 0
| **Important**: It returns 0 for zero input
Parameters:
| *[in]* **val** an integer
Returns:
sign of given number
.. c:function:: float glm_signf(float val)
| returns sign of 32 bit integer as +1.0, -1.0, 0.0
| **Important**: It returns 0.0f for zero input
Parameters:
| *[in]* **val** a float
Returns:
sign of given number
.. c:function:: float glm_rad(float deg)
| convert degree to radians
Parameters:
| *[in]* **deg** angle in degrees
.. c:function:: float glm_deg(float rad)
| convert radians to degree
Parameters:
| *[in]* **rad** angle in radians
.. c:function:: void glm_make_rad(float *degm)
| convert exsisting degree to radians. this will override degrees value
Parameters:
| *[in, out]* **deg** pointer to angle in degrees
.. c:function:: void glm_make_deg(float *rad)
| convert exsisting radians to degree. this will override radians value
Parameters:
| *[in, out]* **rad** pointer to angle in radians
.. c:function:: float glm_pow2(float x)
| multiplies given parameter with itself = x * x or powf(x, 2)
Parameters:
| *[in]* **x** value
Returns:
square of a given number
.. c:function:: float glm_min(float a, float b)
| returns minimum of given two values
Parameters:
| *[in]* **a** number 1
| *[in]* **b** number 2
Returns:
minimum value
.. c:function:: float glm_max(float a, float b)
| returns maximum of given two values
Parameters:
| *[in]* **a** number 1
| *[in]* **b** number 2
Returns:
maximum value
.. c:function:: void glm_clamp(float val, float minVal, float maxVal)
constrain a value to lie between two further values
Parameters:
| *[in]* **val** input value
| *[in]* **minVal** minimum value
| *[in]* **maxVal** maximum value
Returns:
clamped value
.. c:function:: float glm_lerp(float from, float to, float t)
linear interpolation between two number
| formula: from + s * (to - from)
Parameters:
| *[in]* **from** from value
| *[in]* **to** to value
| *[in]* **t** interpolant (amount) clamped between 0 and 1
Returns:
interpolated value
.. c:function:: bool glm_eq(float a, float b)
check if two float equal with using EPSILON
Parameters:
| *[in]* **a** a
| *[in]* **b** b
Returns:
true if a and b equals
.. c:function:: float glm_percent(float from, float to, float current)
percentage of current value between start and end value
Parameters:
| *[in]* **from** from value
| *[in]* **to** to value
| *[in]* **current** value between from and to values
Returns:
clamped normalized percent (0-100 in 0-1)
.. c:function:: float glm_percentc(float from, float to, float current)
clamped percentage of current value between start and end value
Parameters:
| *[in]* **from** from value
| *[in]* **to** to value
| *[in]* **current** value between from and to values
Returns:
clamped normalized percent (0-100 in 0-1)

143
docs/source/vec3-ext.rst Normal file
View File

@@ -0,0 +1,143 @@
.. default-domain:: C
vec3 extra
==========
Header: cglm/vec3-ext.h
There are some functions are in called in extra header. These are called extra
because they are not used like other functions in vec3.h in the future some of
these functions ma be moved to vec3 header.
Table of contents (click to go):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Functions:
1. :c:func:`glm_vec3_mulv`
#. :c:func:`glm_vec3_broadcast`
#. :c:func:`glm_vec3_eq`
#. :c:func:`glm_vec3_eq_eps`
#. :c:func:`glm_vec3_eq_all`
#. :c:func:`glm_vec3_eqv`
#. :c:func:`glm_vec3_eqv_eps`
#. :c:func:`glm_vec3_max`
#. :c:func:`glm_vec3_min`
#. :c:func:`glm_vec3_isnan`
#. :c:func:`glm_vec3_isinf`
#. :c:func:`glm_vec3_isvalid`
#. :c:func:`glm_vec3_sign`
#. :c:func:`glm_vec3_sqrt`
Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~
.. c:function:: void glm_vec3_mulv(vec3 a, vec3 b, vec3 d)
multiplies individual items
Parameters:
| *[in]* **a** vec1
| *[in]* **b** vec2
| *[out]* **d** destination (v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2])
.. c:function:: void glm_vec3_broadcast(float val, vec3 d)
fill a vector with specified value
Parameters:
| *[in]* **val** value
| *[out]* **dest** destination
.. c:function:: bool glm_vec3_eq(vec3 v, float val)
check if vector is equal to value (without epsilon)
Parameters:
| *[in]* **v** vector
| *[in]* **val** value
.. c:function:: bool glm_vec3_eq_eps(vec3 v, float val)
check if vector is equal to value (with epsilon)
Parameters:
| *[in]* **v** vector
| *[in]* **val** value
.. c:function:: bool glm_vec3_eq_all(vec3 v)
check if vectors members are equal (without epsilon)
Parameters:
| *[in]* **v** vector
.. c:function:: bool glm_vec3_eqv(vec3 v1, vec3 v2)
check if vector is equal to another (without epsilon) vector
Parameters:
| *[in]* **vec** vector 1
| *[in]* **vec** vector 2
.. c:function:: bool glm_vec3_eqv_eps(vec3 v1, vec3 v2)
check if vector is equal to another (with epsilon)
Parameters:
| *[in]* **v1** vector1
| *[in]* **v2** vector2
.. c:function:: float glm_vec3_max(vec3 v)
max value of vector
Parameters:
| *[in]* **v** vector
.. c:function:: float glm_vec3_min(vec3 v)
min value of vector
Parameters:
| *[in]* **v** vector
.. c:function:: bool glm_vec3_isnan(vec3 v)
| check if one of items is NaN (not a number)
| you should only use this in DEBUG mode or very critical asserts
Parameters:
| *[in]* **v** vector
.. c:function:: bool glm_vec3_isinf(vec3 v)
| check if one of items is INFINITY
| you should only use this in DEBUG mode or very critical asserts
Parameters:
| *[in]* **v** vector
.. c:function:: bool glm_vec3_isvalid(vec3 v)
| check if all items are valid number
| you should only use this in DEBUG mode or very critical asserts
Parameters:
| *[in]* **v** vector
.. c:function:: void glm_vec3_sign(vec3 v, vec3 dest)
get sign of 32 bit float as +1, -1, 0
Parameters:
| *[in]* **v** vector
| *[out]* **dest** sign vector (only keeps signs as -1, 0, -1)
.. c:function:: void glm_vec3_sqrt(vec3 v, vec3 dest)
square root of each vector item
Parameters:
| *[in]* **v** vector
| *[out]* **dest** destination vector (sqrt(v))

499
docs/source/vec3.rst Normal file
View File

@@ -0,0 +1,499 @@
.. default-domain:: C
vec3
====
Header: cglm/vec3.h
**Important:** *cglm* was used **glm_vec_** namespace for vec3 functions until
**v0.5.0**, since **v0.5.0** cglm uses **glm_vec3_** namespace for vec3.
Also `glm_vec3_flipsign` has been renamed to `glm_vec3_negate`
We mostly use vectors in graphics math, to make writing code faster
and easy to read, some *vec3* functions are aliased in global namespace.
For instance :c:func:`glm_dot` is alias of :c:func:`glm_vec3_dot`,
alias means inline wrapper here. There is no call verison of alias functions
There are also functions for rotating *vec3* vector. **_m4**, **_m3** prefixes
rotate *vec3* with matrix.
Table of contents (click to go):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Macros:
1. glm_vec3_dup(v, dest)
#. GLM_VEC3_ONE_INIT
#. GLM_VEC3_ZERO_INIT
#. GLM_VEC3_ONE
#. GLM_VEC3_ZERO
#. GLM_YUP
#. GLM_ZUP
#. GLM_XUP
Functions:
1. :c:func:`glm_vec3`
#. :c:func:`glm_vec3_copy`
#. :c:func:`glm_vec3_zero`
#. :c:func:`glm_vec3_one`
#. :c:func:`glm_vec3_dot`
#. :c:func:`glm_vec3_norm2`
#. :c:func:`glm_vec3_norm`
#. :c:func:`glm_vec3_add`
#. :c:func:`glm_vec3_adds`
#. :c:func:`glm_vec3_sub`
#. :c:func:`glm_vec3_subs`
#. :c:func:`glm_vec3_mul`
#. :c:func:`glm_vec3_scale`
#. :c:func:`glm_vec3_scale_as`
#. :c:func:`glm_vec3_div`
#. :c:func:`glm_vec3_divs`
#. :c:func:`glm_vec3_addadd`
#. :c:func:`glm_vec3_subadd`
#. :c:func:`glm_vec3_muladd`
#. :c:func:`glm_vec3_muladds`
#. :c:func:`glm_vec3_maxadd`
#. :c:func:`glm_vec3_minadd`
#. :c:func:`glm_vec3_flipsign`
#. :c:func:`glm_vec3_flipsign_to`
#. :c:func:`glm_vec3_inv`
#. :c:func:`glm_vec3_inv_to`
#. :c:func:`glm_vec3_negate`
#. :c:func:`glm_vec3_negate_to`
#. :c:func:`glm_vec3_normalize`
#. :c:func:`glm_vec3_normalize_to`
#. :c:func:`glm_vec3_cross`
#. :c:func:`glm_vec3_crossn`
#. :c:func:`glm_vec3_distance2`
#. :c:func:`glm_vec3_distance`
#. :c:func:`glm_vec3_angle`
#. :c:func:`glm_vec3_rotate`
#. :c:func:`glm_vec3_rotate_m4`
#. :c:func:`glm_vec3_rotate_m3`
#. :c:func:`glm_vec3_proj`
#. :c:func:`glm_vec3_center`
#. :c:func:`glm_vec3_maxv`
#. :c:func:`glm_vec3_minv`
#. :c:func:`glm_vec3_ortho`
#. :c:func:`glm_vec3_clamp`
#. :c:func:`glm_vec3_lerp`
Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~
.. c:function:: void glm_vec3(vec4 v4, vec3 dest)
init vec3 using vec4
Parameters:
| *[in]* **v4** vector4
| *[out]* **dest** destination
.. c:function:: void glm_vec3_copy(vec3 a, vec3 dest)
copy all members of [a] to [dest]
Parameters:
| *[in]* **a** source
| *[out]* **dest** destination
.. c:function:: void glm_vec3_zero(vec3 v)
makes all members 0.0f (zero)
Parameters:
| *[in, out]* **v** vector
.. c:function:: void glm_vec3_one(vec3 v)
makes all members 1.0f (one)
Parameters:
| *[in, out]* **v** vector
.. c:function:: float glm_vec3_dot(vec3 a, vec3 b)
dot product of vec3
Parameters:
| *[in]* **a** vector1
| *[in]* **b** vector2
Returns:
dot product
.. c:function:: void glm_vec3_cross(vec3 a, vec3 b, vec3 d)
cross product of two vector (RH)
Parameters:
| *[in]* **a** vector 1
| *[in]* **b** vector 2
| *[out]* **dest** destination
.. c:function:: void glm_vec3_crossn(vec3 a, vec3 b, vec3 dest)
cross product of two vector (RH) and normalize the result
Parameters:
| *[in]* **a** vector 1
| *[in]* **b** vector 2
| *[out]* **dest** destination
.. c:function:: float glm_vec3_norm2(vec3 v)
norm * norm (magnitude) of vector
we can use this func instead of calling norm * norm, because it would call
sqrtf fuction twice but with this func we can avoid func call, maybe this is
not good name for this func
Parameters:
| *[in]* **v** vector
Returns:
square of norm / magnitude
.. c:function:: float glm_vec3_norm(vec3 vec)
norm (magnitude) of vec3
Parameters:
| *[in]* **vec** vector
.. c:function:: void glm_vec3_add(vec3 a, vec3 b, vec3 dest)
add a vector to b vector store result in dest
Parameters:
| *[in]* **a** vector1
| *[in]* **b** vector2
| *[out]* **dest** destination vector
.. c:function:: void glm_vec3_adds(vec3 a, float s, vec3 dest)
add scalar to v vector store result in dest (d = v + vec(s))
Parameters:
| *[in]* **v** vector
| *[in]* **s** scalar
| *[out]* **dest** destination vector
.. c:function:: void glm_vec3_sub(vec3 v1, vec3 v2, vec3 dest)
subtract b vector from a vector store result in dest (d = v1 - v2)
Parameters:
| *[in]* **a** vector1
| *[in]* **b** vector2
| *[out]* **dest** destination vector
.. c:function:: void glm_vec3_subs(vec3 v, float s, vec3 dest)
subtract scalar from v vector store result in dest (d = v - vec(s))
Parameters:
| *[in]* **v** vector
| *[in]* **s** scalar
| *[out]* **dest** destination vector
.. c:function:: void glm_vec3_mul(vec3 a, vec3 b, vec3 d)
multiply two vector (component-wise multiplication)
Parameters:
| *[in]* **a** vector
| *[in]* **b** scalar
| *[out]* **d** result = (a[0] * b[0], a[1] * b[1], a[2] * b[2])
.. c:function:: void glm_vec3_scale(vec3 v, float s, vec3 dest)
multiply/scale vec3 vector with scalar: result = v * s
Parameters:
| *[in]* **v** vector
| *[in]* **s** scalar
| *[out]* **dest** destination vector
.. c:function:: void glm_vec3_scale_as(vec3 v, float s, vec3 dest)
make vec3 vector scale as specified: result = unit(v) * s
Parameters:
| *[in]* **v** vector
| *[in]* **s** scalar
| *[out]* **dest** destination vector
.. c:function:: void glm_vec3_div(vec3 a, vec3 b, vec3 dest)
div vector with another component-wise division: d = a / b
Parameters:
| *[in]* **a** vector 1
| *[in]* **b** vector 2
| *[out]* **dest** result = (a[0] / b[0], a[1] / b[1], a[2] / b[2])
.. c:function:: void glm_vec3_divs(vec3 v, float s, vec3 dest)
div vector with scalar: d = v / s
Parameters:
| *[in]* **v** vector
| *[in]* **s** scalar
| *[out]* **dest** result = (a[0] / s, a[1] / s, a[2] / s])
.. c:function:: void glm_vec3_addadd(vec3 a, vec3 b, vec3 dest)
| add two vectors and add result to sum
| it applies += operator so dest must be initialized
Parameters:
| *[in]* **a** vector 1
| *[in]* **b** vector 2
| *[out]* **dest** dest += (a + b)
.. c:function:: void glm_vec3_subadd(vec3 a, vec3 b, vec3 dest)
| sub two vectors and add result to sum
| it applies += operator so dest must be initialized
Parameters:
| *[in]* **a** vector 1
| *[in]* **b** vector 2
| *[out]* **dest** dest += (a - b)
.. c:function:: void glm_vec3_muladd(vec3 a, vec3 b, vec3 dest)
| mul two vectors and add result to sum
| it applies += operator so dest must be initialized
Parameters:
| *[in]* **a** vector 1
| *[in]* **b** vector 2
| *[out]* **dest** dest += (a * b)
.. c:function:: void glm_vec3_muladds(vec3 a, float s, vec3 dest)
| mul vector with scalar and add result to sum
| it applies += operator so dest must be initialized
Parameters:
| *[in]* **a** vector
| *[in]* **s** scalar
| *[out]* **dest** dest += (a * b)
.. c:function:: void glm_vec3_maxadd(vec3 a, vec3 b, vec3 dest)
| add max of two vector to result/dest
| it applies += operator so dest must be initialized
Parameters:
| *[in]* **a** vector 1
| *[in]* **b** vector 2
| *[out]* **dest** dest += (a * b)
.. c:function:: void glm_vec3_minadd(vec3 a, vec3 b, vec3 dest)
| add min of two vector to result/dest
| it applies += operator so dest must be initialized
Parameters:
| *[in]* **a** vector 1
| *[in]* **b** vector 2
| *[out]* **dest** dest += (a * b)
.. c:function:: void glm_vec3_flipsign(vec3 v)
**DEPRACATED!**
use :c:func:`glm_vec3_negate`
Parameters:
| *[in, out]* **v** vector
.. c:function:: void glm_vec3_flipsign_to(vec3 v, vec3 dest)
**DEPRACATED!**
use :c:func:`glm_vec3_negate_to`
Parameters:
| *[in]* **v** vector
| *[out]* **dest** negated vector
.. c:function:: void glm_vec3_inv(vec3 v)
**DEPRACATED!**
use :c:func:`glm_vec3_negate`
Parameters:
| *[in, out]* **v** vector
.. c:function:: void glm_vec3_inv_to(vec3 v, vec3 dest)
**DEPRACATED!**
use :c:func:`glm_vec3_negate_to`
Parameters:
| *[in]* **v** source
| *[out]* **dest** destination
.. c:function:: void glm_vec3_negate(vec3 v)
negate vector components
Parameters:
| *[in, out]* **v** vector
.. c:function:: void glm_vec3_negate_to(vec3 v, vec3 dest)
negate vector components and store result in dest
Parameters:
| *[in]* **v** vector
| *[out]* **dest** negated vector
.. c:function:: void glm_vec3_normalize(vec3 v)
normalize vec3 and store result in same vec
Parameters:
| *[in, out]* **v** vector
.. c:function:: void glm_vec3_normalize_to(vec3 vec, vec3 dest)
normalize vec3 to dest
Parameters:
| *[in]* **vec** source
| *[out]* **dest** destination
.. c:function:: float glm_vec3_angle(vec3 v1, vec3 v2)
angle betwen two vector
Parameters:
| *[in]* **v1** vector1
| *[in]* **v2** vector2
Return:
| angle as radians
.. c:function:: void glm_vec3_rotate(vec3 v, float angle, vec3 axis)
rotate vec3 around axis by angle using Rodrigues' rotation formula
Parameters:
| *[in, out]* **v** vector
| *[in]* **axis** axis vector (will be normalized)
| *[out]* **angle** angle (radians)
.. c:function:: void glm_vec3_rotate_m4(mat4 m, vec3 v, vec3 dest)
apply rotation matrix to vector
Parameters:
| *[in]* **m** affine matrix or rot matrix
| *[in]* **v** vector
| *[out]* **dest** rotated vector
.. c:function:: void glm_vec3_rotate_m3(mat3 m, vec3 v, vec3 dest)
apply rotation matrix to vector
Parameters:
| *[in]* **m** affine matrix or rot matrix
| *[in]* **v** vector
| *[out]* **dest** rotated vector
.. c:function:: void glm_vec3_proj(vec3 a, vec3 b, vec3 dest)
project a vector onto b vector
Parameters:
| *[in]* **a** vector1
| *[in]* **b** vector2
| *[out]* **dest** projected vector
.. c:function:: void glm_vec3_center(vec3 v1, vec3 v2, vec3 dest)
find center point of two vector
Parameters:
| *[in]* **v1** vector1
| *[in]* **v2** vector2
| *[out]* **dest** center point
.. c:function:: float glm_vec3_distance2(vec3 v1, vec3 v2)
squared distance between two vectors
Parameters:
| *[in]* **mat** vector1
| *[in]* **row1** vector2
Returns:
| squared distance (distance * distance)
.. c:function:: float glm_vec3_distance(vec3 v1, vec3 v2)
distance between two vectors
Parameters:
| *[in]* **mat** vector1
| *[in]* **row1** vector2
Returns:
| distance
.. c:function:: void glm_vec3_maxv(vec3 v1, vec3 v2, vec3 dest)
max values of vectors
Parameters:
| *[in]* **v1** vector1
| *[in]* **v2** vector2
| *[out]* **dest** destination
.. c:function:: void glm_vec3_minv(vec3 v1, vec3 v2, vec3 dest)
min values of vectors
Parameters:
| *[in]* **v1** vector1
| *[in]* **v2** vector2
| *[out]* **dest** destination
.. c:function:: void glm_vec3_ortho(vec3 v, vec3 dest)
possible orthogonal/perpendicular vector
Parameters:
| *[in]* **mat** vector
| *[out]* **dest** orthogonal/perpendicular vector
.. c:function:: void glm_vec3_clamp(vec3 v, float minVal, float maxVal)
constrain a value to lie between two further values
Parameters:
| *[in, out]* **v** vector
| *[in]* **minVal** minimum value
| *[in]* **maxVal** maximum value
.. c:function:: void glm_vec3_lerp(vec3 from, vec3 to, float t, vec3 dest)
linear interpolation between two vector
| formula: from + s * (to - from)
Parameters:
| *[in]* **from** from value
| *[in]* **to** to value
| *[in]* **t** interpolant (amount) clamped between 0 and 1
| *[out]* **dest** destination

138
docs/source/vec4-ext.rst Normal file
View File

@@ -0,0 +1,138 @@
.. default-domain:: C
vec4 extra
==========
Header: cglm/vec4-ext.h
There are some functions are in called in extra header. These are called extra
because they are not used like other functions in vec4.h in the future some of
these functions ma be moved to vec4 header.
Table of contents (click to go):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Functions:
1. :c:func:`glm_vec4_mulv`
#. :c:func:`glm_vec4_broadcast`
#. :c:func:`glm_vec4_eq`
#. :c:func:`glm_vec4_eq_eps`
#. :c:func:`glm_vec4_eq_all`
#. :c:func:`glm_vec4_eqv`
#. :c:func:`glm_vec4_eqv_eps`
#. :c:func:`glm_vec4_max`
#. :c:func:`glm_vec4_min`
Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~
.. c:function:: void glm_vec4_mulv(vec4 a, vec4 b, vec4 d)
multiplies individual items
Parameters:
| *[in]* **a** vec1
| *[in]* **b** vec2
| *[out]* **d** destination
.. c:function:: void glm_vec4_broadcast(float val, vec4 d)
fill a vector with specified value
Parameters:
| *[in]* **val** value
| *[out]* **dest** destination
.. c:function:: bool glm_vec4_eq(vec4 v, float val)
check if vector is equal to value (without epsilon)
Parameters:
| *[in]* **v** vector
| *[in]* **val** value
.. c:function:: bool glm_vec4_eq_eps(vec4 v, float val)
check if vector is equal to value (with epsilon)
Parameters:
| *[in]* **v** vector
| *[in]* **val** value
.. c:function:: bool glm_vec4_eq_all(vec4 v)
check if vectors members are equal (without epsilon)
Parameters:
| *[in]* **v** vector
.. c:function:: bool glm_vec4_eqv(vec4 v1, vec4 v2)
check if vector is equal to another (without epsilon) vector
Parameters:
| *[in]* **vec** vector 1
| *[in]* **vec** vector 2
.. c:function:: bool glm_vec4_eqv_eps(vec4 v1, vec4 v2)
check if vector is equal to another (with epsilon)
Parameters:
| *[in]* **v1** vector1
| *[in]* **v2** vector2
.. c:function:: float glm_vec4_max(vec4 v)
max value of vector
Parameters:
| *[in]* **v** vector
.. c:function:: float glm_vec4_min(vec4 v)
min value of vector
Parameters:
| *[in]* **v** vector
.. c:function:: bool glm_vec4_isnan(vec4 v)
| check if one of items is NaN (not a number)
| you should only use this in DEBUG mode or very critical asserts
Parameters:
| *[in]* **v** vector
.. c:function:: bool glm_vec4_isinf(vec4 v)
| check if one of items is INFINITY
| you should only use this in DEBUG mode or very critical asserts
Parameters:
| *[in]* **v** vector
.. c:function:: bool glm_vec4_isvalid(vec4 v)
| check if all items are valid number
| you should only use this in DEBUG mode or very critical asserts
Parameters:
| *[in]* **v** vector
.. c:function:: void glm_vec4_sign(vec4 v, vec4 dest)
get sign of 32 bit float as +1, -1, 0
Parameters:
| *[in]* **v** vector
| *[out]* **dest** sign vector (only keeps signs as -1, 0, -1)
.. c:function:: void glm_vec4_sqrt(vec4 v, vec4 dest)
square root of each vector item
Parameters:
| *[in]* **v** vector
| *[out]* **dest** destination vector (sqrt(v))

407
docs/source/vec4.rst Normal file
View File

@@ -0,0 +1,407 @@
.. default-domain:: C
vec4
====
Header: cglm/vec4.h
Table of contents (click to go):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Macros:
1. glm_vec4_dup3(v, dest)
#. glm_vec4_dup(v, dest)
#. GLM_VEC4_ONE_INIT
#. GLM_VEC4_BLACK_INIT
#. GLM_VEC4_ZERO_INIT
#. GLM_VEC4_ONE
#. GLM_VEC4_BLACK
#. GLM_VEC4_ZERO
Functions:
1. :c:func:`glm_vec4`
#. :c:func:`glm_vec4_copy3`
#. :c:func:`glm_vec4_copy`
#. :c:func:`glm_vec4_ucopy`
#. :c:func:`glm_vec4_zero`
#. :c:func:`glm_vec4_one`
#. :c:func:`glm_vec4_dot`
#. :c:func:`glm_vec4_norm2`
#. :c:func:`glm_vec4_norm`
#. :c:func:`glm_vec4_add`
#. :c:func:`glm_vec4_adds`
#. :c:func:`glm_vec4_sub`
#. :c:func:`glm_vec4_subs`
#. :c:func:`glm_vec4_mul`
#. :c:func:`glm_vec4_scale`
#. :c:func:`glm_vec4_scale_as`
#. :c:func:`glm_vec4_div`
#. :c:func:`glm_vec4_divs`
#. :c:func:`glm_vec4_addadd`
#. :c:func:`glm_vec4_subadd`
#. :c:func:`glm_vec4_muladd`
#. :c:func:`glm_vec4_muladds`
#. :c:func:`glm_vec4_maxadd`
#. :c:func:`glm_vec4_minadd`
#. :c:func:`glm_vec4_flipsign`
#. :c:func:`glm_vec4_flipsign_to`
#. :c:func:`glm_vec4_inv`
#. :c:func:`glm_vec4_inv_to`
#. :c:func:`glm_vec4_negate`
#. :c:func:`glm_vec4_negate_to`
#. :c:func:`glm_vec4_normalize`
#. :c:func:`glm_vec4_normalize_to`
#. :c:func:`glm_vec4_distance`
#. :c:func:`glm_vec4_maxv`
#. :c:func:`glm_vec4_minv`
#. :c:func:`glm_vec4_clamp`
#. :c:func:`glm_vec4_lerp`
#. :c:func:`glm_vec4_cubic`
Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~
.. c:function:: void glm_vec4(vec3 v3, float last, vec4 dest)
init vec4 using vec3, since you are initializing vec4 with vec3
you need to set last item. cglm could set it zero but making it parameter
gives more control
Parameters:
| *[in]* **v3** vector4
| *[in]* **last** last item of vec4
| *[out]* **dest** destination
.. c:function:: void glm_vec4_copy3(vec4 a, vec3 dest)
copy first 3 members of [a] to [dest]
Parameters:
| *[in]* **a** source
| *[out]* **dest** destination
.. c:function:: void glm_vec4_copy(vec4 v, vec4 dest)
copy all members of [a] to [dest]
Parameters:
| *[in]* **v** source
| *[in]* **dest** destination
.. c:function:: void glm_vec4_ucopy(vec4 v, vec4 dest)
copy all members of [a] to [dest]
| alignment is not required
Parameters:
| *[in]* **v** source
| *[in]* **dest** destination
.. c:function:: void glm_vec4_zero(vec4 v)
makes all members zero
Parameters:
| *[in, out]* **v** vector
.. c:function:: float glm_vec4_dot(vec4 a, vec4 b)
dot product of vec4
Parameters:
| *[in]* **a** vector1
| *[in]* **b** vector2
Returns:
dot product
.. c:function:: float glm_vec4_norm2(vec4 v)
norm * norm (magnitude) of vector
we can use this func instead of calling norm * norm, because it would call
sqrtf fuction twice but with this func we can avoid func call, maybe this is
not good name for this func
Parameters:
| *[in]* **v** vector
Returns:
square of norm / magnitude
.. c:function:: float glm_vec4_norm(vec4 vec)
norm (magnitude) of vec4
Parameters:
| *[in]* **vec** vector
.. c:function:: void glm_vec4_add(vec4 a, vec4 b, vec4 dest)
add a vector to b vector store result in dest
Parameters:
| *[in]* **a** vector1
| *[in]* **b** vector2
| *[out]* **dest** destination vector
.. c:function:: void glm_vec4_adds(vec4 v, float s, vec4 dest)
add scalar to v vector store result in dest (d = v + vec(s))
Parameters:
| *[in]* **v** vector
| *[in]* **s** scalar
| *[out]* **dest** destination vector
.. c:function:: void glm_vec4_sub(vec4 a, vec4 b, vec4 dest)
subtract b vector from a vector store result in dest (d = v1 - v2)
Parameters:
| *[in]* **a** vector1
| *[in]* **b** vector2
| *[out]* **dest** destination vector
.. c:function:: void glm_vec4_subs(vec4 v, float s, vec4 dest)
subtract scalar from v vector store result in dest (d = v - vec(s))
Parameters:
| *[in]* **v** vector
| *[in]* **s** scalar
| *[out]* **dest** destination vector
.. c:function:: void glm_vec4_mul(vec4 a, vec4 b, vec4 d)
multiply two vector (component-wise multiplication)
Parameters:
| *[in]* **a** vector1
| *[in]* **b** vector2
| *[out]* **dest** result = (a[0] * b[0], a[1] * b[1], a[2] * b[2], a[3] * b[3])
.. c:function:: void glm_vec4_scale(vec4 v, float s, vec4 dest)
multiply/scale vec4 vector with scalar: result = v * s
Parameters:
| *[in]* **v** vector
| *[in]* **s** scalar
| *[out]* **dest** destination vector
.. c:function:: void glm_vec4_scale_as(vec4 v, float s, vec4 dest)
make vec4 vector scale as specified: result = unit(v) * s
Parameters:
| *[in]* **v** vector
| *[in]* **s** scalar
| *[out]* **dest** destination vector
.. c:function:: void glm_vec4_div(vec4 a, vec4 b, vec4 dest)
div vector with another component-wise division: d = v1 / v2
Parameters:
| *[in]* **a** vector1
| *[in]* **b** vector2
| *[out]* **dest** result = (a[0] / b[0], a[1] / b[1], a[2] / b[2], a[3] / b[3])
.. c:function:: void glm_vec4_divs(vec4 v, float s, vec4 dest)
div vector with scalar: d = v / s
Parameters:
| *[in]* **v** vector
| *[in]* **s** scalar
| *[out]* **dest** result = (a[0] / s, a[1] / s, a[2] / s, a[3] / s)
.. c:function:: void glm_vec4_addadd(vec4 a, vec4 b, vec4 dest)
| add two vectors and add result to sum
| it applies += operator so dest must be initialized
Parameters:
| *[in]* **a** vector 1
| *[in]* **b** vector 2
| *[out]* **dest** dest += (a + b)
.. c:function:: void glm_vec4_subadd(vec4 a, vec4 b, vec4 dest)
| sub two vectors and add result to sum
| it applies += operator so dest must be initialized
Parameters:
| *[in]* **a** vector 1
| *[in]* **b** vector 2
| *[out]* **dest** dest += (a - b)
.. c:function:: void glm_vec4_muladd(vec4 a, vec4 b, vec4 dest)
| mul two vectors and add result to sum
| it applies += operator so dest must be initialized
Parameters:
| *[in]* **a** vector 1
| *[in]* **b** vector 2
| *[out]* **dest** dest += (a * b)
.. c:function:: void glm_vec4_muladds(vec4 a, float s, vec4 dest)
| mul vector with scalar and add result to sum
| it applies += operator so dest must be initialized
Parameters:
| *[in]* **a** vector
| *[in]* **s** scalar
| *[out]* **dest** dest += (a * b)
.. c:function:: void glm_vec4_maxadd(vec4 a, vec4 b, vec4 dest)
| add max of two vector to result/dest
| it applies += operator so dest must be initialized
Parameters:
| *[in]* **a** vector 1
| *[in]* **b** vector 2
| *[out]* **dest** dest += (a * b)
.. c:function:: void glm_vec4_minadd(vec4 a, vec4 b, vec4 dest)
| add min of two vector to result/dest
| it applies += operator so dest must be initialized
Parameters:
| *[in]* **a** vector 1
| *[in]* **b** vector 2
| *[out]* **dest** dest += (a * b)
.. c:function:: void glm_vec4_flipsign(vec4 v)
**DEPRACATED!**
use :c:func:`glm_vec4_negate`
Parameters:
| *[in, out]* **v** vector
.. c:function:: void glm_vec4_flipsign_to(vec4 v, vec4 dest)
**DEPRACATED!**
use :c:func:`glm_vec4_negate_to`
Parameters:
| *[in]* **v** vector
| *[out]* **dest** negated vector
.. c:function:: void glm_vec4_inv(vec4 v)
**DEPRACATED!**
use :c:func:`glm_vec4_negate`
Parameters:
| *[in, out]* **v** vector
.. c:function:: void glm_vec4_inv_to(vec4 v, vec4 dest)
**DEPRACATED!**
use :c:func:`glm_vec4_negate_to`
Parameters:
| *[in]* **v** source
| *[out]* **dest** destination
.. c:function:: void glm_vec4_negate(vec4 v)
negate vector components
Parameters:
| *[in, out]* **v** vector
.. c:function:: void glm_vec4_negate_to(vec4 v, vec4 dest)
negate vector components and store result in dest
Parameters:
| *[in]* **v** vector
| *[out]* **dest** negated vector
.. c:function:: void glm_vec4_normalize(vec4 v)
normalize vec4 and store result in same vec
Parameters:
| *[in, out]* **v** vector
.. c:function:: void glm_vec4_normalize_to(vec4 vec, vec4 dest)
normalize vec4 to dest
Parameters:
| *[in]* **vec** source
| *[out]* **dest** destination
.. c:function:: float glm_vec4_distance(vec4 v1, vec4 v2)
distance between two vectors
Parameters:
| *[in]* **mat** vector1
| *[in]* **row1** vector2
Returns:
| distance
.. c:function:: void glm_vec4_maxv(vec4 v1, vec4 v2, vec4 dest)
max values of vectors
Parameters:
| *[in]* **v1** vector1
| *[in]* **v2** vector2
| *[out]* **dest** destination
.. c:function:: void glm_vec4_minv(vec4 v1, vec4 v2, vec4 dest)
min values of vectors
Parameters:
| *[in]* **v1** vector1
| *[in]* **v2** vector2
| *[out]* **dest** destination
.. c:function:: void glm_vec4_clamp(vec4 v, float minVal, float maxVal)
constrain a value to lie between two further values
Parameters:
| *[in, out]* **v** vector
| *[in]* **minVal** minimum value
| *[in]* **maxVal** maximum value
.. c:function:: void glm_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest)
linear interpolation between two vector
| formula: from + s * (to - from)
Parameters:
| *[in]* **from** from value
| *[in]* **to** to value
| *[in]* **t** interpolant (amount) clamped between 0 and 1
| *[out]* **dest** destination
.. c:function:: void glm_vec4_cubic(float s, vec4 dest)
helper to fill vec4 as [S^3, S^2, S, 1]
Parameters:
| *[in]* **s** parameter
| *[out]* **dest** destination

View File

@@ -16,6 +16,7 @@
#include "common.h"
#include "mat4.h"
#include "mat3.h"
#ifdef CGLM_SSE_FP
# include "simd/sse2/affine.h"
@@ -81,6 +82,59 @@ glm_mul(mat4 m1, mat4 m2, mat4 dest) {
#endif
}
/*!
* @brief this is similar to glm_mat4_mul but specialized to affine transform
*
* Right Matrix format should be:
* R R R 0
* R R R 0
* R R R 0
* 0 0 0 1
*
* this reduces some multiplications. It should be faster than mat4_mul.
* if you are not sure about matrix format then DON'T use this! use mat4_mul
*
* @param[in] m1 affine matrix 1
* @param[in] m2 affine matrix 2
* @param[out] dest result matrix
*/
CGLM_INLINE
void
glm_mul_rot(mat4 m1, mat4 m2, mat4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
glm_mul_rot_sse2(m1, m2, dest);
#else
float a00 = m1[0][0], a01 = m1[0][1], a02 = m1[0][2], a03 = m1[0][3],
a10 = m1[1][0], a11 = m1[1][1], a12 = m1[1][2], a13 = m1[1][3],
a20 = m1[2][0], a21 = m1[2][1], a22 = m1[2][2], a23 = m1[2][3],
a30 = m1[3][0], a31 = m1[3][1], a32 = m1[3][2], a33 = m1[3][3],
b00 = m2[0][0], b01 = m2[0][1], b02 = m2[0][2],
b10 = m2[1][0], b11 = m2[1][1], b12 = m2[1][2],
b20 = m2[2][0], b21 = m2[2][1], b22 = m2[2][2];
dest[0][0] = a00 * b00 + a10 * b01 + a20 * b02;
dest[0][1] = a01 * b00 + a11 * b01 + a21 * b02;
dest[0][2] = a02 * b00 + a12 * b01 + a22 * b02;
dest[0][3] = a03 * b00 + a13 * b01 + a23 * b02;
dest[1][0] = a00 * b10 + a10 * b11 + a20 * b12;
dest[1][1] = a01 * b10 + a11 * b11 + a21 * b12;
dest[1][2] = a02 * b10 + a12 * b11 + a22 * b12;
dest[1][3] = a03 * b10 + a13 * b11 + a23 * b12;
dest[2][0] = a00 * b20 + a10 * b21 + a20 * b22;
dest[2][1] = a01 * b20 + a11 * b21 + a21 * b22;
dest[2][2] = a02 * b20 + a12 * b21 + a22 * b22;
dest[2][3] = a03 * b20 + a13 * b21 + a23 * b22;
dest[3][0] = a30;
dest[3][1] = a31;
dest[3][2] = a32;
dest[3][3] = a33;
#endif
}
/*!
* @brief inverse orthonormal rotation + translation matrix (ridig-body)
*
@@ -97,8 +151,8 @@ glm_inv_tr(mat4 mat) {
#if defined( __SSE__ ) || defined( __SSE2__ )
glm_inv_tr_sse2(mat);
#else
CGLM_ALIGN(16) mat3 r;
CGLM_ALIGN(16) vec3 t;
CGLM_ALIGN_MAT mat3 r;
CGLM_ALIGN(8) vec3 t;
/* rotate */
glm_mat4_pick3t(mat, r);
@@ -106,8 +160,8 @@ glm_inv_tr(mat4 mat) {
/* translate */
glm_mat3_mulv(r, mat[3], t);
glm_vec_flipsign(t);
glm_vec_copy(t, mat[3]);
glm_vec3_negate(t);
glm_vec3_copy(t, mat[3]);
#endif
}

View File

@@ -16,15 +16,14 @@
CGLM_INLINE void glm_scale_to(mat4 m, vec3 v, mat4 dest);
CGLM_INLINE void glm_scale_make(mat4 m, vec3 v);
CGLM_INLINE void glm_scale(mat4 m, vec3 v);
CGLM_INLINE void glm_scale1(mat4 m, float s);
CGLM_INLINE void glm_scale_uni(mat4 m, float s);
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_ndc_make(mat4 m, float angle, vec3 axis_ndc);
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);
@@ -35,51 +34,15 @@
#define cglm_affine_h
#include "common.h"
#include "vec4.h"
#include "affine-mat.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 store result in dest
*
* @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) {
mat4 t = GLM_MAT4_IDENTITY_INIT;
#if defined( __SSE__ ) || defined( __SSE2__ )
_mm_store_ps(dest[3],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_load_ps(t[0]),
_mm_set1_ps(v[0])),
_mm_mul_ps(_mm_load_ps(t[1]),
_mm_set1_ps(v[1]))),
_mm_add_ps(_mm_mul_ps(_mm_load_ps(t[2]),
_mm_set1_ps(v[2])),
_mm_load_ps(t[3]))))
;
_mm_store_ps(dest[0], _mm_load_ps(m[0]));
_mm_store_ps(dest[1], _mm_load_ps(m[1]));
_mm_store_ps(dest[2], _mm_load_ps(m[2]));
#else
vec4 v1, v2, v3;
glm_vec4_scale(t[0], v[0], v1);
glm_vec4_scale(t[1], v[1], v2);
glm_vec4_scale(t[2], v[2], v3);
glm_vec4_add(v1, t[3], t[3]);
glm_vec4_add(v2, t[3], t[3]);
glm_vec4_add(v3, t[3], t[3]);
glm__memcpy(float, dest, t, sizeof(mat4));
#endif
}
glm_mat4_mul(mat4 m1, mat4 m2, mat4 dest);
/*!
* @brief translate existing transform matrix by v vector
@@ -92,14 +55,14 @@ CGLM_INLINE
void
glm_translate(mat4 m, vec3 v) {
#if defined( __SSE__ ) || defined( __SSE2__ )
_mm_store_ps(m[3],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_load_ps(m[0]),
_mm_set1_ps(v[0])),
_mm_mul_ps(_mm_load_ps(m[1]),
_mm_set1_ps(v[1]))),
_mm_add_ps(_mm_mul_ps(_mm_load_ps(m[2]),
_mm_set1_ps(v[2])),
_mm_load_ps(m[3]))))
glmm_store(m[3],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_load(m[0]),
_mm_set1_ps(v[0])),
_mm_mul_ps(glmm_load(m[1]),
_mm_set1_ps(v[1]))),
_mm_add_ps(_mm_mul_ps(glmm_load(m[2]),
_mm_set1_ps(v[2])),
glmm_load(m[3]))))
;
#else
vec4 v1, v2, v3;
@@ -114,6 +77,23 @@ glm_translate(mat4 m, vec3 v) {
#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
*
@@ -124,10 +104,10 @@ CGLM_INLINE
void
glm_translate_x(mat4 m, float x) {
#if defined( __SSE__ ) || defined( __SSE2__ )
_mm_store_ps(m[3],
_mm_add_ps(_mm_mul_ps(_mm_load_ps(m[0]),
_mm_set1_ps(x)),
_mm_load_ps(m[3])))
glmm_store(m[3],
_mm_add_ps(_mm_mul_ps(glmm_load(m[0]),
_mm_set1_ps(x)),
glmm_load(m[3])))
;
#else
vec4 v1;
@@ -146,10 +126,10 @@ CGLM_INLINE
void
glm_translate_y(mat4 m, float y) {
#if defined( __SSE__ ) || defined( __SSE2__ )
_mm_store_ps(m[3],
_mm_add_ps(_mm_mul_ps(_mm_load_ps(m[1]),
_mm_set1_ps(y)),
_mm_load_ps(m[3])))
glmm_store(m[3],
_mm_add_ps(_mm_mul_ps(glmm_load(m[1]),
_mm_set1_ps(y)),
glmm_load(m[3])))
;
#else
vec4 v1;
@@ -168,10 +148,10 @@ CGLM_INLINE
void
glm_translate_z(mat4 m, float z) {
#if defined( __SSE__ ) || defined( __SSE2__ )
_mm_store_ps(m[3],
_mm_add_ps(_mm_mul_ps(_mm_load_ps(m[2]),
_mm_set1_ps(z)),
_mm_load_ps(m[3])))
glmm_store(m[3],
_mm_add_ps(_mm_mul_ps(glmm_load(m[2]),
_mm_set1_ps(z)),
glmm_load(m[3])))
;
#else
vec4 v1;
@@ -189,8 +169,8 @@ glm_translate_z(mat4 m, float z) {
CGLM_INLINE
void
glm_translate_make(mat4 m, vec3 v) {
mat4 t = GLM_MAT4_IDENTITY_INIT;
glm_translate_to(t, v, m);
glm_mat4_identity(m);
glm_vec3_copy(v, m[3]);
}
/*!
@@ -220,8 +200,10 @@ glm_scale_to(mat4 m, vec3 v, mat4 dest) {
CGLM_INLINE
void
glm_scale_make(mat4 m, vec3 v) {
mat4 t = GLM_MAT4_IDENTITY_INIT;
glm_scale_to(t, v, m);
glm_mat4_identity(m);
m[0][0] = v[0];
m[1][1] = v[1];
m[2][2] = v[2];
}
/*!
@@ -237,16 +219,6 @@ glm_scale(mat4 m, vec3 v) {
glm_scale_to(m, v, m);
}
/*!
* @brief DEPRECATED! Use glm_scale_uni
*/
CGLM_INLINE
void
glm_scale1(mat4 m, float s) {
vec3 v = { s, s, s };
glm_scale_to(m, v, m);
}
/*!
* @brief applies uniform scale to existing transform matrix v = [s, s, s]
* and stores result in same matrix
@@ -257,7 +229,7 @@ glm_scale1(mat4 m, float s) {
CGLM_INLINE
void
glm_scale_uni(mat4 m, float s) {
vec3 v = { s, s, s };
CGLM_ALIGN(8) vec3 v = { s, s, s };
glm_scale_to(m, v, m);
}
@@ -272,19 +244,18 @@ glm_scale_uni(mat4 m, float s) {
CGLM_INLINE
void
glm_rotate_x(mat4 m, float angle, mat4 dest) {
float cosVal;
float sinVal;
mat4 t = GLM_MAT4_IDENTITY_INIT;
CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT;
float c, s;
cosVal = cosf(angle);
sinVal = sinf(angle);
c = cosf(angle);
s = sinf(angle);
t[1][1] = cosVal;
t[1][2] = sinVal;
t[2][1] = -sinVal;
t[2][2] = cosVal;
t[1][1] = c;
t[1][2] = s;
t[2][1] = -s;
t[2][2] = c;
glm_mat4_mul(m, t, dest);
glm_mul_rot(m, t, dest);
}
/*!
@@ -298,19 +269,18 @@ glm_rotate_x(mat4 m, float angle, mat4 dest) {
CGLM_INLINE
void
glm_rotate_y(mat4 m, float angle, mat4 dest) {
float cosVal;
float sinVal;
mat4 t = GLM_MAT4_IDENTITY_INIT;
CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT;
float c, s;
cosVal = cosf(angle);
sinVal = sinf(angle);
c = cosf(angle);
s = sinf(angle);
t[0][0] = cosVal;
t[0][2] = -sinVal;
t[2][0] = sinVal;
t[2][2] = cosVal;
t[0][0] = c;
t[0][2] = -s;
t[2][0] = s;
t[2][2] = c;
glm_mat4_mul(m, t, dest);
glm_mul_rot(m, t, dest);
}
/*!
@@ -324,67 +294,24 @@ glm_rotate_y(mat4 m, float angle, mat4 dest) {
CGLM_INLINE
void
glm_rotate_z(mat4 m, float angle, mat4 dest) {
float cosVal;
float sinVal;
mat4 t = GLM_MAT4_IDENTITY_INIT;
cosVal = cosf(angle);
sinVal = sinf(angle);
t[0][0] = cosVal;
t[0][1] = sinVal;
t[1][0] = -sinVal;
t[1][1] = cosVal;
glm_mat4_mul(m, t, dest);
}
/*!
* @brief creates NEW rotation matrix by angle and axis
*
* this name may change in the future. axis must be is normalized
*
* @param[out] m affine transfrom
* @param[in] angle angle (radians)
* @param[in] axis_ndc normalized axis
*/
CGLM_INLINE
void
glm_rotate_ndc_make(mat4 m, float angle, vec3 axis_ndc) {
/* https://www.opengl.org/sdk/docs/man2/xhtml/glRotate.xml */
vec3 v, vs;
float c;
CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT;
float c, s;
c = cosf(angle);
s = sinf(angle);
glm_vec_scale(axis_ndc, 1.0f - c, v);
glm_vec_scale(axis_ndc, sinf(angle), vs);
t[0][0] = c;
t[0][1] = s;
t[1][0] = -s;
t[1][1] = c;
glm_vec_scale(axis_ndc, v[0], m[0]);
glm_vec_scale(axis_ndc, v[1], m[1]);
glm_vec_scale(axis_ndc, v[2], m[2]);
m[0][0] += c;
m[0][1] += vs[2];
m[0][2] -= vs[1];
m[1][0] -= vs[2];
m[1][1] += c;
m[1][2] += vs[0];
m[2][0] += vs[1];
m[2][1] -= vs[0];
m[2][2] += c;
m[0][3] = m[1][3] = m[2][3] = m[3][0] = m[3][1] = m[3][2] = 0.0f;
m[3][3] = 1.0f;
glm_mul_rot(m, t, dest);
}
/*!
* @brief creates NEW rotation matrix by angle and axis
*
* this name may change in the future. axis must be is normalized
* axis will be normalized so you don't need to normalize it
*
* @param[out] m affine transfrom
* @param[in] angle angle (radians)
@@ -393,53 +320,29 @@ glm_rotate_ndc_make(mat4 m, float angle, vec3 axis_ndc) {
CGLM_INLINE
void
glm_rotate_make(mat4 m, float angle, vec3 axis) {
vec3 axis_ndc;
CGLM_ALIGN(8) vec3 axisn, v, vs;
float c;
glm_vec_normalize_to(axis, axis_ndc);
glm_rotate_ndc_make(m, angle, axis_ndc);
c = cosf(angle);
glm_vec3_normalize_to(axis, axisn);
glm_vec3_scale(axisn, 1.0f - c, v);
glm_vec3_scale(axisn, sinf(angle), vs);
glm_vec3_scale(axisn, v[0], m[0]);
glm_vec3_scale(axisn, v[1], m[1]);
glm_vec3_scale(axisn, v[2], m[2]);
m[0][0] += c; m[1][0] -= vs[2]; m[2][0] += vs[1];
m[0][1] += vs[2]; m[1][1] += c; m[2][1] -= vs[0];
m[0][2] -= vs[1]; m[1][2] += vs[0]; m[2][2] += c;
m[0][3] = m[1][3] = m[2][3] = m[3][0] = m[3][1] = m[3][2] = 0.0f;
m[3][3] = 1.0f;
}
/*!
* @brief rotate existing transform matrix around Z axis by angle and axis
*
* this name may change in the future, axis must be normalized.
*
* @param[in, out] m affine transfrom
* @param[in] angle angle (radians)
* @param[in] axis_ndc normalized axis
*/
CGLM_INLINE
void
glm_rotate_ndc(mat4 m, float angle, vec3 axis_ndc) {
mat4 rot, tmp;
glm_rotate_ndc_make(rot, angle, axis_ndc);
glm_vec4_scale(m[0], rot[0][0], tmp[1]);
glm_vec4_scale(m[1], rot[0][1], tmp[0]);
glm_vec4_add(tmp[1], tmp[0], tmp[1]);
glm_vec4_scale(m[2], rot[0][2], tmp[0]);
glm_vec4_add(tmp[1], tmp[0], tmp[1]);
glm_vec4_scale(m[0], rot[1][0], tmp[2]);
glm_vec4_scale(m[1], rot[1][1], tmp[0]);
glm_vec4_add(tmp[2], tmp[0], tmp[2]);
glm_vec4_scale(m[2], rot[1][2], tmp[0]);
glm_vec4_add(tmp[2], tmp[0], tmp[2]);
glm_vec4_scale(m[0], rot[2][0], tmp[3]);
glm_vec4_scale(m[1], rot[2][1], tmp[0]);
glm_vec4_add(tmp[3], tmp[0], tmp[3]);
glm_vec4_scale(m[2], rot[2][2], tmp[0]);
glm_vec4_add(tmp[3], tmp[0], tmp[3]);
glm_vec4_copy(tmp[1], m[0]);
glm_vec4_copy(tmp[2], m[1]);
glm_vec4_copy(tmp[3], m[2]);
}
/*!
* @brief rotate existing transform matrix around Z axis by angle and axis
* @brief rotate existing transform matrix around given axis by angle
*
* @param[in, out] m affine transfrom
* @param[in] angle angle (radians)
@@ -448,10 +351,55 @@ glm_rotate_ndc(mat4 m, float angle, vec3 axis_ndc) {
CGLM_INLINE
void
glm_rotate(mat4 m, float angle, vec3 axis) {
vec3 axis_ndc;
CGLM_ALIGN_MAT mat4 rot;
glm_rotate_make(rot, angle, axis);
glm_mul_rot(m, rot, m);
}
glm_vec_normalize_to(axis, axis_ndc);
glm_rotate_ndc(m, angle, axis_ndc);
/*!
* @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);
}
/*!
@@ -463,13 +411,13 @@ glm_rotate(mat4 m, float angle, vec3 axis) {
CGLM_INLINE
void
glm_decompose_scalev(mat4 m, vec3 s) {
s[0] = glm_vec_norm(m[0]);
s[1] = glm_vec_norm(m[1]);
s[2] = glm_vec_norm(m[2]);
s[0] = glm_vec3_norm(m[0]);
s[1] = glm_vec3_norm(m[1]);
s[2] = glm_vec3_norm(m[2]);
}
/*!
* @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
@@ -479,10 +427,9 @@ glm_decompose_scalev(mat4 m, vec3 s) {
CGLM_INLINE
bool
glm_uniscaled(mat4 m) {
vec3 s;
CGLM_ALIGN(8) vec3 s;
glm_decompose_scalev(m, s);
return glm_vec_eq_all(s);
return glm_vec3_eq_all(s);
}
/*!
@@ -496,17 +443,17 @@ glm_uniscaled(mat4 m) {
CGLM_INLINE
void
glm_decompose_rs(mat4 m, mat4 r, vec3 s) {
vec4 t = {0.0f, 0.0f, 0.0f, 1.0f};
vec3 v;
CGLM_ALIGN(16) vec4 t = {0.0f, 0.0f, 0.0f, 1.0f};
CGLM_ALIGN(8) vec3 v;
glm_vec4_copy(m[0], r[0]);
glm_vec4_copy(m[1], r[1]);
glm_vec4_copy(m[2], r[2]);
glm_vec4_copy(t, r[3]);
s[0] = glm_vec_norm(m[0]);
s[1] = glm_vec_norm(m[1]);
s[2] = glm_vec_norm(m[2]);
s[0] = glm_vec3_norm(m[0]);
s[1] = glm_vec3_norm(m[1]);
s[2] = glm_vec3_norm(m[2]);
glm_vec4_scale(r[0], 1.0f/s[0], r[0]);
glm_vec4_scale(r[1], 1.0f/s[1], r[1]);
@@ -515,12 +462,12 @@ glm_decompose_rs(mat4 m, mat4 r, vec3 s) {
/* Note from Apple Open Source (asume that the matrix is orthonormal):
check for a coordinate system flip. If the determinant
is -1, then negate the matrix and the scaling factors. */
glm_vec_cross(m[0], m[1], v);
if (glm_vec_dot(v, m[2]) < 0.0f) {
glm_vec4_flipsign(r[0]);
glm_vec4_flipsign(r[1]);
glm_vec4_flipsign(r[2]);
glm_vec_flipsign(s);
glm_vec3_cross(m[0], m[1], v);
if (glm_vec3_dot(v, m[2]) < 0.0f) {
glm_vec4_negate(r[0]);
glm_vec4_negate(r[1]);
glm_vec4_negate(r[2]);
glm_vec3_negate(s);
}
}

154
include/cglm/bezier.h Normal file
View File

@@ -0,0 +1,154 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglm_bezier_h
#define cglm_bezier_h
#include "common.h"
#define GLM_BEZIER_MAT_INIT {{-1.0f, 3.0f, -3.0f, 1.0f}, \
{ 3.0f, -6.0f, 3.0f, 0.0f}, \
{-3.0f, 3.0f, 0.0f, 0.0f}, \
{ 1.0f, 0.0f, 0.0f, 0.0f}}
#define GLM_HERMITE_MAT_INIT {{ 2.0f, -3.0f, 0.0f, 1.0f}, \
{-2.0f, 3.0f, 0.0f, 0.0f}, \
{ 1.0f, -2.0f, 1.0f, 0.0f}, \
{ 1.0f, -1.0f, 0.0f, 0.0f}}
/* for C only */
#define GLM_BEZIER_MAT ((mat4)GLM_BEZIER_MAT_INIT)
#define GLM_HERMITE_MAT ((mat4)GLM_HERMITE_MAT_INIT)
#define CGLM_DECASTEL_EPS 1e-9
#define CGLM_DECASTEL_MAX 1000
#define CGLM_DECASTEL_SMALL 1e-20
/*!
* @brief cubic bezier interpolation
*
* Formula:
* B(s) = P0*(1-s)^3 + 3*C0*s*(1-s)^2 + 3*C1*s^2*(1-s) + P1*s^3
*
* similar result using matrix:
* B(s) = glm_smc(t, GLM_BEZIER_MAT, (vec4){p0, c0, c1, p1})
*
* glm_eq(glm_smc(...), glm_bezier(...)) should return TRUE
*
* @param[in] s parameter between 0 and 1
* @param[in] p0 begin point
* @param[in] c0 control point 1
* @param[in] c1 control point 2
* @param[in] p1 end point
*
* @return B(s)
*/
CGLM_INLINE
float
glm_bezier(float s, float p0, float c0, float c1, float p1) {
float x, xx, ss, xs3, a;
x = 1.0f - s;
xx = x * x;
ss = s * s;
xs3 = (s - ss) * 3.0f;
a = p0 * xx + c0 * xs3;
return a + s * (c1 * xs3 + p1 * ss - a);
}
/*!
* @brief cubic hermite interpolation
*
* Formula:
* H(s) = P0*(2*s^3 - 3*s^2 + 1) + T0*(s^3 - 2*s^2 + s)
* + P1*(-2*s^3 + 3*s^2) + T1*(s^3 - s^2)
*
* similar result using matrix:
* H(s) = glm_smc(t, GLM_HERMITE_MAT, (vec4){p0, p1, c0, c1})
*
* glm_eq(glm_smc(...), glm_hermite(...)) should return TRUE
*
* @param[in] s parameter between 0 and 1
* @param[in] p0 begin point
* @param[in] t0 tangent 1
* @param[in] t1 tangent 2
* @param[in] p1 end point
*
* @return H(s)
*/
CGLM_INLINE
float
glm_hermite(float s, float p0, float t0, float t1, float p1) {
float ss, d, a, b, c, e, f;
ss = s * s;
a = ss + ss;
c = a + ss;
b = a * s;
d = s * ss;
f = d - ss;
e = b - c;
return p0 * (e + 1.0f) + t0 * (f - ss + s) + t1 * f - p1 * e;
}
/*!
* @brief iterative way to solve cubic equation
*
* @param[in] prm parameter between 0 and 1
* @param[in] p0 begin point
* @param[in] c0 control point 1
* @param[in] c1 control point 2
* @param[in] p1 end point
*
* @return parameter to use in cubic equation
*/
CGLM_INLINE
float
glm_decasteljau(float prm, float p0, float c0, float c1, float p1) {
float u, v, a, b, c, d, e, f;
int i;
if (prm - p0 < CGLM_DECASTEL_SMALL)
return 0.0f;
if (p1 - prm < CGLM_DECASTEL_SMALL)
return 1.0f;
u = 0.0f;
v = 1.0f;
for (i = 0; i < CGLM_DECASTEL_MAX; i++) {
/* de Casteljau Subdivision */
a = (p0 + c0) * 0.5f;
b = (c0 + c1) * 0.5f;
c = (c1 + p1) * 0.5f;
d = (a + b) * 0.5f;
e = (b + c) * 0.5f;
f = (d + e) * 0.5f; /* this one is on the curve! */
/* The curve point is close enough to our wanted t */
if (fabsf(f - prm) < CGLM_DECASTEL_EPS)
return glm_clamp_zo((u + v) * 0.5f);
/* dichotomy */
if (f < prm) {
p0 = f;
c0 = e;
c1 = c;
u = (u + v) * 0.5f;
} else {
c0 = a;
c1 = d;
p1 = f;
v = (u + v) * 0.5f;
}
}
return glm_clamp_zo((u + v) * 0.5f);
}
#endif /* cglm_bezier_h */

View File

@@ -11,6 +11,7 @@
#include "common.h"
#include "vec3.h"
#include "vec4.h"
#include "util.h"
/*!
* @brief apply transform to Axis-Aligned Bounding Box
@@ -22,35 +23,31 @@
CGLM_INLINE
void
glm_aabb_transform(vec3 box[2], mat4 m, vec3 dest[2]) {
vec3 v[2], xa, xb, ya, yb, za, zb, tmp;
vec3 v[2], xa, xb, ya, yb, za, zb;
glm_vec_scale(m[0], box[0][0], xa);
glm_vec_scale(m[0], box[1][0], xb);
glm_vec3_scale(m[0], box[0][0], xa);
glm_vec3_scale(m[0], box[1][0], xb);
glm_vec_scale(m[1], box[0][1], ya);
glm_vec_scale(m[1], box[1][1], yb);
glm_vec3_scale(m[1], box[0][1], ya);
glm_vec3_scale(m[1], box[1][1], yb);
glm_vec_scale(m[2], box[0][2], za);
glm_vec_scale(m[2], box[1][2], zb);
glm_vec3_scale(m[2], box[0][2], za);
glm_vec3_scale(m[2], box[1][2], zb);
/* min(xa, xb) + min(ya, yb) + min(za, zb) + translation */
glm_vec_minv(xa, xb, v[0]);
glm_vec_minv(ya, yb, tmp);
glm_vec_add(v[0], tmp, v[0]);
glm_vec_minv(za, zb, tmp);
glm_vec_add(v[0], tmp, v[0]);
glm_vec_add(v[0], m[3], v[0]);
/* translation + min(xa, xb) + min(ya, yb) + min(za, zb) */
glm_vec3(m[3], v[0]);
glm_vec3_minadd(xa, xb, v[0]);
glm_vec3_minadd(ya, yb, v[0]);
glm_vec3_minadd(za, zb, v[0]);
/* max(xa, xb) + max(ya, yb) + max(za, zb) + translation */
glm_vec_maxv(xa, xb, v[1]);
glm_vec_maxv(ya, yb, tmp);
glm_vec_add(v[1], tmp, v[1]);
glm_vec_maxv(za, zb, tmp);
glm_vec_add(v[1], tmp, v[1]);
glm_vec_add(v[1], m[3], v[1]);
/* translation + max(xa, xb) + max(ya, yb) + max(za, zb) */
glm_vec3(m[3], v[1]);
glm_vec3_maxadd(xa, xb, v[1]);
glm_vec3_maxadd(ya, yb, v[1]);
glm_vec3_maxadd(za, zb, v[1]);
glm_vec_copy(v[0], dest[0]);
glm_vec_copy(v[1], dest[1]);
glm_vec3_copy(v[0], dest[0]);
glm_vec3_copy(v[1], dest[1]);
}
/*!
@@ -153,4 +150,130 @@ glm_aabb_frustum(vec3 box[2], vec4 planes[6]) {
return true;
}
/*!
* @brief invalidate AABB min and max values
*
* @param[in, out] box bounding box
*/
CGLM_INLINE
void
glm_aabb_invalidate(vec3 box[2]) {
glm_vec3_broadcast(FLT_MAX, box[0]);
glm_vec3_broadcast(-FLT_MAX, box[1]);
}
/*!
* @brief check if AABB is valid or not
*
* @param[in] box bounding box
*/
CGLM_INLINE
bool
glm_aabb_isvalid(vec3 box[2]) {
return glm_vec3_max(box[0]) != FLT_MAX
&& glm_vec3_min(box[1]) != -FLT_MAX;
}
/*!
* @brief distance between of min and max
*
* @param[in] box bounding box
*/
CGLM_INLINE
float
glm_aabb_size(vec3 box[2]) {
return glm_vec3_distance(box[0], box[1]);
}
/*!
* @brief radius of sphere which surrounds AABB
*
* @param[in] box bounding box
*/
CGLM_INLINE
float
glm_aabb_radius(vec3 box[2]) {
return glm_aabb_size(box) * 0.5f;
}
/*!
* @brief computes center point of AABB
*
* @param[in] box bounding box
* @param[out] dest center of bounding box
*/
CGLM_INLINE
void
glm_aabb_center(vec3 box[2], vec3 dest) {
glm_vec3_center(box[0], box[1], dest);
}
/*!
* @brief check if two AABB intersects
*
* @param[in] box bounding box
* @param[in] other other bounding box
*/
CGLM_INLINE
bool
glm_aabb_aabb(vec3 box[2], vec3 other[2]) {
return (box[0][0] <= other[1][0] && box[1][0] >= other[0][0])
&& (box[0][1] <= other[1][1] && box[1][1] >= other[0][1])
&& (box[0][2] <= other[1][2] && box[1][2] >= other[0][2]);
}
/*!
* @brief check if AABB intersects with sphere
*
* https://github.com/erich666/GraphicsGems/blob/master/gems/BoxSphere.c
* Solid Box - Solid Sphere test.
*
* @param[in] box solid bounding box
* @param[in] s solid sphere
*/
CGLM_INLINE
bool
glm_aabb_sphere(vec3 box[2], vec4 s) {
float dmin;
int a, b, c;
a = s[0] >= box[0][0];
b = s[1] >= box[0][1];
c = s[2] >= box[0][2];
dmin = glm_pow2(s[0] - box[a][0])
+ glm_pow2(s[1] - box[b][1])
+ glm_pow2(s[2] - box[c][2]);
return dmin <= glm_pow2(s[3]);
}
/*!
* @brief check if point is inside of AABB
*
* @param[in] box bounding box
* @param[in] point point
*/
CGLM_INLINE
bool
glm_aabb_point(vec3 box[2], vec3 point) {
return (point[0] >= box[0][0] && point[0] <= box[1][0])
&& (point[1] >= box[0][1] && point[1] <= box[1][1])
&& (point[2] >= box[0][2] && point[2] <= box[1][2]);
}
/*!
* @brief check if AABB contains other AABB
*
* @param[in] box bounding box
* @param[in] other other bounding box
*/
CGLM_INLINE
bool
glm_aabb_contains(vec3 box[2], vec3 other[2]) {
return (box[0][0] <= other[0][0] && box[1][0] >= other[1][0])
&& (box[0][1] <= other[0][1] && box[1][1] >= other[1][1])
&& (box[0][2] <= other[0][2] && box[1][2] >= other[1][2]);
}
#endif /* cglm_box_h */

View File

@@ -24,6 +24,11 @@ extern "C" {
#include "call/frustum.h"
#include "call/box.h"
#include "call/io.h"
#include "call/project.h"
#include "call/sphere.h"
#include "call/ease.h"
#include "call/curve.h"
#include "call/bezier.h"
#ifdef __cplusplus
}

View File

@@ -13,6 +13,10 @@ extern "C" {
#include "../cglm.h"
CGLM_EXPORT
void
glmc_translate_make(mat4 m, vec3 v);
CGLM_EXPORT
void
glmc_translate_to(mat4 m, vec3 v, mat4 dest);
@@ -33,6 +37,10 @@ CGLM_EXPORT
void
glmc_translate_z(mat4 m, float to);
CGLM_EXPORT
void
glmc_scale_make(mat4 m, vec3 v);
CGLM_EXPORT
void
glmc_scale_to(mat4 m, vec3 v, mat4 dest);
@@ -43,7 +51,7 @@ glmc_scale(mat4 m, vec3 v);
CGLM_EXPORT
void
glmc_scale1(mat4 m, float s);
glmc_scale_uni(mat4 m, float s);
CGLM_EXPORT
void
@@ -57,26 +65,30 @@ CGLM_EXPORT
void
glmc_rotate_z(mat4 m, float rad, mat4 dest);
CGLM_EXPORT
void
glmc_rotate_ndc_make(mat4 m, float angle, vec3 axis_ndc);
CGLM_EXPORT
void
glmc_rotate_make(mat4 m, float angle, vec3 axis);
CGLM_EXPORT
void
glmc_rotate_ndc(mat4 m, float angle, vec3 axis_ndc);
CGLM_EXPORT
void
glmc_rotate(mat4 m, float angle, vec3 axis);
CGLM_EXPORT
void
glmc_rotate_at(mat4 m, vec3 pivot, float angle, vec3 axis);
CGLM_EXPORT
void
glmc_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis);
CGLM_EXPORT
void
glmc_decompose_scalev(mat4 m, vec3 s);
CGLM_EXPORT
bool
glmc_uniscaled(mat4 m);
CGLM_EXPORT
void
glmc_decompose_rs(mat4 m, mat4 r, vec3 s);
@@ -85,6 +97,20 @@ CGLM_EXPORT
void
glmc_decompose(mat4 m, vec4 t, mat4 r, vec3 s);
/* affine-mat */
CGLM_EXPORT
void
glmc_mul(mat4 m1, mat4 m2, mat4 dest);
CGLM_EXPORT
void
glmc_mul_rot(mat4 m1, mat4 m2, mat4 dest);
CGLM_EXPORT
void
glmc_inv_tr(mat4 mat);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglmc_bezier_h
#define cglmc_bezier_h
#ifdef __cplusplus
extern "C" {
#endif
#include "../cglm.h"
CGLM_EXPORT
float
glmc_bezier(float s, float p0, float c0, float c1, float p1);
CGLM_EXPORT
float
glmc_hermite(float s, float p0, float t0, float t1, float p1);
CGLM_EXPORT
float
glmc_decasteljau(float prm, float p0, float c0, float c1, float p1);
#ifdef __cplusplus
}
#endif
#endif /* cglmc_bezier_h */

View File

@@ -32,6 +32,46 @@ glmc_aabb_crop_until(vec3 box[2],
vec3 clampBox[2],
vec3 dest[2]);
CGLM_EXPORT
bool
glmc_aabb_frustum(vec3 box[2], vec4 planes[6]);
CGLM_EXPORT
void
glmc_aabb_invalidate(vec3 box[2]);
CGLM_EXPORT
bool
glmc_aabb_isvalid(vec3 box[2]);
CGLM_EXPORT
float
glmc_aabb_size(vec3 box[2]);
CGLM_EXPORT
float
glmc_aabb_radius(vec3 box[2]);
CGLM_EXPORT
void
glmc_aabb_center(vec3 box[2], vec3 dest);
CGLM_EXPORT
bool
glmc_aabb_aabb(vec3 box[2], vec3 other[2]);
CGLM_EXPORT
bool
glmc_aabb_point(vec3 box[2], vec3 point);
CGLM_EXPORT
bool
glmc_aabb_contains(vec3 box[2], vec3 other[2]);
CGLM_EXPORT
bool
glmc_aabb_sphere(vec3 box[2], vec4 s);
#ifdef __cplusplus
}
#endif

View File

@@ -33,6 +33,26 @@ glmc_ortho(float left,
float farVal,
mat4 dest);
CGLM_EXPORT
void
glmc_ortho_aabb(vec3 box[2], mat4 dest);
CGLM_EXPORT
void
glmc_ortho_aabb_p(vec3 box[2], float padding, mat4 dest);
CGLM_EXPORT
void
glmc_ortho_aabb_pz(vec3 box[2], float padding, mat4 dest);
CGLM_EXPORT
void
glmc_ortho_default(float aspect, mat4 dest);
CGLM_EXPORT
void
glmc_ortho_default_s(float aspect, float size, mat4 dest);
CGLM_EXPORT
void
glmc_perspective(float fovy,
@@ -41,6 +61,18 @@ glmc_perspective(float fovy,
float farVal,
mat4 dest);
CGLM_EXPORT
void
glmc_persp_move_far(mat4 proj, float deltaFar);
CGLM_EXPORT
void
glmc_perspective_default(float aspect, mat4 dest);
CGLM_EXPORT
void
glmc_perspective_resize(float aspect, mat4 proj);
CGLM_EXPORT
void
glmc_lookat(vec3 eye, vec3 center, vec3 up, mat4 dest);
@@ -53,6 +85,58 @@ CGLM_EXPORT
void
glmc_look_anyup(vec3 eye, vec3 dir, mat4 dest);
CGLM_EXPORT
void
glmc_persp_decomp(mat4 proj,
float * __restrict nearVal,
float * __restrict farVal,
float * __restrict top,
float * __restrict bottom,
float * __restrict left,
float * __restrict right);
CGLM_EXPORT
void
glmc_persp_decompv(mat4 proj, float dest[6]);
CGLM_EXPORT
void
glmc_persp_decomp_x(mat4 proj,
float * __restrict left,
float * __restrict right);
CGLM_EXPORT
void
glmc_persp_decomp_y(mat4 proj,
float * __restrict top,
float * __restrict bottom);
CGLM_EXPORT
void
glmc_persp_decomp_z(mat4 proj,
float * __restrict nearVal,
float * __restrict farVal);
CGLM_EXPORT
void
glmc_persp_decomp_far(mat4 proj, float * __restrict farVal);
CGLM_EXPORT
void
glmc_persp_decomp_near(mat4 proj, float * __restrict nearVal);
CGLM_EXPORT
float
glmc_persp_fovy(mat4 proj);
CGLM_EXPORT
float
glmc_persp_aspect(mat4 proj);
CGLM_EXPORT
void
glmc_persp_sizes(mat4 proj, float fovy, vec4 dest);
#ifdef __cplusplus
}
#endif

23
include/cglm/call/curve.h Normal file
View File

@@ -0,0 +1,23 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglmc_curve_h
#define cglmc_curve_h
#ifdef __cplusplus
extern "C" {
#endif
#include "../cglm.h"
CGLM_EXPORT
float
glmc_smc(float s, mat4 m, vec4 c);
#ifdef __cplusplus
}
#endif
#endif /* cglmc_curve_h */

143
include/cglm/call/ease.h Normal file
View File

@@ -0,0 +1,143 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglmc_ease_h
#define cglmc_ease_h
#ifdef __cplusplus
extern "C" {
#endif
#include "../cglm.h"
CGLM_EXPORT
float
glmc_ease_linear(float t);
CGLM_EXPORT
float
glmc_ease_sine_in(float t);
CGLM_EXPORT
float
glmc_ease_sine_out(float t);
CGLM_EXPORT
float
glmc_ease_sine_inout(float t);
CGLM_EXPORT
float
glmc_ease_quad_in(float t);
CGLM_EXPORT
float
glmc_ease_quad_out(float t);
CGLM_EXPORT
float
glmc_ease_quad_inout(float t);
CGLM_EXPORT
float
glmc_ease_cubic_in(float t);
CGLM_EXPORT
float
glmc_ease_cubic_out(float t);
CGLM_EXPORT
float
glmc_ease_cubic_inout(float t);
CGLM_EXPORT
float
glmc_ease_quart_in(float t);
CGLM_EXPORT
float
glmc_ease_quart_out(float t);
CGLM_EXPORT
float
glmc_ease_quart_inout(float t);
CGLM_EXPORT
float
glmc_ease_quint_in(float t);
CGLM_EXPORT
float
glmc_ease_quint_out(float t);
CGLM_EXPORT
float
glmc_ease_quint_inout(float t);
CGLM_EXPORT
float
glmc_ease_exp_in(float t);
CGLM_EXPORT
float
glmc_ease_exp_out(float t);
CGLM_EXPORT
float
glmc_ease_exp_inout(float t);
CGLM_EXPORT
float
glmc_ease_circ_in(float t);
CGLM_EXPORT
float
glmc_ease_circ_out(float t);
CGLM_EXPORT
float
glmc_ease_circ_inout(float t);
CGLM_EXPORT
float
glmc_ease_back_in(float t);
CGLM_EXPORT
float
glmc_ease_back_out(float t);
CGLM_EXPORT
float
glmc_ease_back_inout(float t);
CGLM_EXPORT
float
glmc_ease_elast_in(float t);
CGLM_EXPORT
float
glmc_ease_elast_out(float t);
CGLM_EXPORT
float
glmc_ease_elast_inout(float t);
CGLM_EXPORT
float
glmc_ease_bounce_out(float t);
CGLM_EXPORT
float
glmc_ease_bounce_in(float t);
CGLM_EXPORT
float
glmc_ease_bounce_inout(float t);
#ifdef __cplusplus
}
#endif
#endif /* cglmc_ease_h */

View File

@@ -21,6 +21,10 @@ CGLM_EXPORT
void
glmc_euler(vec3 angles, mat4 dest);
CGLM_EXPORT
void
glmc_euler_xyz(vec3 angles, mat4 dest);
CGLM_EXPORT
void
glmc_euler_zyx(vec3 angles, mat4 dest);

View File

@@ -24,6 +24,10 @@ CGLM_EXPORT
void
glmc_mat3_identity(mat3 mat);
CGLM_EXPORT
void
glmc_mat3_identity_array(mat3 * __restrict mat, size_t count);
CGLM_EXPORT
void
glmc_mat3_mul(mat3 m1, mat3 m2, mat3 dest);
@@ -40,6 +44,14 @@ CGLM_EXPORT
void
glmc_mat3_mulv(mat3 m, vec3 v, vec3 dest);
CGLM_EXPORT
float
glmc_mat3_trace(mat3 m);
CGLM_EXPORT
void
glmc_mat3_quat(mat3 m, versor dest);
CGLM_EXPORT
void
glmc_mat3_scale(mat3 m, float s);
@@ -60,6 +72,10 @@ CGLM_EXPORT
void
glmc_mat3_swap_row(mat3 mat, int row1, int row2);
CGLM_EXPORT
float
glmc_mat3_rmc(vec3 r, mat3 m, vec3 c);
#ifdef __cplusplus
}
#endif

View File

@@ -29,6 +29,10 @@ CGLM_EXPORT
void
glmc_mat4_identity(mat4 mat);
CGLM_EXPORT
void
glmc_mat4_identity_array(mat4 * __restrict mat, size_t count);
CGLM_EXPORT
void
glmc_mat4_pick3(mat4 mat, mat3 dest);
@@ -47,12 +51,28 @@ glmc_mat4_mul(mat4 m1, mat4 m2, mat4 dest);
CGLM_EXPORT
void
glmc_mat4_mulN(mat4 * __restrict matrices[], int len, mat4 dest);
glmc_mat4_mulN(mat4 * __restrict matrices[], uint32_t len, mat4 dest);
CGLM_EXPORT
void
glmc_mat4_mulv(mat4 m, vec4 v, vec4 dest);
CGLM_EXPORT
void
glmc_mat4_mulv3(mat4 m, vec3 v, float last, vec3 dest);
CGLM_EXPORT
float
glmc_mat4_trace(mat4 m);
CGLM_EXPORT
float
glmc_mat4_trace3(mat4 m);
CGLM_EXPORT
void
glmc_mat4_quat(mat4 m, versor dest);
CGLM_EXPORT
void
glmc_mat4_transpose_to(mat4 m, mat4 dest);
@@ -81,6 +101,10 @@ CGLM_EXPORT
void
glmc_mat4_inv_precise(mat4 mat, mat4 dest);
CGLM_EXPORT
void
glmc_mat4_inv_fast(mat4 mat, mat4 dest);
CGLM_EXPORT
void
glmc_mat4_swap_col(mat4 mat, int col1, int col2);
@@ -89,6 +113,10 @@ CGLM_EXPORT
void
glmc_mat4_swap_row(mat4 mat, int row1, int row2);
CGLM_EXPORT
float
glmc_mat4_rmc(vec4 r, mat4 m, vec4 c);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglmc_project_h
#define cglmc_project_h
#ifdef __cplusplus
extern "C" {
#endif
#include "../cglm.h"
CGLM_EXPORT
void
glmc_unprojecti(vec3 pos, mat4 invMat, vec4 vp, vec3 dest);
CGLM_EXPORT
void
glmc_unproject(vec3 pos, mat4 m, vec4 vp, vec3 dest);
CGLM_EXPORT
void
glmc_project(vec3 pos, mat4 m, vec4 vp, vec3 dest);
#ifdef __cplusplus
}
#endif
#endif /* cglmc_project_h */

View File

@@ -19,33 +19,83 @@ glmc_quat_identity(versor q);
CGLM_EXPORT
void
glmc_quat(versor q,
float angle,
float x,
float y,
float z);
glmc_quat_identity_array(versor * __restrict q, size_t count);
CGLM_EXPORT
void
glmc_quatv(versor q,
float angle,
vec3 v);
glmc_quat_init(versor q, float x, float y, float z, float w);
CGLM_EXPORT
void
glmc_quat(versor q, float angle, float x, float y, float z);
CGLM_EXPORT
void
glmc_quatv(versor q, float angle, vec3 axis);
CGLM_EXPORT
void
glmc_quat_copy(versor q, versor dest);
CGLM_EXPORT
float
glmc_quat_norm(versor q);
CGLM_EXPORT
void
glmc_quat_normalize_to(versor q, versor dest);
CGLM_EXPORT
void
glmc_quat_normalize(versor q);
CGLM_EXPORT
float
glmc_quat_dot(versor q, versor r);
glmc_quat_dot(versor p, versor q);
CGLM_EXPORT
void
glmc_quat_mulv(versor q1, versor q2, versor dest);
glmc_quat_conjugate(versor q, versor dest);
CGLM_EXPORT
void
glmc_quat_inv(versor q, versor dest);
CGLM_EXPORT
void
glmc_quat_add(versor p, versor q, versor dest);
CGLM_EXPORT
void
glmc_quat_sub(versor p, versor q, versor dest);
CGLM_EXPORT
float
glmc_quat_real(versor q);
CGLM_EXPORT
void
glmc_quat_imag(versor q, vec3 dest);
CGLM_EXPORT
void
glmc_quat_imagn(versor q, vec3 dest);
CGLM_EXPORT
float
glmc_quat_imaglen(versor q);
CGLM_EXPORT
float
glmc_quat_angle(versor q);
CGLM_EXPORT
void
glmc_quat_axis(versor q, vec3 dest);
CGLM_EXPORT
void
glmc_quat_mul(versor p, versor q, versor dest);
CGLM_EXPORT
void
@@ -53,10 +103,51 @@ glmc_quat_mat4(versor q, mat4 dest);
CGLM_EXPORT
void
glmc_quat_slerp(versor q,
versor r,
float t,
versor dest);
glmc_quat_mat4t(versor q, mat4 dest);
CGLM_EXPORT
void
glmc_quat_mat3(versor q, mat3 dest);
CGLM_EXPORT
void
glmc_quat_mat3t(versor q, mat3 dest);
CGLM_EXPORT
void
glmc_quat_lerp(versor from, versor to, float t, versor dest);
CGLM_EXPORT
void
glmc_quat_slerp(versor q, versor r, float t, versor dest);
CGLM_EXPORT
void
glmc_quat_look(vec3 eye, versor ori, mat4 dest);
CGLM_EXPORT
void
glmc_quat_for(vec3 dir, vec3 fwd, vec3 up, versor dest);
CGLM_EXPORT
void
glmc_quat_forp(vec3 from, vec3 to, vec3 fwd, vec3 up, versor dest);
CGLM_EXPORT
void
glmc_quat_rotatev(versor from, vec3 to, vec3 dest);
CGLM_EXPORT
void
glmc_quat_rotate(mat4 m, versor q, mat4 dest);
CGLM_EXPORT
void
glmc_quat_rotate_at(mat4 model, versor q, vec3 pivot);
CGLM_EXPORT
void
glmc_quat_rotate_atm(mat4 m, versor q, vec3 pivot);
#ifdef __cplusplus
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglmc_sphere_h
#define cglmc_sphere_h
#ifdef __cplusplus
extern "C" {
#endif
#include "../cglm.h"
CGLM_EXPORT
float
glmc_sphere_radii(vec4 s);
CGLM_EXPORT
void
glmc_sphere_transform(vec4 s, mat4 m, vec4 dest);
CGLM_EXPORT
void
glmc_sphere_merge(vec4 s1, vec4 s2, vec4 dest);
CGLM_EXPORT
bool
glmc_sphere_sphere(vec4 s1, vec4 s2);
CGLM_EXPORT
bool
glmc_sphere_point(vec4 s, vec3 point);
#ifdef __cplusplus
}
#endif
#endif /* cglmc_sphere_h */

View File

@@ -14,95 +14,233 @@ extern "C" {
#include "../cglm.h"
/* DEPRECATED! use _copy, _ucopy versions */
#define glmc_vec_dup(v, dest) glmc_vec_copy(v, dest)
#define glmc_vec_dup(v, dest) glmc_vec3_copy(v, dest)
#define glmc_vec3_flipsign(v) glmc_vec3_negate(v)
#define glmc_vec3_flipsign_to(v, dest) glmc_vec3_negate_to(v, dest)
#define glmc_vec3_inv(v) glmc_vec3_negate(v)
#define glmc_vec3_inv_to(v, dest) glmc_vec3_negate_to(v, dest)
CGLM_EXPORT
void
glmc_vec_copy(vec3 a, vec3 dest);
glmc_vec3(vec4 v4, vec3 dest);
CGLM_EXPORT
void
glmc_vec3_copy(vec3 a, vec3 dest);
CGLM_EXPORT
void
glmc_vec3_zero(vec3 v);
CGLM_EXPORT
void
glmc_vec3_one(vec3 v);
CGLM_EXPORT
float
glmc_vec_dot(vec3 a, vec3 b);
glmc_vec3_dot(vec3 a, vec3 b);
CGLM_EXPORT
void
glmc_vec_cross(vec3 a, vec3 b, vec3 d);
glmc_vec3_cross(vec3 a, vec3 b, vec3 dest);
CGLM_EXPORT
void
glmc_vec3_crossn(vec3 a, vec3 b, vec3 dest);
CGLM_EXPORT
float
glmc_vec_norm(vec3 vec);
glmc_vec3_norm(vec3 v);
CGLM_EXPORT
float
glmc_vec_norm2(vec3 vec);
glmc_vec3_norm2(vec3 v);
CGLM_EXPORT
void
glmc_vec_normalize_to(vec3 vec, vec3 dest);
glmc_vec3_normalize_to(vec3 v, vec3 dest);
CGLM_EXPORT
void
glmc_vec_normalize(vec3 v);
glmc_vec3_normalize(vec3 v);
CGLM_EXPORT
void
glmc_vec_add(vec3 v1, vec3 v2, vec3 dest);
glmc_vec3_add(vec3 a, vec3 b, vec3 dest);
CGLM_EXPORT
void
glmc_vec_sub(vec3 v1, vec3 v2, vec3 dest);
glmc_vec3_adds(vec3 v, float s, vec3 dest);
CGLM_EXPORT
void
glmc_vec_scale(vec3 v, float s, vec3 dest);
glmc_vec3_sub(vec3 a, vec3 b, vec3 dest);
CGLM_EXPORT
void
glmc_vec_scale_as(vec3 v, float s, vec3 dest);
glmc_vec3_subs(vec3 v, float s, vec3 dest);
CGLM_EXPORT
void
glmc_vec_flipsign(vec3 v);
glmc_vec3_mul(vec3 a, vec3 b, vec3 d);
CGLM_EXPORT
void
glmc_vec_inv(vec3 v);
glmc_vec3_scale(vec3 v, float s, vec3 dest);
CGLM_EXPORT
void
glmc_vec_inv_to(vec3 v, vec3 dest);
CGLM_EXPORT
float
glmc_vec_angle(vec3 v1, vec3 v2);
glmc_vec3_scale_as(vec3 v, float s, vec3 dest);
CGLM_EXPORT
void
glmc_vec_rotate(vec3 v, float angle, vec3 axis);
glmc_vec3_div(vec3 a, vec3 b, vec3 dest);
CGLM_EXPORT
void
glmc_vec_rotate_m4(mat4 m, vec3 v, vec3 dest);
glmc_vec3_divs(vec3 a, float s, vec3 dest);
CGLM_EXPORT
void
glmc_vec_proj(vec3 a, vec3 b, vec3 dest);
glmc_vec3_addadd(vec3 a, vec3 b, vec3 dest);
CGLM_EXPORT
void
glmc_vec_center(vec3 v1, vec3 v2, vec3 dest);
glmc_vec3_subadd(vec3 a, vec3 b, vec3 dest);
CGLM_EXPORT
void
glmc_vec3_muladd(vec3 a, vec3 b, vec3 dest);
CGLM_EXPORT
void
glmc_vec3_muladds(vec3 a, float s, vec3 dest);
CGLM_EXPORT
void
glmc_vec3_maxadd(vec3 a, vec3 b, vec3 dest);
CGLM_EXPORT
void
glmc_vec3_minadd(vec3 a, vec3 b, vec3 dest);
CGLM_EXPORT
void
glmc_vec3_negate(vec3 v);
CGLM_EXPORT
void
glmc_vec3_negate_to(vec3 v, vec3 dest);
CGLM_EXPORT
float
glmc_vec_distance(vec3 v1, vec3 v2);
glmc_vec3_angle(vec3 a, vec3 b);
CGLM_EXPORT
void
glmc_vec_maxv(vec3 v1, vec3 v2, vec3 dest);
glmc_vec3_rotate(vec3 v, float angle, vec3 axis);
CGLM_EXPORT
void
glmc_vec_minv(vec3 v1, vec3 v2, vec3 dest);
glmc_vec3_rotate_m4(mat4 m, vec3 v, vec3 dest);
CGLM_EXPORT
void
glmc_vec3_rotate_m3(mat3 m, vec3 v, vec3 dest);
CGLM_EXPORT
void
glmc_vec3_proj(vec3 a, vec3 b, vec3 dest);
CGLM_EXPORT
void
glmc_vec3_center(vec3 a, vec3 b, vec3 dest);
CGLM_EXPORT
float
glmc_vec3_distance2(vec3 a, vec3 b);
CGLM_EXPORT
float
glmc_vec3_distance(vec3 a, vec3 b);
CGLM_EXPORT
void
glmc_vec3_maxv(vec3 a, vec3 b, vec3 dest);
CGLM_EXPORT
void
glmc_vec3_minv(vec3 a, vec3 b, vec3 dest);
CGLM_EXPORT
void
glmc_vec3_clamp(vec3 v, float minVal, float maxVal);
CGLM_EXPORT
void
glmc_vec3_ortho(vec3 v, vec3 dest);
CGLM_EXPORT
void
glmc_vec3_lerp(vec3 from, vec3 to, float t, vec3 dest);
/* ext */
CGLM_EXPORT
void
glmc_vec3_mulv(vec3 a, vec3 b, vec3 d);
CGLM_EXPORT
void
glmc_vec3_broadcast(float val, vec3 d);
CGLM_EXPORT
bool
glmc_vec3_eq(vec3 v, float val);
CGLM_EXPORT
bool
glmc_vec3_eq_eps(vec3 v, float val);
CGLM_EXPORT
bool
glmc_vec3_eq_all(vec3 v);
CGLM_EXPORT
bool
glmc_vec3_eqv(vec3 a, vec3 b);
CGLM_EXPORT
bool
glmc_vec3_eqv_eps(vec3 a, vec3 b);
CGLM_EXPORT
float
glmc_vec3_max(vec3 v);
CGLM_EXPORT
float
glmc_vec3_min(vec3 v);
CGLM_EXPORT
bool
glmc_vec3_isnan(vec3 v);
CGLM_EXPORT
bool
glmc_vec3_isinf(vec3 v);
CGLM_EXPORT
bool
glmc_vec3_isvalid(vec3 v);
CGLM_EXPORT
void
glmc_vec3_sign(vec3 v, vec3 dest);
CGLM_EXPORT
void
glmc_vec3_sqrt(vec3 v, vec3 dest);
#ifdef __cplusplus
}

View File

@@ -14,32 +14,52 @@ extern "C" {
#include "../cglm.h"
/* DEPRECATED! use _copy, _ucopy versions */
#define glmc_vec4_dup3(v, dest) glmc_vec4_copy3(v, dest)
#define glmc_vec4_dup(v, dest) glmc_vec4_copy(v, dest)
#define glmc_vec4_dup3(v, dest) glmc_vec4_copy3(v, dest)
#define glmc_vec4_dup(v, dest) glmc_vec4_copy(v, dest)
#define glmc_vec4_flipsign(v) glmc_vec4_negate(v)
#define glmc_vec4_flipsign_to(v, dest) glmc_vec4_negate_to(v, dest)
#define glmc_vec4_inv(v) glmc_vec4_negate(v)
#define glmc_vec4_inv_to(v, dest) glmc_vec4_negate_to(v, dest)
CGLM_EXPORT
void
glmc_vec4_copy3(vec4 a, vec3 dest);
glmc_vec4(vec3 v3, float last, vec4 dest);
CGLM_EXPORT
void
glmc_vec4_zero(vec4 v);
CGLM_EXPORT
void
glmc_vec4_one(vec4 v);
CGLM_EXPORT
void
glmc_vec4_copy3(vec4 v, vec3 dest);
CGLM_EXPORT
void
glmc_vec4_copy(vec4 v, vec4 dest);
CGLM_EXPORT
void
glmc_vec4_ucopy(vec4 v, vec4 dest);
CGLM_EXPORT
float
glmc_vec4_dot(vec4 a, vec4 b);
CGLM_EXPORT
float
glmc_vec4_norm(vec4 vec);
glmc_vec4_norm(vec4 v);
CGLM_EXPORT
float
glmc_vec4_norm2(vec4 vec);
glmc_vec4_norm2(vec4 v);
CGLM_EXPORT
void
glmc_vec4_normalize_to(vec4 vec, vec4 dest);
glmc_vec4_normalize_to(vec4 v, vec4 dest);
CGLM_EXPORT
void
@@ -47,11 +67,23 @@ glmc_vec4_normalize(vec4 v);
CGLM_EXPORT
void
glmc_vec4_add(vec4 v1, vec4 v2, vec4 dest);
glmc_vec4_add(vec4 a, vec4 b, vec4 dest);
CGLM_EXPORT
void
glmc_vec4_sub(vec4 v1, vec4 v2, vec4 dest);
glmc_vec4_adds(vec4 v, float s, vec4 dest);
CGLM_EXPORT
void
glmc_vec4_sub(vec4 a, vec4 b, vec4 dest);
CGLM_EXPORT
void
glmc_vec4_subs(vec4 v, float s, vec4 dest);
CGLM_EXPORT
void
glmc_vec4_mul(vec4 a, vec4 b, vec4 d);
CGLM_EXPORT
void
@@ -63,27 +95,125 @@ glmc_vec4_scale_as(vec3 v, float s, vec3 dest);
CGLM_EXPORT
void
glmc_vec4_flipsign(vec4 v);
glmc_vec4_div(vec4 a, vec4 b, vec4 dest);
CGLM_EXPORT
void
glmc_vec4_inv(vec4 v);
glmc_vec4_divs(vec4 v, float s, vec4 dest);
CGLM_EXPORT
void
glmc_vec4_inv_to(vec4 v, vec4 dest);
glmc_vec4_addadd(vec4 a, vec4 b, vec4 dest);
CGLM_EXPORT
void
glmc_vec4_subadd(vec4 a, vec4 b, vec4 dest);
CGLM_EXPORT
void
glmc_vec4_muladd(vec4 a, vec4 b, vec4 dest);
CGLM_EXPORT
void
glmc_vec4_muladds(vec4 a, float s, vec4 dest);
CGLM_EXPORT
void
glmc_vec4_maxadd(vec4 a, vec4 b, vec4 dest);
CGLM_EXPORT
void
glmc_vec4_minadd(vec4 a, vec4 b, vec4 dest);
CGLM_EXPORT
void
glmc_vec4_negate(vec4 v);
CGLM_EXPORT
void
glmc_vec4_negate_to(vec4 v, vec4 dest);
CGLM_EXPORT
float
glmc_vec4_distance(vec4 v1, vec4 v2);
glmc_vec4_distance(vec4 a, vec4 b);
CGLM_EXPORT
void
glmc_vec4_maxv(vec4 v1, vec4 v2, vec4 dest);
glmc_vec4_maxv(vec4 a, vec4 b, vec4 dest);
CGLM_EXPORT
void
glmc_vec4_minv(vec4 v1, vec4 v2, vec4 dest);
glmc_vec4_minv(vec4 a, vec4 b, vec4 dest);
CGLM_EXPORT
void
glmc_vec4_clamp(vec4 v, float minVal, float maxVal);
CGLM_EXPORT
void
glmc_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest);
CGLM_EXPORT
void
glmc_vec4_cubic(float s, vec4 dest);
/* ext */
CGLM_EXPORT
void
glmc_vec4_mulv(vec4 a, vec4 b, vec4 d);
CGLM_EXPORT
void
glmc_vec4_broadcast(float val, vec4 d);
CGLM_EXPORT
bool
glmc_vec4_eq(vec4 v, float val);
CGLM_EXPORT
bool
glmc_vec4_eq_eps(vec4 v, float val);
CGLM_EXPORT
bool
glmc_vec4_eq_all(vec4 v);
CGLM_EXPORT
bool
glmc_vec4_eqv(vec4 a, vec4 b);
CGLM_EXPORT
bool
glmc_vec4_eqv_eps(vec4 a, vec4 b);
CGLM_EXPORT
float
glmc_vec4_max(vec4 v);
CGLM_EXPORT
float
glmc_vec4_min(vec4 v);
CGLM_EXPORT
bool
glmc_vec4_isnan(vec4 v);
CGLM_EXPORT
bool
glmc_vec4_isinf(vec4 v);
CGLM_EXPORT
bool
glmc_vec4_isvalid(vec4 v);
CGLM_EXPORT
void
glmc_vec4_sign(vec4 v, vec4 dest);
CGLM_EXPORT
void
glmc_vec4_sqrt(vec4 v, vec4 dest);
#ifdef __cplusplus
}

View File

@@ -7,54 +7,42 @@
/*
Functions:
CGLM_INLINE void glm_frustum(float left,
float right,
float bottom,
float top,
float nearVal,
float farVal,
mat4 dest);
CGLM_INLINE void glm_ortho(float left,
float right,
float bottom,
float top,
float nearVal,
float farVal,
mat4 dest);
CGLM_INLINE void glm_ortho_default(float aspect, mat4 dest);
CGLM_INLINE void glm_ortho_default_s(float aspect, float size, mat4 dest);
CGLM_INLINE void glm_perspective(float fovy,
float aspect,
float nearVal,
float farVal,
mat4 dest);
CGLM_INLINE void glm_perspective_default(float aspect, mat4 dest);
CGLM_INLINE void glm_perspective_resize(float aspect, mat4 proj);
CGLM_INLINE void glm_lookat(vec3 eye, vec3 center, vec3 up, mat4 dest);
CGLM_INLINE void glm_persp_decomp(mat4 proj,
float * __restrict nearVal,
float * __restrict farVal,
float * __restrict top,
float * __restrict bottom,
float * __restrict left,
float * __restrict right);
CGLM_INLINE void glm_persp_decompv(mat4 proj, float dest[6]);
CGLM_INLINE void glm_persp_decomp_x(mat4 proj,
float * __restrict left,
float * __restrict right);
CGLM_INLINE void glm_persp_decomp_y(mat4 proj,
float * __restrict top,
float * __restrict bottom);
CGLM_INLINE void glm_persp_decomp_z(mat4 proj,
float * __restrict nearVal,
float * __restrict farVal);
CGLM_INLINE void glm_persp_decomp_far(mat4 proj, float * __restrict farVal);
CGLM_INLINE void glm_persp_decomp_near(mat4 proj, float *__restrict nearVal);
CGLM_INLINE void glm_frustum_planes(mat4 m, vec4 dest[6]);
CGLM_INLINE void glm_frustum_corners(mat4 invMat, vec4 dest[8]);
CGLM_INLINE glm_ortho_box(vec3 box[2], mat4 dest);
CGLM_INLINE void glm_ortho_boxp(vec3 box[2], float padding, mat4 dest);
CGLM_INLINE void glm_ortho_boxp(vec3 box[2], float padding, mat4 dest);
CGLM_INLINE void glm_frustum(float left, float right,
float bottom, float top,
float nearVal, float farVal,
mat4 dest)
CGLM_INLINE void glm_ortho(float left, float right,
float bottom, float top,
float nearVal, float farVal,
mat4 dest)
CGLM_INLINE void glm_ortho_aabb(vec3 box[2], mat4 dest)
CGLM_INLINE void glm_ortho_aabb_p(vec3 box[2], float padding, mat4 dest)
CGLM_INLINE void glm_ortho_aabb_pz(vec3 box[2], float padding, mat4 dest)
CGLM_INLINE void glm_ortho_default(float aspect, mat4 dest)
CGLM_INLINE void glm_ortho_default_s(float aspect, float size, mat4 dest)
CGLM_INLINE void glm_perspective(float fovy,
float aspect,
float nearVal,
float farVal,
mat4 dest)
CGLM_INLINE void glm_perspective_default(float aspect, mat4 dest)
CGLM_INLINE void glm_perspective_resize(float aspect, mat4 proj)
CGLM_INLINE void glm_lookat(vec3 eye, vec3 center, vec3 up, mat4 dest)
CGLM_INLINE void glm_look(vec3 eye, vec3 dir, vec3 up, mat4 dest)
CGLM_INLINE void glm_look_anyup(vec3 eye, vec3 dir, mat4 dest)
CGLM_INLINE void glm_persp_decomp(mat4 proj,
float *nearVal, float *farVal,
float *top, float *bottom,
float *left, float *right)
CGLM_INLINE void glm_persp_decompv(mat4 proj, float dest[6])
CGLM_INLINE void glm_persp_decomp_x(mat4 proj, float *left, float *right)
CGLM_INLINE void glm_persp_decomp_y(mat4 proj, float *top, float *bottom)
CGLM_INLINE void glm_persp_decomp_z(mat4 proj, float *nearv, float *farv)
CGLM_INLINE void glm_persp_decomp_far(mat4 proj, float *farVal)
CGLM_INLINE void glm_persp_decomp_near(mat4 proj, float *nearVal)
CGLM_INLINE float glm_persp_fovy(mat4 proj)
CGLM_INLINE float glm_persp_aspect(mat4 proj)
CGLM_INLINE void glm_persp_sizes(mat4 proj, float fovy, vec4 dest)
*/
#ifndef cglm_vcam_h
@@ -76,16 +64,13 @@
*/
CGLM_INLINE
void
glm_frustum(float left,
float right,
float bottom,
float top,
float nearVal,
float farVal,
glm_frustum(float left, float right,
float bottom, float top,
float nearVal, float farVal,
mat4 dest) {
float rl, tb, fn, nv;
glm__memzero(float, dest, sizeof(mat4));
glm_mat4_zero(dest);
rl = 1.0f / (right - left);
tb = 1.0f / (top - bottom);
@@ -114,16 +99,13 @@ glm_frustum(float left,
*/
CGLM_INLINE
void
glm_ortho(float left,
float right,
float bottom,
float top,
float nearVal,
float farVal,
glm_ortho(float left, float right,
float bottom, float top,
float nearVal, float farVal,
mat4 dest) {
float rl, tb, fn;
glm__memzero(float, dest, sizeof(mat4));
glm_mat4_zero(dest);
rl = 1.0f / (right - left);
tb = 1.0f / (top - bottom);
@@ -199,26 +181,15 @@ glm_ortho_aabb_pz(vec3 box[2], float padding, mat4 dest) {
*/
CGLM_INLINE
void
glm_ortho_default(float aspect,
mat4 dest) {
glm_ortho_default(float aspect, mat4 dest) {
if (aspect >= 1.0f) {
glm_ortho(-1.0f * aspect,
1.0f * aspect,
-1.0f,
1.0f,
-100.0f,
100.0f,
dest);
return;
glm_ortho(-aspect, aspect, -1.0f, 1.0f, -100.0f, 100.0f, dest);
return;
}
glm_ortho(-1.0f,
1.0f,
-1.0f / aspect,
1.0f / aspect,
-100.0f,
100.0f,
dest);
aspect = 1.0f / aspect;
glm_ortho(-1.0f, 1.0f, -aspect, aspect, -100.0f, 100.0f, dest);
}
/*!
@@ -230,9 +201,7 @@ glm_ortho_default(float aspect,
*/
CGLM_INLINE
void
glm_ortho_default_s(float aspect,
float size,
mat4 dest) {
glm_ortho_default_s(float aspect, float size, mat4 dest) {
if (aspect >= 1.0f) {
glm_ortho(-size * aspect,
size * aspect,
@@ -241,7 +210,7 @@ glm_ortho_default_s(float aspect,
-size - 100.0f,
size + 100.0f,
dest);
return;
return;
}
glm_ortho(-size,
@@ -271,7 +240,7 @@ glm_perspective(float fovy,
mat4 dest) {
float f, fn;
glm__memzero(float, dest, sizeof(mat4));
glm_mat4_zero(dest);
f = 1.0f / tanf(fovy * 0.5f);
fn = 1.0f / (nearVal - farVal);
@@ -283,6 +252,30 @@ glm_perspective(float fovy,
dest[3][2] = 2.0f * nearVal * farVal * fn;
}
/*!
* @brief extend perspective projection matrix's far distance
*
* this function does not guarantee far >= near, be aware of that!
*
* @param[in, out] proj projection matrix to extend
* @param[in] deltaFar distance from existing far (negative to shink)
*/
CGLM_INLINE
void
glm_persp_move_far(mat4 proj, float deltaFar) {
float fn, farVal, nearVal, p22, p32;
p22 = proj[2][2];
p32 = proj[3][2];
nearVal = p32 / (p22 - 1.0f);
farVal = p32 / (p22 + 1.0f) + deltaFar;
fn = 1.0f / (nearVal - farVal);
proj[2][2] = (nearVal + farVal) * fn;
proj[3][2] = 2.0f * nearVal * farVal * fn;
}
/*!
* @brief set up perspective projection matrix with default near/far
* and angle values
@@ -292,18 +285,13 @@ glm_perspective(float fovy,
*/
CGLM_INLINE
void
glm_perspective_default(float aspect,
mat4 dest) {
glm_perspective((float)CGLM_PI_4,
aspect,
0.01f,
100.0f,
dest);
glm_perspective_default(float aspect, mat4 dest) {
glm_perspective(GLM_PI_4f, aspect, 0.01f, 100.0f, dest);
}
/*!
* @brief resize perspective matrix by aspect ratio ( width / height )
* this very make easy to resize proj matrix when window, viewport
* this makes very easy to resize proj matrix when window /viewport
* reized
*
* @param[in] aspect aspect ratio ( width / height )
@@ -311,8 +299,7 @@ glm_perspective_default(float aspect,
*/
CGLM_INLINE
void
glm_perspective_resize(float aspect,
mat4 proj) {
glm_perspective_resize(float aspect, mat4 proj) {
if (proj[0][0] == 0.0f)
return;
@@ -322,6 +309,9 @@ glm_perspective_resize(float aspect,
/*!
* @brief set up view matrix
*
* NOTE: The UP vector must not be parallel to the line of sight from
* the eye point to the reference point
*
* @param[in] eye eye vector
* @param[in] center center vector
* @param[in] up up vector
@@ -333,15 +323,13 @@ glm_lookat(vec3 eye,
vec3 center,
vec3 up,
mat4 dest) {
vec3 f, u, s;
CGLM_ALIGN(8) vec3 f, u, s;
glm_vec_sub(center, eye, f);
glm_vec_normalize(f);
glm_vec3_sub(center, eye, f);
glm_vec3_normalize(f);
glm_vec_cross(f, up, s);
glm_vec_normalize(s);
glm_vec_cross(s, f, u);
glm_vec3_crossn(f, up, s);
glm_vec3_cross(s, f, u);
dest[0][0] = s[0];
dest[0][1] = u[0];
@@ -352,9 +340,9 @@ glm_lookat(vec3 eye,
dest[2][0] = s[2];
dest[2][1] = u[2];
dest[2][2] =-f[2];
dest[3][0] =-glm_vec_dot(s, eye);
dest[3][1] =-glm_vec_dot(u, eye);
dest[3][2] = glm_vec_dot(f, eye);
dest[3][0] =-glm_vec3_dot(s, eye);
dest[3][1] =-glm_vec3_dot(u, eye);
dest[3][2] = glm_vec3_dot(f, eye);
dest[0][3] = dest[1][3] = dest[2][3] = 0.0f;
dest[3][3] = 1.0f;
}
@@ -365,6 +353,9 @@ glm_lookat(vec3 eye,
* convenient wrapper for lookat: if you only have direction not target self
* then this might be useful. Because you need to get target from direction.
*
* NOTE: The UP vector must not be parallel to the line of sight from
* the eye point to the reference point
*
* @param[in] eye eye vector
* @param[in] dir direction vector
* @param[in] up up vector
@@ -373,8 +364,8 @@ glm_lookat(vec3 eye,
CGLM_INLINE
void
glm_look(vec3 eye, vec3 dir, vec3 up, mat4 dest) {
vec3 target;
glm_vec_add(eye, dir, target);
CGLM_ALIGN(8) vec3 target;
glm_vec3_add(eye, dir, target);
glm_lookat(eye, target, up, dest);
}
@@ -391,8 +382,8 @@ glm_look(vec3 eye, vec3 dir, vec3 up, mat4 dest) {
CGLM_INLINE
void
glm_look_anyup(vec3 eye, vec3 dir, mat4 dest) {
vec3 up;
glm_vec_ortho(dir, up);
CGLM_ALIGN(8) vec3 up;
glm_vec3_ortho(dir, up);
glm_look(eye, dir, up, dest);
}
@@ -410,12 +401,9 @@ glm_look_anyup(vec3 eye, vec3 dir, mat4 dest) {
CGLM_INLINE
void
glm_persp_decomp(mat4 proj,
float * __restrict nearVal,
float * __restrict farVal,
float * __restrict top,
float * __restrict bottom,
float * __restrict left,
float * __restrict right) {
float * __restrict nearVal, float * __restrict farVal,
float * __restrict top, float * __restrict bottom,
float * __restrict left, float * __restrict right) {
float m00, m11, m20, m21, m22, m32, n, f;
float n_m11, n_m00;
@@ -458,7 +446,7 @@ glm_persp_decompv(mat4 proj, float dest[6]) {
* @brief decomposes left and right values of perspective projection.
* x stands for x axis (left / right axis)
*
* @param[in] proj perspective projection matrix
* @param[in] proj perspective projection matrix
* @param[out] left left
* @param[out] right right
*/
@@ -572,10 +560,7 @@ glm_persp_aspect(mat4 proj) {
}
/*!
* @brief returns aspect ratio of perspective projection
*
* if you don't have fovy then use glm_persp_fovy(proj) to get it
* or pass directly: glm_persp_sizes(proj, glm_persp_fovy(proj), sizes);
* @brief returns sizes of near and far planes of perspective projection
*
* @param[in] proj perspective projection matrix
* @param[in] fovy fovy (see brief)

View File

@@ -20,7 +20,13 @@
#include "euler.h"
#include "plane.h"
#include "box.h"
#include "color.h"
#include "util.h"
#include "io.h"
#include "project.h"
#include "sphere.h"
#include "ease.h"
#include "curve.h"
#include "bezier.h"
#endif /* cglm_h */

26
include/cglm/color.h Normal file
View File

@@ -0,0 +1,26 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglm_color_h
#define cglm_color_h
#include "common.h"
#include "vec3.h"
/*!
* @brief averages the color channels into one value
*
* @param[in] rgb RGB color
*/
CGLM_INLINE
float
glm_luminance(vec3 rgb) {
vec3 l = {0.212671f, 0.715160f, 0.072169f};
return glm_dot(rgb, l);
}
#endif /* cglm_color_h */

View File

@@ -11,10 +11,12 @@
#define _USE_MATH_DEFINES /* for windows */
#include <stdint.h>
#include <stddef.h>
#include <math.h>
#include <float.h>
#include <stdbool.h>
#if defined(_WIN32)
#if defined(_MSC_VER)
# ifdef CGLM_DLL
# define CGLM_EXPORT __declspec(dllexport)
# else
@@ -26,34 +28,6 @@
# define CGLM_INLINE static inline __attribute((always_inline))
#endif
#define glm__memcpy(type, dest, src, size) \
do { \
type *srci; \
type *srci_end; \
type *desti; \
\
srci = (type *)src; \
srci_end = (type *)((char *)srci + size); \
desti = (type *)dest; \
\
while (srci != srci_end) \
*desti++ = *srci++; \
} while (0)
#define glm__memset(type, dest, size, val) \
do { \
type *desti; \
type *desti_end; \
\
desti = (type *)dest; \
desti_end = (type *)((char *)desti + size); \
\
while (desti != desti_end) \
*desti++ = val; \
} while (0)
#define glm__memzero(type, dest, size) glm__memset(type, dest, size, 0)
#define GLM_SHUFFLE4(z, y, x, w) (((z) << 6) | ((y) << 4) | ((x) << 2) | (w))
#define GLM_SHUFFLE3(z, y, x) (((z) << 4) | ((y) << 2) | (x))

40
include/cglm/curve.h Normal file
View File

@@ -0,0 +1,40 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglm_curve_h
#define cglm_curve_h
#include "common.h"
#include "vec4.h"
#include "mat4.h"
/*!
* @brief helper function to calculate S*M*C multiplication for curves
*
* This function does not encourage you to use SMC,
* instead it is a helper if you use SMC.
*
* if you want to specify S as vector then use more generic glm_mat4_rmc() func.
*
* Example usage:
* B(s) = glm_smc(s, GLM_BEZIER_MAT, (vec4){p0, c0, c1, p1})
*
* @param[in] s parameter between 0 and 1 (this will be [s3, s2, s, 1])
* @param[in] m basis matrix
* @param[in] c position/control vector
*
* @return B(s)
*/
CGLM_INLINE
float
glm_smc(float s, mat4 m, vec4 c) {
vec4 vs;
glm_vec4_cubic(s, vs);
return glm_mat4_rmc(vs, m, c);
}
#endif /* cglm_curve_h */

317
include/cglm/ease.h Normal file
View File

@@ -0,0 +1,317 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglm_ease_h
#define cglm_ease_h
#include "common.h"
CGLM_INLINE
float
glm_ease_linear(float t) {
return t;
}
CGLM_INLINE
float
glm_ease_sine_in(float t) {
return sinf((t - 1.0f) * GLM_PI_2f) + 1.0f;
}
CGLM_INLINE
float
glm_ease_sine_out(float t) {
return sinf(t * GLM_PI_2f);
}
CGLM_INLINE
float
glm_ease_sine_inout(float t) {
return 0.5f * (1.0f - cosf(t * GLM_PIf));
}
CGLM_INLINE
float
glm_ease_quad_in(float t) {
return t * t;
}
CGLM_INLINE
float
glm_ease_quad_out(float t) {
return -(t * (t - 2.0f));
}
CGLM_INLINE
float
glm_ease_quad_inout(float t) {
float tt;
tt = t * t;
if (t < 0.5f)
return 2.0f * tt;
return (-2.0f * tt) + (4.0f * t) - 1.0f;
}
CGLM_INLINE
float
glm_ease_cubic_in(float t) {
return t * t * t;
}
CGLM_INLINE
float
glm_ease_cubic_out(float t) {
float f;
f = t - 1.0f;
return f * f * f + 1.0f;
}
CGLM_INLINE
float
glm_ease_cubic_inout(float t) {
float f;
if (t < 0.5f)
return 4.0f * t * t * t;
f = 2.0f * t - 2.0f;
return 0.5f * f * f * f + 1.0f;
}
CGLM_INLINE
float
glm_ease_quart_in(float t) {
float f;
f = t * t;
return f * f;
}
CGLM_INLINE
float
glm_ease_quart_out(float t) {
float f;
f = t - 1.0f;
return f * f * f * (1.0f - t) + 1.0f;
}
CGLM_INLINE
float
glm_ease_quart_inout(float t) {
float f, g;
if (t < 0.5f) {
f = t * t;
return 8.0f * f * f;
}
f = t - 1.0f;
g = f * f;
return -8.0f * g * g + 1.0f;
}
CGLM_INLINE
float
glm_ease_quint_in(float t) {
float f;
f = t * t;
return f * f * t;
}
CGLM_INLINE
float
glm_ease_quint_out(float t) {
float f, g;
f = t - 1.0f;
g = f * f;
return g * g * f + 1.0f;
}
CGLM_INLINE
float
glm_ease_quint_inout(float t) {
float f, g;
if (t < 0.5f) {
f = t * t;
return 16.0f * f * f * t;
}
f = 2.0f * t - 2.0f;
g = f * f;
return 0.5f * g * g * f + 1.0f;
}
CGLM_INLINE
float
glm_ease_exp_in(float t) {
if (t == 0.0f)
return t;
return powf(2.0f, 10.0f * (t - 1.0f));
}
CGLM_INLINE
float
glm_ease_exp_out(float t) {
if (t == 1.0f)
return t;
return 1.0f - powf(2.0f, -10.0f * t);
}
CGLM_INLINE
float
glm_ease_exp_inout(float t) {
if (t == 0.0f || t == 1.0f)
return t;
if (t < 0.5f)
return 0.5f * powf(2.0f, (20.0f * t) - 10.0f);
return -0.5f * powf(2.0f, (-20.0f * t) + 10.0f) + 1.0f;
}
CGLM_INLINE
float
glm_ease_circ_in(float t) {
return 1.0f - sqrtf(1.0f - (t * t));
}
CGLM_INLINE
float
glm_ease_circ_out(float t) {
return sqrtf((2.0f - t) * t);
}
CGLM_INLINE
float
glm_ease_circ_inout(float t) {
if (t < 0.5f)
return 0.5f * (1.0f - sqrtf(1.0f - 4.0f * (t * t)));
return 0.5f * (sqrtf(-((2.0f * t) - 3.0f) * ((2.0f * t) - 1.0f)) + 1.0f);
}
CGLM_INLINE
float
glm_ease_back_in(float t) {
float o, z;
o = 1.70158f;
z = ((o + 1.0f) * t) - o;
return t * t * z;
}
CGLM_INLINE
float
glm_ease_back_out(float t) {
float o, z, n;
o = 1.70158f;
n = t - 1.0f;
z = (o + 1.0f) * n + o;
return n * n * z + 1.0f;
}
CGLM_INLINE
float
glm_ease_back_inout(float t) {
float o, z, n, m, s, x;
o = 1.70158f;
s = o * 1.525f;
x = 0.5;
n = t / 0.5f;
if (n < 1.0f) {
z = (s + 1) * n - s;
m = n * n * z;
return x * m;
}
n -= 2.0f;
z = (s + 1.0f) * n + s;
m = (n * n * z) + 2;
return x * m;
}
CGLM_INLINE
float
glm_ease_elast_in(float t) {
return sinf(13.0f * GLM_PI_2f * t) * powf(2.0f, 10.0f * (t - 1.0f));
}
CGLM_INLINE
float
glm_ease_elast_out(float t) {
return sinf(-13.0f * GLM_PI_2f * (t + 1.0f)) * powf(2.0f, -10.0f * t) + 1.0f;
}
CGLM_INLINE
float
glm_ease_elast_inout(float t) {
float a;
a = 2.0f * t;
if (t < 0.5f)
return 0.5f * sinf(13.0f * GLM_PI_2f * a)
* powf(2.0f, 10.0f * (a - 1.0f));
return 0.5f * (sinf(-13.0f * GLM_PI_2f * a)
* powf(2.0f, -10.0f * (a - 1.0f)) + 2.0f);
}
CGLM_INLINE
float
glm_ease_bounce_out(float t) {
float tt;
tt = t * t;
if (t < (4.0f / 11.0f))
return (121.0f * tt) / 16.0f;
if (t < 8.0f / 11.0f)
return ((363.0f / 40.0f) * tt) - ((99.0f / 10.0f) * t) + (17.0f / 5.0f);
if (t < (9.0f / 10.0f))
return (4356.0f / 361.0f) * tt
- (35442.0f / 1805.0f) * t
+ (16061.0f / 1805.0f);
return ((54.0f / 5.0f) * tt) - ((513.0f / 25.0f) * t) + (268.0f / 25.0f);
}
CGLM_INLINE
float
glm_ease_bounce_in(float t) {
return 1.0f - glm_ease_bounce_out(1.0f - t);
}
CGLM_INLINE
float
glm_ease_bounce_inout(float t) {
if (t < 0.5f)
return 0.5f * (1.0f - glm_ease_bounce_out(t * 2.0f));
return 0.5f * glm_ease_bounce_out(t * 2.0f - 1.0f) + 0.5f;
}
#endif /* cglm_ease_h */

View File

@@ -5,21 +5,30 @@
* Full license can be found in the LICENSE file
*/
/*
NOTE:
angles must be passed as [X-Angle, Y-Angle, Z-angle] order
For instance you don't pass angles as [Z-Angle, X-Angle, Y-angle] to
glm_euler_zxy funciton, All RELATED functions accept angles same order
which is [X, Y, Z].
*/
/*
Types:
enum glm_euler_sq
Functions:
CGLM_INLINE glm_euler_sq glm_euler_order(int newOrder[3]);
CGLM_INLINE void glm_euler_angles(mat4 m, vec3 dest);
CGLM_INLINE void glm_euler(vec3 angles, mat4 dest);
CGLM_INLINE void glm_euler_xyz(vec3 angles, mat4 dest);
CGLM_INLINE void glm_euler_zyx(vec3 angles, mat4 dest);
CGLM_INLINE void glm_euler_zxy(vec3 angles, mat4 dest);
CGLM_INLINE void glm_euler_xzy(vec3 angles, mat4 dest);
CGLM_INLINE void glm_euler_yzx(vec3 angles, mat4 dest);
CGLM_INLINE void glm_euler_yxz(vec3 angles, mat4 dest);
CGLM_INLINE void glm_euler_by_order(vec3 angles,
glm_euler_sq axis,
glm_euler_sq ord,
mat4 dest);
*/
@@ -48,12 +57,12 @@ typedef enum glm_euler_sq {
CGLM_INLINE
glm_euler_sq
glm_euler_order(int newOrder[3]) {
return (glm_euler_sq)(newOrder[0] | newOrder[1] << 2 | newOrder[2] << 4);
glm_euler_order(int ord[3]) {
return (glm_euler_sq)(ord[0] << 0 | ord[1] << 2 | ord[2] << 4);
}
/*!
* @brief euler angles (in radian) using xyz sequence
* @brief extract euler angles (in radians) using xyz order
*
* @param[in] m affine transform
* @param[out] dest angles vector [x, y, z]
@@ -61,225 +70,289 @@ glm_euler_order(int newOrder[3]) {
CGLM_INLINE
void
glm_euler_angles(mat4 m, vec3 dest) {
if (m[0][2] < 1.0f) {
if (m[0][2] > -1.0f) {
vec3 a[2];
float cy1, cy2;
int path;
a[0][1] = asinf(-m[0][2]);
a[1][1] = CGLM_PI - a[0][1];
float m00, m01, m10, m11, m20, m21, m22;
float thetaX, thetaY, thetaZ;
cy1 = cosf(a[0][1]);
cy2 = cosf(a[1][1]);
m00 = m[0][0]; m10 = m[1][0]; m20 = m[2][0];
m01 = m[0][1]; m11 = m[1][1]; m21 = m[2][1];
m22 = m[2][2];
a[0][0] = atan2f(m[1][2] / cy1, m[2][2] / cy1);
a[1][0] = atan2f(m[1][2] / cy2, m[2][2] / cy2);
a[0][2] = atan2f(m[0][1] / cy1, m[0][0] / cy1);
a[1][2] = atan2f(m[0][1] / cy2, m[0][0] / cy2);
path = (fabsf(a[0][0]) + fabsf(a[0][1]) + fabsf(a[0][2])) >=
(fabsf(a[1][0]) + fabsf(a[1][1]) + fabsf(a[1][2]));
glm_vec_copy(a[path], dest);
} else {
dest[0] = atan2f(m[1][0], m[2][0]);
dest[1] = CGLM_PI_2;
dest[2] = 0.0f;
if (m20 < 1.0f) {
if (m20 > -1.0f) {
thetaY = asinf(m20);
thetaX = atan2f(-m21, m22);
thetaZ = atan2f(-m10, m00);
} else { /* m20 == -1 */
/* Not a unique solution */
thetaY = -GLM_PI_2f;
thetaX = -atan2f(m01, m11);
thetaZ = 0.0f;
}
} else {
dest[0] = atan2f(-m[1][0], -m[2][0]);
dest[1] =-CGLM_PI_2;
dest[2] = 0.0f;
} else { /* m20 == +1 */
thetaY = GLM_PI_2f;
thetaX = atan2f(m01, m11);
thetaZ = 0.0f;
}
dest[0] = thetaX;
dest[1] = thetaY;
dest[2] = thetaZ;
}
/*!
* @brief build rotation matrix from euler angles(ExEyEz/RzRyRx)
* @brief build rotation matrix from euler angles
*
* @param[in] angles angles as vector [Ex, Ey, Ez]
* @param[in] angles angles as vector [Xangle, Yangle, Zangle]
* @param[out] dest rotation matrix
*/
CGLM_INLINE
void
glm_euler_xyz(vec3 angles, mat4 dest) {
float cx, cy, cz,
sx, sy, sz, czsx, cxcz, sysz;
sx = sinf(angles[0]); cx = cosf(angles[0]);
sy = sinf(angles[1]); cy = cosf(angles[1]);
sz = sinf(angles[2]); cz = cosf(angles[2]);
czsx = cz * sx;
cxcz = cx * cz;
sysz = sy * sz;
dest[0][0] = cy * cz;
dest[0][1] = czsx * sy + cx * sz;
dest[0][2] = -cxcz * sy + sx * sz;
dest[1][0] = -cy * sz;
dest[1][1] = cxcz - sx * sysz;
dest[1][2] = czsx + cx * sysz;
dest[2][0] = sy;
dest[2][1] = -cy * sx;
dest[2][2] = cx * cy;
dest[0][3] = 0.0f;
dest[1][3] = 0.0f;
dest[2][3] = 0.0f;
dest[3][0] = 0.0f;
dest[3][1] = 0.0f;
dest[3][2] = 0.0f;
dest[3][3] = 1.0f;
}
/*!
* @brief build rotation matrix from euler angles
*
* @param[in] angles angles as vector [Xangle, Yangle, Zangle]
* @param[out] dest rotation matrix
*/
CGLM_INLINE
void
glm_euler(vec3 angles, mat4 dest) {
float cx, cy, cz,
sx, sy, sz;
sx = sinf(angles[0]); cx = cosf(angles[0]);
sy = sinf(angles[1]); cy = cosf(angles[1]);
sz = sinf(angles[2]); cz = cosf(angles[2]);
dest[0][0] = cy * cz;
dest[0][1] = cy * sz;
dest[0][2] =-sy;
dest[1][0] = cz * sx * sy - cx * sz;
dest[1][1] = cx * cz + sx * sy * sz;
dest[1][2] = cy * sx;
dest[2][0] = cx * cz * sy + sx * sz;
dest[2][1] =-cz * sx + cx * sy * sz;
dest[2][2] = cx * cy;
dest[0][3] = 0.0f;
dest[1][3] = 0.0f;
dest[2][3] = 0.0f;
dest[3][0] = 0.0f;
dest[3][1] = 0.0f;
dest[3][2] = 0.0f;
dest[3][3] = 1.0f;
glm_euler_xyz(angles, dest);
}
/*!
* @brief build rotation matrix from euler angles (EzEyEx/RxRyRz)
* @brief build rotation matrix from euler angles
*
* @param[in] angles angles as vector [Xangle, Yangle, Zangle]
* @param[out] dest rotation matrix
*/
CGLM_INLINE
void
glm_euler_zyx(vec3 angles,
mat4 dest) {
glm_euler_xzy(vec3 angles, mat4 dest) {
float cx, cy, cz,
sx, sy, sz;
sx, sy, sz, sxsy, cysx, cxsy, cxcy;
sx = sinf(angles[0]); cx = cosf(angles[0]);
sy = sinf(angles[1]); cy = cosf(angles[1]);
sz = sinf(angles[2]); cz = cosf(angles[2]);
sx = sinf(angles[0]); cx = cosf(angles[0]);
sy = sinf(angles[1]); cy = cosf(angles[1]);
sz = sinf(angles[2]); cz = cosf(angles[2]);
dest[0][0] = cy * cz;
dest[0][1] = cz * sx * sy + cx * sz;
dest[0][2] =-cx * cz * sy + sx * sz;
dest[1][0] =-cy * sz;
dest[1][1] = cx * cz - sx * sy * sz;
dest[1][2] = cz * sx + cx * sy * sz;
dest[2][0] = sy;
dest[2][1] =-cy * sx;
dest[2][2] = cx * cy;
dest[0][3] = 0.0f;
dest[1][3] = 0.0f;
dest[2][3] = 0.0f;
dest[3][0] = 0.0f;
dest[3][1] = 0.0f;
dest[3][2] = 0.0f;
dest[3][3] = 1.0f;
sxsy = sx * sy;
cysx = cy * sx;
cxsy = cx * sy;
cxcy = cx * cy;
dest[0][0] = cy * cz;
dest[0][1] = sxsy + cxcy * sz;
dest[0][2] = -cxsy + cysx * sz;
dest[1][0] = -sz;
dest[1][1] = cx * cz;
dest[1][2] = cz * sx;
dest[2][0] = cz * sy;
dest[2][1] = -cysx + cxsy * sz;
dest[2][2] = cxcy + sxsy * sz;
dest[0][3] = 0.0f;
dest[1][3] = 0.0f;
dest[2][3] = 0.0f;
dest[3][0] = 0.0f;
dest[3][1] = 0.0f;
dest[3][2] = 0.0f;
dest[3][3] = 1.0f;
}
/*!
* @brief build rotation matrix from euler angles
*
* @param[in] angles angles as vector [Xangle, Yangle, Zangle]
* @param[out] dest rotation matrix
*/
CGLM_INLINE
void
glm_euler_zxy(vec3 angles,
mat4 dest) {
glm_euler_yxz(vec3 angles, mat4 dest) {
float cx, cy, cz,
sx, sy, sz;
sx, sy, sz, cycz, sysz, czsy, cysz;
sx = sinf(angles[0]); cx = cosf(angles[0]);
sy = sinf(angles[1]); cy = cosf(angles[1]);
sz = sinf(angles[2]); cz = cosf(angles[2]);
sx = sinf(angles[0]); cx = cosf(angles[0]);
sy = sinf(angles[1]); cy = cosf(angles[1]);
sz = sinf(angles[2]); cz = cosf(angles[2]);
dest[0][0] = cy * cz + sx * sy * sz;
dest[0][1] = cx * sz;
dest[0][2] =-cz * sy + cy * sx * sz;
dest[1][0] = cz * sx * sy - cy * sz;
dest[1][1] = cx * cz;
dest[1][2] = cy * cz * sx + sy * sz;
dest[2][0] = cx * sy;
dest[2][1] =-sx;
dest[2][2] = cx * cy;
dest[0][3] = 0.0f;
dest[1][3] = 0.0f;
dest[2][3] = 0.0f;
dest[3][0] = 0.0f;
dest[3][1] = 0.0f;
dest[3][2] = 0.0f;
dest[3][3] = 1.0f;
cycz = cy * cz;
sysz = sy * sz;
czsy = cz * sy;
cysz = cy * sz;
dest[0][0] = cycz + sx * sysz;
dest[0][1] = cx * sz;
dest[0][2] = -czsy + cysz * sx;
dest[1][0] = -cysz + czsy * sx;
dest[1][1] = cx * cz;
dest[1][2] = cycz * sx + sysz;
dest[2][0] = cx * sy;
dest[2][1] = -sx;
dest[2][2] = cx * cy;
dest[0][3] = 0.0f;
dest[1][3] = 0.0f;
dest[2][3] = 0.0f;
dest[3][0] = 0.0f;
dest[3][1] = 0.0f;
dest[3][2] = 0.0f;
dest[3][3] = 1.0f;
}
/*!
* @brief build rotation matrix from euler angles
*
* @param[in] angles angles as vector [Xangle, Yangle, Zangle]
* @param[out] dest rotation matrix
*/
CGLM_INLINE
void
glm_euler_xzy(vec3 angles,
mat4 dest) {
glm_euler_yzx(vec3 angles, mat4 dest) {
float cx, cy, cz,
sx, sy, sz;
sx, sy, sz, sxsy, cxcy, cysx, cxsy;
sx = sinf(angles[0]); cx = cosf(angles[0]);
sy = sinf(angles[1]); cy = cosf(angles[1]);
sz = sinf(angles[2]); cz = cosf(angles[2]);
sx = sinf(angles[0]); cx = cosf(angles[0]);
sy = sinf(angles[1]); cy = cosf(angles[1]);
sz = sinf(angles[2]); cz = cosf(angles[2]);
dest[0][0] = cy * cz;
dest[0][1] = sz;
dest[0][2] =-cz * sy;
dest[1][0] = sx * sy - cx * cy * sz;
dest[1][1] = cx * cz;
dest[1][2] = cy * sx + cx * sy * sz;
dest[2][0] = cx * sy + cy * sx * sz;
dest[2][1] =-cz * sx;
dest[2][2] = cx * cy - sx * sy * sz;
dest[0][3] = 0.0f;
dest[1][3] = 0.0f;
dest[2][3] = 0.0f;
dest[3][0] = 0.0f;
dest[3][1] = 0.0f;
dest[3][2] = 0.0f;
dest[3][3] = 1.0f;
sxsy = sx * sy;
cxcy = cx * cy;
cysx = cy * sx;
cxsy = cx * sy;
dest[0][0] = cy * cz;
dest[0][1] = sz;
dest[0][2] = -cz * sy;
dest[1][0] = sxsy - cxcy * sz;
dest[1][1] = cx * cz;
dest[1][2] = cysx + cxsy * sz;
dest[2][0] = cxsy + cysx * sz;
dest[2][1] = -cz * sx;
dest[2][2] = cxcy - sxsy * sz;
dest[0][3] = 0.0f;
dest[1][3] = 0.0f;
dest[2][3] = 0.0f;
dest[3][0] = 0.0f;
dest[3][1] = 0.0f;
dest[3][2] = 0.0f;
dest[3][3] = 1.0f;
}
/*!
* @brief build rotation matrix from euler angles
*
* @param[in] angles angles as vector [Xangle, Yangle, Zangle]
* @param[out] dest rotation matrix
*/
CGLM_INLINE
void
glm_euler_yzx(vec3 angles,
mat4 dest) {
glm_euler_zxy(vec3 angles, mat4 dest) {
float cx, cy, cz,
sx, sy, sz;
sx, sy, sz, cycz, sxsy, cysz;
sx = sinf(angles[0]); cx = cosf(angles[0]);
sy = sinf(angles[1]); cy = cosf(angles[1]);
sz = sinf(angles[2]); cz = cosf(angles[2]);
sx = sinf(angles[0]); cx = cosf(angles[0]);
sy = sinf(angles[1]); cy = cosf(angles[1]);
sz = sinf(angles[2]); cz = cosf(angles[2]);
dest[0][0] = cy * cz;
dest[0][1] = sx * sy + cx * cy * sz;
dest[0][2] =-cx * sy + cy * sx * sz;
dest[1][0] =-sz;
dest[1][1] = cx * cz;
dest[1][2] = cz * sx;
dest[2][0] = cz * sy;
dest[2][1] =-cy * sx + cx * sy * sz;
dest[2][2] = cx * cy + sx * sy * sz;
dest[0][3] = 0.0f;
dest[1][3] = 0.0f;
dest[2][3] = 0.0f;
dest[3][0] = 0.0f;
dest[3][1] = 0.0f;
dest[3][2] = 0.0f;
dest[3][3] = 1.0f;
cycz = cy * cz;
sxsy = sx * sy;
cysz = cy * sz;
dest[0][0] = cycz - sxsy * sz;
dest[0][1] = cz * sxsy + cysz;
dest[0][2] = -cx * sy;
dest[1][0] = -cx * sz;
dest[1][1] = cx * cz;
dest[1][2] = sx;
dest[2][0] = cz * sy + cysz * sx;
dest[2][1] = -cycz * sx + sy * sz;
dest[2][2] = cx * cy;
dest[0][3] = 0.0f;
dest[1][3] = 0.0f;
dest[2][3] = 0.0f;
dest[3][0] = 0.0f;
dest[3][1] = 0.0f;
dest[3][2] = 0.0f;
dest[3][3] = 1.0f;
}
/*!
* @brief build rotation matrix from euler angles
*
* @param[in] angles angles as vector [Xangle, Yangle, Zangle]
* @param[out] dest rotation matrix
*/
CGLM_INLINE
void
glm_euler_yxz(vec3 angles,
mat4 dest) {
glm_euler_zyx(vec3 angles, mat4 dest) {
float cx, cy, cz,
sx, sy, sz;
sx, sy, sz, czsx, cxcz, sysz;
sx = sinf(angles[0]); cx = cosf(angles[0]);
sy = sinf(angles[1]); cy = cosf(angles[1]);
sz = sinf(angles[2]); cz = cosf(angles[2]);
sx = sinf(angles[0]); cx = cosf(angles[0]);
sy = sinf(angles[1]); cy = cosf(angles[1]);
sz = sinf(angles[2]); cz = cosf(angles[2]);
dest[0][0] = cy * cz - sx * sy * sz;
dest[0][1] = cz * sx * sy + cy * sz;
dest[0][2] =-cx * sy;
dest[1][0] =-cx * sz;
dest[1][1] = cx * cz;
dest[1][2] = sx;
dest[2][0] = cz * sy + cy * sx * sz;
dest[2][1] =-cy * cz * sx + sy * sz;
dest[2][2] = cx * cy;
dest[0][3] = 0.0f;
dest[1][3] = 0.0f;
dest[2][3] = 0.0f;
dest[3][0] = 0.0f;
dest[3][1] = 0.0f;
dest[3][2] = 0.0f;
dest[3][3] = 1.0f;
czsx = cz * sx;
cxcz = cx * cz;
sysz = sy * sz;
dest[0][0] = cy * cz;
dest[0][1] = cy * sz;
dest[0][2] = -sy;
dest[1][0] = czsx * sy - cx * sz;
dest[1][1] = cxcz + sx * sysz;
dest[1][2] = cy * sx;
dest[2][0] = cxcz * sy + sx * sz;
dest[2][1] = -czsx + cx * sysz;
dest[2][2] = cx * cy;
dest[0][3] = 0.0f;
dest[1][3] = 0.0f;
dest[2][3] = 0.0f;
dest[3][0] = 0.0f;
dest[3][1] = 0.0f;
dest[3][2] = 0.0f;
dest[3][3] = 1.0f;
}
/*!
* @brief build rotation matrix from euler angles
*
* @param[in] angles angles as vector [Xangle, Yangle, Zangle]
* @param[in] ord euler order
* @param[out] dest rotation matrix
*/
CGLM_INLINE
void
glm_euler_by_order(vec3 angles, glm_euler_sq axis, mat4 dest) {
glm_euler_by_order(vec3 angles, glm_euler_sq ord, mat4 dest) {
float cx, cy, cz,
sx, sy, sz;
@@ -297,72 +370,72 @@ glm_euler_by_order(vec3 angles, glm_euler_sq axis, mat4 dest) {
czsx = cz * sx; cxsz = cx * sz;
sysz = sy * sz;
switch (axis) {
case GLM_EULER_XYZ:
dest[0][0] = cycz;
dest[0][1] = cysz;
dest[0][2] =-sy;
dest[1][0] = czsx * sy - cxsz;
dest[1][1] = cxcz + sx * sysz;
dest[1][2] = cysx;
dest[2][0] = cx * czsy + sx * sz;
dest[2][1] =-czsx + cx * sysz;
dest[2][2] = cxcy;
break;
switch (ord) {
case GLM_EULER_XZY:
dest[0][0] = cycz;
dest[0][1] = sz;
dest[0][2] =-czsy;
dest[1][0] = sx * sy - cx * cysz;
dest[1][1] = cxcz;
dest[1][2] = cysx + cx * sysz;
dest[2][0] = cx * sy + cysx * sz;
dest[2][1] =-czsx;
dest[2][2] = cxcy - sx * sysz;
dest[0][0] = cycz;
dest[0][1] = sx * sy + cx * cysz;
dest[0][2] = -cx * sy + cysx * sz;
dest[1][0] = -sz;
dest[1][1] = cxcz;
dest[1][2] = czsx;
dest[2][0] = czsy;
dest[2][1] = -cysx + cx * sysz;
dest[2][2] = cxcy + sx * sysz;
break;
case GLM_EULER_ZXY:
dest[0][0] = cycz + sx * sysz;
dest[0][1] = cxsz;
dest[0][2] =-czsy + cysx * sz;
dest[1][0] = czsx * sy - cysz;
dest[1][1] = cxcz;
dest[1][2] = cycz * sx + sysz;
dest[2][0] = cx * sy;
dest[2][1] =-sx;
dest[2][2] = cxcy;
break;
case GLM_EULER_ZYX:
dest[0][0] = cycz;
dest[0][1] = czsx * sy + cxsz;
dest[0][2] =-cx * czsy + sx * sz;
dest[1][0] =-cysz;
dest[1][1] = cxcz - sx * sysz;
dest[1][2] = czsx + cx * sysz;
dest[2][0] = sy;
dest[2][1] =-cysx;
dest[2][2] = cxcy;
case GLM_EULER_XYZ:
dest[0][0] = cycz;
dest[0][1] = czsx * sy + cxsz;
dest[0][2] = -cx * czsy + sx * sz;
dest[1][0] = -cysz;
dest[1][1] = cxcz - sx * sysz;
dest[1][2] = czsx + cx * sysz;
dest[2][0] = sy;
dest[2][1] = -cysx;
dest[2][2] = cxcy;
break;
case GLM_EULER_YXZ:
dest[0][0] = cycz - sx * sysz;
dest[0][1] = czsx * sy + cysz;
dest[0][2] =-cx * sy;
dest[1][0] =-cxsz;
dest[1][1] = cxcz;
dest[1][2] = sx;
dest[2][0] = czsy + cysx * sz;
dest[2][1] =-cycz * sx + sysz;
dest[2][2] = cxcy;
dest[0][0] = cycz + sx * sysz;
dest[0][1] = cxsz;
dest[0][2] = -czsy + cysx * sz;
dest[1][0] = czsx * sy - cysz;
dest[1][1] = cxcz;
dest[1][2] = cycz * sx + sysz;
dest[2][0] = cx * sy;
dest[2][1] = -sx;
dest[2][2] = cxcy;
break;
case GLM_EULER_YZX:
dest[0][0] = cycz;
dest[0][1] = sx * sy + cx * cysz;
dest[0][2] =-cx * sy + cysx * sz;
dest[1][0] =-sz;
dest[1][1] = cxcz;
dest[1][2] = czsx;
dest[2][0] = czsy;
dest[2][1] =-cysx + cx * sysz;
dest[2][2] = cxcy + sx * sysz;
dest[0][0] = cycz;
dest[0][1] = sz;
dest[0][2] = -czsy;
dest[1][0] = sx * sy - cx * cysz;
dest[1][1] = cxcz;
dest[1][2] = cysx + cx * sysz;
dest[2][0] = cx * sy + cysx * sz;
dest[2][1] = -czsx;
dest[2][2] = cxcy - sx * sysz;
break;
case GLM_EULER_ZXY:
dest[0][0] = cycz - sx * sysz;
dest[0][1] = czsx * sy + cysz;
dest[0][2] = -cx * sy;
dest[1][0] = -cxsz;
dest[1][1] = cxcz;
dest[1][2] = sx;
dest[2][0] = czsy + cysx * sz;
dest[2][1] = -cycz * sx + sysz;
dest[2][2] = cxcy;
break;
case GLM_EULER_ZYX:
dest[0][0] = cycz;
dest[0][1] = cysz;
dest[0][2] = -sy;
dest[1][0] = czsx * sy - cxsz;
dest[1][1] = cxcz + sx * sysz;
dest[1][2] = cysx;
dest[2][0] = cx * czsy + sx * sz;
dest[2][1] = -czsx + cx * sysz;
dest[2][2] = cxcy;
break;
}

View File

@@ -10,6 +10,9 @@
#include "common.h"
#include "plane.h"
#include "vec3.h"
#include "vec4.h"
#include "mat4.h"
#define GLM_LBN 0 /* left bottom near */
#define GLM_LTN 1 /* left top near */
@@ -62,7 +65,7 @@
* Exracted planes order: [left, right, bottom, top, near, far]
*
* @param[in] m matrix (see brief)
* @param[out] dest exracted view frustum planes (see brief)
* @param[out] dest extracted view frustum planes (see brief)
*/
CGLM_INLINE
void
@@ -103,7 +106,7 @@ glm_frustum_planes(mat4 m, vec4 dest[6]) {
*
* Find center coordinates:
* for (j = 0; j < 4; j++) {
* glm_vec_center(corners[i], corners[i + 4], centerCorners[i]);
* glm_vec3_center(corners[i], corners[i + 4], centerCorners[i]);
* }
*
* @param[in] invMat matrix (see brief)
@@ -184,8 +187,8 @@ glm_frustum_box(vec4 corners[8], mat4 m, vec3 box[2]) {
vec3 min, max;
int i;
glm_vec_broadcast(FLT_MAX, min);
glm_vec_broadcast(-FLT_MAX, max);
glm_vec3_broadcast(FLT_MAX, min);
glm_vec3_broadcast(-FLT_MAX, max);
for (i = 0; i < 8; i++) {
glm_mat4_mulv(m, corners[i], v);
@@ -199,8 +202,8 @@ glm_frustum_box(vec4 corners[8], mat4 m, vec3 box[2]) {
max[2] = glm_max(max[2], v[2]);
}
glm_vec_copy(min, box[0]);
glm_vec_copy(max, box[1]);
glm_vec3_copy(min, box[0]);
glm_vec3_copy(max, box[1]);
}
/*!
@@ -225,7 +228,7 @@ glm_frustum_corners_at(vec4 corners[8],
float dist, sc;
/* because distance and scale is same for all */
dist = glm_vec_distance(corners[GLM_RTF], corners[GLM_RTN]);
dist = glm_vec3_distance(corners[GLM_RTF], corners[GLM_RTN]);
sc = dist * (splitDist / farDist);
/* left bottom */

View File

@@ -25,7 +25,7 @@
CGLM_INLINE
void
glm_mat4_print(mat4 matrix,
glm_mat4_print(mat4 matrix,
FILE * __restrict ostream) {
int i;
int j;
@@ -55,7 +55,7 @@ glm_mat4_print(mat4 matrix,
CGLM_INLINE
void
glm_mat3_print(mat3 matrix,
glm_mat3_print(mat3 matrix,
FILE * __restrict ostream) {
int i;
int j;
@@ -85,7 +85,7 @@ glm_mat3_print(mat3 matrix,
CGLM_INLINE
void
glm_vec4_print(vec4 vec,
glm_vec4_print(vec4 vec,
FILE * __restrict ostream) {
int i;
@@ -107,7 +107,7 @@ glm_vec4_print(vec4 vec,
CGLM_INLINE
void
glm_vec3_print(vec3 vec,
glm_vec3_print(vec3 vec,
FILE * __restrict ostream) {
int i;
@@ -129,7 +129,7 @@ glm_vec3_print(vec3 vec,
CGLM_INLINE
void
glm_ivec3_print(ivec3 vec,
glm_ivec3_print(ivec3 vec,
FILE * __restrict ostream) {
int i;
@@ -151,7 +151,7 @@ glm_ivec3_print(ivec3 vec,
CGLM_INLINE
void
glm_versor_print(versor vec,
glm_versor_print(versor vec,
FILE * __restrict ostream) {
int i;
@@ -171,4 +171,33 @@ glm_versor_print(versor vec,
#undef m
}
CGLM_INLINE
void
glm_aabb_print(vec3 bbox[2],
const char * __restrict tag,
FILE * __restrict ostream) {
int i, j;
#define m 3
fprintf(ostream, "AABB (%s):\n", tag ? tag: "float");
for (i = 0; i < 2; i++) {
fprintf(ostream, "\t|");
for (j = 0; j < m; j++) {
fprintf(ostream, "%0.4f", bbox[i][j]);
if (j != m - 1)
fprintf(ostream, "\t");
}
fprintf(ostream, "|\n");
}
fprintf(ostream, "\n");
#undef m
}
#endif /* cglm_io_h */

View File

@@ -16,21 +16,27 @@
Functions:
CGLM_INLINE void glm_mat3_copy(mat3 mat, mat3 dest);
CGLM_INLINE void glm_mat3_identity(mat3 mat);
CGLM_INLINE void glm_mat3_identity_array(mat3 * restrict mat, size_t count);
CGLM_INLINE void glm_mat3_zero(mat3 mat);
CGLM_INLINE void glm_mat3_mul(mat3 m1, mat3 m2, mat3 dest);
CGLM_INLINE void glm_mat3_transpose_to(mat3 m, mat3 dest);
CGLM_INLINE void glm_mat3_transpose(mat3 m);
CGLM_INLINE void glm_mat3_mulv(mat3 m, vec3 v, vec3 dest);
CGLM_INLINE float glm_mat3_trace(mat3 m);
CGLM_INLINE void glm_mat3_quat(mat3 m, versor dest);
CGLM_INLINE void glm_mat3_scale(mat3 m, float s);
CGLM_INLINE float glm_mat3_det(mat3 mat);
CGLM_INLINE void glm_mat3_inv(mat3 mat, mat3 dest);
CGLM_INLINE void glm_mat3_swap_col(mat3 mat, int col1, int col2);
CGLM_INLINE void glm_mat3_swap_row(mat3 mat, int row1, int row2);
CGLM_INLINE float glm_mat3_rmc(vec3 r, mat3 m, vec3 c);
*/
#ifndef cglm_mat3_h
#define cglm_mat3_h
#include "common.h"
#include "vec3.h"
#ifdef CGLM_SSE_FP
# include "simd/sse2/mat3.h"
@@ -45,8 +51,8 @@
/* for C only */
#define GLM_MAT3_IDENTITY (mat3)GLM_MAT3_IDENTITY_INIT
#define GLM_MAT3_ZERO (mat3)GLM_MAT3_ZERO_INIT
#define GLM_MAT3_IDENTITY ((mat3)GLM_MAT3_IDENTITY_INIT)
#define GLM_MAT3_ZERO ((mat3)GLM_MAT3_ZERO_INIT)
/* DEPRECATED! use _copy, _ucopy versions */
#define glm_mat3_dup(mat, dest) glm_mat3_copy(mat, dest)
@@ -60,7 +66,17 @@
CGLM_INLINE
void
glm_mat3_copy(mat3 mat, mat3 dest) {
glm__memcpy(float, dest, mat, sizeof(mat3));
dest[0][0] = mat[0][0];
dest[0][1] = mat[0][1];
dest[0][2] = mat[0][2];
dest[1][0] = mat[1][0];
dest[1][1] = mat[1][1];
dest[1][2] = mat[1][2];
dest[2][0] = mat[2][0];
dest[2][1] = mat[2][1];
dest[2][2] = mat[2][2];
}
/*!
@@ -80,7 +96,38 @@ glm_mat3_copy(mat3 mat, mat3 dest) {
CGLM_INLINE
void
glm_mat3_identity(mat3 mat) {
mat3 t = GLM_MAT3_IDENTITY_INIT;
CGLM_ALIGN_MAT mat3 t = GLM_MAT3_IDENTITY_INIT;
glm_mat3_copy(t, mat);
}
/*!
* @brief make given matrix array's each element identity matrix
*
* @param[in, out] mat matrix array (must be aligned (16/32)
* if alignment is not disabled)
*
* @param[in] count count of matrices
*/
CGLM_INLINE
void
glm_mat3_identity_array(mat3 * __restrict mat, size_t count) {
CGLM_ALIGN_MAT mat3 t = GLM_MAT3_IDENTITY_INIT;
size_t i;
for (i = 0; i < count; i++) {
glm_mat3_copy(t, mat[i]);
}
}
/*!
* @brief make given matrix zero.
*
* @param[in, out] mat matrix
*/
CGLM_INLINE
void
glm_mat3_zero(mat3 mat) {
CGLM_ALIGN_MAT mat3 t = GLM_MAT3_ZERO_INIT;
glm_mat3_copy(t, mat);
}
@@ -154,7 +201,7 @@ glm_mat3_transpose_to(mat3 m, mat3 dest) {
CGLM_INLINE
void
glm_mat3_transpose(mat3 m) {
mat3 tmp;
CGLM_ALIGN_MAT mat3 tmp;
tmp[0][1] = m[1][0];
tmp[0][2] = m[2][0];
@@ -186,6 +233,68 @@ glm_mat3_mulv(mat3 m, vec3 v, vec3 dest) {
dest[2] = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2];
}
/*!
* @brief trace of matrix
*
* sum of the elements on the main diagonal from upper left to the lower right
*
* @param[in] m matrix
*/
CGLM_INLINE
float
glm_mat3_trace(mat3 m) {
return m[0][0] + m[1][1] + m[2][2];
}
/*!
* @brief convert mat3 to quaternion
*
* @param[in] m rotation matrix
* @param[out] dest destination quaternion
*/
CGLM_INLINE
void
glm_mat3_quat(mat3 m, versor dest) {
float trace, r, rinv;
/* it seems using like m12 instead of m[1][2] causes extra instructions */
trace = m[0][0] + m[1][1] + m[2][2];
if (trace >= 0.0f) {
r = sqrtf(1.0f + trace);
rinv = 0.5f / r;
dest[0] = rinv * (m[1][2] - m[2][1]);
dest[1] = rinv * (m[2][0] - m[0][2]);
dest[2] = rinv * (m[0][1] - m[1][0]);
dest[3] = r * 0.5f;
} else if (m[0][0] >= m[1][1] && m[0][0] >= m[2][2]) {
r = sqrtf(1.0f - m[1][1] - m[2][2] + m[0][0]);
rinv = 0.5f / r;
dest[0] = r * 0.5f;
dest[1] = rinv * (m[0][1] + m[1][0]);
dest[2] = rinv * (m[0][2] + m[2][0]);
dest[3] = rinv * (m[1][2] - m[2][1]);
} else if (m[1][1] >= m[2][2]) {
r = sqrtf(1.0f - m[0][0] - m[2][2] + m[1][1]);
rinv = 0.5f / r;
dest[0] = rinv * (m[0][1] + m[1][0]);
dest[1] = r * 0.5f;
dest[2] = rinv * (m[1][2] + m[2][1]);
dest[3] = rinv * (m[2][0] - m[0][2]);
} else {
r = sqrtf(1.0f - m[0][0] - m[1][1] + m[2][2]);
rinv = 0.5f / r;
dest[0] = rinv * (m[0][2] + m[2][0]);
dest[1] = rinv * (m[1][2] + m[2][1]);
dest[2] = r * 0.5f;
dest[3] = rinv * (m[0][1] - m[1][0]);
}
}
/*!
* @brief scale (multiply with scalar) matrix
*
@@ -259,9 +368,9 @@ CGLM_INLINE
void
glm_mat3_swap_col(mat3 mat, int col1, int col2) {
vec3 tmp;
glm_vec_copy(mat[col1], tmp);
glm_vec_copy(mat[col2], mat[col1]);
glm_vec_copy(tmp, mat[col2]);
glm_vec3_copy(mat[col1], tmp);
glm_vec3_copy(mat[col2], mat[col1]);
glm_vec3_copy(tmp, mat[col2]);
}
/*!
@@ -288,4 +397,26 @@ glm_mat3_swap_row(mat3 mat, int row1, int row2) {
mat[2][row2] = tmp[2];
}
/*!
* @brief helper for R (row vector) * M (matrix) * C (column vector)
*
* rmc stands for Row * Matrix * Column
*
* the result is scalar because R * M = Matrix1x3 (row vector),
* then Matrix1x3 * Vec3 (column vector) = Matrix1x1 (Scalar)
*
* @param[in] r row vector or matrix1x3
* @param[in] m matrix3x3
* @param[in] c column vector or matrix3x1
*
* @return scalar value e.g. Matrix1x1
*/
CGLM_INLINE
float
glm_mat3_rmc(vec3 r, mat3 m, vec3 c) {
vec3 tmp;
glm_mat3_mulv(m, c, tmp);
return glm_vec3_dot(r, tmp);
}
#endif /* cglm_mat3_h */

View File

@@ -16,13 +16,13 @@
GLM_MAT4_ZERO_INIT
GLM_MAT4_IDENTITY
GLM_MAT4_ZERO
glm_mat4_udup(mat, dest)
glm_mat4_dup(mat, dest)
Functions:
CGLM_INLINE void glm_mat4_ucopy(mat4 mat, mat4 dest);
CGLM_INLINE void glm_mat4_copy(mat4 mat, mat4 dest);
CGLM_INLINE void glm_mat4_identity(mat4 mat);
CGLM_INLINE void glm_mat4_identity_array(mat4 * restrict mat, size_t count);
CGLM_INLINE void glm_mat4_zero(mat4 mat);
CGLM_INLINE void glm_mat4_pick3(mat4 mat, mat3 dest);
CGLM_INLINE void glm_mat4_pick3t(mat4 mat, mat3 dest);
CGLM_INLINE void glm_mat4_ins3(mat3 mat, mat4 dest);
@@ -30,6 +30,9 @@
CGLM_INLINE void glm_mat4_mulN(mat4 *matrices[], int len, mat4 dest);
CGLM_INLINE void glm_mat4_mulv(mat4 m, vec4 v, vec4 dest);
CGLM_INLINE void glm_mat4_mulv3(mat4 m, vec3 v, vec3 dest);
CGLM_INLINE float glm_mat4_trace(mat4 m);
CGLM_INLINE float glm_mat4_trace3(mat4 m);
CGLM_INLINE void glm_mat4_quat(mat4 m, versor dest) ;
CGLM_INLINE void glm_mat4_transpose_to(mat4 m, mat4 dest);
CGLM_INLINE void glm_mat4_transpose(mat4 m);
CGLM_INLINE void glm_mat4_scale_p(mat4 m, float s);
@@ -39,12 +42,15 @@
CGLM_INLINE void glm_mat4_inv_fast(mat4 mat, mat4 dest);
CGLM_INLINE void glm_mat4_swap_col(mat4 mat, int col1, int col2);
CGLM_INLINE void glm_mat4_swap_row(mat4 mat, int row1, int row2);
CGLM_INLINE float glm_mat4_rmc(vec4 r, mat4 m, vec4 c);
*/
#ifndef cglm_mat_h
#define cglm_mat_h
#include "common.h"
#include "vec4.h"
#include "vec3.h"
#ifdef CGLM_SSE_FP
# include "simd/sse2/mat4.h"
@@ -58,7 +64,9 @@
# include "simd/neon/mat4.h"
#endif
#include <assert.h>
#ifdef DEBUG
# include <assert.h>
#endif
#define GLM_MAT4_IDENTITY_INIT {{1.0f, 0.0f, 0.0f, 0.0f}, \
{0.0f, 1.0f, 0.0f, 0.0f}, \
@@ -71,8 +79,8 @@
{0.0f, 0.0f, 0.0f, 0.0f}}
/* for C only */
#define GLM_MAT4_IDENTITY (mat4)GLM_MAT4_IDENTITY_INIT
#define GLM_MAT4_ZERO (mat4)GLM_MAT4_ZERO_INIT
#define GLM_MAT4_IDENTITY ((mat4)GLM_MAT4_IDENTITY_INIT)
#define GLM_MAT4_ZERO ((mat4)GLM_MAT4_ZERO_INIT)
/* DEPRECATED! use _copy, _ucopy versions */
#define glm_mat4_udup(mat, dest) glm_mat4_ucopy(mat, dest)
@@ -93,7 +101,15 @@
CGLM_INLINE
void
glm_mat4_ucopy(mat4 mat, mat4 dest) {
glm__memcpy(float, dest, mat, sizeof(mat4));
dest[0][0] = mat[0][0]; dest[1][0] = mat[1][0];
dest[0][1] = mat[0][1]; dest[1][1] = mat[1][1];
dest[0][2] = mat[0][2]; dest[1][2] = mat[1][2];
dest[0][3] = mat[0][3]; dest[1][3] = mat[1][3];
dest[2][0] = mat[2][0]; dest[3][0] = mat[3][0];
dest[2][1] = mat[2][1]; dest[3][1] = mat[3][1];
dest[2][2] = mat[2][2]; dest[3][2] = mat[3][2];
dest[2][3] = mat[2][3]; dest[3][3] = mat[3][3];
}
/*!
@@ -106,13 +122,18 @@ CGLM_INLINE
void
glm_mat4_copy(mat4 mat, mat4 dest) {
#ifdef __AVX__
_mm256_store_ps(dest[0], _mm256_load_ps(mat[0]));
_mm256_store_ps(dest[2], _mm256_load_ps(mat[2]));
glmm_store256(dest[0], glmm_load256(mat[0]));
glmm_store256(dest[2], glmm_load256(mat[2]));
#elif defined( __SSE__ ) || defined( __SSE2__ )
_mm_store_ps(dest[0], _mm_load_ps(mat[0]));
_mm_store_ps(dest[1], _mm_load_ps(mat[1]));
_mm_store_ps(dest[2], _mm_load_ps(mat[2]));
_mm_store_ps(dest[3], _mm_load_ps(mat[3]));
glmm_store(dest[0], glmm_load(mat[0]));
glmm_store(dest[1], glmm_load(mat[1]));
glmm_store(dest[2], glmm_load(mat[2]));
glmm_store(dest[3], glmm_load(mat[3]));
#elif defined(CGLM_NEON_FP)
vst1q_f32(dest[0], vld1q_f32(mat[0]));
vst1q_f32(dest[1], vld1q_f32(mat[1]));
vst1q_f32(dest[2], vld1q_f32(mat[2]));
vst1q_f32(dest[3], vld1q_f32(mat[3]));
#else
glm_mat4_ucopy(mat, dest);
#endif
@@ -135,7 +156,38 @@ glm_mat4_copy(mat4 mat, mat4 dest) {
CGLM_INLINE
void
glm_mat4_identity(mat4 mat) {
mat4 t = GLM_MAT4_IDENTITY_INIT;
CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT;
glm_mat4_copy(t, mat);
}
/*!
* @brief make given matrix array's each element identity matrix
*
* @param[in, out] mat matrix array (must be aligned (16/32)
* if alignment is not disabled)
*
* @param[in] count count of matrices
*/
CGLM_INLINE
void
glm_mat4_identity_array(mat4 * __restrict mat, size_t count) {
CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT;
size_t i;
for (i = 0; i < count; i++) {
glm_mat4_copy(t, mat[i]);
}
}
/*!
* @brief make given matrix zero.
*
* @param[in, out] mat matrix
*/
CGLM_INLINE
void
glm_mat4_zero(mat4 mat) {
CGLM_ALIGN_MAT mat4 t = GLM_MAT4_ZERO_INIT;
glm_mat4_copy(t, mat);
}
@@ -228,7 +280,7 @@ glm_mat4_mul(mat4 m1, mat4 m2, mat4 dest) {
glm_mat4_mul_avx(m1, m2, dest);
#elif defined( __SSE__ ) || defined( __SSE2__ )
glm_mat4_mul_sse2(m1, m2, dest);
#elif defined( __ARM_NEON_FP )
#elif defined(CGLM_NEON_FP)
glm_mat4_mul_neon(m1, m2, dest);
#else
float a00 = m1[0][0], a01 = m1[0][1], a02 = m1[0][2], a03 = m1[0][3],
@@ -281,19 +333,17 @@ glm_mat4_mul(mat4 m1, mat4 m2, mat4 dest) {
*/
CGLM_INLINE
void
glm_mat4_mulN(mat4 * __restrict matrices[], int len, mat4 dest) {
int i;
glm_mat4_mulN(mat4 * __restrict matrices[], uint32_t len, mat4 dest) {
uint32_t i;
#ifdef DEBUG
assert(len > 1 && "there must be least 2 matrices to go!");
#endif
glm_mat4_mul(*matrices[0],
*matrices[1],
dest);
glm_mat4_mul(*matrices[0], *matrices[1], dest);
for (i = 2; i < len; i++)
glm_mat4_mul(dest,
*matrices[i],
dest);
glm_mat4_mul(dest, *matrices[i], dest);
}
/*!
@@ -319,20 +369,95 @@ glm_mat4_mulv(mat4 m, vec4 v, vec4 dest) {
}
/*!
* @brief multiply vector with mat4's mat3 part(rotation)
* @brief trace of matrix
*
* @param[in] m mat4(affine transform)
* @param[in] v vec3
* @param[out] dest vec3
* sum of the elements on the main diagonal from upper left to the lower right
*
* @param[in] m matrix
*/
CGLM_INLINE
float
glm_mat4_trace(mat4 m) {
return m[0][0] + m[1][1] + m[2][2] + m[3][3];
}
/*!
* @brief trace of matrix (rotation part)
*
* sum of the elements on the main diagonal from upper left to the lower right
*
* @param[in] m matrix
*/
CGLM_INLINE
float
glm_mat4_trace3(mat4 m) {
return m[0][0] + m[1][1] + m[2][2];
}
/*!
* @brief convert mat4's rotation part to quaternion
*
* @param[in] m affine matrix
* @param[out] dest destination quaternion
*/
CGLM_INLINE
void
glm_mat4_mulv3(mat4 m, vec3 v, vec3 dest) {
vec3 res;
res[0] = m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2];
res[1] = m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2];
res[2] = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2];
glm_vec_copy(res, dest);
glm_mat4_quat(mat4 m, versor dest) {
float trace, r, rinv;
/* it seems using like m12 instead of m[1][2] causes extra instructions */
trace = m[0][0] + m[1][1] + m[2][2];
if (trace >= 0.0f) {
r = sqrtf(1.0f + trace);
rinv = 0.5f / r;
dest[0] = rinv * (m[1][2] - m[2][1]);
dest[1] = rinv * (m[2][0] - m[0][2]);
dest[2] = rinv * (m[0][1] - m[1][0]);
dest[3] = r * 0.5f;
} else if (m[0][0] >= m[1][1] && m[0][0] >= m[2][2]) {
r = sqrtf(1.0f - m[1][1] - m[2][2] + m[0][0]);
rinv = 0.5f / r;
dest[0] = r * 0.5f;
dest[1] = rinv * (m[0][1] + m[1][0]);
dest[2] = rinv * (m[0][2] + m[2][0]);
dest[3] = rinv * (m[1][2] - m[2][1]);
} else if (m[1][1] >= m[2][2]) {
r = sqrtf(1.0f - m[0][0] - m[2][2] + m[1][1]);
rinv = 0.5f / r;
dest[0] = rinv * (m[0][1] + m[1][0]);
dest[1] = r * 0.5f;
dest[2] = rinv * (m[1][2] + m[2][1]);
dest[3] = rinv * (m[2][0] - m[0][2]);
} else {
r = sqrtf(1.0f - m[0][0] - m[1][1] + m[2][2]);
rinv = 0.5f / r;
dest[0] = rinv * (m[0][2] + m[2][0]);
dest[1] = rinv * (m[1][2] + m[2][1]);
dest[2] = r * 0.5f;
dest[3] = rinv * (m[0][1] - m[1][0]);
}
}
/*!
* @brief multiply vector with mat4
*
* @param[in] m mat4(affine transform)
* @param[in] v vec3
* @param[in] last 4th item to make it vec4
* @param[out] dest result vector (vec3)
*/
CGLM_INLINE
void
glm_mat4_mulv3(mat4 m, vec3 v, float last, vec3 dest) {
vec4 res;
glm_vec4(v, last, res);
glm_mat4_mulv(m, res, res);
glm_vec3(res, dest);
}
/*!
@@ -372,10 +497,8 @@ glm_mat4_transpose(mat4 m) {
glm_mat4_transp_sse2(m, m);
#else
mat4 d;
glm_mat4_transpose_to(m, d);
glm__memcpy(float, m, d, sizeof(mat4));
glm_mat4_ucopy(d, m);
#endif
}
@@ -409,6 +532,13 @@ void
glm_mat4_scale(mat4 m, float s) {
#if defined( __SSE__ ) || defined( __SSE2__ )
glm_mat4_scale_sse2(m, s);
#elif defined(CGLM_NEON_FP)
float32x4_t v0;
v0 = vdupq_n_f32(s);
vst1q_f32(m[0], vmulq_f32(vld1q_f32(m[0]), v0));
vst1q_f32(m[1], vmulq_f32(vld1q_f32(m[1]), v0));
vst1q_f32(m[2], vmulq_f32(vld1q_f32(m[2]), v0));
vst1q_f32(m[3], vmulq_f32(vld1q_f32(m[3]), v0));
#else
glm_mat4_scale_p(m, s);
#endif
@@ -535,7 +665,7 @@ glm_mat4_inv_fast(mat4 mat, mat4 dest) {
CGLM_INLINE
void
glm_mat4_swap_col(mat4 mat, int col1, int col2) {
vec4 tmp;
CGLM_ALIGN(16) vec4 tmp;
glm_vec4_copy(mat[col1], tmp);
glm_vec4_copy(mat[col2], mat[col1]);
glm_vec4_copy(tmp, mat[col2]);
@@ -551,7 +681,7 @@ glm_mat4_swap_col(mat4 mat, int col1, int col2) {
CGLM_INLINE
void
glm_mat4_swap_row(mat4 mat, int row1, int row2) {
vec4 tmp;
CGLM_ALIGN(16) vec4 tmp;
tmp[0] = mat[0][row1];
tmp[1] = mat[1][row1];
tmp[2] = mat[2][row1];
@@ -568,5 +698,26 @@ glm_mat4_swap_row(mat4 mat, int row1, int row2) {
mat[3][row2] = tmp[3];
}
#else
/*!
* @brief helper for R (row vector) * M (matrix) * C (column vector)
*
* rmc stands for Row * Matrix * Column
*
* the result is scalar because R * M = Matrix1x4 (row vector),
* then Matrix1x4 * Vec4 (column vector) = Matrix1x1 (Scalar)
*
* @param[in] r row vector or matrix1x4
* @param[in] m matrix4x4
* @param[in] c column vector or matrix4x1
*
* @return scalar value e.g. B(s)
*/
CGLM_INLINE
float
glm_mat4_rmc(vec4 r, mat4 m, vec4 c) {
vec4 tmp;
glm_mat4_mulv(m, c, tmp);
return glm_vec4_dot(r, tmp);
}
#endif /* cglm_mat_h */

View File

@@ -9,9 +9,7 @@
#define cglm_plane_h
#include "common.h"
#include "mat4.h"
#include "vec4.h"
#include "vec3.h"
/*
Plane equation: Ax + By + Cz + D = 0;
@@ -27,12 +25,12 @@
/*!
* @brief normalizes a plane
*
* @param[in, out] plane pnale to normalize
* @param[in, out] plane plane to normalize
*/
CGLM_INLINE
void
glm_plane_normalize(vec4 plane) {
glm_vec4_scale(plane, 1.0f / glm_vec_norm(plane), plane);
glm_vec4_scale(plane, 1.0f / glm_vec3_norm(plane), plane);
}
#endif /* cglm_plane_h */

118
include/cglm/project.h Normal file
View File

@@ -0,0 +1,118 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglm_project_h
#define cglm_project_h
#include "common.h"
#include "vec3.h"
#include "vec4.h"
#include "mat4.h"
/*!
* @brief 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
*
* [1] space:
* 1- if m = invProj: View Space
* 2- if m = invViewProj: World Space
* 3- if m = invMVP: Object Space
*
* You probably want to map the coordinates into object space
* so use invMVP as m
*
* Computing viewProj:
* glm_mat4_mul(proj, view, viewProj);
* glm_mat4_mul(viewProj, model, MVP);
* glm_mat4_inv(viewProj, invMVP);
*
* @param[in] pos point/position in viewport coordinates
* @param[in] invMat matrix (see brief)
* @param[in] vp viewport as [x, y, width, height]
* @param[out] dest unprojected coordinates
*/
CGLM_INLINE
void
glm_unprojecti(vec3 pos, mat4 invMat, vec4 vp, vec3 dest) {
vec4 v;
v[0] = 2.0f * (pos[0] - vp[0]) / vp[2] - 1.0f;
v[1] = 2.0f * (pos[1] - vp[1]) / vp[3] - 1.0f;
v[2] = 2.0f * pos[2] - 1.0f;
v[3] = 1.0f;
glm_mat4_mulv(invMat, v, v);
glm_vec4_scale(v, 1.0f / v[3], v);
glm_vec3(v, dest);
}
/*!
* @brief 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
* you.
*
* [1] space:
* 1- if m = proj: View Space
* 2- if m = viewProj: World Space
* 3- if m = MVP: Object Space
*
* You probably want to map the coordinates into object space
* so use MVP as m
*
* Computing viewProj and MVP:
* glm_mat4_mul(proj, view, viewProj);
* glm_mat4_mul(viewProj, model, MVP);
*
* @param[in] pos point/position in viewport coordinates
* @param[in] m matrix (see brief)
* @param[in] vp viewport as [x, y, width, height]
* @param[out] dest unprojected coordinates
*/
CGLM_INLINE
void
glm_unproject(vec3 pos, mat4 m, vec4 vp, vec3 dest) {
mat4 inv;
glm_mat4_inv(m, inv);
glm_unprojecti(pos, inv, vp, dest);
}
/*!
* @brief map object coordinates to window coordinates
*
* Computing MVP:
* glm_mat4_mul(proj, view, viewProj);
* glm_mat4_mul(viewProj, model, MVP);
*
* @param[in] pos object coordinates
* @param[in] m MVP matrix
* @param[in] vp viewport as [x, y, width, height]
* @param[out] dest projected coordinates
*/
CGLM_INLINE
void
glm_project(vec3 pos, mat4 m, vec4 vp, vec3 dest) {
CGLM_ALIGN(16) vec4 pos4, vone = GLM_VEC4_ONE_INIT;
glm_vec4(pos, 1.0f, pos4);
glm_mat4_mulv(m, pos4, pos4);
glm_vec4_scale(pos4, 1.0f / pos4[3], pos4); /* pos = pos / pos.w */
glm_vec4_add(pos4, vone, pos4);
glm_vec4_scale(pos4, 0.5f, pos4);
dest[0] = pos4[0] * vp[2] + vp[0];
dest[1] = pos4[1] * vp[3] + vp[1];
dest[2] = pos4[2];
}
#endif /* cglm_project_h */

View File

@@ -11,42 +11,85 @@
GLM_QUAT_IDENTITY
Functions:
CGLM_INLINE void glm_quat_identity(versor q);
CGLM_INLINE void glm_quat(versor q, float angle, float x, float y, float z);
CGLM_INLINE void glm_quatv(versor q, float angle, vec3 v);
CGLM_INLINE void glm_quat_identity(versor q);
CGLM_INLINE void glm_quat_init(versor q, float x, float y, float z, float w);
CGLM_INLINE void glm_quat(versor q, float angle, float x, float y, float z);
CGLM_INLINE void glm_quatv(versor q, float angle, vec3 axis);
CGLM_INLINE void glm_quat_copy(versor q, versor dest);
CGLM_INLINE float glm_quat_norm(versor q);
CGLM_INLINE void glm_quat_normalize(versor q);
CGLM_INLINE float glm_quat_dot(versor q, versor r);
CGLM_INLINE void glm_quat_mulv(versor q1, versor q2, versor dest);
CGLM_INLINE void glm_quat_mat4(versor q, mat4 dest);
CGLM_INLINE void glm_quat_slerp(versor q, versor r, float t, versor dest);
CGLM_INLINE void glm_quat_normalize(versor q);
CGLM_INLINE void glm_quat_normalize_to(versor q, versor dest);
CGLM_INLINE float glm_quat_dot(versor p, versor q);
CGLM_INLINE void glm_quat_conjugate(versor q, versor dest);
CGLM_INLINE void glm_quat_inv(versor q, versor dest);
CGLM_INLINE void glm_quat_add(versor p, versor q, versor dest);
CGLM_INLINE void glm_quat_sub(versor p, versor q, versor dest);
CGLM_INLINE float glm_quat_real(versor q);
CGLM_INLINE void glm_quat_imag(versor q, vec3 dest);
CGLM_INLINE void glm_quat_imagn(versor q, vec3 dest);
CGLM_INLINE float glm_quat_imaglen(versor q);
CGLM_INLINE float glm_quat_angle(versor q);
CGLM_INLINE void glm_quat_axis(versor q, vec3 dest);
CGLM_INLINE void glm_quat_mul(versor p, versor q, versor dest);
CGLM_INLINE void glm_quat_mat4(versor q, mat4 dest);
CGLM_INLINE void glm_quat_mat4t(versor q, mat4 dest);
CGLM_INLINE void glm_quat_mat3(versor q, mat3 dest);
CGLM_INLINE void glm_quat_mat3t(versor q, mat3 dest);
CGLM_INLINE void glm_quat_lerp(versor from, versor to, float t, versor dest);
CGLM_INLINE void glm_quat_slerp(versor q, versor r, float t, versor dest);
CGLM_INLINE void glm_quat_look(vec3 eye, versor ori, mat4 dest);
CGLM_INLINE void glm_quat_for(vec3 dir, vec3 fwd, vec3 up, versor dest);
CGLM_INLINE void glm_quat_forp(vec3 from,
vec3 to,
vec3 fwd,
vec3 up,
versor dest);
CGLM_INLINE void glm_quat_rotatev(versor q, vec3 v, vec3 dest);
CGLM_INLINE void glm_quat_rotate(mat4 m, versor q, mat4 dest);
*/
#ifndef cglm_quat_h
#define cglm_quat_h
#include "common.h"
#include "vec3.h"
#include "vec4.h"
#include "mat4.h"
#include "mat3.h"
#include "affine-mat.h"
#ifdef CGLM_SSE_FP
# include "simd/sse2/quat.h"
#endif
CGLM_INLINE
void
glm_mat4_identity(mat4 mat);
CGLM_INLINE
void
glm_mat4_mulv(mat4 m, vec4 v, vec4 dest);
CGLM_INLINE
void
glm_mul_rot(mat4 m1, mat4 m2, mat4 dest);
CGLM_INLINE
void
glm_translate(mat4 m, vec3 v);
/*
* IMPORTANT! cglm stores quat as [w, x, y, z]
* IMPORTANT:
* ----------------------------------------------------------------------------
* cglm stores quat as [x, y, z, w] since v0.3.6
*
* Possible changes (these may be changed in the future):
* - versor is identity quat, we can define new type for quat.
* it can't be quat or quaternion becuase someone can use that name for
* variable name. maybe just vec4.
* - it stores [w, x, y, z] but it may change to [x, y, z, w] if we get enough
* feedback to change it.
* - in general we use last param as dest, but this header used first param
* as dest this may be changed but decided yet
* it was [w, x, y, z] before v0.3.6 it has been changed to [x, y, z, w]
* with v0.3.6 version.
* ----------------------------------------------------------------------------
*/
#define GLM_QUAT_IDENTITY_INIT {1.0f, 0.0f, 0.0f, 0.0f}
#define GLM_QUAT_IDENTITY (versor)GLM_QUAT_IDENTITY_INIT
#define GLM_QUAT_IDENTITY_INIT {0.0f, 0.0f, 0.0f, 1.0f}
#define GLM_QUAT_IDENTITY ((versor)GLM_QUAT_IDENTITY_INIT)
/*!
* @brief makes given quat to identity
@@ -56,10 +99,72 @@
CGLM_INLINE
void
glm_quat_identity(versor q) {
versor v = GLM_QUAT_IDENTITY_INIT;
CGLM_ALIGN(16) versor v = GLM_QUAT_IDENTITY_INIT;
glm_vec4_copy(v, q);
}
/*!
* @brief make given quaternion array's each element identity quaternion
*
* @param[in, out] q quat array (must be aligned (16)
* if alignment is not disabled)
*
* @param[in] count count of quaternions
*/
CGLM_INLINE
void
glm_quat_identity_array(versor * __restrict q, size_t count) {
CGLM_ALIGN(16) versor v = GLM_QUAT_IDENTITY_INIT;
size_t i;
for (i = 0; i < count; i++) {
glm_vec4_copy(v, q[i]);
}
}
/*!
* @brief inits quaterion with raw values
*
* @param[out] q quaternion
* @param[in] x x
* @param[in] y y
* @param[in] z z
* @param[in] w w (real part)
*/
CGLM_INLINE
void
glm_quat_init(versor q, float x, float y, float z, float w) {
q[0] = x;
q[1] = y;
q[2] = z;
q[3] = w;
}
/*!
* @brief creates NEW quaternion with axis vector
*
* @param[out] q quaternion
* @param[in] angle angle (radians)
* @param[in] axis axis
*/
CGLM_INLINE
void
glm_quatv(versor q, float angle, vec3 axis) {
CGLM_ALIGN(8) vec3 k;
float a, c, s;
a = angle * 0.5f;
c = cosf(a);
s = sinf(a);
glm_normalize_to(axis, k);
q[0] = s * k[0];
q[1] = s * k[1];
q[2] = s * k[2];
q[3] = c;
}
/*!
* @brief creates NEW quaternion with individual axis components
*
@@ -71,45 +176,21 @@ glm_quat_identity(versor q) {
*/
CGLM_INLINE
void
glm_quat(versor q,
float angle,
float x,
float y,
float z) {
float a, c, s;
a = angle * 0.5f;
c = cosf(a);
s = sinf(a);
q[0] = c;
q[1] = s * x;
q[2] = s * y;
q[3] = s * z;
glm_quat(versor q, float angle, float x, float y, float z) {
CGLM_ALIGN(8) vec3 axis = {x, y, z};
glm_quatv(q, angle, axis);
}
/*!
* @brief creates NEW quaternion with axis vector
* @brief copy quaternion to another one
*
* @param[out] q quaternion
* @param[in] angle angle (radians)
* @param[in] v axis
* @param[in] q quaternion
* @param[out] dest destination
*/
CGLM_INLINE
void
glm_quatv(versor q,
float angle,
vec3 v) {
float a, c, s;
a = angle * 0.5f;
c = cosf(a);
s = sinf(a);
q[0] = c;
q[1] = s * v[0];
q[2] = s * v[1];
q[3] = s * v[2];
glm_quat_copy(versor q, versor dest) {
glm_vec4_copy(q, dest);
}
/*!
@@ -123,6 +204,43 @@ glm_quat_norm(versor q) {
return glm_vec4_norm(q);
}
/*!
* @brief normalize quaternion and store result in dest
*
* @param[in] q quaternion to normalze
* @param[out] dest destination quaternion
*/
CGLM_INLINE
void
glm_quat_normalize_to(versor q, versor dest) {
#if defined( __SSE2__ ) || defined( __SSE2__ )
__m128 xdot, x0;
float dot;
x0 = glmm_load(q);
xdot = glmm_vdot(x0, x0);
dot = _mm_cvtss_f32(xdot);
if (dot <= 0.0f) {
glm_quat_identity(dest);
return;
}
glmm_store(dest, _mm_div_ps(x0, _mm_sqrt_ps(xdot)));
#else
float dot;
dot = glm_vec4_norm2(q);
if (dot <= 0.0f) {
glm_quat_identity(dest);
return;
}
glm_vec4_scale(q, 1.0f / sqrtf(dot), dest);
#endif
}
/*!
* @brief normalize quaternion
*
@@ -131,45 +249,178 @@ glm_quat_norm(versor q) {
CGLM_INLINE
void
glm_quat_normalize(versor q) {
float sum;
sum = q[0] * q[0] + q[1] * q[1]
+ q[2] * q[2] + q[3] * q[3];
if (fabs(1.0f - sum) < 0.0001f)
return;
glm_vec4_scale(q, 1.0f / sqrtf(sum), q);
glm_quat_normalize_to(q, q);
}
/*!
* @brief dot product of two quaternion
*
* @param[in] q quaternion 1
* @param[in] r quaternion 2
* @param[in] p quaternion 1
* @param[in] q quaternion 2
*/
CGLM_INLINE
float
glm_quat_dot(versor q, versor r) {
return glm_vec4_dot(q, r);
glm_quat_dot(versor p, versor q) {
return glm_vec4_dot(p, q);
}
/*!
* @brief conjugate of quaternion
*
* @param[in] q quaternion
* @param[out] dest conjugate
*/
CGLM_INLINE
void
glm_quat_conjugate(versor q, versor dest) {
glm_vec4_negate_to(q, dest);
dest[3] = -dest[3];
}
/*!
* @brief inverse of non-zero quaternion
*
* @param[in] q quaternion
* @param[out] dest inverse quaternion
*/
CGLM_INLINE
void
glm_quat_inv(versor q, versor dest) {
CGLM_ALIGN(16) versor conj;
glm_quat_conjugate(q, conj);
glm_vec4_scale(conj, 1.0f / glm_vec4_norm2(q), dest);
}
/*!
* @brief add (componentwise) two quaternions and store result in dest
*
* @param[in] p quaternion 1
* @param[in] q quaternion 2
* @param[out] dest result quaternion
*/
CGLM_INLINE
void
glm_quat_add(versor p, versor q, versor dest) {
glm_vec4_add(p, q, dest);
}
/*!
* @brief subtract (componentwise) two quaternions and store result in dest
*
* @param[in] p quaternion 1
* @param[in] q quaternion 2
* @param[out] dest result quaternion
*/
CGLM_INLINE
void
glm_quat_sub(versor p, versor q, versor dest) {
glm_vec4_sub(p, q, dest);
}
/*!
* @brief returns real part of quaternion
*
* @param[in] q quaternion
*/
CGLM_INLINE
float
glm_quat_real(versor q) {
return q[3];
}
/*!
* @brief returns imaginary part of quaternion
*
* @param[in] q quaternion
* @param[out] dest imag
*/
CGLM_INLINE
void
glm_quat_imag(versor q, vec3 dest) {
dest[0] = q[0];
dest[1] = q[1];
dest[2] = q[2];
}
/*!
* @brief returns normalized imaginary part of quaternion
*
* @param[in] q quaternion
*/
CGLM_INLINE
void
glm_quat_imagn(versor q, vec3 dest) {
glm_normalize_to(q, dest);
}
/*!
* @brief returns length of imaginary part of quaternion
*
* @param[in] q quaternion
*/
CGLM_INLINE
float
glm_quat_imaglen(versor q) {
return glm_vec3_norm(q);
}
/*!
* @brief returns angle of quaternion
*
* @param[in] q quaternion
*/
CGLM_INLINE
float
glm_quat_angle(versor q) {
/*
sin(theta / 2) = length(x*x + y*y + z*z)
cos(theta / 2) = w
theta = 2 * atan(sin(theta / 2) / cos(theta / 2))
*/
return 2.0f * atan2f(glm_quat_imaglen(q), glm_quat_real(q));
}
/*!
* @brief axis of quaternion
*
* @param[in] q quaternion
* @param[out] dest axis of quaternion
*/
CGLM_INLINE
void
glm_quat_axis(versor q, vec3 dest) {
glm_quat_imagn(q, dest);
}
/*!
* @brief multiplies two quaternion and stores result in dest
* this is also called Hamilton Product
*
* @param[in] q1 quaternion 1
* @param[in] q2 quaternion 2
* According to WikiPedia:
* The product of two rotation quaternions [clarification needed] will be
* equivalent to the rotation q followed by the rotation p
*
* @param[in] p quaternion 1
* @param[in] q quaternion 2
* @param[out] dest result quaternion
*/
CGLM_INLINE
void
glm_quat_mulv(versor q1, versor q2, versor dest) {
dest[0] = q2[0] * q1[0] - q2[1] * q1[1] - q2[2] * q1[2] - q2[3] * q1[3];
dest[1] = q2[0] * q1[1] + q2[1] * q1[0] - q2[2] * q1[3] + q2[3] * q1[2];
dest[2] = q2[0] * q1[2] + q2[1] * q1[3] + q2[2] * q1[0] - q2[3] * q1[1];
dest[3] = q2[0] * q1[3] - q2[1] * q1[2] + q2[2] * q1[1] + q2[3] * q1[0];
glm_quat_normalize(dest);
glm_quat_mul(versor p, versor q, versor dest) {
/*
+ (a1 b2 + b1 a2 + c1 d2 d1 c2)i
+ (a1 c2 b1 d2 + c1 a2 + d1 b2)j
+ (a1 d2 + b1 c2 c1 b2 + d1 a2)k
a1 a2 b1 b2 c1 c2 d1 d2
*/
#if defined( __SSE__ ) || defined( __SSE2__ )
glm_quat_mul_sse2(p, q, dest);
#else
dest[0] = p[3] * q[0] + p[0] * q[3] + p[1] * q[2] - p[2] * q[1];
dest[1] = p[3] * q[1] - p[0] * q[2] + p[1] * q[3] + p[2] * q[0];
dest[2] = p[3] * q[2] + p[0] * q[1] - p[1] * q[0] + p[2] * q[3];
dest[3] = p[3] * q[3] - p[0] * q[0] - p[1] * q[1] - p[2] * q[2];
#endif
}
/*!
@@ -181,19 +432,22 @@ glm_quat_mulv(versor q1, versor q2, versor dest) {
CGLM_INLINE
void
glm_quat_mat4(versor q, mat4 dest) {
float w, x, y, z;
float xx, yy, zz;
float xy, yz, xz;
float wx, wy, wz;
float w, x, y, z,
xx, yy, zz,
xy, yz, xz,
wx, wy, wz, norm, s;
w = q[0];
x = q[1];
y = q[2];
z = q[3];
norm = glm_quat_norm(q);
s = norm > 0.0f ? 2.0f / norm : 0.0f;
xx = 2.0f * x * x; xy = 2.0f * x * y; wx = 2.0f * w * x;
yy = 2.0f * y * y; yz = 2.0f * y * z; wy = 2.0f * w * y;
zz = 2.0f * z * z; xz = 2.0f * x * z; wz = 2.0f * w * z;
x = q[0];
y = q[1];
z = q[2];
w = q[3];
xx = s * x * x; xy = s * x * y; wx = s * w * x;
yy = s * y * y; yz = s * y * z; wy = s * w * y;
zz = s * z * z; xz = s * x * z; wz = s * w * z;
dest[0][0] = 1.0f - yy - zz;
dest[1][1] = 1.0f - xx - zz;
@@ -207,8 +461,8 @@ glm_quat_mat4(versor q, mat4 dest) {
dest[2][1] = yz - wx;
dest[0][2] = xz - wy;
dest[1][3] = 0.0f;
dest[0][3] = 0.0f;
dest[1][3] = 0.0f;
dest[2][3] = 0.0f;
dest[3][0] = 0.0f;
dest[3][1] = 0.0f;
@@ -216,69 +470,343 @@ glm_quat_mat4(versor q, mat4 dest) {
dest[3][3] = 1.0f;
}
/*!
* @brief convert quaternion to mat4 (transposed)
*
* @param[in] q quaternion
* @param[out] dest result matrix as transposed
*/
CGLM_INLINE
void
glm_quat_mat4t(versor q, mat4 dest) {
float w, x, y, z,
xx, yy, zz,
xy, yz, xz,
wx, wy, wz, norm, s;
norm = glm_quat_norm(q);
s = norm > 0.0f ? 2.0f / norm : 0.0f;
x = q[0];
y = q[1];
z = q[2];
w = q[3];
xx = s * x * x; xy = s * x * y; wx = s * w * x;
yy = s * y * y; yz = s * y * z; wy = s * w * y;
zz = s * z * z; xz = s * x * z; wz = s * w * z;
dest[0][0] = 1.0f - yy - zz;
dest[1][1] = 1.0f - xx - zz;
dest[2][2] = 1.0f - xx - yy;
dest[1][0] = xy + wz;
dest[2][1] = yz + wx;
dest[0][2] = xz + wy;
dest[0][1] = xy - wz;
dest[1][2] = yz - wx;
dest[2][0] = xz - wy;
dest[0][3] = 0.0f;
dest[1][3] = 0.0f;
dest[2][3] = 0.0f;
dest[3][0] = 0.0f;
dest[3][1] = 0.0f;
dest[3][2] = 0.0f;
dest[3][3] = 1.0f;
}
/*!
* @brief convert quaternion to mat3
*
* @param[in] q quaternion
* @param[out] dest result matrix
*/
CGLM_INLINE
void
glm_quat_mat3(versor q, mat3 dest) {
float w, x, y, z,
xx, yy, zz,
xy, yz, xz,
wx, wy, wz, norm, s;
norm = glm_quat_norm(q);
s = norm > 0.0f ? 2.0f / norm : 0.0f;
x = q[0];
y = q[1];
z = q[2];
w = q[3];
xx = s * x * x; xy = s * x * y; wx = s * w * x;
yy = s * y * y; yz = s * y * z; wy = s * w * y;
zz = s * z * z; xz = s * x * z; wz = s * w * z;
dest[0][0] = 1.0f - yy - zz;
dest[1][1] = 1.0f - xx - zz;
dest[2][2] = 1.0f - xx - yy;
dest[0][1] = xy + wz;
dest[1][2] = yz + wx;
dest[2][0] = xz + wy;
dest[1][0] = xy - wz;
dest[2][1] = yz - wx;
dest[0][2] = xz - wy;
}
/*!
* @brief convert quaternion to mat3 (transposed)
*
* @param[in] q quaternion
* @param[out] dest result matrix
*/
CGLM_INLINE
void
glm_quat_mat3t(versor q, mat3 dest) {
float w, x, y, z,
xx, yy, zz,
xy, yz, xz,
wx, wy, wz, norm, s;
norm = glm_quat_norm(q);
s = norm > 0.0f ? 2.0f / norm : 0.0f;
x = q[0];
y = q[1];
z = q[2];
w = q[3];
xx = s * x * x; xy = s * x * y; wx = s * w * x;
yy = s * y * y; yz = s * y * z; wy = s * w * y;
zz = s * z * z; xz = s * x * z; wz = s * w * z;
dest[0][0] = 1.0f - yy - zz;
dest[1][1] = 1.0f - xx - zz;
dest[2][2] = 1.0f - xx - yy;
dest[1][0] = xy + wz;
dest[2][1] = yz + wx;
dest[0][2] = xz + wy;
dest[0][1] = xy - wz;
dest[1][2] = yz - wx;
dest[2][0] = xz - wy;
}
/*!
* @brief interpolates between two quaternions
* using linear interpolation (LERP)
*
* @param[in] from from
* @param[in] to to
* @param[in] t interpolant (amount) clamped between 0 and 1
* @param[out] dest result quaternion
*/
CGLM_INLINE
void
glm_quat_lerp(versor from, versor to, float t, versor dest) {
glm_vec4_lerp(from, to, t, dest);
}
/*!
* @brief interpolates between two quaternions
* using spherical linear interpolation (SLERP)
*
* @param[in] q from
* @param[in] r to
* @param[in] from from
* @param[in] to to
* @param[in] t amout
* @param[out] dest result quaternion
*/
CGLM_INLINE
void
glm_quat_slerp(versor q,
versor r,
float t,
versor dest) {
/* https://en.wikipedia.org/wiki/Slerp */
#if defined( __SSE__ ) || defined( __SSE2__ )
glm_quat_slerp_sse2(q, r, t, dest);
#else
float cosTheta, sinTheta, angle, a, b, c;
glm_quat_slerp(versor from, versor to, float t, versor dest) {
CGLM_ALIGN(16) vec4 q1, q2;
float cosTheta, sinTheta, angle;
cosTheta = glm_quat_dot(q, r);
if (cosTheta < 0.0f) {
q[0] *= -1.0f;
q[1] *= -1.0f;
q[2] *= -1.0f;
q[3] *= -1.0f;
cosTheta = glm_quat_dot(from, to);
glm_quat_copy(from, q1);
cosTheta = -cosTheta;
}
if (fabs(cosTheta) >= 1.0f) {
dest[0] = q[0];
dest[1] = q[1];
dest[2] = q[2];
dest[3] = q[3];
if (fabsf(cosTheta) >= 1.0f) {
glm_quat_copy(q1, dest);
return;
}
sinTheta = sqrt(1.0f - cosTheta * cosTheta);
if (cosTheta < 0.0f) {
glm_vec4_negate(q1);
cosTheta = -cosTheta;
}
c = 1.0f - t;
sinTheta = sqrtf(1.0f - cosTheta * cosTheta);
/* LERP */
/* TODO: FLT_EPSILON vs 0.001? */
if (sinTheta < 0.001f) {
dest[0] = c * q[0] + t * r[0];
dest[1] = c * q[1] + t * r[1];
dest[2] = c * q[2] + t * r[2];
dest[3] = c * q[3] + t * r[3];
/* LERP to avoid zero division */
if (fabsf(sinTheta) < 0.001f) {
glm_quat_lerp(from, to, t, dest);
return;
}
/* SLERP */
angle = acosf(cosTheta);
a = sinf(c * angle);
b = sinf(t * angle);
glm_vec4_scale(q1, sinf((1.0f - t) * angle), q1);
glm_vec4_scale(to, sinf(t * angle), q2);
dest[0] = (q[0] * a + r[0] * b) / sinTheta;
dest[1] = (q[1] * a + r[1] * b) / sinTheta;
dest[2] = (q[2] * a + r[2] * b) / sinTheta;
dest[3] = (q[3] * a + r[3] * b) / sinTheta;
#endif
glm_vec4_add(q1, q2, q1);
glm_vec4_scale(q1, 1.0f / sinTheta, dest);
}
/*!
* @brief creates view matrix using quaternion as camera orientation
*
* @param[in] eye eye
* @param[in] ori orientation in world space as quaternion
* @param[out] dest view matrix
*/
CGLM_INLINE
void
glm_quat_look(vec3 eye, versor ori, mat4 dest) {
/* orientation */
glm_quat_mat4t(ori, dest);
/* translate */
glm_mat4_mulv3(dest, eye, 1.0f, dest[3]);
glm_vec3_negate(dest[3]);
}
/*!
* @brief creates look rotation quaternion
*
* @param[in] dir direction to look
* @param[in] fwd forward vector
* @param[in] up up vector
* @param[out] dest destination quaternion
*/
CGLM_INLINE
void
glm_quat_for(vec3 dir, vec3 fwd, vec3 up, versor dest) {
CGLM_ALIGN(8) vec3 axis;
float dot, angle;
dot = glm_vec3_dot(dir, fwd);
if (fabsf(dot + 1.0f) < 0.000001f) {
glm_quat_init(dest, up[0], up[1], up[2], GLM_PIf);
return;
}
if (fabsf(dot - 1.0f) < 0.000001f) {
glm_quat_identity(dest);
return;
}
angle = acosf(dot);
glm_cross(fwd, dir, axis);
glm_normalize(axis);
glm_quatv(dest, angle, axis);
}
/*!
* @brief creates look rotation quaternion using source and
* destination positions p suffix stands for position
*
* @param[in] from source point
* @param[in] to destination point
* @param[in] fwd forward vector
* @param[in] up up vector
* @param[out] dest destination quaternion
*/
CGLM_INLINE
void
glm_quat_forp(vec3 from, vec3 to, vec3 fwd, vec3 up, versor dest) {
CGLM_ALIGN(8) vec3 dir;
glm_vec3_sub(to, from, dir);
glm_quat_for(dir, fwd, up, dest);
}
/*!
* @brief rotate vector using using quaternion
*
* @param[in] q quaternion
* @param[in] v vector to rotate
* @param[out] dest rotated vector
*/
CGLM_INLINE
void
glm_quat_rotatev(versor q, vec3 v, vec3 dest) {
CGLM_ALIGN(16) versor p;
CGLM_ALIGN(8) vec3 u, v1, v2;
float s;
glm_quat_normalize_to(q, p);
glm_quat_imag(p, u);
s = glm_quat_real(p);
glm_vec3_scale(u, 2.0f * glm_vec3_dot(u, v), v1);
glm_vec3_scale(v, s * s - glm_vec3_dot(u, u), v2);
glm_vec3_add(v1, v2, v1);
glm_vec3_cross(u, v, v2);
glm_vec3_scale(v2, 2.0f * s, v2);
glm_vec3_add(v1, v2, dest);
}
/*!
* @brief rotate existing transform matrix using quaternion
*
* @param[in] m existing transform matrix
* @param[in] q quaternion
* @param[out] dest rotated matrix/transform
*/
CGLM_INLINE
void
glm_quat_rotate(mat4 m, versor q, mat4 dest) {
CGLM_ALIGN_MAT mat4 rot;
glm_quat_mat4(q, rot);
glm_mul_rot(m, rot, dest);
}
/*!
* @brief rotate existing transform matrix using quaternion at pivot point
*
* @param[in, out] m existing transform matrix
* @param[in] q quaternion
* @param[out] pivot pivot
*/
CGLM_INLINE
void
glm_quat_rotate_at(mat4 m, versor q, vec3 pivot) {
CGLM_ALIGN(8) vec3 pivotInv;
glm_vec3_negate_to(pivot, pivotInv);
glm_translate(m, pivot);
glm_quat_rotate(m, q, m);
glm_translate(m, pivotInv);
}
/*!
* @brief 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.
*
* @param[out] m existing transform matrix
* @param[in] q quaternion
* @param[in] pivot pivot
*/
CGLM_INLINE
void
glm_quat_rotate_atm(mat4 m, versor q, vec3 pivot) {
CGLM_ALIGN(8) vec3 pivotInv;
glm_vec3_negate_to(pivot, pivotInv);
glm_translate_make(m, pivot);
glm_quat_rotate(m, q, m);
glm_translate(m, pivotInv);
}
#endif /* cglm_quat_h */

41
include/cglm/simd/arm.h Normal file
View File

@@ -0,0 +1,41 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglm_simd_arm_h
#define cglm_simd_arm_h
#include "intrin.h"
#ifdef CGLM_SIMD_ARM
#define glmm_load(p) vld1q_f32(p)
#define glmm_store(p, a) vst1q_f32(p, a)
static inline
float
glmm_hadd(float32x4_t v) {
#if defined(__aarch64__)
return vaddvq_f32(v);
#else
v = vaddq_f32(v, vrev64q_f32(v));
v = vaddq_f32(v, vcombine_f32(vget_high_f32(v), vget_low_f32(v)));
return vgetq_lane_f32(v, 0);
#endif
}
static inline
float
glmm_dot(float32x4_t a, float32x4_t b) {
return glmm_hadd(vmulq_f32(a, b));
}
static inline
float
glmm_norm(float32x4_t a) {
return sqrtf(glmm_dot(a, a));
}
#endif
#endif /* cglm_simd_arm_h */

View File

@@ -21,27 +21,30 @@ glm_mul_avx(mat4 m1, mat4 m2, mat4 dest) {
__m256 y0, y1, y2, y3, y4, y5, y6, y7, y8, y9;
y0 = _mm256_load_ps(m2[0]); /* h g f e d c b a */
y1 = _mm256_load_ps(m2[2]); /* p o n m l k j i */
y0 = glmm_load256(m2[0]); /* h g f e d c b a */
y1 = glmm_load256(m2[2]); /* p o n m l k j i */
y2 = _mm256_load_ps(m1[0]); /* h g f e d c b a */
y3 = _mm256_load_ps(m1[2]); /* p o n m l k j i */
y2 = glmm_load256(m1[0]); /* h g f e d c b a */
y3 = glmm_load256(m1[2]); /* p o n m l k j i */
y4 = _mm256_permute2f128_ps(y2, y2, 0b00000011); /* d c b a h g f e */
y5 = _mm256_permute2f128_ps(y3, y3, 0b00000000); /* l k j i l k j i */
/* 0x03: 0b00000011 */
y4 = _mm256_permute2f128_ps(y2, y2, 0x03); /* d c b a h g f e */
y5 = _mm256_permute2f128_ps(y3, y3, 0x03); /* l k j i p o n m */
/* f f f f a a a a */
/* g g g g c c c c */
/* h h h h c c c c */
/* e e e e b b b b */
y7 = _mm256_permute_ps(y0, 0b10101010);
/* g g g g d d d d */
y6 = _mm256_permutevar_ps(y0, _mm256_set_epi32(1, 1, 1, 1, 0, 0, 0, 0));
y7 = _mm256_permutevar_ps(y0, _mm256_set_epi32(3, 3, 3, 3, 2, 2, 2, 2));
y8 = _mm256_permutevar_ps(y0, _mm256_set_epi32(0, 0, 0, 0, 1, 1, 1, 1));
y9 = _mm256_permutevar_ps(y0, _mm256_set_epi32(2, 2, 2, 2, 3, 3, 3, 3));
_mm256_store_ps(dest[0],
_mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6),
_mm256_mul_ps(y4, y8)),
_mm256_mul_ps(y5, y7)));
glmm_store256(dest[0],
_mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6),
_mm256_mul_ps(y3, y7)),
_mm256_add_ps(_mm256_mul_ps(y4, y8),
_mm256_mul_ps(y5, y9))));
/* n n n n i i i i */
/* p p p p k k k k */
@@ -52,11 +55,11 @@ glm_mul_avx(mat4 m1, mat4 m2, mat4 dest) {
y8 = _mm256_permutevar_ps(y1, _mm256_set_epi32(0, 0, 0, 0, 1, 1, 1, 1));
y9 = _mm256_permutevar_ps(y1, _mm256_set_epi32(2, 2, 2, 2, 3, 3, 3, 3));
_mm256_store_ps(dest[2],
_mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6),
_mm256_mul_ps(y3, y7)),
_mm256_add_ps(_mm256_mul_ps(y4, y8),
_mm256_mul_ps(y5, y9))));
glmm_store256(dest[2],
_mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6),
_mm256_mul_ps(y3, y7)),
_mm256_add_ps(_mm256_mul_ps(y4, y8),
_mm256_mul_ps(y5, y9))));
}
#endif

View File

@@ -21,14 +21,15 @@ glm_mat4_mul_avx(mat4 m1, mat4 m2, mat4 dest) {
__m256 y0, y1, y2, y3, y4, y5, y6, y7, y8, y9;
y0 = _mm256_load_ps(m2[0]); /* h g f e d c b a */
y1 = _mm256_load_ps(m2[2]); /* p o n m l k j i */
y0 = glmm_load256(m2[0]); /* h g f e d c b a */
y1 = glmm_load256(m2[2]); /* p o n m l k j i */
y2 = _mm256_load_ps(m1[0]); /* h g f e d c b a */
y3 = _mm256_load_ps(m1[2]); /* p o n m l k j i */
y2 = glmm_load256(m1[0]); /* h g f e d c b a */
y3 = glmm_load256(m1[2]); /* p o n m l k j i */
y4 = _mm256_permute2f128_ps(y2, y2, 0b00000011); /* d c b a h g f e */
y5 = _mm256_permute2f128_ps(y3, y3, 0b00000011); /* l k j i p o n m */
/* 0x03: 0b00000011 */
y4 = _mm256_permute2f128_ps(y2, y2, 0x03); /* d c b a h g f e */
y5 = _mm256_permute2f128_ps(y3, y3, 0x03); /* l k j i p o n m */
/* f f f f a a a a */
/* h h h h c c c c */
@@ -39,11 +40,11 @@ glm_mat4_mul_avx(mat4 m1, mat4 m2, mat4 dest) {
y8 = _mm256_permutevar_ps(y0, _mm256_set_epi32(0, 0, 0, 0, 1, 1, 1, 1));
y9 = _mm256_permutevar_ps(y0, _mm256_set_epi32(2, 2, 2, 2, 3, 3, 3, 3));
_mm256_store_ps(dest[0],
_mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6),
_mm256_mul_ps(y3, y7)),
_mm256_add_ps(_mm256_mul_ps(y4, y8),
_mm256_mul_ps(y5, y9))));
glmm_store256(dest[0],
_mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6),
_mm256_mul_ps(y3, y7)),
_mm256_add_ps(_mm256_mul_ps(y4, y8),
_mm256_mul_ps(y5, y9))));
/* n n n n i i i i */
/* p p p p k k k k */
@@ -54,11 +55,11 @@ glm_mat4_mul_avx(mat4 m1, mat4 m2, mat4 dest) {
y8 = _mm256_permutevar_ps(y1, _mm256_set_epi32(0, 0, 0, 0, 1, 1, 1, 1));
y9 = _mm256_permutevar_ps(y1, _mm256_set_epi32(2, 2, 2, 2, 3, 3, 3, 3));
_mm256_store_ps(dest[2],
_mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6),
_mm256_mul_ps(y3, y7)),
_mm256_add_ps(_mm256_mul_ps(y4, y8),
_mm256_mul_ps(y5, y9))));
glmm_store256(dest[2],
_mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6),
_mm256_mul_ps(y3, y7)),
_mm256_add_ps(_mm256_mul_ps(y4, y8),
_mm256_mul_ps(y5, y9))));
}
#endif

View File

@@ -8,45 +8,83 @@
#ifndef cglm_intrin_h
#define cglm_intrin_h
#if defined( _WIN32 )
#if defined( _MSC_VER )
# if (defined(_M_AMD64) || defined(_M_X64)) || _M_IX86_FP == 2
# define __SSE2__
# ifndef __SSE2__
# define __SSE2__
# endif
# elif _M_IX86_FP == 1
# define __SSE__
# ifndef __SSE__
# define __SSE__
# endif
# endif
/* do not use alignment for older visual studio versions */
# if _MSC_VER < 1913 /* Visual Studio 2017 version 15.6 */
# define CGLM_ALL_UNALIGNED
# endif
#endif
#if defined( __SSE__ ) || defined( __SSE2__ )
# include <xmmintrin.h>
# include <emmintrin.h>
/* float */
# define _mm_shuffle1_ps(a, z, y, x, w) \
_mm_shuffle_ps(a, a, _MM_SHUFFLE(z, y, x, w))
# define _mm_shuffle1_ps1(a, x) \
_mm_shuffle_ps(a, a, _MM_SHUFFLE(x, x, x, x))
# define _mm_shuffle2_ps(a, b, z0, y0, x0, w0, z1, y1, x1, w1) \
_mm_shuffle1_ps(_mm_shuffle_ps(a, b, _MM_SHUFFLE(z0, y0, x0, w0)), \
z1, y1, x1, w1)
# define CGLM_SSE_FP 1
# ifndef CGLM_SIMD_x86
# define CGLM_SIMD_x86
# endif
#endif
/* x86, x64 */
#if defined( __SSE__ ) || defined( __SSE2__ )
# define CGLM_SSE_FP 1
#if defined(__SSE3__)
# include <x86intrin.h>
# ifndef CGLM_SIMD_x86
# define CGLM_SIMD_x86
# endif
#endif
#if defined(__SSE4_1__)
# include <smmintrin.h>
# ifndef CGLM_SIMD_x86
# define CGLM_SIMD_x86
# endif
#endif
#if defined(__SSE4_2__)
# include <nmmintrin.h>
# ifndef CGLM_SIMD_x86
# define CGLM_SIMD_x86
# endif
#endif
#ifdef __AVX__
# include <immintrin.h>
# define CGLM_AVX_FP 1
# ifndef CGLM_SIMD_x86
# define CGLM_SIMD_x86
# endif
#endif
/* ARM Neon */
#if defined(__ARM_NEON) && defined(__ARM_NEON_FP)
#if defined(__ARM_NEON)
# include <arm_neon.h>
# define CGLM_NEON_FP 1
#else
# undef CGLM_NEON_FP
# if defined(__ARM_NEON_FP)
# define CGLM_NEON_FP 1
# ifndef CGLM_SIMD_ARM
# define CGLM_SIMD_ARM
# endif
# endif
#endif
#if defined(CGLM_SIMD_x86) || defined(CGLM_NEON_FP)
# ifndef CGLM_SIMD
# define CGLM_SIMD
# endif
#endif
#if defined(CGLM_SIMD_x86)
# include "x86.h"
#endif
#if defined(CGLM_SIMD_ARM)
# include "arm.h"
#endif
#endif /* cglm_intrin_h */

View File

@@ -18,35 +18,67 @@ glm_mul_sse2(mat4 m1, mat4 m2, mat4 dest) {
/* D = R * L (Column-Major) */
__m128 l0, l1, l2, l3, r;
l0 = _mm_load_ps(m1[0]);
l1 = _mm_load_ps(m1[1]);
l2 = _mm_load_ps(m1[2]);
l3 = _mm_load_ps(m1[3]);
l0 = glmm_load(m1[0]);
l1 = glmm_load(m1[1]);
l2 = glmm_load(m1[2]);
l3 = glmm_load(m1[3]);
r = _mm_load_ps(m2[0]);
_mm_store_ps(dest[0],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0),
_mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)),
_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2)));
r = glmm_load(m2[0]);
glmm_store(dest[0],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0),
_mm_mul_ps(glmm_shuff1x(r, 1), l1)),
_mm_mul_ps(glmm_shuff1x(r, 2), l2)));
r = _mm_load_ps(m2[1]);
_mm_store_ps(dest[1],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0),
_mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)),
_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2)));
r = glmm_load(m2[1]);
glmm_store(dest[1],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0),
_mm_mul_ps(glmm_shuff1x(r, 1), l1)),
_mm_mul_ps(glmm_shuff1x(r, 2), l2)));
r = _mm_load_ps(m2[2]);
_mm_store_ps(dest[2],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0),
_mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)),
_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2)));
r = glmm_load(m2[2]);
glmm_store(dest[2],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0),
_mm_mul_ps(glmm_shuff1x(r, 1), l1)),
_mm_mul_ps(glmm_shuff1x(r, 2), l2)));
r = _mm_load_ps(m2[3]);
_mm_store_ps(dest[3],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0),
_mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)),
_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2),
_mm_mul_ps(_mm_shuffle1_ps1(r, 3), l3))));
r = glmm_load(m2[3]);
glmm_store(dest[3],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0),
_mm_mul_ps(glmm_shuff1x(r, 1), l1)),
_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 2), l2),
_mm_mul_ps(glmm_shuff1x(r, 3), l3))));
}
CGLM_INLINE
void
glm_mul_rot_sse2(mat4 m1, mat4 m2, mat4 dest) {
/* D = R * L (Column-Major) */
__m128 l0, l1, l2, l3, r;
l0 = glmm_load(m1[0]);
l1 = glmm_load(m1[1]);
l2 = glmm_load(m1[2]);
l3 = glmm_load(m1[3]);
r = glmm_load(m2[0]);
glmm_store(dest[0],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0),
_mm_mul_ps(glmm_shuff1x(r, 1), l1)),
_mm_mul_ps(glmm_shuff1x(r, 2), l2)));
r = glmm_load(m2[1]);
glmm_store(dest[1],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0),
_mm_mul_ps(glmm_shuff1x(r, 1), l1)),
_mm_mul_ps(glmm_shuff1x(r, 2), l2)));
r = glmm_load(m2[2]);
glmm_store(dest[2],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0),
_mm_mul_ps(glmm_shuff1x(r, 1), l1)),
_mm_mul_ps(glmm_shuff1x(r, 2), l2)));
glmm_store(dest[3], l3);
}
CGLM_INLINE
@@ -54,25 +86,25 @@ void
glm_inv_tr_sse2(mat4 mat) {
__m128 r0, r1, r2, r3, x0, x1;
r0 = _mm_load_ps(mat[0]);
r1 = _mm_load_ps(mat[1]);
r2 = _mm_load_ps(mat[2]);
r3 = _mm_load_ps(mat[3]);
x1 = _mm_set_ps(1.0f, 0.0f, 0.0f, 0.0f);
r0 = glmm_load(mat[0]);
r1 = glmm_load(mat[1]);
r2 = glmm_load(mat[2]);
r3 = glmm_load(mat[3]);
x1 = _mm_set_ps(1.0f, 0.0f, 0.0f, 0.0f);
_MM_TRANSPOSE4_PS(r0, r1, r2, x1);
x0 = _mm_add_ps(_mm_mul_ps(r0, _mm_shuffle1_ps(r3, 0, 0, 0, 0)),
_mm_mul_ps(r1, _mm_shuffle1_ps(r3, 1, 1, 1, 1)));
x0 = _mm_add_ps(x0, _mm_mul_ps(r2, _mm_shuffle1_ps(r3, 2, 2, 2, 2)));
x0 = _mm_add_ps(_mm_mul_ps(r0, glmm_shuff1(r3, 0, 0, 0, 0)),
_mm_mul_ps(r1, glmm_shuff1(r3, 1, 1, 1, 1)));
x0 = _mm_add_ps(x0, _mm_mul_ps(r2, glmm_shuff1(r3, 2, 2, 2, 2)));
x0 = _mm_xor_ps(x0, _mm_set1_ps(-0.f));
x0 = _mm_add_ps(x0, x1);
_mm_store_ps(mat[0], r0);
_mm_store_ps(mat[1], r1);
_mm_store_ps(mat[2], r2);
_mm_store_ps(mat[3], x0);
glmm_store(mat[0], r0);
glmm_store(mat[1], r1);
glmm_store(mat[2], r2);
glmm_store(mat[3], x0);
}
#endif

View File

@@ -27,27 +27,25 @@ glm_mat3_mul_sse2(mat3 m1, mat3 m2, mat3 dest) {
r1 = _mm_loadu_ps(&m2[1][1]);
r2 = _mm_set1_ps(m2[2][2]);
x1 = _mm_shuffle2_ps(l0, l1, 1, 0, 3, 3, 0, 3, 2, 0);
x2 = _mm_shuffle2_ps(l1, l2, 0, 0, 3, 2, 0, 2, 1, 0);
x1 = glmm_shuff2(l0, l1, 1, 0, 3, 3, 0, 3, 2, 0);
x2 = glmm_shuff2(l1, l2, 0, 0, 3, 2, 0, 2, 1, 0);
x0 = _mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps(l0, 0, 2, 1, 0),
_mm_shuffle1_ps(r0, 3, 0, 0, 0)),
_mm_mul_ps(x1,
_mm_shuffle2_ps(r0, r1, 0, 0, 1, 1, 2, 0, 0, 0)));
x0 = _mm_add_ps(_mm_mul_ps(glmm_shuff1(l0, 0, 2, 1, 0),
glmm_shuff1(r0, 3, 0, 0, 0)),
_mm_mul_ps(x1, glmm_shuff2(r0, r1, 0, 0, 1, 1, 2, 0, 0, 0)));
x0 = _mm_add_ps(x0,
_mm_mul_ps(x2,
_mm_shuffle2_ps(r0, r1, 1, 1, 2, 2, 2, 0, 0, 0)));
_mm_mul_ps(x2, glmm_shuff2(r0, r1, 1, 1, 2, 2, 2, 0, 0, 0)));
_mm_storeu_ps(dest[0], x0);
x0 = _mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps(l0, 1, 0, 2, 1),
x0 = _mm_add_ps(_mm_mul_ps(glmm_shuff1(l0, 1, 0, 2, 1),
_mm_shuffle_ps(r0, r1, _MM_SHUFFLE(2, 2, 3, 3))),
_mm_mul_ps(_mm_shuffle1_ps(x1, 1, 0, 2, 1),
_mm_shuffle1_ps(r1, 3, 3, 0, 0)));
_mm_mul_ps(glmm_shuff1(x1, 1, 0, 2, 1),
glmm_shuff1(r1, 3, 3, 0, 0)));
x0 = _mm_add_ps(x0,
_mm_mul_ps(_mm_shuffle1_ps(x2, 1, 0, 2, 1),
_mm_mul_ps(glmm_shuff1(x2, 1, 0, 2, 1),
_mm_shuffle_ps(r1, r2, _MM_SHUFFLE(0, 0, 1, 1))));
_mm_storeu_ps(&dest[1][1], x0);

View File

@@ -16,32 +16,32 @@
CGLM_INLINE
void
glm_mat4_scale_sse2(mat4 m, float s){
glm_mat4_scale_sse2(mat4 m, float s) {
__m128 x0;
x0 = _mm_set1_ps(s);
_mm_store_ps(m[0], _mm_mul_ps(_mm_load_ps(m[0]), x0));
_mm_store_ps(m[1], _mm_mul_ps(_mm_load_ps(m[1]), x0));
_mm_store_ps(m[2], _mm_mul_ps(_mm_load_ps(m[2]), x0));
_mm_store_ps(m[3], _mm_mul_ps(_mm_load_ps(m[3]), x0));
glmm_store(m[0], _mm_mul_ps(glmm_load(m[0]), x0));
glmm_store(m[1], _mm_mul_ps(glmm_load(m[1]), x0));
glmm_store(m[2], _mm_mul_ps(glmm_load(m[2]), x0));
glmm_store(m[3], _mm_mul_ps(glmm_load(m[3]), x0));
}
CGLM_INLINE
void
glm_mat4_transp_sse2(mat4 m, mat4 dest){
glm_mat4_transp_sse2(mat4 m, mat4 dest) {
__m128 r0, r1, r2, r3;
r0 = _mm_load_ps(m[0]);
r1 = _mm_load_ps(m[1]);
r2 = _mm_load_ps(m[2]);
r3 = _mm_load_ps(m[3]);
r0 = glmm_load(m[0]);
r1 = glmm_load(m[1]);
r2 = glmm_load(m[2]);
r3 = glmm_load(m[3]);
_MM_TRANSPOSE4_PS(r0, r1, r2, r3);
_mm_store_ps(dest[0], r0);
_mm_store_ps(dest[1], r1);
_mm_store_ps(dest[2], r2);
_mm_store_ps(dest[3], r3);
glmm_store(dest[0], r0);
glmm_store(dest[1], r1);
glmm_store(dest[2], r2);
glmm_store(dest[3], r3);
}
CGLM_INLINE
@@ -51,36 +51,36 @@ glm_mat4_mul_sse2(mat4 m1, mat4 m2, mat4 dest) {
__m128 l0, l1, l2, l3, r;
l0 = _mm_load_ps(m1[0]);
l1 = _mm_load_ps(m1[1]);
l2 = _mm_load_ps(m1[2]);
l3 = _mm_load_ps(m1[3]);
l0 = glmm_load(m1[0]);
l1 = glmm_load(m1[1]);
l2 = glmm_load(m1[2]);
l3 = glmm_load(m1[3]);
r = _mm_load_ps(m2[0]);
_mm_store_ps(dest[0],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0),
_mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)),
_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2),
_mm_mul_ps(_mm_shuffle1_ps1(r, 3), l3))));
r = _mm_load_ps(m2[1]);
_mm_store_ps(dest[1],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0),
_mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)),
_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2),
_mm_mul_ps(_mm_shuffle1_ps1(r, 3), l3))));
r = _mm_load_ps(m2[2]);
_mm_store_ps(dest[2],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0),
_mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)),
_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2),
_mm_mul_ps(_mm_shuffle1_ps1(r, 3), l3))));
r = glmm_load(m2[0]);
glmm_store(dest[0],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0),
_mm_mul_ps(glmm_shuff1x(r, 1), l1)),
_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 2), l2),
_mm_mul_ps(glmm_shuff1x(r, 3), l3))));
r = glmm_load(m2[1]);
glmm_store(dest[1],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0),
_mm_mul_ps(glmm_shuff1x(r, 1), l1)),
_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 2), l2),
_mm_mul_ps(glmm_shuff1x(r, 3), l3))));
r = glmm_load(m2[2]);
glmm_store(dest[2],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0),
_mm_mul_ps(glmm_shuff1x(r, 1), l1)),
_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 2), l2),
_mm_mul_ps(glmm_shuff1x(r, 3), l3))));
r = _mm_load_ps(m2[3]);
_mm_store_ps(dest[3],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0),
_mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)),
_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2),
_mm_mul_ps(_mm_shuffle1_ps1(r, 3), l3))));
r = glmm_load(m2[3]);
glmm_store(dest[3],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0),
_mm_mul_ps(glmm_shuff1x(r, 1), l1)),
_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 2), l2),
_mm_mul_ps(glmm_shuff1x(r, 3), l3))));
}
CGLM_INLINE
@@ -88,18 +88,14 @@ void
glm_mat4_mulv_sse2(mat4 m, vec4 v, vec4 dest) {
__m128 x0, x1, x2;
x0 = _mm_load_ps(v);
x1 = _mm_add_ps(_mm_mul_ps(_mm_load_ps(m[0]),
_mm_shuffle1_ps1(x0, 0)),
_mm_mul_ps(_mm_load_ps(m[1]),
_mm_shuffle1_ps1(x0, 1)));
x0 = glmm_load(v);
x1 = _mm_add_ps(_mm_mul_ps(glmm_load(m[0]), glmm_shuff1x(x0, 0)),
_mm_mul_ps(glmm_load(m[1]), glmm_shuff1x(x0, 1)));
x2 = _mm_add_ps(_mm_mul_ps(_mm_load_ps(m[2]),
_mm_shuffle1_ps1(x0, 2)),
_mm_mul_ps(_mm_load_ps(m[3]),
_mm_shuffle1_ps1(x0, 3)));
x2 = _mm_add_ps(_mm_mul_ps(glmm_load(m[2]), glmm_shuff1x(x0, 2)),
_mm_mul_ps(glmm_load(m[3]), glmm_shuff1x(x0, 3)));
_mm_store_ps(dest, _mm_add_ps(x1, x2));
glmm_store(dest, _mm_add_ps(x1, x2));
}
CGLM_INLINE
@@ -108,10 +104,10 @@ glm_mat4_det_sse2(mat4 mat) {
__m128 r0, r1, r2, r3, x0, x1, x2;
/* 127 <- 0, [square] det(A) = det(At) */
r0 = _mm_load_ps(mat[0]); /* d c b a */
r1 = _mm_load_ps(mat[1]); /* h g f e */
r2 = _mm_load_ps(mat[2]); /* l k j i */
r3 = _mm_load_ps(mat[3]); /* p o n m */
r0 = glmm_load(mat[0]); /* d c b a */
r1 = glmm_load(mat[1]); /* h g f e */
r2 = glmm_load(mat[2]); /* l k j i */
r3 = glmm_load(mat[3]); /* p o n m */
/*
t[1] = j * p - n * l;
@@ -119,20 +115,20 @@ glm_mat4_det_sse2(mat4 mat) {
t[3] = i * p - m * l;
t[4] = i * o - m * k;
*/
x0 = _mm_sub_ps(_mm_mul_ps(_mm_shuffle1_ps(r2, 0, 0, 1, 1),
_mm_shuffle1_ps(r3, 2, 3, 2, 3)),
_mm_mul_ps(_mm_shuffle1_ps(r3, 0, 0, 1, 1),
_mm_shuffle1_ps(r2, 2, 3, 2, 3)));
x0 = _mm_sub_ps(_mm_mul_ps(glmm_shuff1(r2, 0, 0, 1, 1),
glmm_shuff1(r3, 2, 3, 2, 3)),
_mm_mul_ps(glmm_shuff1(r3, 0, 0, 1, 1),
glmm_shuff1(r2, 2, 3, 2, 3)));
/*
t[0] = k * p - o * l;
t[0] = k * p - o * l;
t[5] = i * n - m * j;
t[5] = i * n - m * j;
*/
x1 = _mm_sub_ps(_mm_mul_ps(_mm_shuffle1_ps(r2, 0, 0, 2, 2),
_mm_shuffle1_ps(r3, 1, 1, 3, 3)),
_mm_mul_ps(_mm_shuffle1_ps(r3, 0, 0, 2, 2),
_mm_shuffle1_ps(r2, 1, 1, 3, 3)));
x1 = _mm_sub_ps(_mm_mul_ps(glmm_shuff1(r2, 0, 0, 2, 2),
glmm_shuff1(r3, 1, 1, 3, 3)),
_mm_mul_ps(glmm_shuff1(r3, 0, 0, 2, 2),
glmm_shuff1(r2, 1, 1, 3, 3)));
/*
a * (f * t[0] - g * t[1] + h * t[2])
@@ -140,19 +136,19 @@ glm_mat4_det_sse2(mat4 mat) {
+ c * (e * t[1] - f * t[3] + h * t[5])
- d * (e * t[2] - f * t[4] + g * t[5])
*/
x2 = _mm_sub_ps(_mm_mul_ps(_mm_shuffle1_ps(r1, 0, 0, 0, 1),
x2 = _mm_sub_ps(_mm_mul_ps(glmm_shuff1(r1, 0, 0, 0, 1),
_mm_shuffle_ps(x1, x0, _MM_SHUFFLE(1, 0, 0, 0))),
_mm_mul_ps(_mm_shuffle1_ps(r1, 1, 1, 2, 2),
_mm_shuffle1_ps(x0, 3, 2, 2, 0)));
_mm_mul_ps(glmm_shuff1(r1, 1, 1, 2, 2),
glmm_shuff1(x0, 3, 2, 2, 0)));
x2 = _mm_add_ps(x2,
_mm_mul_ps(_mm_shuffle1_ps(r1, 2, 3, 3, 3),
_mm_mul_ps(glmm_shuff1(r1, 2, 3, 3, 3),
_mm_shuffle_ps(x0, x1, _MM_SHUFFLE(2, 2, 3, 1))));
x2 = _mm_xor_ps(x2, _mm_set_ps(-0.f, 0.f, -0.f, 0.f));
x0 = _mm_mul_ps(r0, x2);
x0 = _mm_add_ps(x0, _mm_shuffle1_ps(x0, 0, 1, 2, 3));
x0 = _mm_add_ps(x0, _mm_shuffle1_ps(x0, 1, 3, 3, 1));
x0 = _mm_add_ps(x0, glmm_shuff1(x0, 0, 1, 2, 3));
x0 = _mm_add_ps(x0, glmm_shuff1(x0, 1, 3, 3, 1));
return _mm_cvtss_f32(x0);
}
@@ -166,14 +162,14 @@ glm_mat4_inv_fast_sse2(mat4 mat, mat4 dest) {
x0, x1, x2, x3, x4, x5, x6, x7;
/* 127 <- 0 */
r0 = _mm_load_ps(mat[0]); /* d c b a */
r1 = _mm_load_ps(mat[1]); /* h g f e */
r2 = _mm_load_ps(mat[2]); /* l k j i */
r3 = _mm_load_ps(mat[3]); /* p o n m */
r0 = glmm_load(mat[0]); /* d c b a */
r1 = glmm_load(mat[1]); /* h g f e */
r2 = glmm_load(mat[2]); /* l k j i */
r3 = glmm_load(mat[3]); /* p o n m */
x0 = _mm_shuffle_ps(r2, r3, _MM_SHUFFLE(3, 2, 3, 2)); /* p o l k */
x1 = _mm_shuffle1_ps(x0, 1, 3, 3, 3); /* l p p p */
x2 = _mm_shuffle1_ps(x0, 0, 2, 2, 2); /* k o o o */
x1 = glmm_shuff1(x0, 1, 3, 3, 3); /* l p p p */
x2 = glmm_shuff1(x0, 0, 2, 2, 2); /* k o o o */
x0 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(3, 3, 3, 3)); /* h h l l */
x3 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(2, 2, 2, 2)); /* g g k k */
@@ -184,7 +180,7 @@ glm_mat4_inv_fast_sse2(mat4 mat, mat4 dest) {
t0 = _mm_sub_ps(_mm_mul_ps(x3, x1), _mm_mul_ps(x2, x0));
x4 = _mm_shuffle_ps(r2, r3, _MM_SHUFFLE(2, 1, 2, 1)); /* o n k j */
x4 = _mm_shuffle1_ps(x4, 0, 2, 2, 2); /* j n n n */
x4 = glmm_shuff1(x4, 0, 2, 2, 2); /* j n n n */
x5 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(1, 1, 1, 1)); /* f f j j */
/* t1[1] = j * p - n * l;
@@ -200,7 +196,7 @@ glm_mat4_inv_fast_sse2(mat4 mat, mat4 dest) {
t2 = _mm_sub_ps(_mm_mul_ps(x5, x2), _mm_mul_ps(x4, x3));
x6 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(0, 0, 0, 0)); /* e e i i */
x7 = _mm_shuffle2_ps(r3, r2, 0, 0, 0, 0, 2, 0, 0, 0); /* i m m m */
x7 = glmm_shuff2(r3, r2, 0, 0, 0, 0, 2, 0, 0, 0); /* i m m m */
/* t1[3] = i * p - m * l;
t1[3] = i * p - m * l;
@@ -220,10 +216,10 @@ glm_mat4_inv_fast_sse2(mat4 mat, mat4 dest) {
t3[5] = e * j - i * f; */
t5 = _mm_sub_ps(_mm_mul_ps(x6, x4), _mm_mul_ps(x7, x5));
x0 = _mm_shuffle2_ps(r1, r0, 0, 0, 0, 0, 2, 2, 2, 0); /* a a a e */
x1 = _mm_shuffle2_ps(r1, r0, 1, 1, 1, 1, 2, 2, 2, 0); /* b b b f */
x2 = _mm_shuffle2_ps(r1, r0, 2, 2, 2, 2, 2, 2, 2, 0); /* c c c g */
x3 = _mm_shuffle2_ps(r1, r0, 3, 3, 3, 3, 2, 2, 2, 0); /* d d d h */
x0 = glmm_shuff2(r1, r0, 0, 0, 0, 0, 2, 2, 2, 0); /* a a a e */
x1 = glmm_shuff2(r1, r0, 1, 1, 1, 1, 2, 2, 2, 0); /* b b b f */
x2 = glmm_shuff2(r1, r0, 2, 2, 2, 2, 2, 2, 2, 0); /* c c c g */
x3 = glmm_shuff2(r1, r0, 3, 3, 3, 3, 2, 2, 2, 0); /* d d d h */
/*
dest[0][0] = f * t1[0] - g * t1[1] + h * t1[2];
@@ -271,14 +267,14 @@ glm_mat4_inv_fast_sse2(mat4 mat, mat4 dest) {
x0 = _mm_shuffle_ps(x0, x1, _MM_SHUFFLE(2, 0, 2, 0));
x0 = _mm_mul_ps(x0, r0);
x0 = _mm_add_ps(x0, _mm_shuffle1_ps(x0, 0, 1, 2, 3));
x0 = _mm_add_ps(x0, _mm_shuffle1_ps(x0, 1, 0, 0, 1));
x0 = _mm_add_ps(x0, glmm_shuff1(x0, 0, 1, 2, 3));
x0 = _mm_add_ps(x0, glmm_shuff1(x0, 1, 0, 0, 1));
x0 = _mm_rcp_ps(x0);
_mm_store_ps(dest[0], _mm_mul_ps(v0, x0));
_mm_store_ps(dest[1], _mm_mul_ps(v1, x0));
_mm_store_ps(dest[2], _mm_mul_ps(v2, x0));
_mm_store_ps(dest[3], _mm_mul_ps(v3, x0));
glmm_store(dest[0], _mm_mul_ps(v0, x0));
glmm_store(dest[1], _mm_mul_ps(v1, x0));
glmm_store(dest[2], _mm_mul_ps(v2, x0));
glmm_store(dest[3], _mm_mul_ps(v3, x0));
}
CGLM_INLINE
@@ -290,14 +286,14 @@ glm_mat4_inv_sse2(mat4 mat, mat4 dest) {
x0, x1, x2, x3, x4, x5, x6, x7;
/* 127 <- 0 */
r0 = _mm_load_ps(mat[0]); /* d c b a */
r1 = _mm_load_ps(mat[1]); /* h g f e */
r2 = _mm_load_ps(mat[2]); /* l k j i */
r3 = _mm_load_ps(mat[3]); /* p o n m */
r0 = glmm_load(mat[0]); /* d c b a */
r1 = glmm_load(mat[1]); /* h g f e */
r2 = glmm_load(mat[2]); /* l k j i */
r3 = glmm_load(mat[3]); /* p o n m */
x0 = _mm_shuffle_ps(r2, r3, _MM_SHUFFLE(3, 2, 3, 2)); /* p o l k */
x1 = _mm_shuffle1_ps(x0, 1, 3, 3, 3); /* l p p p */
x2 = _mm_shuffle1_ps(x0, 0, 2, 2, 2); /* k o o o */
x1 = glmm_shuff1(x0, 1, 3, 3, 3); /* l p p p */
x2 = glmm_shuff1(x0, 0, 2, 2, 2); /* k o o o */
x0 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(3, 3, 3, 3)); /* h h l l */
x3 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(2, 2, 2, 2)); /* g g k k */
@@ -308,7 +304,7 @@ glm_mat4_inv_sse2(mat4 mat, mat4 dest) {
t0 = _mm_sub_ps(_mm_mul_ps(x3, x1), _mm_mul_ps(x2, x0));
x4 = _mm_shuffle_ps(r2, r3, _MM_SHUFFLE(2, 1, 2, 1)); /* o n k j */
x4 = _mm_shuffle1_ps(x4, 0, 2, 2, 2); /* j n n n */
x4 = glmm_shuff1(x4, 0, 2, 2, 2); /* j n n n */
x5 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(1, 1, 1, 1)); /* f f j j */
/* t1[1] = j * p - n * l;
@@ -324,7 +320,7 @@ glm_mat4_inv_sse2(mat4 mat, mat4 dest) {
t2 = _mm_sub_ps(_mm_mul_ps(x5, x2), _mm_mul_ps(x4, x3));
x6 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(0, 0, 0, 0)); /* e e i i */
x7 = _mm_shuffle2_ps(r3, r2, 0, 0, 0, 0, 2, 0, 0, 0); /* i m m m */
x7 = glmm_shuff2(r3, r2, 0, 0, 0, 0, 2, 0, 0, 0); /* i m m m */
/* t1[3] = i * p - m * l;
t1[3] = i * p - m * l;
@@ -344,10 +340,10 @@ glm_mat4_inv_sse2(mat4 mat, mat4 dest) {
t3[5] = e * j - i * f; */
t5 = _mm_sub_ps(_mm_mul_ps(x6, x4), _mm_mul_ps(x7, x5));
x0 = _mm_shuffle2_ps(r1, r0, 0, 0, 0, 0, 2, 2, 2, 0); /* a a a e */
x1 = _mm_shuffle2_ps(r1, r0, 1, 1, 1, 1, 2, 2, 2, 0); /* b b b f */
x2 = _mm_shuffle2_ps(r1, r0, 2, 2, 2, 2, 2, 2, 2, 0); /* c c c g */
x3 = _mm_shuffle2_ps(r1, r0, 3, 3, 3, 3, 2, 2, 2, 0); /* d d d h */
x0 = glmm_shuff2(r1, r0, 0, 0, 0, 0, 2, 2, 2, 0); /* a a a e */
x1 = glmm_shuff2(r1, r0, 1, 1, 1, 1, 2, 2, 2, 0); /* b b b f */
x2 = glmm_shuff2(r1, r0, 2, 2, 2, 2, 2, 2, 2, 0); /* c c c g */
x3 = glmm_shuff2(r1, r0, 3, 3, 3, 3, 2, 2, 2, 0); /* d d d h */
/*
dest[0][0] = f * t1[0] - g * t1[1] + h * t1[2];
@@ -395,14 +391,14 @@ glm_mat4_inv_sse2(mat4 mat, mat4 dest) {
x0 = _mm_shuffle_ps(x0, x1, _MM_SHUFFLE(2, 0, 2, 0));
x0 = _mm_mul_ps(x0, r0);
x0 = _mm_add_ps(x0, _mm_shuffle1_ps(x0, 0, 1, 2, 3));
x0 = _mm_add_ps(x0, _mm_shuffle1_ps(x0, 1, 0, 0, 1));
x0 = _mm_add_ps(x0, glmm_shuff1(x0, 0, 1, 2, 3));
x0 = _mm_add_ps(x0, glmm_shuff1(x0, 1, 0, 0, 1));
x0 = _mm_div_ps(_mm_set1_ps(1.0f), x0);
_mm_store_ps(dest[0], _mm_mul_ps(v0, x0));
_mm_store_ps(dest[1], _mm_mul_ps(v1, x0));
_mm_store_ps(dest[2], _mm_mul_ps(v2, x0));
_mm_store_ps(dest[3], _mm_mul_ps(v3, x0));
glmm_store(dest[0], _mm_mul_ps(v0, x0));
glmm_store(dest[1], _mm_mul_ps(v1, x0));
glmm_store(dest[2], _mm_mul_ps(v2, x0));
glmm_store(dest[3], _mm_mul_ps(v3, x0));
}
#endif

View File

@@ -14,56 +14,33 @@
CGLM_INLINE
void
glm_quat_slerp_sse2(versor q,
versor r,
float t,
versor dest) {
/* https://en.wikipedia.org/wiki/Slerp */
float cosTheta, sinTheta, angle, a, b, c;
glm_quat_mul_sse2(versor p, versor q, versor dest) {
/*
+ (a1 b2 + b1 a2 + c1 d2 d1 c2)i
+ (a1 c2 b1 d2 + c1 a2 + d1 b2)j
+ (a1 d2 + b1 c2 c1 b2 + d1 a2)k
a1 a2 b1 b2 c1 c2 d1 d2
*/
__m128 xmm_q;
__m128 xp, xq, x0, r;
xmm_q = _mm_load_ps(q);
xp = glmm_load(p); /* 3 2 1 0 */
xq = glmm_load(q);
cosTheta = glm_vec4_dot(q, r);
if (cosTheta < 0.0f) {
_mm_store_ps(q,
_mm_xor_ps(xmm_q,
_mm_set1_ps(-0.f))) ;
r = _mm_mul_ps(glmm_shuff1x(xp, 3), xq);
cosTheta = -cosTheta;
}
x0 = _mm_xor_ps(glmm_shuff1x(xp, 0), _mm_set_ps(-0.f, 0.f, -0.f, 0.f));
r = _mm_add_ps(r, _mm_mul_ps(x0, glmm_shuff1(xq, 0, 1, 2, 3)));
if (cosTheta >= 1.0f) {
_mm_store_ps(dest, xmm_q);
return;
}
x0 = _mm_xor_ps(glmm_shuff1x(xp, 1), _mm_set_ps(-0.f, -0.f, 0.f, 0.f));
r = _mm_add_ps(r, _mm_mul_ps(x0, glmm_shuff1(xq, 1, 0, 3, 2)));
sinTheta = sqrtf(1.0f - cosTheta * cosTheta);
x0 = _mm_xor_ps(glmm_shuff1x(xp, 2), _mm_set_ps(-0.f, 0.f, 0.f, -0.f));
r = _mm_add_ps(r, _mm_mul_ps(x0, glmm_shuff1(xq, 2, 3, 0, 1)));
c = 1.0f - t;
/* LERP */
if (sinTheta < 0.001f) {
_mm_store_ps(dest, _mm_add_ps(_mm_mul_ps(_mm_set1_ps(c),
xmm_q),
_mm_mul_ps(_mm_set1_ps(t),
_mm_load_ps(r))));
return;
}
/* SLERP */
angle = acosf(cosTheta);
a = sinf(c * angle);
b = sinf(t * angle);
_mm_store_ps(dest,
_mm_div_ps(_mm_add_ps(_mm_mul_ps(_mm_set1_ps(a),
xmm_q),
_mm_mul_ps(_mm_set1_ps(b),
_mm_load_ps(r))),
_mm_set1_ps(sinTheta)));
glmm_store(dest, r);
}
#endif
#endif /* cglm_quat_simd_h */

136
include/cglm/simd/x86.h Normal file
View File

@@ -0,0 +1,136 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglm_simd_x86_h
#define cglm_simd_x86_h
#include "intrin.h"
#ifdef CGLM_SIMD_x86
#ifdef CGLM_ALL_UNALIGNED
# define glmm_load(p) _mm_loadu_ps(p)
# define glmm_store(p, a) _mm_storeu_ps(p, a)
#else
# define glmm_load(p) _mm_load_ps(p)
# define glmm_store(p, a) _mm_store_ps(p, a)
#endif
#ifdef CGLM_USE_INT_DOMAIN
# define glmm_shuff1(xmm, z, y, x, w) \
_mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(xmm), \
_MM_SHUFFLE(z, y, x, w)))
#else
# define glmm_shuff1(xmm, z, y, x, w) \
_mm_shuffle_ps(xmm, xmm, _MM_SHUFFLE(z, y, x, w))
#endif
#define glmm_shuff1x(xmm, x) glmm_shuff1(xmm, x, x, x, x)
#define glmm_shuff2(a, b, z0, y0, x0, w0, z1, y1, x1, w1) \
glmm_shuff1(_mm_shuffle_ps(a, b, _MM_SHUFFLE(z0, y0, x0, w0)), \
z1, y1, x1, w1)
#ifdef __AVX__
# ifdef CGLM_ALL_UNALIGNED
# define glmm_load256(p) _mm256_loadu_ps(p)
# define glmm_store256(p, a) _mm256_storeu_ps(p, a)
# else
# define glmm_load256(p) _mm256_load_ps(p)
# define glmm_store256(p, a) _mm256_store_ps(p, a)
# endif
#endif
static inline
__m128
glmm_vhadds(__m128 v) {
#if defined(__SSE3__)
__m128 shuf, sums;
shuf = _mm_movehdup_ps(v);
sums = _mm_add_ps(v, shuf);
shuf = _mm_movehl_ps(shuf, sums);
sums = _mm_add_ss(sums, shuf);
return sums;
#else
__m128 shuf, sums;
shuf = glmm_shuff1(v, 2, 3, 0, 1);
sums = _mm_add_ps(v, shuf);
shuf = _mm_movehl_ps(shuf, sums);
sums = _mm_add_ss(sums, shuf);
return sums;
#endif
}
static inline
float
glmm_hadd(__m128 v) {
return _mm_cvtss_f32(glmm_vhadds(v));
}
static inline
__m128
glmm_vdots(__m128 a, __m128 b) {
#if (defined(__SSE4_1__) || defined(__SSE4_2__)) && defined(CGLM_SSE4_DOT)
return _mm_dp_ps(a, b, 0xFF);
#elif defined(__SSE3__) && defined(CGLM_SSE3_DOT)
__m128 x0, x1;
x0 = _mm_mul_ps(a, b);
x1 = _mm_hadd_ps(x0, x0);
return _mm_hadd_ps(x1, x1);
#else
return glmm_vhadds(_mm_mul_ps(a, b));
#endif
}
static inline
__m128
glmm_vdot(__m128 a, __m128 b) {
#if (defined(__SSE4_1__) || defined(__SSE4_2__)) && defined(CGLM_SSE4_DOT)
return _mm_dp_ps(a, b, 0xFF);
#elif defined(__SSE3__) && defined(CGLM_SSE3_DOT)
__m128 x0, x1;
x0 = _mm_mul_ps(a, b);
x1 = _mm_hadd_ps(x0, x0);
return _mm_hadd_ps(x1, x1);
#else
__m128 x0;
x0 = _mm_mul_ps(a, b);
x0 = _mm_add_ps(x0, glmm_shuff1(x0, 1, 0, 3, 2));
return _mm_add_ps(x0, glmm_shuff1(x0, 0, 1, 0, 1));
#endif
}
static inline
float
glmm_dot(__m128 a, __m128 b) {
return _mm_cvtss_f32(glmm_vdots(a, b));
}
static inline
float
glmm_norm(__m128 a) {
return _mm_cvtss_f32(_mm_sqrt_ss(glmm_vhadds(_mm_mul_ps(a, a))));
}
static inline
__m128
glmm_load3(float v[3]) {
__m128i xy;
__m128 z;
xy = _mm_loadl_epi64((const __m128i *)v);
z = _mm_load_ss(&v[2]);
return _mm_movelh_ps(_mm_castsi128_ps(xy), z);
}
static inline
void
glmm_store3(__m128 vx, float v[3]) {
_mm_storel_pi((__m64 *)&v[0], vx);
_mm_store_ss(&v[2], glmm_shuff1(vx, 2, 2, 2, 2));
}
#endif
#endif /* cglm_simd_x86_h */

99
include/cglm/sphere.h Normal file
View File

@@ -0,0 +1,99 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglm_sphere_h
#define cglm_sphere_h
#include "common.h"
#include "mat4.h"
/*
Sphere Representation in cglm: [center.x, center.y, center.z, radii]
You could use this representation or you can convert it to vec4 before call
any function
*/
/*!
* @brief helper for getting sphere radius
*
* @param[in] s sphere
*
* @return returns radii
*/
CGLM_INLINE
float
glm_sphere_radii(vec4 s) {
return s[3];
}
/*!
* @brief apply transform to sphere, it is just wrapper for glm_mat4_mulv3
*
* @param[in] s sphere
* @param[in] m transform matrix
* @param[out] dest transformed sphere
*/
CGLM_INLINE
void
glm_sphere_transform(vec4 s, mat4 m, vec4 dest) {
glm_mat4_mulv3(m, s, 1.0f, dest);
dest[3] = s[3];
}
/*!
* @brief merges two spheres and creates a new one
*
* two sphere must be in same space, for instance if one in world space then
* the other must be in world space too, not in local space.
*
* @param[in] s1 sphere 1
* @param[in] s2 sphere 2
* @param[out] dest merged/extended sphere
*/
CGLM_INLINE
void
glm_sphere_merge(vec4 s1, vec4 s2, vec4 dest) {
float dist, radii;
dist = glm_vec3_distance(s1, s2);
radii = dist + s1[3] + s2[3];
radii = glm_max(radii, s1[3]);
radii = glm_max(radii, s2[3]);
glm_vec3_center(s1, s2, dest);
dest[3] = radii;
}
/*!
* @brief check if two sphere intersects
*
* @param[in] s1 sphere
* @param[in] s2 other sphere
*/
CGLM_INLINE
bool
glm_sphere_sphere(vec4 s1, vec4 s2) {
return glm_vec3_distance2(s1, s2) <= glm_pow2(s1[3] + s2[3]);
}
/*!
* @brief check if sphere intersects with point
*
* @param[in] s sphere
* @param[in] point point
*/
CGLM_INLINE
bool
glm_sphere_point(vec4 s, vec3 point) {
float rr;
rr = s[3] * s[3];
return glm_vec3_distance2(point, s) <= rr;
}
#endif /* cglm_sphere_h */

36
include/cglm/struct.h Normal file
View File

@@ -0,0 +1,36 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglm_structs_h
#define cglm_structs_h
#ifdef __cplusplus
extern "C" {
#endif
#include "cglm.h"
#include "types-struct.h"
#include "struct/vec3.h"
#include "struct/vec4.h"
#include "struct/mat3.h"
#include "struct/mat4.h"
#include "struct/affine.h"
#include "struct/frustum.h"
#include "struct/plane.h"
#include "struct/box.h"
#include "struct/color.h"
#include "struct/io.h"
#include "struct/cam.h"
#include "struct/quat.h"
#include "struct/euler.h"
#include "struct/project.h"
#include "struct/sphere.h"
#include "struct/curve.h"
#ifdef __cplusplus
}
#endif
#endif /* cglm_structs_h */

View File

@@ -0,0 +1,337 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
/*
Functions:
CGLM_INLINE mat4s glms_translate(mat4s m, vec3s v);
CGLM_INLINE mat4s glms_translate_x(mat4s m, float x);
CGLM_INLINE mat4s glms_translate_y(mat4s m, float y);
CGLM_INLINE mat4s glms_translate_z(mat4s m, float z);
CGLM_INLINE mat4s glms_translate_make(vec3s v);
CGLM_INLINE mat4s glms_scale_to(mat4s m, vec3s v);
CGLM_INLINE mat4s glms_scale_make(vec3s v);
CGLM_INLINE mat4s glms_scale(mat4s m, vec3s v);
CGLM_INLINE mat4s glms_scale_uni(mat4s m, float s);
CGLM_INLINE mat4s glmx_rotate_x(mat4s m, float angle);
CGLM_INLINE mat4s glms_rotate_y(mat4s m, float angle);
CGLM_INLINE mat4s glms_rotate_z(mat4s m, float angle);
CGLM_INLINE mat4s glms_rotate_make(float angle, vec3s axis);
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 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);
CGLM_INLINE void glms_decompose(mat4s m, vec4s t, mat4s * r, vec3s * s);
*/
#ifndef cglms_affines_h
#define cglms_affines_h
#include "../common.h"
#include "../types-struct.h"
#include "../affine.h"
#include "vec3.h"
#include "vec4.h"
#include "mat4.h"
CGLM_INLINE
mat4s
glms_mat4_mul(mat4s m1, mat4s m2);
/*!
* @brief translate existing transform matrix by v vector
* and stores result in same matrix
*
* @param[in] m affine transfrom
* @param[in] v translate vector [x, y, z]
* @returns affine transfrom
*/
CGLM_INLINE
mat4s
glms_translate(mat4s m, vec3s v) {
glm_translate(m.raw, v.raw);
return m;
}
/*!
* @brief translate existing transform matrix by x factor
*
* @param[in] m affine transfrom
* @param[in] x x factor
* @returns affine transfrom
*/
CGLM_INLINE
mat4s
glms_translate_x(mat4s m, float x) {
glm_translate_x(m.raw, x);
return m;
}
/*!
* @brief translate existing transform matrix by y factor
*
* @param[in] m affine transfrom
* @param[in] y y factor
* @returns affine transfrom
*/
CGLM_INLINE
mat4s
glms_translate_y(mat4s m, float y) {
glm_translate_y(m.raw, y);
return m;
}
/*!
* @brief translate existing transform matrix by z factor
*
* @param[in] m affine transfrom
* @param[in] z z factor
* @returns affine transfrom
*/
CGLM_INLINE
mat4s
glms_translate_z(mat4s m, float z) {
glm_translate_z(m.raw, z);
return m;
}
/*!
* @brief creates NEW translate transform matrix by v vector
*
* @param[in] v translate vector [x, y, z]
* @returns affine transfrom
*/
CGLM_INLINE
mat4s
glms_translate_make(vec3s v) {
mat4s m;
glm_translate_make(m.raw, v.raw);
return m;
}
/*!
* @brief creates NEW scale matrix by v vector
*
* @param[in] v scale vector [x, y, z]
* @returns affine transfrom
*/
CGLM_INLINE
mat4s
glms_scale_make(vec3s v) {
mat4s m;
glm_scale_make(m.raw, v.raw);
return m;
}
/*!
* @brief scales existing transform matrix by v vector
* and stores result in same matrix
*
* @param[in] m affine transfrom
* @param[in] v scale vector [x, y, z]
* @returns affine transfrom
*/
CGLM_INLINE
mat4s
glms_scale(mat4s m, vec3s v) {
mat4s r;
glm_scale_to(m.raw, v.raw, r.raw);
return r;
}
/*!
* @brief applies uniform scale to existing transform matrix v = [s, s, s]
* and stores result in same matrix
*
* @param[in] m affine transfrom
* @param[in] s scale factor
* @returns affine transfrom
*/
CGLM_INLINE
mat4s
glms_scale_uni(mat4s m, float s) {
glm_scale_uni(m.raw, s);
return 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)
* @returns rotated matrix
*/
CGLM_INLINE
mat4s
glmx_rotate_x(mat4s m, float angle) {
mat4s r;
glm_rotate_x(m.raw, angle, r.raw);
return r;
}
/*!
* @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)
* @returns rotated matrix
*/
CGLM_INLINE
mat4s
glms_rotate_y(mat4s m, float angle) {
mat4s r;
glm_rotate_y(m.raw, angle, r.raw);
return r;
}
/*!
* @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)
* @returns rotated matrix
*/
CGLM_INLINE
mat4s
glms_rotate_z(mat4s m, float angle) {
mat4s r;
glm_rotate_z(m.raw, angle, r.raw);
return r;
}
/*!
* @brief creates NEW rotation matrix by angle and axis
*
* axis will be normalized so you don't need to normalize it
*
* @param[in] angle angle (radians)
* @param[in] axis axis
* @returns affine transfrom
*/
CGLM_INLINE
mat4s
glms_rotate_make(float angle, vec3s axis) {
mat4s m;
glm_rotate_make(m.raw, angle, axis.raw);
return m;
}
/*!
* @brief rotate existing transform matrix around given axis by angle
*
* @param[in] m affine transfrom
* @param[in] angle angle (radians)
* @param[in] axis axis
* @returns affine transfrom
*/
CGLM_INLINE
mat4s
glms_rotate(mat4s m, float angle, vec3s axis) {
glm_rotate(m.raw, angle, axis.raw);
return m;
}
/*!
* @brief rotate existing transform
* around given axis by angle at given pivot point (rotation center)
*
* @param[in] m affine transfrom
* @param[in] pivot rotation center
* @param[in] angle angle (radians)
* @param[in] axis axis
* @returns affine transfrom
*/
CGLM_INLINE
mat4s
glms_rotate_at(mat4s m, vec3s pivot, float angle, vec3s axis) {
glm_rotate_at(m.raw, pivot.raw, angle, axis.raw);
return m;
}
/*!
* @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[in] m affine transfrom
* @param[in] pivot rotation center
* @param[in] angle angle (radians)
* @param[in] axis axis
* @returns affine transfrom
*/
CGLM_INLINE
mat4s
glms_rotate_atm(mat4s m, vec3s pivot, float angle, vec3s axis) {
glm_rotate_atm(m.raw, pivot.raw, angle, axis.raw);
return m;
}
/*!
* @brief decompose scale vector
*
* @param[in] m affine transform
* @returns scale vector (Sx, Sy, Sz)
*/
CGLM_INLINE
vec3s
glms_decompose_scalev(mat4s m) {
vec3s r;
glm_decompose_scalev(m.raw, r.raw);
return r;
}
/*!
* @brief returns true if matrix is uniform scaled. This is helpful for
* creating normal matrix.
*
* @param[in] m m
*
* @return boolean
*/
CGLM_INLINE
bool
glms_uniscaled(mat4s m) {
return glm_uniscaled(m.raw);
}
/*!
* @brief decompose rotation matrix (mat4) and scale vector [Sx, Sy, Sz]
* DON'T pass projected matrix here
*
* @param[in] m affine transform
* @param[out] r rotation matrix
* @param[out] s scale matrix
*/
CGLM_INLINE
void
glms_decompose_rs(mat4s m, mat4s * __restrict r, vec3s * __restrict s) {
glm_decompose_rs(m.raw, r->raw, s->raw);
}
/*!
* @brief decompose affine transform, TODO: extract shear factors.
* DON'T pass projected matrix here
*
* @param[in] m affine transfrom
* @param[out] t translation vector
* @param[out] r rotation matrix (mat4)
* @param[out] s scaling vector [X, Y, Z]
*/
CGLM_INLINE
void
glms_decompose(mat4s m, vec4s * __restrict t, mat4s * __restrict r, vec3s * __restrict s) {
glm_decompose(m.raw, t->raw, r->raw, s->raw);
}
#endif /* cglms_affines_h */

256
include/cglm/struct/box.h Normal file
View File

@@ -0,0 +1,256 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglms_boxs_h
#define cglms_boxs_h
#include "../common.h"
#include "../types-struct.h"
#include "../box.h"
#include "vec3.h"
#include "vec4.h"
#include "mat4.h"
/*!
* @brief apply transform to Axis-Aligned Bounding Box
*
* @param[in] box bounding box
* @param[in] m transform matrix
* @param[out] dest transformed bounding box
*/
CGLM_INLINE
void
glms_aabb_transform(vec3s box[2], mat4s m, vec3s dest[2]) {
vec3 rawBox[2];
vec3 rawDest[2];
glms_vec3_unpack(rawBox, box, 2);
glm_aabb_transform(rawBox, m.raw, rawDest);
glms_vec3_pack(dest, rawDest, 2);
}
/*!
* @brief merges two AABB bounding box and creates new one
*
* two box must be in same space, if one of box is in different space then
* you should consider to convert it's space by glm_box_space
*
* @param[in] box1 bounding box 1
* @param[in] box2 bounding box 2
* @param[out] dest merged bounding box
*/
CGLM_INLINE
void
glms_aabb_merge(vec3s box1[2], vec3s box2[2], vec3s dest[2]) {
vec3 rawBox1[2];
vec3 rawBox2[2];
vec3 rawDest[2];
glms_vec3_unpack(rawBox1, box1, 2);
glms_vec3_unpack(rawBox2, box2, 2);
glm_aabb_merge(rawBox1, rawBox2, rawDest);
glms_vec3_pack(dest, rawDest, 2);
}
/*!
* @brief crops a bounding box with another one.
*
* 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
*
* @param[in] box bounding box 1
* @param[in] cropBox crop box
* @param[out] dest cropped bounding box
*/
CGLM_INLINE
void
glms_aabb_crop(vec3s box[2], vec3s cropBox[2], vec3s dest[2]) {
vec3 rawBox[2];
vec3 rawCropBox[2];
vec3 rawDest[2];
glms_vec3_unpack(rawBox, box, 2);
glms_vec3_unpack(rawCropBox, cropBox, 2);
glm_aabb_crop(rawBox, rawCropBox, rawDest);
glms_vec3_pack(dest, rawDest, 2);
}
/*!
* @brief crops a bounding box with another one.
*
* 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
*
* @param[in] box bounding box
* @param[in] cropBox crop box
* @param[in] clampBox miniumum box
* @param[out] dest cropped bounding box
*/
CGLM_INLINE
void
glms_aabb_crop_until(vec3s box[2],
vec3s cropBox[2],
vec3s clampBox[2],
vec3s dest[2]) {
glms_aabb_crop(box, cropBox, dest);
glms_aabb_merge(clampBox, dest, dest);
}
/*!
* @brief check if AABB intersects with frustum planes
*
* this could be useful for frustum culling using AABB.
*
* OPTIMIZATION HINT:
* if planes order is similar to LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR
* then this method should run even faster because it would only use two
* planes if object is not inside the two planes
* fortunately cglm extracts planes as this order! just pass what you got!
*
* @param[in] box bounding box
* @param[in] planes frustum planes
*/
CGLM_INLINE
bool
glms_aabb_frustum(vec3s box[2], vec4s planes[6]) {
vec3 rawBox[2];
vec4 rawPlanes[6];
glms_vec3_unpack(rawBox, box, 2);
glms_vec4_unpack(rawPlanes, planes, 6);
return glm_aabb_frustum(rawBox, rawPlanes);
}
/*!
* @brief invalidate AABB min and max values
*
* @param[in, out] box bounding box
*/
CGLM_INLINE
void
glms_aabb_invalidate(vec3s box[2]) {
box[0] = glms_vec3_broadcast(FLT_MAX);
box[1] = glms_vec3_broadcast(-FLT_MAX);
}
/*!
* @brief check if AABB is valid or not
*
* @param[in] box bounding box
*/
CGLM_INLINE
bool
glms_aabb_isvalid(vec3s box[2]) {
vec3 rawBox[2];
glms_vec3_unpack(rawBox, box, 2);
return glm_aabb_isvalid(rawBox);
}
/*!
* @brief distance between of min and max
*
* @param[in] box bounding box
*/
CGLM_INLINE
float
glms_aabb_size(vec3s box[2]) {
return glm_vec3_distance(box[0].raw, box[1].raw);
}
/*!
* @brief radius of sphere which surrounds AABB
*
* @param[in] box bounding box
*/
CGLM_INLINE
float
glms_aabb_radius(vec3s box[2]) {
return glms_aabb_size(box) * 0.5f;
}
/*!
* @brief computes center point of AABB
*
* @param[in] box bounding box
* @returns center of bounding box
*/
CGLM_INLINE
vec3s
glms_aabb_center(vec3s box[2]) {
return glms_vec3_center(box[0], box[1]);
}
/*!
* @brief check if two AABB intersects
*
* @param[in] box bounding box
* @param[in] other other bounding box
*/
CGLM_INLINE
bool
glms_aabb_aabb(vec3s box[2], vec3s other[2]) {
vec3 rawBox[2];
vec3 rawOther[2];
glms_vec3_unpack(rawBox, box, 2);
glms_vec3_unpack(rawOther, other, 2);
return glm_aabb_aabb(rawBox, rawOther);
}
/*!
* @brief check if AABB intersects with sphere
*
* https://github.com/erich666/GraphicsGems/blob/master/gems/BoxSphere.c
* Solid Box - Solid Sphere test.
*
* @param[in] box solid bounding box
* @param[in] s solid sphere
*/
CGLM_INLINE
bool
glms_aabb_sphere(vec3s box[2], vec4s s) {
vec3 rawBox[2];
glms_vec3_unpack(rawBox, box, 2);
return glm_aabb_sphere(rawBox, s.raw);
}
/*!
* @brief check if point is inside of AABB
*
* @param[in] box bounding box
* @param[in] point point
*/
CGLM_INLINE
bool
glms_aabb_point(vec3s box[2], vec3s point) {
vec3 rawBox[2];
glms_vec3_unpack(rawBox, box, 2);
return glm_aabb_point(rawBox, point.raw);
}
/*!
* @brief check if AABB contains other AABB
*
* @param[in] box bounding box
* @param[in] other other bounding box
*/
CGLM_INLINE
bool
glms_aabb_contains(vec3s box[2], vec3s other[2]) {
vec3 rawBox[2];
vec3 rawOther[2];
glms_vec3_unpack(rawBox, box, 2);
glms_vec3_unpack(rawOther, other, 2);
return glm_aabb_contains(rawBox, rawOther);
}
#endif /* cglms_boxs_h */

451
include/cglm/struct/cam.h Normal file
View File

@@ -0,0 +1,451 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
/*
Functions:
CGLM_INLINE mat4s glms_frustum(float left, float right,
float bottom, float top,
float nearVal, float farVal)
CGLM_INLINE mat4s glms_ortho(float left, float right,
float bottom, float top,
float nearVal, float farVal)
CGLM_INLINE mat4s glms_ortho_aabb(vec3s box[2]);
CGLM_INLINE mat4s glms_ortho_aabb_p(vec3s box[2], float padding);
CGLM_INLINE mat4s glms_ortho_aabb_pz(vec3s box[2], float padding);
CGLM_INLINE mat4s glms_ortho_default(float aspect)
CGLM_INLINE mat4s glms_ortho_default_s(float aspect, float size)
CGLM_INLINE mat4s glms_perspective(float fovy,
float aspect,
float nearVal,
float farVal)
CGLM_INLINE void glms_persp_move_far(mat4s proj, float deltaFar)
CGLM_INLINE mat4s glms_perspective_default(float aspect)
CGLM_INLINE void glms_perspective_resize(mat4s proj, float aspect)
CGLM_INLINE mat4s glms_lookat(vec3s eye, vec3s center, vec3s up)
CGLM_INLINE mat4s glms_look(vec3s eye, vec3s dir, vec3s up)
CGLM_INLINE mat4s glms_look_anyup(vec3s eye, vec3s dir)
CGLM_INLINE void glms_persp_decomp(mat4s proj,
float *nearv, float *farv,
float *top, float *bottom,
float *left, float *right)
CGLM_INLINE void glms_persp_decompv(mat4s proj, float dest[6])
CGLM_INLINE void glms_persp_decomp_x(mat4s proj, float *left, float *right)
CGLM_INLINE void glms_persp_decomp_y(mat4s proj, float *top, float *bottom)
CGLM_INLINE void glms_persp_decomp_z(mat4s proj, float *nearv, float *farv)
CGLM_INLINE void glms_persp_decomp_far(mat4s proj, float *farVal)
CGLM_INLINE void glms_persp_decomp_near(mat4s proj, float *nearVal)
CGLM_INLINE float glms_persp_fovy(mat4s proj)
CGLM_INLINE float glms_persp_aspect(mat4s proj)
CGLM_INLINE vec4s glms_persp_sizes(mat4s proj, float fovy)
*/
#ifndef cglms_cam_h
#define cglms_cam_h
#include "../common.h"
#include "../types-struct.h"
#include "../plane.h"
#include "../cam.h"
/*!
* @brief set up perspective peprojection matrix
*
* @param[in] left viewport.left
* @param[in] right viewport.right
* @param[in] bottom viewport.bottom
* @param[in] top viewport.top
* @param[in] nearVal near clipping plane
* @param[in] farVal far clipping plane
* @returns result matrix
*/
CGLM_INLINE
mat4s
glms_frustum(float left, float right,
float bottom, float top,
float nearVal, float farVal) {
mat4s dest;
glm_frustum(left, right, bottom, top, nearVal, farVal, dest.raw);
return dest;
}
/*!
* @brief set up orthographic projection matrix
*
* @param[in] left viewport.left
* @param[in] right viewport.right
* @param[in] bottom viewport.bottom
* @param[in] top viewport.top
* @param[in] nearVal near clipping plane
* @param[in] farVal far clipping plane
* @returns result matrix
*/
CGLM_INLINE
mat4s
glms_ortho(float left, float right,
float bottom, float top,
float nearVal, float farVal) {
mat4s dest;
glm_ortho(left, right, bottom, top, nearVal, farVal, dest.raw);
return dest;
}
/*!
* @brief set up orthographic projection matrix using bounding box
*
* bounding box (AABB) must be in view space
*
* @param[in] box AABB
* @returns result matrix
*/
CGLM_INLINE
mat4s
glms_ortho_aabb(vec3s box[2]) {
mat4s dest;
vec3 rawBox[2];
glms_vec3_unpack(rawBox, box, 2);
glm_ortho_aabb(rawBox, dest.raw);
return dest;
}
/*!
* @brief set up orthographic projection matrix using bounding box
*
* bounding box (AABB) must be in view space
*
* @param[in] box AABB
* @param[in] padding padding
* @returns result matrix
*/
CGLM_INLINE
mat4s
glms_ortho_aabb_p(vec3s box[2], float padding) {
mat4s dest;
vec3 rawBox[2];
glms_vec3_unpack(rawBox, box, 2);
glm_ortho_aabb_p(rawBox, padding, dest.raw);
return dest;
}
/*!
* @brief set up orthographic projection matrix using bounding box
*
* bounding box (AABB) must be in view space
*
* @param[in] box AABB
* @param[in] padding padding for near and far
* @returns result matrix
*/
CGLM_INLINE
mat4s
glms_ortho_aabb_pz(vec3s box[2], float padding) {
mat4s dest;
vec3 rawBox[2];
glms_vec3_unpack(rawBox, box, 2);
glm_ortho_aabb_pz(rawBox, padding, dest.raw);
return dest;
}
/*!
* @brief set up unit orthographic projection matrix
*
* @param[in] aspect aspect ration ( width / height )
* @returns result matrix
*/
CGLM_INLINE
mat4s
glms_ortho_default(float aspect) {
mat4s dest;
glm_ortho_default(aspect, dest.raw);
return dest;
}
/*!
* @brief set up orthographic projection matrix with given CUBE size
*
* @param[in] aspect aspect ratio ( width / height )
* @param[in] size cube size
* @returns result matrix
*/
CGLM_INLINE
mat4s
glms_ortho_default_s(float aspect, float size) {
mat4s dest;
glm_ortho_default_s(aspect, size, dest.raw);
return dest;
}
/*!
* @brief set up perspective projection matrix
*
* @param[in] fovy field of view angle
* @param[in] aspect aspect ratio ( width / height )
* @param[in] nearVal near clipping plane
* @param[in] farVal far clipping planes
* @returns result matrix
*/
CGLM_INLINE
mat4s
glms_perspective(float fovy, float aspect, float nearVal, float farVal) {
mat4s dest;
glm_perspective(fovy, aspect, nearVal, farVal, dest.raw);
return dest;
}
/*!
* @brief extend perspective projection matrix's far distance
*
* this function does not guarantee far >= near, be aware of that!
*
* @param[in, out] proj projection matrix to extend
* @param[in] deltaFar distance from existing far (negative to shink)
*/
CGLM_INLINE
void
glms_persp_move_far(mat4s proj, float deltaFar) {
glm_persp_move_far(proj.raw, deltaFar);
}
/*!
* @brief set up perspective projection matrix with default near/far
* and angle values
*
* @param[in] aspect aspect ratio ( width / height )
* @returns result matrix
*/
CGLM_INLINE
mat4s
glms_perspective_default(float aspect) {
mat4s dest;
glm_perspective_default(aspect, dest.raw);
return dest;
}
/*!
* @brief resize perspective matrix by aspect ratio ( width / height )
* this makes very easy to resize proj matrix when window /viewport
* reized
*
* @param[in, out] proj perspective projection matrix
* @param[in] aspect aspect ratio ( width / height )
*/
CGLM_INLINE
void
glms_perspective_resize(mat4s proj, float aspect) {
glm_perspective_resize(aspect, proj.raw);
}
/*!
* @brief set up view matrix
*
* NOTE: The UP vector must not be parallel to the line of sight from
* the eye point to the reference point
*
* @param[in] eye eye vector
* @param[in] center center vector
* @param[in] up up vector
* @returns result matrix
*/
CGLM_INLINE
mat4s
glms_lookat(vec3s eye, vec3s center, vec3s up) {
mat4s dest;
glm_lookat(eye.raw, center.raw, up.raw, dest.raw);
return dest;
}
/*!
* @brief set up view matrix
*
* convenient wrapper for lookat: if you only have direction not target self
* then this might be useful. Because you need to get target from direction.
*
* NOTE: The UP vector must not be parallel to the line of sight from
* the eye point to the reference point
*
* @param[in] eye eye vector
* @param[in] dir direction vector
* @param[in] up up vector
* @returns result matrix
*/
CGLM_INLINE
mat4s
glms_look(vec3s eye, vec3s dir, vec3s up) {
mat4s dest;
glm_look(eye.raw, dir.raw, up.raw, dest.raw);
return dest;
}
/*!
* @brief set up view matrix
*
* convenient wrapper for look: if you only have direction and if you don't
* care what UP vector is then this might be useful to create view matrix
*
* @param[in] eye eye vector
* @param[in] dir direction vector
* @returns result matrix
*/
CGLM_INLINE
mat4s
glms_look_anyup(vec3s eye, vec3s dir) {
mat4s dest;
glm_look_anyup(eye.raw, dir.raw, dest.raw);
return dest;
}
/*!
* @brief decomposes frustum values of perspective projection.
*
* @param[in] proj perspective projection matrix
* @param[out] nearVal near
* @param[out] farVal far
* @param[out] top top
* @param[out] bottom bottom
* @param[out] left left
* @param[out] right right
*/
CGLM_INLINE
void
glms_persp_decomp(mat4s proj,
float * __restrict nearVal, float * __restrict farVal,
float * __restrict top, float * __restrict bottom,
float * __restrict left, float * __restrict right) {
glm_persp_decomp(proj.raw, nearVal, farVal, top, bottom, left, right);
}
/*!
* @brief decomposes frustum values of perspective projection.
* this makes easy to get all values at once
*
* @param[in] proj perspective projection matrix
* @param[out] dest array
*/
CGLM_INLINE
void
glms_persp_decompv(mat4s proj, float dest[6]) {
glm_persp_decompv(proj.raw, dest);
}
/*!
* @brief decomposes left and right values of perspective projection.
* x stands for x axis (left / right axis)
*
* @param[in] proj perspective projection matrix
* @param[out] left left
* @param[out] right right
*/
CGLM_INLINE
void
glms_persp_decomp_x(mat4s proj,
float * __restrict left,
float * __restrict right) {
glm_persp_decomp_x(proj.raw, left, right);
}
/*!
* @brief decomposes top and bottom values of perspective projection.
* y stands for y axis (top / botom axis)
*
* @param[in] proj perspective projection matrix
* @param[out] top top
* @param[out] bottom bottom
*/
CGLM_INLINE
void
glms_persp_decomp_y(mat4s proj,
float * __restrict top,
float * __restrict bottom) {
glm_persp_decomp_y(proj.raw, top, bottom);
}
/*!
* @brief decomposes near and far values of perspective projection.
* z stands for z axis (near / far axis)
*
* @param[in] proj perspective projection matrix
* @param[out] nearVal near
* @param[out] farVal far
*/
CGLM_INLINE
void
glms_persp_decomp_z(mat4s proj,
float * __restrict nearVal,
float * __restrict farVal) {
glm_persp_decomp_z(proj.raw, nearVal, farVal);
}
/*!
* @brief decomposes far value of perspective projection.
*
* @param[in] proj perspective projection matrix
* @param[out] farVal far
*/
CGLM_INLINE
void
glms_persp_decomp_far(mat4s proj, float * __restrict farVal) {
glm_persp_decomp_far(proj.raw, farVal);
}
/*!
* @brief decomposes near value of perspective projection.
*
* @param[in] proj perspective projection matrix
* @param[out] nearVal near
*/
CGLM_INLINE
void
glms_persp_decomp_near(mat4s proj, float * __restrict nearVal) {
glm_persp_decomp_near(proj.raw, nearVal);
}
/*!
* @brief returns field of view angle along the Y-axis (in radians)
*
* if you need to degrees, use glm_deg to convert it or use this:
* fovy_deg = glm_deg(glm_persp_fovy(projMatrix))
*
* @param[in] proj perspective projection matrix
*/
CGLM_INLINE
float
glms_persp_fovy(mat4s proj) {
return glm_persp_fovy(proj.raw);
}
/*!
* @brief returns aspect ratio of perspective projection
*
* @param[in] proj perspective projection matrix
*/
CGLM_INLINE
float
glms_persp_aspect(mat4s proj) {
return glm_persp_aspect(proj.raw);
}
/*!
* @brief returns sizes of near and far planes of perspective projection
*
* @param[in] proj perspective projection matrix
* @param[in] fovy fovy (see brief)
* @returns sizes as vector, sizes order: [Wnear, Hnear, Wfar, Hfar]
*/
CGLM_INLINE
vec4s
glms_persp_sizes(mat4s proj, float fovy) {
vec4s dest;
glm_persp_sizes(proj.raw, fovy, dest.raw);
return dest;
}
#endif /* cglms_cam_h */

View File

@@ -0,0 +1,27 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglms_colors_h
#define cglms_colors_h
#include "../common.h"
#include "../types-struct.h"
#include "../color.h"
#include "vec3.h"
/*!
* @brief averages the color channels into one value
*
* @param[in] rgb RGB color
*/
CGLM_INLINE
float
glms_luminance(vec3s rgb) {
return glm_luminance(rgb.raw);
}
#endif /* cglms_colors_h */

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglms_curves_h
#define cglms_curves_h
#include "../common.h"
#include "../types-struct.h"
#include "../curve.h"
#include "vec4.h"
#include "mat4.h"
/*!
* @brief helper function to calculate S*M*C multiplication for curves
*
* This function does not encourage you to use SMC,
* instead it is a helper if you use SMC.
*
* if you want to specify S as vector then use more generic glm_mat4_rmc() func.
*
* Example usage:
* B(s) = glm_smc(s, GLM_BEZIER_MAT, (vec4){p0, c0, c1, p1})
*
* @param[in] s parameter between 0 and 1 (this will be [s3, s2, s, 1])
* @param[in] m basis matrix
* @param[in] c position/control vector
*
* @return B(s)
*/
CGLM_INLINE
float
glms_smc(float s, mat4s m, vec4s c) {
return glm_smc(s, m.raw, c.raw);
}
#endif /* cglms_curves_h */

152
include/cglm/struct/euler.h Normal file
View File

@@ -0,0 +1,152 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
/*
NOTE:
angles must be passed as [X-Angle, Y-Angle, Z-angle] order
For instance you don't pass angles as [Z-Angle, X-Angle, Y-angle] to
glm_euler_zxy funciton, All RELATED functions accept angles same order
which is [X, Y, Z].
*/
/*
Types:
enum glm_euler_sq
Functions:
CGLM_INLINE vec3s glms_euler_angles(mat4s m)
CGLM_INLINE mat4s glms_euler_xyz(vec3s angles)
CGLM_INLINE mat4s glms_euler_xzy(vec3s angles)
CGLM_INLINE mat4s glms_euler_yxz(vec3s angles)
CGLM_INLINE mat4s glms_euler_yzx(vec3s angles)
CGLM_INLINE mat4s glms_euler_zxy(vec3s angles)
CGLM_INLINE mat4s glms_euler_zyx(vec3s angles)
CGLM_INLINE mat4s glms_euler_by_order(vec3s angles, glm_euler_sq ord)
*/
#ifndef cglms_euler_h
#define cglms_euler_h
#include "../common.h"
#include "../types-struct.h"
#include "../euler.h"
/*!
* @brief extract euler angles (in radians) using xyz order
*
* @param[in] m affine transform
* @returns angles vector [x, y, z]
*/
CGLM_INLINE
vec3s
glms_euler_angles(mat4s m) {
vec3s dest;
glm_euler_angles(m.raw, dest.raw);
return dest;
}
/*!
* @brief build rotation matrix from euler angles
*
* @param[in] angles angles as vector [Xangle, Yangle, Zangle]
* @returns rotation matrix
*/
CGLM_INLINE
mat4s
glms_euler_xyz(vec3s angles) {
mat4s dest;
glm_euler_xyz(angles.raw, dest.raw);
return dest;
}
/*!
* @brief build rotation matrix from euler angles
*
* @param[in] angles angles as vector [Xangle, Yangle, Zangle]
* @returns rotation matrix
*/
CGLM_INLINE
mat4s
glms_euler_xzy(vec3s angles) {
mat4s dest;
glm_euler_xzy(angles.raw, dest.raw);
return dest;
}
/*!
* @brief build rotation matrix from euler angles
*
* @param[in] angles angles as vector [Xangle, Yangle, Zangle]
* @returns rotation matrix
*/
CGLM_INLINE
mat4s
glms_euler_yxz(vec3s angles) {
mat4s dest;
glm_euler_yxz(angles.raw, dest.raw);
return dest;
}
/*!
* @brief build rotation matrix from euler angles
*
* @param[in] angles angles as vector [Xangle, Yangle, Zangle]
* @returns rotation matrix
*/
CGLM_INLINE
mat4s
glms_euler_yzx(vec3s angles) {
mat4s dest;
glm_euler_yzx(angles.raw, dest.raw);
return dest;
}
/*!
* @brief build rotation matrix from euler angles
*
* @param[in] angles angles as vector [Xangle, Yangle, Zangle]
* @returns rotation matrix
*/
CGLM_INLINE
mat4s
glms_euler_zxy(vec3s angles) {
mat4s dest;
glm_euler_zxy(angles.raw, dest.raw);
return dest;
}
/*!
* @brief build rotation matrix from euler angles
*
* @param[in] angles angles as vector [Xangle, Yangle, Zangle]
* @returns rotation matrix
*/
CGLM_INLINE
mat4s
glms_euler_zyx(vec3s angles) {
mat4s dest;
glm_euler_zyx(angles.raw, dest.raw);
return dest;
}
/*!
* @brief build rotation matrix from euler angles
*
* @param[in] angles angles as vector [Xangle, Yangle, Zangle]
* @param[in] ord euler order
* @returns rotation matrix
*/
CGLM_INLINE
mat4s
glms_euler_by_order(vec3s angles, glm_euler_sq ord) {
mat4s dest;
glm_euler_by_order(angles.raw, ord, dest.raw);
return dest;
}
#endif /* cglms_euler_h */

View File

@@ -0,0 +1,155 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglms_frustums_h
#define cglms_frustums_h
#include "../common.h"
#include "../types-struct.h"
#include "../frustum.h"
#include "plane.h"
#include "vec3.h"
#include "vec4.h"
#include "mat4.h"
/* you can override clip space coords
but you have to provide all with same name
e.g.: define GLM_CSCOORD_LBN {0.0f, 0.0f, 1.0f, 1.0f} */
#ifndef GLM_CUSTOM_CLIPSPACE
/* near */
#define GLMS_CSCOORD_LBN {-1.0f, -1.0f, -1.0f, 1.0f}
#define GLMS_CSCOORD_LTN {-1.0f, 1.0f, -1.0f, 1.0f}
#define GLMS_CSCOORD_RTN { 1.0f, 1.0f, -1.0f, 1.0f}
#define GLMS_CSCOORD_RBN { 1.0f, -1.0f, -1.0f, 1.0f}
/* far */
#define GLMS_CSCOORD_LBF {-1.0f, -1.0f, 1.0f, 1.0f}
#define GLMS_CSCOORD_LTF {-1.0f, 1.0f, 1.0f, 1.0f}
#define GLMS_CSCOORD_RTF { 1.0f, 1.0f, 1.0f, 1.0f}
#define GLMS_CSCOORD_RBF { 1.0f, -1.0f, 1.0f, 1.0f}
#endif
/*!
* @brief extracts view frustum planes
*
* planes' space:
* 1- if m = proj: View Space
* 2- if m = viewProj: World Space
* 3- if m = MVP: Object Space
*
* You probably want to extract planes in world space so use viewProj as m
* Computing viewProj:
* glm_mat4_mul(proj, view, viewProj);
*
* Exracted planes order: [left, right, bottom, top, near, far]
*
* @param[in] m matrix (see brief)
* @param[out] dest extracted view frustum planes (see brief)
*/
CGLM_INLINE
void
glms_frustum_planes(mat4s m, vec4s dest[6]) {
vec4 rawDest[6];
glm_frustum_planes(m.raw, rawDest);
glms_vec4_pack(dest, rawDest, 6);
}
/*!
* @brief extracts view frustum corners using clip-space coordinates
*
* corners' space:
* 1- if m = invViewProj: World Space
* 2- if m = invMVP: Object Space
*
* You probably want to extract corners in world space so use invViewProj
* Computing invViewProj:
* glm_mat4_mul(proj, view, viewProj);
* ...
* glm_mat4_inv(viewProj, invViewProj);
*
* if you have a near coord at i index, you can get it's far coord by i + 4
*
* Find center coordinates:
* for (j = 0; j < 4; j++) {
* glm_vec3_center(corners[i], corners[i + 4], centerCorners[i]);
* }
*
* @param[in] invMat matrix (see brief)
* @param[out] dest exracted view frustum corners (see brief)
*/
CGLM_INLINE
void
glms_frustum_corners(mat4s invMat, vec4s dest[8]) {
vec4 rawDest[8];
glm_frustum_corners(invMat.raw, rawDest);
glms_vec4_pack(dest, rawDest, 8);
}
/*!
* @brief finds center of view frustum
*
* @param[in] corners view frustum corners
* @returns view frustum center
*/
CGLM_INLINE
vec4s
glms_frustum_center(vec4s corners[8]) {
vec4 rawCorners[8];
vec4s r;
glms_vec4_unpack(rawCorners, corners, 8);
glm_frustum_center(rawCorners, r.raw);
return r;
}
/*!
* @brief finds bounding box of frustum relative to given matrix e.g. view mat
*
* @param[in] corners view frustum corners
* @param[in] m matrix to convert existing conners
* @param[out] box bounding box as array [min, max]
*/
CGLM_INLINE
void
glms_frustum_box(vec4s corners[8], mat4s m, vec3s box[2]) {
vec4 rawCorners[8];
vec3 rawBox[2];
glms_vec4_unpack(rawCorners, corners, 8);
glm_frustum_box(rawCorners, m.raw, rawBox);
glms_vec3_pack(box, rawBox, 2);
}
/*!
* @brief finds planes corners which is between near and far planes (parallel)
*
* this will be helpful if you want to split a frustum e.g. CSM/PSSM. This will
* find planes' corners but you will need to one more plane.
* Actually you have it, it is near, far or created previously with this func ;)
*
* @param[in] corners view frustum corners
* @param[in] splitDist split distance
* @param[in] farDist far distance (zFar)
* @param[out] planeCorners plane corners [LB, LT, RT, RB]
*/
CGLM_INLINE
void
glms_frustum_corners_at(vec4s corners[8],
float splitDist,
float farDist,
vec4s planeCorners[4]) {
vec4 rawCorners[8];
vec4 rawPlaneCorners[4];
glms_vec4_unpack(rawCorners, corners, 8);
glm_frustum_corners_at(rawCorners, splitDist, farDist, rawPlaneCorners);
glms_vec4_pack(planeCorners, rawPlaneCorners, 8);
}
#endif /* cglms_frustums_h */

82
include/cglm/struct/io.h Normal file
View File

@@ -0,0 +1,82 @@
/*
* 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_mat4_print(mat4 matrix, FILE *ostream);
CGLM_INLINE void glm_mat3_print(mat3 matrix, FILE *ostream);
CGLM_INLINE void glm_vec4_print(vec4 vec, FILE *ostream);
CGLM_INLINE void glm_vec3_print(vec3 vec, FILE *ostream);
CGLM_INLINE void glm_ivec3_print(ivec3 vec, FILE *ostream);
CGLM_INLINE void glm_versor_print(versor vec, FILE *ostream);
*/
#ifndef cglms_ios_h
#define cglms_ios_h
#include "../common.h"
#include "../io.h"
#include "mat4.h"
#include <stdio.h>
#include <stdlib.h>
CGLM_INLINE
void
glms_mat4_print(mat4s matrix,
FILE * __restrict ostream) {
glm_mat4_print(matrix.raw, ostream);
}
CGLM_INLINE
void
glms_mat3_print(mat3s matrix,
FILE * __restrict ostream) {
glm_mat3_print(matrix.raw, ostream);
}
CGLM_INLINE
void
glms_vec4_print(vec4s vec,
FILE * __restrict ostream) {
glm_vec4_print(vec.raw, ostream);
}
CGLM_INLINE
void
glms_vec3_print(vec3s vec,
FILE * __restrict ostream) {
glm_vec3_print(vec.raw, ostream);
}
CGLM_INLINE
void
glms_ivec3_print(ivec3s vec,
FILE * __restrict ostream) {
glm_ivec3_print(vec.raw, ostream);
}
CGLM_INLINE
void
glms_versor_print(versors vec,
FILE * __restrict ostream) {
glm_versor_print(vec.raw, ostream);
}
CGLM_INLINE
void
glms_aabb_print(vec3s bbox[2],
const char * __restrict tag,
FILE * __restrict ostream) {
vec3 rawBbox[2];
glms_vec3_unpack(rawBbox, bbox, 2);
glm_aabb_print(rawBbox, tag, ostream);
}
#endif /* cglms_ios_h */

289
include/cglm/struct/mat3.h Normal file
View File

@@ -0,0 +1,289 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
/*
Macros:
GLMS_MAT3_IDENTITY_INIT
GLMS_MAT3_ZERO_INIT
GLMS_MAT3_IDENTITY
GLMS_MAT3_ZERO
Functions:
CGLM_INLINE mat3s glms_mat3_copy(mat3s mat);
CGLM_INLINE mat3s glms_mat3_identity();
CGLM_INLINE void glms_mat3_identity_array(mat3s * __restrict mat, size_t count);
CGLM_INLINE mat3s glms_mat3_zero();
CGLM_INLINE mat3s glms_mat3_mul(mat3s m1, mat3s m2);
CGLM_INLINE ma3s glms_mat3_transpose(mat3s m);
CGLM_INLINE vec3s glms_mat3_mulv(mat3s m, vec3s v);
CGLM_INLINE float glms_mat3_trace(mat3s m);
CGLM_INLINE versor glms_mat3_quat(mat3s m);
CGLM_INLINE mat3s glms_mat3_scale(mat3s m, float s);
CGLM_INLINE float glms_mat3_det(mat3s mat);
CGLM_INLINE mat3s glms_mat3_inv(mat3s mat);
CGLM_INLINE mat3s glms_mat3_swap_col(mat3s mat, int col1, int col2);
CGLM_INLINE mat3s glms_mat3_swap_row(mat3s mat, int row1, int row2);
CGLM_INLINE float glms_mat3_rmc(vec3s r, mat3s m, vec3s c);
*/
#ifndef cglms_mat3s_h
#define cglms_mat3s_h
#include "../common.h"
#include "../types-struct.h"
#include "../mat3.h"
#include "vec3.h"
#define GLMS_MAT3_IDENTITY_INIT {1.0f, 0.0f, 0.0f, \
0.0f, 1.0f, 0.0f, \
0.0f, 0.0f, 1.0f}
#define GLMS_MAT3_ZERO_INIT {0.0f, 0.0f, 0.0f, \
0.0f, 0.0f, 0.0f, \
0.0f, 0.0f, 0.0f}
/* for C only */
#define GLMS_MAT3_IDENTITY ((mat3s)GLMS_MAT3_IDENTITY_INIT)
#define GLMS_MAT3_ZERO ((mat3s)GLMS_MAT3_ZERO_INIT)
/*!
* @brief copy all members of [mat] to [dest]
*
* @param[in] mat source
* @returns destination
*/
CGLM_INLINE
mat3s
glms_mat3_copy(mat3s mat) {
mat3s r;
glm_mat3_copy(mat.raw, r.raw);
return r;
}
/*!
* @brief make given matrix identity. It is identical with below,
* but it is more easy to do that with this func especially for members
* e.g. glm_mat3_identity(aStruct->aMatrix);
*
* @code
* glm_mat3_copy(GLM_MAT3_IDENTITY, mat); // C only
*
* // or
* mat3 mat = GLM_MAT3_IDENTITY_INIT;
* @endcode
*
* @returns destination
*/
CGLM_INLINE
mat3s
glms_mat3_identity() {
mat3s r;
glm_mat3_identity(r.raw);
return r;
}
/*!
* @brief make given matrix array's each element identity matrix
*
* @param[in, out] mat matrix array (must be aligned (16/32)
* if alignment is not disabled)
*
* @param[in] count count of matrices
*/
CGLM_INLINE
void
glms_mat3_identity_array(mat3s * __restrict mat, size_t count) {
CGLM_ALIGN_MAT mat3s t = GLMS_MAT3_IDENTITY_INIT;
size_t i;
for (i = 0; i < count; i++) {
glm_mat3_copy(t.raw, mat[i].raw);
}
}
/*!
* @brief make given matrix zero.
*
* @returns matrix
*/
CGLM_INLINE
mat3s
glms_mat3_zero() {
mat3s r;
glm_mat3_zero(r.raw);
return r;
}
/*!
* @brief multiply m1 and m2 to dest
*
* m1, m2 and dest matrices can be same matrix, it is possible to write this:
*
* @code
* mat3 m = GLM_MAT3_IDENTITY_INIT;
* glm_mat3_mul(m, m, m);
* @endcode
*
* @param[in] m1 left matrix
* @param[in] m2 right matrix
* @returns destination matrix
*/
CGLM_INLINE
mat3s
glms_mat3_mul(mat3s m1, mat3s m2) {
mat3s r;
glm_mat3_mul(m1.raw, m2.raw, r.raw);
return r;
}
/*!
* @brief tranpose mat3 and store result in same matrix
*
* @param[in, out] m source and dest
*/
CGLM_INLINE
mat3s
glms_mat3_transpose(mat3s m) {
glm_mat3_transpose(m.raw);
return m;
}
/*!
* @brief multiply mat3 with vec3 (column vector) and store in dest vector
*
* @param[in] m mat3 (left)
* @param[in] v vec3 (right, column vector)
* @returns vec3 (result, column vector)
*/
CGLM_INLINE
vec3s
glms_mat3_mulv(mat3s m, vec3s v) {
vec3s r;
glm_mat3_mulv(m.raw, v.raw, r.raw);
return r;
}
/*!
* @brief trace of matrix
*
* sum of the elements on the main diagonal from upper left to the lower right
*
* @param[in] m matrix
*/
CGLM_INLINE
float
glms_mat3_trace(mat3s m) {
return glm_mat3_trace(m.raw);
}
/*!
* @brief convert mat3 to quaternion
*
* @param[in] m rotation matrix
* @returns destination quaternion
*/
CGLM_INLINE
versors
glms_mat3_quat(mat3s m) {
versors r;
glm_mat3_quat(m.raw, r.raw);
return r;
}
/*!
* @brief scale (multiply with scalar) matrix
*
* multiply matrix with scalar
*
* @param[in] m matrix
* @param[in] s scalar
* @returns scaled matrix
*/
CGLM_INLINE
mat3s
glms_mat3_scale(mat3s m, float s) {
glm_mat3_scale(m.raw, s);
return m;
}
/*!
* @brief mat3 determinant
*
* @param[in] mat matrix
*
* @return determinant
*/
CGLM_INLINE
float
glms_mat3_det(mat3s mat) {
return glm_mat3_det(mat.raw);
}
/*!
* @brief inverse mat3 and store in dest
*
* @param[in] mat matrix
* @returns inverse matrix
*/
CGLM_INLINE
mat3s
glms_mat3_inv(mat3s mat) {
mat3s r;
glm_mat3_inv(mat.raw, r.raw);
return r;
}
/*!
* @brief swap two matrix columns
*
* @param[in] mat matrix
* @param[in] col1 col1
* @param[in] col2 col2
* @returns matrix
*/
CGLM_INLINE
mat3s
glms_mat3_swap_col(mat3s mat, int col1, int col2) {
glm_mat3_swap_col(mat.raw, col1, col2);
return mat;
}
/*!
* @brief swap two matrix rows
*
* @param[in] mat matrix
* @param[in] row1 row1
* @param[in] row2 row2
* @returns matrix
*/
CGLM_INLINE
mat3s
glms_mat3_swap_row(mat3s mat, int row1, int row2) {
glm_mat3_swap_row(mat.raw, row1, row2);
return mat;
}
/*!
* @brief helper for R (row vector) * M (matrix) * C (column vector)
*
* rmc stands for Row * Matrix * Column
*
* the result is scalar because R * M = Matrix1x3 (row vector),
* then Matrix1x3 * Vec3 (column vector) = Matrix1x1 (Scalar)
*
* @param[in] r row vector or matrix1x3
* @param[in] m matrix3x3
* @param[in] c column vector or matrix3x1
*
* @return scalar value e.g. Matrix1x1
*/
CGLM_INLINE
float
glms_mat3_rmc(vec3s r, mat3s m, vec3s c) {
return glm_mat3_rmc(r.raw, m.raw, c.raw);
}
#endif /* cglms_mat3s_h */

466
include/cglm/struct/mat4.h Normal file
View File

@@ -0,0 +1,466 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
/*!
* Most of functions in this header are optimized manually with SIMD
* if available. You dont need to call/incude SIMD headers manually
*/
/*
Macros:
GLMS_MAT4_IDENTITY_INIT
GLMS_MAT4_ZERO_INIT
GLMS_MAT4_IDENTITY
GLMS_MAT4_ZERO
Functions:
CGLM_INLINE mat4s glms_mat4_ucopy(mat4s mat);
CGLM_INLINE mat4s glms_mat4_copy(mat4s mat);
CGLM_INLINE mat4s glms_mat4_identity();
CGLM_INLINE void glms_mat4_identity_array(mat4s * __restrict mat, size_t count);
CGLM_INLINE mat4s glms_mat4_zero();
CGLM_INLINE mat3s glms_mat4_pick3(mat4s mat);
CGLM_INLINE mat3s glms_mat4_pick3t(mat4s mat);
CGLM_INLINE mat4s glms_mat4_ins3(mat3s mat);
CGLM_INLINE mat4s glms_mat4_mul(mat4s m1, mat4s m2);
CGLM_INLINE mat4s glms_mat4_mulN(mat4s * __restrict matrices[], uint32_t len);
CGLM_INLINE vec4s glms_mat4_mulv(mat4s m, vec4s v);
CGLM_INLINE float glms_mat4_trace(mat4s m);
CGLM_INLINE float glms_mat4_trace3(mat4s m);
CGLM_INLINE versors glms_mat4_quat(mat4s m);
CGLM_INLINE vec3s glms_mat4_mulv3(mat4s m, vec3s v, float last);
CGLM_INLINE mat4s glms_mat4_transpose(mat4s m);
CGLM_INLINE mat4s glms_mat4_scale_p(mat4s m, float s);
CGLM_INLINE mat4s glms_mat4_scale(mat4s m, float s);
CGLM_INLINE float glms_mat4_det(mat4s mat);
CGLM_INLINE mat4s glms_mat4_inv(mat4s mat);
CGLM_INLINE mat4s glms_mat4_inv_fast(mat4s mat);
CGLM_INLINE mat4s glms_mat4_swap_col(mat4s mat, int col1, int col2);
CGLM_INLINE mat4s glms_mat4_swap_row(mat4s mat, int row1, int row2);
CGLM_INLINE float glms_mat4_rmc(vec4s r, mat4s m, vec4s c);
*/
#ifndef cglms_mat4s_h
#define cglms_mat4s_h
#include "../common.h"
#include "../types-struct.h"
#include "../mat4.h"
#include "vec4.h"
#include "vec3.h"
#define GLMS_MAT4_IDENTITY_INIT {1.0f, 0.0f, 0.0f, 0.0f, \
0.0f, 1.0f, 0.0f, 0.0f, \
0.0f, 0.0f, 1.0f, 0.0f, \
0.0f, 0.0f, 0.0f, 1.0f}
#define GLMS_MAT4_ZERO_INIT {0.0f, 0.0f, 0.0f, 0.0f, \
0.0f, 0.0f, 0.0f, 0.0f, \
0.0f, 0.0f, 0.0f, 0.0f, \
0.0f, 0.0f, 0.0f, 0.0f}
/* for C only */
#define GLMS_MAT4_IDENTITY ((mat4s)GLMS_MAT4_IDENTITY_INIT)
#define GLMS_MAT4_ZERO ((mat4s)GLMS_MAT4_ZERO_INIT)
/*!
* @brief copy all members of [mat] to [dest]
*
* matrix may not be aligned, u stands for unaligned, this may be useful when
* copying a matrix from external source e.g. asset importer...
*
* @param[in] mat source
* @returns destination
*/
CGLM_INLINE
mat4s
glms_mat4_ucopy(mat4s mat) {
mat4s r;
glm_mat4_ucopy(mat.raw, r.raw);
return r;
}
/*!
* @brief copy all members of [mat] to [dest]
*
* @param[in] mat source
* @returns destination
*/
CGLM_INLINE
mat4s
glms_mat4_copy(mat4s mat) {
mat4s r;
glm_mat4_copy(mat.raw, r.raw);
return r;
}
/*!
* @brief make given matrix identity. It is identical with below,
* but it is more easy to do that with this func especially for members
* e.g. glm_mat4_identity(aStruct->aMatrix);
*
* @code
* glm_mat4_copy(GLM_MAT4_IDENTITY, mat); // C only
*
* // or
* mat4 mat = GLM_MAT4_IDENTITY_INIT;
* @endcode
*
* @retuns destination
*/
CGLM_INLINE
mat4s
glms_mat4_identity() {
mat4s r;
glm_mat4_identity(r.raw);
return r;
}
/*!
* @brief make given matrix array's each element identity matrix
*
* @param[in, out] mat matrix array (must be aligned (16/32)
* if alignment is not disabled)
*
* @param[in] count count of matrices
*/
CGLM_INLINE
void
glms_mat4_identity_array(mat4s * __restrict mat, size_t count) {
CGLM_ALIGN_MAT mat4s t = GLMS_MAT4_IDENTITY_INIT;
size_t i;
for (i = 0; i < count; i++) {
glm_mat4_copy(t.raw, mat[i].raw);
}
}
/*!
* @brief make given matrix zero.
*
* @returns matrix
*/
CGLM_INLINE
mat4s
glms_mat4_zero() {
mat4s r;
glm_mat4_zero(r.raw);
return r;
}
/*!
* @brief copy upper-left of mat4 to mat3
*
* @param[in] mat source
* @returns destination
*/
CGLM_INLINE
mat3s
glms_mat4_pick3(mat4s mat) {
mat3s r;
glm_mat4_pick3(mat.raw, r.raw);
return r;
}
/*!
* @brief copy upper-left of mat4 to mat3 (transposed)
*
* the postfix t stands for transpose
*
* @param[in] mat source
* @returns destination
*/
CGLM_INLINE
mat3s
glms_mat4_pick3t(mat4s mat) {
mat3s r;
glm_mat4_pick3t(mat.raw, r.raw);
return r;
}
/*!
* @brief copy mat3 to mat4's upper-left
*
* @param[in] mat source
* @returns destination
*/
CGLM_INLINE
mat4s
glms_mat4_ins3(mat3s mat) {
mat4s r;
glm_mat4_ins3(mat.raw, r.raw);
return r;
}
/*!
* @brief multiply m1 and m2 to dest
*
* m1, m2 and dest matrices can be same matrix, it is possible to write this:
*
* @code
* mat4 m = GLM_MAT4_IDENTITY_INIT;
* glm_mat4_mul(m, m, m);
* @endcode
*
* @param[in] m1 left matrix
* @param[in] m2 right matrix
* @returns destination matrix
*/
CGLM_INLINE
mat4s
glms_mat4_mul(mat4s m1, mat4s m2) {
mat4s r;
glm_mat4_mul(m1.raw, m2.raw, r.raw);
return r;
}
/*!
* @brief mupliply N mat4 matrices and store result in dest
*
* this function lets you multiply multiple (more than two or more...) matrices
* <br><br>multiplication will be done in loop, this may reduce instructions
* size but if <b>len</b> is too small then compiler may unroll whole loop,
* usage:
* @code
* mat m1, m2, m3, m4, res;
*
* res = glm_mat4_mulN((mat4 *[]){&m1, &m2, &m3, &m4}, 4);
* @endcode
*
* @warning matrices parameter is pointer array not mat4 array!
*
* @param[in] matrices mat4 * array
* @param[in] len matrices count
* @returns result matrix
*/
CGLM_INLINE
mat4s
glms_mat4_mulN(mat4s * __restrict matrices[], uint32_t len) {
CGLM_ALIGN_MAT mat4s r = GLMS_MAT4_IDENTITY_INIT;
size_t i;
for (i = 0; i < len; i++) {
r = glms_mat4_mul(r, *matrices[i]);
}
return r;
}
/*!
* @brief multiply mat4 with vec4 (column vector) and store in dest vector
*
* @param[in] m mat4 (left)
* @param[in] v vec4 (right, column vector)
* @returns vec4 (result, column vector)
*/
CGLM_INLINE
vec4s
glms_mat4_mulv(mat4s m, vec4s v) {
vec4s r;
glm_mat4_mulv(m.raw, v.raw, r.raw);
return r;
}
/*!
* @brief trace of matrix
*
* sum of the elements on the main diagonal from upper left to the lower right
*
* @param[in] m matrix
*/
CGLM_INLINE
float
glms_mat4_trace(mat4s m) {
return glm_mat4_trace(m.raw);
}
/*!
* @brief trace of matrix (rotation part)
*
* sum of the elements on the main diagonal from upper left to the lower right
*
* @param[in] m matrix
*/
CGLM_INLINE
float
glms_mat4_trace3(mat4s m) {
return glm_mat4_trace3(m.raw);
}
/*!
* @brief convert mat4's rotation part to quaternion
*
* @param[in] m affine matrix
* @returns destination quaternion
*/
CGLM_INLINE
versors
glms_mat4_quat(mat4s m) {
versors r;
glm_mat4_quat(m.raw, r.raw);
return r;
}
/*!
* @brief multiply vector with mat4
*
* @param[in] m mat4(affine transform)
* @param[in] v vec3
* @param[in] last 4th item to make it vec4
* @returns result vector (vec3)
*/
CGLM_INLINE
vec3s
glms_mat4_mulv3(mat4s m, vec3s v, float last) {
vec3s r;
glm_mat4_mulv3(m.raw, v.raw, last, r.raw);
return r;
}
/*!
* @brief tranpose mat4 and store result in same matrix
*
* @param[in] m source
* @returns result
*/
CGLM_INLINE
mat4s
glms_mat4_transpose(mat4s m) {
glm_mat4_transpose(m.raw);
return m;
}
/*!
* @brief scale (multiply with scalar) matrix without simd optimization
*
* multiply matrix with scalar
*
* @param[in] m matrix
* @param[in] s scalar
* @returns matrix
*/
CGLM_INLINE
mat4s
glms_mat4_scale_p(mat4s m, float s) {
glm_mat4_scale_p(m.raw, s);
return m;
}
/*!
* @brief scale (multiply with scalar) matrix
*
* multiply matrix with scalar
*
* @param[in] m matrix
* @param[in] s scalar
* @returns matrix
*/
CGLM_INLINE
mat4s
glms_mat4_scale(mat4s m, float s) {
glm_mat4_scale(m.raw, s);
return m;
}
/*!
* @brief mat4 determinant
*
* @param[in] mat matrix
*
* @return determinant
*/
CGLM_INLINE
float
glms_mat4_det(mat4s mat) {
return glm_mat4_det(mat.raw);
}
/*!
* @brief inverse mat4 and store in dest
*
* @param[in] mat matrix
* @returns inverse matrix
*/
CGLM_INLINE
mat4s
glms_mat4_inv(mat4s mat) {
mat4s r;
glm_mat4_inv(mat.raw, r.raw);
return r;
}
/*!
* @brief inverse mat4 and store in dest
*
* this func uses reciprocal approximation without extra corrections
* e.g Newton-Raphson. this should work faster than normal,
* to get more precise use glm_mat4_inv version.
*
* NOTE: You will lose precision, glm_mat4_inv is more accurate
*
* @param[in] mat matrix
* @returns inverse matrix
*/
CGLM_INLINE
mat4s
glms_mat4_inv_fast(mat4s mat) {
mat4s r;
glm_mat4_inv_fast(mat.raw, r.raw);
return r;
}
/*!
* @brief swap two matrix columns
*
* @param[in] mat matrix
* @param[in] col1 col1
* @param[in] col2 col2
* @returns matrix
*/
CGLM_INLINE
mat4s
glms_mat4_swap_col(mat4s mat, int col1, int col2) {
glm_mat4_swap_col(mat.raw, col1, col2);
return mat;
}
/*!
* @brief swap two matrix rows
*
* @param[in] mat matrix
* @param[in] row1 row1
* @param[in] row2 row2
* @returns matrix
*/
CGLM_INLINE
mat4s
glms_mat4_swap_row(mat4s mat, int row1, int row2) {
glm_mat4_swap_row(mat.raw, row1, row2);
return mat;
}
/*!
* @brief helper for R (row vector) * M (matrix) * C (column vector)
*
* rmc stands for Row * Matrix * Column
*
* the result is scalar because R * M = Matrix1x4 (row vector),
* then Matrix1x4 * Vec4 (column vector) = Matrix1x1 (Scalar)
*
* @param[in] r row vector or matrix1x4
* @param[in] m matrix4x4
* @param[in] c column vector or matrix4x1
*
* @return scalar value e.g. B(s)
*/
CGLM_INLINE
float
glms_mat4_rmc(vec4s r, mat4s m, vec4s c) {
return glm_mat4_rmc(r.raw, m.raw, c.raw);
}
#endif /* cglms_mat4s_h */

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglms_planes_h
#define cglms_planes_h
#include "../common.h"
#include "../types-struct.h"
#include "../plane.h"
#include "vec4.h"
/*
Plane equation: Ax + By + Cz + D = 0;
It stored in vec4 as [A, B, C, D]. (A, B, C) is normal and D is distance
*/
/*
Functions:
CGLM_INLINE vec4s glms_plane_normalize(vec4s plane);
*/
/*!
* @brief normalizes a plane
*
* @param[in] plane plane to normalize
* @returns normalized plane
*/
CGLM_INLINE
vec4s
glms_plane_normalize(vec4s plane) {
glm_plane_normalize(plane.raw);
return plane;
}
#endif /* cglms_planes_h */

View File

@@ -0,0 +1,104 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglms_projects_h
#define cglms_projects_h
#include "../common.h"
#include "../types-struct.h"
#include "../project.h"
#include "vec3.h"
#include "vec4.h"
#include "mat4.h"
/*!
* @brief 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
*
* [1] space:
* 1- if m = invProj: View Space
* 2- if m = invViewProj: World Space
* 3- if m = invMVP: Object Space
*
* You probably want to map the coordinates into object space
* so use invMVP as m
*
* Computing viewProj:
* glm_mat4_mul(proj, view, viewProj);
* glm_mat4_mul(viewProj, model, MVP);
* glm_mat4_inv(viewProj, invMVP);
*
* @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
vec3s
glms_unprojecti(vec3s pos, mat4s invMat, vec4s vp) {
vec3s r;
glm_unprojecti(pos.raw, invMat.raw, vp.raw, r.raw);
return r;
}
/*!
* @brief 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
* you.
*
* [1] space:
* 1- if m = proj: View Space
* 2- if m = viewProj: World Space
* 3- if m = MVP: Object Space
*
* You probably want to map the coordinates into object space
* so use MVP as m
*
* Computing viewProj and MVP:
* glm_mat4_mul(proj, view, viewProj);
* glm_mat4_mul(viewProj, model, MVP);
*
* @param[in] pos point/position in viewport coordinates
* @param[in] m matrix (see brief)
* @param[in] vp viewport as [x, y, width, height]
* @returns unprojected coordinates
*/
CGLM_INLINE
vec3s
glms_unproject(vec3s pos, mat4s m, vec4s vp) {
vec3s r;
glm_unproject(pos.raw, m.raw, vp.raw, r.raw);
return r;
}
/*!
* @brief map object coordinates to window coordinates
*
* Computing MVP:
* glm_mat4_mul(proj, view, viewProj);
* glm_mat4_mul(viewProj, model, MVP);
*
* @param[in] pos object coordinates
* @param[in] m MVP matrix
* @param[in] vp viewport as [x, y, width, height]
* @returns projected coordinates
*/
CGLM_INLINE
vec3s
glms_project(vec3s pos, mat4s m, vec4s vp) {
vec3s r;
glm_project(pos.raw, m.raw, vp.raw, r.raw);
return r;
}
#endif /* cglms_projects_h */

514
include/cglm/struct/quat.h Normal file
View File

@@ -0,0 +1,514 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
/*
Macros:
GLMS_QUAT_IDENTITY_INIT
GLMS_QUAT_IDENTITY
Functions:
CGLM_INLINE versors glms_quat_identity()
CGLM_INLINE void glms_quat_identity_array(versor *q, size_t count)
CGLM_INLINE versors glms_quat_init(float x, float y, float z, float w)
CGLM_INLINE versors glms_quatv(float angle, vec3s axis)
CGLM_INLINE versors glms_quat(float angle, float x, float y, float z)
CGLM_INLINE float glms_quat_norm(versors q)
CGLM_INLINE versors glms_quat_normalize(versors q)
CGLM_INLINE float glms_quat_dot(versors p, versors q)
CGLM_INLINE versors glms_quat_conjugate(versors q)
CGLM_INLINE versors glms_quat_inv(versors q)
CGLM_INLINE versors glms_quat_add(versors p, versors q)
CGLM_INLINE versors glms_quat_sub(versors p, versors q)
CGLM_INLINE vec3s glms_quat_imagn(versors q)
CGLM_INLINE float glms_quat_imaglen(versors q)
CGLM_INLINE float glms_quat_angle(versors q)
CGLM_INLINE vec3s glms_quat_axis(versors q)
CGLM_INLINE versors glms_quat_mul(versors p, versors q)
CGLM_INLINE mat4s glms_quat_mat4(versors q)
CGLM_INLINE mat4s glms_quat_mat4t(versors q)
CGLM_INLINE mat3s glms_quat_mat3(versors q)
CGLM_INLINE mat3s glms_quat_mat3t(versors q)
CGLM_INLINE versors glms_quat_lerp(versors from, versors to, float t)
CGLM_INLINE versors glms_quat_slerp(versors from, versors to, float t)
CGLM_INLINE mat4s. glms_quat_look(vec3s eye, versors ori)
CGLM_INLINE versors glms_quat_for(vec3s dir, vec3s fwd, vec3s up)
CGLM_INLINE versors glms_quat_forp(vec3s from, vec3s to, vec3s fwd, vec3s up)
CGLM_INLINE vec3s glms_quat_rotatev(versors q, vec3s v)
CGLM_INLINE mat4s glms_quat_rotate(mat4s m, versors q)
CGLM_INLINE mat4s glms_quat_rotate_at(mat4s m, versors q, vec3s pivot)
CGLM_INLINE mat4s glms_quat_rotate_atm(versors q, vec3s pivot)
*/
#ifndef cglms_quat_h
#define cglms_quat_h
#include "../common.h"
#include "../types-struct.h"
#include "../plane.h"
#include "../quat.h"
/*
* IMPORTANT:
* ----------------------------------------------------------------------------
* cglm stores quat as [x, y, z, w] since v0.3.6
*
* it was [w, x, y, z] before v0.3.6 it has been changed to [x, y, z, w]
* with v0.3.6 version.
* ----------------------------------------------------------------------------
*/
#define GLMS_QUAT_IDENTITY_INIT GLM_QUAT_IDENTITY_INIT
#define GLMS_QUAT_IDENTITY ((versors)GLMS_QUAT_IDENTITY_INIT)
/*!
* @brief makes given quat to identity
*
* @returns identity quaternion
*/
CGLM_INLINE
versors
glms_quat_identity() {
versors dest;
glm_quat_identity(dest.raw);
return dest;
}
/*!
* @brief make given quaternion array's each element identity quaternion
*
* @param[in, out] q quat array (must be aligned (16)
* if alignment is not disabled)
*
* @param[in] count count of quaternions
*/
CGLM_INLINE
void
glms_quat_identity_array(versors * __restrict q, size_t count) {
CGLM_ALIGN(16) versor v = GLM_QUAT_IDENTITY_INIT;
size_t i;
for (i = 0; i < count; i++) {
glm_vec4_copy(v, q[i].raw);
}
}
/*!
* @brief inits quaterion with raw values
*
* @param[in] x x
* @param[in] y y
* @param[in] z z
* @param[in] w w (real part)
* @returns quaternion
*/
CGLM_INLINE
versors
glms_quat_init(float x, float y, float z, float w) {
versors dest;
glm_quat_init(dest.raw, x, y, z, w);
return dest;
}
/*!
* @brief creates NEW quaternion with axis vector
*
* @param[in] angle angle (radians)
* @param[in] axis axis
* @returns quaternion
*/
CGLM_INLINE
versors
glms_quatv(float angle, vec3s axis) {
versors dest;
glm_quatv(dest.raw, angle, axis.raw);
return dest;
}
/*!
* @brief creates NEW quaternion with individual axis components
*
* @param[in] angle angle (radians)
* @param[in] x axis.x
* @param[in] y axis.y
* @param[in] z axis.z
* @returns quaternion
*/
CGLM_INLINE
versors
glms_quat(float angle, float x, float y, float z) {
versors dest;
glm_quat(dest.raw, angle, x, y, z);
return dest;
}
/*!
* @brief returns norm (magnitude) of quaternion
*
* @param[out] q quaternion
*/
CGLM_INLINE
float
glms_quat_norm(versors q) {
return glm_quat_norm(q.raw);
}
/*!
* @brief normalize quaternion
*
* @param[in] q quaternion
* @returns quaternion
*/
CGLM_INLINE
versors
glms_quat_normalize(versors q) {
versors dest;
glm_quat_normalize_to(q.raw, dest.raw);
return dest;
}
/*!
* @brief dot product of two quaternion
*
* @param[in] p quaternion 1
* @param[in] q quaternion 2
* @returns dot product
*/
CGLM_INLINE
float
glms_quat_dot(versors p, versors q) {
return glm_quat_dot(p.raw, q.raw);
}
/*!
* @brief conjugate of quaternion
*
* @param[in] q quaternion
* @returns conjugate
*/
CGLM_INLINE
versors
glms_quat_conjugate(versors q) {
versors dest;
glm_quat_conjugate(q.raw, dest.raw);
return dest;
}
/*!
* @brief inverse of non-zero quaternion
*
* @param[in] q quaternion
* @returns inverse quaternion
*/
CGLM_INLINE
versors
glms_quat_inv(versors q) {
versors dest;
glm_quat_inv(q.raw, dest.raw);
return dest;
}
/*!
* @brief add (componentwise) two quaternions and store result in dest
*
* @param[in] p quaternion 1
* @param[in] q quaternion 2
* @returns result quaternion
*/
CGLM_INLINE
versors
glms_quat_add(versors p, versors q) {
versors dest;
glm_quat_add(p.raw, q.raw, dest.raw);
return dest;
}
/*!
* @brief subtract (componentwise) two quaternions and store result in dest
*
* @param[in] p quaternion 1
* @param[in] q quaternion 2
* @returns result quaternion
*/
CGLM_INLINE
versors
glms_quat_sub(versors p, versors q) {
versors dest;
glm_quat_sub(p.raw, q.raw, dest.raw);
return dest;
}
/*!
* @brief returns normalized imaginary part of quaternion
*
* @param[in] q quaternion
*/
CGLM_INLINE
vec3s
glms_quat_imagn(versors q) {
vec3s dest;
glm_normalize_to(q.imag.raw, dest.raw);
return dest;
}
/*!
* @brief returns length of imaginary part of quaternion
*
* @param[in] q quaternion
*/
CGLM_INLINE
float
glms_quat_imaglen(versors q) {
return glm_quat_imaglen(q.raw);
}
/*!
* @brief returns angle of quaternion
*
* @param[in] q quaternion
*/
CGLM_INLINE
float
glms_quat_angle(versors q) {
return glm_quat_angle(q.raw);
}
/*!
* @brief axis of quaternion
*
* @param[in] q quaternion
* @returns axis of quaternion
*/
CGLM_INLINE
vec3s
glms_quat_axis(versors q) {
vec3s dest;
glm_quat_axis(q.raw, dest.raw);
return dest;
}
/*!
* @brief multiplies two quaternion and stores result in dest
* this is also called Hamilton Product
*
* According to WikiPedia:
* The product of two rotation quaternions [clarification needed] will be
* equivalent to the rotation q followed by the rotation p
*
* @param[in] p quaternion 1
* @param[in] q quaternion 2
* @returns result quaternion
*/
CGLM_INLINE
versors
glms_quat_mul(versors p, versors q) {
versors dest;
glm_quat_mul(p.raw, q.raw, dest.raw);
return dest;
}
/*!
* @brief convert quaternion to mat4
*
* @param[in] q quaternion
* @returns result matrix
*/
CGLM_INLINE
mat4s
glms_quat_mat4(versors q) {
mat4s dest;
glm_quat_mat4(q.raw, dest.raw);
return dest;
}
/*!
* @brief convert quaternion to mat4 (transposed)
*
* @param[in] q quaternion
* @returns result matrix as transposed
*/
CGLM_INLINE
mat4s
glms_quat_mat4t(versors q) {
mat4s dest;
glm_quat_mat4t(q.raw, dest.raw);
return dest;
}
/*!
* @brief convert quaternion to mat3
*
* @param[in] q quaternion
* @returns result matrix
*/
CGLM_INLINE
mat3s
glms_quat_mat3(versors q) {
mat3s dest;
glm_quat_mat3(q.raw, dest.raw);
return dest;
}
/*!
* @brief convert quaternion to mat3 (transposed)
*
* @param[in] q quaternion
* @returns result matrix
*/
CGLM_INLINE
mat3s
glms_quat_mat3t(versors q) {
mat3s dest;
glm_quat_mat3t(q.raw, dest.raw);
return dest;
}
/*!
* @brief interpolates between two quaternions
* using linear interpolation (LERP)
*
* @param[in] from from
* @param[in] to to
* @param[in] t interpolant (amount) clamped between 0 and 1
* @returns result quaternion
*/
CGLM_INLINE
versors
glms_quat_lerp(versors from, versors to, float t) {
versors dest;
glm_quat_lerp(from.raw, to.raw, t, dest.raw);
return dest;
}
/*!
* @brief interpolates between two quaternions
* using spherical linear interpolation (SLERP)
*
* @param[in] from from
* @param[in] to to
* @param[in] t amout
* @returns result quaternion
*/
CGLM_INLINE
versors
glms_quat_slerp(versors from, versors to, float t) {
versors dest;
glm_quat_slerp(from.raw, to.raw, t, dest.raw);
return dest;
}
/*!
* @brief creates view matrix using quaternion as camera orientation
*
* @param[in] eye eye
* @param[in] ori orientation in world space as quaternion
* @returns view matrix
*/
CGLM_INLINE
mat4s
glms_quat_look(vec3s eye, versors ori) {
mat4s dest;
glm_quat_look(eye.raw, ori.raw, dest.raw);
return dest;
}
/*!
* @brief creates look rotation quaternion
*
* @param[in] dir direction to look
* @param[in] fwd forward vector
* @param[in] up up vector
* @returns destination quaternion
*/
CGLM_INLINE
versors
glms_quat_for(vec3s dir, vec3s fwd, vec3s up) {
versors dest;
glm_quat_for(dir.raw, fwd.raw, up.raw, dest.raw);
return dest;
}
/*!
* @brief creates look rotation quaternion using source and
* destination positions p suffix stands for position
*
* @param[in] from source point
* @param[in] to destination point
* @param[in] fwd forward vector
* @param[in] up up vector
* @returns destination quaternion
*/
CGLM_INLINE
versors
glms_quat_forp(vec3s from, vec3s to, vec3s fwd, vec3s up) {
versors dest;
glm_quat_forp(from.raw, to.raw, fwd.raw, up.raw, dest.raw);
return dest;
}
/*!
* @brief rotate vector using using quaternion
*
* @param[in] q quaternion
* @param[in] v vector to rotate
* @returns rotated vector
*/
CGLM_INLINE
vec3s
glms_quat_rotatev(versors q, vec3s v) {
vec3s dest;
glm_quat_rotatev(q.raw, v.raw, dest.raw);
return dest;
}
/*!
* @brief rotate existing transform matrix using quaternion
*
* @param[in] m existing transform matrix
* @param[in] q quaternion
* @returns rotated matrix/transform
*/
CGLM_INLINE
mat4s
glms_quat_rotate(mat4s m, versors q) {
glm_quat_rotate(m.raw, q.raw, m.raw);
return m;
}
/*!
* @brief rotate existing transform matrix using quaternion at pivot point
*
* @param[in, out] m existing transform matrix
* @param[in] q quaternion
* @returns pivot
*/
CGLM_INLINE
mat4s
glms_quat_rotate_at(mat4s m, versors q, vec3s pivot) {
glm_quat_rotate_at(m.raw, q.raw, pivot.raw);
return m;
}
/*!
* @brief 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.
*
* @param[in] q quaternion
* @returns pivot
*/
CGLM_INLINE
mat4s
glms_quat_rotate_atm(versors q, vec3s pivot) {
mat4s dest;
glm_quat_rotate_atm(dest.raw, q.raw, pivot.raw);
return dest;
}
#endif /* cglms_quat_h */

View File

@@ -0,0 +1,93 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglms_spheres_h
#define cglms_spheres_h
#include "../common.h"
#include "../types-struct.h"
#include "../sphere.h"
#include "mat4.h"
/*
Sphere Representation in cglm: [center.x, center.y, center.z, radii]
You could use this representation or you can convert it to vec4 before call
any function
*/
/*!
* @brief helper for getting sphere radius
*
* @param[in] s sphere
*
* @return returns radii
*/
CGLM_INLINE
float
glms_sphere_radii(vec4s s) {
return glm_sphere_radii(s.raw);
}
/*!
* @brief apply transform to sphere, it is just wrapper for glm_mat4_mulv3
*
* @param[in] s sphere
* @param[in] m transform matrix
* @returns transformed sphere
*/
CGLM_INLINE
vec4s
glms_sphere_transform(vec4s s, mat4 m) {
vec4s r;
glm_sphere_transform(s.raw, m, r.raw);
return r;
}
/*!
* @brief merges two spheres and creates a new one
*
* two sphere must be in same space, for instance if one in world space then
* the other must be in world space too, not in local space.
*
* @param[in] s1 sphere 1
* @param[in] s2 sphere 2
* returns merged/extended sphere
*/
CGLM_INLINE
vec4s
glms_sphere_merge(vec4s s1, vec4s s2) {
vec4s r;
glm_sphere_merge(s1.raw, s2.raw, r.raw);
return r;
}
/*!
* @brief check if two sphere intersects
*
* @param[in] s1 sphere
* @param[in] s2 other sphere
*/
CGLM_INLINE
bool
glms_sphere_sphere(vec4s s1, vec4s s2) {
return glm_sphere_sphere(s1.raw, s2.raw);
}
/*!
* @brief check if sphere intersects with point
*
* @param[in] s sphere
* @param[in] point point
*/
CGLM_INLINE
bool
glms_sphere_point(vec4s s, vec3s point) {
return glm_sphere_point(s.raw, point.raw);
}
#endif /* cglms_spheres_h */

Some files were not shown because too many files have changed in this diff Show More