Compare commits

...

211 Commits

Author SHA1 Message Date
Recep Aslantas
6d6954b208 vec: minnadd and maxadd helpers 2018-11-29 10:50:24 +03:00
Recep Aslantas
4e08b7e335 vec: rename parameter names 2018-11-29 09:55:27 +03:00
Recep Aslantas
aee381d869 vec: deprecate glm_vec_inv and glm_vec4_inv
* because in the current implementation, `glm_vec3_negate` does same thing. It is duplicate.
2018-11-29 09:23:14 +03:00
Recep Aslantas
b4bf8f3537 vec: rename glm_vec_ to glm_vec3_ (continue)
* add missing functions to vec4
* update docs
2018-11-29 09:07:48 +03:00
Recep Aslantas
0b8c63a90e vec: rename glm_vec_ namespace to glm_vec3_ 2018-11-28 23:22:30 +03:00
Recep Aslantas
ef6134263e vec: improve angle between two vector
* because `acosf()` may return NaN if cosine/dot is out of range
2018-11-28 14:48:12 +03:00
Recep Aslantas
9af61d2101 vec: use _negate instead of _flipsign and _inv 2018-11-28 10:50:21 +03:00
Recep Aslantas
463099350a vec: use _negate instead of _flipsign and _inv
* negate is better and common name, flipsign is deprecated now.
2018-11-28 10:28:00 +03:00
Recep Aslantas
89f64f0794 Merge pull request #65 from sinisterchipmunk/fix-versor-alignment
fix versor alignment
2018-11-17 22:36:12 +03:00
Recep Aslantas
d794f17e51 Merge branch 'master' into fix-versor-alignment 2018-11-17 22:32:48 +03:00
Recep Aslantas
a7cdbcec2b now working on v0.5.0 2018-11-17 22:31:51 +03:00
Colin MacKenzie IV
20a2312351 fix versor alignment 2018-11-16 19:25:44 -05:00
Recep Aslantas
08479f38ce Merge pull request #63 from recp/avx
avx: replace binary constants (resolve https://github.com/recp/cglm/issues/62) with hex and fix glm_mul_avx
2018-10-19 09:52:32 +03:00
Recep Aslantas
dadae4b773 avx: fix glm_mul_avx
* use glm_mat4_mul_avx here. because it seems there is no big difference for now.
2018-10-19 09:40:40 +03:00
Recep Aslantas
20360f2296 avx: replace binary constants with hex 2018-10-12 09:05:42 +03:00
Recep Aslantas
aa2b0f2631 code style and minor optimization[s] 2018-09-22 00:10:50 +03:00
Recep Aslantas
280ac72fd8 Merge pull request #61 from hartenfels/master
Replace non-standard M_PI* constants
2018-09-21 23:39:10 +03:00
Recep Aslantas
7405d5e1d0 Update types.h 2018-09-21 23:33:42 +03:00
Carsten Hartenfels
eefafefbae Also add a load of other number constants
These are all missing from standard C, so we might as well define em.

See https://github.com/recp/cglm/pull/61#discussion_r219406859
2018-09-21 20:03:28 +02:00
Carsten Hartenfels
b9021978cb Replace the use of deprecated CGLM_PI* constants 2018-09-21 19:59:23 +02:00
Carsten Hartenfels
3fd12032e6 Clean up pi constants, deprecating the old names
GLM_PI* is now used for the double versions, GLM_PI*f for the float
versions. The CGLM_ prefixed versions are now deprecated, since that
prefix is kinda only used for constants.

See https://github.com/recp/cglm/pull/61#issuecomment-423069770
2018-09-21 07:29:54 +02:00
Carsten Hartenfels
59ee8c1fd2 Use even more precise definitions for pi constants
See https://github.com/recp/cglm/pull/61#issuecomment-422955122
2018-09-21 07:26:55 +02:00
Carsten Hartenfels
b00f2b9ccc Replace M_PI_4 in test_affine with CGLM_PI_4
As in the previous commit, because it's non-standard and depending on
your settings it can fail to compile because of it.
2018-09-19 20:46:37 +02:00
Carsten Hartenfels
d3c50147cb Replace non-standard M_PI* constants with literals
M_PI, M_PI_2 and M_PI_4 aren't part of the C standard. If you put your
gcc into strict standards mode, like `-std=c11`, you won't get these
constants and including cglm.h will fail.

This commit replaces those constants with their literal values. The cast
to a float remains, to keep exactly the same behavior as before.
2018-09-19 20:42:05 +02:00
Recep Aslantas
98da3daf82 identiy helper for arrays (matrix/quaternion)
this helpers makes all array elements identity
2018-09-12 12:44:11 +03:00
Recep Aslantas
2e1790ccf9 Merge pull request #59 from jonathanplatzer/avx
Fix alignment issue when using AVX
2018-07-19 11:38:55 +03:00
Jonathan Platzer
cc5f533fc9 Add macro for automatic alignment of matrices 2018-07-19 10:14:30 +02:00
Jonathan Platzer
2d63d7e0cd Fix alignment issue when using AVX 2018-07-18 12:03:38 +02:00
Recep Aslantas
3738499927 update doc for vec4_ucopy 2018-07-14 12:12:15 +03:00
Recep Aslantas
1d527dc2f0 unalignned version for vec4_copy 2018-07-14 12:03:42 +03:00
Recep Aslantas
43c4d05d4a new version for clamp: clamp to zero and one 2018-07-12 11:39:56 +03:00
Recep Aslantas
c5f5032fcc fix function params docs 2018-07-10 11:42:18 +03:00
Recep Aslantas
5d605ce372 avoid zero division for percent
* two value may be same, in this case now returns 1.
* to must be >= from and current <= to && current >= from
2018-07-10 10:54:31 +03:00
Recep Aslantas
c216c0cb7e add MIN and MAX macros
because we could use min/max for intergers too. it may not guarantee that MIN and MAX macros will always be defined by compiler
2018-06-26 15:27:53 +03:00
Recep Aslantas
eb8e0df6df update version 2018-06-21 10:54:53 +03:00
Recep Aslantas
1775bf7458 Merge pull request #57 from recp/anim
Animation Utils
2018-06-21 10:48:19 +03:00
Recep Aslantas
3adeac06f8 update build files 2018-06-21 10:07:51 +03:00
Recep Aslantas
669777eb37 additional utils 2018-06-18 17:55:25 +03:00
Recep Aslantas
02f6c67393 improve easing funcs 2018-06-15 08:55:59 +03:00
Recep Aslantas
564324f5d2 easing functions 2018-06-10 10:29:02 +03:00
Recep Aslantas
93e6c3c102 Merge pull request #56 from recp/sphere
aabb and sphere intersect functions
2018-06-09 18:43:54 +03:00
Recep Aslantas
857265b892 sphere point intersection 2018-06-09 18:21:29 +03:00
Recep Aslantas
fc14cedf89 update version 2018-06-09 18:10:54 +03:00
Recep Aslantas
7a80178357 improve quat_look 2018-06-09 18:10:44 +03:00
Recep Aslantas
720b617ee0 sphere and aabb 2018-05-30 23:42:22 +03:00
Recep Aslantas
3dc9070909 squared distance for vec3 2018-05-30 23:35:59 +03:00
Recep Aslantas
6b2b4b4f12 implement glm_aabb_sphere as GraphicsGems Solid Box - Solid Sphere test 2018-05-30 23:00:18 +03:00
Recep Aslantas
c8fc460ba1 add support for spheres 2018-05-29 23:29:09 +03:00
Recep Aslantas
5b3aabc103 aabb intersect functions
* AABB vs AABB
* AABB vs Point
* AABB vs Sphere
* AABB contains AABB
2018-05-29 23:19:39 +03:00
Recep Aslantas
af812e86eb add a note to clarify up vector restriction for glm_lookat and glm_look 2018-05-29 11:30:38 +03:00
Recep Aslantas
059bdfdd4b update docs 2018-05-27 11:54:05 +03:00
Recep Aslantas
ef0653640f update cocoapod version tag 2018-05-27 11:53:48 +03:00
Recep Aslantas
e5d61b3433 update mat4_mulv3 api to include translation 2018-05-27 11:46:27 +03:00
Recep Aslantas
73c073cf32 add missing call functions 2018-05-27 11:44:06 +03:00
Recep Aslantas
1362bef50f fix glm_translate_to 2018-05-23 23:13:41 +03:00
Recep Aslantas
7d783eeace align local variables on stack 2018-05-23 23:04:06 +03:00
Recep Aslantas
e12e79b1a5 improve scale_make 2018-05-23 22:11:44 +03:00
Recep Aslantas
6cd3d52dc5 improve translate_make 2018-05-23 22:08:12 +03:00
Recep Aslantas
fb2cac9816 aabb: center of AABB helper
* it is just wrapper of vec_center but it saves to access min and max values of AABB
2018-05-22 17:45:37 +03:00
Recep Aslantas
4e63325f55 aabb: add missing call versions 2018-05-22 17:44:36 +03:00
Recep Aslantas
96c3e604ff now working on v0.4.6 2018-05-22 17:43:46 +03:00
Recep Aslantas
077e304fc5 Merge pull request #42 from recp/optimizations
simd: optional shuffle configuration to save move instructions
2018-05-10 16:47:00 +03:00
Recep Aslantas
599524dacf docs: add new option to docs 2018-05-10 16:42:13 +03:00
Recep Aslantas
da5ad69863 simd: rename _mm_ extensions to glmm_ 2018-05-10 14:27:53 +03:00
Recep Aslantas
9fc2ead8ef Merge branch 'master' into optimizations 2018-05-10 13:59:10 +03:00
Recep Aslantas
48d33c16cb Merge pull request #53 from recp/simd
simd: Make alignment OPTIONAL
2018-05-10 13:57:31 +03:00
Recep Aslantas
464bd917d0 update readme 2018-05-10 12:21:33 +03:00
Recep Aslantas
c6d07bb6eb surround PI with parentheses + code style + update docs 2018-05-10 12:18:54 +03:00
Recep Aslantas
94b286f1f9 docs: add new alignment option to docs 2018-05-09 16:43:42 +03:00
Recep Aslantas
f774925e8a win, simd: make sure that CGLM_ALL_UNALIGNED is defined for older visual studios 2018-05-09 15:30:54 +03:00
Recep Aslantas
0e49e95161 win: update visual studio version for align requirement 2018-05-08 18:29:02 +03:00
Recep Aslantas
b277357800 update gitignore 2018-05-08 18:28:31 +03:00
Recep Aslantas
835cec2ccb drop alignment requirement if CGLM_ALL_UNALIGNED defined
* bring alignment back for visual studio 2017
2018-05-08 16:26:33 +03:00
Recep Aslantas
5dbbd0826d simd: replace glm_simd_ with glmm_
* now glmm_ is used as global simd namescape
2018-05-08 15:55:36 +03:00
Recep Aslantas
56f0bb0928 simd, avx: make alignment optional for load/store operations 2018-05-08 15:35:17 +03:00
Recep Aslantas
568001d26a simd, sse2: make alignment optional for store operations 2018-05-08 15:31:09 +03:00
Recep Aslantas
252bf925fc simd, sse2: make alignment optional for load operations 2018-05-08 15:25:23 +03:00
Recep Aslantas
0f339c5c03 fix header dependencies 2018-05-07 21:12:29 +03:00
Recep Aslantas
a9d56f2dae docs: fix typos 2018-05-04 00:50:56 +03:00
Recep Aslantas
dd60496ffc Merge pull request #49 from Yatima1460/master
replace _WIN32 with _MSC_VER
2018-04-30 19:08:59 +03:00
Federico Santamorena
7c0e9e99c6 _WIN32 to _MSC_VER 2018-04-30 17:17:06 +02:00
Federico Santamorena
064209c917 replaced _WIN32 with _MSC_VER 2018-04-30 17:13:16 +02:00
Recep Aslantas
94d6036c38 suppress warnings for Mingw 2018-04-30 11:09:42 +03:00
Recep Aslantas
6c01eff056 now working on v0.4.5 2018-04-30 10:59:40 +03:00
Recep Aslantas
ada69a7c43 fix cocoapods validation errors 2018-04-22 10:14:17 +03:00
Recep Aslantas
cef97fca3e add cocoapods spec 2018-04-22 01:03:17 +03:00
Recep Aslantas
498a33fac5 fix public header's includes 2018-04-21 22:36:25 +03:00
Recep Aslantas
3c7a729729 build: remove making symbolic link for libtoolize 2018-04-20 15:19:06 +03:00
Recep Aslantas
a6a37995e9 build: update automake sources 2018-04-18 23:02:15 +03:00
Recep Aslantas
6202179c23 update version 2018-04-18 22:30:20 +03:00
Recep Aslantas
22b699174c build: improve calling libtoolize 2018-04-18 21:47:53 +03:00
Recep Aslantas
016c0a71a6 Merge pull request #46 from recp/affine
affine transform update
2018-04-18 15:25:40 +03:00
Recep Aslantas
e28cf1d3f6 remove unused variable 2018-04-18 15:23:07 +03:00
Recep Aslantas
63966ee5c0 quat: use the new "glm_mul_rot" for quaternion
* this should be faster than mat4_mul
2018-04-18 15:16:24 +03:00
Recep Aslantas
a723ecdb7e add troubleshooting to docs 2018-04-18 15:11:06 +03:00
Recep Aslantas
065f93ab3c update docs, drop scale1 2018-04-18 14:30:44 +03:00
Recep Aslantas
4dbcd28fdb use mul_rot for rotations to make thrm faster 2018-04-18 14:12:56 +03:00
Recep Aslantas
be0e3fc9f2 new matrix multiplication helper for rotation matrices 2018-04-18 14:05:09 +03:00
Recep Aslantas
d648f5772d affine: drop rotate_ndc functions 2018-04-18 10:57:35 +03:00
Recep Aslantas
f163fcd043 simd: load vec3 helpers for sse/sse2 2018-04-18 00:00:47 +03:00
Recep Aslantas
27ab6a7dd0 update docs, add clarifications for affine transforms 2018-04-17 15:42:24 +03:00
Recep Aslantas
33e951fe2e implement rotate_at for quat and provide make version 2018-04-17 12:17:04 +03:00
Recep Aslantas
c63c6c90ac implement rotate_at 2018-04-17 11:12:18 +03:00
Recep Aslantas
a2792178db add missing call funcs for affine transforms 2018-04-17 11:07:57 +03:00
Recep Aslantas
cefd5fb53d test: add some tests for affine transforms 2018-04-17 10:33:52 +03:00
Recep Aslantas
821c79572f test: add some tests for mat3 2018-04-15 20:47:38 +03:00
Recep Aslantas
f0a27d0ce2 now working on v0.4.2 2018-04-15 20:46:46 +03:00
Recep Aslantas
007ae62e06 update docs version 2018-04-15 13:10:07 +03:00
Recep Aslantas
826ddf0f5b improve normalize vectors 2018-04-15 12:46:29 +03:00
Recep Aslantas
b09b5f260b vec: fix rotate vector using mat4 and mat3 rotation matrices 2018-04-15 12:44:50 +03:00
Recep Aslantas
59aacee968 optimize clamp for vec4 2018-04-14 12:49:37 +03:00
Recep Aslantas
429aff087f optimize min and max for vec4 2018-04-14 11:35:28 +03:00
Recep Aslantas
ca9f61dd74 Merge pull request #44 from recp/vector
new vector functions and optimizations
2018-04-14 09:19:51 +03:00
Recep Aslantas
d6395d4fb8 vec: optimize rotate vector using matrix
* add mat3 version
2018-04-13 22:33:32 +03:00
Recep Aslantas
7f7007574b vec: implement muladd's scalar version 2018-04-13 22:30:44 +03:00
Recep Aslantas
13345f06c1 fix vec4 scalar ops 2018-04-13 15:50:05 +03:00
Recep Aslantas
725fac75d0 now working on v0.4.1 2018-04-13 15:47:45 +03:00
Recep Aslantas
c05f58a169 vec: add addadd, subadd and muladd helpers 2018-04-13 15:46:43 +03:00
Recep Aslantas
d841f8809d vec: add some new functions for vector
* _mul: multiply two vector (replacement for _mulv)
* _div: div two vector
* _divs: div vector with scalar
* adds: add scalar to each components of vec
* subs: sub scalar from each components of vec
2018-04-13 15:12:56 +03:00
Recep Aslantas
af5a2627b4 fix scale_as for zero length vector
* return zero if vector length is zero
2018-04-13 11:57:34 +03:00
Recep Aslantas
25fc3d0284 vec: add one and zero helpers for vectors 2018-04-13 11:57:14 +03:00
Recep Aslantas
c489955b00 add simd norm helper 2018-04-13 11:39:14 +03:00
Recep Aslantas
79f8b1ebf8 vec4: optimize vec4 norm and norm2 2018-04-13 11:18:42 +03:00
Recep Aslantas
0eb37da8bb vec4: optimize vec4 normalize with SIMD 2018-04-13 11:01:07 +03:00
Recep Aslantas
44728c536b ci: update travis ci 2018-04-12 15:52:06 +03:00
Recep Aslantas
c8ed8acbed Update README.md 2018-04-12 14:47:14 +03:00
Recep Aslantas
2d77123999 quat: fix quaternion inverse and tests about it
* multiplication quaternion and its inverse must be identity
2018-04-11 16:50:37 +03:00
Recep Aslantas
462067cfdc Merge pull request #43 from recp/quaternion
quaternion improvements and new features
2018-04-11 12:43:48 +03:00
Recep Aslantas
9ae8da3e0a update version to v0.4.0 2018-04-11 12:36:39 +03:00
Recep Aslantas
0e63c245d4 update docs 2018-04-11 12:34:20 +03:00
Recep Aslantas
de55850136 add call version of vector extensions 2018-04-11 12:31:29 +03:00
Recep Aslantas
51278b26b4 quat: update call versions of quaternion 2018-04-11 11:19:13 +03:00
Recep Aslantas
fdea13507b replace mat4_mulq with glm_quat_rotate
* glm_quat_rotate is better name to rotate transform matrix using quaternion.
* we may use mat4_mulq in the future for another purpose e.g. left multiplication quat with matrix
2018-04-11 10:49:53 +03:00
Recep Aslantas
80d255e6d9 rotate vector using quaternion 2018-04-11 00:47:11 +03:00
Recep Aslantas
d447876c70 improve glm_vec_rotate 2018-04-11 00:46:23 +03:00
Recep Aslantas
b1fa7ff597 normalize axis quaternion axis-angle constructor 2018-04-11 00:36:39 +03:00
Recep Aslantas
010dcc9837 optimize normalize quaternion with SIMD
* provide _to version for storing into another quat
2018-04-11 00:17:41 +03:00
Recep Aslantas
5dec68823c add additional tests and comments to quat tests 2018-04-10 17:41:25 +03:00
Recep Aslantas
4c79fee5d3 quat: additional tests for angle, axis, mul (hamilton product) 2018-04-10 17:16:31 +03:00
Recep Aslantas
18ef0d7af1 quat: quaternion for look rotation ( from source point to dest point ) 2018-04-10 16:52:52 +03:00
Recep Aslantas
9466182c10 quat: create view wmatrix with quaternion helper 2018-04-10 16:01:23 +03:00
Recep Aslantas
f0a51b35ad quat: transposed/inverted version of quat2mat 2018-04-10 15:41:09 +03:00
Recep Aslantas
290bcf134c quat: add lerp and improve slerp 2018-04-10 12:38:54 +03:00
Recep Aslantas
416e2f4452 vec: lerp for vec3 and vec4 2018-04-10 11:44:16 +03:00
Recep Aslantas
1fb82a1922 quat: use vector functions for available operations
* provide quat_copy function
2018-04-10 10:47:55 +03:00
Recep Aslantas
591c881376 vec: extend flip sign to store result in another vector 2018-04-10 10:46:45 +03:00
Recep Aslantas
6f69da361b quaternion multiplication
* convert quaternion multiplication to xyzw
* previous implementation may be wrong, wikipedia version implemented
* implement SSE version
2018-04-09 23:56:09 +03:00
Recep Aslantas
93a08fce17 quat: axis angle of quaternion 2018-04-09 23:12:44 +03:00
Recep Aslantas
cc1d3b53ea quat: implement add, sub, real and imag helpers 2018-04-09 22:32:55 +03:00
Recep Aslantas
b21df8fc37 inverse of quaternion 2018-04-09 22:26:23 +03:00
Recep Aslantas
76e9f74020 conjugate of quaternion 2018-04-09 21:54:53 +03:00
Recep Aslantas
d79e58486d update credits file 2018-04-09 21:54:35 +03:00
Recep Aslantas
3dc93c56e8 convert quaterinon to xyzw order (part 1) 2018-04-09 18:49:12 +03:00
Recep Aslantas
7615f785ac improve quaternion to matrix 2018-04-09 00:53:14 +03:00
Recep Aslantas
f0daaca58b improve matrix to quaternion 2018-04-09 00:46:00 +03:00
Recep Aslantas
381b2fdcc0 fix vec4_norm2, use dot for vec3_norm2 2018-04-09 00:01:56 +03:00
Recep Aslantas
e4e0fa623c sse2 version of vec4 dot product
* use this for normalizing vector
2018-04-08 18:27:54 +03:00
Recep Aslantas
932f638d5a optimize mat4 to quaternion
* add SSE2 version and optimize scalar version
2018-04-08 12:31:32 +03:00
Recep Aslantas
81bda7439d vector square root 2018-04-08 12:30:15 +03:00
Recep Aslantas
b27603c268 normalize quaternion before converting to matrix
* because it must be unit quaternion and didn't specified this in docs.

* we must provide alternative func for unit quat
2018-04-08 00:09:40 +03:00
Recep Aslantas
12c5307447 vec3 and vec4 sign helper 2018-04-07 21:53:22 +03:00
Recep Aslantas
257c57d41f mat4 to quaternion 2018-04-07 19:46:46 +03:00
Recep Aslantas
f5140ea005 quat: mat4_mul_quat helper
* the quaternion is used as right matrix
2018-04-07 13:47:20 +03:00
Recep Aslantas
619ecdc5a4 quat: improve normalize 2018-04-07 13:46:46 +03:00
Recep Aslantas
9b8748acc4 quat: quaternion to mat3 2018-04-07 13:27:40 +03:00
Recep Aslantas
ae06c51746 improve glm_mat4_mulN for non-DEBUG environment 2018-04-07 13:22:44 +03:00
Recep Aslantas
11430559b4 fix isnan and isinf 2018-04-07 08:28:37 +03:00
Recep Aslantas
58f0043417 vector utils: isnan and isinf
* a vector which has least one NaN or INF member, is assumed not valid vector.
2018-04-06 22:57:24 +03:00
Recep Aslantas
cfd3600107 simd: optional shuffle configuration to save move instructions 2018-04-04 22:42:21 +03:00
Recep Aslantas
967fb1afad Update README.md 2018-04-03 17:32:10 +03:00
Recep Aslantas
7411ac36c1 update docs for euler angles 2018-04-03 17:05:45 +03:00
Recep Aslantas
238609f2c0 Merge pull request #31 from recp/proj
add project / unproject functions
2018-04-03 16:51:55 +03:00
Recep Aslantas
ea0a10ade9 suppress warnings 2018-04-03 16:47:59 +03:00
Recep Aslantas
429fdfd5c5 update build scripts 2018-04-03 16:47:51 +03:00
Recep Aslantas
024412f00e add docs for project/unproject 2018-04-03 16:41:13 +03:00
Recep Aslantas
e8615ea14c fix tests list 2018-04-03 12:35:30 +03:00
Recep Aslantas
be81d73895 Update test_main.c 2018-04-03 12:32:21 +03:00
Recep Aslantas
b16f0ded85 Merge branch 'master' into proj 2018-04-03 12:30:03 +03:00
Recep Aslantas
63acfd681e fix unproject, add tests to project/unproject 2018-04-03 12:27:20 +03:00
Recep Aslantas
eb527e39b4 optimize project 2018-04-03 11:25:33 +03:00
Recep Aslantas
9f389ab8ec project function 2018-04-03 11:09:13 +03:00
Recep Aslantas
3399595dc2 add vec2 type 2018-04-03 10:46:46 +03:00
Recep Aslantas
2513d46102 Merge pull request #41 from winduptoy/patch-1
Fix small typo.
2018-04-02 20:26:52 +03:00
Matt Reyer
c298f4a4d7 Fix small typo. 2018-04-02 11:33:58 -04:00
Recep Aslantas
84cdbd5072 Merge pull request #40 from recp/aabb-ext
Axis-Aligned Bounding Box (AABB) Extensions
2018-04-02 16:40:23 +03:00
Recep Aslantas
74f9865884 add docs for new aabb functions 2018-04-02 16:36:55 +03:00
Recep Aslantas
dbd1e334ea aabb box size and radius 2018-04-02 16:26:14 +03:00
Recep Aslantas
acda316c12 get sign of float helper as -1, +1 and 0
* add clarification for zero input
2018-04-02 16:18:50 +03:00
Recep Aslantas
86efe64b8e helper for check aabb is valid or not 2018-04-02 12:35:22 +03:00
Recep Aslantas
b0991342a6 aabb printer function 2018-04-02 12:08:08 +03:00
Recep Aslantas
984916d520 invalidate axis-aligned boundng box util 2018-04-02 11:50:53 +03:00
Recep Aslantas
54c44ff224 Merge pull request #39 from opencollective/opencollective
Activating Open Collective
2018-04-01 22:26:33 +03:00
Jess
db4761b437 Added backers and sponsors on the README 2018-04-01 18:12:46 +09:00
Recep Aslantas
ca504f7058 now working on v0.3.6 2018-03-29 00:12:16 +03:00
Recep Aslantas
5a7b9caf16 Update README.md 2018-03-29 00:02:37 +03:00
Recep Aslantas
43b3df992d Merge pull request #37 from recp/euler
fix euler angles (extrinsic -> intrinsic)
2018-03-28 23:58:15 +03:00
Recep Aslantas
26110f83d1 euler: fix thetaY in extracting angles 2018-03-27 12:35:19 +03:00
Recep Aslantas
d1f3feeb6e test: add tests for euler XYZ 2018-03-27 12:14:46 +03:00
Recep Aslantas
4298211795 euler: fix extracting XYZ angles 2018-03-27 12:14:12 +03:00
Recep Aslantas
c244b68e73 build: improve build-deps 2018-03-27 11:22:05 +03:00
Recep Aslantas
205d13aa93 fix euler angles (extrinsic -> intrinsic)
because cglm uses intrinsics for these rotations
2018-03-27 11:14:26 +03:00
Recep Aslantas
45f13217c3 Merge pull request #35 from recp/clamp
clamp functions
2018-03-22 21:28:19 +03:00
Recep Aslantas
21ec45b2af add tests for clamp 2018-03-22 21:24:41 +03:00
Recep Aslantas
71b48b530e add documentation for clamp 2018-03-22 21:24:26 +03:00
Recep Aslantas
48b7b30e42 add call version for clamp 2018-03-22 21:18:08 +03:00
Recep Aslantas
86055097e1 clamp functions 2018-03-22 18:10:10 +03:00
Recep Aslantas
08be94a89b Merge pull request #34 from NoxNode/typofix
typo fixes
2018-03-20 10:41:11 +03:00
mcsquizzy123
91b2a989e2 typo fixes - heaer and haeder 2018-03-19 18:37:49 -07:00
Recep Aslantas
780179ff0d fix unproject 2018-03-08 22:29:10 +03:00
Recep Aslantas
c148eacdc2 fix unproject's parameters 2018-03-08 13:12:08 +03:00
Recep Aslantas
29996d0bdd add unproject function 2018-03-08 13:02:33 +03:00
102 changed files with 8337 additions and 1691 deletions

9
.gitignore vendored
View File

@@ -60,3 +60,12 @@ cglm_test_iosTests/*
docs/build/* docs/build/*
win/cglm_test_* win/cglm_test_*
* copy.* * copy.*
*.o
*.obj
*codeanalysis.*.xml
*codeanalysis.xml
*.lib
*.tlog
win/x64
win/x85
win/Debug

View File

@@ -49,7 +49,7 @@ script:
after_success: after_success:
- if [[ "$CC" == "gcc" && "$CODE_COVERAGE" == "ON" ]]; then - if [[ "$CC" == "gcc" && "$CODE_COVERAGE" == "ON" ]]; then
pip install --user cpp-coveralls pip install --user cpp-coveralls &&
coveralls coveralls
--build-root . --build-root .
--exclude lib --exclude lib

13
CREDITS
View File

@@ -1,7 +1,7 @@
This library [initially] used some [piece of] implementations This library [initially] used some [piece of] implementations
(may include codes) from these open source projects/resources: (may include codes) from these open source projects/resources:
1. Affine Transforms 1. Initial Affine Transforms
The original glm repo (g-truc), url: https://github.com/g-truc/glm The original glm repo (g-truc), url: https://github.com/g-truc/glm
LICENSE[S]: LICENSE[S]:
@@ -11,7 +11,7 @@ LICENSE[S]:
FULL LICENSE: https://github.com/g-truc/glm/blob/master/copying.txt FULL LICENSE: https://github.com/g-truc/glm/blob/master/copying.txt
2. Quaternions 2. Initial Quaternions
Anton's OpenGL 4 Tutorials book source code: Anton's OpenGL 4 Tutorials book source code:
LICENSE: LICENSE:
@@ -43,3 +43,12 @@ https://github.com/erich666/GraphicsGems/blob/master/gems/TransBox.c
6. Cull frustum 6. Cull frustum
http://www.txutxi.com/?p=584 http://www.txutxi.com/?p=584
http://old.cescg.org/CESCG-2002/DSykoraJJelinek/ 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

View File

@@ -1,9 +1,11 @@
# 🎥 OpenGL Mathematics (glm) for `C` # 🎥 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://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) [![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) [![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&amp;utm_medium=referral&amp;utm_content=recp/cglm&amp;utm_campaign=Badge_Grade) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/6a62b37d5f214f178ebef269dc4a6bf1)](https://www.codacy.com/app/recp/cglm?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=recp/cglm&amp;utm_campaign=Badge_Grade)
[![Backers on Open Collective](https://opencollective.com/cglm/backers/badge.svg)](#backers)
[![Sponsors on Open Collective](https://opencollective.com/cglm/sponsors/badge.svg)](#sponsors)
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` 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`
@@ -14,9 +16,14 @@ Complete documentation: http://cglm.readthedocs.io
#### Note for previous versions: #### 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 - 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 - 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.
#### Note for C++ developers: #### Note for C++ developers:
If you don't aware about original GLM library yet, you may also want to look at: If you don't aware about original GLM library yet, you may also want to look at:
@@ -73,6 +80,7 @@ Currently *cglm* uses default clip space configuration (-1, 1) for camera functi
- inline or pre-compiled function call - inline or pre-compiled function call
- frustum (extract view frustum planes, corners...) - frustum (extract view frustum planes, corners...)
- bounding box (AABB in Frustum (culling), crop, merge...) - bounding box (AABB in Frustum (culling), crop, merge...)
- project, unproject
<hr /> <hr />
@@ -114,6 +122,36 @@ glm_mul(T, R, modelMat);
glm_inv_tr(modelMat); glm_inv_tr(modelMat);
``` ```
## 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 ## License
MIT. check the LICENSE file MIT. check the LICENSE file
@@ -161,17 +199,17 @@ If you want to use inline versions of funcstions then; include main header
```C ```C
#include <cglm/cglm.h> #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 ```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: some functions are overloaded :) e.g you can normalize vector:
```C ```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: this will normalize vec and store normalized vector into `vec` but if you will store normalized vector into another vector do this:
```C ```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 like this function you may see `_to` postfix, this functions store results to another variables and save temp memory
@@ -180,9 +218,9 @@ to call pre-compiled versions include header with `c` postfix, c means call. Pre
```C ```C
#include <cglm/call.h> #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 ```C
glmc_vec_normalize(vec); glmc_vec3_normalize(vec);
``` ```
Function usage and parameters are documented inside related headers. You may see same parameter passed twice in some examples like this: Function usage and parameters are documented inside related headers. You may see same parameter passed twice in some examples like this:
@@ -194,6 +232,27 @@ 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. 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 ## 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: 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:

View File

@@ -8,17 +8,14 @@
cd $(dirname "$0") 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 autoheader
libtoolize
if [ "$(uname)" = "Darwin" ]; then
glibtoolize
else
libtoolize
fi
aclocal -I m4 aclocal -I m4
autoconf autoconf
automake --add-missing --copy automake --add-missing --copy

View File

@@ -9,21 +9,14 @@
# check if deps are pulled # check if deps are pulled
git submodule update --init --recursive git submodule update --init --recursive
# fix glibtoolize
cd $(dirname "$0") 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 # general deps: gcc make autoconf automake libtool cmake
# test - cmocka # test - cmocka
cd ./test/lib/cmocka cd ./test/lib/cmocka
mkdir build rm -rf build
mkdir -p build
cd build cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug .. cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug ..
make -j8 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.4.6"
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_PREREQ([2.69])
AC_INIT([cglm], [0.3.5], [info@recp.me]) AC_INIT([cglm], [0.5.0], [info@recp.me])
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])

View File

@@ -33,6 +33,7 @@ Table of contents (click func go):
Functions: Functions:
1. :c:func:`glm_mul` 1. :c:func:`glm_mul`
#. :c:func:`glm_mul_rot`
#. :c:func:`glm_inv_tr` #. :c:func:`glm_inv_tr`
Functions documentation Functions documentation
@@ -59,6 +60,27 @@ Functions documentation
| *[in]* **m2** affine matrix 2 | *[in]* **m2** affine matrix 2
| *[out]* **dest** result matrix | *[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) .. c:function:: void glm_inv_tr(mat4 mat)
| inverse orthonormal rotation + translation matrix (ridig-body) | inverse orthonormal rotation + translation matrix (ridig-body)

View File

@@ -5,6 +5,8 @@ affine transforms
Header: cglm/affine.h Header: cglm/affine.h
Initialize Transform Matrices
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Functions with **_make** prefix expect you don't have a matrix and they create 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. a matrix for you. You don't need to pass identity matrix.
@@ -15,6 +17,107 @@ before sending to transfrom functions.
There are also functions to decompose transform matrix. These functions can't There are also functions to decompose transform matrix. These functions can't
decompose matrix after projected. 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): Table of contents (click to go):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -29,15 +132,14 @@ Functions:
#. :c:func:`glm_scale_to` #. :c:func:`glm_scale_to`
#. :c:func:`glm_scale_make` #. :c:func:`glm_scale_make`
#. :c:func:`glm_scale` #. :c:func:`glm_scale`
#. :c:func:`glm_scale1`
#. :c:func:`glm_scale_uni` #. :c:func:`glm_scale_uni`
#. :c:func:`glm_rotate_x` #. :c:func:`glm_rotate_x`
#. :c:func:`glm_rotate_y` #. :c:func:`glm_rotate_y`
#. :c:func:`glm_rotate_z` #. :c:func:`glm_rotate_z`
#. :c:func:`glm_rotate_ndc_make`
#. :c:func:`glm_rotate_make` #. :c:func:`glm_rotate_make`
#. :c:func:`glm_rotate_ndc`
#. :c:func:`glm_rotate` #. :c:func:`glm_rotate`
#. :c:func:`glm_rotate_at`
#. :c:func:`glm_rotate_atm`
#. :c:func:`glm_decompose_scalev` #. :c:func:`glm_decompose_scalev`
#. :c:func:`glm_uniscaled` #. :c:func:`glm_uniscaled`
#. :c:func:`glm_decompose_rs` #. :c:func:`glm_decompose_rs`
@@ -122,10 +224,6 @@ Functions documentation
| *[in, out]* **m** affine transfrom | *[in, out]* **m** affine transfrom
| *[in]* **v** scale vector [x, y, z] | *[in]* **v** scale vector [x, y, z]
.. c:function:: void glm_scale1(mat4 m, float s)
DEPRECATED! Use glm_scale_uni
.. c:function:: void glm_scale_uni(mat4 m, float s) .. c:function:: void glm_scale_uni(mat4 m, float s)
applies uniform scale to existing transform matrix v = [s, s, s] applies uniform scale to existing transform matrix v = [s, s, s]
@@ -165,16 +263,6 @@ Functions documentation
| *[in]* **angle** angle (radians) | *[in]* **angle** angle (radians)
| *[out]* **dest** rotated matrix | *[out]* **dest** rotated matrix
.. c:function:: void glm_rotate_ndc_make(mat4 m, float angle, vec3 axis_ndc)
creates NEW rotation matrix by angle and axis
this name may change in the future. axis must be is normalized
Parameters:
| *[out]* **m** affine transfrom
| *[in]* **angle** angle (radians)
| *[in]* **axis_ndc** normalized axis
.. c:function:: void glm_rotate_make(mat4 m, float angle, vec3 axis) .. c:function:: void glm_rotate_make(mat4 m, float angle, vec3 axis)
creates NEW rotation matrix by angle and axis, creates NEW rotation matrix by angle and axis,
@@ -185,16 +273,6 @@ Functions documentation
| *[in]* **axis** angle (radians) | *[in]* **axis** angle (radians)
| *[in]* **axis** axis | *[in]* **axis** axis
.. c:function:: void glm_rotate_ndc(mat4 m, float angle, vec3 axis_ndc)
rotate existing transform matrix around Z axis by angle and axis
this name may change in the future, axis must be normalized.
Parameters:
| *[out]* **m** affine transfrom
| *[in]* **angle** angle (radians)
| *[in]* **axis_ndc** normalized axis
.. c:function:: void glm_rotate(mat4 m, float angle, vec3 axis) .. c:function:: void glm_rotate(mat4 m, float angle, vec3 axis)
rotate existing transform matrix around Z axis by angle and axis rotate existing transform matrix around Z axis by angle and axis
@@ -204,6 +282,29 @@ Functions documentation
| *[in]* **angle** angle (radians) | *[in]* **angle** angle (radians)
| *[in]* **axis** axis | *[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) .. c:function:: void glm_decompose_scalev(mat4 m, vec3 s)
decompose scale vector decompose scale vector

View File

@@ -5,14 +5,14 @@ Some functions may exist twice,
once for their namespace and once for global namespace once for their namespace and once for global namespace
to make easier to write very common functions to make easier to write very common functions
For instance, in general we use :code:`glm_vec_dot` to get dot product 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`, of two **vec3**. Now we can also do this with :code:`glm_dot`,
same for *_cross* and so on... same for *_cross* and so on...
The original function stays where it is, the function in global namespace 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. 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 e.g there is no func like :code:`glmc_dot` because *glm_dot* is just alias for
:code:`glm_vec_dot` :code:`glm_vec3_dot`
By including **cglm/cglm.h** header you will include all inline version 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 of functions. Since functions in this header[s] are inline you don't need to
@@ -41,6 +41,8 @@ Follow the :doc:`build` documentation for this
vec4-ext vec4-ext
color color
plane plane
project
util util
io io
call call
sphere

View File

@@ -24,6 +24,15 @@ Functions:
#. :c:func:`glm_aabb_crop` #. :c:func:`glm_aabb_crop`
#. :c:func:`glm_aabb_crop_until` #. :c:func:`glm_aabb_crop_until`
#. :c:func:`glm_aabb_frustum` #. :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 Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
@@ -91,3 +100,82 @@ Functions documentation
Parameters: Parameters:
| *[in]* **box** bounding box | *[in]* **box** bounding box
| *[out]* **planes** frustum planes | *[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

@@ -9,7 +9,7 @@ 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 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. 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 There is also :c:func:`glm_look_anyup` function which can help build view matrix
without providing UP axis. It uses :c:func:`glm_vec_ortho` to get a UP axis and without providing UP axis. It uses :c:func:`glm_vec3_ortho` to get a UP axis and
builds view matrix. builds view matrix.
You can also *_default* versions of ortho and perspective to build projection You can also *_default* versions of ortho and perspective to build projection
@@ -167,6 +167,8 @@ Functions documentation
| set up view matrix | 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: Parameters:
| *[in]* **eye** eye vector | *[in]* **eye** eye vector
| *[in]* **center** center vector | *[in]* **center** center vector
@@ -181,6 +183,8 @@ Functions documentation
target self then this might be useful. Because you need to get target target self then this might be useful. Because you need to get target
from direction. from direction.
**NOTE:** The UP vector must not be parallel to the line of sight from the eye point to the reference point.
Parameters: Parameters:
| *[in]* **eye** eye vector | *[in]* **eye** eye vector
| *[in]* **center** direction vector | *[in]* **center** direction vector

View File

@@ -62,9 +62,9 @@ author = u'Recep Aslantas'
# built documents. # built documents.
# #
# The short X.Y version. # The short X.Y version.
version = u'0.3.4' version = u'0.5.0'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = u'0.3.4' release = u'0.5.0'
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.

View File

@@ -70,6 +70,7 @@ Functions:
1. :c:func:`glm_euler_order` 1. :c:func:`glm_euler_order`
#. :c:func:`glm_euler_angles` #. :c:func:`glm_euler_angles`
#. :c:func:`glm_euler` #. :c:func:`glm_euler`
#. :c:func:`glm_euler_xyz`
#. :c:func:`glm_euler_zyx` #. :c:func:`glm_euler_zyx`
#. :c:func:`glm_euler_zxy` #. :c:func:`glm_euler_zxy`
#. :c:func:`glm_euler_xzy` #. :c:func:`glm_euler_xzy`
@@ -115,8 +116,18 @@ Functions documentation
| build rotation matrix from euler angles | build rotation matrix from euler angles
this is alias of glm_euler_xyz function
Parameters: Parameters:
| *[in]* **angles** angles as vector [Ex, Ey, Ez] | *[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 | *[in]* **dest** rotation matrix
.. c:function:: void glm_euler_zyx(vec3 angles, mat4 dest) .. c:function:: void glm_euler_zyx(vec3 angles, mat4 dest)
@@ -124,7 +135,7 @@ Functions documentation
| build rotation matrix from euler angles | build rotation matrix from euler angles
Parameters: Parameters:
| *[in]* **angles** angles as vector [Ez, Ey, Ex] | *[in]* **angles** angles as vector [Xangle, Yangle, Zangle]
| *[in]* **dest** rotation matrix | *[in]* **dest** rotation matrix
.. c:function:: void glm_euler_zxy(vec3 angles, mat4 dest) .. c:function:: void glm_euler_zxy(vec3 angles, mat4 dest)
@@ -132,7 +143,7 @@ Functions documentation
| build rotation matrix from euler angles | build rotation matrix from euler angles
Parameters: Parameters:
| *[in]* **angles** angles as vector [Ez, Ex, Ey] | *[in]* **angles** angles as vector [Xangle, Yangle, Zangle]
| *[in]* **dest** rotation matrix | *[in]* **dest** rotation matrix
.. c:function:: void glm_euler_xzy(vec3 angles, mat4 dest) .. c:function:: void glm_euler_xzy(vec3 angles, mat4 dest)
@@ -140,7 +151,7 @@ Functions documentation
| build rotation matrix from euler angles | build rotation matrix from euler angles
Parameters: Parameters:
| *[in]* **angles** angles as vector [Ex, Ez, Ey] | *[in]* **angles** angles as vector [Xangle, Yangle, Zangle]
| *[in]* **dest** rotation matrix | *[in]* **dest** rotation matrix
.. c:function:: void glm_euler_yzx(vec3 angles, mat4 dest) .. c:function:: void glm_euler_yzx(vec3 angles, mat4 dest)
@@ -148,7 +159,7 @@ Functions documentation
build rotation matrix from euler angles build rotation matrix from euler angles
Parameters: Parameters:
| *[in]* **angles** angles as vector [Ey, Ez, Ex] | *[in]* **angles** angles as vector [Xangle, Yangle, Zangle]
| *[in]* **dest** rotation matrix | *[in]* **dest** rotation matrix
.. c:function:: void glm_euler_yxz(vec3 angles, mat4 dest) .. c:function:: void glm_euler_yxz(vec3 angles, mat4 dest)
@@ -156,7 +167,7 @@ Functions documentation
| build rotation matrix from euler angles | build rotation matrix from euler angles
Parameters: Parameters:
| *[in]* **angles** angles as vector [Ey, Ex, Ez] | *[in]* **angles** angles as vector [Xangle, Yangle, Zangle]
| *[in]* **dest** rotation matrix | *[in]* **dest** rotation matrix
.. c:function:: void glm_euler_by_order(vec3 angles, glm_euler_sq ord, mat4 dest) .. c:function:: void glm_euler_by_order(vec3 angles, glm_euler_sq ord, mat4 dest)
@@ -166,6 +177,6 @@ Functions documentation
Use :c:func:`glm_euler_order` function to build *ord* parameter Use :c:func:`glm_euler_order` function to build *ord* parameter
Parameters: Parameters:
| *[in]* **angles** angles as vector (ord parameter spceifies angles order) | *[in]* **angles** angles as vector [Xangle, Yangle, Zangle]
| *[in]* **ord** euler order | *[in]* **ord** euler order
| *[in]* **dest** rotation matrix | *[in]* **dest** rotation matrix

View File

@@ -127,7 +127,7 @@ Functions documentation
.. code-block:: c .. code-block:: c
for (j = 0; j < 4; j++) { 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]);
} }
corners[i + 4] is far of corners[i] point. corners[i + 4] is far of corners[i] point.

View File

@@ -21,17 +21,24 @@ Types:
As you can see types don't store extra informations in favor of space. 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* You can send these values e.g. matrix to OpenGL directly without casting or calling a function like *value_ptr*
Aligment is Required: Alignment is Required:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**vec4** and **mat4** requires 16 byte aligment because vec4 and mat4 operations are **vec4** and **mat4** requires 16 byte alignment because vec4 and mat4 operations are
vectorized by SIMD instructions (SSE/AVX). vectorized by SIMD instructions (SSE/AVX).
**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: Allocations:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*cglm* doesn't alloc any memory on heap. So it doesn't provide any allocator. *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. 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** requires aligment. When allocating memory don't forget that **vec4** and **mat4** requires alignment.
**NOTE:** Unaligned vec4 and unaligned mat4 operations will be supported in the future. Check todo list. **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. Because you may want to multiply a CGLM matrix with external matrix.

View File

@@ -40,6 +40,8 @@ Also currently only **float** type is supported for most operations.
getting_started getting_started
opengl opengl
api api
opt
troubleshooting
Indices and tables Indices and tables
================== ==================

View File

@@ -39,6 +39,7 @@ Functions:
#. :c:func:`glm_vec3_print` #. :c:func:`glm_vec3_print`
#. :c:func:`glm_ivec3_print` #. :c:func:`glm_ivec3_print`
#. :c:func:`glm_versor_print` #. :c:func:`glm_versor_print`
#. :c:func:`glm_aabb_print`
Functions documentation Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
@@ -90,3 +91,12 @@ Functions documentation
Parameters: Parameters:
| *[in]* **vec** quaternion | *[in]* **vec** quaternion
| *[in]* **ostream** FILE to write | *[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

View File

@@ -20,10 +20,12 @@ Functions:
1. :c:func:`glm_mat3_copy` 1. :c:func:`glm_mat3_copy`
#. :c:func:`glm_mat3_identity` #. :c:func:`glm_mat3_identity`
#. :c:func:`glm_mat3_identity_array`
#. :c:func:`glm_mat3_mul` #. :c:func:`glm_mat3_mul`
#. :c:func:`glm_mat3_transpose_to` #. :c:func:`glm_mat3_transpose_to`
#. :c:func:`glm_mat3_transpose` #. :c:func:`glm_mat3_transpose`
#. :c:func:`glm_mat3_mulv` #. :c:func:`glm_mat3_mulv`
#. :c:func:`glm_mat3_quat`
#. :c:func:`glm_mat3_scale` #. :c:func:`glm_mat3_scale`
#. :c:func:`glm_mat3_det` #. :c:func:`glm_mat3_det`
#. :c:func:`glm_mat3_inv` #. :c:func:`glm_mat3_inv`
@@ -48,6 +50,14 @@ Functions documentation
Parameters: Parameters:
| *[out]* **mat** matrix | *[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_mul(mat3 m1, mat3 m2, mat3 dest) .. c:function:: void glm_mat3_mul(mat3 m1, mat3 m2, mat3 dest)
multiply m1 and m2 to dest multiply m1 and m2 to dest
@@ -89,6 +99,14 @@ Functions documentation
| *[in]* **v** vec3 (right, column vector) | *[in]* **v** vec3 (right, column vector)
| *[out]* **dest** destination (result, 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) .. c:function:: void glm_mat3_scale(mat3 m, float s)
multiply matrix with scalar multiply matrix with scalar

View File

@@ -25,6 +25,7 @@ Functions:
1. :c:func:`glm_mat4_ucopy` 1. :c:func:`glm_mat4_ucopy`
#. :c:func:`glm_mat4_copy` #. :c:func:`glm_mat4_copy`
#. :c:func:`glm_mat4_identity` #. :c:func:`glm_mat4_identity`
#. :c:func:`glm_mat4_identity_array`
#. :c:func:`glm_mat4_pick3` #. :c:func:`glm_mat4_pick3`
#. :c:func:`glm_mat4_pick3t` #. :c:func:`glm_mat4_pick3t`
#. :c:func:`glm_mat4_ins3` #. :c:func:`glm_mat4_ins3`
@@ -32,6 +33,7 @@ Functions:
#. :c:func:`glm_mat4_mulN` #. :c:func:`glm_mat4_mulN`
#. :c:func:`glm_mat4_mulv` #. :c:func:`glm_mat4_mulv`
#. :c:func:`glm_mat4_mulv3` #. :c:func:`glm_mat4_mulv3`
#. :c:func:`glm_mat4_quat`
#. :c:func:`glm_mat4_transpose_to` #. :c:func:`glm_mat4_transpose_to`
#. :c:func:`glm_mat4_transpose` #. :c:func:`glm_mat4_transpose`
#. :c:func:`glm_mat4_scale_p` #. :c:func:`glm_mat4_scale_p`
@@ -68,6 +70,14 @@ Functions documentation
Parameters: Parameters:
| *[out]* **mat** matrix | *[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_pick3(mat4 mat, mat3 dest) .. c:function:: void glm_mat4_pick3(mat4 mat, mat3 dest)
copy upper-left of mat4 to mat3 copy upper-left of mat4 to mat3
@@ -146,6 +156,14 @@ Functions documentation
| *[in]* **v** vec3 (right, column vector) | *[in]* **v** vec3 (right, column vector)
| *[out]* **dest** vec3 (result, column vector) | *[out]* **dest** vec3 (result, column vector)
.. 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) .. c:function:: void glm_mat4_transpose_to(mat4 m, mat4 dest)
transpose mat4 and store in dest transpose mat4 and store in dest

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

@@ -0,0 +1,42 @@
.. 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.

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

View File

@@ -5,17 +5,16 @@ quaternions
Header: cglm/quat.h Header: cglm/quat.h
**Important:** *cglm* stores quaternion as [w, x, y, z] in memory, don't **Important:** *cglm* stores quaternion as **[x, y, z, w]** in memory
forget that when changing quaternion items manually. For instance *quat[3]* since **v0.4.0** it was **[w, x, y, z]**
is *quat.z* and *quat[0*] is *quat.w*. This may change in the future if *cglm* before v0.4.0 ( **v0.3.5 and earlier** ). w is real part.
will got enough request to do that. Probably it will not be changed in near
future
There are some TODOs for quaternions check TODO list to see them. What you can do with quaternions with existing functions is (Some of them):
Also **versor** is identity quaternion so the type may change to **vec4** or - You can rotate transform matrix using quaterion
something else. This will not affect existing functions for your engine because - You can rotate vector using quaterion
*versor* is alias of *vec4* - You can create view matrix using quaterion
- You can create a lookrotation (from source point to dest)
Table of contents (click to go): Table of contents (click to go):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -28,14 +27,39 @@ Macros:
Functions: Functions:
1. :c:func:`glm_quat_identity` 1. :c:func:`glm_quat_identity`
#. :c:func:`glm_quat_identity_array`
#. :c:func:`glm_quat_init`
#. :c:func:`glm_quat` #. :c:func:`glm_quat`
#. :c:func:`glm_quatv` #. :c:func:`glm_quatv`
#. :c:func:`glm_quat_copy`
#. :c:func:`glm_quat_norm` #. :c:func:`glm_quat_norm`
#. :c:func:`glm_quat_normalize` #. :c:func:`glm_quat_normalize`
#. :c:func:`glm_quat_normalize_to`
#. :c:func:`glm_quat_dot` #. :c:func:`glm_quat_dot`
#. :c:func:`glm_quat_mulv` #. :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_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_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 Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
@@ -47,10 +71,31 @@ Functions documentation
Parameters: Parameters:
| *[in, out]* **q** quaternion | *[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) .. c:function:: void glm_quat(versor q, float angle, float x, float y, float z)
| creates NEW quaternion with individual axis components | creates NEW quaternion with individual axis components
| given axis will be normalized
Parameters: Parameters:
| *[out]* **q** quaternion | *[out]* **q** quaternion
| *[in]* **angle** angle (radians) | *[in]* **angle** angle (radians)
@@ -58,14 +103,24 @@ Functions documentation
| *[in]* **y** axis.y | *[in]* **y** axis.y
| *[in]* **z** axis.z | *[in]* **z** axis.z
.. c:function:: void glm_quatv(versor q, float angle, vec3 v) .. c:function:: void glm_quatv(versor q, float angle, vec3 axis)
| creates NEW quaternion with axis vector | creates NEW quaternion with axis vector
| given axis will be normalized
Parameters: Parameters:
| *[out]* **q** quaternion | *[out]* **q** quaternion
| *[in]* **angle** angle (radians) | *[in]* **angle** angle (radians)
| *[in]* **v** axis | *[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) .. c:function:: float glm_quat_norm(versor q)
@@ -77,6 +132,14 @@ Functions documentation
Returns: Returns:
norm (magnitude) 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) .. c:function:: void glm_quat_normalize(versor q)
| normalize quaternion | normalize quaternion
@@ -84,24 +147,118 @@ Functions documentation
Parameters: Parameters:
| *[in, out]* **q** quaternion | *[in, out]* **q** quaternion
.. c:function:: float glm_quat_dot(versor q, versor r) .. c:function:: float glm_quat_dot(versor p, versor q)
dot product of two quaternion dot product of two quaternion
Parameters: Parameters:
| *[in]* **q1** quaternion 1 | *[in]* **p** quaternion 1
| *[in]* **q2** quaternion 2 | *[in]* **q** quaternion 2
Returns: Returns:
dot product dot product
.. c:function:: void glm_quat_mulv(versor q1, versor q2, versor dest) .. 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 | 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: Parameters:
| *[in]* **q1** quaternion 1 | *[in]* **p** quaternion 1 (first rotation)
| *[in]* **q2** quaternion 2 | *[in]* **q** quaternion 2 (second rotation)
| *[out]* **dest** result quaternion | *[out]* **dest** result quaternion
.. c:function:: void glm_quat_mat4(versor q, mat4 dest) .. c:function:: void glm_quat_mat4(versor q, mat4 dest)
@@ -112,13 +269,121 @@ Functions documentation
| *[in]* **q** quaternion | *[in]* **q** quaternion
| *[out]* **dest** result matrix | *[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) .. c:function:: void glm_quat_slerp(versor q, versor r, float t, versor dest)
| interpolates between two quaternions | interpolates between two quaternions
| using spherical linear interpolation (SLERP) | using spherical linear interpolation (SLERP)
Parameters: Parameters:
| *[in]* **q** from | *[in]* **from** from
| *[in]* **r** to | *[in]* **to** to
| *[in]* **t** amout | *[in]* **t** interpolant (amount) clamped between 0 and 1
| *[out]* **dest** result quaternion | *[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.**

View File

@@ -13,18 +13,25 @@ Table of contents (click to go):
Functions: Functions:
1. :c:func:`glm_sign` 1. :c:func:`glm_sign`
#. :c:func:`glm_signf`
#. :c:func:`glm_rad` #. :c:func:`glm_rad`
#. :c:func:`glm_deg` #. :c:func:`glm_deg`
#. :c:func:`glm_make_rad` #. :c:func:`glm_make_rad`
#. :c:func:`glm_make_deg` #. :c:func:`glm_make_deg`
#. :c:func:`glm_pow2` #. :c:func:`glm_pow2`
#. :c:func:`glm_min`
#. :c:func:`glm_max`
#. :c:func:`glm_clamp`
#. :c:func:`glm_lerp`
Functions documentation Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
.. c:function:: int glm_sign(int val) .. c:function:: int glm_sign(int val)
| returns sign of 32 bit integer as +1 or -1 | returns sign of 32 bit integer as +1, -1, 0
| **Important**: It returns 0 for zero input
Parameters: Parameters:
| *[in]* **val** an integer | *[in]* **val** an integer
@@ -32,6 +39,18 @@ Functions documentation
Returns: Returns:
sign of given number 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) .. c:function:: float glm_rad(float deg)
| convert degree to radians | convert degree to radians
@@ -91,3 +110,64 @@ Functions documentation
Returns: Returns:
maximum value 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)

View File

@@ -14,20 +14,25 @@ Table of contents (click to go):
Functions: Functions:
1. :c:func:`glm_vec_mulv` 1. :c:func:`glm_vec3_mulv`
#. :c:func:`glm_vec_broadcast` #. :c:func:`glm_vec3_broadcast`
#. :c:func:`glm_vec_eq` #. :c:func:`glm_vec3_eq`
#. :c:func:`glm_vec_eq_eps` #. :c:func:`glm_vec3_eq_eps`
#. :c:func:`glm_vec_eq_all` #. :c:func:`glm_vec3_eq_all`
#. :c:func:`glm_vec_eqv` #. :c:func:`glm_vec3_eqv`
#. :c:func:`glm_vec_eqv_eps` #. :c:func:`glm_vec3_eqv_eps`
#. :c:func:`glm_vec_max` #. :c:func:`glm_vec3_max`
#. :c:func:`glm_vec_min` #. :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 Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
.. c:function:: void glm_vec_mulv(vec3 a, vec3 b, vec3 d) .. c:function:: void glm_vec3_mulv(vec3 a, vec3 b, vec3 d)
multiplies individual items multiplies individual items
@@ -36,7 +41,7 @@ Functions documentation
| *[in]* **b** vec2 | *[in]* **b** vec2
| *[out]* **d** destination (v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2]) | *[out]* **d** destination (v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2])
.. c:function:: void glm_vec_broadcast(float val, vec3 d) .. c:function:: void glm_vec3_broadcast(float val, vec3 d)
fill a vector with specified value fill a vector with specified value
@@ -44,7 +49,7 @@ Functions documentation
| *[in]* **val** value | *[in]* **val** value
| *[out]* **dest** destination | *[out]* **dest** destination
.. c:function:: bool glm_vec_eq(vec3 v, float val) .. c:function:: bool glm_vec3_eq(vec3 v, float val)
check if vector is equal to value (without epsilon) check if vector is equal to value (without epsilon)
@@ -52,7 +57,7 @@ Functions documentation
| *[in]* **v** vector | *[in]* **v** vector
| *[in]* **val** value | *[in]* **val** value
.. c:function:: bool glm_vec_eq_eps(vec3 v, float val) .. c:function:: bool glm_vec3_eq_eps(vec3 v, float val)
check if vector is equal to value (with epsilon) check if vector is equal to value (with epsilon)
@@ -60,14 +65,14 @@ Functions documentation
| *[in]* **v** vector | *[in]* **v** vector
| *[in]* **val** value | *[in]* **val** value
.. c:function:: bool glm_vec_eq_all(vec3 v) .. c:function:: bool glm_vec3_eq_all(vec3 v)
check if vectors members are equal (without epsilon) check if vectors members are equal (without epsilon)
Parameters: Parameters:
| *[in]* **v** vector | *[in]* **v** vector
.. c:function:: bool glm_vec_eqv(vec3 v1, vec3 v2) .. c:function:: bool glm_vec3_eqv(vec3 v1, vec3 v2)
check if vector is equal to another (without epsilon) vector check if vector is equal to another (without epsilon) vector
@@ -75,7 +80,7 @@ Functions documentation
| *[in]* **vec** vector 1 | *[in]* **vec** vector 1
| *[in]* **vec** vector 2 | *[in]* **vec** vector 2
.. c:function:: bool glm_vec_eqv_eps(vec3 v1, vec3 v2) .. c:function:: bool glm_vec3_eqv_eps(vec3 v1, vec3 v2)
check if vector is equal to another (with epsilon) check if vector is equal to another (with epsilon)
@@ -83,16 +88,56 @@ Functions documentation
| *[in]* **v1** vector1 | *[in]* **v1** vector1
| *[in]* **v2** vector2 | *[in]* **v2** vector2
.. c:function:: float glm_vec_max(vec3 v) .. c:function:: float glm_vec3_max(vec3 v)
max value of vector max value of vector
Parameters: Parameters:
| *[in]* **v** vector | *[in]* **v** vector
.. c:function:: float glm_vec_min(vec3 v) .. c:function:: float glm_vec3_min(vec3 v)
min value of vector min value of vector
Parameters: Parameters:
| *[in]* **v** vector | *[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))

View File

@@ -5,9 +5,14 @@ vec3
Header: cglm/vec3.h 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 We mostly use vectors in graphics math, to make writing code faster
and easy to read, some *vec3* functions are aliased in global namespace. and easy to read, some *vec3* functions are aliased in global namespace.
For instance :c:func:`glm_dot` is alias of :c:func:`glm_vec_dot`, 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 alias means inline wrapper here. There is no call verison of alias functions
There are also functions for rotating *vec3* vector. **_m4**, **_m3** prefixes There are also functions for rotating *vec3* vector. **_m4**, **_m3** prefixes
@@ -18,7 +23,7 @@ Table of contents (click to go):
Macros: Macros:
1. glm_vec_dup(v, dest) 1. glm_vec3_dup(v, dest)
#. GLM_VEC3_ONE_INIT #. GLM_VEC3_ONE_INIT
#. GLM_VEC3_ZERO_INIT #. GLM_VEC3_ZERO_INIT
#. GLM_VEC3_ONE #. GLM_VEC3_ONE
@@ -30,29 +35,49 @@ Macros:
Functions: Functions:
1. :c:func:`glm_vec3` 1. :c:func:`glm_vec3`
#. :c:func:`glm_vec_copy` #. :c:func:`glm_vec3_copy`
#. :c:func:`glm_vec_dot` #. :c:func:`glm_vec3_zero`
#. :c:func:`glm_vec_cross` #. :c:func:`glm_vec3_one`
#. :c:func:`glm_vec_norm2` #. :c:func:`glm_vec3_dot`
#. :c:func:`glm_vec_norm` #. :c:func:`glm_vec3_cross`
#. :c:func:`glm_vec_add` #. :c:func:`glm_vec3_norm2`
#. :c:func:`glm_vec_sub` #. :c:func:`glm_vec3_norm`
#. :c:func:`glm_vec_scale` #. :c:func:`glm_vec3_add`
#. :c:func:`glm_vec_scale_as` #. :c:func:`glm_vec3_adds`
#. :c:func:`glm_vec_flipsign` #. :c:func:`glm_vec3_sub`
#. :c:func:`glm_vec_inv` #. :c:func:`glm_vec3_subs`
#. :c:func:`glm_vec_inv_to` #. :c:func:`glm_vec3_mul`
#. :c:func:`glm_vec_normalize` #. :c:func:`glm_vec3_scale`
#. :c:func:`glm_vec_normalize_to` #. :c:func:`glm_vec3_scale_as`
#. :c:func:`glm_vec_distance` #. :c:func:`glm_vec3_div`
#. :c:func:`glm_vec_angle` #. :c:func:`glm_vec3_divs`
#. :c:func:`glm_vec_rotate` #. :c:func:`glm_vec3_addadd`
#. :c:func:`glm_vec_rotate_m4` #. :c:func:`glm_vec3_subadd`
#. :c:func:`glm_vec_proj` #. :c:func:`glm_vec3_muladd`
#. :c:func:`glm_vec_center` #. :c:func:`glm_vec3_muladds`
#. :c:func:`glm_vec_maxv` #. :c:func:`glm_vec3_maxadd`
#. :c:func:`glm_vec_minv` #. :c:func:`glm_vec3_minadd`
#. :c:func:`glm_vec_ortho` #. :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_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 Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
@@ -65,7 +90,7 @@ Functions documentation
| *[in]* **v4** vector4 | *[in]* **v4** vector4
| *[out]* **dest** destination | *[out]* **dest** destination
.. c:function:: void glm_vec_copy(vec3 a, vec3 dest) .. c:function:: void glm_vec3_copy(vec3 a, vec3 dest)
copy all members of [a] to [dest] copy all members of [a] to [dest]
@@ -73,7 +98,21 @@ Functions documentation
| *[in]* **a** source | *[in]* **a** source
| *[out]* **dest** destination | *[out]* **dest** destination
.. c:function:: float glm_vec_dot(vec3 a, vec3 b) .. 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 dot product of vec3
@@ -84,7 +123,7 @@ Functions documentation
Returns: Returns:
dot product dot product
.. c:function:: void glm_vec_cross(vec3 a, vec3 b, vec3 d) .. c:function:: void glm_vec3_cross(vec3 a, vec3 b, vec3 d)
cross product cross product
@@ -93,7 +132,7 @@ Functions documentation
| *[in]* **b** source 2 | *[in]* **b** source 2
| *[out]* **d** destination | *[out]* **d** destination
.. c:function:: float glm_vec_norm2(vec3 v) .. c:function:: float glm_vec3_norm2(vec3 v)
norm * norm (magnitude) of vector norm * norm (magnitude) of vector
@@ -107,32 +146,59 @@ Functions documentation
Returns: Returns:
square of norm / magnitude square of norm / magnitude
.. c:function:: float glm_vec_norm(vec3 vec) .. c:function:: float glm_vec3_norm(vec3 vec)
norm (magnitude) of vec3 norm (magnitude) of vec3
Parameters: Parameters:
| *[in]* **vec** vector | *[in]* **vec** vector
.. c:function:: void glm_vec_add(vec3 v1, vec3 v2, vec3 dest) .. c:function:: void glm_vec3_add(vec3 a, vec3 b, vec3 dest)
add v2 vector to v1 vector store result in dest add a vector to b vector store result in dest
Parameters: Parameters:
| *[in]* **v1** vector1 | *[in]* **a** vector1
| *[in]* **v2** vector2 | *[in]* **b** vector2
| *[out]* **dest** destination vector | *[out]* **dest** destination vector
.. c:function:: void glm_vec_sub(vec3 v1, vec3 v2, vec3 dest) .. c:function:: void glm_vec3_adds(vec3 a, float s, vec3 dest)
subtract v2 vector from v1 vector store result in dest add scalar to v vector store result in dest (d = v + vec(s))
Parameters: Parameters:
| *[in]* **v1** vector1 | *[in]* **v** vector
| *[in]* **v2** vector2 | *[in]* **s** scalar
| *[out]* **dest** destination vector | *[out]* **dest** destination vector
.. c:function:: void glm_vec_scale(vec3 v, float s, vec3 dest) .. 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 multiply/scale vec3 vector with scalar: result = v * s
@@ -142,7 +208,7 @@ Functions documentation
| *[in]* **s** scalar | *[in]* **s** scalar
| *[out]* **dest** destination vector | *[out]* **dest** destination vector
.. c:function:: void glm_vec_scale_as(vec3 v, float s, vec3 dest) .. c:function:: void glm_vec3_scale_as(vec3 v, float s, vec3 dest)
make vec3 vector scale as specified: result = unit(v) * s make vec3 vector scale as specified: result = unit(v) * s
@@ -151,36 +217,145 @@ Functions documentation
| *[in]* **s** scalar | *[in]* **s** scalar
| *[out]* **dest** destination vector | *[out]* **dest** destination vector
.. c:function:: void glm_vec_flipsign(vec3 v) .. c:function:: void glm_vec3_div(vec3 a, vec3 b, vec3 dest)
flip sign of all vec3 members 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: Parameters:
| *[in, out]* **v** vector | *[in, out]* **v** vector
.. c:function:: void glm_vec_inv(vec3 v) .. c:function:: void glm_vec3_flipsign_to(vec3 v, vec3 dest)
make vector as inverse/opposite of itself **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: Parameters:
| *[in, out]* **v** vector | *[in, out]* **v** vector
.. c:function:: void glm_vec_inv_to(vec3 v, vec3 dest) .. c:function:: void glm_vec3_inv_to(vec3 v, vec3 dest)
inverse/opposite vector **DEPRACATED!**
use :c:func:`glm_vec3_negate_to`
Parameters: Parameters:
| *[in]* **v** source | *[in]* **v** source
| *[out]* **dest** destination | *[out]* **dest** destination
.. c:function:: void glm_vec_normalize(vec3 v) .. 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 normalize vec3 and store result in same vec
Parameters: Parameters:
| *[in, out]* **v** vector | *[in, out]* **v** vector
.. c:function:: void glm_vec_normalize_to(vec3 vec, vec3 dest) .. c:function:: void glm_vec3_normalize_to(vec3 vec, vec3 dest)
normalize vec3 to dest normalize vec3 to dest
@@ -188,7 +363,7 @@ Functions documentation
| *[in]* **vec** source | *[in]* **vec** source
| *[out]* **dest** destination | *[out]* **dest** destination
.. c:function:: float glm_vec_angle(vec3 v1, vec3 v2) .. c:function:: float glm_vec3_angle(vec3 v1, vec3 v2)
angle betwen two vector angle betwen two vector
@@ -199,16 +374,16 @@ Functions documentation
Return: Return:
| angle as radians | angle as radians
.. c:function:: void glm_vec_rotate(vec3 v, float angle, vec3 axis) .. c:function:: void glm_vec3_rotate(vec3 v, float angle, vec3 axis)
rotate vec3 around axis by angle using Rodrigues' rotation formula rotate vec3 around axis by angle using Rodrigues' rotation formula
Parameters: Parameters:
| *[in, out]* **v** vector | *[in, out]* **v** vector
| *[in]* **axis** axis vector (must be unit vector) | *[in]* **axis** axis vector (will be normalized)
| *[out]* **angle** angle (radians) | *[out]* **angle** angle (radians)
.. c:function:: void glm_vec_rotate_m4(mat4 m, vec3 v, vec3 dest) .. c:function:: void glm_vec3_rotate_m4(mat4 m, vec3 v, vec3 dest)
apply rotation matrix to vector apply rotation matrix to vector
@@ -217,7 +392,16 @@ Functions documentation
| *[in]* **v** vector | *[in]* **v** vector
| *[out]* **dest** rotated vector | *[out]* **dest** rotated vector
.. c:function:: void glm_vec_proj(vec3 a, vec3 b, vec3 dest) .. 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 project a vector onto b vector
@@ -226,7 +410,7 @@ Functions documentation
| *[in]* **b** vector2 | *[in]* **b** vector2
| *[out]* **dest** projected vector | *[out]* **dest** projected vector
.. c:function:: void glm_vec_center(vec3 v1, vec3 v2, vec3 dest) .. c:function:: void glm_vec3_center(vec3 v1, vec3 v2, vec3 dest)
find center point of two vector find center point of two vector
@@ -235,7 +419,18 @@ Functions documentation
| *[in]* **v2** vector2 | *[in]* **v2** vector2
| *[out]* **dest** center point | *[out]* **dest** center point
.. c:function:: float glm_vec_distance(vec3 v1, vec3 v2) .. 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 distance between two vectors
@@ -246,7 +441,7 @@ Functions documentation
Returns: Returns:
| distance | distance
.. c:function:: void glm_vec_maxv(vec3 v1, vec3 v2, vec3 dest) .. c:function:: void glm_vec3_maxv(vec3 v1, vec3 v2, vec3 dest)
max values of vectors max values of vectors
@@ -255,7 +450,7 @@ Functions documentation
| *[in]* **v2** vector2 | *[in]* **v2** vector2
| *[out]* **dest** destination | *[out]* **dest** destination
.. c:function:: void glm_vec_minv(vec3 v1, vec3 v2, vec3 dest) .. c:function:: void glm_vec3_minv(vec3 v1, vec3 v2, vec3 dest)
min values of vectors min values of vectors
@@ -264,10 +459,31 @@ Functions documentation
| *[in]* **v2** vector2 | *[in]* **v2** vector2
| *[out]* **dest** destination | *[out]* **dest** destination
.. c:function:: void glm_vec_ortho(vec3 v, vec3 dest) .. c:function:: void glm_vec3_ortho(vec3 v, vec3 dest)
possible orthogonal/perpendicular vector possible orthogonal/perpendicular vector
Parameters: Parameters:
| *[in]* **mat** vector | *[in]* **mat** vector
| *[out]* **dest** orthogonal/perpendicular 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

View File

@@ -96,3 +96,43 @@ Functions documentation
Parameters: Parameters:
| *[in]* **v** vector | *[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))

View File

@@ -24,21 +24,45 @@ Functions:
1. :c:func:`glm_vec4` 1. :c:func:`glm_vec4`
#. :c:func:`glm_vec4_copy3` #. :c:func:`glm_vec4_copy3`
#. :c:func:`glm_vec4_copy` #. :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_dot`
#. :c:func:`glm_vec4_norm2` #. :c:func:`glm_vec4_norm2`
#. :c:func:`glm_vec4_norm` #. :c:func:`glm_vec4_norm`
#. :c:func:`glm_vec4_add` #. :c:func:`glm_vec4_add`
#. :c:func:`glm_vec4_adds`
#. :c:func:`glm_vec4_sub` #. :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`
#. :c:func:`glm_vec4_scale_as` #. :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`
#. :c:func:`glm_vec4_flipsign_to`
#. :c:func:`glm_vec4_inv` #. :c:func:`glm_vec4_inv`
#. :c:func:`glm_vec4_inv_to` #. :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`
#. :c:func:`glm_vec4_normalize_to` #. :c:func:`glm_vec4_normalize_to`
#. :c:func:`glm_vec4_distance` #. :c:func:`glm_vec4_distance`
#. :c:func:`glm_vec4_maxv` #. :c:func:`glm_vec4_maxv`
#. :c:func:`glm_vec4_minv` #. :c:func:`glm_vec4_minv`
#. :c:func:`glm_vec4_clamp`
#. :c:func:`glm_vec4_lerp`
#. :c:func:`glm_vec4_isnan`
#. :c:func:`glm_vec4_isinf`
#. :c:func:`glm_vec4_isvalid`
#. :c:func:`glm_vec4_sign`
#. :c:func:`glm_vec4_sqrt`
Functions documentation Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
@@ -70,6 +94,23 @@ Functions documentation
| *[in]* **v** source | *[in]* **v** source
| *[in]* **dest** destination | *[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) .. c:function:: float glm_vec4_dot(vec4 a, vec4 b)
dot product of vec4 dot product of vec4
@@ -102,24 +143,51 @@ Functions documentation
Parameters: Parameters:
| *[in]* **vec** vector | *[in]* **vec** vector
.. c:function:: void glm_vec4_add(vec4 v1, vec4 v2, vec4 dest) .. c:function:: void glm_vec4_add(vec4 a, vec4 b, vec4 dest)
add v2 vector to v1 vector store result in dest add a vector to b vector store result in dest
Parameters: Parameters:
| *[in]* **v1** vector1 | *[in]* **a** vector1
| *[in]* **v2** vector2 | *[in]* **b** vector2
| *[out]* **dest** destination vector | *[out]* **dest** destination vector
.. c:function:: void glm_vec4_sub(vec4 v1, vec4 v2, vec4 dest) .. c:function:: void glm_vec4_adds(vec4 v, float s, vec4 dest)
subtract v2 vector from v1 vector store result in dest add scalar to v vector store result in dest (d = v + vec(s))
Parameters: Parameters:
| *[in]* **v1** vector1 | *[in]* **v** vector
| *[in]* **v2** vector2 | *[in]* **s** scalar
| *[out]* **dest** destination vector | *[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) .. c:function:: void glm_vec4_scale(vec4 v, float s, vec4 dest)
multiply/scale vec4 vector with scalar: result = v * s multiply/scale vec4 vector with scalar: result = v * s
@@ -138,28 +206,137 @@ Functions documentation
| *[in]* **s** scalar | *[in]* **s** scalar
| *[out]* **dest** destination vector | *[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) .. c:function:: void glm_vec4_flipsign(vec4 v)
flip sign of all vec4 members **DEPRACATED!**
use :c:func:`glm_vec4_negate`
Parameters: Parameters:
| *[in, out]* **v** vector | *[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) .. c:function:: void glm_vec4_inv(vec4 v)
make vector as inverse/opposite of itself **DEPRACATED!**
use :c:func:`glm_vec4_negate`
Parameters: Parameters:
| *[in, out]* **v** vector | *[in, out]* **v** vector
.. c:function:: void glm_vec4_inv_to(vec4 v, vec4 dest) .. c:function:: void glm_vec4_inv_to(vec4 v, vec4 dest)
inverse/opposite vector **DEPRACATED!**
use :c:func:`glm_vec4_negate_to`
Parameters: Parameters:
| *[in]* **v** source | *[in]* **v** source
| *[out]* **dest** destination | *[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) .. c:function:: void glm_vec4_normalize(vec4 v)
normalize vec4 and store result in same vec normalize vec4 and store result in same vec
@@ -203,3 +380,24 @@ Functions documentation
| *[in]* **v1** vector1 | *[in]* **v1** vector1
| *[in]* **v2** vector2 | *[in]* **v2** vector2
| *[out]* **dest** destination | *[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

View File

@@ -16,6 +16,7 @@
#include "common.h" #include "common.h"
#include "mat4.h" #include "mat4.h"
#include "mat3.h"
#ifdef CGLM_SSE_FP #ifdef CGLM_SSE_FP
# include "simd/sse2/affine.h" # include "simd/sse2/affine.h"
@@ -81,6 +82,59 @@ glm_mul(mat4 m1, mat4 m2, mat4 dest) {
#endif #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) * @brief inverse orthonormal rotation + translation matrix (ridig-body)
* *
@@ -97,7 +151,7 @@ glm_inv_tr(mat4 mat) {
#if defined( __SSE__ ) || defined( __SSE2__ ) #if defined( __SSE__ ) || defined( __SSE2__ )
glm_inv_tr_sse2(mat); glm_inv_tr_sse2(mat);
#else #else
CGLM_ALIGN(16) mat3 r; CGLM_ALIGN_MAT mat3 r;
CGLM_ALIGN(16) vec3 t; CGLM_ALIGN(16) vec3 t;
/* rotate */ /* rotate */
@@ -106,8 +160,8 @@ glm_inv_tr(mat4 mat) {
/* translate */ /* translate */
glm_mat3_mulv(r, mat[3], t); glm_mat3_mulv(r, mat[3], t);
glm_vec_flipsign(t); glm_vec3_negate(t);
glm_vec_copy(t, mat[3]); glm_vec3_copy(t, mat[3]);
#endif #endif
} }

View File

@@ -16,15 +16,14 @@
CGLM_INLINE void glm_scale_to(mat4 m, vec3 v, mat4 dest); 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_make(mat4 m, vec3 v);
CGLM_INLINE void glm_scale(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_scale_uni(mat4 m, float s);
CGLM_INLINE void glm_rotate_x(mat4 m, float angle, mat4 dest); 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_y(mat4 m, float angle, mat4 dest);
CGLM_INLINE void glm_rotate_z(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_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(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 void glm_decompose_scalev(mat4 m, vec3 s);
CGLM_INLINE bool glm_uniscaled(mat4 m); CGLM_INLINE bool glm_uniscaled(mat4 m);
CGLM_INLINE void glm_decompose_rs(mat4 m, mat4 r, vec3 s); CGLM_INLINE void glm_decompose_rs(mat4 m, mat4 r, vec3 s);
@@ -35,51 +34,15 @@
#define cglm_affine_h #define cglm_affine_h
#include "common.h" #include "common.h"
#include "vec4.h"
#include "affine-mat.h"
#include "util.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 CGLM_INLINE
void void
glm_translate_to(mat4 m, vec3 v, mat4 dest) { glm_mat4_mul(mat4 m1, mat4 m2, 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
}
/*! /*!
* @brief translate existing transform matrix by v vector * @brief translate existing transform matrix by v vector
@@ -92,14 +55,14 @@ CGLM_INLINE
void void
glm_translate(mat4 m, vec3 v) { glm_translate(mat4 m, vec3 v) {
#if defined( __SSE__ ) || defined( __SSE2__ ) #if defined( __SSE__ ) || defined( __SSE2__ )
_mm_store_ps(m[3], glmm_store(m[3],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_load_ps(m[0]), _mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_load(m[0]),
_mm_set1_ps(v[0])), _mm_set1_ps(v[0])),
_mm_mul_ps(_mm_load_ps(m[1]), _mm_mul_ps(glmm_load(m[1]),
_mm_set1_ps(v[1]))), _mm_set1_ps(v[1]))),
_mm_add_ps(_mm_mul_ps(_mm_load_ps(m[2]), _mm_add_ps(_mm_mul_ps(glmm_load(m[2]),
_mm_set1_ps(v[2])), _mm_set1_ps(v[2])),
_mm_load_ps(m[3])))) glmm_load(m[3]))))
; ;
#else #else
vec4 v1, v2, v3; vec4 v1, v2, v3;
@@ -114,6 +77,23 @@ glm_translate(mat4 m, vec3 v) {
#endif #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 * @brief translate existing transform matrix by x factor
* *
@@ -124,10 +104,10 @@ CGLM_INLINE
void void
glm_translate_x(mat4 m, float x) { glm_translate_x(mat4 m, float x) {
#if defined( __SSE__ ) || defined( __SSE2__ ) #if defined( __SSE__ ) || defined( __SSE2__ )
_mm_store_ps(m[3], glmm_store(m[3],
_mm_add_ps(_mm_mul_ps(_mm_load_ps(m[0]), _mm_add_ps(_mm_mul_ps(glmm_load(m[0]),
_mm_set1_ps(x)), _mm_set1_ps(x)),
_mm_load_ps(m[3]))) glmm_load(m[3])))
; ;
#else #else
vec4 v1; vec4 v1;
@@ -146,10 +126,10 @@ CGLM_INLINE
void void
glm_translate_y(mat4 m, float y) { glm_translate_y(mat4 m, float y) {
#if defined( __SSE__ ) || defined( __SSE2__ ) #if defined( __SSE__ ) || defined( __SSE2__ )
_mm_store_ps(m[3], glmm_store(m[3],
_mm_add_ps(_mm_mul_ps(_mm_load_ps(m[1]), _mm_add_ps(_mm_mul_ps(glmm_load(m[1]),
_mm_set1_ps(y)), _mm_set1_ps(y)),
_mm_load_ps(m[3]))) glmm_load(m[3])))
; ;
#else #else
vec4 v1; vec4 v1;
@@ -168,10 +148,10 @@ CGLM_INLINE
void void
glm_translate_z(mat4 m, float z) { glm_translate_z(mat4 m, float z) {
#if defined( __SSE__ ) || defined( __SSE2__ ) #if defined( __SSE__ ) || defined( __SSE2__ )
_mm_store_ps(m[3], glmm_store(m[3],
_mm_add_ps(_mm_mul_ps(_mm_load_ps(m[2]), _mm_add_ps(_mm_mul_ps(glmm_load(m[2]),
_mm_set1_ps(z)), _mm_set1_ps(z)),
_mm_load_ps(m[3]))) glmm_load(m[3])))
; ;
#else #else
vec4 v1; vec4 v1;
@@ -189,8 +169,8 @@ glm_translate_z(mat4 m, float z) {
CGLM_INLINE CGLM_INLINE
void void
glm_translate_make(mat4 m, vec3 v) { glm_translate_make(mat4 m, vec3 v) {
mat4 t = GLM_MAT4_IDENTITY_INIT; glm_mat4_identity(m);
glm_translate_to(t, v, m); glm_vec3_copy(v, m[3]);
} }
/*! /*!
@@ -220,8 +200,10 @@ glm_scale_to(mat4 m, vec3 v, mat4 dest) {
CGLM_INLINE CGLM_INLINE
void void
glm_scale_make(mat4 m, vec3 v) { glm_scale_make(mat4 m, vec3 v) {
mat4 t = GLM_MAT4_IDENTITY_INIT; glm_mat4_identity(m);
glm_scale_to(t, v, 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); 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] * @brief applies uniform scale to existing transform matrix v = [s, s, s]
* and stores result in same matrix * and stores result in same matrix
@@ -257,7 +229,7 @@ glm_scale1(mat4 m, float s) {
CGLM_INLINE CGLM_INLINE
void void
glm_scale_uni(mat4 m, float s) { 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); glm_scale_to(m, v, m);
} }
@@ -272,19 +244,18 @@ glm_scale_uni(mat4 m, float s) {
CGLM_INLINE CGLM_INLINE
void void
glm_rotate_x(mat4 m, float angle, mat4 dest) { glm_rotate_x(mat4 m, float angle, mat4 dest) {
float cosVal; CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT;
float sinVal; float c, s;
mat4 t = GLM_MAT4_IDENTITY_INIT;
cosVal = cosf(angle); c = cosf(angle);
sinVal = sinf(angle); s = sinf(angle);
t[1][1] = cosVal; t[1][1] = c;
t[1][2] = sinVal; t[1][2] = s;
t[2][1] = -sinVal; t[2][1] = -s;
t[2][2] = cosVal; 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 CGLM_INLINE
void void
glm_rotate_y(mat4 m, float angle, mat4 dest) { glm_rotate_y(mat4 m, float angle, mat4 dest) {
float cosVal; CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT;
float sinVal; float c, s;
mat4 t = GLM_MAT4_IDENTITY_INIT;
cosVal = cosf(angle); c = cosf(angle);
sinVal = sinf(angle); s = sinf(angle);
t[0][0] = cosVal; t[0][0] = c;
t[0][2] = -sinVal; t[0][2] = -s;
t[2][0] = sinVal; t[2][0] = s;
t[2][2] = cosVal; t[2][2] = c;
glm_mat4_mul(m, t, dest); glm_mul_rot(m, t, dest);
} }
/*! /*!
@@ -324,61 +294,18 @@ glm_rotate_y(mat4 m, float angle, mat4 dest) {
CGLM_INLINE CGLM_INLINE
void void
glm_rotate_z(mat4 m, float angle, mat4 dest) { glm_rotate_z(mat4 m, float angle, mat4 dest) {
float cosVal; CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT;
float sinVal; float c, s;
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;
c = cosf(angle); c = cosf(angle);
s = sinf(angle);
glm_vec_scale(axis_ndc, 1.0f - c, v); t[0][0] = c;
glm_vec_scale(axis_ndc, sinf(angle), vs); t[0][1] = s;
t[1][0] = -s;
t[1][1] = c;
glm_vec_scale(axis_ndc, v[0], m[0]); glm_mul_rot(m, t, dest);
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;
} }
/*! /*!
@@ -393,53 +320,29 @@ glm_rotate_ndc_make(mat4 m, float angle, vec3 axis_ndc) {
CGLM_INLINE CGLM_INLINE
void void
glm_rotate_make(mat4 m, float angle, vec3 axis) { 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); c = cosf(angle);
glm_rotate_ndc_make(m, angle, axis_ndc);
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 * @brief rotate existing transform matrix around given axis by angle
*
* 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
* *
* @param[in, out] m affine transfrom * @param[in, out] m affine transfrom
* @param[in] angle angle (radians) * @param[in] angle angle (radians)
@@ -448,10 +351,55 @@ glm_rotate_ndc(mat4 m, float angle, vec3 axis_ndc) {
CGLM_INLINE CGLM_INLINE
void void
glm_rotate(mat4 m, float angle, vec3 axis) { 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,9 +411,9 @@ glm_rotate(mat4 m, float angle, vec3 axis) {
CGLM_INLINE CGLM_INLINE
void void
glm_decompose_scalev(mat4 m, vec3 s) { glm_decompose_scalev(mat4 m, vec3 s) {
s[0] = glm_vec_norm(m[0]); s[0] = glm_vec3_norm(m[0]);
s[1] = glm_vec_norm(m[1]); s[1] = glm_vec3_norm(m[1]);
s[2] = glm_vec_norm(m[2]); s[2] = glm_vec3_norm(m[2]);
} }
/*! /*!
@@ -479,10 +427,9 @@ glm_decompose_scalev(mat4 m, vec3 s) {
CGLM_INLINE CGLM_INLINE
bool bool
glm_uniscaled(mat4 m) { glm_uniscaled(mat4 m) {
vec3 s; CGLM_ALIGN(8) vec3 s;
glm_decompose_scalev(m, s); glm_decompose_scalev(m, s);
return glm_vec3_eq_all(s);
return glm_vec_eq_all(s);
} }
/*! /*!
@@ -496,17 +443,17 @@ glm_uniscaled(mat4 m) {
CGLM_INLINE CGLM_INLINE
void void
glm_decompose_rs(mat4 m, mat4 r, vec3 s) { glm_decompose_rs(mat4 m, mat4 r, vec3 s) {
vec4 t = {0.0f, 0.0f, 0.0f, 1.0f}; CGLM_ALIGN(16) vec4 t = {0.0f, 0.0f, 0.0f, 1.0f};
vec3 v; CGLM_ALIGN(8) vec3 v;
glm_vec4_copy(m[0], r[0]); glm_vec4_copy(m[0], r[0]);
glm_vec4_copy(m[1], r[1]); glm_vec4_copy(m[1], r[1]);
glm_vec4_copy(m[2], r[2]); glm_vec4_copy(m[2], r[2]);
glm_vec4_copy(t, r[3]); glm_vec4_copy(t, r[3]);
s[0] = glm_vec_norm(m[0]); s[0] = glm_vec3_norm(m[0]);
s[1] = glm_vec_norm(m[1]); s[1] = glm_vec3_norm(m[1]);
s[2] = glm_vec_norm(m[2]); s[2] = glm_vec3_norm(m[2]);
glm_vec4_scale(r[0], 1.0f/s[0], r[0]); glm_vec4_scale(r[0], 1.0f/s[0], r[0]);
glm_vec4_scale(r[1], 1.0f/s[1], r[1]); 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): /* Note from Apple Open Source (asume that the matrix is orthonormal):
check for a coordinate system flip. If the determinant check for a coordinate system flip. If the determinant
is -1, then negate the matrix and the scaling factors. */ is -1, then negate the matrix and the scaling factors. */
glm_vec_cross(m[0], m[1], v); glm_vec3_cross(m[0], m[1], v);
if (glm_vec_dot(v, m[2]) < 0.0f) { if (glm_vec3_dot(v, m[2]) < 0.0f) {
glm_vec4_flipsign(r[0]); glm_vec4_negate(r[0]);
glm_vec4_flipsign(r[1]); glm_vec4_negate(r[1]);
glm_vec4_flipsign(r[2]); glm_vec4_negate(r[2]);
glm_vec_flipsign(s); glm_vec3_negate(s);
} }
} }

View File

@@ -11,6 +11,7 @@
#include "common.h" #include "common.h"
#include "vec3.h" #include "vec3.h"
#include "vec4.h" #include "vec4.h"
#include "util.h"
/*! /*!
* @brief apply transform to Axis-Aligned Bounding Box * @brief apply transform to Axis-Aligned Bounding Box
@@ -22,35 +23,31 @@
CGLM_INLINE CGLM_INLINE
void void
glm_aabb_transform(vec3 box[2], mat4 m, vec3 dest[2]) { 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_vec3_scale(m[0], box[0][0], xa);
glm_vec_scale(m[0], box[1][0], xb); glm_vec3_scale(m[0], box[1][0], xb);
glm_vec_scale(m[1], box[0][1], ya); glm_vec3_scale(m[1], box[0][1], ya);
glm_vec_scale(m[1], box[1][1], yb); glm_vec3_scale(m[1], box[1][1], yb);
glm_vec_scale(m[2], box[0][2], za); glm_vec3_scale(m[2], box[0][2], za);
glm_vec_scale(m[2], box[1][2], zb); glm_vec3_scale(m[2], box[1][2], zb);
/* min(xa, xb) + min(ya, yb) + min(za, zb) + translation */ /* translation + min(xa, xb) + min(ya, yb) + min(za, zb) */
glm_vec_minv(xa, xb, v[0]); glm_vec3(m[3], v[0]);
glm_vec_minv(ya, yb, tmp); glm_vec3_minadd(xa, xb, v[0]);
glm_vec_add(v[0], tmp, v[0]); glm_vec3_minadd(ya, yb, v[0]);
glm_vec_minv(za, zb, tmp); glm_vec3_minadd(za, zb, v[0]);
glm_vec_add(v[0], tmp, v[0]);
glm_vec_add(v[0], m[3], v[0]);
/* max(xa, xb) + max(ya, yb) + max(za, zb) + translation */ /* translation + max(xa, xb) + max(ya, yb) + max(za, zb) */
glm_vec_maxv(xa, xb, v[1]); glm_vec3(m[3], v[1]);
glm_vec_maxv(ya, yb, tmp); glm_vec3_maxadd(xa, xb, v[1]);
glm_vec_add(v[1], tmp, v[1]); glm_vec3_maxadd(ya, yb, v[1]);
glm_vec_maxv(za, zb, tmp); glm_vec3_maxadd(za, zb, v[1]);
glm_vec_add(v[1], tmp, v[1]);
glm_vec_add(v[1], m[3], v[1]);
glm_vec_copy(v[0], dest[0]); glm_vec3_copy(v[0], dest[0]);
glm_vec_copy(v[1], dest[1]); glm_vec3_copy(v[1], dest[1]);
} }
/*! /*!
@@ -153,4 +150,130 @@ glm_aabb_frustum(vec3 box[2], vec4 planes[6]) {
return true; 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 */ #endif /* cglm_box_h */

View File

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

View File

@@ -13,6 +13,10 @@ extern "C" {
#include "../cglm.h" #include "../cglm.h"
CGLM_EXPORT
void
glmc_translate_make(mat4 m, vec3 v);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_translate_to(mat4 m, vec3 v, mat4 dest); glmc_translate_to(mat4 m, vec3 v, mat4 dest);
@@ -33,6 +37,10 @@ CGLM_EXPORT
void void
glmc_translate_z(mat4 m, float to); glmc_translate_z(mat4 m, float to);
CGLM_EXPORT
void
glmc_scale_make(mat4 m, vec3 v);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_scale_to(mat4 m, vec3 v, mat4 dest); glmc_scale_to(mat4 m, vec3 v, mat4 dest);
@@ -43,7 +51,7 @@ glmc_scale(mat4 m, vec3 v);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_scale1(mat4 m, float s); glmc_scale_uni(mat4 m, float s);
CGLM_EXPORT CGLM_EXPORT
void void
@@ -57,26 +65,30 @@ CGLM_EXPORT
void void
glmc_rotate_z(mat4 m, float rad, mat4 dest); 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 CGLM_EXPORT
void void
glmc_rotate_make(mat4 m, float angle, vec3 axis); glmc_rotate_make(mat4 m, float angle, vec3 axis);
CGLM_EXPORT
void
glmc_rotate_ndc(mat4 m, float angle, vec3 axis_ndc);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_rotate(mat4 m, float angle, vec3 axis); 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 CGLM_EXPORT
void void
glmc_decompose_scalev(mat4 m, vec3 s); glmc_decompose_scalev(mat4 m, vec3 s);
CGLM_EXPORT
bool
glmc_uniscaled(mat4 m);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_decompose_rs(mat4 m, mat4 r, vec3 s); glmc_decompose_rs(mat4 m, mat4 r, vec3 s);
@@ -85,6 +97,20 @@ CGLM_EXPORT
void void
glmc_decompose(mat4 m, vec4 t, mat4 r, vec3 s); 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 #ifdef __cplusplus
} }
#endif #endif

View File

@@ -32,6 +32,46 @@ glmc_aabb_crop_until(vec3 box[2],
vec3 clampBox[2], vec3 clampBox[2],
vec3 dest[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 #ifdef __cplusplus
} }
#endif #endif

View File

@@ -33,6 +33,26 @@ glmc_ortho(float left,
float farVal, float farVal,
mat4 dest); 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 CGLM_EXPORT
void void
glmc_perspective(float fovy, glmc_perspective(float fovy,
@@ -41,6 +61,14 @@ glmc_perspective(float fovy,
float farVal, float farVal,
mat4 dest); mat4 dest);
CGLM_EXPORT
void
glmc_perspective_default(float aspect, mat4 dest);
CGLM_EXPORT
void
glmc_perspective_resize(float aspect, mat4 proj);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_lookat(vec3 eye, vec3 center, vec3 up, mat4 dest); glmc_lookat(vec3 eye, vec3 center, vec3 up, mat4 dest);
@@ -53,6 +81,58 @@ CGLM_EXPORT
void void
glmc_look_anyup(vec3 eye, vec3 dir, mat4 dest); 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 #ifdef __cplusplus
} }
#endif #endif

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

@@ -0,0 +1,140 @@
/*
* 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);
#endif /* cglmc_ease_h */

View File

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

View File

@@ -24,6 +24,10 @@ CGLM_EXPORT
void void
glmc_mat3_identity(mat3 mat); glmc_mat3_identity(mat3 mat);
CGLM_EXPORT
void
glmc_mat3_identity_array(mat3 * __restrict mat, size_t count);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_mat3_mul(mat3 m1, mat3 m2, mat3 dest); glmc_mat3_mul(mat3 m1, mat3 m2, mat3 dest);
@@ -40,6 +44,10 @@ CGLM_EXPORT
void void
glmc_mat3_mulv(mat3 m, vec3 v, vec3 dest); glmc_mat3_mulv(mat3 m, vec3 v, vec3 dest);
CGLM_EXPORT
void
glmc_mat3_quat(mat3 m, versor dest);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_mat3_scale(mat3 m, float s); glmc_mat3_scale(mat3 m, float s);

View File

@@ -29,6 +29,10 @@ CGLM_EXPORT
void void
glmc_mat4_identity(mat4 mat); glmc_mat4_identity(mat4 mat);
CGLM_EXPORT
void
glmc_mat4_identity_array(mat4 * __restrict mat, size_t count);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_mat4_pick3(mat4 mat, mat3 dest); glmc_mat4_pick3(mat4 mat, mat3 dest);
@@ -47,12 +51,20 @@ glmc_mat4_mul(mat4 m1, mat4 m2, mat4 dest);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_mat4_mulN(mat4 * __restrict matrices[], int len, mat4 dest); glmc_mat4_mulN(mat4 * __restrict matrices[], uint32_t len, mat4 dest);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_mat4_mulv(mat4 m, vec4 v, vec4 dest); 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
void
glmc_mat4_quat(mat4 m, versor dest);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_mat4_transpose_to(mat4 m, mat4 dest); glmc_mat4_transpose_to(mat4 m, mat4 dest);
@@ -81,6 +93,10 @@ CGLM_EXPORT
void void
glmc_mat4_inv_precise(mat4 mat, mat4 dest); glmc_mat4_inv_precise(mat4 mat, mat4 dest);
CGLM_EXPORT
void
glmc_mat4_inv_fast(mat4 mat, mat4 dest);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_mat4_swap_col(mat4 mat, int col1, int col2); glmc_mat4_swap_col(mat4 mat, int col1, int col2);

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 CGLM_EXPORT
void void
glmc_quat(versor q, glmc_quat_identity_array(versor * __restrict q, size_t count);
float angle,
float x,
float y,
float z);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_quatv(versor q, glmc_quat_init(versor q, float x, float y, float z, float w);
float angle,
vec3 v); 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 CGLM_EXPORT
float float
glmc_quat_norm(versor q); glmc_quat_norm(versor q);
CGLM_EXPORT
void
glmc_quat_normalize_to(versor q, versor dest);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_quat_normalize(versor q); glmc_quat_normalize(versor q);
CGLM_EXPORT CGLM_EXPORT
float float
glmc_quat_dot(versor q, versor r); glmc_quat_dot(versor p, versor q);
CGLM_EXPORT CGLM_EXPORT
void 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, versor dest);
CGLM_EXPORT
void
glmc_quat_mul(versor p, versor q, versor dest);
CGLM_EXPORT CGLM_EXPORT
void void
@@ -53,10 +103,51 @@ glmc_quat_mat4(versor q, mat4 dest);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_quat_slerp(versor q, glmc_quat_mat4t(versor q, mat4 dest);
versor r,
float t, CGLM_EXPORT
versor dest); 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 #ifdef __cplusplus
} }

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 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);
#endif /* cglmc_sphere_h */

View File

@@ -14,95 +14,229 @@ extern "C" {
#include "../cglm.h" #include "../cglm.h"
/* DEPRECATED! use _copy, _ucopy versions */ /* 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 CGLM_EXPORT
void 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 CGLM_EXPORT
float float
glmc_vec_dot(vec3 a, vec3 b); glmc_vec3_dot(vec3 a, vec3 b);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_cross(vec3 a, vec3 b, vec3 d); glmc_vec3_cross(vec3 a, vec3 b, vec3 d);
CGLM_EXPORT CGLM_EXPORT
float float
glmc_vec_norm(vec3 vec); glmc_vec3_norm(vec3 v);
CGLM_EXPORT CGLM_EXPORT
float float
glmc_vec_norm2(vec3 vec); glmc_vec3_norm2(vec3 v);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_normalize_to(vec3 vec, vec3 dest); glmc_vec3_normalize_to(vec3 v, vec3 dest);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_normalize(vec3 v); glmc_vec3_normalize(vec3 v);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_add(vec3 v1, vec3 v2, vec3 dest); glmc_vec3_add(vec3 a, vec3 b, vec3 dest);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_sub(vec3 v1, vec3 v2, vec3 dest); glmc_vec3_adds(vec3 v, float s, vec3 dest);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_scale(vec3 v, float s, vec3 dest); glmc_vec3_sub(vec3 a, vec3 b, vec3 dest);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_scale_as(vec3 v, float s, vec3 dest); glmc_vec3_subs(vec3 v, float s, vec3 dest);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_flipsign(vec3 v); glmc_vec3_mul(vec3 a, vec3 b, vec3 d);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_inv(vec3 v); glmc_vec3_scale(vec3 v, float s, vec3 dest);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_inv_to(vec3 v, vec3 dest); glmc_vec3_scale_as(vec3 v, float s, vec3 dest);
CGLM_EXPORT
void
glmc_vec3_div(vec3 a, vec3 b, vec3 dest);
CGLM_EXPORT
void
glmc_vec3_divs(vec3 a, float s, vec3 dest);
CGLM_EXPORT
void
glmc_vec3_addadd(vec3 a, vec3 b, vec3 dest);
CGLM_EXPORT
void
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 CGLM_EXPORT
float float
glmc_vec_angle(vec3 v1, vec3 v2); glmc_vec3_angle(vec3 a, vec3 b);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_rotate(vec3 v, float angle, vec3 axis); glmc_vec3_rotate(vec3 v, float angle, vec3 axis);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_rotate_m4(mat4 m, vec3 v, vec3 dest); glmc_vec3_rotate_m4(mat4 m, vec3 v, vec3 dest);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_proj(vec3 a, vec3 b, vec3 dest); glmc_vec3_rotate_m3(mat3 m, vec3 v, vec3 dest);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_center(vec3 v1, vec3 v2, vec3 dest); glmc_vec3_proj(vec3 a, vec3 b, vec3 dest);
CGLM_EXPORT
void
glmc_vec3_center(vec3 a, vec3 b, vec3 dest);
CGLM_EXPORT CGLM_EXPORT
float float
glmc_vec_distance(vec3 v1, vec3 v2); glmc_vec3_distance2(vec3 a, vec3 b);
CGLM_EXPORT
float
glmc_vec3_distance(vec3 a, vec3 b);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_maxv(vec3 v1, vec3 v2, vec3 dest); glmc_vec3_maxv(vec3 a, vec3 b, vec3 dest);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_minv(vec3 v1, vec3 v2, vec3 dest); 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 #ifdef __cplusplus
} }

View File

@@ -16,30 +16,50 @@ extern "C" {
/* DEPRECATED! use _copy, _ucopy versions */ /* DEPRECATED! use _copy, _ucopy versions */
#define glmc_vec4_dup3(v, dest) glmc_vec4_copy3(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_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 CGLM_EXPORT
void 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 CGLM_EXPORT
void void
glmc_vec4_copy(vec4 v, vec4 dest); glmc_vec4_copy(vec4 v, vec4 dest);
CGLM_EXPORT
void
glmc_vec4_ucopy(vec4 v, vec4 dest);
CGLM_EXPORT CGLM_EXPORT
float float
glmc_vec4_dot(vec4 a, vec4 b); glmc_vec4_dot(vec4 a, vec4 b);
CGLM_EXPORT CGLM_EXPORT
float float
glmc_vec4_norm(vec4 vec); glmc_vec4_norm(vec4 v);
CGLM_EXPORT CGLM_EXPORT
float float
glmc_vec4_norm2(vec4 vec); glmc_vec4_norm2(vec4 v);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec4_normalize_to(vec4 vec, vec4 dest); glmc_vec4_normalize_to(vec4 v, vec4 dest);
CGLM_EXPORT CGLM_EXPORT
void void
@@ -47,11 +67,23 @@ glmc_vec4_normalize(vec4 v);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec4_add(vec4 v1, vec4 v2, vec4 dest); glmc_vec4_add(vec4 a, vec4 b, vec4 dest);
CGLM_EXPORT CGLM_EXPORT
void 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 CGLM_EXPORT
void void
@@ -63,27 +95,121 @@ glmc_vec4_scale_as(vec3 v, float s, vec3 dest);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec4_flipsign(vec4 v); glmc_vec4_div(vec4 a, vec4 b, vec4 dest);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec4_inv(vec4 v); glmc_vec4_divs(vec4 v, float s, vec4 dest);
CGLM_EXPORT CGLM_EXPORT
void 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 CGLM_EXPORT
float float
glmc_vec4_distance(vec4 v1, vec4 v2); glmc_vec4_distance(vec4 a, vec4 b);
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec4_maxv(vec4 v1, vec4 v2, vec4 dest); glmc_vec4_maxv(vec4 a, vec4 b, vec4 dest);
CGLM_EXPORT CGLM_EXPORT
void 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);
/* 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 #ifdef __cplusplus
} }

View File

@@ -198,26 +198,15 @@ glm_ortho_aabb_pz(vec3 box[2], float padding, mat4 dest) {
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_ortho_default(float aspect, glm_ortho_default(float aspect, mat4 dest) {
mat4 dest) {
if (aspect >= 1.0f) { if (aspect >= 1.0f) {
glm_ortho(-1.0f * aspect, glm_ortho(-aspect, aspect, -1.0f, 1.0f, -100.0f, 100.0f, dest);
1.0f * aspect,
-1.0f,
1.0f,
-100.0f,
100.0f,
dest);
return; return;
} }
glm_ortho(-1.0f, aspect = 1.0f / aspect;
1.0f,
-1.0f / aspect, glm_ortho(-1.0f, 1.0f, -aspect, aspect, -100.0f, 100.0f, dest);
1.0f / aspect,
-100.0f,
100.0f,
dest);
} }
/*! /*!
@@ -291,13 +280,8 @@ glm_perspective(float fovy,
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_perspective_default(float aspect, glm_perspective_default(float aspect, mat4 dest) {
mat4 dest) { glm_perspective(GLM_PI_4f, aspect, 0.01f, 100.0f, dest);
glm_perspective((float)CGLM_PI_4,
aspect,
0.01f,
100.0f,
dest);
} }
/*! /*!
@@ -310,8 +294,7 @@ glm_perspective_default(float aspect,
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_perspective_resize(float aspect, glm_perspective_resize(float aspect, mat4 proj) {
mat4 proj) {
if (proj[0][0] == 0.0f) if (proj[0][0] == 0.0f)
return; return;
@@ -321,6 +304,9 @@ glm_perspective_resize(float aspect,
/*! /*!
* @brief set up view matrix * @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] eye eye vector
* @param[in] center center vector * @param[in] center center vector
* @param[in] up up vector * @param[in] up up vector
@@ -332,15 +318,15 @@ glm_lookat(vec3 eye,
vec3 center, vec3 center,
vec3 up, vec3 up,
mat4 dest) { mat4 dest) {
vec3 f, u, s; CGLM_ALIGN(8) vec3 f, u, s;
glm_vec_sub(center, eye, f); glm_vec3_sub(center, eye, f);
glm_vec_normalize(f); glm_vec3_normalize(f);
glm_vec_cross(f, up, s); glm_vec3_cross(f, up, s);
glm_vec_normalize(s); glm_vec3_normalize(s);
glm_vec_cross(s, f, u); glm_vec3_cross(s, f, u);
dest[0][0] = s[0]; dest[0][0] = s[0];
dest[0][1] = u[0]; dest[0][1] = u[0];
@@ -351,9 +337,9 @@ glm_lookat(vec3 eye,
dest[2][0] = s[2]; dest[2][0] = s[2];
dest[2][1] = u[2]; dest[2][1] = u[2];
dest[2][2] =-f[2]; dest[2][2] =-f[2];
dest[3][0] =-glm_vec_dot(s, eye); dest[3][0] =-glm_vec3_dot(s, eye);
dest[3][1] =-glm_vec_dot(u, eye); dest[3][1] =-glm_vec3_dot(u, eye);
dest[3][2] = glm_vec_dot(f, eye); dest[3][2] = glm_vec3_dot(f, eye);
dest[0][3] = dest[1][3] = dest[2][3] = 0.0f; dest[0][3] = dest[1][3] = dest[2][3] = 0.0f;
dest[3][3] = 1.0f; dest[3][3] = 1.0f;
} }
@@ -364,6 +350,9 @@ glm_lookat(vec3 eye,
* convenient wrapper for lookat: if you only have direction not target self * 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. * 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] eye eye vector
* @param[in] dir direction vector * @param[in] dir direction vector
* @param[in] up up vector * @param[in] up up vector
@@ -372,8 +361,8 @@ glm_lookat(vec3 eye,
CGLM_INLINE CGLM_INLINE
void void
glm_look(vec3 eye, vec3 dir, vec3 up, mat4 dest) { glm_look(vec3 eye, vec3 dir, vec3 up, mat4 dest) {
vec3 target; CGLM_ALIGN(8) vec3 target;
glm_vec_add(eye, dir, target); glm_vec3_add(eye, dir, target);
glm_lookat(eye, target, up, dest); glm_lookat(eye, target, up, dest);
} }
@@ -390,8 +379,8 @@ glm_look(vec3 eye, vec3 dir, vec3 up, mat4 dest) {
CGLM_INLINE CGLM_INLINE
void void
glm_look_anyup(vec3 eye, vec3 dir, mat4 dest) { glm_look_anyup(vec3 eye, vec3 dir, mat4 dest) {
vec3 up; CGLM_ALIGN(8) vec3 up;
glm_vec_ortho(dir, up); glm_vec3_ortho(dir, up);
glm_look(eye, dir, up, dest); glm_look(eye, dir, up, dest);
} }

View File

@@ -23,5 +23,8 @@
#include "color.h" #include "color.h"
#include "util.h" #include "util.h"
#include "io.h" #include "io.h"
#include "project.h"
#include "sphere.h"
#include "ease.h"
#endif /* cglm_h */ #endif /* cglm_h */

View File

@@ -14,7 +14,7 @@
#include <math.h> #include <math.h>
#include <float.h> #include <float.h>
#if defined(_WIN32) #if defined(_MSC_VER)
# ifdef CGLM_DLL # ifdef CGLM_DLL
# define CGLM_EXPORT __declspec(dllexport) # define CGLM_EXPORT __declspec(dllexport)
# else # else

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,6 +5,14 @@
* Full license can be found in the LICENSE file * 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: Types:
enum glm_euler_sq enum glm_euler_sq
@@ -13,6 +21,7 @@
CGLM_INLINE glm_euler_sq glm_euler_order(int newOrder[3]); 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_angles(mat4 m, vec3 dest);
CGLM_INLINE void glm_euler(vec3 angles, mat4 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_zyx(vec3 angles, mat4 dest);
CGLM_INLINE void glm_euler_zxy(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_xzy(vec3 angles, mat4 dest);
@@ -61,205 +70,115 @@ glm_euler_order(int ord[3]) {
CGLM_INLINE CGLM_INLINE
void void
glm_euler_angles(mat4 m, vec3 dest) { glm_euler_angles(mat4 m, vec3 dest) {
if (m[0][2] < 1.0f) { float m00, m01, m10, m11, m20, m21, m22;
if (m[0][2] > -1.0f) { float thetaX, thetaY, thetaZ;
vec3 a[2];
float cy1, cy2;
int path;
a[0][1] = asinf(-m[0][2]); m00 = m[0][0]; m10 = m[1][0]; m20 = m[2][0];
a[1][1] = CGLM_PI - a[0][1]; m01 = m[0][1]; m11 = m[1][1]; m21 = m[2][1];
m22 = m[2][2];
cy1 = cosf(a[0][1]); if (m20 < 1.0f) {
cy2 = cosf(a[1][1]); if (m20 > -1.0f) {
thetaY = asinf(m20);
a[0][0] = atan2f(m[1][2] / cy1, m[2][2] / cy1); thetaX = atan2f(-m21, m22);
a[1][0] = atan2f(m[1][2] / cy2, m[2][2] / cy2); thetaZ = atan2f(-m10, m00);
} else { /* m20 == -1 */
a[0][2] = atan2f(m[0][1] / cy1, m[0][0] / cy1); /* Not a unique solution */
a[1][2] = atan2f(m[0][1] / cy2, m[0][0] / cy2); thetaY = -GLM_PI_2f;
thetaX = -atan2f(m01, m11);
path = (fabsf(a[0][0]) + fabsf(a[0][1]) + fabsf(a[0][2])) >= thetaZ = 0.0f;
(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;
} }
} else { } else { /* m20 == +1 */
dest[0] = atan2f(-m[1][0], -m[2][0]); thetaY = GLM_PI_2f;
dest[1] =-CGLM_PI_2; thetaX = atan2f(m01, m11);
dest[2] = 0.0f; thetaZ = 0.0f;
} }
dest[0] = thetaX;
dest[1] = thetaY;
dest[2] = thetaZ;
} }
/*! /*!
* @brief build rotation matrix from euler angles * @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 * @param[out] dest rotation matrix
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_euler(vec3 angles, mat4 dest) { glm_euler(vec3 angles, mat4 dest) {
float cx, cy, cz, glm_euler_xyz(angles, dest);
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;
} }
/*! /*!
* @brief build rotation matrix from euler angles * @brief build rotation matrix from euler angles
* *
* @param[in] angles angles as vector [Ez, Ey, Ex] * @param[in] angles angles as vector [Xangle, Yangle, Zangle]
* @param[out] dest rotation matrix * @param[out] dest rotation matrix
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_euler_zyx(vec3 angles, glm_euler_xzy(vec3 angles, mat4 dest) {
mat4 dest) {
float cx, cy, cz, float cx, cy, cz,
sx, sy, sz; sx, sy, sz, sxsy, cysx, cxsy, cxcy;
sx = sinf(angles[0]); cx = cosf(angles[0]); sx = sinf(angles[0]); cx = cosf(angles[0]);
sy = sinf(angles[1]); cy = cosf(angles[1]); sy = sinf(angles[1]); cy = cosf(angles[1]);
sz = sinf(angles[2]); cz = cosf(angles[2]); sz = sinf(angles[2]); cz = cosf(angles[2]);
sxsy = sx * sy;
cysx = cy * sx;
cxsy = cx * sy;
cxcy = cx * cy;
dest[0][0] = cy * cz; dest[0][0] = cy * cz;
dest[0][1] = cz * sx * sy + cx * sz; dest[0][1] = sxsy + cxcy * sz;
dest[0][2] =-cx * cz * sy + sx * sz; dest[0][2] = -cxsy + cysx * sz;
dest[1][0] =-cy * sz; dest[1][0] = -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;
}
/*!
* @brief build rotation matrix from euler angles
*
* @param[in] angles angles as vector [Ez, Ex, Ey]
* @param[out] dest rotation matrix
*/
CGLM_INLINE
void
glm_euler_zxy(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 + 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;
}
/*!
* @brief build rotation matrix from euler angles
*
* @param[in] angles angles as vector [Ex, Ez, Ey]
* @param[out] dest rotation matrix
*/
CGLM_INLINE
void
glm_euler_xzy(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] = 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;
}
/*!
* @brief build rotation matrix from euler angles
*
* @param[in] angles angles as vector [Ey, Ez, Ex]
* @param[out] dest rotation matrix
*/
CGLM_INLINE
void
glm_euler_yzx(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] = sx * sy + cx * cy * sz;
dest[0][2] =-cx * sy + cy * sx * sz;
dest[1][0] =-sz;
dest[1][1] = cx * cz; dest[1][1] = cx * cz;
dest[1][2] = cz * sx; dest[1][2] = cz * sx;
dest[2][0] = cz * sy; dest[2][0] = cz * sy;
dest[2][1] =-cy * sx + cx * sy * sz; dest[2][1] = -cysx + cxsy * sz;
dest[2][2] = cx * cy + sx * sy * sz; dest[2][2] = cxcy + sxsy * sz;
dest[0][3] = 0.0f; dest[0][3] = 0.0f;
dest[1][3] = 0.0f; dest[1][3] = 0.0f;
dest[2][3] = 0.0f; dest[2][3] = 0.0f;
@@ -269,31 +188,36 @@ glm_euler_yzx(vec3 angles,
dest[3][3] = 1.0f; dest[3][3] = 1.0f;
} }
/*! /*!
* @brief build rotation matrix from euler angles * @brief build rotation matrix from euler angles
* *
* @param[in] angles angles as vector [Ey, Ex, Ez] * @param[in] angles angles as vector [Xangle, Yangle, Zangle]
* @param[out] dest rotation matrix * @param[out] dest rotation matrix
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_euler_yxz(vec3 angles, glm_euler_yxz(vec3 angles, mat4 dest) {
mat4 dest) {
float cx, cy, cz, float cx, cy, cz,
sx, sy, sz; sx, sy, sz, cycz, sysz, czsy, cysz;
sx = sinf(angles[0]); cx = cosf(angles[0]); sx = sinf(angles[0]); cx = cosf(angles[0]);
sy = sinf(angles[1]); cy = cosf(angles[1]); sy = sinf(angles[1]); cy = cosf(angles[1]);
sz = sinf(angles[2]); cz = cosf(angles[2]); sz = sinf(angles[2]); cz = cosf(angles[2]);
dest[0][0] = cy * cz - sx * sy * sz; cycz = cy * cz;
dest[0][1] = cz * sx * sy + cy * sz; sysz = sy * sz;
dest[0][2] =-cx * sy; czsy = cz * sy;
dest[1][0] =-cx * sz; 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][1] = cx * cz;
dest[1][2] = sx; dest[1][2] = cycz * sx + sysz;
dest[2][0] = cz * sy + cy * sx * sz; dest[2][0] = cx * sy;
dest[2][1] =-cy * cz * sx + sy * sz; dest[2][1] = -sx;
dest[2][2] = cx * cy; dest[2][2] = cx * cy;
dest[0][3] = 0.0f; dest[0][3] = 0.0f;
dest[1][3] = 0.0f; dest[1][3] = 0.0f;
@@ -307,7 +231,122 @@ glm_euler_yxz(vec3 angles,
/*! /*!
* @brief build rotation matrix from euler angles * @brief build rotation matrix from euler angles
* *
* @param[in] angles angles as vector (ord parameter spceifies angles order) * @param[in] angles angles as vector [Xangle, Yangle, Zangle]
* @param[out] dest rotation matrix
*/
CGLM_INLINE
void
glm_euler_yzx(vec3 angles, mat4 dest) {
float cx, cy, cz,
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]);
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_zxy(vec3 angles, mat4 dest) {
float cx, cy, cz,
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]);
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_zyx(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] = 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[in] ord euler order
* @param[out] dest rotation matrix * @param[out] dest rotation matrix
*/ */
@@ -332,71 +371,71 @@ glm_euler_by_order(vec3 angles, glm_euler_sq ord, mat4 dest) {
sysz = sy * sz; sysz = sy * sz;
switch (ord) { switch (ord) {
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;
case GLM_EULER_XZY: case GLM_EULER_XZY:
dest[0][0] = cycz; dest[0][0] = cycz;
dest[0][1] = sz; dest[0][1] = sx * sy + cx * cysz;
dest[0][2] =-czsy; dest[0][2] = -cx * sy + cysx * sz;
dest[1][0] = sx * sy - cx * cysz; dest[1][0] = -sz;
dest[1][1] = cxcz; dest[1][1] = cxcz;
dest[1][2] = cysx + cx * sysz; dest[1][2] = czsx;
dest[2][0] = cx * sy + cysx * sz; dest[2][0] = czsy;
dest[2][1] =-czsx; dest[2][1] = -cysx + cx * sysz;
dest[2][2] = cxcy - sx * sysz; dest[2][2] = cxcy + sx * sysz;
break; break;
case GLM_EULER_ZXY: 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][0] = cycz + sx * sysz;
dest[0][1] = cxsz; dest[0][1] = cxsz;
dest[0][2] =-czsy + cysx * sz; dest[0][2] = -czsy + cysx * sz;
dest[1][0] = czsx * sy - cysz; dest[1][0] = czsx * sy - cysz;
dest[1][1] = cxcz; dest[1][1] = cxcz;
dest[1][2] = cycz * sx + sysz; dest[1][2] = cycz * sx + sysz;
dest[2][0] = cx * sy; dest[2][0] = cx * sy;
dest[2][1] =-sx; 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;
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[2][2] = cxcy;
break; break;
case GLM_EULER_YZX: case GLM_EULER_YZX:
dest[0][0] = cycz; dest[0][0] = cycz;
dest[0][1] = sx * sy + cx * cysz; dest[0][1] = sz;
dest[0][2] =-cx * sy + cysx * sz; dest[0][2] = -czsy;
dest[1][0] =-sz; dest[1][0] = sx * sy - cx * cysz;
dest[1][1] = cxcz; dest[1][1] = cxcz;
dest[1][2] = czsx; dest[1][2] = cysx + cx * sysz;
dest[2][0] = czsy; dest[2][0] = cx * sy + cysx * sz;
dest[2][1] =-cysx + cx * sysz; dest[2][1] = -czsx;
dest[2][2] = cxcy + sx * sysz; 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; break;
} }

View File

@@ -10,6 +10,9 @@
#include "common.h" #include "common.h"
#include "plane.h" #include "plane.h"
#include "vec3.h"
#include "vec4.h"
#include "mat4.h"
#define GLM_LBN 0 /* left bottom near */ #define GLM_LBN 0 /* left bottom near */
#define GLM_LTN 1 /* left top near */ #define GLM_LTN 1 /* left top near */
@@ -103,7 +106,7 @@ glm_frustum_planes(mat4 m, vec4 dest[6]) {
* *
* Find center coordinates: * Find center coordinates:
* for (j = 0; j < 4; j++) { * 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) * @param[in] invMat matrix (see brief)
@@ -184,8 +187,8 @@ glm_frustum_box(vec4 corners[8], mat4 m, vec3 box[2]) {
vec3 min, max; vec3 min, max;
int i; int i;
glm_vec_broadcast(FLT_MAX, min); glm_vec3_broadcast(FLT_MAX, min);
glm_vec_broadcast(-FLT_MAX, max); glm_vec3_broadcast(-FLT_MAX, max);
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
glm_mat4_mulv(m, corners[i], v); 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]); max[2] = glm_max(max[2], v[2]);
} }
glm_vec_copy(min, box[0]); glm_vec3_copy(min, box[0]);
glm_vec_copy(max, box[1]); glm_vec3_copy(max, box[1]);
} }
/*! /*!
@@ -225,7 +228,7 @@ glm_frustum_corners_at(vec4 corners[8],
float dist, sc; float dist, sc;
/* because distance and scale is same for all */ /* 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); sc = dist * (splitDist / farDist);
/* left bottom */ /* left bottom */

View File

@@ -171,4 +171,33 @@ glm_versor_print(versor vec,
#undef m #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 */ #endif /* cglm_io_h */

View File

@@ -16,6 +16,7 @@
Functions: Functions:
CGLM_INLINE void glm_mat3_copy(mat3 mat, mat3 dest); CGLM_INLINE void glm_mat3_copy(mat3 mat, mat3 dest);
CGLM_INLINE void glm_mat3_identity(mat3 mat); 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_mul(mat3 m1, mat3 m2, mat3 dest); 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_to(mat3 m, mat3 dest);
CGLM_INLINE void glm_mat3_transpose(mat3 m); CGLM_INLINE void glm_mat3_transpose(mat3 m);
@@ -31,6 +32,7 @@
#define cglm_mat3_h #define cglm_mat3_h
#include "common.h" #include "common.h"
#include "vec3.h"
#ifdef CGLM_SSE_FP #ifdef CGLM_SSE_FP
# include "simd/sse2/mat3.h" # include "simd/sse2/mat3.h"
@@ -80,10 +82,29 @@ glm_mat3_copy(mat3 mat, mat3 dest) {
CGLM_INLINE CGLM_INLINE
void void
glm_mat3_identity(mat3 mat) { 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); 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 multiply m1 and m2 to dest * @brief multiply m1 and m2 to dest
* *
@@ -154,7 +175,7 @@ glm_mat3_transpose_to(mat3 m, mat3 dest) {
CGLM_INLINE CGLM_INLINE
void void
glm_mat3_transpose(mat3 m) { glm_mat3_transpose(mat3 m) {
mat3 tmp; CGLM_ALIGN_MAT mat3 tmp;
tmp[0][1] = m[1][0]; tmp[0][1] = m[1][0];
tmp[0][2] = m[2][0]; tmp[0][2] = m[2][0];
@@ -186,6 +207,56 @@ 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]; dest[2] = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[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 * @brief scale (multiply with scalar) matrix
* *
@@ -259,9 +330,9 @@ CGLM_INLINE
void void
glm_mat3_swap_col(mat3 mat, int col1, int col2) { glm_mat3_swap_col(mat3 mat, int col1, int col2) {
vec3 tmp; vec3 tmp;
glm_vec_copy(mat[col1], tmp); glm_vec3_copy(mat[col1], tmp);
glm_vec_copy(mat[col2], mat[col1]); glm_vec3_copy(mat[col2], mat[col1]);
glm_vec_copy(tmp, mat[col2]); glm_vec3_copy(tmp, mat[col2]);
} }
/*! /*!

View File

@@ -16,13 +16,12 @@
GLM_MAT4_ZERO_INIT GLM_MAT4_ZERO_INIT
GLM_MAT4_IDENTITY GLM_MAT4_IDENTITY
GLM_MAT4_ZERO GLM_MAT4_ZERO
glm_mat4_udup(mat, dest)
glm_mat4_dup(mat, dest)
Functions: Functions:
CGLM_INLINE void glm_mat4_ucopy(mat4 mat, mat4 dest); 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_copy(mat4 mat, mat4 dest);
CGLM_INLINE void glm_mat4_identity(mat4 mat); 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_pick3(mat4 mat, mat3 dest); 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_pick3t(mat4 mat, mat3 dest);
CGLM_INLINE void glm_mat4_ins3(mat3 mat, mat4 dest); CGLM_INLINE void glm_mat4_ins3(mat3 mat, mat4 dest);
@@ -45,6 +44,8 @@
#define cglm_mat_h #define cglm_mat_h
#include "common.h" #include "common.h"
#include "vec4.h"
#include "vec3.h"
#ifdef CGLM_SSE_FP #ifdef CGLM_SSE_FP
# include "simd/sse2/mat4.h" # include "simd/sse2/mat4.h"
@@ -58,7 +59,9 @@
# include "simd/neon/mat4.h" # include "simd/neon/mat4.h"
#endif #endif
#include <assert.h> #ifdef DEBUG
# include <assert.h>
#endif
#define GLM_MAT4_IDENTITY_INIT {{1.0f, 0.0f, 0.0f, 0.0f}, \ #define GLM_MAT4_IDENTITY_INIT {{1.0f, 0.0f, 0.0f, 0.0f}, \
{0.0f, 1.0f, 0.0f, 0.0f}, \ {0.0f, 1.0f, 0.0f, 0.0f}, \
@@ -106,13 +109,13 @@ CGLM_INLINE
void void
glm_mat4_copy(mat4 mat, mat4 dest) { glm_mat4_copy(mat4 mat, mat4 dest) {
#ifdef __AVX__ #ifdef __AVX__
_mm256_store_ps(dest[0], _mm256_load_ps(mat[0])); glmm_store256(dest[0], glmm_load256(mat[0]));
_mm256_store_ps(dest[2], _mm256_load_ps(mat[2])); glmm_store256(dest[2], glmm_load256(mat[2]));
#elif defined( __SSE__ ) || defined( __SSE2__ ) #elif defined( __SSE__ ) || defined( __SSE2__ )
_mm_store_ps(dest[0], _mm_load_ps(mat[0])); glmm_store(dest[0], glmm_load(mat[0]));
_mm_store_ps(dest[1], _mm_load_ps(mat[1])); glmm_store(dest[1], glmm_load(mat[1]));
_mm_store_ps(dest[2], _mm_load_ps(mat[2])); glmm_store(dest[2], glmm_load(mat[2]));
_mm_store_ps(dest[3], _mm_load_ps(mat[3])); glmm_store(dest[3], glmm_load(mat[3]));
#else #else
glm_mat4_ucopy(mat, dest); glm_mat4_ucopy(mat, dest);
#endif #endif
@@ -135,10 +138,29 @@ glm_mat4_copy(mat4 mat, mat4 dest) {
CGLM_INLINE CGLM_INLINE
void void
glm_mat4_identity(mat4 mat) { 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); 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 copy upper-left of mat4 to mat3 * @brief copy upper-left of mat4 to mat3
* *
@@ -281,19 +303,17 @@ glm_mat4_mul(mat4 m1, mat4 m2, mat4 dest) {
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_mat4_mulN(mat4 * __restrict matrices[], int len, mat4 dest) { glm_mat4_mulN(mat4 * __restrict matrices[], uint32_t len, mat4 dest) {
int i; uint32_t i;
#ifdef DEBUG
assert(len > 1 && "there must be least 2 matrices to go!"); assert(len > 1 && "there must be least 2 matrices to go!");
#endif
glm_mat4_mul(*matrices[0], glm_mat4_mul(*matrices[0], *matrices[1], dest);
*matrices[1],
dest);
for (i = 2; i < len; i++) for (i = 2; i < len; i++)
glm_mat4_mul(dest, glm_mat4_mul(dest, *matrices[i], dest);
*matrices[i],
dest);
} }
/*! /*!
@@ -319,20 +339,69 @@ glm_mat4_mulv(mat4 m, vec4 v, vec4 dest) {
} }
/*! /*!
* @brief multiply vector with mat4's mat3 part(rotation) * @brief convert mat4's rotation part to quaternion
* *
* @param[in] m mat4(affine transform) * @param[in] m affine matrix
* @param[in] v vec3 * @param[out] dest destination quaternion
* @param[out] dest vec3
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_mat4_mulv3(mat4 m, vec3 v, vec3 dest) { glm_mat4_quat(mat4 m, versor dest) {
vec3 res; float trace, r, rinv;
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]; /* it seems using like m12 instead of m[1][2] causes extra instructions */
res[2] = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2];
glm_vec_copy(res, dest); 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);
} }
/*! /*!
@@ -535,7 +604,7 @@ glm_mat4_inv_fast(mat4 mat, mat4 dest) {
CGLM_INLINE CGLM_INLINE
void void
glm_mat4_swap_col(mat4 mat, int col1, int col2) { 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[col1], tmp);
glm_vec4_copy(mat[col2], mat[col1]); glm_vec4_copy(mat[col2], mat[col1]);
glm_vec4_copy(tmp, mat[col2]); glm_vec4_copy(tmp, mat[col2]);
@@ -551,7 +620,7 @@ glm_mat4_swap_col(mat4 mat, int col1, int col2) {
CGLM_INLINE CGLM_INLINE
void void
glm_mat4_swap_row(mat4 mat, int row1, int row2) { glm_mat4_swap_row(mat4 mat, int row1, int row2) {
vec4 tmp; CGLM_ALIGN(16) vec4 tmp;
tmp[0] = mat[0][row1]; tmp[0] = mat[0][row1];
tmp[1] = mat[1][row1]; tmp[1] = mat[1][row1];
tmp[2] = mat[2][row1]; tmp[2] = mat[2][row1];
@@ -568,5 +637,4 @@ glm_mat4_swap_row(mat4 mat, int row1, int row2) {
mat[3][row2] = tmp[3]; mat[3][row2] = tmp[3];
} }
#else
#endif /* cglm_mat_h */ #endif /* cglm_mat_h */

View File

@@ -9,9 +9,7 @@
#define cglm_plane_h #define cglm_plane_h
#include "common.h" #include "common.h"
#include "mat4.h"
#include "vec4.h" #include "vec4.h"
#include "vec3.h"
/* /*
Plane equation: Ax + By + Cz + D = 0; Plane equation: Ax + By + Cz + D = 0;
@@ -32,7 +30,7 @@
CGLM_INLINE CGLM_INLINE
void void
glm_plane_normalize(vec4 plane) { 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 */ #endif /* cglm_plane_h */

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

@@ -0,0 +1,117 @@
/*
* 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 "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

@@ -12,40 +12,83 @@
Functions: Functions:
CGLM_INLINE void glm_quat_identity(versor q); 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_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_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 float glm_quat_norm(versor q);
CGLM_INLINE void glm_quat_normalize(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_normalize_to(versor q, versor dest);
CGLM_INLINE void glm_quat_mulv(versor q1, versor q2, 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, versor 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_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_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 #ifndef cglm_quat_h
#define cglm_quat_h #define cglm_quat_h
#include "common.h" #include "common.h"
#include "vec3.h"
#include "vec4.h" #include "vec4.h"
#include "mat4.h"
#include "mat3.h"
#include "affine-mat.h"
#ifdef CGLM_SSE_FP #ifdef CGLM_SSE_FP
# include "simd/sse2/quat.h" # include "simd/sse2/quat.h"
#endif #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): * it was [w, x, y, z] before v0.3.6 it has been changed to [x, y, z, w]
* - versor is identity quat, we can define new type for quat. * with v0.3.6 version.
* 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
*/ */
#define GLM_QUAT_IDENTITY_INIT {1.0f, 0.0f, 0.0f, 0.0f} #define GLM_QUAT_IDENTITY_INIT {0.0f, 0.0f, 0.0f, 1.0f}
#define GLM_QUAT_IDENTITY ((versor)GLM_QUAT_IDENTITY_INIT) #define GLM_QUAT_IDENTITY ((versor)GLM_QUAT_IDENTITY_INIT)
/*! /*!
@@ -56,10 +99,72 @@
CGLM_INLINE CGLM_INLINE
void void
glm_quat_identity(versor q) { 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); 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 * @brief creates NEW quaternion with individual axis components
* *
@@ -71,45 +176,21 @@ glm_quat_identity(versor q) {
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_quat(versor q, glm_quat(versor q, float angle, float x, float y, float z) {
float angle, CGLM_ALIGN(8) vec3 axis = {x, y, z};
float x, glm_quatv(q, angle, axis);
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;
} }
/*! /*!
* @brief creates NEW quaternion with axis vector * @brief copy quaternion to another one
* *
* @param[out] q quaternion * @param[in] q quaternion
* @param[in] angle angle (radians) * @param[out] dest destination
* @param[in] v axis
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_quatv(versor q, glm_quat_copy(versor q, versor dest) {
float angle, glm_vec4_copy(q, dest);
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];
} }
/*! /*!
@@ -123,6 +204,43 @@ glm_quat_norm(versor q) {
return glm_vec4_norm(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_dot(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(q);
return;
}
glm_vec4_scale(q, 1.0f / sqrtf(dot), dest);
#endif
}
/*! /*!
* @brief normalize quaternion * @brief normalize quaternion
* *
@@ -131,45 +249,178 @@ glm_quat_norm(versor q) {
CGLM_INLINE CGLM_INLINE
void void
glm_quat_normalize(versor q) { glm_quat_normalize(versor q) {
float sum; glm_quat_normalize_to(q, q);
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);
} }
/*! /*!
* @brief dot product of two quaternion * @brief dot product of two quaternion
* *
* @param[in] q quaternion 1 * @param[in] p quaternion 1
* @param[in] r quaternion 2 * @param[in] q quaternion 2
*/ */
CGLM_INLINE CGLM_INLINE
float float
glm_quat_dot(versor q, versor r) { glm_quat_dot(versor p, versor q) {
return glm_vec4_dot(q, r); return glm_vec4_dot(p, q);
} }
/*! /*!
* @brief multiplies two quaternion and stores result in dest * @brief conjugate of quaternion
* *
* @param[in] q1 quaternion 1 * @param[in] q quaternion
* @param[in] q2 quaternion 2 * @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 * @param[out] dest result quaternion
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_quat_mulv(versor q1, versor q2, versor dest) { glm_quat_add(versor p, versor q, versor dest) {
dest[0] = q2[0] * q1[0] - q2[1] * q1[1] - q2[2] * q1[2] - q2[3] * q1[3]; glm_vec4_add(p, q, dest);
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); /*!
* @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, versor dest) {
glm_quat_imagn(q, 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
* @param[out] dest result quaternion
*/
CGLM_INLINE
void
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 CGLM_INLINE
void void
glm_quat_mat4(versor q, mat4 dest) { glm_quat_mat4(versor q, mat4 dest) {
float w, x, y, z; float w, x, y, z,
float xx, yy, zz; xx, yy, zz,
float xy, yz, xz; xy, yz, xz,
float wx, wy, wz; wx, wy, wz, norm, s;
w = q[0]; norm = glm_quat_norm(q);
x = q[1]; s = norm > 0.0f ? 2.0f / norm : 0.0f;
y = q[2];
z = q[3];
xx = 2.0f * x * x; xy = 2.0f * x * y; wx = 2.0f * w * x; x = q[0];
yy = 2.0f * y * y; yz = 2.0f * y * z; wy = 2.0f * w * y; y = q[1];
zz = 2.0f * z * z; xz = 2.0f * x * z; wz = 2.0f * w * z; 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[0][0] = 1.0f - yy - zz;
dest[1][1] = 1.0f - xx - 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[2][1] = yz - wx;
dest[0][2] = xz - wy; dest[0][2] = xz - wy;
dest[1][3] = 0.0f;
dest[0][3] = 0.0f; dest[0][3] = 0.0f;
dest[1][3] = 0.0f;
dest[2][3] = 0.0f; dest[2][3] = 0.0f;
dest[3][0] = 0.0f; dest[3][0] = 0.0f;
dest[3][1] = 0.0f; dest[3][1] = 0.0f;
@@ -216,69 +470,343 @@ glm_quat_mat4(versor q, mat4 dest) {
dest[3][3] = 1.0f; 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 * @brief interpolates between two quaternions
* using spherical linear interpolation (SLERP) * using spherical linear interpolation (SLERP)
* *
* @param[in] q from * @param[in] from from
* @param[in] r to * @param[in] to to
* @param[in] t amout * @param[in] t amout
* @param[out] dest result quaternion * @param[out] dest result quaternion
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_quat_slerp(versor q, glm_quat_slerp(versor from, versor to, float t, versor dest) {
versor r, CGLM_ALIGN(16) vec4 q1, q2;
float t, float cosTheta, sinTheta, angle;
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;
cosTheta = glm_quat_dot(q, r); cosTheta = glm_quat_dot(from, to);
if (cosTheta < 0.0f) { glm_quat_copy(from, q1);
q[0] *= -1.0f;
q[1] *= -1.0f;
q[2] *= -1.0f;
q[3] *= -1.0f;
cosTheta = -cosTheta; if (fabsf(cosTheta) >= 1.0f) {
} glm_quat_copy(q1, dest);
if (fabs(cosTheta) >= 1.0f) {
dest[0] = q[0];
dest[1] = q[1];
dest[2] = q[2];
dest[3] = q[3];
return; 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 */ /* LERP to avoid zero division */
/* TODO: FLT_EPSILON vs 0.001? */ if (fabsf(sinTheta) < 0.001f) {
if (sinTheta < 0.001f) { glm_quat_lerp(from, to, t, dest);
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];
return; return;
} }
/* SLERP */ /* SLERP */
angle = acosf(cosTheta); angle = acosf(cosTheta);
a = sinf(c * angle); glm_vec4_scale(q1, sinf((1.0f - t) * angle), q1);
b = sinf(t * angle); glm_vec4_scale(to, sinf(t * angle), q2);
dest[0] = (q[0] * a + r[0] * b) / sinTheta; glm_vec4_add(q1, q2, q1);
dest[1] = (q[1] * a + r[1] * b) / sinTheta; glm_vec4_scale(q1, 1.0f / sinTheta, dest);
dest[2] = (q[2] * a + r[2] * b) / sinTheta; }
dest[3] = (q[3] * a + r[3] * b) / sinTheta;
#endif /*!
* @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 */ #endif /* cglm_quat_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; __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 */ y0 = glmm_load256(m2[0]); /* h g f e d c b a */
y1 = _mm256_load_ps(m2[2]); /* p o n m l k j i */ 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 */ y2 = glmm_load256(m1[0]); /* h g f e d c b a */
y3 = _mm256_load_ps(m1[2]); /* p o n m l k j i */ 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 */ /* 0x03: 0b00000011 */
y5 = _mm256_permute2f128_ps(y3, y3, 0b00000000); /* l k j i l k j i */ 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 */ /* 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 */ /* 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)); 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)); 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], glmm_store256(dest[0],
_mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6), _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6),
_mm256_mul_ps(y4, y8)), _mm256_mul_ps(y3, y7)),
_mm256_mul_ps(y5, y7))); _mm256_add_ps(_mm256_mul_ps(y4, y8),
_mm256_mul_ps(y5, y9))));
/* n n n n i i i i */ /* n n n n i i i i */
/* p p p p k k k k */ /* p p p p k k k k */
@@ -52,7 +55,7 @@ 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)); 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)); y9 = _mm256_permutevar_ps(y1, _mm256_set_epi32(2, 2, 2, 2, 3, 3, 3, 3));
_mm256_store_ps(dest[2], glmm_store256(dest[2],
_mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6), _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6),
_mm256_mul_ps(y3, y7)), _mm256_mul_ps(y3, y7)),
_mm256_add_ps(_mm256_mul_ps(y4, y8), _mm256_add_ps(_mm256_mul_ps(y4, y8),

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; __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 */ y0 = glmm_load256(m2[0]); /* h g f e d c b a */
y1 = _mm256_load_ps(m2[2]); /* p o n m l k j i */ 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 */ y2 = glmm_load256(m1[0]); /* h g f e d c b a */
y3 = _mm256_load_ps(m1[2]); /* p o n m l k j i */ 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 */ /* 0x03: 0b00000011 */
y5 = _mm256_permute2f128_ps(y3, y3, 0b00000011); /* l k j i p o n m */ 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 */ /* f f f f a a a a */
/* h h h h c c c c */ /* h h h h c c c c */
@@ -39,7 +40,7 @@ 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)); 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)); y9 = _mm256_permutevar_ps(y0, _mm256_set_epi32(2, 2, 2, 2, 3, 3, 3, 3));
_mm256_store_ps(dest[0], glmm_store256(dest[0],
_mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6), _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6),
_mm256_mul_ps(y3, y7)), _mm256_mul_ps(y3, y7)),
_mm256_add_ps(_mm256_mul_ps(y4, y8), _mm256_add_ps(_mm256_mul_ps(y4, y8),
@@ -54,7 +55,7 @@ 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)); 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)); y9 = _mm256_permutevar_ps(y1, _mm256_set_epi32(2, 2, 2, 2, 3, 3, 3, 3));
_mm256_store_ps(dest[2], glmm_store256(dest[2],
_mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6), _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6),
_mm256_mul_ps(y3, y7)), _mm256_mul_ps(y3, y7)),
_mm256_add_ps(_mm256_mul_ps(y4, y8), _mm256_add_ps(_mm256_mul_ps(y4, y8),

View File

@@ -8,28 +8,83 @@
#ifndef cglm_intrin_h #ifndef cglm_intrin_h
#define 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 # if (defined(_M_AMD64) || defined(_M_X64)) || _M_IX86_FP == 2
# ifndef __SSE2__
# define __SSE2__ # define __SSE2__
# endif
# elif _M_IX86_FP == 1 # elif _M_IX86_FP == 1
# ifndef __SSE__
# define __SSE__ # define __SSE__
# endif # 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 #endif
#if defined( __SSE__ ) || defined( __SSE2__ ) #if defined( __SSE__ ) || defined( __SSE2__ )
# include <xmmintrin.h> # include <xmmintrin.h>
# include <emmintrin.h> # include <emmintrin.h>
/* float */ /* OPTIONAL: You may save some instructions but latency (not sure) */
# define _mm_shuffle1_ps(a, z, y, x, w) \ #ifdef CGLM_USE_INT_DOMAIN
_mm_shuffle_ps(a, a, _MM_SHUFFLE(z, y, x, w)) # 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 _mm_shuffle1_ps1(a, x) \ #define glmm_shuff1x(xmm, x) glmm_shuff1(xmm, x, x, x, x)
_mm_shuffle_ps(a, a, _MM_SHUFFLE(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)), \
# 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) z1, y1, x1, w1)
static inline
__m128
glmm_dot(__m128 a, __m128 b) {
__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));
}
static inline
__m128
glmm_norm(__m128 a) {
return _mm_sqrt_ps(glmm_dot(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));
}
#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
#endif #endif
/* x86, x64 */ /* x86, x64 */
@@ -39,6 +94,15 @@
#ifdef __AVX__ #ifdef __AVX__
# define CGLM_AVX_FP 1 # define CGLM_AVX_FP 1
#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 #endif
/* ARM Neon */ /* ARM Neon */

View File

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

View File

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

View File

@@ -16,32 +16,32 @@
CGLM_INLINE CGLM_INLINE
void void
glm_mat4_scale_sse2(mat4 m, float s){ glm_mat4_scale_sse2(mat4 m, float s) {
__m128 x0; __m128 x0;
x0 = _mm_set1_ps(s); x0 = _mm_set1_ps(s);
_mm_store_ps(m[0], _mm_mul_ps(_mm_load_ps(m[0]), x0)); glmm_store(m[0], _mm_mul_ps(glmm_load(m[0]), x0));
_mm_store_ps(m[1], _mm_mul_ps(_mm_load_ps(m[1]), x0)); glmm_store(m[1], _mm_mul_ps(glmm_load(m[1]), x0));
_mm_store_ps(m[2], _mm_mul_ps(_mm_load_ps(m[2]), x0)); glmm_store(m[2], _mm_mul_ps(glmm_load(m[2]), x0));
_mm_store_ps(m[3], _mm_mul_ps(_mm_load_ps(m[3]), x0)); glmm_store(m[3], _mm_mul_ps(glmm_load(m[3]), x0));
} }
CGLM_INLINE CGLM_INLINE
void void
glm_mat4_transp_sse2(mat4 m, mat4 dest){ glm_mat4_transp_sse2(mat4 m, mat4 dest) {
__m128 r0, r1, r2, r3; __m128 r0, r1, r2, r3;
r0 = _mm_load_ps(m[0]); r0 = glmm_load(m[0]);
r1 = _mm_load_ps(m[1]); r1 = glmm_load(m[1]);
r2 = _mm_load_ps(m[2]); r2 = glmm_load(m[2]);
r3 = _mm_load_ps(m[3]); r3 = glmm_load(m[3]);
_MM_TRANSPOSE4_PS(r0, r1, r2, r3); _MM_TRANSPOSE4_PS(r0, r1, r2, r3);
_mm_store_ps(dest[0], r0); glmm_store(dest[0], r0);
_mm_store_ps(dest[1], r1); glmm_store(dest[1], r1);
_mm_store_ps(dest[2], r2); glmm_store(dest[2], r2);
_mm_store_ps(dest[3], r3); glmm_store(dest[3], r3);
} }
CGLM_INLINE CGLM_INLINE
@@ -51,36 +51,36 @@ glm_mat4_mul_sse2(mat4 m1, mat4 m2, mat4 dest) {
__m128 l0, l1, l2, l3, r; __m128 l0, l1, l2, l3, r;
l0 = _mm_load_ps(m1[0]); l0 = glmm_load(m1[0]);
l1 = _mm_load_ps(m1[1]); l1 = glmm_load(m1[1]);
l2 = _mm_load_ps(m1[2]); l2 = glmm_load(m1[2]);
l3 = _mm_load_ps(m1[3]); l3 = glmm_load(m1[3]);
r = _mm_load_ps(m2[0]); r = glmm_load(m2[0]);
_mm_store_ps(dest[0], glmm_store(dest[0],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), _mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0),
_mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), _mm_mul_ps(glmm_shuff1x(r, 1), l1)),
_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2), _mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 2), l2),
_mm_mul_ps(_mm_shuffle1_ps1(r, 3), l3)))); _mm_mul_ps(glmm_shuff1x(r, 3), l3))));
r = _mm_load_ps(m2[1]); r = glmm_load(m2[1]);
_mm_store_ps(dest[1], glmm_store(dest[1],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), _mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0),
_mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), _mm_mul_ps(glmm_shuff1x(r, 1), l1)),
_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2), _mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 2), l2),
_mm_mul_ps(_mm_shuffle1_ps1(r, 3), l3)))); _mm_mul_ps(glmm_shuff1x(r, 3), l3))));
r = _mm_load_ps(m2[2]); r = glmm_load(m2[2]);
_mm_store_ps(dest[2], glmm_store(dest[2],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), _mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0),
_mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), _mm_mul_ps(glmm_shuff1x(r, 1), l1)),
_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2), _mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 2), l2),
_mm_mul_ps(_mm_shuffle1_ps1(r, 3), l3)))); _mm_mul_ps(glmm_shuff1x(r, 3), l3))));
r = _mm_load_ps(m2[3]); r = glmm_load(m2[3]);
_mm_store_ps(dest[3], glmm_store(dest[3],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 0), l0), _mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0),
_mm_mul_ps(_mm_shuffle1_ps1(r, 1), l1)), _mm_mul_ps(glmm_shuff1x(r, 1), l1)),
_mm_add_ps(_mm_mul_ps(_mm_shuffle1_ps1(r, 2), l2), _mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 2), l2),
_mm_mul_ps(_mm_shuffle1_ps1(r, 3), l3)))); _mm_mul_ps(glmm_shuff1x(r, 3), l3))));
} }
CGLM_INLINE CGLM_INLINE
@@ -88,18 +88,14 @@ void
glm_mat4_mulv_sse2(mat4 m, vec4 v, vec4 dest) { glm_mat4_mulv_sse2(mat4 m, vec4 v, vec4 dest) {
__m128 x0, x1, x2; __m128 x0, x1, x2;
x0 = _mm_load_ps(v); x0 = glmm_load(v);
x1 = _mm_add_ps(_mm_mul_ps(_mm_load_ps(m[0]), x1 = _mm_add_ps(_mm_mul_ps(glmm_load(m[0]), glmm_shuff1x(x0, 0)),
_mm_shuffle1_ps1(x0, 0)), _mm_mul_ps(glmm_load(m[1]), glmm_shuff1x(x0, 1)));
_mm_mul_ps(_mm_load_ps(m[1]),
_mm_shuffle1_ps1(x0, 1)));
x2 = _mm_add_ps(_mm_mul_ps(_mm_load_ps(m[2]), x2 = _mm_add_ps(_mm_mul_ps(glmm_load(m[2]), glmm_shuff1x(x0, 2)),
_mm_shuffle1_ps1(x0, 2)), _mm_mul_ps(glmm_load(m[3]), glmm_shuff1x(x0, 3)));
_mm_mul_ps(_mm_load_ps(m[3]),
_mm_shuffle1_ps1(x0, 3)));
_mm_store_ps(dest, _mm_add_ps(x1, x2)); glmm_store(dest, _mm_add_ps(x1, x2));
} }
CGLM_INLINE CGLM_INLINE
@@ -108,10 +104,10 @@ glm_mat4_det_sse2(mat4 mat) {
__m128 r0, r1, r2, r3, x0, x1, x2; __m128 r0, r1, r2, r3, x0, x1, x2;
/* 127 <- 0, [square] det(A) = det(At) */ /* 127 <- 0, [square] det(A) = det(At) */
r0 = _mm_load_ps(mat[0]); /* d c b a */ r0 = glmm_load(mat[0]); /* d c b a */
r1 = _mm_load_ps(mat[1]); /* h g f e */ r1 = glmm_load(mat[1]); /* h g f e */
r2 = _mm_load_ps(mat[2]); /* l k j i */ r2 = glmm_load(mat[2]); /* l k j i */
r3 = _mm_load_ps(mat[3]); /* p o n m */ r3 = glmm_load(mat[3]); /* p o n m */
/* /*
t[1] = j * p - n * l; t[1] = j * p - n * l;
@@ -119,20 +115,20 @@ glm_mat4_det_sse2(mat4 mat) {
t[3] = i * p - m * l; t[3] = i * p - m * l;
t[4] = i * o - m * k; t[4] = i * o - m * k;
*/ */
x0 = _mm_sub_ps(_mm_mul_ps(_mm_shuffle1_ps(r2, 0, 0, 1, 1), x0 = _mm_sub_ps(_mm_mul_ps(glmm_shuff1(r2, 0, 0, 1, 1),
_mm_shuffle1_ps(r3, 2, 3, 2, 3)), glmm_shuff1(r3, 2, 3, 2, 3)),
_mm_mul_ps(_mm_shuffle1_ps(r3, 0, 0, 1, 1), _mm_mul_ps(glmm_shuff1(r3, 0, 0, 1, 1),
_mm_shuffle1_ps(r2, 2, 3, 2, 3))); glmm_shuff1(r2, 2, 3, 2, 3)));
/* /*
t[0] = k * p - o * l; t[0] = k * p - o * l;
t[0] = k * p - o * l; t[0] = k * p - o * l;
t[5] = i * n - m * j; t[5] = i * n - m * j;
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), x1 = _mm_sub_ps(_mm_mul_ps(glmm_shuff1(r2, 0, 0, 2, 2),
_mm_shuffle1_ps(r3, 1, 1, 3, 3)), glmm_shuff1(r3, 1, 1, 3, 3)),
_mm_mul_ps(_mm_shuffle1_ps(r3, 0, 0, 2, 2), _mm_mul_ps(glmm_shuff1(r3, 0, 0, 2, 2),
_mm_shuffle1_ps(r2, 1, 1, 3, 3))); glmm_shuff1(r2, 1, 1, 3, 3)));
/* /*
a * (f * t[0] - g * t[1] + h * t[2]) 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]) + c * (e * t[1] - f * t[3] + h * t[5])
- d * (e * t[2] - f * t[4] + g * 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_shuffle_ps(x1, x0, _MM_SHUFFLE(1, 0, 0, 0))),
_mm_mul_ps(_mm_shuffle1_ps(r1, 1, 1, 2, 2), _mm_mul_ps(glmm_shuff1(r1, 1, 1, 2, 2),
_mm_shuffle1_ps(x0, 3, 2, 2, 0))); glmm_shuff1(x0, 3, 2, 2, 0)));
x2 = _mm_add_ps(x2, 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)))); _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)); x2 = _mm_xor_ps(x2, _mm_set_ps(-0.f, 0.f, -0.f, 0.f));
x0 = _mm_mul_ps(r0, x2); x0 = _mm_mul_ps(r0, x2);
x0 = _mm_add_ps(x0, _mm_shuffle1_ps(x0, 0, 1, 2, 3)); x0 = _mm_add_ps(x0, glmm_shuff1(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, 1, 3, 3, 1));
return _mm_cvtss_f32(x0); 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; x0, x1, x2, x3, x4, x5, x6, x7;
/* 127 <- 0 */ /* 127 <- 0 */
r0 = _mm_load_ps(mat[0]); /* d c b a */ r0 = glmm_load(mat[0]); /* d c b a */
r1 = _mm_load_ps(mat[1]); /* h g f e */ r1 = glmm_load(mat[1]); /* h g f e */
r2 = _mm_load_ps(mat[2]); /* l k j i */ r2 = glmm_load(mat[2]); /* l k j i */
r3 = _mm_load_ps(mat[3]); /* p o n m */ 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 */ 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 */ x1 = glmm_shuff1(x0, 1, 3, 3, 3); /* l p p p */
x2 = _mm_shuffle1_ps(x0, 0, 2, 2, 2); /* k o o o */ 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 */ 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 */ 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)); 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_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 */ x5 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(1, 1, 1, 1)); /* f f j j */
/* t1[1] = j * p - n * l; /* 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)); 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 */ 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;
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; */ t3[5] = e * j - i * f; */
t5 = _mm_sub_ps(_mm_mul_ps(x6, x4), _mm_mul_ps(x7, x5)); 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 */ x0 = glmm_shuff2(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 */ x1 = glmm_shuff2(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 */ x2 = glmm_shuff2(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 */ 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]; 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_shuffle_ps(x0, x1, _MM_SHUFFLE(2, 0, 2, 0));
x0 = _mm_mul_ps(x0, r0); x0 = _mm_mul_ps(x0, r0);
x0 = _mm_add_ps(x0, _mm_shuffle1_ps(x0, 0, 1, 2, 3)); x0 = _mm_add_ps(x0, glmm_shuff1(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, 1, 0, 0, 1));
x0 = _mm_rcp_ps(x0); x0 = _mm_rcp_ps(x0);
_mm_store_ps(dest[0], _mm_mul_ps(v0, x0)); glmm_store(dest[0], _mm_mul_ps(v0, x0));
_mm_store_ps(dest[1], _mm_mul_ps(v1, x0)); glmm_store(dest[1], _mm_mul_ps(v1, x0));
_mm_store_ps(dest[2], _mm_mul_ps(v2, x0)); glmm_store(dest[2], _mm_mul_ps(v2, x0));
_mm_store_ps(dest[3], _mm_mul_ps(v3, x0)); glmm_store(dest[3], _mm_mul_ps(v3, x0));
} }
CGLM_INLINE CGLM_INLINE
@@ -290,14 +286,14 @@ glm_mat4_inv_sse2(mat4 mat, mat4 dest) {
x0, x1, x2, x3, x4, x5, x6, x7; x0, x1, x2, x3, x4, x5, x6, x7;
/* 127 <- 0 */ /* 127 <- 0 */
r0 = _mm_load_ps(mat[0]); /* d c b a */ r0 = glmm_load(mat[0]); /* d c b a */
r1 = _mm_load_ps(mat[1]); /* h g f e */ r1 = glmm_load(mat[1]); /* h g f e */
r2 = _mm_load_ps(mat[2]); /* l k j i */ r2 = glmm_load(mat[2]); /* l k j i */
r3 = _mm_load_ps(mat[3]); /* p o n m */ 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 */ 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 */ x1 = glmm_shuff1(x0, 1, 3, 3, 3); /* l p p p */
x2 = _mm_shuffle1_ps(x0, 0, 2, 2, 2); /* k o o o */ 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 */ 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 */ 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)); 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_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 */ x5 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(1, 1, 1, 1)); /* f f j j */
/* t1[1] = j * p - n * l; /* 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)); 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 */ 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;
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; */ t3[5] = e * j - i * f; */
t5 = _mm_sub_ps(_mm_mul_ps(x6, x4), _mm_mul_ps(x7, x5)); 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 */ x0 = glmm_shuff2(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 */ x1 = glmm_shuff2(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 */ x2 = glmm_shuff2(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 */ 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]; 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_shuffle_ps(x0, x1, _MM_SHUFFLE(2, 0, 2, 0));
x0 = _mm_mul_ps(x0, r0); x0 = _mm_mul_ps(x0, r0);
x0 = _mm_add_ps(x0, _mm_shuffle1_ps(x0, 0, 1, 2, 3)); x0 = _mm_add_ps(x0, glmm_shuff1(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, 1, 0, 0, 1));
x0 = _mm_div_ps(_mm_set1_ps(1.0f), x0); x0 = _mm_div_ps(_mm_set1_ps(1.0f), x0);
_mm_store_ps(dest[0], _mm_mul_ps(v0, x0)); glmm_store(dest[0], _mm_mul_ps(v0, x0));
_mm_store_ps(dest[1], _mm_mul_ps(v1, x0)); glmm_store(dest[1], _mm_mul_ps(v1, x0));
_mm_store_ps(dest[2], _mm_mul_ps(v2, x0)); glmm_store(dest[2], _mm_mul_ps(v2, x0));
_mm_store_ps(dest[3], _mm_mul_ps(v3, x0)); glmm_store(dest[3], _mm_mul_ps(v3, x0));
} }
#endif #endif

View File

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

View File

@@ -9,22 +9,75 @@
#define cglm_types_h #define cglm_types_h
#if defined(_MSC_VER) #if defined(_MSC_VER)
# define CGLM_ALIGN(X) /* __declspec(align(X)) */ /* do not use alignment for older visual studio versions */
#if _MSC_VER < 1913 /* Visual Studio 2017 version 15.6 */
# define CGLM_ALL_UNALIGNED
# define CGLM_ALIGN(X) /* no alignment */
#else
# define CGLM_ALIGN(X) __declspec(align(X))
#endif
#else #else
# define CGLM_ALIGN(X) __attribute((aligned(X))) # define CGLM_ALIGN(X) __attribute((aligned(X)))
#endif #endif
typedef float vec3[3]; #ifndef CGLM_ALL_UNALIGNED
typedef int ivec3[3]; # define CGLM_ALIGN_IF(X) CGLM_ALIGN(X)
typedef CGLM_ALIGN(16) float vec4[4]; #else
# define CGLM_ALIGN_IF(X) /* no alignment */
#endif
#ifdef __AVX__
# define CGLM_ALIGN_MAT CGLM_ALIGN(32)
#else
# define CGLM_ALIGN_MAT CGLM_ALIGN(16)
#endif
typedef float vec2[2];
typedef CGLM_ALIGN_IF(8) float vec3[3];
typedef int ivec3[3];
typedef CGLM_ALIGN_IF(16) float vec4[4];
#ifdef __AVX__
typedef CGLM_ALIGN_IF(32) vec3 mat3[3];
typedef CGLM_ALIGN_IF(32) vec4 mat4[4];
#else
typedef vec3 mat3[3]; typedef vec3 mat3[3];
typedef vec4 mat4[4]; typedef CGLM_ALIGN_IF(16) vec4 mat4[4];
#endif
typedef vec4 versor; typedef vec4 versor;
#define CGLM_PI (float)M_PI #define GLM_E 2.71828182845904523536028747135266250 /* e */
#define CGLM_PI_2 (float)M_PI_2 #define GLM_LOG2E 1.44269504088896340735992468100189214 /* log2(e) */
#define CGLM_PI_4 (float)M_PI_4 #define GLM_LOG10E 0.434294481903251827651128918916605082 /* log10(e) */
#define GLM_LN2 0.693147180559945309417232121458176568 /* loge(2) */
#define GLM_LN10 2.30258509299404568401799145468436421 /* loge(10) */
#define GLM_PI 3.14159265358979323846264338327950288 /* pi */
#define GLM_PI_2 1.57079632679489661923132169163975144 /* pi/2 */
#define GLM_PI_4 0.785398163397448309615660845819875721 /* pi/4 */
#define GLM_1_PI 0.318309886183790671537767526745028724 /* 1/pi */
#define GLM_2_PI 0.636619772367581343075535053490057448 /* 2/pi */
#define GLM_2_SQRTPI 1.12837916709551257389615890312154517 /* 2/sqrt(pi) */
#define GLM_SQRT2 1.41421356237309504880168872420969808 /* sqrt(2) */
#define GLM_SQRT1_2 0.707106781186547524400844362104849039 /* 1/sqrt(2) */
#define GLM_Ef ((float)GLM_E)
#define GLM_LOG2Ef ((float)GLM_LOG2E)
#define GLM_LOG10Ef ((float)GLM_LOG10E)
#define GLM_LN2f ((float)GLM_LN2)
#define GLM_LN10f ((float)GLM_LN10)
#define GLM_PIf ((float)GLM_PI)
#define GLM_PI_2f ((float)GLM_PI_2)
#define GLM_PI_4f ((float)GLM_PI_4)
#define GLM_1_PIf ((float)GLM_1_PI)
#define GLM_2_PIf ((float)GLM_2_PI)
#define GLM_2_SQRTPIf ((float)GLM_2_SQRTPI)
#define GLM_SQRT2f ((float)GLM_SQRT2)
#define GLM_SQRT1_2f ((float)GLM_SQRT1_2)
/* DEPRECATED! use GLM_PI and friends */
#define CGLM_PI GLM_PIf
#define CGLM_PI_2 GLM_PI_2f
#define CGLM_PI_4 GLM_PI_4f
#endif /* cglm_types_h */ #endif /* cglm_types_h */

View File

@@ -19,9 +19,15 @@
#define cglm_util_h #define cglm_util_h
#include "common.h" #include "common.h"
#include <stdbool.h>
#define GLM_MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
#define GLM_MAX(X, Y) (((X) > (Y)) ? (X) : (Y))
/*! /*!
* @brief get sign of 32 bit integer as +1 or -1 * @brief get sign of 32 bit integer as +1, -1, 0
*
* Important: It returns 0 for zero input
* *
* @param val integer value * @param val integer value
*/ */
@@ -31,6 +37,19 @@ glm_sign(int val) {
return ((val >> 31) - (-val >> 31)); return ((val >> 31) - (-val >> 31));
} }
/*!
* @brief get sign of 32 bit float as +1, -1, 0
*
* Important: It returns 0 for zero/NaN input
*
* @param val float value
*/
CGLM_INLINE
float
glm_signf(float val) {
return (float)((val > 0.0f) - (val < 0.0f));
}
/*! /*!
* @brief convert degree to radians * @brief convert degree to radians
* *
@@ -39,7 +58,7 @@ glm_sign(int val) {
CGLM_INLINE CGLM_INLINE
float float
glm_rad(float deg) { glm_rad(float deg) {
return deg * CGLM_PI / 180.0f; return deg * GLM_PIf / 180.0f;
} }
/*! /*!
@@ -50,7 +69,7 @@ glm_rad(float deg) {
CGLM_INLINE CGLM_INLINE
float float
glm_deg(float rad) { glm_deg(float rad) {
return rad * 180.0f / CGLM_PI; return rad * 180.0f / GLM_PIf;
} }
/*! /*!
@@ -61,7 +80,7 @@ glm_deg(float rad) {
CGLM_INLINE CGLM_INLINE
void void
glm_make_rad(float *deg) { glm_make_rad(float *deg) {
*deg = *deg * CGLM_PI / 180.0f; *deg = *deg * GLM_PIf / 180.0f;
} }
/*! /*!
@@ -72,7 +91,7 @@ glm_make_rad(float *deg) {
CGLM_INLINE CGLM_INLINE
void void
glm_make_deg(float *rad) { glm_make_deg(float *rad) {
*rad = *rad * 180.0f / CGLM_PI; *rad = *rad * 180.0f / GLM_PIf;
} }
/*! /*!
@@ -83,7 +102,6 @@ glm_make_deg(float *rad) {
CGLM_INLINE CGLM_INLINE
float float
glm_pow2(float x) { glm_pow2(float x) {
return x * x; return x * x;
} }
@@ -115,4 +133,88 @@ glm_max(float a, float b) {
return b; return b;
} }
/*!
* @brief clamp a number between min and max
*
* @param[in] val value to clamp
* @param[in] minVal minimum value
* @param[in] maxVal maximum value
*/
CGLM_INLINE
float
glm_clamp(float val, float minVal, float maxVal) {
return glm_min(glm_max(val, minVal), maxVal);
}
/*!
* @brief clamp a number to zero and one
*
* @param[in] val value to clamp
*/
CGLM_INLINE
float
glm_clamp_zo(float val) {
return glm_clamp(val, 0.0f, 1.0f);
}
/*!
* @brief linear interpolation between two number
*
* formula: from + s * (to - from)
*
* @param[in] from from value
* @param[in] to to value
* @param[in] t interpolant (amount) clamped between 0 and 1
*/
CGLM_INLINE
float
glm_lerp(float from, float to, float t) {
return from + glm_clamp_zo(t) * (to - from);
}
/*!
* @brief check if two float equal with using EPSILON
*
* @param[in] a a
* @param[in] b b
*/
CGLM_INLINE
bool
glm_eq(float a, float b) {
return fabsf(a - b) <= FLT_EPSILON;
}
/*!
* @brief percentage of current value between start and end value
*
* maybe fraction could be alternative name.
*
* @param[in] from from value
* @param[in] to to value
* @param[in] current current value
*/
CGLM_INLINE
float
glm_percent(float from, float to, float current) {
float t;
if ((t = to - from) == 0.0f)
return 1.0f;
return (current - from) / t;
}
/*!
* @brief clamped percentage of current value between start and end value
*
* @param[in] from from value
* @param[in] to to value
* @param[in] current current value
*/
CGLM_INLINE
float
glm_percentc(float from, float to, float current) {
return glm_clamp(glm_percent(from, to, current), 0.0f, 1.0f);
}
#endif /* cglm_util_h */ #endif /* cglm_util_h */

View File

@@ -11,40 +11,30 @@
/* /*
Functions: Functions:
CGLM_INLINE void glm_vec_mulv(vec3 a, vec3 b, vec3 d); CGLM_INLINE void glm_vec3_broadcast(float val, vec3 d);
CGLM_INLINE void glm_vec_broadcast(float val, vec3 d); CGLM_INLINE bool glm_vec3_eq(vec3 v, float val);
CGLM_INLINE bool glm_vec_eq(vec3 v, float val); CGLM_INLINE bool glm_vec3_eq_eps(vec3 v, float val);
CGLM_INLINE bool glm_vec_eq_eps(vec3 v, float val); CGLM_INLINE bool glm_vec3_eq_all(vec3 v);
CGLM_INLINE bool glm_vec_eq_all(vec3 v); CGLM_INLINE bool glm_vec3_eqv(vec3 a, vec3 b);
CGLM_INLINE bool glm_vec_eqv(vec3 v1, vec3 v2); CGLM_INLINE bool glm_vec3_eqv_eps(vec3 a, vec3 b);
CGLM_INLINE bool glm_vec_eqv_eps(vec3 v1, vec3 v2); CGLM_INLINE float glm_vec3_max(vec3 v);
CGLM_INLINE float glm_vec_max(vec3 v); CGLM_INLINE float glm_vec3_min(vec3 v);
CGLM_INLINE float glm_vec_min(vec3 v); CGLM_INLINE bool glm_vec3_isnan(vec3 v);
CGLM_INLINE bool glm_vec3_isinf(vec3 v);
CGLM_INLINE bool glm_vec3_isvalid(vec3 v);
CGLM_INLINE void glm_vec3_sign(vec3 v, vec3 dest);
CGLM_INLINE void glm_vec3_sqrt(vec3 v, vec3 dest);
*/ */
#ifndef cglm_vec3_ext_h #ifndef cglm_vec3_ext_h
#define cglm_vec3_ext_h #define cglm_vec3_ext_h
#include "common.h" #include "common.h"
#include "util.h"
#include <stdbool.h> #include <stdbool.h>
#include <math.h> #include <math.h>
#include <float.h> #include <float.h>
/*!
* @brief multiplies individual items, just for convenient like SIMD
*
* @param[in] a vec1
* @param[in] b vec2
* @param[out] d vec3 = (v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2])
*/
CGLM_INLINE
void
glm_vec_mulv(vec3 a, vec3 b, vec3 d) {
d[0] = a[0] * b[0];
d[1] = a[1] * b[1];
d[2] = a[2] * b[2];
}
/*! /*!
* @brief fill a vector with specified value * @brief fill a vector with specified value
* *
@@ -53,7 +43,7 @@ glm_vec_mulv(vec3 a, vec3 b, vec3 d) {
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_vec_broadcast(float val, vec3 d) { glm_vec3_broadcast(float val, vec3 d) {
d[0] = d[1] = d[2] = val; d[0] = d[1] = d[2] = val;
} }
@@ -65,7 +55,7 @@ glm_vec_broadcast(float val, vec3 d) {
*/ */
CGLM_INLINE CGLM_INLINE
bool bool
glm_vec_eq(vec3 v, float val) { glm_vec3_eq(vec3 v, float val) {
return v[0] == val && v[0] == v[1] && v[0] == v[2]; return v[0] == val && v[0] == v[1] && v[0] == v[2];
} }
@@ -77,7 +67,7 @@ glm_vec_eq(vec3 v, float val) {
*/ */
CGLM_INLINE CGLM_INLINE
bool bool
glm_vec_eq_eps(vec3 v, float val) { glm_vec3_eq_eps(vec3 v, float val) {
return fabsf(v[0] - val) <= FLT_EPSILON return fabsf(v[0] - val) <= FLT_EPSILON
&& fabsf(v[1] - val) <= FLT_EPSILON && fabsf(v[1] - val) <= FLT_EPSILON
&& fabsf(v[2] - val) <= FLT_EPSILON; && fabsf(v[2] - val) <= FLT_EPSILON;
@@ -90,36 +80,36 @@ glm_vec_eq_eps(vec3 v, float val) {
*/ */
CGLM_INLINE CGLM_INLINE
bool bool
glm_vec_eq_all(vec3 v) { glm_vec3_eq_all(vec3 v) {
return v[0] == v[1] && v[0] == v[2]; return v[0] == v[1] && v[0] == v[2];
} }
/*! /*!
* @brief check if vector is equal to another (without epsilon) * @brief check if vector is equal to another (without epsilon)
* *
* @param[in] v1 vector * @param[in] a vector
* @param[in] v2 vector * @param[in] b vector
*/ */
CGLM_INLINE CGLM_INLINE
bool bool
glm_vec_eqv(vec3 v1, vec3 v2) { glm_vec3_eqv(vec3 a, vec3 b) {
return v1[0] == v2[0] return a[0] == b[0]
&& v1[1] == v2[1] && a[1] == b[1]
&& v1[2] == v2[2]; && a[2] == b[2];
} }
/*! /*!
* @brief check if vector is equal to another (with epsilon) * @brief check if vector is equal to another (with epsilon)
* *
* @param[in] v1 vector * @param[in] a vector
* @param[in] v2 vector * @param[in] b vector
*/ */
CGLM_INLINE CGLM_INLINE
bool bool
glm_vec_eqv_eps(vec3 v1, vec3 v2) { glm_vec3_eqv_eps(vec3 a, vec3 b) {
return fabsf(v1[0] - v2[0]) <= FLT_EPSILON return fabsf(a[0] - b[0]) <= FLT_EPSILON
&& fabsf(v1[1] - v2[1]) <= FLT_EPSILON && fabsf(a[1] - b[1]) <= FLT_EPSILON
&& fabsf(v1[2] - v2[2]) <= FLT_EPSILON; && fabsf(a[2] - b[2]) <= FLT_EPSILON;
} }
/*! /*!
@@ -129,7 +119,7 @@ glm_vec_eqv_eps(vec3 v1, vec3 v2) {
*/ */
CGLM_INLINE CGLM_INLINE
float float
glm_vec_max(vec3 v) { glm_vec3_max(vec3 v) {
float max; float max;
max = v[0]; max = v[0];
@@ -148,7 +138,7 @@ glm_vec_max(vec3 v) {
*/ */
CGLM_INLINE CGLM_INLINE
float float
glm_vec_min(vec3 v) { glm_vec3_min(vec3 v) {
float min; float min;
min = v[0]; min = v[0];
@@ -160,4 +150,69 @@ glm_vec_min(vec3 v) {
return min; return min;
} }
/*!
* @brief check if all items are NaN (not a number)
* you should only use this in DEBUG mode or very critical asserts
*
* @param[in] v vector
*/
CGLM_INLINE
bool
glm_vec3_isnan(vec3 v) {
return isnan(v[0]) || isnan(v[1]) || isnan(v[2]);
}
/*!
* @brief check if all items are INFINITY
* you should only use this in DEBUG mode or very critical asserts
*
* @param[in] v vector
*/
CGLM_INLINE
bool
glm_vec3_isinf(vec3 v) {
return isinf(v[0]) || isinf(v[1]) || isinf(v[2]);
}
/*!
* @brief check if all items are valid number
* you should only use this in DEBUG mode or very critical asserts
*
* @param[in] v vector
*/
CGLM_INLINE
bool
glm_vec3_isvalid(vec3 v) {
return !glm_vec3_isnan(v) && !glm_vec3_isinf(v);
}
/*!
* @brief get sign of 32 bit float as +1, -1, 0
*
* Important: It returns 0 for zero/NaN input
*
* @param v vector
*/
CGLM_INLINE
void
glm_vec3_sign(vec3 v, vec3 dest) {
dest[0] = glm_signf(v[0]);
dest[1] = glm_signf(v[1]);
dest[2] = glm_signf(v[2]);
}
/*!
* @brief square root of each vector item
*
* @param[in] v vector
* @param[out] dest destination vector
*/
CGLM_INLINE
void
glm_vec3_sqrt(vec3 v, vec3 dest) {
dest[0] = sqrtf(v[0]);
dest[1] = sqrtf(v[1]);
dest[2] = sqrtf(v[2]);
}
#endif /* cglm_vec3_ext_h */ #endif /* cglm_vec3_ext_h */

View File

@@ -5,14 +5,8 @@
* Full license can be found in the LICENSE file * Full license can be found in the LICENSE file
*/ */
/*!
* vec3 functions dont have suffix e.g glm_vec_dot (not glm_vec3_dot)
* all functions without suffix are vec3 functions
*/
/* /*
Macros: Macros:
glm_vec_dup(v, dest)
GLM_VEC3_ONE_INIT GLM_VEC3_ONE_INIT
GLM_VEC3_ZERO_INIT GLM_VEC3_ZERO_INIT
GLM_VEC3_ONE GLM_VEC3_ONE
@@ -23,46 +17,80 @@
Functions: Functions:
CGLM_INLINE void glm_vec3(vec4 v4, vec3 dest); CGLM_INLINE void glm_vec3(vec4 v4, vec3 dest);
CGLM_INLINE void glm_vec_copy(vec3 a, vec3 dest); CGLM_INLINE void glm_vec3_copy(vec3 a, vec3 dest);
CGLM_INLINE float glm_vec_dot(vec3 a, vec3 b); CGLM_INLINE void glm_vec3_zero(vec3 v);
CGLM_INLINE void glm_vec_cross(vec3 a, vec3 b, vec3 d); CGLM_INLINE void glm_vec3_one(vec3 v);
CGLM_INLINE float glm_vec_norm2(vec3 v); CGLM_INLINE float glm_vec3_dot(vec3 a, vec3 b);
CGLM_INLINE float glm_vec_norm(vec3 vec); CGLM_INLINE void glm_vec3_cross(vec3 a, vec3 b, vec3 d);
CGLM_INLINE void glm_vec_add(vec3 v1, vec3 v2, vec3 dest); CGLM_INLINE float glm_vec3_norm2(vec3 v);
CGLM_INLINE void glm_vec_sub(vec3 v1, vec3 v2, vec3 dest); CGLM_INLINE float glm_vec3_norm(vec3 v);
CGLM_INLINE void glm_vec_scale(vec3 v, float s, vec3 dest); CGLM_INLINE void glm_vec3_add(vec3 a, vec3 b, vec3 dest);
CGLM_INLINE void glm_vec_scale_as(vec3 v, float s, vec3 dest); CGLM_INLINE void glm_vec3_adds(vec3 a, float s, vec3 dest);
CGLM_INLINE void glm_vec_flipsign(vec3 v); CGLM_INLINE void glm_vec3_sub(vec3 a, vec3 b, vec3 dest);
CGLM_INLINE void glm_vec_inv(vec3 v); CGLM_INLINE void glm_vec3_subs(vec3 a, float s, vec3 dest);
CGLM_INLINE void glm_vec_inv_to(vec3 v, vec3 dest); CGLM_INLINE void glm_vec3_mul(vec3 a, vec3 b, vec3 dest);
CGLM_INLINE void glm_vec_normalize(vec3 v); CGLM_INLINE void glm_vec3_scale(vec3 v, float s, vec3 dest);
CGLM_INLINE void glm_vec_normalize_to(vec3 vec, vec3 dest); CGLM_INLINE void glm_vec3_scale_as(vec3 v, float s, vec3 dest);
CGLM_INLINE float glm_vec_distance(vec3 v1, vec3 v2); CGLM_INLINE void glm_vec3_div(vec3 a, vec3 b, vec3 dest);
CGLM_INLINE float glm_vec_angle(vec3 v1, vec3 v2); CGLM_INLINE void glm_vec3_divs(vec3 a, float s, vec3 dest);
CGLM_INLINE void glm_vec_rotate(vec3 v, float angle, vec3 axis); CGLM_INLINE void glm_vec3_addadd(vec3 a, vec3 b, vec3 dest);
CGLM_INLINE void glm_vec_rotate_m4(mat4 m, vec3 v, vec3 dest); CGLM_INLINE void glm_vec3_subadd(vec3 a, vec3 b, vec3 dest);
CGLM_INLINE void glm_vec_proj(vec3 a, vec3 b, vec3 dest); CGLM_INLINE void glm_vec3_muladd(vec3 a, vec3 b, vec3 dest);
CGLM_INLINE void glm_vec_center(vec3 v1, vec3 v2, vec3 dest); CGLM_INLINE void glm_vec3_muladds(vec3 a, float s, vec3 dest);
CGLM_INLINE void glm_vec_maxv(vec3 v1, vec3 v2, vec3 dest); CGLM_INLINE void glm_vec3_maxadd(vec3 a, vec3 b, vec3 dest);
CGLM_INLINE void glm_vec_minv(vec3 v1, vec3 v2, vec3 dest); CGLM_INLINE void glm_vec3_minadd(vec3 a, vec3 b, vec3 dest);
CGLM_INLINE void glm_vec_ortho(vec3 v, vec3 dest); CGLM_INLINE void glm_vec3_flipsign(vec3 v);
CGLM_INLINE void glm_vec3_flipsign_to(vec3 v, vec3 dest);
CGLM_INLINE void glm_vec3_negate_to(vec3 v, vec3 dest);
CGLM_INLINE void glm_vec3_negate(vec3 v);
CGLM_INLINE void glm_vec3_inv(vec3 v);
CGLM_INLINE void glm_vec3_inv_to(vec3 v, vec3 dest);
CGLM_INLINE void glm_vec3_normalize(vec3 v);
CGLM_INLINE void glm_vec3_normalize_to(vec3 v, vec3 dest);
CGLM_INLINE float glm_vec3_distance(vec3 a, vec3 b);
CGLM_INLINE float glm_vec3_angle(vec3 a, vec3 b);
CGLM_INLINE void glm_vec3_rotate(vec3 v, float angle, vec3 axis);
CGLM_INLINE void glm_vec3_rotate_m4(mat4 m, vec3 v, vec3 dest);
CGLM_INLINE void glm_vec3_rotate_m3(mat3 m, vec3 v, vec3 dest);
CGLM_INLINE void glm_vec3_proj(vec3 a, vec3 b, vec3 dest);
CGLM_INLINE void glm_vec3_center(vec3 a, vec3 b, vec3 dest);
CGLM_INLINE float glm_vec3_distance2(vec3 a, vec3 b);
CGLM_INLINE void glm_vec3_maxv(vec3 a, vec3 b, vec3 dest);
CGLM_INLINE void glm_vec3_minv(vec3 a, vec3 b, vec3 dest);
CGLM_INLINE void glm_vec3_ortho(vec3 v, vec3 dest);
CGLM_INLINE void glm_vec3_clamp(vec3 v, float minVal, float maxVal);
CGLM_INLINE void glm_vec3_lerp(vec3 from, vec3 to, float t, vec3 dest);
Convenient: Convenient:
CGLM_INLINE void glm_cross(vec3 a, vec3 b, vec3 d); CGLM_INLINE void glm_cross(vec3 a, vec3 b, vec3 d);
CGLM_INLINE float glm_dot(vec3 a, vec3 b); CGLM_INLINE float glm_dot(vec3 a, vec3 b);
CGLM_INLINE void glm_normalize(vec3 v); CGLM_INLINE void glm_normalize(vec3 v);
CGLM_INLINE void glm_normalize_to(vec3 v, vec3 dest); CGLM_INLINE void glm_normalize_to(vec3 v, vec3 dest);
DEPRECATED:
glm_vec3_dup
glm_vec3_flipsign
glm_vec3_flipsign_to
glm_vec3_inv
glm_vec3_inv_to
glm_vec3_mulv
*/ */
#ifndef cglm_vec3_h #ifndef cglm_vec3_h
#define cglm_vec3_h #define cglm_vec3_h
#include "common.h" #include "common.h"
#include "vec4.h"
#include "vec3-ext.h" #include "vec3-ext.h"
#include "util.h" #include "util.h"
/* DEPRECATED! use _copy, _ucopy versions */ /* DEPRECATED! use _copy, _ucopy versions */
#define glm_vec_dup(v, dest) glm_vec_copy(v, dest) #define glm_vec3_dup(v, dest) glm_vec3_copy(v, dest)
#define glm_vec3_flipsign(v) glm_vec3_negate(v)
#define glm_vec3_flipsign_to(v, dest) glm_vec3_negate_to(v, dest)
#define glm_vec3_inv(v) glm_vec3_negate(v)
#define glm_vec3_inv_to(v, dest) glm_vec3_negate_to(v, dest)
#define glm_vec3_mulv(a, b, d) glm_vec3_mul(a, b, d)
#define GLM_VEC3_ONE_INIT {1.0f, 1.0f, 1.0f} #define GLM_VEC3_ONE_INIT {1.0f, 1.0f, 1.0f}
#define GLM_VEC3_ZERO_INIT {0.0f, 0.0f, 0.0f} #define GLM_VEC3_ZERO_INIT {0.0f, 0.0f, 0.0f}
@@ -96,12 +124,34 @@ glm_vec3(vec4 v4, vec3 dest) {
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_vec_copy(vec3 a, vec3 dest) { glm_vec3_copy(vec3 a, vec3 dest) {
dest[0] = a[0]; dest[0] = a[0];
dest[1] = a[1]; dest[1] = a[1];
dest[2] = a[2]; dest[2] = a[2];
} }
/*!
* @brief make vector zero
*
* @param[in, out] v vector
*/
CGLM_INLINE
void
glm_vec3_zero(vec3 v) {
v[0] = v[1] = v[2] = 0.0f;
}
/*!
* @brief make vector one
*
* @param[in, out] v vector
*/
CGLM_INLINE
void
glm_vec3_one(vec3 v) {
v[0] = v[1] = v[2] = 1.0f;
}
/*! /*!
* @brief vec3 dot product * @brief vec3 dot product
* *
@@ -112,7 +162,7 @@ glm_vec_copy(vec3 a, vec3 dest) {
*/ */
CGLM_INLINE CGLM_INLINE
float float
glm_vec_dot(vec3 a, vec3 b) { glm_vec3_dot(vec3 a, vec3 b) {
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
} }
@@ -125,7 +175,7 @@ glm_vec_dot(vec3 a, vec3 b) {
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_vec_cross(vec3 a, vec3 b, vec3 d) { glm_vec3_cross(vec3 a, vec3 b, vec3 d) {
/* (u2.v3 - u3.v2, u3.v1 - u1.v3, u1.v2 - u2.v1) */ /* (u2.v3 - u3.v2, u3.v1 - u1.v3, u1.v2 - u2.v1) */
d[0] = a[1] * b[2] - a[2] * b[1]; d[0] = a[1] * b[2] - a[2] * b[1];
d[1] = a[2] * b[0] - a[0] * b[2]; d[1] = a[2] * b[0] - a[0] * b[2];
@@ -145,51 +195,96 @@ glm_vec_cross(vec3 a, vec3 b, vec3 d) {
*/ */
CGLM_INLINE CGLM_INLINE
float float
glm_vec_norm2(vec3 v) { glm_vec3_norm2(vec3 v) {
return v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; return glm_vec3_dot(v, v);
} }
/*! /*!
* @brief norm (magnitude) of vec3 * @brief norm (magnitude) of vec3
* *
* @param[in] vec vector * @param[in] v vector
* *
* @return norm * @return norm
*/ */
CGLM_INLINE CGLM_INLINE
float float
glm_vec_norm(vec3 vec) { glm_vec3_norm(vec3 v) {
return sqrtf(glm_vec_norm2(vec)); return sqrtf(glm_vec3_norm2(v));
} }
/*! /*!
* @brief add v2 vector to v1 vector store result in dest * @brief add a vector to b vector store result in dest
* *
* @param[in] v1 vector1 * @param[in] a vector1
* @param[in] v2 vector2 * @param[in] b vector2
* @param[out] dest destination vector * @param[out] dest destination vector
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_vec_add(vec3 v1, vec3 v2, vec3 dest) { glm_vec3_add(vec3 a, vec3 b, vec3 dest) {
dest[0] = v1[0] + v2[0]; dest[0] = a[0] + b[0];
dest[1] = v1[1] + v2[1]; dest[1] = a[1] + b[1];
dest[2] = v1[2] + v2[2]; dest[2] = a[2] + b[2];
} }
/*! /*!
* @brief subtract v2 vector from v1 vector store result in dest * @brief add scalar to v vector store result in dest (d = v + s)
* *
* @param[in] v1 vector1 * @param[in] v vector
* @param[in] v2 vector2 * @param[in] s scalar
* @param[out] dest destination vector * @param[out] dest destination vector
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_vec_sub(vec3 v1, vec3 v2, vec3 dest) { glm_vec3_adds(vec3 v, float s, vec3 dest) {
dest[0] = v1[0] - v2[0]; dest[0] = v[0] + s;
dest[1] = v1[1] - v2[1]; dest[1] = v[1] + s;
dest[2] = v1[2] - v2[2]; dest[2] = v[2] + s;
}
/*!
* @brief subtract b vector from a vector store result in dest
*
* @param[in] a vector1
* @param[in] b vector2
* @param[out] dest destination vector
*/
CGLM_INLINE
void
glm_vec3_sub(vec3 a, vec3 b, vec3 dest) {
dest[0] = a[0] - b[0];
dest[1] = a[1] - b[1];
dest[2] = a[2] - b[2];
}
/*!
* @brief subtract scalar from v vector store result in dest (d = v - s)
*
* @param[in] v vector
* @param[in] s scalar
* @param[out] dest destination vector
*/
CGLM_INLINE
void
glm_vec3_subs(vec3 v, float s, vec3 dest) {
dest[0] = v[0] - s;
dest[1] = v[1] - s;
dest[2] = v[2] - s;
}
/*!
* @brief multiply two vector (component-wise multiplication)
*
* @param a vector1
* @param b vector2
* @param dest v3 = (a[0] * b[0], a[1] * b[1], a[2] * b[2])
*/
CGLM_INLINE
void
glm_vec3_mul(vec3 a, vec3 b, vec3 dest) {
dest[0] = a[0] * b[0];
dest[1] = a[1] * b[1];
dest[2] = a[2] * b[2];
} }
/*! /*!
@@ -201,7 +296,7 @@ glm_vec_sub(vec3 v1, vec3 v2, vec3 dest) {
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_vec_scale(vec3 v, float s, vec3 dest) { glm_vec3_scale(vec3 v, float s, vec3 dest) {
dest[0] = v[0] * s; dest[0] = v[0] * s;
dest[1] = v[1] * s; dest[1] = v[1] * s;
dest[2] = v[2] * s; dest[2] = v[2] * s;
@@ -216,53 +311,173 @@ glm_vec_scale(vec3 v, float s, vec3 dest) {
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_vec_scale_as(vec3 v, float s, vec3 dest) { glm_vec3_scale_as(vec3 v, float s, vec3 dest) {
float norm; float norm;
norm = glm_vec_norm(v); norm = glm_vec3_norm(v);
if (norm == 0) { if (norm == 0.0f) {
glm_vec_copy(v, dest); glm_vec3_zero(dest);
return; return;
} }
glm_vec_scale(v, s / norm, dest); glm_vec3_scale(v, s / norm, dest);
} }
/*! /*!
* @brief flip sign of all vec3 members * @brief div vector with another component-wise division: d = a / b
*
* @param[in] a vector 1
* @param[in] b vector 2
* @param[out] dest result = (a[0]/b[0], a[1]/b[1], a[2]/b[2])
*/
CGLM_INLINE
void
glm_vec3_div(vec3 a, vec3 b, vec3 dest) {
dest[0] = a[0] / b[0];
dest[1] = a[1] / b[1];
dest[2] = a[2] / b[2];
}
/*!
* @brief div vector with scalar: d = v / s
*
* @param[in] v vector
* @param[in] s scalar
* @param[out] dest result = (a[0]/s, a[1]/s, a[2]/s)
*/
CGLM_INLINE
void
glm_vec3_divs(vec3 v, float s, vec3 dest) {
dest[0] = v[0] / s;
dest[1] = v[1] / s;
dest[2] = v[2] / s;
}
/*!
* @brief add two vectors and add result to sum
*
* it applies += operator so dest must be initialized
*
* @param[in] a vector 1
* @param[in] b vector 2
* @param[out] dest dest += (a + b)
*/
CGLM_INLINE
void
glm_vec3_addadd(vec3 a, vec3 b, vec3 dest) {
dest[0] += a[0] + b[0];
dest[1] += a[1] + b[1];
dest[2] += a[2] + b[2];
}
/*!
* @brief sub two vectors and add result to dest
*
* it applies += operator so dest must be initialized
*
* @param[in] a vector 1
* @param[in] b vector 2
* @param[out] dest dest += (a + b)
*/
CGLM_INLINE
void
glm_vec3_subadd(vec3 a, vec3 b, vec3 dest) {
dest[0] += a[0] - b[0];
dest[1] += a[1] - b[1];
dest[2] += a[2] - b[2];
}
/*!
* @brief mul two vectors and add result to dest
*
* it applies += operator so dest must be initialized
*
* @param[in] a vector 1
* @param[in] b vector 2
* @param[out] dest dest += (a * b)
*/
CGLM_INLINE
void
glm_vec3_muladd(vec3 a, vec3 b, vec3 dest) {
dest[0] += a[0] * b[0];
dest[1] += a[1] * b[1];
dest[2] += a[2] * b[2];
}
/*!
* @brief mul vector with scalar and add result to sum
*
* it applies += operator so dest must be initialized
*
* @param[in] a vector
* @param[in] s scalar
* @param[out] dest dest += (a * b)
*/
CGLM_INLINE
void
glm_vec3_muladds(vec3 a, float s, vec3 dest) {
dest[0] += a[0] * s;
dest[1] += a[1] * s;
dest[2] += a[2] * s;
}
/*!
* @brief add max of two vector to result/dest
*
* it applies += operator so dest must be initialized
*
* @param[in] a vector 1
* @param[in] b vector 2
* @param[out] dest dest += max(a, b)
*/
CGLM_INLINE
void
glm_vec3_maxadd(vec3 a, vec3 b, vec3 dest) {
dest[0] += glm_max(a[0], b[0]);
dest[1] += glm_max(a[1], b[1]);
dest[2] += glm_max(a[2], b[2]);
}
/*!
* @brief add min of two vector to result/dest
*
* it applies += operator so dest must be initialized
*
* @param[in] a vector
* @param[in] s scalar
* @param[out] dest dest += min(a, b)
*/
CGLM_INLINE
void
glm_vec3_minadd(vec3 a, vec3 b, vec3 dest) {
dest[0] += glm_min(a[0], b[0]);
dest[1] += glm_min(a[1], b[1]);
dest[2] += glm_min(a[2], b[2]);
}
/*!
* @brief negate vector components and store result in dest
*
* @param[in] v vector
* @param[out] dest result vector
*/
CGLM_INLINE
void
glm_vec3_negate_to(vec3 v, vec3 dest) {
dest[0] = -v[0];
dest[1] = -v[1];
dest[2] = -v[2];
}
/*!
* @brief negate vector components
* *
* @param[in, out] v vector * @param[in, out] v vector
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_vec_flipsign(vec3 v) { glm_vec3_negate(vec3 v) {
v[0] = -v[0]; glm_vec3_negate_to(v, v);
v[1] = -v[1];
v[2] = -v[2];
}
/*!
* @brief make vector as inverse/opposite of itself
*
* @param[in, out] v vector
*/
CGLM_INLINE
void
glm_vec_inv(vec3 v) {
glm_vec_flipsign(v);
}
/*!
* @brief inverse/opposite vector
*
* @param[in] v source
* @param[out] dest destination
*/
CGLM_INLINE
void
glm_vec_inv_to(vec3 v, vec3 dest) {
glm_vec_copy(v, dest);
glm_vec_flipsign(dest);
} }
/*! /*!
@@ -272,63 +487,64 @@ glm_vec_inv_to(vec3 v, vec3 dest) {
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_vec_normalize(vec3 v) { glm_vec3_normalize(vec3 v) {
float norm; float norm;
norm = glm_vec_norm(v); norm = glm_vec3_norm(v);
if (norm == 0.0f) { if (norm == 0.0f) {
v[0] = v[1] = v[2] = 0.0f; v[0] = v[1] = v[2] = 0.0f;
return; return;
} }
glm_vec_scale(v, 1.0f / norm, v); glm_vec3_scale(v, 1.0f / norm, v);
} }
/*! /*!
* @brief normalize vec3 to dest * @brief normalize vec3 to dest
* *
* @param[in] vec source * @param[in] v source
* @param[out] dest destination * @param[out] dest destination
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_vec_normalize_to(vec3 vec, vec3 dest) { glm_vec3_normalize_to(vec3 v, vec3 dest) {
float norm; float norm;
norm = glm_vec_norm(vec); norm = glm_vec3_norm(v);
if (norm == 0.0f) { if (norm == 0.0f) {
dest[0] = dest[1] = dest[2] = 0.0f; glm_vec3_zero(dest);
return; return;
} }
glm_vec_scale(vec, 1.0f / norm, dest); glm_vec3_scale(v, 1.0f / norm, dest);
} }
/*! /*!
* @brief angle betwen two vector * @brief angle betwen two vector
* *
* @param[in] v1 vector1 * @param[in] a vector1
* @param[in] v2 vector2 * @param[in] b vector2
* *
* @return angle as radians * @return angle as radians
*/ */
CGLM_INLINE CGLM_INLINE
float float
glm_vec_angle(vec3 v1, vec3 v2) { glm_vec3_angle(vec3 a, vec3 b) {
float norm; float norm, dot;
/* maybe compiler generate approximation instruction (rcp) */ /* maybe compiler generate approximation instruction (rcp) */
norm = 1.0f / (glm_vec_norm(v1) * glm_vec_norm(v2)); norm = 1.0f / (glm_vec3_norm(a) * glm_vec3_norm(b));
return acosf(glm_vec_dot(v1, v2) * norm); dot = glm_vec3_dot(a, b) * norm;
}
CGLM_INLINE if (dot > 1.0f)
void return 0.0f;
glm_quatv(versor q, else if (dot < -1.0f)
float angle, return CGLM_PI;
vec3 v);
return acosf(dot);
}
/*! /*!
* @brief rotate vec3 around axis by angle using Rodrigues' rotation formula * @brief rotate vec3 around axis by angle using Rodrigues' rotation formula
@@ -339,32 +555,56 @@ glm_quatv(versor q,
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_vec_rotate(vec3 v, float angle, vec3 axis) { glm_vec3_rotate(vec3 v, float angle, vec3 axis) {
versor q; vec3 v1, v2, k;
vec3 v1, v2, v3;
float c, s; float c, s;
c = cosf(angle); c = cosf(angle);
s = sinf(angle); s = sinf(angle);
glm_vec3_normalize_to(axis, k);
/* Right Hand, Rodrigues' rotation formula: /* Right Hand, Rodrigues' rotation formula:
v = v*cos(t) + (kxv)sin(t) + k*(k.v)(1 - cos(t)) v = v*cos(t) + (kxv)sin(t) + k*(k.v)(1 - cos(t))
*/ */
glm_vec3_scale(v, c, v1);
/* quaternion */ glm_vec3_cross(k, v, v2);
glm_quatv(q, angle, v); glm_vec3_scale(v2, s, v2);
glm_vec_scale(v, c, v1); glm_vec3_add(v1, v2, v1);
glm_vec_cross(axis, v, v2); glm_vec3_scale(k, glm_vec3_dot(k, v) * (1.0f - c), v2);
glm_vec_scale(v2, s, v2); glm_vec3_add(v1, v2, v);
}
glm_vec_scale(axis, /*!
glm_vec_dot(axis, v) * (1.0f - c), * @brief apply rotation matrix to vector
v3); *
* matrix format should be (no perspective):
* a b c x
* e f g y
* i j k z
* 0 0 0 w
*
* @param[in] m affine matrix or rot matrix
* @param[in] v vector
* @param[out] dest rotated vector
*/
CGLM_INLINE
void
glm_vec3_rotate_m4(mat4 m, vec3 v, vec3 dest) {
vec4 x, y, z, res;
glm_vec_add(v1, v2, v1); glm_vec4_normalize_to(m[0], x);
glm_vec_add(v1, v3, v); glm_vec4_normalize_to(m[1], y);
glm_vec4_normalize_to(m[2], z);
glm_vec4_scale(x, v[0], res);
glm_vec4_muladds(y, v[1], res);
glm_vec4_muladds(z, v[2], res);
glm_vec3(res, dest);
} }
/*! /*!
@@ -376,18 +616,22 @@ glm_vec_rotate(vec3 v, float angle, vec3 axis) {
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_vec_rotate_m4(mat4 m, vec3 v, vec3 dest) { glm_vec3_rotate_m3(mat3 m, vec3 v, vec3 dest) {
vec3 res, x, y, z; vec4 res, x, y, z;
glm_vec_normalize_to(m[0], x); glm_vec4(m[0], 0.0f, x);
glm_vec_normalize_to(m[1], y); glm_vec4(m[1], 0.0f, y);
glm_vec_normalize_to(m[2], z); glm_vec4(m[2], 0.0f, z);
res[0] = x[0] * v[0] + y[0] * v[1] + z[0] * v[2]; glm_vec4_normalize(x);
res[1] = x[1] * v[0] + y[1] * v[1] + z[1] * v[2]; glm_vec4_normalize(y);
res[2] = x[2] * v[0] + y[2] * v[1] + z[2] * v[2]; glm_vec4_normalize(z);
glm_vec_copy(res, dest); glm_vec4_scale(x, v[0], res);
glm_vec4_muladds(y, v[1], res);
glm_vec4_muladds(z, v[2], res);
glm_vec3(res, dest);
} }
/*! /*!
@@ -399,69 +643,82 @@ glm_vec_rotate_m4(mat4 m, vec3 v, vec3 dest) {
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_vec_proj(vec3 a, vec3 b, vec3 dest) { glm_vec3_proj(vec3 a, vec3 b, vec3 dest) {
glm_vec_scale(b, glm_vec3_scale(b,
glm_vec_dot(a, b) / glm_vec_norm2(b), glm_vec3_dot(a, b) / glm_vec3_norm2(b),
dest); dest);
} }
/** /**
* @brief find center point of two vector * @brief find center point of two vector
* *
* @param[in] v1 vector1 * @param[in] a vector1
* @param[in] v2 vector2 * @param[in] b vector2
* @param[out] dest center point * @param[out] dest center point
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_vec_center(vec3 v1, vec3 v2, vec3 dest) { glm_vec3_center(vec3 a, vec3 b, vec3 dest) {
glm_vec_add(v1, v2, dest); glm_vec3_add(a, b, dest);
glm_vec_scale(dest, 0.5f, dest); glm_vec3_scale(dest, 0.5f, dest);
}
/**
* @brief squared distance between two vectors
*
* @param[in] a vector1
* @param[in] b vector2
* @return returns squared distance (distance * distance)
*/
CGLM_INLINE
float
glm_vec3_distance2(vec3 a, vec3 b) {
return glm_pow2(b[0] - a[0])
+ glm_pow2(b[1] - a[1])
+ glm_pow2(b[2] - a[2]);
} }
/** /**
* @brief distance between two vectors * @brief distance between two vectors
* *
* @param[in] v1 vector1 * @param[in] a vector1
* @param[in] v2 vector2 * @param[in] b vector2
* @return returns distance * @return returns distance
*/ */
CGLM_INLINE CGLM_INLINE
float float
glm_vec_distance(vec3 v1, vec3 v2) { glm_vec3_distance(vec3 a, vec3 b) {
return sqrtf(glm_pow2(v2[0] - v1[0]) return sqrtf(glm_vec3_distance2(a, b));
+ glm_pow2(v2[1] - v1[1])
+ glm_pow2(v2[2] - v1[2]));
} }
/*! /*!
* @brief max values of vectors * @brief max values of vectors
* *
* @param[in] v1 vector1 * @param[in] a vector1
* @param[in] v2 vector2 * @param[in] b vector2
* @param[out] dest destination * @param[out] dest destination
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_vec_maxv(vec3 v1, vec3 v2, vec3 dest) { glm_vec3_maxv(vec3 a, vec3 b, vec3 dest) {
dest[0] = glm_max(v1[0], v2[0]); dest[0] = glm_max(a[0], b[0]);
dest[1] = glm_max(v1[1], v2[1]); dest[1] = glm_max(a[1], b[1]);
dest[2] = glm_max(v1[2], v2[2]); dest[2] = glm_max(a[2], b[2]);
} }
/*! /*!
* @brief min values of vectors * @brief min values of vectors
* *
* @param[in] v1 vector1 * @param[in] a vector1
* @param[in] v2 vector2 * @param[in] b vector2
* @param[out] dest destination * @param[out] dest destination
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_vec_minv(vec3 v1, vec3 v2, vec3 dest) { glm_vec3_minv(vec3 a, vec3 b, vec3 dest) {
dest[0] = glm_min(v1[0], v2[0]); dest[0] = glm_min(a[0], b[0]);
dest[1] = glm_min(v1[1], v2[1]); dest[1] = glm_min(a[1], b[1]);
dest[2] = glm_min(v1[2], v2[2]); dest[2] = glm_min(a[2], b[2]);
} }
/*! /*!
@@ -472,12 +729,49 @@ glm_vec_minv(vec3 v1, vec3 v2, vec3 dest) {
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_vec_ortho(vec3 v, vec3 dest) { glm_vec3_ortho(vec3 v, vec3 dest) {
dest[0] = v[1] - v[2]; dest[0] = v[1] - v[2];
dest[1] = v[2] - v[0]; dest[1] = v[2] - v[0];
dest[2] = v[0] - v[1]; dest[2] = v[0] - v[1];
} }
/*!
* @brief clamp vector's individual members between min and max values
*
* @param[in, out] v vector
* @param[in] minVal minimum value
* @param[in] maxVal maximum value
*/
CGLM_INLINE
void
glm_vec3_clamp(vec3 v, float minVal, float maxVal) {
v[0] = glm_clamp(v[0], minVal, maxVal);
v[1] = glm_clamp(v[1], minVal, maxVal);
v[2] = glm_clamp(v[2], minVal, maxVal);
}
/*!
* @brief linear interpolation between two vector
*
* formula: from + s * (to - from)
*
* @param[in] from from value
* @param[in] to to value
* @param[in] t interpolant (amount) clamped between 0 and 1
* @param[out] dest destination
*/
CGLM_INLINE
void
glm_vec3_lerp(vec3 from, vec3 to, float t, vec3 dest) {
vec3 s, v;
/* from + s * (to - from) */
glm_vec3_broadcast(glm_clamp_zo(t), s);
glm_vec3_sub(to, from, v);
glm_vec3_mul(s, v, v);
glm_vec3_add(from, v, dest);
}
/*! /*!
* @brief vec3 cross product * @brief vec3 cross product
* *
@@ -490,7 +784,7 @@ glm_vec_ortho(vec3 v, vec3 dest) {
CGLM_INLINE CGLM_INLINE
void void
glm_cross(vec3 a, vec3 b, vec3 d) { glm_cross(vec3 a, vec3 b, vec3 d) {
glm_vec_cross(a, b, d); glm_vec3_cross(a, b, d);
} }
/*! /*!
@@ -506,7 +800,7 @@ glm_cross(vec3 a, vec3 b, vec3 d) {
CGLM_INLINE CGLM_INLINE
float float
glm_dot(vec3 a, vec3 b) { glm_dot(vec3 a, vec3 b) {
return glm_vec_dot(a, b); return glm_vec3_dot(a, b);
} }
/*! /*!
@@ -519,7 +813,7 @@ glm_dot(vec3 a, vec3 b) {
CGLM_INLINE CGLM_INLINE
void void
glm_normalize(vec3 v) { glm_normalize(vec3 v) {
glm_vec_normalize(v); glm_vec3_normalize(v);
} }
/*! /*!
@@ -533,7 +827,7 @@ glm_normalize(vec3 v) {
CGLM_INLINE CGLM_INLINE
void void
glm_normalize_to(vec3 v, vec3 dest) { glm_normalize_to(vec3 v, vec3 dest) {
glm_vec_normalize_to(v, dest); glm_vec3_normalize_to(v, dest);
} }
#endif /* cglm_vec3_h */ #endif /* cglm_vec3_h */

View File

@@ -11,15 +11,19 @@
/* /*
Functions: Functions:
CGLM_INLINE void glm_vec4_mulv(vec4 a, vec4 b, vec4 d);
CGLM_INLINE void glm_vec4_broadcast(float val, vec4 d); CGLM_INLINE void glm_vec4_broadcast(float val, vec4 d);
CGLM_INLINE bool glm_vec4_eq(vec4 v, float val); CGLM_INLINE bool glm_vec4_eq(vec4 v, float val);
CGLM_INLINE bool glm_vec4_eq_eps(vec4 v, float val); CGLM_INLINE bool glm_vec4_eq_eps(vec4 v, float val);
CGLM_INLINE bool glm_vec4_eq_all(vec4 v); CGLM_INLINE bool glm_vec4_eq_all(vec4 v);
CGLM_INLINE bool glm_vec4_eqv(vec4 v1, vec4 v2); CGLM_INLINE bool glm_vec4_eqv(vec4 a, vec4 b);
CGLM_INLINE bool glm_vec4_eqv_eps(vec4 v1, vec4 v2); CGLM_INLINE bool glm_vec4_eqv_eps(vec4 a, vec4 b);
CGLM_INLINE float glm_vec4_max(vec4 v); CGLM_INLINE float glm_vec4_max(vec4 v);
CGLM_INLINE float glm_vec4_min(vec4 v); CGLM_INLINE float glm_vec4_min(vec4 v);
CGLM_INLINE bool glm_vec4_isnan(vec4 v);
CGLM_INLINE bool glm_vec4_isinf(vec4 v);
CGLM_INLINE bool glm_vec4_isvalid(vec4 v);
CGLM_INLINE void glm_vec4_sign(vec4 v, vec4 dest);
CGLM_INLINE void glm_vec4_sqrt(vec4 v, vec4 dest);
*/ */
#ifndef cglm_vec4_ext_h #ifndef cglm_vec4_ext_h
@@ -31,26 +35,6 @@
#include <math.h> #include <math.h>
#include <float.h> #include <float.h>
/*!
* @brief multiplies individual items, just for convenient like SIMD
*
* @param a v1
* @param b v2
* @param d v3 = (v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2], v1[3] * v2[3])
*/
CGLM_INLINE
void
glm_vec4_mulv(vec4 a, vec4 b, vec4 d) {
#if defined( __SSE__ ) || defined( __SSE2__ )
_mm_store_ps(d, _mm_mul_ps(_mm_load_ps(a), _mm_load_ps(b)));
#else
d[0] = a[0] * b[0];
d[1] = a[1] * b[1];
d[2] = a[2] * b[2];
d[3] = a[3] * b[3];
#endif
}
/*! /*!
* @brief fill a vector with specified value * @brief fill a vector with specified value
* *
@@ -61,7 +45,7 @@ CGLM_INLINE
void void
glm_vec4_broadcast(float val, vec4 d) { glm_vec4_broadcast(float val, vec4 d) {
#if defined( __SSE__ ) || defined( __SSE2__ ) #if defined( __SSE__ ) || defined( __SSE2__ )
_mm_store_ps(d, _mm_set1_ps(val)); glmm_store(d, _mm_set1_ps(val));
#else #else
d[0] = d[1] = d[2] = d[3] = val; d[0] = d[1] = d[2] = d[3] = val;
#endif #endif
@@ -113,31 +97,31 @@ glm_vec4_eq_all(vec4 v) {
/*! /*!
* @brief check if vector is equal to another (without epsilon) * @brief check if vector is equal to another (without epsilon)
* *
* @param v1 vector * @param a vector
* @param v2 vector * @param b vector
*/ */
CGLM_INLINE CGLM_INLINE
bool bool
glm_vec4_eqv(vec4 v1, vec4 v2) { glm_vec4_eqv(vec4 a, vec4 b) {
return v1[0] == v2[0] return a[0] == b[0]
&& v1[1] == v2[1] && a[1] == b[1]
&& v1[2] == v2[2] && a[2] == b[2]
&& v1[3] == v2[3]; && a[3] == b[3];
} }
/*! /*!
* @brief check if vector is equal to another (with epsilon) * @brief check if vector is equal to another (with epsilon)
* *
* @param v1 vector * @param a vector
* @param v2 vector * @param b vector
*/ */
CGLM_INLINE CGLM_INLINE
bool bool
glm_vec4_eqv_eps(vec4 v1, vec4 v2) { glm_vec4_eqv_eps(vec4 a, vec4 b) {
return fabsf(v1[0] - v2[0]) <= FLT_EPSILON return fabsf(a[0] - b[0]) <= FLT_EPSILON
&& fabsf(v1[1] - v2[1]) <= FLT_EPSILON && fabsf(a[1] - b[1]) <= FLT_EPSILON
&& fabsf(v1[2] - v2[2]) <= FLT_EPSILON && fabsf(a[2] - b[2]) <= FLT_EPSILON
&& fabsf(v1[3] - v2[3]) <= FLT_EPSILON; && fabsf(a[3] - b[3]) <= FLT_EPSILON;
} }
/*! /*!
@@ -150,7 +134,7 @@ float
glm_vec4_max(vec4 v) { glm_vec4_max(vec4 v) {
float max; float max;
max = glm_vec_max(v); max = glm_vec3_max(v);
if (v[3] > max) if (v[3] > max)
max = v[3]; max = v[3];
@@ -167,12 +151,95 @@ float
glm_vec4_min(vec4 v) { glm_vec4_min(vec4 v) {
float min; float min;
min = glm_vec_min(v); min = glm_vec3_min(v);
if (v[3] < min) if (v[3] < min)
min = v[3]; min = v[3];
return min; return min;
} }
#endif /* cglm_vec4_ext_h */ /*!
* @brief check if one of items is NaN (not a number)
* you should only use this in DEBUG mode or very critical asserts
*
* @param[in] v vector
*/
CGLM_INLINE
bool
glm_vec4_isnan(vec4 v) {
return isnan(v[0]) || isnan(v[1]) || isnan(v[2]) || isnan(v[3]);
}
/*!
* @brief check if one of items is INFINITY
* you should only use this in DEBUG mode or very critical asserts
*
* @param[in] v vector
*/
CGLM_INLINE
bool
glm_vec4_isinf(vec4 v) {
return isinf(v[0]) || isinf(v[1]) || isinf(v[2]) || isinf(v[3]);
}
/*!
* @brief check if all items are valid number
* you should only use this in DEBUG mode or very critical asserts
*
* @param[in] v vector
*/
CGLM_INLINE
bool
glm_vec4_isvalid(vec4 v) {
return !glm_vec4_isnan(v) && !glm_vec4_isinf(v);
}
/*!
* @brief get sign of 32 bit float as +1, -1, 0
*
* Important: It returns 0 for zero/NaN input
*
* @param v vector
*/
CGLM_INLINE
void
glm_vec4_sign(vec4 v, vec4 dest) {
#if defined( __SSE2__ ) || defined( __SSE2__ )
__m128 x0, x1, x2, x3, x4;
x0 = glmm_load(v);
x1 = _mm_set_ps(0.0f, 0.0f, 1.0f, -1.0f);
x2 = glmm_shuff1x(x1, 2);
x3 = _mm_and_ps(_mm_cmpgt_ps(x0, x2), glmm_shuff1x(x1, 1));
x4 = _mm_and_ps(_mm_cmplt_ps(x0, x2), glmm_shuff1x(x1, 0));
glmm_store(dest, _mm_or_ps(x3, x4));
#else
dest[0] = glm_signf(v[0]);
dest[1] = glm_signf(v[1]);
dest[2] = glm_signf(v[2]);
dest[3] = glm_signf(v[3]);
#endif
}
/*!
* @brief square root of each vector item
*
* @param[in] v vector
* @param[out] dest destination vector
*/
CGLM_INLINE
void
glm_vec4_sqrt(vec4 v, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_sqrt_ps(glmm_load(v)));
#else
dest[0] = sqrtf(v[0]);
dest[1] = sqrtf(v[1]);
dest[2] = sqrtf(v[2]);
dest[3] = sqrtf(v[3]);
#endif
}
#endif /* cglm_vec4_ext_h */

View File

@@ -5,15 +5,8 @@
* Full license can be found in the LICENSE file * Full license can be found in the LICENSE file
*/ */
/*!
* vec3 functions dont have suffix e.g glm_vec_dot (not glm_vec3_dot)
* all functions without suffix are vec3 functions
*/
/* /*
Macros: Macros:
glm_vec4_dup3(v, dest)
glm_vec4_dup(v, dest)
GLM_VEC4_ONE_INIT GLM_VEC4_ONE_INIT
GLM_VEC4_BLACK_INIT GLM_VEC4_BLACK_INIT
GLM_VEC4_ZERO_INIT GLM_VEC4_ZERO_INIT
@@ -25,21 +18,43 @@
CGLM_INLINE void glm_vec4(vec3 v3, float last, vec4 dest); CGLM_INLINE void glm_vec4(vec3 v3, float last, vec4 dest);
CGLM_INLINE void glm_vec4_copy3(vec4 a, vec3 dest); CGLM_INLINE void glm_vec4_copy3(vec4 a, vec3 dest);
CGLM_INLINE void glm_vec4_copy(vec4 v, vec4 dest); CGLM_INLINE void glm_vec4_copy(vec4 v, vec4 dest);
CGLM_INLINE void glm_vec4_ucopy(vec4 v, vec4 dest);
CGLM_INLINE float glm_vec4_dot(vec4 a, vec4 b); CGLM_INLINE float glm_vec4_dot(vec4 a, vec4 b);
CGLM_INLINE float glm_vec4_norm2(vec4 v); CGLM_INLINE float glm_vec4_norm2(vec4 v);
CGLM_INLINE float glm_vec4_norm(vec4 vec); CGLM_INLINE float glm_vec4_norm(vec4 v);
CGLM_INLINE void glm_vec4_add(vec4 v1, vec4 v2, vec4 dest); CGLM_INLINE void glm_vec4_add(vec4 a, vec4 b, vec4 dest);
CGLM_INLINE void glm_vec4_sub(vec4 v1, vec4 v2, vec4 dest); CGLM_INLINE void glm_vec4_adds(vec4 v, float s, vec4 dest);
CGLM_INLINE void glm_vec4_sub(vec4 a, vec4 b, vec4 dest);
CGLM_INLINE void glm_vec4_subs(vec4 v, float s, vec4 dest);
CGLM_INLINE void glm_vec4_mul(vec4 a, vec4 b, vec4 dest);
CGLM_INLINE void glm_vec4_scale(vec4 v, float s, vec4 dest); CGLM_INLINE void glm_vec4_scale(vec4 v, float s, vec4 dest);
CGLM_INLINE void glm_vec4_scale_as(vec4 v, float s, vec4 dest); CGLM_INLINE void glm_vec4_scale_as(vec4 v, float s, vec4 dest);
CGLM_INLINE void glm_vec4_flipsign(vec4 v); CGLM_INLINE void glm_vec4_div(vec4 a, vec4 b, vec4 dest);
CGLM_INLINE void glm_vec4_divs(vec4 v, float s, vec4 dest);
CGLM_INLINE void glm_vec4_addadd(vec4 a, vec4 b, vec4 dest);
CGLM_INLINE void glm_vec4_subadd(vec4 a, vec4 b, vec4 dest);
CGLM_INLINE void glm_vec4_muladd(vec4 a, vec4 b, vec4 dest);
CGLM_INLINE void glm_vec4_muladds(vec4 a, float s, vec4 dest);
CGLM_INLINE void glm_vec4_maxadd(vec4 a, vec4 b, vec4 dest);
CGLM_INLINE void glm_vec4_minadd(vec4 a, vec4 b, vec4 dest);
CGLM_INLINE void glm_vec4_negate(vec4 v);
CGLM_INLINE void glm_vec4_inv(vec4 v); CGLM_INLINE void glm_vec4_inv(vec4 v);
CGLM_INLINE void glm_vec4_inv_to(vec4 v, vec4 dest); CGLM_INLINE void glm_vec4_inv_to(vec4 v, vec4 dest);
CGLM_INLINE void glm_vec4_normalize(vec4 v); CGLM_INLINE void glm_vec4_normalize(vec4 v);
CGLM_INLINE void glm_vec4_normalize_to(vec4 vec, vec4 dest); CGLM_INLINE void glm_vec4_normalize_to(vec4 vec, vec4 dest);
CGLM_INLINE float glm_vec4_distance(vec4 v1, vec4 v2); CGLM_INLINE float glm_vec4_distance(vec4 a, vec4 b);
CGLM_INLINE void glm_vec4_maxv(vec4 v1, vec4 v2, vec4 dest); CGLM_INLINE void glm_vec4_maxv(vec4 a, vec4 b, vec4 dest);
CGLM_INLINE void glm_vec4_minv(vec4 v1, vec4 v2, vec4 dest); CGLM_INLINE void glm_vec4_minv(vec4 a, vec4 b, vec4 dest);
CGLM_INLINE void glm_vec4_clamp(vec4 v, float minVal, float maxVal);
CGLM_INLINE void glm_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest)
DEPRECATED:
glm_vec4_dup
glm_vec4_flipsign
glm_vec4_flipsign_to
glm_vec4_inv
glm_vec4_inv_to
glm_vec4_mulv
*/ */
#ifndef cglm_vec4_h #ifndef cglm_vec4_h
@@ -49,9 +64,14 @@
#include "vec4-ext.h" #include "vec4-ext.h"
#include "util.h" #include "util.h"
/* DEPRECATED! use _copy, _ucopy versions */ /* DEPRECATED! functions */
#define glm_vec4_dup3(v, dest) glm_vec4_copy3(v, dest) #define glm_vec4_dup3(v, dest) glm_vec4_copy3(v, dest)
#define glm_vec4_dup(v, dest) glm_vec4_copy(v, dest) #define glm_vec4_dup(v, dest) glm_vec4_copy(v, dest)
#define glm_vec4_flipsign(v) glm_vec4_negate(v)
#define glm_vec4_flipsign_to(v, dest) glm_vec4_negate_to(v, dest)
#define glm_vec4_inv(v) glm_vec4_negate(v)
#define glm_vec4_inv_to(v, dest) glm_vec4_negate_to(v, dest)
#define glm_vec4_mulv(a, b, d) glm_vec4_mul(a, b, d)
#define GLM_VEC4_ONE_INIT {1.0f, 1.0f, 1.0f, 1.0f} #define GLM_VEC4_ONE_INIT {1.0f, 1.0f, 1.0f, 1.0f}
#define GLM_VEC4_BLACK_INIT {0.0f, 0.0f, 0.0f, 1.0f} #define GLM_VEC4_BLACK_INIT {0.0f, 0.0f, 0.0f, 1.0f}
@@ -101,7 +121,7 @@ CGLM_INLINE
void void
glm_vec4_copy(vec4 v, vec4 dest) { glm_vec4_copy(vec4 v, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ ) #if defined( __SSE__ ) || defined( __SSE2__ )
_mm_store_ps(dest, _mm_load_ps(v)); glmm_store(dest, glmm_load(v));
#else #else
dest[0] = v[0]; dest[0] = v[0];
dest[1] = v[1]; dest[1] = v[1];
@@ -110,6 +130,59 @@ glm_vec4_copy(vec4 v, vec4 dest) {
#endif #endif
} }
/*!
* @brief copy all members of [a] to [dest]
*
* alignment is not required
*
* @param[in] v source
* @param[out] dest destination
*/
CGLM_INLINE
void
glm_vec4_ucopy(vec4 v, vec4 dest) {
dest[0] = v[0];
dest[1] = v[1];
dest[2] = v[2];
dest[3] = v[3];
}
/*!
* @brief make vector zero
*
* @param[in, out] v vector
*/
CGLM_INLINE
void
glm_vec4_zero(vec4 v) {
#if defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(v, _mm_setzero_ps());
#else
v[0] = 0.0f;
v[1] = 0.0f;
v[2] = 0.0f;
v[3] = 0.0f;
#endif
}
/*!
* @brief make vector one
*
* @param[in, out] v vector
*/
CGLM_INLINE
void
glm_vec4_one(vec4 v) {
#if defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(v, _mm_set1_ps(1.0f));
#else
v[0] = 1.0f;
v[1] = 1.0f;
v[2] = 1.0f;
v[3] = 1.0f;
#endif
}
/*! /*!
* @brief vec4 dot product * @brief vec4 dot product
* *
@@ -121,7 +194,14 @@ glm_vec4_copy(vec4 v, vec4 dest) {
CGLM_INLINE CGLM_INLINE
float float
glm_vec4_dot(vec4 a, vec4 b) { glm_vec4_dot(vec4 a, vec4 b) {
#if defined( __SSE__ ) || defined( __SSE2__ )
__m128 x0;
x0 = _mm_mul_ps(glmm_load(a), glmm_load(b));
x0 = _mm_add_ps(x0, glmm_shuff1(x0, 1, 0, 3, 2));
return _mm_cvtss_f32(_mm_add_ss(x0, glmm_shuff1(x0, 0, 1, 0, 1)));
#else
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
#endif
} }
/*! /*!
@@ -138,63 +218,133 @@ glm_vec4_dot(vec4 a, vec4 b) {
CGLM_INLINE CGLM_INLINE
float float
glm_vec4_norm2(vec4 v) { glm_vec4_norm2(vec4 v) {
#if defined( __SSE__ ) || defined( __SSE2__ )
__m128 x0;
x0 = glmm_load(v);
x0 = _mm_mul_ps(x0, x0);
x0 = _mm_add_ps(x0, glmm_shuff1(x0, 1, 0, 3, 2));
return _mm_cvtss_f32(_mm_add_ss(x0, glmm_shuff1(x0, 0, 1, 0, 1)));
#else
return v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]; return v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3];
#endif
} }
/*! /*!
* @brief norm (magnitude) of vec4 * @brief norm (magnitude) of vec4
* *
* @param[in] vec vector * @param[in] v vector
* *
* @return norm * @return norm
*/ */
CGLM_INLINE CGLM_INLINE
float float
glm_vec4_norm(vec4 vec) { glm_vec4_norm(vec4 v) {
return sqrtf(glm_vec4_norm2(vec));
}
/*!
* @brief add v2 vector to v1 vector store result in dest
*
* @param[in] v1 vector1
* @param[in] v2 vector2
* @param[out] dest destination vector
*/
CGLM_INLINE
void
glm_vec4_add(vec4 v1, vec4 v2, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ ) #if defined( __SSE__ ) || defined( __SSE2__ )
_mm_store_ps(dest, __m128 x0;
_mm_add_ps(_mm_load_ps(v1), x0 = glmm_load(v);
_mm_load_ps(v2))); return _mm_cvtss_f32(_mm_sqrt_ss(glmm_dot(x0, x0)));
#else #else
dest[0] = v1[0] + v2[0]; return sqrtf(glm_vec4_norm2(v));
dest[1] = v1[1] + v2[1];
dest[2] = v1[2] + v2[2];
dest[3] = v1[3] + v2[3];
#endif #endif
} }
/*! /*!
* @brief subtract v2 vector from v1 vector store result in dest * @brief add b vector to a vector store result in dest
* *
* @param[in] v1 vector1 * @param[in] a vector1
* @param[in] v2 vector2 * @param[in] b vector2
* @param[out] dest destination vector * @param[out] dest destination vector
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_vec4_sub(vec4 v1, vec4 v2, vec4 dest) { glm_vec4_add(vec4 a, vec4 b, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ ) #if defined( __SSE__ ) || defined( __SSE2__ )
_mm_store_ps(dest, glmm_store(dest, _mm_add_ps(glmm_load(a), glmm_load(b)));
_mm_sub_ps(_mm_load_ps(v1),
_mm_load_ps(v2)));
#else #else
dest[0] = v1[0] - v2[0]; dest[0] = a[0] + b[0];
dest[1] = v1[1] - v2[1]; dest[1] = a[1] + b[1];
dest[2] = v1[2] - v2[2]; dest[2] = a[2] + b[2];
dest[3] = v1[3] - v2[3]; dest[3] = a[3] + b[3];
#endif
}
/*!
* @brief add scalar to v vector store result in dest (d = v + vec(s))
*
* @param[in] v vector
* @param[in] s scalar
* @param[out] dest destination vector
*/
CGLM_INLINE
void
glm_vec4_adds(vec4 v, float s, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_add_ps(glmm_load(v), _mm_set1_ps(s)));
#else
dest[0] = v[0] + s;
dest[1] = v[1] + s;
dest[2] = v[2] + s;
dest[3] = v[3] + s;
#endif
}
/*!
* @brief subtract b vector from a vector store result in dest (d = a - b)
*
* @param[in] a vector1
* @param[in] b vector2
* @param[out] dest destination vector
*/
CGLM_INLINE
void
glm_vec4_sub(vec4 a, vec4 b, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_sub_ps(glmm_load(a), glmm_load(b)));
#else
dest[0] = a[0] - b[0];
dest[1] = a[1] - b[1];
dest[2] = a[2] - b[2];
dest[3] = a[3] - b[3];
#endif
}
/*!
* @brief subtract scalar from v vector store result in dest (d = v - vec(s))
*
* @param[in] v vector
* @param[in] s scalar
* @param[out] dest destination vector
*/
CGLM_INLINE
void
glm_vec4_subs(vec4 v, float s, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_sub_ps(glmm_load(v), _mm_set1_ps(s)));
#else
dest[0] = v[0] - s;
dest[1] = v[1] - s;
dest[2] = v[2] - s;
dest[3] = v[3] - s;
#endif
}
/*!
* @brief multiply two vector (component-wise multiplication)
*
* @param a vector1
* @param b vector2
* @param d dest = (a[0] * b[0], a[1] * b[1], a[2] * b[2], a[3] * b[3])
*/
CGLM_INLINE
void
glm_vec4_mul(vec4 a, vec4 b, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_mul_ps(glmm_load(a), glmm_load(b)));
#else
dest[0] = a[0] * b[0];
dest[1] = a[1] * b[1];
dest[2] = a[2] * b[2];
dest[3] = a[3] * b[3];
#endif #endif
} }
@@ -209,9 +359,7 @@ CGLM_INLINE
void void
glm_vec4_scale(vec4 v, float s, vec4 dest) { glm_vec4_scale(vec4 v, float s, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ ) #if defined( __SSE__ ) || defined( __SSE2__ )
_mm_store_ps(dest, glmm_store(dest, _mm_mul_ps(glmm_load(v), _mm_set1_ps(s)));
_mm_mul_ps(_mm_load_ps(v),
_mm_set1_ps(s)));
#else #else
dest[0] = v[0] * s; dest[0] = v[0] * s;
dest[1] = v[1] * s; dest[1] = v[1] * s;
@@ -233,14 +381,215 @@ glm_vec4_scale_as(vec4 v, float s, vec4 dest) {
float norm; float norm;
norm = glm_vec4_norm(v); norm = glm_vec4_norm(v);
if (norm == 0) { if (norm == 0.0f) {
glm_vec4_copy(v, dest); glm_vec4_zero(dest);
return; return;
} }
glm_vec4_scale(v, s / norm, dest); glm_vec4_scale(v, s / norm, dest);
} }
/*!
* @brief div vector with another component-wise division: d = a / b
*
* @param[in] a vector 1
* @param[in] b vector 2
* @param[out] dest result = (a[0]/b[0], a[1]/b[1], a[2]/b[2], a[3]/b[3])
*/
CGLM_INLINE
void
glm_vec4_div(vec4 a, vec4 b, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_div_ps(glmm_load(a), glmm_load(b)));
#else
dest[0] = a[0] / b[0];
dest[1] = a[1] / b[1];
dest[2] = a[2] / b[2];
dest[3] = a[3] / b[3];
#endif
}
/*!
* @brief div vec4 vector with scalar: d = v / s
*
* @param[in] v vector
* @param[in] s scalar
* @param[out] dest destination vector
*/
CGLM_INLINE
void
glm_vec4_divs(vec4 v, float s, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_div_ps(glmm_load(v), _mm_set1_ps(s)));
#else
glm_vec4_scale(v, 1.0f / s, dest);
#endif
}
/*!
* @brief add two vectors and add result to sum
*
* it applies += operator so dest must be initialized
*
* @param[in] a vector 1
* @param[in] b vector 2
* @param[out] dest dest += (a + b)
*/
CGLM_INLINE
void
glm_vec4_addadd(vec4 a, vec4 b, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_add_ps(glmm_load(dest),
_mm_add_ps(glmm_load(a),
glmm_load(b))));
#else
dest[0] += a[0] + b[0];
dest[1] += a[1] + b[1];
dest[2] += a[2] + b[2];
dest[3] += a[3] + b[3];
#endif
}
/*!
* @brief sub two vectors and add result to dest
*
* it applies += operator so dest must be initialized
*
* @param[in] a vector 1
* @param[in] b vector 2
* @param[out] dest dest += (a - b)
*/
CGLM_INLINE
void
glm_vec4_subadd(vec4 a, vec4 b, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_add_ps(glmm_load(dest),
_mm_sub_ps(glmm_load(a),
glmm_load(b))));
#else
dest[0] += a[0] - b[0];
dest[1] += a[1] - b[1];
dest[2] += a[2] - b[2];
dest[3] += a[3] - b[3];
#endif
}
/*!
* @brief mul two vectors and add result to dest
*
* it applies += operator so dest must be initialized
*
* @param[in] a vector 1
* @param[in] b vector 2
* @param[out] dest dest += (a * b)
*/
CGLM_INLINE
void
glm_vec4_muladd(vec4 a, vec4 b, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_add_ps(glmm_load(dest),
_mm_mul_ps(glmm_load(a),
glmm_load(b))));
#else
dest[0] += a[0] * b[0];
dest[1] += a[1] * b[1];
dest[2] += a[2] * b[2];
dest[3] += a[3] * b[3];
#endif
}
/*!
* @brief mul vector with scalar and add result to sum
*
* it applies += operator so dest must be initialized
*
* @param[in] a vector
* @param[in] s scalar
* @param[out] dest dest += (a * b)
*/
CGLM_INLINE
void
glm_vec4_muladds(vec4 a, float s, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_add_ps(glmm_load(dest),
_mm_mul_ps(glmm_load(a),
_mm_set1_ps(s))));
#else
dest[0] += a[0] * s;
dest[1] += a[1] * s;
dest[2] += a[2] * s;
dest[3] += a[3] * s;
#endif
}
/*!
* @brief add max of two vector to result/dest
*
* it applies += operator so dest must be initialized
*
* @param[in] a vector 1
* @param[in] b vector 2
* @param[out] dest dest += max(a, b)
*/
CGLM_INLINE
void
glm_vec4_maxadd(vec4 a, vec4 b, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_add_ps(glmm_load(dest),
_mm_max_ps(glmm_load(a),
glmm_load(b))));
#else
dest[0] += glm_max(a[0], b[0]);
dest[1] += glm_max(a[1], b[1]);
dest[2] += glm_max(a[2], b[2]);
dest[3] += glm_max(a[3], b[3]);
#endif
}
/*!
* @brief add min of two vector to result/dest
*
* it applies += operator so dest must be initialized
*
* @param[in] a vector
* @param[in] s scalar
* @param[out] dest dest += min(a, b)
*/
CGLM_INLINE
void
glm_vec4_minadd(vec4 a, vec4 b, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_add_ps(glmm_load(dest),
_mm_min_ps(glmm_load(a),
glmm_load(b))));
#else
dest[0] += glm_min(a[0], b[0]);
dest[1] += glm_min(a[1], b[1]);
dest[2] += glm_min(a[2], b[2]);
dest[3] += glm_min(a[3], b[3]);
#endif
}
/*!
* @brief negate vector components and store result in dest
*
* @param[in] v vector
* @param[out] dest result vector
*/
CGLM_INLINE
void
glm_vec4_negate_to(vec4 v, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_xor_ps(glmm_load(v), _mm_set1_ps(-0.0f)));
#else
dest[0] = -v[0];
dest[1] = -v[1];
dest[2] = -v[2];
dest[3] = -v[3];
#endif
}
/*! /*!
* @brief flip sign of all vec4 members * @brief flip sign of all vec4 members
* *
@@ -248,40 +597,45 @@ glm_vec4_scale_as(vec4 v, float s, vec4 dest) {
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_vec4_flipsign(vec4 v) { glm_vec4_negate(vec4 v) {
#if defined( __SSE__ ) || defined( __SSE2__ ) glm_vec4_negate_to(v, v);
_mm_store_ps(v, _mm_xor_ps(_mm_load_ps(v),
_mm_set1_ps(-0.0f)));
#else
v[0] = -v[0];
v[1] = -v[1];
v[2] = -v[2];
v[3] = -v[3];
#endif
} }
/*! /*!
* @brief make vector as inverse/opposite of itself * @brief normalize vec4 to dest
*
* @param[in, out] v vector
*/
CGLM_INLINE
void
glm_vec4_inv(vec4 v) {
glm_vec4_flipsign(v);
}
/*!
* @brief inverse/opposite vector
* *
* @param[in] v source * @param[in] v source
* @param[out] dest destination * @param[out] dest destination
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_vec4_inv_to(vec4 v, vec4 dest) { glm_vec4_normalize_to(vec4 v, vec4 dest) {
glm_vec4_copy(v, dest); #if defined( __SSE__ ) || defined( __SSE2__ )
glm_vec4_flipsign(dest); __m128 xdot, x0;
float dot;
x0 = glmm_load(v);
xdot = glmm_dot(x0, x0);
dot = _mm_cvtss_f32(xdot);
if (dot == 0.0f) {
glmm_store(dest, _mm_setzero_ps());
return;
}
glmm_store(dest, _mm_div_ps(x0, _mm_sqrt_ps(xdot)));
#else
float norm;
norm = glm_vec4_norm(v);
if (norm == 0.0f) {
glm_vec4_zero(dest);
return;
}
glm_vec4_scale(v, 1.0f / norm, dest);
#endif
} }
/*! /*!
@@ -292,85 +646,106 @@ glm_vec4_inv_to(vec4 v, vec4 dest) {
CGLM_INLINE CGLM_INLINE
void void
glm_vec4_normalize(vec4 v) { glm_vec4_normalize(vec4 v) {
float norm; glm_vec4_normalize_to(v, v);
norm = glm_vec4_norm(v);
if (norm == 0.0f) {
v[0] = v[1] = v[2] = v[3] = 0.0f;
return;
}
glm_vec4_scale(v, 1.0f / norm, v);
}
/*!
* @brief normalize vec4 to dest
*
* @param[in] vec source
* @param[out] dest destination
*/
CGLM_INLINE
void
glm_vec4_normalize_to(vec4 vec, vec4 dest) {
float norm;
norm = glm_vec4_norm(vec);
if (norm == 0.0f) {
dest[0] = dest[1] = dest[2] = dest[3] = 0.0f;
return;
}
glm_vec4_scale(vec, 1.0f / norm, dest);
} }
/** /**
* @brief distance between two vectors * @brief distance between two vectors
* *
* @param[in] v1 vector1 * @param[in] a vector1
* @param[in] v2 vector2 * @param[in] b vector2
* @return returns distance * @return returns distance
*/ */
CGLM_INLINE CGLM_INLINE
float float
glm_vec4_distance(vec4 v1, vec4 v2) { glm_vec4_distance(vec4 a, vec4 b) {
return sqrtf(glm_pow2(v2[0] - v1[0]) return sqrtf(glm_pow2(b[0] - a[0])
+ glm_pow2(v2[1] - v1[1]) + glm_pow2(b[1] - a[1])
+ glm_pow2(v2[2] - v1[2]) + glm_pow2(b[2] - a[2])
+ glm_pow2(v2[3] - v1[3])); + glm_pow2(b[3] - a[3]));
} }
/*! /*!
* @brief max values of vectors * @brief max values of vectors
* *
* @param[in] v1 vector1 * @param[in] a vector1
* @param[in] v2 vector2 * @param[in] b vector2
* @param[out] dest destination * @param[out] dest destination
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_vec4_maxv(vec4 v1, vec4 v2, vec4 dest) { glm_vec4_maxv(vec4 a, vec4 b, vec4 dest) {
dest[0] = glm_max(v1[0], v2[0]); #if defined( __SSE__ ) || defined( __SSE2__ )
dest[1] = glm_max(v1[1], v2[1]); glmm_store(dest, _mm_max_ps(glmm_load(a), glmm_load(b)));
dest[2] = glm_max(v1[2], v2[2]); #else
dest[3] = glm_max(v1[3], v2[3]); dest[0] = glm_max(a[0], b[0]);
dest[1] = glm_max(a[1], b[1]);
dest[2] = glm_max(a[2], b[2]);
dest[3] = glm_max(a[3], b[3]);
#endif
} }
/*! /*!
* @brief min values of vectors * @brief min values of vectors
* *
* @param[in] v1 vector1 * @param[in] a vector1
* @param[in] v2 vector2 * @param[in] b vector2
* @param[out] dest destination * @param[out] dest destination
*/ */
CGLM_INLINE CGLM_INLINE
void void
glm_vec4_minv(vec4 v1, vec4 v2, vec4 dest) { glm_vec4_minv(vec4 a, vec4 b, vec4 dest) {
dest[0] = glm_min(v1[0], v2[0]); #if defined( __SSE__ ) || defined( __SSE2__ )
dest[1] = glm_min(v1[1], v2[1]); glmm_store(dest, _mm_min_ps(glmm_load(a), glmm_load(b)));
dest[2] = glm_min(v1[2], v2[2]); #else
dest[3] = glm_min(v1[3], v2[3]); dest[0] = glm_min(a[0], b[0]);
dest[1] = glm_min(a[1], b[1]);
dest[2] = glm_min(a[2], b[2]);
dest[3] = glm_min(a[3], b[3]);
#endif
}
/*!
* @brief clamp vector's individual members between min and max values
*
* @param[in, out] v vector
* @param[in] minVal minimum value
* @param[in] maxVal maximum value
*/
CGLM_INLINE
void
glm_vec4_clamp(vec4 v, float minVal, float maxVal) {
#if defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(v, _mm_min_ps(_mm_max_ps(glmm_load(v), _mm_set1_ps(minVal)),
_mm_set1_ps(maxVal)));
#else
v[0] = glm_clamp(v[0], minVal, maxVal);
v[1] = glm_clamp(v[1], minVal, maxVal);
v[2] = glm_clamp(v[2], minVal, maxVal);
v[3] = glm_clamp(v[3], minVal, maxVal);
#endif
}
/*!
* @brief linear interpolation between two vector
*
* formula: from + s * (to - from)
*
* @param[in] from from value
* @param[in] to to value
* @param[in] t interpolant (amount) clamped between 0 and 1
* @param[out] dest destination
*/
CGLM_INLINE
void
glm_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest) {
vec4 s, v;
/* from + s * (to - from) */
glm_vec4_broadcast(glm_clamp_zo(t), s);
glm_vec4_sub(to, from, v);
glm_vec4_mul(s, v, v);
glm_vec4_add(from, v, dest);
} }
#endif /* cglm_vec4_h */ #endif /* cglm_vec4_h */

View File

@@ -9,7 +9,7 @@
#define cglm_version_h #define cglm_version_h
#define CGLM_VERSION_MAJOR 0 #define CGLM_VERSION_MAJOR 0
#define CGLM_VERSION_MINOR 3 #define CGLM_VERSION_MINOR 5
#define CGLM_VERSION_PATCH 5 #define CGLM_VERSION_PATCH 0
#endif /* cglm_version_h */ #endif /* cglm_version_h */

View File

@@ -54,7 +54,10 @@ cglm_HEADERS = include/cglm/version.h \
include/cglm/plane.h \ include/cglm/plane.h \
include/cglm/frustum.h \ include/cglm/frustum.h \
include/cglm/box.h \ include/cglm/box.h \
include/cglm/color.h include/cglm/color.h \
include/cglm/project.h \
include/cglm/sphere.h \
include/cglm/ease.h
cglm_calldir=$(includedir)/cglm/call cglm_calldir=$(includedir)/cglm/call
cglm_call_HEADERS = include/cglm/call/mat4.h \ cglm_call_HEADERS = include/cglm/call/mat4.h \
@@ -68,7 +71,10 @@ cglm_call_HEADERS = include/cglm/call/mat4.h \
include/cglm/call/euler.h \ include/cglm/call/euler.h \
include/cglm/call/plane.h \ include/cglm/call/plane.h \
include/cglm/call/frustum.h \ include/cglm/call/frustum.h \
include/cglm/call/box.h include/cglm/call/box.h \
include/cglm/call/project.h \
include/cglm/call/sphere.h \
include/cglm/call/ease.h
cglm_simddir=$(includedir)/cglm/simd cglm_simddir=$(includedir)/cglm/simd
cglm_simd_HEADERS = include/cglm/simd/intrin.h cglm_simd_HEADERS = include/cglm/simd/intrin.h
@@ -98,13 +104,24 @@ libcglm_la_SOURCES=\
src/mat4.c \ src/mat4.c \
src/plane.c \ src/plane.c \
src/frustum.c \ src/frustum.c \
src/box.c src/box.c \
src/project.c \
src/sphere.c \
src/ease.c
test_tests_SOURCES=\ test_tests_SOURCES=\
test/src/test_common.c \ test/src/test_common.c \
test/src/test_main.c \ test/src/test_main.c \
test/src/test_mat4.c \ test/src/test_mat4.c \
test/src/test_cam.c test/src/test_cam.c \
test/src/test_project.c \
test/src/test_clamp.c \
test/src/test_euler.c \
test/src/test_quat.c \
test/src/test_vec4.c \
test/src/test_vec3.c \
test/src/test_mat3.c \
test/src/test_affine.c
all-local: all-local:
sh ./post-build.sh sh ./post-build.sh

View File

@@ -8,6 +8,12 @@
#include "../include/cglm/cglm.h" #include "../include/cglm/cglm.h"
#include "../include/cglm/call.h" #include "../include/cglm/call.h"
CGLM_EXPORT
void
glmc_translate_make(mat4 m, vec3 v) {
glm_translate_make(m, v);
}
CGLM_EXPORT CGLM_EXPORT
void void
glmc_translate_to(mat4 m, vec3 v, mat4 dest) { glmc_translate_to(mat4 m, vec3 v, mat4 dest) {
@@ -38,6 +44,12 @@ glmc_translate_z(mat4 m, float to) {
glm_translate_z(m, to); glm_translate_z(m, to);
} }
CGLM_EXPORT
void
glmc_scale_make(mat4 m, vec3 v) {
glm_scale_make(m, v);
}
CGLM_EXPORT CGLM_EXPORT
void void
glmc_scale_to(mat4 m, vec3 v, mat4 dest) { glmc_scale_to(mat4 m, vec3 v, mat4 dest) {
@@ -52,8 +64,8 @@ glmc_scale(mat4 m, vec3 v) {
CGLM_EXPORT CGLM_EXPORT
void void
glmc_scale1(mat4 m, float s) { glmc_scale_uni(mat4 m, float s) {
glm_scale1(m, s); glm_scale_uni(m, s);
} }
CGLM_EXPORT CGLM_EXPORT
@@ -74,36 +86,42 @@ glmc_rotate_z(mat4 m, float rad, mat4 dest) {
glm_rotate_z(m, rad, dest); glm_rotate_z(m, rad, dest);
} }
CGLM_EXPORT
void
glmc_rotate_ndc_make(mat4 m, float angle, vec3 axis_ndc) {
glm_rotate_ndc_make(m, angle, axis_ndc);
}
CGLM_EXPORT CGLM_EXPORT
void void
glmc_rotate_make(mat4 m, float angle, vec3 axis) { glmc_rotate_make(mat4 m, float angle, vec3 axis) {
glm_rotate_make(m, angle, axis); glm_rotate_make(m, angle, axis);
} }
CGLM_EXPORT
void
glmc_rotate_ndc(mat4 m, float angle, vec3 axis_ndc) {
glm_rotate_ndc(m, angle, axis_ndc);
}
CGLM_EXPORT CGLM_EXPORT
void void
glmc_rotate(mat4 m, float angle, vec3 axis) { glmc_rotate(mat4 m, float angle, vec3 axis) {
glm_rotate(m, angle, axis); glm_rotate(m, angle, axis);
} }
CGLM_EXPORT
void
glmc_rotate_at(mat4 m, vec3 pivot, float angle, vec3 axis) {
glm_rotate_at(m, pivot, angle, axis);
}
CGLM_EXPORT
void
glmc_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis) {
glm_rotate_atm(m, pivot, angle, axis);
}
CGLM_EXPORT CGLM_EXPORT
void void
glmc_decompose_scalev(mat4 m, vec3 s) { glmc_decompose_scalev(mat4 m, vec3 s) {
glm_decompose_scalev(m, s); glm_decompose_scalev(m, s);
} }
CGLM_EXPORT
bool
glmc_uniscaled(mat4 m) {
return glm_uniscaled(m);
}
CGLM_EXPORT CGLM_EXPORT
void void
glmc_decompose_rs(mat4 m, mat4 r, vec3 s) { glmc_decompose_rs(mat4 m, mat4 r, vec3 s) {
@@ -115,3 +133,21 @@ void
glmc_decompose(mat4 m, vec4 t, mat4 r, vec3 s) { glmc_decompose(mat4 m, vec4 t, mat4 r, vec3 s) {
glm_decompose(m, t, r, s); glm_decompose(m, t, r, s);
} }
CGLM_EXPORT
void
glmc_mul(mat4 m1, mat4 m2, mat4 dest) {
glm_mul(m1, m2, dest);
}
CGLM_EXPORT
void
glmc_mul_rot(mat4 m1, mat4 m2, mat4 dest) {
glm_mul_rot(m1, m2, dest);
}
CGLM_EXPORT
void
glmc_inv_tr(mat4 mat) {
glm_inv_tr(mat);
}

View File

@@ -34,3 +34,63 @@ glmc_aabb_crop_until(vec3 box[2],
vec3 dest[2]) { vec3 dest[2]) {
glm_aabb_crop_until(box, cropBox, clampBox, dest); glm_aabb_crop_until(box, cropBox, clampBox, dest);
} }
CGLM_EXPORT
bool
glmc_aabb_frustum(vec3 box[2], vec4 planes[6]) {
return glm_aabb_frustum(box, planes);
}
CGLM_EXPORT
void
glmc_aabb_invalidate(vec3 box[2]) {
glm_aabb_invalidate(box);
}
CGLM_EXPORT
bool
glmc_aabb_isvalid(vec3 box[2]) {
return glm_aabb_isvalid(box);
}
CGLM_EXPORT
float
glmc_aabb_size(vec3 box[2]) {
return glm_aabb_size(box);
}
CGLM_EXPORT
float
glmc_aabb_radius(vec3 box[2]) {
return glm_aabb_radius(box);
}
CGLM_EXPORT
void
glmc_aabb_center(vec3 box[2], vec3 dest) {
glm_aabb_center(box, dest);
}
CGLM_EXPORT
bool
glmc_aabb_aabb(vec3 box[2], vec3 other[2]) {
return glm_aabb_aabb(box, other);
}
CGLM_EXPORT
bool
glmc_aabb_point(vec3 box[2], vec3 point) {
return glm_aabb_point(box, point);
}
CGLM_EXPORT
bool
glmc_aabb_contains(vec3 box[2], vec3 other[2]) {
return glm_aabb_contains(box, other);
}
CGLM_EXPORT
bool
glmc_aabb_sphere(vec3 box[2], vec4 s) {
return glm_aabb_sphere(box, s);
}

114
src/cam.c
View File

@@ -44,6 +44,36 @@ glmc_ortho(float left,
dest); dest);
} }
CGLM_EXPORT
void
glmc_ortho_aabb(vec3 box[2], mat4 dest) {
glm_ortho_aabb(box, dest);
}
CGLM_EXPORT
void
glmc_ortho_aabb_p(vec3 box[2], float padding, mat4 dest) {
glm_ortho_aabb_p(box, padding, dest);
}
CGLM_EXPORT
void
glmc_ortho_aabb_pz(vec3 box[2], float padding, mat4 dest) {
glm_ortho_aabb_pz(box, padding, dest);
}
CGLM_EXPORT
void
glmc_ortho_default(float aspect, mat4 dest) {
glm_ortho_default(aspect, dest);
}
CGLM_EXPORT
void
glmc_ortho_default_s(float aspect, float size, mat4 dest) {
glm_ortho_default_s(aspect, size, dest);
}
CGLM_EXPORT CGLM_EXPORT
void void
glmc_perspective(float fovy, glmc_perspective(float fovy,
@@ -58,6 +88,18 @@ glmc_perspective(float fovy,
dest); dest);
} }
CGLM_EXPORT
void
glmc_perspective_default(float aspect, mat4 dest) {
glm_perspective_default(aspect, dest);
}
CGLM_EXPORT
void
glmc_perspective_resize(float aspect, mat4 proj) {
glm_perspective_resize(aspect, proj);
}
CGLM_EXPORT CGLM_EXPORT
void void
glmc_lookat(vec3 eye, glmc_lookat(vec3 eye,
@@ -78,3 +120,75 @@ void
glmc_look_anyup(vec3 eye, vec3 dir, mat4 dest) { glmc_look_anyup(vec3 eye, vec3 dir, mat4 dest) {
glm_look_anyup(eye, dir, dest); glm_look_anyup(eye, dir, 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) {
glm_persp_decomp(proj, nearVal, farVal, top, bottom, left, right);
}
CGLM_EXPORT
void
glmc_persp_decompv(mat4 proj, float dest[6]) {
glm_persp_decompv(proj, dest);
}
CGLM_EXPORT
void
glmc_persp_decomp_x(mat4 proj,
float * __restrict left,
float * __restrict right) {
glm_persp_decomp_x(proj, left, right);
}
CGLM_EXPORT
void
glmc_persp_decomp_y(mat4 proj,
float * __restrict top,
float * __restrict bottom) {
glm_persp_decomp_y(proj, top, bottom);
}
CGLM_EXPORT
void
glmc_persp_decomp_z(mat4 proj,
float * __restrict nearVal,
float * __restrict farVal) {
glm_persp_decomp_z(proj, nearVal, farVal);
}
CGLM_EXPORT
void
glmc_persp_decomp_far(mat4 proj, float * __restrict farVal) {
glm_persp_decomp_far(proj, farVal);
}
CGLM_EXPORT
void
glmc_persp_decomp_near(mat4 proj, float * __restrict nearVal) {
glm_persp_decomp_near(proj, nearVal);
}
CGLM_EXPORT
float
glmc_persp_fovy(mat4 proj) {
return glm_persp_fovy(proj);
}
CGLM_EXPORT
float
glmc_persp_aspect(mat4 proj) {
return glm_persp_aspect(proj);
}
CGLM_EXPORT
void
glmc_persp_sizes(mat4 proj, float fovy, vec4 dest) {
glm_persp_sizes(proj, fovy, dest);
}

195
src/ease.c Normal file
View File

@@ -0,0 +1,195 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#include "../include/cglm/cglm.h"
#include "../include/cglm/call.h"
CGLM_EXPORT
float
glmc_ease_linear(float t) {
return glm_ease_linear(t);
}
CGLM_EXPORT
float
glmc_ease_sine_in(float t) {
return glm_ease_sine_in(t);
}
CGLM_EXPORT
float
glmc_ease_sine_out(float t) {
return glm_ease_sine_out(t);
}
CGLM_EXPORT
float
glmc_ease_sine_inout(float t) {
return glm_ease_sine_inout(t);
}
CGLM_EXPORT
float
glmc_ease_quad_in(float t) {
return glm_ease_quad_in(t);
}
CGLM_EXPORT
float
glmc_ease_quad_out(float t) {
return glm_ease_quad_out(t);
}
CGLM_EXPORT
float
glmc_ease_quad_inout(float t) {
return glm_ease_quad_inout(t);
}
CGLM_EXPORT
float
glmc_ease_cubic_in(float t) {
return glm_ease_cubic_in(t);
}
CGLM_EXPORT
float
glmc_ease_cubic_out(float t) {
return glm_ease_cubic_out(t);
}
CGLM_EXPORT
float
glmc_ease_cubic_inout(float t) {
return glm_ease_cubic_inout(t);
}
CGLM_EXPORT
float
glmc_ease_quart_in(float t) {
return glm_ease_quart_in(t);
}
CGLM_EXPORT
float
glmc_ease_quart_out(float t) {
return glm_ease_quart_out(t);
}
CGLM_EXPORT
float
glmc_ease_quart_inout(float t) {
return glm_ease_quart_inout(t);
}
CGLM_EXPORT
float
glmc_ease_quint_in(float t) {
return glm_ease_quint_in(t);
}
CGLM_EXPORT
float
glmc_ease_quint_out(float t) {
return glm_ease_quint_out(t);
}
CGLM_EXPORT
float
glmc_ease_quint_inout(float t) {
return glm_ease_quint_inout(t);
}
CGLM_EXPORT
float
glmc_ease_exp_in(float t) {
return glm_ease_exp_in(t);
}
CGLM_EXPORT
float
glmc_ease_exp_out(float t) {
return glm_ease_exp_out(t);
}
CGLM_EXPORT
float
glmc_ease_exp_inout(float t) {
return glm_ease_exp_inout(t);
}
CGLM_EXPORT
float
glmc_ease_circ_in(float t) {
return glm_ease_circ_in(t);
}
CGLM_EXPORT
float
glmc_ease_circ_out(float t) {
return glm_ease_circ_out(t);
}
CGLM_EXPORT
float
glmc_ease_circ_inout(float t) {
return glm_ease_circ_inout(t);
}
CGLM_EXPORT
float
glmc_ease_back_in(float t) {
return glm_ease_back_in(t);
}
CGLM_EXPORT
float
glmc_ease_back_out(float t) {
return glm_ease_back_out(t);
}
CGLM_EXPORT
float
glmc_ease_back_inout(float t) {
return glm_ease_back_inout(t);
}
CGLM_EXPORT
float
glmc_ease_elast_in(float t) {
return glm_ease_elast_in(t);
}
CGLM_EXPORT
float
glmc_ease_elast_out(float t) {
return glm_ease_elast_out(t);
}
CGLM_EXPORT
float
glmc_ease_elast_inout(float t) {
return glm_ease_elast_inout(t);
}
CGLM_EXPORT
float
glmc_ease_bounce_out(float t) {
return glm_ease_bounce_out(t);
}
CGLM_EXPORT
float
glmc_ease_bounce_in(float t) {
return glm_ease_bounce_in(t);
}
CGLM_EXPORT
float
glmc_ease_bounce_inout(float t) {
return glm_ease_bounce_inout(t);
}

View File

@@ -20,6 +20,12 @@ glmc_euler(vec3 angles, mat4 dest) {
glm_euler(angles, dest); glm_euler(angles, dest);
} }
CGLM_EXPORT
void
glmc_euler_xyz(vec3 angles, mat4 dest) {
glm_euler_xyz(angles, dest);
}
CGLM_EXPORT CGLM_EXPORT
void void
glmc_euler_zyx(vec3 angles, mat4 dest) { glmc_euler_zyx(vec3 angles, mat4 dest) {

View File

@@ -20,6 +20,12 @@ glmc_mat3_identity(mat3 mat) {
glm_mat3_identity(mat); glm_mat3_identity(mat);
} }
CGLM_EXPORT
void
glmc_mat3_identity_array(mat3 * __restrict mat, size_t count) {
glm_mat3_identity_array(mat, count);
}
CGLM_EXPORT CGLM_EXPORT
void void
glmc_mat3_mul(mat3 m1, mat3 m2, mat3 dest) { glmc_mat3_mul(mat3 m1, mat3 m2, mat3 dest) {
@@ -44,6 +50,12 @@ glmc_mat3_mulv(mat3 m, vec3 v, vec3 dest) {
glm_mat3_mulv(m, v, dest); glm_mat3_mulv(m, v, dest);
} }
CGLM_EXPORT
void
glmc_mat3_quat(mat3 m, versor dest) {
glm_mat3_quat(m, dest);
}
CGLM_EXPORT CGLM_EXPORT
void void
glmc_mat3_scale(mat3 m, float s) { glmc_mat3_scale(mat3 m, float s) {

View File

@@ -26,6 +26,12 @@ glmc_mat4_identity(mat4 mat) {
glm_mat4_identity(mat); glm_mat4_identity(mat);
} }
CGLM_EXPORT
void
glmc_mat4_identity_array(mat4 * __restrict mat, size_t count) {
glm_mat4_identity_array(mat, count);
}
CGLM_EXPORT CGLM_EXPORT
void void
glmc_mat4_pick3(mat4 mat, mat3 dest) { glmc_mat4_pick3(mat4 mat, mat3 dest) {
@@ -52,7 +58,7 @@ glmc_mat4_mul(mat4 m1, mat4 m2, mat4 dest) {
CGLM_EXPORT CGLM_EXPORT
void void
glmc_mat4_mulN(mat4 * __restrict matrices[], int len, mat4 dest) { glmc_mat4_mulN(mat4 * __restrict matrices[], uint32_t len, mat4 dest) {
glm_mat4_mulN(matrices, len, dest); glm_mat4_mulN(matrices, len, dest);
} }
@@ -62,6 +68,18 @@ glmc_mat4_mulv(mat4 m, vec4 v, vec4 dest) {
glm_mat4_mulv(m, v, dest); glm_mat4_mulv(m, v, dest);
} }
CGLM_EXPORT
void
glmc_mat4_mulv3(mat4 m, vec3 v, float last, vec3 dest) {
glm_mat4_mulv3(m, v, last, dest);
}
CGLM_EXPORT
void
glmc_mat4_quat(mat4 m, versor dest) {
glm_mat4_quat(m, dest);
}
CGLM_EXPORT CGLM_EXPORT
void void
glmc_mat4_transpose_to(mat4 m, mat4 dest) { glmc_mat4_transpose_to(mat4 m, mat4 dest) {
@@ -104,6 +122,12 @@ glmc_mat4_inv_precise(mat4 mat, mat4 dest) {
glm_mat4_inv_precise(mat, dest); glm_mat4_inv_precise(mat, dest);
} }
CGLM_EXPORT
void
glmc_mat4_inv_fast(mat4 mat, mat4 dest) {
glm_mat4_inv_fast(mat, dest);
}
CGLM_EXPORT CGLM_EXPORT
void void
glmc_mat4_swap_col(mat4 mat, int col1, int col2) { glmc_mat4_swap_col(mat4 mat, int col1, int col2) {

27
src/project.c Normal file
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
*/
#include "../include/cglm/cglm.h"
#include "../include/cglm/call.h"
CGLM_EXPORT
void
glmc_unprojecti(vec3 pos, mat4 invMat, vec4 vp, vec3 dest) {
glm_unprojecti(pos, invMat, vp, dest);
}
CGLM_EXPORT
void
glmc_unproject(vec3 pos, mat4 m, vec4 vp, vec3 dest) {
glm_unproject(pos, m, vp, dest);
}
CGLM_EXPORT
void
glmc_project(vec3 pos, mat4 m, vec4 vp, vec3 dest) {
glm_project(pos, m, vp, dest);
}

View File

@@ -16,20 +16,32 @@ glmc_quat_identity(versor q) {
CGLM_EXPORT CGLM_EXPORT
void void
glmc_quat(versor q, glmc_quat_identity_array(versor * __restrict q, size_t count) {
float angle, glm_quat_identity_array(q, count);
float x, }
float y,
float z) { CGLM_EXPORT
void
glmc_quat_init(versor q, float x, float y, float z, float w) {
glm_quat_init(q, x, y, z, w);
}
CGLM_EXPORT
void
glmc_quat(versor q, float angle, float x, float y, float z) {
glm_quat(q, angle, x, y, z); glm_quat(q, angle, x, y, z);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_quatv(versor q, glmc_quatv(versor q, float angle, vec3 axis) {
float angle, glm_quatv(q, angle, axis);
vec3 v) { }
glm_quatv(q, angle, v);
CGLM_EXPORT
void
glmc_quat_copy(versor q, versor dest) {
glm_quat_copy(q, dest);
} }
CGLM_EXPORT CGLM_EXPORT
@@ -40,20 +52,86 @@ glmc_quat_norm(versor q) {
CGLM_EXPORT CGLM_EXPORT
void void
glmc_quat_normalize(versor q) { glmc_quat_normalize_to(versor q, versor dest) {
glm_quat_normalize(q); glm_quat_normalize_to(q, dest);
}
CGLM_EXPORT
float
glmc_quat_dot(versor q, versor r) {
return glm_quat_dot(q, r);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_quat_mulv(versor q1, versor q2, versor dest) { glmc_quat_normalize(versor q) {
glm_quat_mulv(q1, q2, dest); glm_quat_norm(q);
}
CGLM_EXPORT
float
glmc_quat_dot(versor p, versor q) {
return glm_quat_dot(p, q);
}
CGLM_EXPORT
void
glmc_quat_conjugate(versor q, versor dest) {
glm_quat_conjugate(q, dest);
}
CGLM_EXPORT
void
glmc_quat_inv(versor q, versor dest) {
glm_quat_inv(q, dest);
}
CGLM_EXPORT
void
glmc_quat_add(versor p, versor q, versor dest) {
glm_quat_add(p, q, dest);
}
CGLM_EXPORT
void
glmc_quat_sub(versor p, versor q, versor dest) {
glm_quat_sub(p, q, dest);
}
CGLM_EXPORT
float
glmc_quat_real(versor q) {
return glm_quat_real(q);
}
CGLM_EXPORT
void
glmc_quat_imag(versor q, vec3 dest) {
glm_quat_imag(q, dest);
}
CGLM_EXPORT
void
glmc_quat_imagn(versor q, vec3 dest) {
glm_quat_imagn(q, dest);
}
CGLM_EXPORT
float
glmc_quat_imaglen(versor q) {
return glm_quat_imaglen(q);
}
CGLM_EXPORT
float
glmc_quat_angle(versor q) {
return glm_quat_angle(q);
}
CGLM_EXPORT
void
glmc_quat_axis(versor q, versor dest) {
glm_quat_axis(q, dest);
}
CGLM_EXPORT
void
glmc_quat_mul(versor p, versor q, versor dest) {
glm_quat_mul(p, q, dest);
} }
CGLM_EXPORT CGLM_EXPORT
@@ -64,9 +142,72 @@ glmc_quat_mat4(versor q, mat4 dest) {
CGLM_EXPORT CGLM_EXPORT
void void
glmc_quat_slerp(versor q, glmc_quat_mat4t(versor q, mat4 dest) {
versor r, glm_quat_mat4t(q, dest);
float t, }
versor dest) {
glm_quat_slerp(q, r, t, dest); CGLM_EXPORT
void
glmc_quat_mat3(versor q, mat3 dest) {
glm_quat_mat3(q, dest);
}
CGLM_EXPORT
void
glmc_quat_mat3t(versor q, mat3 dest) {
glm_quat_mat3t(q, dest);
}
CGLM_EXPORT
void
glmc_quat_lerp(versor from, versor to, float t, versor dest) {
glm_quat_lerp(from, to, t, dest);
}
CGLM_EXPORT
void
glmc_quat_slerp(versor from, versor to, float t, versor dest) {
glm_quat_slerp(from, to, t, dest);
}
CGLM_EXPORT
void
glmc_quat_look(vec3 eye, versor ori, mat4 dest) {
glm_quat_look(eye, ori, dest);
}
CGLM_EXPORT
void
glmc_quat_for(vec3 dir, vec3 fwd, vec3 up, versor dest) {
glm_quat_for(dir, fwd, up, dest);
}
CGLM_EXPORT
void
glmc_quat_forp(vec3 from, vec3 to, vec3 fwd, vec3 up, versor dest) {
glm_quat_forp(from, to, fwd, up, dest);
}
CGLM_EXPORT
void
glmc_quat_rotatev(versor q, vec3 v, vec3 dest) {
glm_quat_rotatev(q, v, dest);
}
CGLM_EXPORT
void
glmc_quat_rotate(mat4 m, versor q, mat4 dest) {
glm_quat_rotate(m, q, dest);
}
CGLM_EXPORT
void
glmc_quat_rotate_at(mat4 model, versor q, vec3 pivot) {
glm_quat_rotate_at(model, q, pivot);
}
CGLM_EXPORT
void
glmc_quat_rotate_atm(mat4 m, versor q, vec3 pivot) {
glm_quat_rotate_atm(m, q, pivot);
} }

39
src/sphere.c Normal file
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
*/
#include "../include/cglm/cglm.h"
#include "../include/cglm/call.h"
CGLM_EXPORT
float
glmc_sphere_radii(vec4 s) {
return glm_sphere_radii(s);
}
CGLM_EXPORT
void
glmc_sphere_transform(vec4 s, mat4 m, vec4 dest) {
glm_sphere_transform(s, m, dest);
}
CGLM_EXPORT
void
glmc_sphere_merge(vec4 s1, vec4 s2, vec4 dest) {
glm_sphere_merge(s1, s2, dest);
}
CGLM_EXPORT
bool
glmc_sphere_sphere(vec4 s1, vec4 s2) {
return glm_sphere_sphere(s1, s2);
}
CGLM_EXPORT
bool
glmc_sphere_point(vec4 s, vec3 point) {
return glm_sphere_point(s, point);
}

View File

@@ -10,132 +10,326 @@
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_copy(vec3 a, vec3 dest) { glmc_vec3(vec4 v4, vec3 dest) {
glm_vec_copy(a, dest); glm_vec3(v4, dest);
}
CGLM_EXPORT
void
glmc_vec3_copy(vec3 a, vec3 dest) {
glm_vec3_copy(a, dest);
}
CGLM_EXPORT
void
glmc_vec3_zero(vec3 v) {
glm_vec3_zero(v);
}
CGLM_EXPORT
void
glmc_vec3_one(vec3 v) {
glm_vec3_one(v);
} }
CGLM_EXPORT CGLM_EXPORT
float float
glmc_vec_dot(vec3 a, vec3 b) { glmc_vec3_dot(vec3 a, vec3 b) {
return glm_vec_dot(a, b); return glm_vec3_dot(a, b);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_cross(vec3 a, vec3 b, vec3 d) { glmc_vec3_cross(vec3 a, vec3 b, vec3 d) {
glm_vec_cross(a, b, d); glm_vec3_cross(a, b, d);
} }
CGLM_EXPORT CGLM_EXPORT
float float
glmc_vec_norm(vec3 vec) { glmc_vec3_norm(vec3 v) {
return glm_vec_norm(vec); return glm_vec3_norm(v);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_normalize_to(vec3 vec, vec3 dest) { glmc_vec3_normalize_to(vec3 v, vec3 dest) {
glm_vec_normalize_to(vec, dest); glm_vec3_normalize_to(v, dest);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_normalize(vec3 v) { glmc_vec3_normalize(vec3 v) {
glm_vec_normalize(v); glm_vec3_normalize(v);
} }
CGLM_EXPORT CGLM_EXPORT
float float
glmc_vec_norm2(vec3 vec) { glmc_vec3_norm2(vec3 v) {
return glm_vec_norm2(vec); return glm_vec3_norm2(v);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_add(vec3 v1, vec3 v2, vec3 dest) { glmc_vec3_add(vec3 a, vec3 b, vec3 dest) {
glm_vec_add(v1, v2, dest); glm_vec3_add(a, b, dest);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_sub(vec3 v1, vec3 v2, vec3 dest) { glmc_vec3_adds(vec3 v, float s, vec3 dest) {
glm_vec_sub(v1, v2, dest); glm_vec3_adds(v, s, dest);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_scale(vec3 v, float s, vec3 dest) { glmc_vec3_sub(vec3 a, vec3 b, vec3 dest) {
glm_vec_scale(v, s, dest); glm_vec3_sub(a, b, dest);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_scale_as(vec3 v, float s, vec3 dest) { glmc_vec3_subs(vec3 v, float s, vec3 dest) {
glm_vec_scale_as(v, s, dest); glm_vec3_subs(v, s, dest);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_flipsign(vec3 v) { glmc_vec3_mul(vec3 a, vec3 b, vec3 d) {
glm_vec_flipsign(v); glm_vec3_mul(a, b, d);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_inv(vec3 v) { glmc_vec3_scale(vec3 v, float s, vec3 dest) {
glm_vec_inv(v); glm_vec3_scale(v, s, dest);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_inv_to(vec3 v, vec3 dest) { glmc_vec3_scale_as(vec3 v, float s, vec3 dest) {
glm_vec_inv_to(v, dest); glm_vec3_scale_as(v, s, dest);
}
CGLM_EXPORT
void
glmc_vec3_div(vec3 a, vec3 b, vec3 dest) {
glm_vec3_div(a, b, dest);
}
CGLM_EXPORT
void
glmc_vec3_divs(vec3 a, float s, vec3 dest) {
glm_vec3_divs(a, s, dest);
}
CGLM_EXPORT
void
glmc_vec3_addadd(vec3 a, vec3 b, vec3 dest) {
glm_vec3_addadd(a, b, dest);
}
CGLM_EXPORT
void
glmc_vec3_subadd(vec3 a, vec3 b, vec3 dest) {
glm_vec3_subadd(a, b, dest);
}
CGLM_EXPORT
void
glmc_vec3_muladd(vec3 a, vec3 b, vec3 dest) {
glm_vec3_muladd(a, b, dest);
}
CGLM_EXPORT
void
glmc_vec3_muladds(vec3 a, float s, vec3 dest) {
glm_vec3_muladds(a, s, dest);
}
CGLM_EXPORT
void
glmc_vec3_maxadd(vec3 a, vec3 b, vec3 dest) {
glm_vec3_maxadd(a, b, dest);
}
CGLM_EXPORT
void
glmc_vec3_minadd(vec3 a, vec3 b, vec3 dest) {
glm_vec3_minadd(a, b, dest);
}
CGLM_EXPORT
void
glmc_vec3_negate(vec3 v) {
glm_vec3_negate(v);
}
CGLM_EXPORT
void
glmc_vec3_negate_to(vec3 v, vec3 dest) {
glm_vec3_negate_to(v, dest);
} }
CGLM_EXPORT CGLM_EXPORT
float float
glmc_vec_angle(vec3 v1, vec3 v2) { glmc_vec3_angle(vec3 a, vec3 b) {
return glm_vec_angle(v1, v2); return glm_vec3_angle(a, b);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_rotate(vec3 v, float angle, vec3 axis) { glmc_vec3_rotate(vec3 v, float angle, vec3 axis) {
glm_vec_rotate(v, angle, axis); glm_vec3_rotate(v, angle, axis);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_rotate_m4(mat4 m, vec3 v, vec3 dest) { glmc_vec3_rotate_m4(mat4 m, vec3 v, vec3 dest) {
glm_vec_rotate_m4(m, v, dest); glm_vec3_rotate_m4(m, v, dest);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_proj(vec3 a, vec3 b, vec3 dest) { glmc_vec3_rotate_m3(mat3 m, vec3 v, vec3 dest) {
glm_vec_proj(a, b, dest); glm_vec3_rotate_m3(m, v, dest);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_center(vec3 v1, vec3 v2, vec3 dest) { glmc_vec3_proj(vec3 a, vec3 b, vec3 dest) {
glm_vec_center(v1, v2, dest); glm_vec3_proj(a, b, dest);
}
CGLM_EXPORT
void
glmc_vec3_center(vec3 a, vec3 b, vec3 dest) {
glm_vec3_center(a, b, dest);
} }
CGLM_EXPORT CGLM_EXPORT
float float
glmc_vec_distance(vec3 v1, vec3 v2) { glmc_vec3_distance2(vec3 a, vec3 b) {
return glm_vec_distance(v1, v2); return glm_vec3_distance2(a, b);
}
CGLM_EXPORT
float
glmc_vec3_distance(vec3 a, vec3 b) {
return glm_vec3_distance(a, b);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_maxv(vec3 v1, vec3 v2, vec3 dest) { glmc_vec3_maxv(vec3 a, vec3 b, vec3 dest) {
glm_vec_minv(v1, v2, dest); glm_vec3_minv(a, b, dest);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec_minv(vec3 v1, vec3 v2, vec3 dest) { glmc_vec3_minv(vec3 a, vec3 b, vec3 dest) {
glm_vec_maxv(v1, v2, dest); glm_vec3_maxv(a, b, dest);
}
CGLM_EXPORT
void
glmc_vec3_clamp(vec3 v, float minVal, float maxVal) {
glm_vec3_clamp(v, minVal, maxVal);
}
CGLM_EXPORT
void
glmc_vec3_ortho(vec3 v, vec3 dest) {
glm_vec3_ortho(v, dest);
}
CGLM_EXPORT
void
glmc_vec3_lerp(vec3 from, vec3 to, float t, vec3 dest) {
glm_vec3_lerp(from, to, t, dest);
}
/* ext */
CGLM_EXPORT
void
glmc_vec3_mulv(vec3 a, vec3 b, vec3 d) {
glm_vec3_mulv(a, b, d);
}
CGLM_EXPORT
void
glmc_vec3_broadcast(float val, vec3 d) {
glm_vec3_broadcast(val, d);
}
CGLM_EXPORT
bool
glmc_vec3_eq(vec3 v, float val) {
return glm_vec3_eq(v, val);
}
CGLM_EXPORT
bool
glmc_vec3_eq_eps(vec3 v, float val) {
return glm_vec3_eq_eps(v, val);
}
CGLM_EXPORT
bool
glmc_vec3_eq_all(vec3 v) {
return glm_vec3_eq_all(v);
}
CGLM_EXPORT
bool
glmc_vec3_eqv(vec3 a, vec3 b) {
return glm_vec3_eqv(a, b);
}
CGLM_EXPORT
bool
glmc_vec3_eqv_eps(vec3 a, vec3 b) {
return glm_vec3_eqv_eps(a, b);
}
CGLM_EXPORT
float
glmc_vec3_max(vec3 v) {
return glm_vec3_max(v);
}
CGLM_EXPORT
float
glmc_vec3_min(vec3 v) {
return glm_vec3_min(v);
}
CGLM_EXPORT
bool
glmc_vec3_isnan(vec3 v) {
return glm_vec3_isnan(v);
}
CGLM_EXPORT
bool
glmc_vec3_isinf(vec3 v) {
return glm_vec3_isinf(v);
}
CGLM_EXPORT
bool
glmc_vec3_isvalid(vec3 v) {
return glm_vec3_isvalid(v);
}
CGLM_EXPORT
void
glmc_vec3_sign(vec3 v, vec3 dest) {
glm_vec3_sign(v, dest);
}
CGLM_EXPORT
void
glmc_vec3_sqrt(vec3 v, vec3 dest) {
glm_vec3_sqrt(v, dest);
} }

View File

@@ -10,8 +10,26 @@
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec4_copy3(vec4 a, vec3 dest) { glmc_vec4(vec3 v3, float last, vec4 dest) {
glm_vec4_copy3(a, dest); glm_vec4(v3, last, dest);
}
CGLM_EXPORT
void
glmc_vec4_zero(vec4 v) {
glm_vec4_zero(v);
}
CGLM_EXPORT
void
glmc_vec4_one(vec4 v) {
glm_vec4_one(v);
}
CGLM_EXPORT
void
glmc_vec4_copy3(vec4 v, vec3 dest) {
glm_vec4_copy3(v, dest);
} }
CGLM_EXPORT CGLM_EXPORT
@@ -20,6 +38,12 @@ glmc_vec4_copy(vec4 v, vec4 dest) {
glm_vec4_copy(v, dest); glm_vec4_copy(v, dest);
} }
CGLM_EXPORT
void
glmc_vec4_ucopy(vec4 v, vec4 dest) {
glm_vec4_ucopy(v, dest);
}
CGLM_EXPORT CGLM_EXPORT
float float
glmc_vec4_dot(vec4 a, vec4 b) { glmc_vec4_dot(vec4 a, vec4 b) {
@@ -28,14 +52,14 @@ glmc_vec4_dot(vec4 a, vec4 b) {
CGLM_EXPORT CGLM_EXPORT
float float
glmc_vec4_norm(vec4 vec) { glmc_vec4_norm(vec4 v) {
return glm_vec4_norm(vec); return glm_vec4_norm(v);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec4_normalize_to(vec4 vec, vec4 dest) { glmc_vec4_normalize_to(vec4 v, vec4 dest) {
glm_vec4_normalize_to(vec, dest); glm_vec4_normalize_to(v, dest);
} }
CGLM_EXPORT CGLM_EXPORT
@@ -46,20 +70,38 @@ glmc_vec4_normalize(vec4 v) {
CGLM_EXPORT CGLM_EXPORT
float float
glmc_vec4_norm2(vec4 vec) { glmc_vec4_norm2(vec4 v) {
return glm_vec4_norm2(vec); return glm_vec4_norm2(v);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec4_add(vec4 v1, vec4 v2, vec4 dest) { glmc_vec4_add(vec4 a, vec4 b, vec4 dest) {
glm_vec4_add(v1, v2, dest); glm_vec4_add(a, b, dest);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec4_sub(vec4 v1, vec4 v2, vec4 dest) { glmc_vec4_adds(vec4 v, float s, vec4 dest) {
glm_vec4_sub(v1, v2, dest); glm_vec4_adds(v, s, dest);
}
CGLM_EXPORT
void
glmc_vec4_sub(vec4 a, vec4 b, vec4 dest) {
glm_vec4_sub(a, b, dest);
}
CGLM_EXPORT
void
glmc_vec4_subs(vec4 v, float s, vec4 dest) {
glm_vec4_subs(v, s, dest);
}
CGLM_EXPORT
void
glmc_vec4_mul(vec4 a, vec4 b, vec4 d) {
glm_vec4_mul(a, b, d);
} }
CGLM_EXPORT CGLM_EXPORT
@@ -70,42 +112,182 @@ glmc_vec4_scale(vec4 v, float s, vec4 dest) {
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec4_scale_as(vec3 v, float s, vec3 dest) { glmc_vec4_scale_as(vec4 v, float s, vec4 dest) {
glm_vec4_scale_as(v, s, dest); glm_vec4_scale_as(v, s, dest);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec4_flipsign(vec4 v) { glmc_vec4_div(vec4 a, vec4 b, vec4 dest) {
glm_vec4_flipsign(v); glm_vec4_div(a, b, dest);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec4_inv(vec4 v) { glmc_vec4_divs(vec4 v, float s, vec4 dest) {
glm_vec4_inv(v); glm_vec4_divs(v, s, dest);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec4_inv_to(vec4 v, vec4 dest) { glmc_vec4_addadd(vec4 a, vec4 b, vec4 dest) {
glm_vec4_inv_to(v, dest); glm_vec4_addadd(a, b, dest);
}
CGLM_EXPORT
void
glmc_vec4_subadd(vec4 a, vec4 b, vec4 dest) {
glm_vec4_subadd(a, b, dest);
}
CGLM_EXPORT
void
glmc_vec4_muladd(vec4 a, vec4 b, vec4 dest) {
glm_vec4_muladd(a, b, dest);
}
CGLM_EXPORT
void
glmc_vec4_muladds(vec4 a, float s, vec4 dest) {
glm_vec4_muladds(a, s, dest);
}
CGLM_EXPORT
void
glmc_vec4_maxadd(vec4 a, vec4 b, vec4 dest) {
glm_vec4_maxadd(a, b, dest);
}
CGLM_EXPORT
void
glmc_vec4_minadd(vec4 a, vec4 b, vec4 dest) {
glm_vec4_minadd(a, b, dest);
}
CGLM_EXPORT
void
glmc_vec4_negate(vec4 v) {
glm_vec4_negate(v);
}
CGLM_EXPORT
void
glmc_vec4_negate_to(vec4 v, vec4 dest) {
glm_vec4_negate_to(v, dest);
} }
CGLM_EXPORT CGLM_EXPORT
float float
glmc_vec4_distance(vec4 v1, vec4 v2) { glmc_vec4_distance(vec4 a, vec4 b) {
return glm_vec4_distance(v1, v2); return glm_vec4_distance(a, b);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec4_maxv(vec4 v1, vec4 v2, vec4 dest) { glmc_vec4_maxv(vec4 a, vec4 b, vec4 dest) {
glm_vec4_minv(v1, v2, dest); glm_vec4_minv(a, b, dest);
} }
CGLM_EXPORT CGLM_EXPORT
void void
glmc_vec4_minv(vec4 v1, vec4 v2, vec4 dest) { glmc_vec4_minv(vec4 a, vec4 b, vec4 dest) {
glm_vec4_maxv(v1, v2, dest); glm_vec4_maxv(a, b, dest);
}
CGLM_EXPORT
void
glmc_vec4_clamp(vec4 v, float minVal, float maxVal) {
glm_vec4_clamp(v, minVal, maxVal);
}
CGLM_EXPORT
void
glmc_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest) {
glm_vec4_lerp(from, to, t, dest);
}
/* ext */
CGLM_EXPORT
void
glmc_vec4_mulv(vec4 a, vec4 b, vec4 d) {
glm_vec4_mulv(a, b, d);
}
CGLM_EXPORT
void
glmc_vec4_broadcast(float val, vec4 d) {
glm_vec4_broadcast(val, d);
}
CGLM_EXPORT
bool
glmc_vec4_eq(vec4 v, float val) {
return glm_vec4_eq(v, val);
}
CGLM_EXPORT
bool
glmc_vec4_eq_eps(vec4 v, float val) {
return glm_vec4_eq_eps(v, val);
}
CGLM_EXPORT
bool
glmc_vec4_eq_all(vec4 v) {
return glm_vec4_eq_all(v);
}
CGLM_EXPORT
bool
glmc_vec4_eqv(vec4 a, vec4 b) {
return glm_vec4_eqv(a, b);
}
CGLM_EXPORT
bool
glmc_vec4_eqv_eps(vec4 a, vec4 b) {
return glm_vec4_eqv_eps(a, b);
}
CGLM_EXPORT
float
glmc_vec4_max(vec4 v) {
return glm_vec4_max(v);
}
CGLM_EXPORT
float
glmc_vec4_min(vec4 v) {
return glm_vec4_min(v);
}
CGLM_EXPORT
bool
glmc_vec4_isnan(vec4 v) {
return glm_vec4_isnan(v);
}
CGLM_EXPORT
bool
glmc_vec4_isinf(vec4 v) {
return glm_vec4_isinf(v);
}
CGLM_EXPORT
bool
glmc_vec4_isvalid(vec4 v) {
return glm_vec4_isvalid(v);
}
CGLM_EXPORT
void
glmc_vec4_sign(vec4 v, vec4 dest) {
glm_vec4_sign(v, dest);
}
CGLM_EXPORT
void
glmc_vec4_sqrt(vec4 v, vec4 dest) {
glm_vec4_sqrt(v, dest);
} }

113
test/src/test_affine.c Normal file
View File

@@ -0,0 +1,113 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#include "test_common.h"
void
test_affine(void **state) {
mat4 t1, t2, t3, t4, t5;
/* test translate is postmultiplied */
glmc_rotate_make(t1, GLM_PI_4f, GLM_YUP);
glm_translate_make(t2, (vec3){34, 57, 36});
glmc_mat4_mul(t1, t2, t3); /* R * T */
glm_translate(t1, (vec3){34, 57, 36});
test_assert_mat4_eq(t1, t3);
/* test rotate is postmultiplied */
glmc_rotate_make(t1, GLM_PI_4f, GLM_YUP);
glm_translate_make(t2, (vec3){34, 57, 36});
glmc_mat4_mul(t2, t1, t3); /* T * R */
glm_rotate(t2, GLM_PI_4f, GLM_YUP);
test_assert_mat4_eq(t2, t3);
/* test scale is postmultiplied */
glmc_rotate_make(t1, GLM_PI_4f, GLM_YUP);
glm_translate_make(t2, (vec3){34, 57, 36});
glm_scale_make(t4, (vec3){3, 5, 6});
glmc_mat4_mul(t2, t1, t3); /* T * R */
glmc_mat4_mul(t3, t4, t5); /* T * R * S */
glm_scale(t3, (vec3){3, 5, 6});
test_assert_mat4_eq(t3, t5);
/* test translate_x */
glmc_rotate_make(t1, GLM_PI_4f, GLM_YUP);
glm_translate_make(t2, (vec3){34, 0, 0});
glmc_mat4_mul(t1, t2, t3); /* R * T */
glm_translate_x(t1, 34);
test_assert_mat4_eq(t1, t3);
/* test translate_y */
glmc_rotate_make(t1, GLM_PI_4f, GLM_YUP);
glm_translate_make(t2, (vec3){0, 57, 0});
glmc_mat4_mul(t1, t2, t3); /* R * T */
glm_translate_y(t1, 57);
test_assert_mat4_eq(t1, t3);
/* test translate_z */
glmc_rotate_make(t1, GLM_PI_4f, GLM_YUP);
glm_translate_make(t2, (vec3){0, 0, 36});
glmc_mat4_mul(t1, t2, t3); /* R * T */
glm_translate_z(t1, 36);
test_assert_mat4_eq(t1, t3);
/* test rotate_x */
glmc_rotate_make(t1, GLM_PI_4f, (vec3){1, 0, 0});
glm_translate_make(t2, (vec3){34, 57, 36});
glmc_mat4_mul(t2, t1, t3); /* T * R */
glm_rotate_x(t2, GLM_PI_4f, t2);
test_assert_mat4_eq(t2, t3);
/* test rotate_y */
glmc_rotate_make(t1, GLM_PI_4f, (vec3){0, 1, 0});
glm_translate_make(t2, (vec3){34, 57, 36});
glmc_mat4_mul(t2, t1, t3); /* T * R */
glm_rotate_y(t2, GLM_PI_4f, t2);
test_assert_mat4_eq(t2, t3);
/* test rotate_z */
glmc_rotate_make(t1, GLM_PI_4f, (vec3){0, 0, 1});
glm_translate_make(t2, (vec3){34, 57, 36});
glmc_mat4_mul(t2, t1, t3); /* T * R */
glm_rotate_z(t2, GLM_PI_4f, t2);
test_assert_mat4_eq(t2, t3);
/* test rotate */
glmc_rotate_make(t1, GLM_PI_4f, (vec3){0, 0, 1});
glm_translate_make(t2, (vec3){34, 57, 36});
glmc_mat4_mul(t2, t1, t3); /* T * R */
glmc_rotate(t2, GLM_PI_4f, (vec3){0, 0, 1});
test_assert_mat4_eq(t3, t2);
/* test scale_uni */
glmc_rotate_make(t1, GLM_PI_4f, GLM_YUP);
glm_translate_make(t2, (vec3){34, 57, 36});
glm_scale_make(t4, (vec3){3, 3, 3});
glmc_mat4_mul(t2, t1, t3); /* T * R */
glmc_mat4_mul(t3, t4, t5); /* T * R * S */
glm_scale_uni(t3, 3);
test_assert_mat4_eq(t3, t5);
}

View File

@@ -16,7 +16,7 @@ test_camera_lookat(void **state) {
up = {0.0f, 1.0f, 0.0f} up = {0.0f, 1.0f, 0.0f}
; ;
glm_vec_add(eye, dir, center); glm_vec3_add(eye, dir, center);
glm_lookat(eye, center, up, view1); glm_lookat(eye, center, up, view1);
glm_look(eye, dir, up, view2); glm_look(eye, dir, up, view2);

30
test/src/test_clamp.c Normal file
View File

@@ -0,0 +1,30 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#include "test_common.h"
void
test_clamp(void **state) {
vec3 v3 = {15.07, 0.4, 17.3};
vec4 v4 = {5.07, 2.3, 1.3, 1.4};
assert_true(glm_clamp(1.6f, 0.0f, 1.0f) == 1.0f);
assert_true(glm_clamp(-1.6f, 0.0f, 1.0f) == 0.0f);
assert_true(glm_clamp(0.6f, 0.0f, 1.0f) == 0.6f);
glm_vec3_clamp(v3, 0.0, 1.0);
glm_vec4_clamp(v4, 1.5, 3.0);
assert_true(v3[0] == 1.0f);
assert_true(v3[1] == 0.4f);
assert_true(v3[2] == 1.0f);
assert_true(v4[0] == 3.0f);
assert_true(v4[1] == 2.3f);
assert_true(v4[2] == 1.5f);
assert_true(v4[3] == 1.5f);
}

View File

@@ -27,6 +27,50 @@ test_rand_mat4(mat4 dest) {
/* glm_scale(dest, (vec3){drand48(), drand48(), drand48()}); */ /* glm_scale(dest, (vec3){drand48(), drand48(), drand48()}); */
} }
void
test_rand_mat3(mat3 dest) {
mat4 m4;
srand((unsigned int)time(NULL));
/* random rotatation around random axis with random angle */
glm_rotate_make(m4, drand48(), (vec3){drand48(), drand48(), drand48()});
glm_mat4_pick3(m4, dest);
}
void
test_rand_vec3(vec3 dest) {
srand((unsigned int)time(NULL));
dest[0] = drand48();
dest[1] = drand48();
dest[2] = drand48();
}
void
test_rand_vec4(vec4 dest) {
srand((unsigned int)time(NULL));
dest[0] = drand48();
dest[1] = drand48();
dest[2] = drand48();
dest[3] = drand48();
}
float
test_rand_angle(void) {
srand((unsigned int)time(NULL));
return drand48();
}
void
test_rand_quat(versor q) {
srand((unsigned int)time(NULL));
glm_quat(q, drand48(), drand48(), drand48(), drand48());
glm_quat_normalize(q);
}
void void
test_assert_mat4_eq(mat4 m1, mat4 m2) { test_assert_mat4_eq(mat4 m1, mat4 m2) {
int i, j, k; int i, j, k;
@@ -50,3 +94,52 @@ test_assert_mat4_eq2(mat4 m1, mat4 m2, float eps) {
} }
} }
} }
void
test_assert_mat3_eq(mat3 m1, mat3 m2) {
int i, j, k;
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
for (k = 0; k < 3; k++)
assert_true(fabsf(m1[i][j] - m2[i][j]) <= 0.0000009);
}
}
}
void
test_assert_eqf(float a, float b) {
assert_true(fabsf(a - b) <= 0.000009); /* rounding errors */
}
void
test_assert_vec3_eq(vec3 v1, vec3 v2) {
assert_true(fabsf(v1[0] - v2[0]) <= 0.000009); /* rounding errors */
assert_true(fabsf(v1[1] - v2[1]) <= 0.000009);
assert_true(fabsf(v1[2] - v2[2]) <= 0.000009);
}
void
test_assert_vec4_eq(vec4 v1, vec4 v2) {
assert_true(fabsf(v1[0] - v2[0]) <= 0.000009); /* rounding errors */
assert_true(fabsf(v1[1] - v2[1]) <= 0.000009);
assert_true(fabsf(v1[2] - v2[2]) <= 0.000009);
assert_true(fabsf(v1[3] - v2[3]) <= 0.000009);
}
void
test_assert_quat_eq_abs(versor v1, versor v2) {
assert_true(fabsf(fabsf(v1[0]) - fabsf(v2[0])) <= 0.0009); /* rounding errors */
assert_true(fabsf(fabsf(v1[1]) - fabsf(v2[1])) <= 0.0009);
assert_true(fabsf(fabsf(v1[2]) - fabsf(v2[2])) <= 0.0009);
assert_true(fabsf(fabsf(v1[3]) - fabsf(v2[3])) <= 0.0009);
}
void
test_assert_quat_eq(versor v1, versor v2) {
assert_true(fabsf(v1[0] - v2[0]) <= 0.000009); /* rounding errors */
assert_true(fabsf(v1[1] - v2[1]) <= 0.000009);
assert_true(fabsf(v1[2] - v2[2]) <= 0.000009);
assert_true(fabsf(v1[3] - v2[3]) <= 0.000009);
}

View File

@@ -25,10 +25,43 @@
void void
test_rand_mat4(mat4 dest); test_rand_mat4(mat4 dest);
void
test_rand_mat3(mat3 dest);
void
test_assert_eqf(float a, float b);
void void
test_assert_mat4_eq(mat4 m1, mat4 m2); test_assert_mat4_eq(mat4 m1, mat4 m2);
void void
test_assert_mat4_eq2(mat4 m1, mat4 m2, float eps); test_assert_mat4_eq2(mat4 m1, mat4 m2, float eps);
void
test_assert_mat3_eq(mat3 m1, mat3 m2);
void
test_assert_vec3_eq(vec3 v1, vec3 v2);
void
test_assert_vec4_eq(vec4 v1, vec4 v2);
void
test_assert_quat_eq(versor v1, versor v2);
void
test_assert_quat_eq_abs(versor v1, versor v2);
void
test_rand_vec3(vec3 dest);
void
test_rand_vec4(vec4 dest) ;
float
test_rand_angle(void);
void
test_rand_quat(versor q);
#endif /* test_common_h */ #endif /* test_common_h */

44
test/src/test_euler.c Normal file
View File

@@ -0,0 +1,44 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#include "test_common.h"
void
test_euler(void **state) {
mat4 rot1, rot2;
vec3 inAngles, outAngles;
inAngles[0] = glm_rad(-45.0f); /* X angle */
inAngles[1] = glm_rad(88.0f); /* Y angle */
inAngles[2] = glm_rad(18.0f); /* Z angle */
glm_euler_xyz(inAngles, rot1);
/* extract angles */
glmc_euler_angles(rot1, outAngles);
/* angles must be equal in that range */
test_assert_vec3_eq(inAngles, outAngles);
/* matrices must be equal */
glmc_euler_xyz(outAngles, rot2);
test_assert_mat4_eq(rot1, rot2);
/* change range */
inAngles[0] = glm_rad(-145.0f); /* X angle */
inAngles[1] = glm_rad(818.0f); /* Y angle */
inAngles[2] = glm_rad(181.0f); /* Z angle */
glm_euler_xyz(inAngles, rot1);
glmc_euler_angles(rot1, outAngles);
/* angles may not be equal but matrices MUST! */
/* matrices must be equal */
glmc_euler_xyz(outAngles, rot2);
test_assert_mat4_eq(rot1, rot2);
}

View File

@@ -12,9 +12,33 @@ main(int argc, const char * argv[]) {
/* mat4 */ /* mat4 */
cmocka_unit_test(test_mat4), cmocka_unit_test(test_mat4),
/* mat3 */
cmocka_unit_test(test_mat3),
/* camera */ /* camera */
cmocka_unit_test(test_camera_lookat), cmocka_unit_test(test_camera_lookat),
cmocka_unit_test(test_camera_decomp) cmocka_unit_test(test_camera_decomp),
/* project */
cmocka_unit_test(test_project),
/* vector */
cmocka_unit_test(test_clamp),
/* euler */
cmocka_unit_test(test_euler),
/* quaternion */
cmocka_unit_test(test_quat),
/* vec4 */
cmocka_unit_test(test_vec4),
/* vec3 */
cmocka_unit_test(test_vec3),
/* affine */
cmocka_unit_test(test_affine)
}; };
return cmocka_run_group_tests(tests, NULL, NULL); return cmocka_run_group_tests(tests, NULL, NULL);

58
test/src/test_mat3.c Normal file
View File

@@ -0,0 +1,58 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#include "test_common.h"
#define m 3
#define n 3
void
test_mat3(void **state) {
mat3 m1 = GLM_MAT3_IDENTITY_INIT;
mat3 m2 = GLM_MAT3_IDENTITY_INIT;
mat3 m3;
mat3 m4 = GLM_MAT3_ZERO_INIT;
mat3 m5;
int i, j, k;
/* test identity matrix multiplication */
glmc_mat3_mul(m1, m2, m3);
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
if (i == j)
assert_true(m3[i][j] == 1.0f);
else
assert_true(m3[i][j] == 0.0f);
}
}
/* test random matrices */
/* random matrices */
test_rand_mat3(m1);
test_rand_mat3(m2);
glmc_mat3_mul(m1, m2, m3);
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
for (k = 0; k < m; k++)
/* column-major */
m4[i][j] += m1[k][j] * m2[i][k];
}
}
test_assert_mat3_eq(m3, m4);
for (i = 0; i < 100000; i++) {
test_rand_mat3(m3);
test_rand_mat3(m4);
/* test inverse precise */
glmc_mat3_inv(m3, m4);
glmc_mat3_inv(m4, m5);
test_assert_mat3_eq(m3, m5);
}
}

31
test/src/test_project.c Normal file
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
*/
#include "test_common.h"
void
test_project(void **state) {
mat4 model, view, proj, mvp;
vec4 viewport = {0.0f, 0.0f, 800.0f, 600.0f};
vec3 pos = {13.0f, 45.0f, 0.74f};
vec3 projected, unprojected;
glm_translate_make(model, (vec3){0.0f, 0.0f, -10.0f});
glm_lookat((vec3){0.0f, 0.0f, 0.0f}, pos, GLM_YUP, view);
glm_perspective_default(0.5f, proj);
glm_mat4_mulN((mat4 *[]){&proj, &view, &model}, 3, mvp);
glmc_project(pos, mvp, viewport, projected);
glmc_unproject(projected, mvp, viewport, unprojected);
/* unprojected of projected vector must be same as original one */
/* we used 0.01 because of projection floating point errors */
assert_true(fabsf(pos[0] - unprojected[0]) < 0.01);
assert_true(fabsf(pos[1] - unprojected[1]) < 0.01);
assert_true(fabsf(pos[2] - unprojected[2]) < 0.01);
}

199
test/src/test_quat.c Normal file
View File

@@ -0,0 +1,199 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#include "test_common.h"
CGLM_INLINE
void
test_quat_mul_raw(versor p, versor q, versor dest) {
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];
}
void
test_quat(void **state) {
mat4 inRot, outRot, view1, view2, rot1, rot2;
versor inQuat, outQuat, q3, q4, q5;
vec3 eye, axis, imag, v1, v2;
int i;
/* 0. test identiy quat */
glm_quat_identity(q4);
assert_true(glm_quat_real(q4) == cosf(glm_rad(0.0f) * 0.5f));
glm_quat_mat4(q4, rot1);
test_assert_mat4_eq2(rot1, GLM_MAT4_IDENTITY, 0.000009);
/* 1. test quat to mat and mat to quat */
for (i = 0; i < 1000; i++) {
test_rand_quat(inQuat);
glmc_quat_mat4(inQuat, inRot);
glmc_mat4_quat(inRot, outQuat);
glmc_quat_mat4(outQuat, outRot);
/* 2. test first quat and generated one equality */
test_assert_quat_eq_abs(inQuat, outQuat);
/* 3. test first rot and second rotation */
test_assert_mat4_eq2(inRot, outRot, 0.000009); /* almost equal */
/* 4. test SSE mul and raw mul */
test_quat_mul_raw(inQuat, outQuat, q3);
glm_quat_mul_sse2(inQuat, outQuat, q4);
test_assert_quat_eq(q3, q4);
}
/* 5. test lookat */
test_rand_vec3(eye);
glm_quatv(q3, glm_rad(-90.0f), GLM_YUP);
/* now X axis must be forward axis, Z must be right axis */
glm_look(eye, GLM_XUP, GLM_YUP, view1);
/* create view matrix with quaternion */
glm_quat_look(eye, q3, view2);
test_assert_mat4_eq2(view1, view2, 0.000009);
/* 6. test quaternion rotation matrix result */
test_rand_quat(q3);
glm_quat_mat4(q3, rot1);
/* 6.1 test axis and angle of quat */
glm_quat_axis(q3, axis);
glm_rotate_make(rot2, glm_quat_angle(q3), axis);
test_assert_mat4_eq2(rot1, rot2, 0.000009);
/* 7. test quaternion multiplication (hamilton product),
final rotation = first rotation + second = quat1 * quat2
*/
test_rand_quat(q3);
test_rand_quat(q4);
glm_quat_mul(q3, q4, q5);
glm_quat_axis(q3, axis);
glm_rotate_make(rot1, glm_quat_angle(q3), axis);
glm_quat_axis(q4, axis);
glm_rotate(rot1, glm_quat_angle(q4), axis);
/* rot2 is combine of two rotation now test with quaternion result */
glm_quat_mat4(q5, rot2);
/* result must be same (almost) */
test_assert_mat4_eq2(rot1, rot2, 0.000009);
/* 8. test quaternion for look rotation */
/* 8.1 same direction */
/* look at from 0, 0, 1 to zero, direction = 0, 0, -1 */
glm_quat_for((vec3){0, 0, -1}, (vec3){0, 0, -1}, GLM_YUP, q3);
/* result must be identity */
glm_quat_identity(q4);
test_assert_quat_eq(q3, q4);
/* look at from 0, 0, 1 to zero, direction = 0, 0, -1 */
glm_quat_forp(GLM_ZUP, GLM_VEC3_ZERO, (vec3){0, 0, -1}, GLM_YUP, q3);
/* result must be identity */
glm_quat_identity(q4);
test_assert_quat_eq(q3, q4);
/* 8.2 perpendicular */
glm_quat_for(GLM_XUP, (vec3){0, 0, -1}, GLM_YUP, q3);
/* result must be -90 */
glm_quatv(q4, glm_rad(-90.0f), GLM_YUP);
test_assert_quat_eq(q3, q4);
/* 9. test imag, real */
/* 9.1 real */
assert_true(glm_quat_real(q4) == cosf(glm_rad(-90.0f) * 0.5f));
/* 9.1 imag */
glm_quat_imag(q4, imag);
/* axis = Y_UP * sinf(angle * 0.5), YUP = 0, 1, 0 */
axis[0] = 0.0f;
axis[1] = sinf(glm_rad(-90.0f) * 0.5f) * 1.0f;
axis[2] = 0.0f;
assert_true(glm_vec3_eqv_eps(imag, axis));
/* 9.2 axis */
glm_quat_axis(q4, axis);
imag[0] = 0.0f;
imag[1] = -1.0f;
imag[2] = 0.0f;
test_assert_vec3_eq(imag, axis);
/* 10. test rotate vector using quat */
/* (0,0,-1) around (1,0,0) must give (0,1,0) */
v1[0] = 0.0f; v1[1] = 0.0f; v1[2] = -1.0f;
v2[0] = 0.0f; v2[1] = 0.0f; v2[2] = -1.0f;
glm_vec3_rotate(v1, glm_rad(90.0f), (vec3){1.0f, 0.0f, 0.0f});
glm_quatv(q3, glm_rad(90.0f), (vec3){1.0f, 0.0f, 0.0f});
glm_vec4_scale(q3, 1.5, q3);
glm_quat_rotatev(q3, v2, v2);
/* result must be : (0,1,0) */
assert_true(fabsf(v1[0]) <= 0.00009f
&& fabsf(v1[1] - 1.0f) <= 0.00009f
&& fabsf(v1[2]) <= 0.00009f);
test_assert_vec3_eq(v1, v2);
/* 11. test rotate transform */
glm_translate_make(rot1, (vec3){-10.0, 45.0f, 8.0f});
glm_rotate(rot1, glm_rad(-90), GLM_ZUP);
glm_quatv(q3, glm_rad(-90.0f), GLM_ZUP);
glm_translate_make(rot2, (vec3){-10.0, 45.0f, 8.0f});
glm_quat_rotate(rot2, q3, rot2);
/* result must be same (almost) */
test_assert_mat4_eq2(rot1, rot2, 0.000009);
glm_rotate_make(rot1, glm_rad(-90), GLM_ZUP);
glm_translate(rot1, (vec3){-10.0, 45.0f, 8.0f});
glm_quatv(q3, glm_rad(-90.0f), GLM_ZUP);
glm_mat4_identity(rot2);
glm_quat_rotate(rot2, q3, rot2);
glm_translate(rot2, (vec3){-10.0, 45.0f, 8.0f});
/* result must be same (almost) */
test_assert_mat4_eq2(rot1, rot2, 0.000009);
/* reverse */
glm_rotate_make(rot1, glm_rad(-90), GLM_ZUP);
glm_quatv(q3, glm_rad(90.0f), GLM_ZUP);
glm_quat_rotate(rot1, q3, rot1);
/* result must be identity */
test_assert_mat4_eq2(rot1, GLM_MAT4_IDENTITY, 0.000009);
test_rand_quat(q3);
/* 12. inverse of quat, multiplication must be IDENTITY */
glm_quat_inv(q3, q4);
glm_quat_mul(q3, q4, q5);
glm_quat_identity(q3);
test_assert_quat_eq(q3, q5);
/* TODO: add tests for slerp, lerp */
}

View File

@@ -9,6 +9,9 @@
/* mat4 */ /* mat4 */
void test_mat4(void **state); void test_mat4(void **state);
/* mat3 */
void test_mat3(void **state);
/* camera */ /* camera */
void void
test_camera_lookat(void **state); test_camera_lookat(void **state);
@@ -16,4 +19,25 @@ test_camera_lookat(void **state);
void void
test_camera_decomp(void **state); test_camera_decomp(void **state);
void
test_project(void **state);
void
test_clamp(void **state);
void
test_euler(void **state);
void
test_quat(void **state);
void
test_vec4(void **state);
void
test_vec3(void **state);
void
test_affine(void **state);
#endif /* test_tests_h */ #endif /* test_tests_h */

78
test/src/test_vec3.c Normal file
View File

@@ -0,0 +1,78 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#include "test_common.h"
void
test_vec3(void **state) {
mat3 rot1m3;
mat4 rot1;
vec3 v, v1, v2;
/* test zero */
glm_vec3_zero(v);
test_assert_vec3_eq(GLM_VEC3_ZERO, v);
/* test one */
glm_vec3_one(v);
test_assert_vec3_eq(GLM_VEC3_ONE, v);
/* adds, subs, div, divs, mul */
glm_vec3_add(v, GLM_VEC3_ONE, v);
assert_true(glmc_vec3_eq_eps(v, 2));
glm_vec3_adds(v, 10, v);
assert_true(glmc_vec3_eq_eps(v, 12));
glm_vec3_sub(v, GLM_VEC3_ONE, v);
assert_true(glmc_vec3_eq_eps(v, 11));
glm_vec3_subs(v, 1, v);
assert_true(glmc_vec3_eq_eps(v, 10));
glm_vec3_broadcast(2, v1);
glm_vec3_div(v, v1, v);
assert_true(glmc_vec3_eq_eps(v, 5));
glm_vec3_divs(v, 0.5, v);
assert_true(glmc_vec3_eq_eps(v, 10));
glm_vec3_mul(v, v1, v);
assert_true(glmc_vec3_eq_eps(v, 20));
glm_vec3_scale(v, 0.5, v);
assert_true(glmc_vec3_eq_eps(v, 10));
glm_vec3_normalize_to(v, v1);
glm_vec3_scale(v1, 0.8, v1);
glm_vec3_scale_as(v, 0.8, v);
test_assert_vec3_eq(v1, v);
/* addadd, subadd, muladd */
glm_vec3_one(v);
glm_vec3_addadd(GLM_VEC3_ONE, GLM_VEC3_ONE, v);
assert_true(glmc_vec3_eq_eps(v, 3));
glm_vec3_subadd(GLM_VEC3_ONE, GLM_VEC3_ZERO, v);
assert_true(glmc_vec3_eq_eps(v, 4));
glm_vec3_broadcast(2, v1);
glm_vec3_broadcast(3, v2);
glm_vec3_muladd(v1, v2, v);
assert_true(glmc_vec3_eq_eps(v, 10));
/* rotate */
glm_vec3_copy(GLM_YUP, v);
glm_rotate_make(rot1, glm_rad(90), GLM_XUP);
glm_vec3_rotate_m4(rot1, v, v1);
glm_mat4_pick3(rot1, rot1m3);
glm_vec3_rotate_m3(rot1m3, v, v2);
test_assert_vec3_eq(v1, v2);
test_assert_vec3_eq(v1, GLM_ZUP);
}

178
test/src/test_vec4.c Normal file
View File

@@ -0,0 +1,178 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#include "test_common.h"
CGLM_INLINE
float
test_vec4_dot(vec4 a, vec4 b) {
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
}
CGLM_INLINE
void
test_vec4_normalize_to(vec4 vec, vec4 dest) {
float norm;
norm = glm_vec4_norm(vec);
if (norm == 0.0f) {
dest[0] = dest[1] = dest[2] = dest[3] = 0.0f;
return;
}
glm_vec4_scale(vec, 1.0f / norm, dest);
}
float
test_vec4_norm2(vec4 vec) {
return test_vec4_dot(vec, vec);
}
float
test_vec4_norm(vec4 vec) {
return sqrtf(test_vec4_dot(vec, vec));
}
void
test_vec4_maxv(vec4 v1, vec4 v2, vec4 dest) {
dest[0] = glm_max(v1[0], v2[0]);
dest[1] = glm_max(v1[1], v2[1]);
dest[2] = glm_max(v1[2], v2[2]);
dest[3] = glm_max(v1[3], v2[3]);
}
void
test_vec4_minv(vec4 v1, vec4 v2, vec4 dest) {
dest[0] = glm_min(v1[0], v2[0]);
dest[1] = glm_min(v1[1], v2[1]);
dest[2] = glm_min(v1[2], v2[2]);
dest[3] = glm_min(v1[3], v2[3]);
}
void
test_vec4_clamp(vec4 v, float minVal, float maxVal) {
v[0] = glm_clamp(v[0], minVal, maxVal);
v[1] = glm_clamp(v[1], minVal, maxVal);
v[2] = glm_clamp(v[2], minVal, maxVal);
v[3] = glm_clamp(v[3], minVal, maxVal);
}
void
test_vec4(void **state) {
vec4 v, v1, v2, v3, v4;
int i;
float d1, d2;
for (i = 0; i < 1000; i++) {
/* 1. test SSE/SIMD dot product */
test_rand_vec4(v);
d1 = glm_vec4_dot(v, v);
d2 = test_vec4_dot(v, v);
assert_true(fabsf(d1 - d2) <= 0.000009);
/* 2. test SIMD normalize */
test_vec4_normalize_to(v, v1);
glm_vec4_normalize_to(v, v2);
glm_vec4_normalize(v);
/* all must be same */
test_assert_vec4_eq(v1, v2);
test_assert_vec4_eq(v, v2);
/* 3. test SIMD norm */
test_rand_vec4(v);
test_assert_eqf(test_vec4_norm(v), glm_vec4_norm(v));
/* 3. test SIMD norm2 */
test_rand_vec4(v);
test_assert_eqf(test_vec4_norm2(v), glm_vec4_norm2(v));
}
/* test zero */
glm_vec4_zero(v);
test_assert_vec4_eq(GLM_VEC4_ZERO, v);
/* test one */
glm_vec4_one(v);
test_assert_vec4_eq(GLM_VEC4_ONE, v);
/* adds, subs, div, divs, mul */
glm_vec4_add(v, GLM_VEC4_ONE, v);
assert_true(glmc_vec4_eq_eps(v, 2));
glm_vec4_adds(v, 10, v);
assert_true(glmc_vec4_eq_eps(v, 12));
glm_vec4_sub(v, GLM_VEC4_ONE, v);
assert_true(glmc_vec4_eq_eps(v, 11));
glm_vec4_subs(v, 1, v);
assert_true(glmc_vec4_eq_eps(v, 10));
glm_vec4_broadcast(2, v1);
glm_vec4_div(v, v1, v);
assert_true(glmc_vec4_eq_eps(v, 5));
glm_vec4_divs(v, 0.5, v);
assert_true(glmc_vec4_eq_eps(v, 10));
glm_vec4_mul(v, v1, v);
assert_true(glmc_vec4_eq_eps(v, 20));
glm_vec4_scale(v, 0.5, v);
assert_true(glmc_vec4_eq_eps(v, 10));
glm_vec4_normalize_to(v, v1);
glm_vec4_scale(v1, 0.8, v1);
glm_vec4_scale_as(v, 0.8, v);
test_assert_vec4_eq(v1, v);
/* addadd, subadd, muladd */
glm_vec4_one(v);
glm_vec4_addadd(GLM_VEC4_ONE, GLM_VEC4_ONE, v);
assert_true(glmc_vec4_eq_eps(v, 3));
glm_vec4_subadd(GLM_VEC4_ONE, GLM_VEC4_ZERO, v);
assert_true(glmc_vec4_eq_eps(v, 4));
glm_vec4_broadcast(2, v1);
glm_vec4_broadcast(3, v2);
glm_vec4_muladd(v1, v2, v);
assert_true(glmc_vec4_eq_eps(v, 10));
/* min, max */
test_rand_vec4(v1);
test_rand_vec4(v2);
glm_vec4_maxv(v1, v2, v3);
test_vec4_maxv(v1, v2, v4);
test_assert_vec4_eq(v3, v4);
glm_vec4_minv(v1, v2, v3);
test_vec4_minv(v1, v2, v4);
test_assert_vec4_eq(v3, v4);
glm_vec4_print(v3, stderr);
glm_vec4_print(v4, stderr);
/* clamp */
glm_vec4_clamp(v3, 0.1, 0.8);
test_vec4_clamp(v4, 0.1, 0.8);
test_assert_vec4_eq(v3, v4);
glm_vec4_print(v3, stderr);
glm_vec4_print(v4, stderr);
assert_true(v3[0] >= 0.0999 && v3[0] <= 0.80001); /* rounding erros */
assert_true(v3[1] >= 0.0999 && v3[1] <= 0.80001);
assert_true(v3[2] >= 0.0999 && v3[2] <= 0.80001);
assert_true(v3[3] >= 0.0999 && v3[3] <= 0.80001);
}

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