summaryrefslogtreecommitdiff
path: root/libs/cglm/include
diff options
context:
space:
mode:
Diffstat (limited to 'libs/cglm/include')
-rw-r--r--libs/cglm/include/cglm/affine-mat.h178
-rw-r--r--libs/cglm/include/cglm/affine.h470
-rw-r--r--libs/cglm/include/cglm/affine2d.h268
-rw-r--r--libs/cglm/include/cglm/applesimd.h95
-rw-r--r--libs/cglm/include/cglm/bezier.h154
-rw-r--r--libs/cglm/include/cglm/box.h281
-rw-r--r--libs/cglm/include/cglm/call.h43
-rw-r--r--libs/cglm/include/cglm/call/affine.h117
-rw-r--r--libs/cglm/include/cglm/call/affine2d.h67
-rw-r--r--libs/cglm/include/cglm/call/bezier.h31
-rw-r--r--libs/cglm/include/cglm/call/box.h79
-rw-r--r--libs/cglm/include/cglm/call/cam.h133
-rw-r--r--libs/cglm/include/cglm/call/clipspace/ortho_lh_no.h46
-rw-r--r--libs/cglm/include/cglm/call/clipspace/ortho_lh_zo.h46
-rw-r--r--libs/cglm/include/cglm/call/clipspace/ortho_rh_no.h46
-rw-r--r--libs/cglm/include/cglm/call/clipspace/ortho_rh_zo.h46
-rw-r--r--libs/cglm/include/cglm/call/clipspace/persp_lh_no.h87
-rw-r--r--libs/cglm/include/cglm/call/clipspace/persp_lh_zo.h87
-rw-r--r--libs/cglm/include/cglm/call/clipspace/persp_rh_no.h87
-rw-r--r--libs/cglm/include/cglm/call/clipspace/persp_rh_zo.h87
-rw-r--r--libs/cglm/include/cglm/call/clipspace/project_no.h27
-rw-r--r--libs/cglm/include/cglm/call/clipspace/project_zo.h27
-rw-r--r--libs/cglm/include/cglm/call/clipspace/view_lh_no.h31
-rw-r--r--libs/cglm/include/cglm/call/clipspace/view_lh_zo.h31
-rw-r--r--libs/cglm/include/cglm/call/clipspace/view_rh_no.h31
-rw-r--r--libs/cglm/include/cglm/call/clipspace/view_rh_zo.h31
-rw-r--r--libs/cglm/include/cglm/call/curve.h23
-rw-r--r--libs/cglm/include/cglm/call/ease.h143
-rw-r--r--libs/cglm/include/cglm/call/euler.h55
-rw-r--r--libs/cglm/include/cglm/call/frustum.h41
-rw-r--r--libs/cglm/include/cglm/call/io.h45
-rw-r--r--libs/cglm/include/cglm/call/ivec2.h79
-rw-r--r--libs/cglm/include/cglm/call/ivec3.h79
-rw-r--r--libs/cglm/include/cglm/call/ivec4.h79
-rw-r--r--libs/cglm/include/cglm/call/mat2.h79
-rw-r--r--libs/cglm/include/cglm/call/mat3.h86
-rw-r--r--libs/cglm/include/cglm/call/mat4.h127
-rw-r--r--libs/cglm/include/cglm/call/plane.h23
-rw-r--r--libs/cglm/include/cglm/call/project.h37
-rw-r--r--libs/cglm/include/cglm/call/quat.h167
-rw-r--r--libs/cglm/include/cglm/call/ray.h27
-rw-r--r--libs/cglm/include/cglm/call/sphere.h39
-rw-r--r--libs/cglm/include/cglm/call/vec2.h167
-rw-r--r--libs/cglm/include/cglm/call/vec3.h312
-rw-r--r--libs/cglm/include/cglm/call/vec4.h290
-rw-r--r--libs/cglm/include/cglm/cam.h582
-rw-r--r--libs/cglm/include/cglm/cglm.h39
-rw-r--r--libs/cglm/include/cglm/clipspace/ortho_lh_no.h183
-rw-r--r--libs/cglm/include/cglm/clipspace/ortho_lh_zo.h177
-rw-r--r--libs/cglm/include/cglm/clipspace/ortho_rh_no.h183
-rw-r--r--libs/cglm/include/cglm/clipspace/ortho_rh_zo.h181
-rw-r--r--libs/cglm/include/cglm/clipspace/persp.h48
-rw-r--r--libs/cglm/include/cglm/clipspace/persp_lh_no.h395
-rw-r--r--libs/cglm/include/cglm/clipspace/persp_lh_zo.h387
-rw-r--r--libs/cglm/include/cglm/clipspace/persp_rh_no.h395
-rw-r--r--libs/cglm/include/cglm/clipspace/persp_rh_zo.h389
-rw-r--r--libs/cglm/include/cglm/clipspace/project_no.h86
-rw-r--r--libs/cglm/include/cglm/clipspace/project_zo.h88
-rw-r--r--libs/cglm/include/cglm/clipspace/view_lh.h99
-rw-r--r--libs/cglm/include/cglm/clipspace/view_lh_no.h74
-rw-r--r--libs/cglm/include/cglm/clipspace/view_lh_zo.h74
-rw-r--r--libs/cglm/include/cglm/clipspace/view_rh.h99
-rw-r--r--libs/cglm/include/cglm/clipspace/view_rh_no.h74
-rw-r--r--libs/cglm/include/cglm/clipspace/view_rh_zo.h74
-rw-r--r--libs/cglm/include/cglm/color.h26
-rw-r--r--libs/cglm/include/cglm/common.h84
-rw-r--r--libs/cglm/include/cglm/curve.h40
-rw-r--r--libs/cglm/include/cglm/ease.h317
-rw-r--r--libs/cglm/include/cglm/euler.h451
-rw-r--r--libs/cglm/include/cglm/frustum.h255
-rw-r--r--libs/cglm/include/cglm/io.h344
-rw-r--r--libs/cglm/include/cglm/ivec2.h242
-rw-r--r--libs/cglm/include/cglm/ivec3.h258
-rw-r--r--libs/cglm/include/cglm/ivec4.h275
-rw-r--r--libs/cglm/include/cglm/mat2.h337
-rw-r--r--libs/cglm/include/cglm/mat3.h424
-rw-r--r--libs/cglm/include/cglm/mat4.h754
-rw-r--r--libs/cglm/include/cglm/plane.h44
-rw-r--r--libs/cglm/include/cglm/project.h150
-rw-r--r--libs/cglm/include/cglm/quat.h867
-rw-r--r--libs/cglm/include/cglm/ray.h77
-rw-r--r--libs/cglm/include/cglm/simd/arm.h173
-rw-r--r--libs/cglm/include/cglm/simd/avx/affine.h66
-rw-r--r--libs/cglm/include/cglm/simd/avx/mat4.h76
-rw-r--r--libs/cglm/include/cglm/simd/intrin.h90
-rw-r--r--libs/cglm/include/cglm/simd/neon/affine.h121
-rw-r--r--libs/cglm/include/cglm/simd/neon/mat2.h44
-rw-r--r--libs/cglm/include/cglm/simd/neon/mat4.h317
-rw-r--r--libs/cglm/include/cglm/simd/neon/quat.h56
-rw-r--r--libs/cglm/include/cglm/simd/sse2/affine.h115
-rw-r--r--libs/cglm/include/cglm/simd/sse2/mat2.h48
-rw-r--r--libs/cglm/include/cglm/simd/sse2/mat3.h76
-rw-r--r--libs/cglm/include/cglm/simd/sse2/mat4.h434
-rw-r--r--libs/cglm/include/cglm/simd/sse2/quat.h54
-rw-r--r--libs/cglm/include/cglm/simd/x86.h307
-rw-r--r--libs/cglm/include/cglm/sphere.h99
-rw-r--r--libs/cglm/include/cglm/struct.h39
-rw-r--r--libs/cglm/include/cglm/struct/affine.h333
-rw-r--r--libs/cglm/include/cglm/struct/affine2d.h177
-rw-r--r--libs/cglm/include/cglm/struct/box.h256
-rw-r--r--libs/cglm/include/cglm/struct/cam.h646
-rw-r--r--libs/cglm/include/cglm/struct/clipspace/ortho_lh_no.h152
-rw-r--r--libs/cglm/include/cglm/struct/clipspace/ortho_lh_zo.h152
-rw-r--r--libs/cglm/include/cglm/struct/clipspace/ortho_rh_no.h152
-rw-r--r--libs/cglm/include/cglm/struct/clipspace/ortho_rh_zo.h152
-rw-r--r--libs/cglm/include/cglm/struct/clipspace/persp_lh_no.h311
-rw-r--r--libs/cglm/include/cglm/struct/clipspace/persp_lh_zo.h311
-rw-r--r--libs/cglm/include/cglm/struct/clipspace/persp_rh_no.h311
-rw-r--r--libs/cglm/include/cglm/struct/clipspace/persp_rh_zo.h311
-rw-r--r--libs/cglm/include/cglm/struct/clipspace/view_lh_no.h88
-rw-r--r--libs/cglm/include/cglm/struct/clipspace/view_lh_zo.h88
-rw-r--r--libs/cglm/include/cglm/struct/clipspace/view_rh_no.h88
-rw-r--r--libs/cglm/include/cglm/struct/clipspace/view_rh_zo.h88
-rw-r--r--libs/cglm/include/cglm/struct/color.h27
-rw-r--r--libs/cglm/include/cglm/struct/curve.h40
-rw-r--r--libs/cglm/include/cglm/struct/euler.h152
-rw-r--r--libs/cglm/include/cglm/struct/frustum.h155
-rw-r--r--libs/cglm/include/cglm/struct/io.h82
-rw-r--r--libs/cglm/include/cglm/struct/mat2.h258
-rw-r--r--libs/cglm/include/cglm/struct/mat3.h285
-rw-r--r--libs/cglm/include/cglm/struct/mat4.h459
-rw-r--r--libs/cglm/include/cglm/struct/plane.h40
-rw-r--r--libs/cglm/include/cglm/struct/project.h120
-rw-r--r--libs/cglm/include/cglm/struct/quat.h565
-rw-r--r--libs/cglm/include/cglm/struct/sphere.h93
-rw-r--r--libs/cglm/include/cglm/struct/vec2-ext.h239
-rw-r--r--libs/cglm/include/cglm/struct/vec2.h561
-rw-r--r--libs/cglm/include/cglm/struct/vec3-ext.h257
-rw-r--r--libs/cglm/include/cglm/struct/vec3.h970
-rw-r--r--libs/cglm/include/cglm/struct/vec4-ext.h257
-rw-r--r--libs/cglm/include/cglm/struct/vec4.h814
-rw-r--r--libs/cglm/include/cglm/types-struct.h218
-rw-r--r--libs/cglm/include/cglm/types.h95
-rw-r--r--libs/cglm/include/cglm/util.h343
-rw-r--r--libs/cglm/include/cglm/vec2-ext.h241
-rw-r--r--libs/cglm/include/cglm/vec2.h585
-rw-r--r--libs/cglm/include/cglm/vec3-ext.h272
-rw-r--r--libs/cglm/include/cglm/vec3.h1082
-rw-r--r--libs/cglm/include/cglm/vec4-ext.h313
-rw-r--r--libs/cglm/include/cglm/vec4.h1066
-rw-r--r--libs/cglm/include/cglm/version.h15
-rw-r--r--libs/cglm/include/module.modulemap14
142 files changed, 28445 insertions, 0 deletions
diff --git a/libs/cglm/include/cglm/affine-mat.h b/libs/cglm/include/cglm/affine-mat.h
new file mode 100644
index 0000000..75607e7
--- /dev/null
+++ b/libs/cglm/include/cglm/affine-mat.h
@@ -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
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glm_mul(mat4 m1, mat4 m2, mat4 dest);
+ CGLM_INLINE void glm_inv_tr(mat4 mat);
+ */
+
+#ifndef cglm_affine_mat_h
+#define cglm_affine_mat_h
+
+#include "common.h"
+#include "mat4.h"
+#include "mat3.h"
+
+#ifdef CGLM_SSE_FP
+# include "simd/sse2/affine.h"
+#endif
+
+#ifdef CGLM_AVX_FP
+# include "simd/avx/affine.h"
+#endif
+
+#ifdef CGLM_NEON_FP
+# include "simd/neon/affine.h"
+#endif
+
+/*!
+ * @brief this is similar to glm_mat4_mul but specialized to affine transform
+ *
+ * Matrix format should be:
+ * R R R X
+ * R R R Y
+ * R R R Z
+ * 0 0 0 W
+ *
+ * this reduces some multiplications. It should be faster than mat4_mul.
+ * if you are not sure about matrix format then DON'T use this! use mat4_mul
+ *
+ * @param[in] m1 affine matrix 1
+ * @param[in] m2 affine matrix 2
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_mul(mat4 m1, mat4 m2, mat4 dest) {
+#ifdef __AVX__
+ glm_mul_avx(m1, m2, dest);
+#elif defined( __SSE__ ) || defined( __SSE2__ )
+ glm_mul_sse2(m1, m2, dest);
+#elif defined(CGLM_NEON_FP)
+ glm_mul_neon(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],
+ b30 = m2[3][0], b31 = m2[3][1], b32 = m2[3][2], b33 = m2[3][3];
+
+ 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] = a00 * b30 + a10 * b31 + a20 * b32 + a30 * b33;
+ dest[3][1] = a01 * b30 + a11 * b31 + a21 * b32 + a31 * b33;
+ dest[3][2] = a02 * b30 + a12 * b31 + a22 * b32 + a32 * b33;
+ dest[3][3] = a03 * b30 + a13 * b31 + a23 * b32 + a33 * b33;
+#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);
+#elif defined(CGLM_NEON_FP)
+ glm_mul_rot_neon(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)
+ *
+ * @code
+ * X = | R T | X' = | R' -R'T |
+ * | 0 1 | | 0 1 |
+ * @endcode
+ *
+ * @param[in,out] mat matrix
+ */
+CGLM_INLINE
+void
+glm_inv_tr(mat4 mat) {
+#if defined( __SSE__ ) || defined( __SSE2__ )
+ glm_inv_tr_sse2(mat);
+#elif defined(CGLM_NEON_FP)
+ glm_inv_tr_neon(mat);
+#else
+ CGLM_ALIGN_MAT mat3 r;
+ CGLM_ALIGN(8) vec3 t;
+
+ /* rotate */
+ glm_mat4_pick3t(mat, r);
+ glm_mat4_ins3(r, mat);
+
+ /* translate */
+ glm_mat3_mulv(r, mat[3], t);
+ glm_vec3_negate(t);
+ glm_vec3_copy(t, mat[3]);
+#endif
+}
+
+#endif /* cglm_affine_mat_h */
diff --git a/libs/cglm/include/cglm/affine.h b/libs/cglm/include/cglm/affine.h
new file mode 100644
index 0000000..d0e5bc9
--- /dev/null
+++ b/libs/cglm/include/cglm/affine.h
@@ -0,0 +1,470 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glm_translate_to(mat4 m, vec3 v, mat4 dest);
+ CGLM_INLINE void glm_translate(mat4 m, vec3 v);
+ CGLM_INLINE void glm_translate_x(mat4 m, float to);
+ CGLM_INLINE void glm_translate_y(mat4 m, float to);
+ CGLM_INLINE void glm_translate_z(mat4 m, float to);
+ CGLM_INLINE void glm_translate_make(mat4 m, vec3 v);
+ CGLM_INLINE void glm_scale_to(mat4 m, vec3 v, mat4 dest);
+ CGLM_INLINE void glm_scale_make(mat4 m, vec3 v);
+ CGLM_INLINE void glm_scale(mat4 m, vec3 v);
+ CGLM_INLINE void glm_scale_uni(mat4 m, float s);
+ CGLM_INLINE void glm_rotate_x(mat4 m, float angle, mat4 dest);
+ CGLM_INLINE void glm_rotate_y(mat4 m, float angle, mat4 dest);
+ CGLM_INLINE void glm_rotate_z(mat4 m, float angle, mat4 dest);
+ CGLM_INLINE void glm_rotate_make(mat4 m, float angle, vec3 axis);
+ CGLM_INLINE void glm_rotate(mat4 m, float angle, vec3 axis);
+ CGLM_INLINE void glm_rotate_at(mat4 m, vec3 pivot, float angle, vec3 axis);
+ CGLM_INLINE void glm_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis);
+ CGLM_INLINE void glm_decompose_scalev(mat4 m, vec3 s);
+ CGLM_INLINE bool glm_uniscaled(mat4 m);
+ CGLM_INLINE void glm_decompose_rs(mat4 m, mat4 r, vec3 s);
+ CGLM_INLINE void glm_decompose(mat4 m, vec4 t, mat4 r, vec3 s);
+ */
+
+#ifndef cglm_affine_h
+#define cglm_affine_h
+
+#include "common.h"
+#include "util.h"
+#include "vec3.h"
+#include "vec4.h"
+#include "mat4.h"
+#include "affine-mat.h"
+
+/*!
+ * @brief translate existing transform matrix by v vector
+ * and stores result in same matrix
+ *
+ * @param[in, out] m affine transfrom
+ * @param[in] v translate vector [x, y, z]
+ */
+CGLM_INLINE
+void
+glm_translate(mat4 m, vec3 v) {
+#if defined(CGLM_SIMD)
+ glmm_128 m0, m1, m2, m3;
+
+ m0 = glmm_load(m[0]);
+ m1 = glmm_load(m[1]);
+ m2 = glmm_load(m[2]);
+ m3 = glmm_load(m[3]);
+
+ glmm_store(m[3],
+ glmm_fmadd(m0, glmm_set1(v[0]),
+ glmm_fmadd(m1, glmm_set1(v[1]),
+ glmm_fmadd(m2, glmm_set1(v[2]), m3))));
+#else
+ glm_vec4_muladds(m[0], v[0], m[3]);
+ glm_vec4_muladds(m[1], v[1], m[3]);
+ glm_vec4_muladds(m[2], v[2], m[3]);
+#endif
+}
+
+/*!
+ * @brief translate existing transform matrix by v vector
+ * and store result in dest
+ *
+ * source matrix will remain same
+ *
+ * @param[in] m affine transfrom
+ * @param[in] v translate vector [x, y, z]
+ * @param[out] dest translated matrix
+ */
+CGLM_INLINE
+void
+glm_translate_to(mat4 m, vec3 v, mat4 dest) {
+ glm_mat4_copy(m, dest);
+ glm_translate(dest, v);
+}
+
+/*!
+ * @brief translate existing transform matrix by x factor
+ *
+ * @param[in, out] m affine transfrom
+ * @param[in] x x factor
+ */
+CGLM_INLINE
+void
+glm_translate_x(mat4 m, float x) {
+#if defined(CGLM_SIMD)
+ glmm_store(m[3], glmm_fmadd(glmm_load(m[0]), glmm_set1(x), glmm_load(m[3])));
+#else
+ vec4 v1;
+ glm_vec4_scale(m[0], x, v1);
+ glm_vec4_add(v1, m[3], m[3]);
+#endif
+}
+
+/*!
+ * @brief translate existing transform matrix by y factor
+ *
+ * @param[in, out] m affine transfrom
+ * @param[in] y y factor
+ */
+CGLM_INLINE
+void
+glm_translate_y(mat4 m, float y) {
+#if defined(CGLM_SIMD)
+ glmm_store(m[3], glmm_fmadd(glmm_load(m[1]), glmm_set1(y), glmm_load(m[3])));
+#else
+ vec4 v1;
+ glm_vec4_scale(m[1], y, v1);
+ glm_vec4_add(v1, m[3], m[3]);
+#endif
+}
+
+/*!
+ * @brief translate existing transform matrix by z factor
+ *
+ * @param[in, out] m affine transfrom
+ * @param[in] z z factor
+ */
+CGLM_INLINE
+void
+glm_translate_z(mat4 m, float z) {
+#if defined(CGLM_SIMD)
+ glmm_store(m[3], glmm_fmadd(glmm_load(m[2]), glmm_set1(z), glmm_load(m[3])));
+#else
+ vec4 v1;
+ glm_vec4_scale(m[2], z, v1);
+ glm_vec4_add(v1, m[3], m[3]);
+#endif
+}
+
+/*!
+ * @brief creates NEW translate transform matrix by v vector
+ *
+ * @param[out] m affine transfrom
+ * @param[in] v translate vector [x, y, z]
+ */
+CGLM_INLINE
+void
+glm_translate_make(mat4 m, vec3 v) {
+ glm_mat4_identity(m);
+ glm_vec3_copy(v, m[3]);
+}
+
+/*!
+ * @brief scale existing transform matrix by v vector
+ * and store result in dest
+ *
+ * @param[in] m affine transfrom
+ * @param[in] v scale vector [x, y, z]
+ * @param[out] dest scaled matrix
+ */
+CGLM_INLINE
+void
+glm_scale_to(mat4 m, vec3 v, mat4 dest) {
+ glm_vec4_scale(m[0], v[0], dest[0]);
+ glm_vec4_scale(m[1], v[1], dest[1]);
+ glm_vec4_scale(m[2], v[2], dest[2]);
+
+ glm_vec4_copy(m[3], dest[3]);
+}
+
+/*!
+ * @brief creates NEW scale matrix by v vector
+ *
+ * @param[out] m affine transfrom
+ * @param[in] v scale vector [x, y, z]
+ */
+CGLM_INLINE
+void
+glm_scale_make(mat4 m, vec3 v) {
+ glm_mat4_identity(m);
+ m[0][0] = v[0];
+ m[1][1] = v[1];
+ m[2][2] = v[2];
+}
+
+/*!
+ * @brief scales existing transform matrix by v vector
+ * and stores result in same matrix
+ *
+ * @param[in, out] m affine transfrom
+ * @param[in] v scale vector [x, y, z]
+ */
+CGLM_INLINE
+void
+glm_scale(mat4 m, vec3 v) {
+ glm_scale_to(m, v, m);
+}
+
+/*!
+ * @brief applies uniform scale to existing transform matrix v = [s, s, s]
+ * and stores result in same matrix
+ *
+ * @param[in, out] m affine transfrom
+ * @param[in] s scale factor
+ */
+CGLM_INLINE
+void
+glm_scale_uni(mat4 m, float s) {
+ CGLM_ALIGN(8) vec3 v = { s, s, s };
+ glm_scale_to(m, v, m);
+}
+
+/*!
+ * @brief rotate existing transform matrix around X axis by angle
+ * and store result in dest
+ *
+ * @param[in] m affine transfrom
+ * @param[in] angle angle (radians)
+ * @param[out] dest rotated matrix
+ */
+CGLM_INLINE
+void
+glm_rotate_x(mat4 m, float angle, mat4 dest) {
+ CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT;
+ float c, s;
+
+ c = cosf(angle);
+ s = sinf(angle);
+
+ t[1][1] = c;
+ t[1][2] = s;
+ t[2][1] = -s;
+ t[2][2] = c;
+
+ glm_mul_rot(m, t, dest);
+}
+
+/*!
+ * @brief rotate existing transform matrix around Y axis by angle
+ * and store result in dest
+ *
+ * @param[in] m affine transfrom
+ * @param[in] angle angle (radians)
+ * @param[out] dest rotated matrix
+ */
+CGLM_INLINE
+void
+glm_rotate_y(mat4 m, float angle, mat4 dest) {
+ CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT;
+ float c, s;
+
+ c = cosf(angle);
+ s = sinf(angle);
+
+ t[0][0] = c;
+ t[0][2] = -s;
+ t[2][0] = s;
+ t[2][2] = c;
+
+ glm_mul_rot(m, t, dest);
+}
+
+/*!
+ * @brief rotate existing transform matrix around Z axis by angle
+ * and store result in dest
+ *
+ * @param[in] m affine transfrom
+ * @param[in] angle angle (radians)
+ * @param[out] dest rotated matrix
+ */
+CGLM_INLINE
+void
+glm_rotate_z(mat4 m, float angle, mat4 dest) {
+ CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT;
+ float c, s;
+
+ c = cosf(angle);
+ s = sinf(angle);
+
+ t[0][0] = c;
+ t[0][1] = s;
+ t[1][0] = -s;
+ t[1][1] = c;
+
+ glm_mul_rot(m, t, dest);
+}
+
+/*!
+ * @brief creates NEW rotation matrix by angle and axis
+ *
+ * axis will be normalized so you don't need to normalize it
+ *
+ * @param[out] m affine transfrom
+ * @param[in] angle angle (radians)
+ * @param[in] axis axis
+ */
+CGLM_INLINE
+void
+glm_rotate_make(mat4 m, float angle, vec3 axis) {
+ CGLM_ALIGN(8) vec3 axisn, v, vs;
+ float c;
+
+ c = cosf(angle);
+
+ glm_vec3_normalize_to(axis, axisn);
+ glm_vec3_scale(axisn, 1.0f - c, v);
+ glm_vec3_scale(axisn, sinf(angle), vs);
+
+ glm_vec3_scale(axisn, v[0], m[0]);
+ glm_vec3_scale(axisn, v[1], m[1]);
+ glm_vec3_scale(axisn, v[2], m[2]);
+
+ m[0][0] += c; m[1][0] -= vs[2]; m[2][0] += vs[1];
+ m[0][1] += vs[2]; m[1][1] += c; m[2][1] -= vs[0];
+ m[0][2] -= vs[1]; m[1][2] += vs[0]; m[2][2] += c;
+
+ m[0][3] = m[1][3] = m[2][3] = m[3][0] = m[3][1] = m[3][2] = 0.0f;
+ m[3][3] = 1.0f;
+}
+
+/*!
+ * @brief rotate existing transform matrix around given axis by angle
+ *
+ * @param[in, out] m affine transfrom
+ * @param[in] angle angle (radians)
+ * @param[in] axis axis
+ */
+CGLM_INLINE
+void
+glm_rotate(mat4 m, float angle, vec3 axis) {
+ CGLM_ALIGN_MAT mat4 rot;
+ glm_rotate_make(rot, angle, axis);
+ glm_mul_rot(m, rot, m);
+}
+
+/*!
+ * @brief rotate existing transform
+ * around given axis by angle at given pivot point (rotation center)
+ *
+ * @param[in, out] m affine transfrom
+ * @param[in] pivot rotation center
+ * @param[in] angle angle (radians)
+ * @param[in] axis axis
+ */
+CGLM_INLINE
+void
+glm_rotate_at(mat4 m, vec3 pivot, float angle, vec3 axis) {
+ CGLM_ALIGN(8) vec3 pivotInv;
+
+ glm_vec3_negate_to(pivot, pivotInv);
+
+ glm_translate(m, pivot);
+ glm_rotate(m, angle, axis);
+ glm_translate(m, pivotInv);
+}
+
+/*!
+ * @brief creates NEW rotation matrix by angle and axis at given point
+ *
+ * this creates rotation matrix, it assumes you don't have a matrix
+ *
+ * this should work faster than glm_rotate_at because it reduces
+ * one glm_translate.
+ *
+ * @param[out] m affine transfrom
+ * @param[in] pivot rotation center
+ * @param[in] angle angle (radians)
+ * @param[in] axis axis
+ */
+CGLM_INLINE
+void
+glm_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis) {
+ CGLM_ALIGN(8) vec3 pivotInv;
+
+ glm_vec3_negate_to(pivot, pivotInv);
+
+ glm_translate_make(m, pivot);
+ glm_rotate(m, angle, axis);
+ glm_translate(m, pivotInv);
+}
+
+/*!
+ * @brief decompose scale vector
+ *
+ * @param[in] m affine transform
+ * @param[out] s scale vector (Sx, Sy, Sz)
+ */
+CGLM_INLINE
+void
+glm_decompose_scalev(mat4 m, vec3 s) {
+ s[0] = glm_vec3_norm(m[0]);
+ s[1] = glm_vec3_norm(m[1]);
+ s[2] = glm_vec3_norm(m[2]);
+}
+
+/*!
+ * @brief returns true if matrix is uniform scaled. This is helpful for
+ * creating normal matrix.
+ *
+ * @param[in] m m
+ *
+ * @return boolean
+ */
+CGLM_INLINE
+bool
+glm_uniscaled(mat4 m) {
+ CGLM_ALIGN(8) vec3 s;
+ glm_decompose_scalev(m, s);
+ return glm_vec3_eq_all(s);
+}
+
+/*!
+ * @brief decompose rotation matrix (mat4) and scale vector [Sx, Sy, Sz]
+ * DON'T pass projected matrix here
+ *
+ * @param[in] m affine transform
+ * @param[out] r rotation matrix
+ * @param[out] s scale matrix
+ */
+CGLM_INLINE
+void
+glm_decompose_rs(mat4 m, mat4 r, vec3 s) {
+ CGLM_ALIGN(16) vec4 t = {0.0f, 0.0f, 0.0f, 1.0f};
+ CGLM_ALIGN(8) vec3 v;
+
+ glm_vec4_copy(m[0], r[0]);
+ glm_vec4_copy(m[1], r[1]);
+ glm_vec4_copy(m[2], r[2]);
+ glm_vec4_copy(t, r[3]);
+
+ s[0] = glm_vec3_norm(m[0]);
+ s[1] = glm_vec3_norm(m[1]);
+ s[2] = glm_vec3_norm(m[2]);
+
+ glm_vec4_scale(r[0], 1.0f/s[0], r[0]);
+ glm_vec4_scale(r[1], 1.0f/s[1], r[1]);
+ glm_vec4_scale(r[2], 1.0f/s[2], r[2]);
+
+ /* Note from Apple Open Source (assume that the matrix is orthonormal):
+ check for a coordinate system flip. If the determinant
+ is -1, then negate the matrix and the scaling factors. */
+ glm_vec3_cross(m[0], m[1], v);
+ if (glm_vec3_dot(v, m[2]) < 0.0f) {
+ glm_vec4_negate(r[0]);
+ glm_vec4_negate(r[1]);
+ glm_vec4_negate(r[2]);
+ glm_vec3_negate(s);
+ }
+}
+
+/*!
+ * @brief decompose affine transform, TODO: extract shear factors.
+ * DON'T pass projected matrix here
+ *
+ * @param[in] m affine transfrom
+ * @param[out] t translation vector
+ * @param[out] r rotation matrix (mat4)
+ * @param[out] s scaling vector [X, Y, Z]
+ */
+CGLM_INLINE
+void
+glm_decompose(mat4 m, vec4 t, mat4 r, vec3 s) {
+ glm_vec4_copy(m[3], t);
+ glm_decompose_rs(m, r, s);
+}
+
+#endif /* cglm_affine_h */
diff --git a/libs/cglm/include/cglm/affine2d.h b/libs/cglm/include/cglm/affine2d.h
new file mode 100644
index 0000000..bb66289
--- /dev/null
+++ b/libs/cglm/include/cglm/affine2d.h
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glm_translate2d(mat3 m, vec2 v)
+ CGLM_INLINE void glm_translate2d_to(mat3 m, vec2 v, mat3 dest)
+ CGLM_INLINE void glm_translate2d_x(mat3 m, float x)
+ CGLM_INLINE void glm_translate2d_y(mat3 m, float y)
+ CGLM_INLINE void glm_translate2d_make(mat3 m, vec2 v)
+ CGLM_INLINE void glm_scale2d_to(mat3 m, vec2 v, mat3 dest)
+ CGLM_INLINE void glm_scale2d_make(mat3 m, vec2 v)
+ CGLM_INLINE void glm_scale2d(mat3 m, vec2 v)
+ CGLM_INLINE void glm_scale2d_uni(mat3 m, float s)
+ CGLM_INLINE void glm_rotate2d_make(mat3 m, float angle)
+ CGLM_INLINE void glm_rotate2d(mat3 m, float angle)
+ CGLM_INLINE void glm_rotate2d_to(mat3 m, float angle, mat3 dest)
+ */
+
+#ifndef cglm_affine2d_h
+#define cglm_affine2d_h
+
+#include "common.h"
+#include "util.h"
+#include "vec2.h"
+#include "mat3.h"
+
+/*!
+ * @brief translate existing 2d transform matrix by v vector
+ * and stores result in same matrix
+ *
+ * @param[in, out] m affine transfrom
+ * @param[in] v translate vector [x, y]
+ */
+CGLM_INLINE
+void
+glm_translate2d(mat3 m, vec2 v) {
+ m[2][0] = m[0][0] * v[0] + m[1][0] * v[1] + m[2][0];
+ m[2][1] = m[0][1] * v[0] + m[1][1] * v[1] + m[2][1];
+ m[2][2] = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2];
+}
+
+/*!
+ * @brief translate existing 2d 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]
+ * @param[out] dest translated matrix
+ */
+CGLM_INLINE
+void
+glm_translate2d_to(mat3 m, vec2 v, mat3 dest) {
+ glm_mat3_copy(m, dest);
+ glm_translate2d(dest, v);
+}
+
+/*!
+ * @brief translate existing 2d transform matrix by x factor
+ *
+ * @param[in, out] m affine transfrom
+ * @param[in] x x factor
+ */
+CGLM_INLINE
+void
+glm_translate2d_x(mat3 m, float x) {
+ m[2][0] = m[0][0] * x + m[2][0];
+ m[2][1] = m[0][1] * x + m[2][1];
+ m[2][2] = m[0][2] * x + m[2][2];
+}
+
+/*!
+ * @brief translate existing 2d transform matrix by y factor
+ *
+ * @param[in, out] m affine transfrom
+ * @param[in] y y factor
+ */
+CGLM_INLINE
+void
+glm_translate2d_y(mat3 m, float y) {
+ m[2][0] = m[1][0] * y + m[2][0];
+ m[2][1] = m[1][1] * y + m[2][1];
+ m[2][2] = m[1][2] * y + m[2][2];
+}
+
+/*!
+ * @brief creates NEW translate 2d transform matrix by v vector
+ *
+ * @param[out] m affine transfrom
+ * @param[in] v translate vector [x, y]
+ */
+CGLM_INLINE
+void
+glm_translate2d_make(mat3 m, vec2 v) {
+ glm_mat3_identity(m);
+ m[2][0] = v[0];
+ m[2][1] = v[1];
+}
+
+/*!
+ * @brief scale existing 2d transform matrix by v vector
+ * and store result in dest
+ *
+ * @param[in] m affine transfrom
+ * @param[in] v scale vector [x, y]
+ * @param[out] dest scaled matrix
+ */
+CGLM_INLINE
+void
+glm_scale2d_to(mat3 m, vec2 v, mat3 dest) {
+ dest[0][0] = m[0][0] * v[0];
+ dest[0][1] = m[0][1] * v[0];
+ dest[0][2] = m[0][2] * v[0];
+
+ dest[1][0] = m[1][0] * v[1];
+ dest[1][1] = m[1][1] * v[1];
+ dest[1][2] = m[1][2] * v[1];
+
+ dest[2][0] = m[2][0];
+ dest[2][1] = m[2][1];
+ dest[2][2] = m[2][2];
+}
+
+/*!
+ * @brief creates NEW 2d scale matrix by v vector
+ *
+ * @param[out] m affine transfrom
+ * @param[in] v scale vector [x, y]
+ */
+CGLM_INLINE
+void
+glm_scale2d_make(mat3 m, vec2 v) {
+ glm_mat3_identity(m);
+ m[0][0] = v[0];
+ m[1][1] = v[1];
+}
+
+/*!
+ * @brief scales existing 2d transform matrix by v vector
+ * and stores result in same matrix
+ *
+ * @param[in, out] m affine transfrom
+ * @param[in] v scale vector [x, y]
+ */
+CGLM_INLINE
+void
+glm_scale2d(mat3 m, vec2 v) {
+ m[0][0] = m[0][0] * v[0];
+ m[0][1] = m[0][1] * v[0];
+ m[0][2] = m[0][2] * v[0];
+
+ m[1][0] = m[1][0] * v[1];
+ m[1][1] = m[1][1] * v[1];
+ m[1][2] = m[1][2] * v[1];
+}
+
+/*!
+ * @brief applies uniform scale to existing 2d transform matrix v = [s, s]
+ * and stores result in same matrix
+ *
+ * @param[in, out] m affine transfrom
+ * @param[in] s scale factor
+ */
+CGLM_INLINE
+void
+glm_scale2d_uni(mat3 m, float s) {
+ m[0][0] = m[0][0] * s;
+ m[0][1] = m[0][1] * s;
+ m[0][2] = m[0][2] * s;
+
+ m[1][0] = m[1][0] * s;
+ m[1][1] = m[1][1] * s;
+ m[1][2] = m[1][2] * s;
+}
+
+/*!
+ * @brief creates NEW rotation matrix by angle around Z axis
+ *
+ * @param[out] m affine transfrom
+ * @param[in] angle angle (radians)
+ */
+CGLM_INLINE
+void
+glm_rotate2d_make(mat3 m, float angle) {
+ float c, s;
+
+ s = sinf(angle);
+ c = cosf(angle);
+
+ m[0][0] = c;
+ m[0][1] = s;
+ m[0][2] = 0;
+
+ m[1][0] = -s;
+ m[1][1] = c;
+ m[1][2] = 0;
+
+ m[2][0] = 0.0f;
+ m[2][1] = 0.0f;
+ m[2][2] = 1.0f;
+}
+
+/*!
+ * @brief rotate existing 2d transform matrix around Z axis by angle
+ * and store result in same matrix
+ *
+ * @param[in, out] m affine transfrom
+ * @param[in] angle angle (radians)
+ */
+CGLM_INLINE
+void
+glm_rotate2d(mat3 m, float angle) {
+ float m00 = m[0][0], m10 = m[1][0],
+ m01 = m[0][1], m11 = m[1][1],
+ m02 = m[0][2], m12 = m[1][2];
+ float c, s;
+
+ s = sinf(angle);
+ c = cosf(angle);
+
+ m[0][0] = m00 * c + m10 * s;
+ m[0][1] = m01 * c + m11 * s;
+ m[0][2] = m02 * c + m12 * s;
+
+ m[1][0] = m00 * -s + m10 * c;
+ m[1][1] = m01 * -s + m11 * c;
+ m[1][2] = m02 * -s + m12 * c;
+}
+
+/*!
+ * @brief rotate existing 2d transform matrix around Z axis by angle
+ * and store result in dest
+ *
+ * @param[in] m affine transfrom
+ * @param[in] angle angle (radians)
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_rotate2d_to(mat3 m, float angle, mat3 dest) {
+ float m00 = m[0][0], m10 = m[1][0],
+ m01 = m[0][1], m11 = m[1][1],
+ m02 = m[0][2], m12 = m[1][2];
+ float c, s;
+
+ s = sinf(angle);
+ c = cosf(angle);
+
+ dest[0][0] = m00 * c + m10 * s;
+ dest[0][1] = m01 * c + m11 * s;
+ dest[0][2] = m02 * c + m12 * s;
+
+ dest[1][0] = m00 * -s + m10 * c;
+ dest[1][1] = m01 * -s + m11 * c;
+ dest[1][2] = m02 * -s + m12 * c;
+
+ dest[2][0] = m[2][0];
+ dest[2][1] = m[2][1];
+ dest[2][2] = m[2][2];
+}
+
+#endif /* cglm_affine2d_h */
diff --git a/libs/cglm/include/cglm/applesimd.h b/libs/cglm/include/cglm/applesimd.h
new file mode 100644
index 0000000..3608bb3
--- /dev/null
+++ b/libs/cglm/include/cglm/applesimd.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_applesimd_h
+#define cglm_applesimd_h
+#if defined(__APPLE__) \
+ && defined(SIMD_COMPILER_HAS_REQUIRED_FEATURES) \
+ && defined(SIMD_BASE) \
+ && defined(SIMD_TYPES) \
+ && defined(SIMD_VECTOR_TYPES)
+
+#include "common.h"
+
+/*!
+* @brief converts mat4 to Apple's simd type simd_float4x4
+* @return simd_float4x4
+*/
+CGLM_INLINE
+simd_float4x4
+glm_mat4_applesimd(mat4 m) {
+ simd_float4x4 t;
+
+ t.columns[0][0] = m[0][0];
+ t.columns[0][1] = m[0][1];
+ t.columns[0][2] = m[0][2];
+ t.columns[0][3] = m[0][3];
+
+ t.columns[1][0] = m[1][0];
+ t.columns[1][1] = m[1][1];
+ t.columns[1][2] = m[1][2];
+ t.columns[1][3] = m[1][3];
+
+ t.columns[2][0] = m[2][0];
+ t.columns[2][1] = m[2][1];
+ t.columns[2][2] = m[2][2];
+ t.columns[2][3] = m[2][3];
+
+ t.columns[3][0] = m[3][0];
+ t.columns[3][1] = m[3][1];
+ t.columns[3][2] = m[3][2];
+ t.columns[3][3] = m[3][3];
+
+ return t;
+}
+
+/*!
+* @brief converts mat3 to Apple's simd type simd_float3x3
+* @return simd_float3x3
+*/
+CGLM_INLINE
+simd_float3x3
+glm_mat3_applesimd(mat3 m) {
+ simd_float3x3 t;
+
+ t.columns[0][0] = m[0][0];
+ t.columns[0][1] = m[0][1];
+ t.columns[0][2] = m[0][2];
+
+ t.columns[1][0] = m[1][0];
+ t.columns[1][1] = m[1][1];
+ t.columns[1][2] = m[1][2];
+
+ t.columns[2][0] = m[2][0];
+ t.columns[2][1] = m[2][1];
+ t.columns[2][2] = m[2][2];
+
+ return t;
+}
+
+/*!
+* @brief converts vec4 to Apple's simd type simd_float4
+* @return simd_float4
+*/
+CGLM_INLINE
+simd_float4
+glm_vec4_applesimd(vec4 v) {
+ return (simd_float4){v[0], v[1], v[2], v[3]};
+}
+
+/*!
+* @brief converts vec3 to Apple's simd type simd_float3
+* @return v
+*/
+CGLM_INLINE
+simd_float3
+glm_vec3_applesimd(vec3 v) {
+ return (simd_float3){v[0], v[1], v[2]};
+}
+
+#endif
+#endif /* cglm_applesimd_h */
diff --git a/libs/cglm/include/cglm/bezier.h b/libs/cglm/include/cglm/bezier.h
new file mode 100644
index 0000000..2bbe09f
--- /dev/null
+++ b/libs/cglm/include/cglm/bezier.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_bezier_h
+#define cglm_bezier_h
+
+#include "common.h"
+
+#define GLM_BEZIER_MAT_INIT {{-1.0f, 3.0f, -3.0f, 1.0f}, \
+ { 3.0f, -6.0f, 3.0f, 0.0f}, \
+ {-3.0f, 3.0f, 0.0f, 0.0f}, \
+ { 1.0f, 0.0f, 0.0f, 0.0f}}
+#define GLM_HERMITE_MAT_INIT {{ 2.0f, -3.0f, 0.0f, 1.0f}, \
+ {-2.0f, 3.0f, 0.0f, 0.0f}, \
+ { 1.0f, -2.0f, 1.0f, 0.0f}, \
+ { 1.0f, -1.0f, 0.0f, 0.0f}}
+/* for C only */
+#define GLM_BEZIER_MAT ((mat4)GLM_BEZIER_MAT_INIT)
+#define GLM_HERMITE_MAT ((mat4)GLM_HERMITE_MAT_INIT)
+
+#define CGLM_DECASTEL_EPS 1e-9f
+#define CGLM_DECASTEL_MAX 1000.0f
+#define CGLM_DECASTEL_SMALL 1e-20f
+
+/*!
+ * @brief cubic bezier interpolation
+ *
+ * Formula:
+ * B(s) = P0*(1-s)^3 + 3*C0*s*(1-s)^2 + 3*C1*s^2*(1-s) + P1*s^3
+ *
+ * similar result using matrix:
+ * B(s) = glm_smc(t, GLM_BEZIER_MAT, (vec4){p0, c0, c1, p1})
+ *
+ * glm_eq(glm_smc(...), glm_bezier(...)) should return TRUE
+ *
+ * @param[in] s parameter between 0 and 1
+ * @param[in] p0 begin point
+ * @param[in] c0 control point 1
+ * @param[in] c1 control point 2
+ * @param[in] p1 end point
+ *
+ * @return B(s)
+ */
+CGLM_INLINE
+float
+glm_bezier(float s, float p0, float c0, float c1, float p1) {
+ float x, xx, ss, xs3, a;
+
+ x = 1.0f - s;
+ xx = x * x;
+ ss = s * s;
+ xs3 = (s - ss) * 3.0f;
+ a = p0 * xx + c0 * xs3;
+
+ return a + s * (c1 * xs3 + p1 * ss - a);
+}
+
+/*!
+ * @brief cubic hermite interpolation
+ *
+ * Formula:
+ * H(s) = P0*(2*s^3 - 3*s^2 + 1) + T0*(s^3 - 2*s^2 + s)
+ * + P1*(-2*s^3 + 3*s^2) + T1*(s^3 - s^2)
+ *
+ * similar result using matrix:
+ * H(s) = glm_smc(t, GLM_HERMITE_MAT, (vec4){p0, p1, c0, c1})
+ *
+ * glm_eq(glm_smc(...), glm_hermite(...)) should return TRUE
+ *
+ * @param[in] s parameter between 0 and 1
+ * @param[in] p0 begin point
+ * @param[in] t0 tangent 1
+ * @param[in] t1 tangent 2
+ * @param[in] p1 end point
+ *
+ * @return H(s)
+ */
+CGLM_INLINE
+float
+glm_hermite(float s, float p0, float t0, float t1, float p1) {
+ float ss, d, a, b, c, e, f;
+
+ ss = s * s;
+ a = ss + ss;
+ c = a + ss;
+ b = a * s;
+ d = s * ss;
+ f = d - ss;
+ e = b - c;
+
+ return p0 * (e + 1.0f) + t0 * (f - ss + s) + t1 * f - p1 * e;
+}
+
+/*!
+ * @brief iterative way to solve cubic equation
+ *
+ * @param[in] prm parameter between 0 and 1
+ * @param[in] p0 begin point
+ * @param[in] c0 control point 1
+ * @param[in] c1 control point 2
+ * @param[in] p1 end point
+ *
+ * @return parameter to use in cubic equation
+ */
+CGLM_INLINE
+float
+glm_decasteljau(float prm, float p0, float c0, float c1, float p1) {
+ float u, v, a, b, c, d, e, f;
+ int i;
+
+ if (prm - p0 < CGLM_DECASTEL_SMALL)
+ return 0.0f;
+
+ if (p1 - prm < CGLM_DECASTEL_SMALL)
+ return 1.0f;
+
+ u = 0.0f;
+ v = 1.0f;
+
+ for (i = 0; i < CGLM_DECASTEL_MAX; i++) {
+ /* de Casteljau Subdivision */
+ a = (p0 + c0) * 0.5f;
+ b = (c0 + c1) * 0.5f;
+ c = (c1 + p1) * 0.5f;
+ d = (a + b) * 0.5f;
+ e = (b + c) * 0.5f;
+ f = (d + e) * 0.5f; /* this one is on the curve! */
+
+ /* The curve point is close enough to our wanted t */
+ if (fabsf(f - prm) < CGLM_DECASTEL_EPS)
+ return glm_clamp_zo((u + v) * 0.5f);
+
+ /* dichotomy */
+ if (f < prm) {
+ p0 = f;
+ c0 = e;
+ c1 = c;
+ u = (u + v) * 0.5f;
+ } else {
+ c0 = a;
+ c1 = d;
+ p1 = f;
+ v = (u + v) * 0.5f;
+ }
+ }
+
+ return glm_clamp_zo((u + v) * 0.5f);
+}
+
+#endif /* cglm_bezier_h */
diff --git a/libs/cglm/include/cglm/box.h b/libs/cglm/include/cglm/box.h
new file mode 100644
index 0000000..4400797
--- /dev/null
+++ b/libs/cglm/include/cglm/box.h
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_box_h
+#define cglm_box_h
+
+#include "common.h"
+#include "vec3.h"
+#include "vec4.h"
+#include "util.h"
+
+/*!
+ * @brief apply transform to Axis-Aligned Bounding Box
+ *
+ * @param[in] box bounding box
+ * @param[in] m transform matrix
+ * @param[out] dest transformed bounding box
+ */
+CGLM_INLINE
+void
+glm_aabb_transform(vec3 box[2], mat4 m, vec3 dest[2]) {
+ vec3 v[2], xa, xb, ya, yb, za, zb;
+
+ glm_vec3_scale(m[0], box[0][0], xa);
+ glm_vec3_scale(m[0], box[1][0], xb);
+
+ glm_vec3_scale(m[1], box[0][1], ya);
+ glm_vec3_scale(m[1], box[1][1], yb);
+
+ glm_vec3_scale(m[2], box[0][2], za);
+ glm_vec3_scale(m[2], box[1][2], zb);
+
+ /* translation + min(xa, xb) + min(ya, yb) + min(za, zb) */
+ glm_vec3(m[3], v[0]);
+ glm_vec3_minadd(xa, xb, v[0]);
+ glm_vec3_minadd(ya, yb, v[0]);
+ glm_vec3_minadd(za, zb, v[0]);
+
+ /* translation + max(xa, xb) + max(ya, yb) + max(za, zb) */
+ glm_vec3(m[3], v[1]);
+ glm_vec3_maxadd(xa, xb, v[1]);
+ glm_vec3_maxadd(ya, yb, v[1]);
+ glm_vec3_maxadd(za, zb, v[1]);
+
+ glm_vec3_copy(v[0], dest[0]);
+ glm_vec3_copy(v[1], dest[1]);
+}
+
+/*!
+ * @brief merges two AABB bounding box and creates new one
+ *
+ * two box must be in same space, if one of box is in different space then
+ * you should consider to convert it's space by glm_box_space
+ *
+ * @param[in] box1 bounding box 1
+ * @param[in] box2 bounding box 2
+ * @param[out] dest merged bounding box
+ */
+CGLM_INLINE
+void
+glm_aabb_merge(vec3 box1[2], vec3 box2[2], vec3 dest[2]) {
+ dest[0][0] = glm_min(box1[0][0], box2[0][0]);
+ dest[0][1] = glm_min(box1[0][1], box2[0][1]);
+ dest[0][2] = glm_min(box1[0][2], box2[0][2]);
+
+ dest[1][0] = glm_max(box1[1][0], box2[1][0]);
+ dest[1][1] = glm_max(box1[1][1], box2[1][1]);
+ dest[1][2] = glm_max(box1[1][2], box2[1][2]);
+}
+
+/*!
+ * @brief crops a bounding box with another one.
+ *
+ * this could be useful for gettng a bbox which fits with view frustum and
+ * object bounding boxes. In this case you crop view frustum box with objects
+ * box
+ *
+ * @param[in] box bounding box 1
+ * @param[in] cropBox crop box
+ * @param[out] dest cropped bounding box
+ */
+CGLM_INLINE
+void
+glm_aabb_crop(vec3 box[2], vec3 cropBox[2], vec3 dest[2]) {
+ dest[0][0] = glm_max(box[0][0], cropBox[0][0]);
+ dest[0][1] = glm_max(box[0][1], cropBox[0][1]);
+ dest[0][2] = glm_max(box[0][2], cropBox[0][2]);
+
+ dest[1][0] = glm_min(box[1][0], cropBox[1][0]);
+ dest[1][1] = glm_min(box[1][1], cropBox[1][1]);
+ dest[1][2] = glm_min(box[1][2], cropBox[1][2]);
+}
+
+/*!
+ * @brief crops a bounding box with another one.
+ *
+ * this could be useful for gettng a bbox which fits with view frustum and
+ * object bounding boxes. In this case you crop view frustum box with objects
+ * box
+ *
+ * @param[in] box bounding box
+ * @param[in] cropBox crop box
+ * @param[in] clampBox miniumum box
+ * @param[out] dest cropped bounding box
+ */
+CGLM_INLINE
+void
+glm_aabb_crop_until(vec3 box[2],
+ vec3 cropBox[2],
+ vec3 clampBox[2],
+ vec3 dest[2]) {
+ glm_aabb_crop(box, cropBox, dest);
+ glm_aabb_merge(clampBox, dest, dest);
+}
+
+/*!
+ * @brief check if AABB intersects with frustum planes
+ *
+ * this could be useful for frustum culling using AABB.
+ *
+ * OPTIMIZATION HINT:
+ * if planes order is similar to LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR
+ * then this method should run even faster because it would only use two
+ * planes if object is not inside the two planes
+ * fortunately cglm extracts planes as this order! just pass what you got!
+ *
+ * @param[in] box bounding box
+ * @param[in] planes frustum planes
+ */
+CGLM_INLINE
+bool
+glm_aabb_frustum(vec3 box[2], vec4 planes[6]) {
+ float *p, dp;
+ int i;
+
+ for (i = 0; i < 6; i++) {
+ p = planes[i];
+ dp = p[0] * box[p[0] > 0.0f][0]
+ + p[1] * box[p[1] > 0.0f][1]
+ + p[2] * box[p[2] > 0.0f][2];
+
+ if (dp < -p[3])
+ return false;
+ }
+
+ 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.
+ *
+ * Sphere Representation in cglm: [center.x, center.y, center.z, radii]
+ *
+ * @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]) + (s[0] > box[1][0]);
+ b = (s[1] < box[0][1]) + (s[1] > box[1][1]);
+ c = (s[2] < box[0][2]) + (s[2] > box[1][2]);
+
+ dmin = glm_pow2((s[0] - box[!(a - 1)][0]) * (a != 0))
+ + glm_pow2((s[1] - box[!(b - 1)][1]) * (b != 0))
+ + glm_pow2((s[2] - box[!(c - 1)][2]) * (c != 0));
+
+ 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 */
diff --git a/libs/cglm/include/cglm/call.h b/libs/cglm/include/cglm/call.h
new file mode 100644
index 0000000..734bd46
--- /dev/null
+++ b/libs/cglm/include/cglm/call.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_call_h
+#define cglm_call_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "cglm.h"
+#include "call/vec2.h"
+#include "call/vec3.h"
+#include "call/vec4.h"
+#include "call/ivec2.h"
+#include "call/ivec3.h"
+#include "call/ivec4.h"
+#include "call/mat2.h"
+#include "call/mat3.h"
+#include "call/mat4.h"
+#include "call/affine.h"
+#include "call/cam.h"
+#include "call/quat.h"
+#include "call/euler.h"
+#include "call/plane.h"
+#include "call/frustum.h"
+#include "call/box.h"
+#include "call/io.h"
+#include "call/project.h"
+#include "call/sphere.h"
+#include "call/ease.h"
+#include "call/curve.h"
+#include "call/bezier.h"
+#include "call/ray.h"
+#include "call/affine2d.h"
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglm_call_h */
diff --git a/libs/cglm/include/cglm/call/affine.h b/libs/cglm/include/cglm/call/affine.h
new file mode 100644
index 0000000..c11405b
--- /dev/null
+++ b/libs/cglm/include/cglm/call/affine.h
@@ -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 cglmc_affine_h
+#define cglmc_affine_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_translate_make(mat4 m, vec3 v);
+
+CGLM_EXPORT
+void
+glmc_translate_to(mat4 m, vec3 v, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_translate(mat4 m, vec3 v);
+
+CGLM_EXPORT
+void
+glmc_translate_x(mat4 m, float to);
+
+CGLM_EXPORT
+void
+glmc_translate_y(mat4 m, float to);
+
+CGLM_EXPORT
+void
+glmc_translate_z(mat4 m, float to);
+
+CGLM_EXPORT
+void
+glmc_scale_make(mat4 m, vec3 v);
+
+CGLM_EXPORT
+void
+glmc_scale_to(mat4 m, vec3 v, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_scale(mat4 m, vec3 v);
+
+CGLM_EXPORT
+void
+glmc_scale_uni(mat4 m, float s);
+
+CGLM_EXPORT
+void
+glmc_rotate_x(mat4 m, float rad, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_rotate_y(mat4 m, float rad, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_rotate_z(mat4 m, float rad, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_rotate_make(mat4 m, float angle, vec3 axis);
+
+CGLM_EXPORT
+void
+glmc_rotate(mat4 m, float angle, vec3 axis);
+
+CGLM_EXPORT
+void
+glmc_rotate_at(mat4 m, vec3 pivot, float angle, vec3 axis);
+
+CGLM_EXPORT
+void
+glmc_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis);
+
+CGLM_EXPORT
+void
+glmc_decompose_scalev(mat4 m, vec3 s);
+
+CGLM_EXPORT
+bool
+glmc_uniscaled(mat4 m);
+
+CGLM_EXPORT
+void
+glmc_decompose_rs(mat4 m, mat4 r, vec3 s);
+
+CGLM_EXPORT
+void
+glmc_decompose(mat4 m, vec4 t, mat4 r, vec3 s);
+
+/* affine-mat */
+
+CGLM_EXPORT
+void
+glmc_mul(mat4 m1, mat4 m2, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_mul_rot(mat4 m1, mat4 m2, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_inv_tr(mat4 mat);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_affine_h */
diff --git a/libs/cglm/include/cglm/call/affine2d.h b/libs/cglm/include/cglm/call/affine2d.h
new file mode 100644
index 0000000..e1b9462
--- /dev/null
+++ b/libs/cglm/include/cglm/call/affine2d.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_affine2d_h
+#define cglmc_affine2d_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_translate2d_make(mat3 m, vec2 v);
+
+CGLM_EXPORT
+void
+glmc_translate2d_to(mat3 m, vec2 v, mat3 dest);
+
+CGLM_EXPORT
+void
+glmc_translate2d(mat3 m, vec2 v);
+
+CGLM_EXPORT
+void
+glmc_translate2d_x(mat3 m, float to);
+
+CGLM_EXPORT
+void
+glmc_translate2d_y(mat3 m, float to);
+
+CGLM_EXPORT
+void
+glmc_scale2d_to(mat3 m, vec2 v, mat3 dest);
+
+CGLM_EXPORT
+void
+glmc_scale2d_make(mat3 m, vec2 v);
+
+CGLM_EXPORT
+void
+glmc_scale2d(mat3 m, vec2 v);
+
+CGLM_EXPORT
+void
+glmc_scale2d_uni(mat3 m, float s);
+
+CGLM_EXPORT
+void
+glmc_rotate2d_make(mat3 m, float angle);
+
+CGLM_EXPORT
+void
+glmc_rotate2d(mat3 m, float angle);
+
+CGLM_EXPORT
+void
+glmc_rotate2d_to(mat3 m, float angle, mat3 dest);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_affine2d_h */
diff --git a/libs/cglm/include/cglm/call/bezier.h b/libs/cglm/include/cglm/call/bezier.h
new file mode 100644
index 0000000..a6a0eb4
--- /dev/null
+++ b/libs/cglm/include/cglm/call/bezier.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_bezier_h
+#define cglmc_bezier_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+CGLM_EXPORT
+float
+glmc_bezier(float s, float p0, float c0, float c1, float p1);
+
+CGLM_EXPORT
+float
+glmc_hermite(float s, float p0, float t0, float t1, float p1);
+
+CGLM_EXPORT
+float
+glmc_decasteljau(float prm, float p0, float c0, float c1, float p1);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_bezier_h */
diff --git a/libs/cglm/include/cglm/call/box.h b/libs/cglm/include/cglm/call/box.h
new file mode 100644
index 0000000..afb7558
--- /dev/null
+++ b/libs/cglm/include/cglm/call/box.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_box_h
+#define cglmc_box_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_aabb_transform(vec3 box[2], mat4 m, vec3 dest[2]);
+
+CGLM_EXPORT
+void
+glmc_aabb_merge(vec3 box1[2], vec3 box2[2], vec3 dest[2]);
+
+CGLM_EXPORT
+void
+glmc_aabb_crop(vec3 box[2], vec3 cropBox[2], vec3 dest[2]);
+
+CGLM_EXPORT
+void
+glmc_aabb_crop_until(vec3 box[2],
+ vec3 cropBox[2],
+ vec3 clampBox[2],
+ vec3 dest[2]);
+
+CGLM_EXPORT
+bool
+glmc_aabb_frustum(vec3 box[2], vec4 planes[6]);
+
+CGLM_EXPORT
+void
+glmc_aabb_invalidate(vec3 box[2]);
+
+CGLM_EXPORT
+bool
+glmc_aabb_isvalid(vec3 box[2]);
+
+CGLM_EXPORT
+float
+glmc_aabb_size(vec3 box[2]);
+
+CGLM_EXPORT
+float
+glmc_aabb_radius(vec3 box[2]);
+
+CGLM_EXPORT
+void
+glmc_aabb_center(vec3 box[2], vec3 dest);
+
+CGLM_EXPORT
+bool
+glmc_aabb_aabb(vec3 box[2], vec3 other[2]);
+
+CGLM_EXPORT
+bool
+glmc_aabb_point(vec3 box[2], vec3 point);
+
+CGLM_EXPORT
+bool
+glmc_aabb_contains(vec3 box[2], vec3 other[2]);
+
+CGLM_EXPORT
+bool
+glmc_aabb_sphere(vec3 box[2], vec4 s);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_box_h */
+
diff --git a/libs/cglm/include/cglm/call/cam.h b/libs/cglm/include/cglm/call/cam.h
new file mode 100644
index 0000000..d9567ec
--- /dev/null
+++ b/libs/cglm/include/cglm/call/cam.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_cam_h
+#define cglmc_cam_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_frustum(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_aabb(vec3 box[2], mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_aabb_p(vec3 box[2], float padding, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_aabb_pz(vec3 box[2], float padding, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_default(float aspect, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_default_s(float aspect, float size, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_perspective(float fovy, float aspect, float nearZ, float farZ, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_persp_move_far(mat4 proj, float deltaFar);
+
+CGLM_EXPORT
+void
+glmc_perspective_default(float aspect, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_perspective_resize(float aspect, mat4 proj);
+
+CGLM_EXPORT
+void
+glmc_lookat(vec3 eye, vec3 center, vec3 up, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_look(vec3 eye, vec3 dir, vec3 up, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_look_anyup(vec3 eye, vec3 dir, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp(mat4 proj,
+ float * __restrict nearZ,
+ float * __restrict farZ,
+ 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 nearZ,
+ float * __restrict farZ);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_far(mat4 proj, float * __restrict farZ);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_near(mat4 proj, float * __restrict nearZ);
+
+CGLM_EXPORT
+float
+glmc_persp_fovy(mat4 proj);
+
+CGLM_EXPORT
+float
+glmc_persp_aspect(mat4 proj);
+
+CGLM_EXPORT
+void
+glmc_persp_sizes(mat4 proj, float fovy, vec4 dest);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_cam_h */
diff --git a/libs/cglm/include/cglm/call/clipspace/ortho_lh_no.h b/libs/cglm/include/cglm/call/clipspace/ortho_lh_no.h
new file mode 100644
index 0000000..3e26fa9
--- /dev/null
+++ b/libs/cglm/include/cglm/call/clipspace/ortho_lh_no.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_ortho_lh_no_h
+#define cglmc_ortho_lh_no_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_ortho_lh_no(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_aabb_lh_no(vec3 box[2], mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_aabb_p_lh_no(vec3 box[2], float padding, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_aabb_pz_lh_no(vec3 box[2], float padding, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_default_lh_no(float aspect, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_default_s_lh_no(float aspect, float size, mat4 dest);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_ortho_lh_no_h */
diff --git a/libs/cglm/include/cglm/call/clipspace/ortho_lh_zo.h b/libs/cglm/include/cglm/call/clipspace/ortho_lh_zo.h
new file mode 100644
index 0000000..dc4c610
--- /dev/null
+++ b/libs/cglm/include/cglm/call/clipspace/ortho_lh_zo.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_ortho_lh_zo_h
+#define cglmc_ortho_lh_zo_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_ortho_lh_zo(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_aabb_lh_zo(vec3 box[2], mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_aabb_p_lh_zo(vec3 box[2], float padding, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_aabb_pz_lh_zo(vec3 box[2], float padding, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_default_lh_zo(float aspect, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_default_s_lh_zo(float aspect, float size, mat4 dest);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_ortho_lh_zo_h */
diff --git a/libs/cglm/include/cglm/call/clipspace/ortho_rh_no.h b/libs/cglm/include/cglm/call/clipspace/ortho_rh_no.h
new file mode 100644
index 0000000..dbba497
--- /dev/null
+++ b/libs/cglm/include/cglm/call/clipspace/ortho_rh_no.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_ortho_rh_no_h
+#define cglmc_ortho_rh_no_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_ortho_rh_no(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_aabb_rh_no(vec3 box[2], mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_aabb_p_rh_no(vec3 box[2], float padding, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_aabb_pz_rh_no(vec3 box[2], float padding, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_default_rh_no(float aspect, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_default_s_rh_no(float aspect, float size, mat4 dest);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_ortho_rh_no_h */
diff --git a/libs/cglm/include/cglm/call/clipspace/ortho_rh_zo.h b/libs/cglm/include/cglm/call/clipspace/ortho_rh_zo.h
new file mode 100644
index 0000000..e79ae83
--- /dev/null
+++ b/libs/cglm/include/cglm/call/clipspace/ortho_rh_zo.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_ortho_rh_zo_h
+#define cglmc_ortho_rh_zo_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_ortho_rh_zo(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_aabb_rh_zo(vec3 box[2], mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_aabb_p_rh_zo(vec3 box[2], float padding, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_aabb_pz_rh_zo(vec3 box[2], float padding, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_default_rh_zo(float aspect, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_ortho_default_s_rh_zo(float aspect, float size, mat4 dest);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_ortho_rh_zo_h */
diff --git a/libs/cglm/include/cglm/call/clipspace/persp_lh_no.h b/libs/cglm/include/cglm/call/clipspace/persp_lh_no.h
new file mode 100644
index 0000000..4bdbcfe
--- /dev/null
+++ b/libs/cglm/include/cglm/call/clipspace/persp_lh_no.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_persp_lh_no_h
+#define cglmc_persp_lh_no_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_frustum_lh_no(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_perspective_lh_no(float fovy,
+ float aspect,
+ float nearVal,
+ float farVal,
+ mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_persp_move_far_lh_no(mat4 proj, float deltaFar);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_lh_no(mat4 proj,
+ float * __restrict nearZ, float * __restrict farZ,
+ float * __restrict top, float * __restrict bottom,
+ float * __restrict left, float * __restrict right);
+
+CGLM_EXPORT
+void
+glmc_persp_decompv_lh_no(mat4 proj, float dest[6]);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_x_lh_no(mat4 proj,
+ float * __restrict left,
+ float * __restrict right);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_y_lh_no(mat4 proj,
+ float * __restrict top,
+ float * __restrict bottom);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_z_lh_no(mat4 proj,
+ float * __restrict nearZ,
+ float * __restrict farZ);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_far_lh_no(mat4 proj, float * __restrict farZ);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_near_lh_no(mat4 proj, float * __restrict nearZ);
+
+CGLM_EXPORT
+void
+glmc_persp_sizes_lh_no(mat4 proj, float fovy, vec4 dest);
+
+CGLM_EXPORT
+float
+glmc_persp_fovy_lh_no(mat4 proj);
+
+CGLM_EXPORT
+float
+glmc_persp_aspect_lh_no(mat4 proj);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_persp_lh_no_h */
diff --git a/libs/cglm/include/cglm/call/clipspace/persp_lh_zo.h b/libs/cglm/include/cglm/call/clipspace/persp_lh_zo.h
new file mode 100644
index 0000000..53c2c1c
--- /dev/null
+++ b/libs/cglm/include/cglm/call/clipspace/persp_lh_zo.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_persp_lh_zo_h
+#define cglmc_persp_lh_zo_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_frustum_lh_zo(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_perspective_lh_zo(float fovy,
+ float aspect,
+ float nearVal,
+ float farVal,
+ mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_persp_move_far_lh_zo(mat4 proj, float deltaFar);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_lh_zo(mat4 proj,
+ float * __restrict nearZ, float * __restrict farZ,
+ float * __restrict top, float * __restrict bottom,
+ float * __restrict left, float * __restrict right);
+
+CGLM_EXPORT
+void
+glmc_persp_decompv_lh_zo(mat4 proj, float dest[6]);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_x_lh_zo(mat4 proj,
+ float * __restrict left,
+ float * __restrict right);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_y_lh_zo(mat4 proj,
+ float * __restrict top,
+ float * __restrict bottom);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_z_lh_zo(mat4 proj,
+ float * __restrict nearZ,
+ float * __restrict farZ);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_far_lh_zo(mat4 proj, float * __restrict farZ);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_near_lh_zo(mat4 proj, float * __restrict nearZ);
+
+CGLM_EXPORT
+void
+glmc_persp_sizes_lh_zo(mat4 proj, float fovy, vec4 dest);
+
+CGLM_EXPORT
+float
+glmc_persp_fovy_lh_zo(mat4 proj);
+
+CGLM_EXPORT
+float
+glmc_persp_aspect_lh_zo(mat4 proj);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_persp_lh_zo_h */
diff --git a/libs/cglm/include/cglm/call/clipspace/persp_rh_no.h b/libs/cglm/include/cglm/call/clipspace/persp_rh_no.h
new file mode 100644
index 0000000..9c0d65d
--- /dev/null
+++ b/libs/cglm/include/cglm/call/clipspace/persp_rh_no.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_persp_rh_no_h
+#define cglmc_persp_rh_no_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_frustum_rh_no(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_perspective_rh_no(float fovy,
+ float aspect,
+ float nearVal,
+ float farVal,
+ mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_persp_move_far_rh_no(mat4 proj, float deltaFar);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_rh_no(mat4 proj,
+ float * __restrict nearZ, float * __restrict farZ,
+ float * __restrict top, float * __restrict bottom,
+ float * __restrict left, float * __restrict right);
+
+CGLM_EXPORT
+void
+glmc_persp_decompv_rh_no(mat4 proj, float dest[6]);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_x_rh_no(mat4 proj,
+ float * __restrict left,
+ float * __restrict right);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_y_rh_no(mat4 proj,
+ float * __restrict top,
+ float * __restrict bottom);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_z_rh_no(mat4 proj,
+ float * __restrict nearZ,
+ float * __restrict farZ);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_far_rh_no(mat4 proj, float * __restrict farZ);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_near_rh_no(mat4 proj, float * __restrict nearZ);
+
+CGLM_EXPORT
+void
+glmc_persp_sizes_rh_no(mat4 proj, float fovy, vec4 dest);
+
+CGLM_EXPORT
+float
+glmc_persp_fovy_rh_no(mat4 proj);
+
+CGLM_EXPORT
+float
+glmc_persp_aspect_rh_no(mat4 proj);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_persp_rh_no_h */
diff --git a/libs/cglm/include/cglm/call/clipspace/persp_rh_zo.h b/libs/cglm/include/cglm/call/clipspace/persp_rh_zo.h
new file mode 100644
index 0000000..718d4ad
--- /dev/null
+++ b/libs/cglm/include/cglm/call/clipspace/persp_rh_zo.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_persp_rh_zo_h
+#define cglmc_persp_rh_zo_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_frustum_rh_zo(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_perspective_rh_zo(float fovy,
+ float aspect,
+ float nearVal,
+ float farVal,
+ mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_persp_move_far_rh_zo(mat4 proj, float deltaFar);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_rh_zo(mat4 proj,
+ float * __restrict nearZ, float * __restrict farZ,
+ float * __restrict top, float * __restrict bottom,
+ float * __restrict left, float * __restrict right);
+
+CGLM_EXPORT
+void
+glmc_persp_decompv_rh_zo(mat4 proj, float dest[6]);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_x_rh_zo(mat4 proj,
+ float * __restrict left,
+ float * __restrict right);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_y_rh_zo(mat4 proj,
+ float * __restrict top,
+ float * __restrict bottom);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_z_rh_zo(mat4 proj,
+ float * __restrict nearZ,
+ float * __restrict farZ);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_far_rh_zo(mat4 proj, float * __restrict farZ);
+
+CGLM_EXPORT
+void
+glmc_persp_decomp_near_rh_zo(mat4 proj, float * __restrict nearZ);
+
+CGLM_EXPORT
+void
+glmc_persp_sizes_rh_zo(mat4 proj, float fovy, vec4 dest);
+
+CGLM_EXPORT
+float
+glmc_persp_fovy_rh_zo(mat4 proj);
+
+CGLM_EXPORT
+float
+glmc_persp_aspect_rh_zo(mat4 proj);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_persp_rh_zo_h */
diff --git a/libs/cglm/include/cglm/call/clipspace/project_no.h b/libs/cglm/include/cglm/call/clipspace/project_no.h
new file mode 100644
index 0000000..c62c37b
--- /dev/null
+++ b/libs/cglm/include/cglm/call/clipspace/project_no.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_project_no_h
+#define cglmc_project_no_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_unprojecti_no(vec3 pos, mat4 invMat, vec4 vp, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_project_no(vec3 pos, mat4 m, vec4 vp, vec3 dest);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_project_no_h */
diff --git a/libs/cglm/include/cglm/call/clipspace/project_zo.h b/libs/cglm/include/cglm/call/clipspace/project_zo.h
new file mode 100644
index 0000000..a7137bd
--- /dev/null
+++ b/libs/cglm/include/cglm/call/clipspace/project_zo.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_project_zo_h
+#define cglmc_project_zo_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_unprojecti_zo(vec3 pos, mat4 invMat, vec4 vp, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_project_zo(vec3 pos, mat4 m, vec4 vp, vec3 dest);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_project_zo_h */
diff --git a/libs/cglm/include/cglm/call/clipspace/view_lh_no.h b/libs/cglm/include/cglm/call/clipspace/view_lh_no.h
new file mode 100644
index 0000000..3b58c84
--- /dev/null
+++ b/libs/cglm/include/cglm/call/clipspace/view_lh_no.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_view_lh_no_h
+#define cglmc_view_lh_no_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_lookat_lh_no(vec3 eye, vec3 center, vec3 up, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_look_lh_no(vec3 eye, vec3 dir, vec3 up, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_look_anyup_lh_no(vec3 eye, vec3 dir, mat4 dest);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_view_lh_no_h */
diff --git a/libs/cglm/include/cglm/call/clipspace/view_lh_zo.h b/libs/cglm/include/cglm/call/clipspace/view_lh_zo.h
new file mode 100644
index 0000000..c877367
--- /dev/null
+++ b/libs/cglm/include/cglm/call/clipspace/view_lh_zo.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_view_lh_zo_h
+#define cglmc_view_lh_zo_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_lookat_lh_zo(vec3 eye, vec3 center, vec3 up, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_look_lh_zo(vec3 eye, vec3 dir, vec3 up, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_look_anyup_lh_zo(vec3 eye, vec3 dir, mat4 dest);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_view_lh_zo_h */
diff --git a/libs/cglm/include/cglm/call/clipspace/view_rh_no.h b/libs/cglm/include/cglm/call/clipspace/view_rh_no.h
new file mode 100644
index 0000000..6303dbf
--- /dev/null
+++ b/libs/cglm/include/cglm/call/clipspace/view_rh_no.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_view_rh_no_h
+#define cglmc_view_rh_no_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_lookat_rh_no(vec3 eye, vec3 center, vec3 up, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_look_rh_no(vec3 eye, vec3 dir, vec3 up, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_look_anyup_rh_no(vec3 eye, vec3 dir, mat4 dest);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_view_rh_no_h */
diff --git a/libs/cglm/include/cglm/call/clipspace/view_rh_zo.h b/libs/cglm/include/cglm/call/clipspace/view_rh_zo.h
new file mode 100644
index 0000000..00b8707
--- /dev/null
+++ b/libs/cglm/include/cglm/call/clipspace/view_rh_zo.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_view_rh_zo_h
+#define cglmc_view_rh_zo_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_lookat_rh_zo(vec3 eye, vec3 center, vec3 up, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_look_rh_zo(vec3 eye, vec3 dir, vec3 up, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_look_anyup_rh_zo(vec3 eye, vec3 dir, mat4 dest);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_view_rh_zo_h */
diff --git a/libs/cglm/include/cglm/call/curve.h b/libs/cglm/include/cglm/call/curve.h
new file mode 100644
index 0000000..061fdb9
--- /dev/null
+++ b/libs/cglm/include/cglm/call/curve.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_curve_h
+#define cglmc_curve_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+CGLM_EXPORT
+float
+glmc_smc(float s, mat4 m, vec4 c);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_curve_h */
diff --git a/libs/cglm/include/cglm/call/ease.h b/libs/cglm/include/cglm/call/ease.h
new file mode 100644
index 0000000..87e39ca
--- /dev/null
+++ b/libs/cglm/include/cglm/call/ease.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_ease_h
+#define cglmc_ease_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+CGLM_EXPORT
+float
+glmc_ease_linear(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_sine_in(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_sine_out(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_sine_inout(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_quad_in(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_quad_out(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_quad_inout(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_cubic_in(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_cubic_out(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_cubic_inout(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_quart_in(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_quart_out(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_quart_inout(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_quint_in(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_quint_out(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_quint_inout(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_exp_in(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_exp_out(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_exp_inout(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_circ_in(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_circ_out(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_circ_inout(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_back_in(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_back_out(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_back_inout(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_elast_in(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_elast_out(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_elast_inout(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_bounce_out(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_bounce_in(float t);
+
+CGLM_EXPORT
+float
+glmc_ease_bounce_inout(float t);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_ease_h */
diff --git a/libs/cglm/include/cglm/call/euler.h b/libs/cglm/include/cglm/call/euler.h
new file mode 100644
index 0000000..2de68fb
--- /dev/null
+++ b/libs/cglm/include/cglm/call/euler.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_euler_h
+#define cglmc_euler_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_euler_angles(mat4 m, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_euler(vec3 angles, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_euler_xyz(vec3 angles, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_euler_zyx(vec3 angles, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_euler_zxy(vec3 angles, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_euler_xzy(vec3 angles, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_euler_yzx(vec3 angles, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_euler_yxz(vec3 angles, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_euler_by_order(vec3 angles, glm_euler_seq axis, mat4 dest);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_euler_h */
diff --git a/libs/cglm/include/cglm/call/frustum.h b/libs/cglm/include/cglm/call/frustum.h
new file mode 100644
index 0000000..6b4facb
--- /dev/null
+++ b/libs/cglm/include/cglm/call/frustum.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_frustum_h
+#define cglmc_frustum_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_frustum_planes(mat4 m, vec4 dest[6]);
+
+CGLM_EXPORT
+void
+glmc_frustum_corners(mat4 invMat, vec4 dest[8]);
+
+CGLM_EXPORT
+void
+glmc_frustum_center(vec4 corners[8], vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_frustum_box(vec4 corners[8], mat4 m, vec3 box[2]);
+
+CGLM_EXPORT
+void
+glmc_frustum_corners_at(vec4 corners[8],
+ float splitDist,
+ float farDist,
+ vec4 planeCorners[4]);
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_frustum_h */
diff --git a/libs/cglm/include/cglm/call/io.h b/libs/cglm/include/cglm/call/io.h
new file mode 100644
index 0000000..19ea06f
--- /dev/null
+++ b/libs/cglm/include/cglm/call/io.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_io_h
+#define cglmc_io_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_mat4_print(mat4 matrix,
+ FILE * __restrict ostream);
+
+CGLM_EXPORT
+void
+glmc_mat3_print(mat3 matrix,
+ FILE * __restrict ostream);
+
+CGLM_EXPORT
+void
+glmc_vec4_print(vec4 vec,
+ FILE * __restrict ostream);
+
+CGLM_EXPORT
+void
+glmc_vec3_print(vec3 vec,
+ FILE * __restrict ostream);
+
+CGLM_EXPORT
+void
+glmc_versor_print(versor vec,
+ FILE * __restrict ostream);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_io_h */
diff --git a/libs/cglm/include/cglm/call/ivec2.h b/libs/cglm/include/cglm/call/ivec2.h
new file mode 100644
index 0000000..d3b8fd2
--- /dev/null
+++ b/libs/cglm/include/cglm/call/ivec2.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_ivec2_h
+#define cglmc_ivec2_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_ivec2(int * __restrict v, ivec2 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec2_copy(ivec2 a, ivec2 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec2_zero(ivec2 v);
+
+CGLM_EXPORT
+void
+glmc_ivec2_one(ivec2 v);
+
+CGLM_EXPORT
+void
+glmc_ivec2_add(ivec2 a, ivec2 b, ivec2 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec2_adds(ivec2 v, int s, ivec2 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec2_sub(ivec2 a, ivec2 b, ivec2 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec2_subs(ivec2 v, int s, ivec2 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec2_mul(ivec2 a, ivec2 b, ivec2 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec2_scale(ivec2 v, int s, ivec2 dest);
+
+CGLM_EXPORT
+int
+glmc_ivec2_distance2(ivec2 a, ivec2 b);
+
+CGLM_EXPORT
+float
+glmc_ivec2_distance(ivec2 a, ivec2 b);
+
+CGLM_EXPORT
+void
+glmc_ivec2_maxv(ivec2 a, ivec2 b, ivec2 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec2_minv(ivec2 a, ivec2 b, ivec2 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec2_clamp(ivec2 v, int minVal, int maxVal);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_ivec2_h */
diff --git a/libs/cglm/include/cglm/call/ivec3.h b/libs/cglm/include/cglm/call/ivec3.h
new file mode 100644
index 0000000..3c28811
--- /dev/null
+++ b/libs/cglm/include/cglm/call/ivec3.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c);, Recep Aslantas.
+ *
+ * MIT License (MIT);, http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_ivec3_h
+#define cglmc_ivec3_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_ivec3(ivec4 v4, ivec3 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec3_copy(ivec3 a, ivec3 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec3_zero(ivec3 v);
+
+CGLM_EXPORT
+void
+glmc_ivec3_one(ivec3 v);
+
+CGLM_EXPORT
+void
+glmc_ivec3_add(ivec3 a, ivec3 b, ivec3 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec3_adds(ivec3 v, int s, ivec3 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec3_sub(ivec3 a, ivec3 b, ivec3 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec3_subs(ivec3 v, int s, ivec3 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec3_mul(ivec3 a, ivec3 b, ivec3 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec3_scale(ivec3 v, int s, ivec3 dest);
+
+CGLM_EXPORT
+int
+glmc_ivec3_distance2(ivec3 a, ivec3 b);
+
+CGLM_EXPORT
+float
+glmc_ivec3_distance(ivec3 a, ivec3 b);
+
+CGLM_EXPORT
+void
+glmc_ivec3_maxv(ivec3 a, ivec3 b, ivec3 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec3_minv(ivec3 a, ivec3 b, ivec3 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec3_clamp(ivec3 v, int minVal, int maxVal);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_ivec3_h */
diff --git a/libs/cglm/include/cglm/call/ivec4.h b/libs/cglm/include/cglm/call/ivec4.h
new file mode 100644
index 0000000..79e11b1
--- /dev/null
+++ b/libs/cglm/include/cglm/call/ivec4.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_ivec4_h
+#define cglmc_ivec4_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_ivec4(ivec3 v3, int last, ivec4 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec4_copy(ivec4 a, ivec4 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec4_zero(ivec4 v);
+
+CGLM_EXPORT
+void
+glmc_ivec4_one(ivec4 v);
+
+CGLM_EXPORT
+void
+glmc_ivec4_add(ivec4 a, ivec4 b, ivec4 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec4_adds(ivec4 v, int s, ivec4 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec4_sub(ivec4 a, ivec4 b, ivec4 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec4_subs(ivec4 v, int s, ivec4 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec4_mul(ivec4 a, ivec4 b, ivec4 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec4_scale(ivec4 v, int s, ivec4 dest);
+
+CGLM_EXPORT
+int
+glmc_ivec4_distance2(ivec4 a, ivec4 b);
+
+CGLM_EXPORT
+float
+glmc_ivec4_distance(ivec4 a, ivec4 b);
+
+CGLM_EXPORT
+void
+glmc_ivec4_maxv(ivec4 a, ivec4 b, ivec4 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec4_minv(ivec4 a, ivec4 b, ivec4 dest);
+
+CGLM_EXPORT
+void
+glmc_ivec4_clamp(ivec4 v, int minVal, int maxVal);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_ivec4_h */
diff --git a/libs/cglm/include/cglm/call/mat2.h b/libs/cglm/include/cglm/call/mat2.h
new file mode 100644
index 0000000..91234a3
--- /dev/null
+++ b/libs/cglm/include/cglm/call/mat2.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_mat2_h
+#define cglmc_mat2_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_mat2_copy(mat2 mat, mat2 dest);
+
+CGLM_EXPORT
+void
+glmc_mat2_identity(mat2 mat);
+
+CGLM_EXPORT
+void
+glmc_mat2_identity_array(mat2 * __restrict mat, size_t count);
+
+CGLM_EXPORT
+void
+glmc_mat2_zero(mat2 mat);
+
+CGLM_EXPORT
+void
+glmc_mat2_mul(mat2 m1, mat2 m2, mat2 dest);
+
+CGLM_EXPORT
+void
+glmc_mat2_transpose_to(mat2 m, mat2 dest);
+
+CGLM_EXPORT
+void
+glmc_mat2_transpose(mat2 m);
+
+CGLM_EXPORT
+void
+glmc_mat2_mulv(mat2 m, vec2 v, vec2 dest);
+
+CGLM_EXPORT
+float
+glmc_mat2_trace(mat2 m);
+
+CGLM_EXPORT
+void
+glmc_mat2_scale(mat2 m, float s);
+
+CGLM_EXPORT
+float
+glmc_mat2_det(mat2 mat);
+
+CGLM_EXPORT
+void
+glmc_mat2_inv(mat2 mat, mat2 dest);
+
+CGLM_EXPORT
+void
+glmc_mat2_swap_col(mat2 mat, int col1, int col2);
+
+CGLM_EXPORT
+void
+glmc_mat2_swap_row(mat2 mat, int row1, int row2);
+
+CGLM_EXPORT
+float
+glmc_mat2_rmc(vec2 r, mat2 m, vec2 c);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_mat2_h */
diff --git a/libs/cglm/include/cglm/call/mat3.h b/libs/cglm/include/cglm/call/mat3.h
new file mode 100644
index 0000000..36dcb27
--- /dev/null
+++ b/libs/cglm/include/cglm/call/mat3.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_mat3_h
+#define cglmc_mat3_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+/* DEPRECATED! use _copy, _ucopy versions */
+#define glmc_mat3_dup(mat, dest) glmc_mat3_copy(mat, dest)
+
+CGLM_EXPORT
+void
+glmc_mat3_copy(mat3 mat, mat3 dest);
+
+CGLM_EXPORT
+void
+glmc_mat3_identity(mat3 mat);
+
+CGLM_EXPORT
+void
+glmc_mat3_zero(mat3 mat);
+
+CGLM_EXPORT
+void
+glmc_mat3_identity_array(mat3 * __restrict mat, size_t count);
+
+CGLM_EXPORT
+void
+glmc_mat3_mul(mat3 m1, mat3 m2, mat3 dest);
+
+CGLM_EXPORT
+void
+glmc_mat3_transpose_to(mat3 m, mat3 dest);
+
+CGLM_EXPORT
+void
+glmc_mat3_transpose(mat3 m);
+
+CGLM_EXPORT
+void
+glmc_mat3_mulv(mat3 m, vec3 v, vec3 dest);
+
+CGLM_EXPORT
+float
+glmc_mat3_trace(mat3 m);
+
+CGLM_EXPORT
+void
+glmc_mat3_quat(mat3 m, versor dest);
+
+CGLM_EXPORT
+void
+glmc_mat3_scale(mat3 m, float s);
+
+CGLM_EXPORT
+float
+glmc_mat3_det(mat3 mat);
+
+CGLM_EXPORT
+void
+glmc_mat3_inv(mat3 mat, mat3 dest);
+
+CGLM_EXPORT
+void
+glmc_mat3_swap_col(mat3 mat, int col1, int col2);
+
+CGLM_EXPORT
+void
+glmc_mat3_swap_row(mat3 mat, int row1, int row2);
+
+CGLM_EXPORT
+float
+glmc_mat3_rmc(vec3 r, mat3 m, vec3 c);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_mat3_h */
diff --git a/libs/cglm/include/cglm/call/mat4.h b/libs/cglm/include/cglm/call/mat4.h
new file mode 100644
index 0000000..1c71da1
--- /dev/null
+++ b/libs/cglm/include/cglm/call/mat4.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_mat_h
+#define cglmc_mat_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+/* DEPRECATED! use _copy, _ucopy versions */
+#define glmc_mat4_udup(mat, dest) glmc_mat4_ucopy(mat, dest)
+#define glmc_mat4_dup(mat, dest) glmc_mat4_copy(mat, dest)
+
+CGLM_EXPORT
+void
+glmc_mat4_ucopy(mat4 mat, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_mat4_copy(mat4 mat, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_mat4_identity(mat4 mat);
+
+CGLM_EXPORT
+void
+glmc_mat4_identity_array(mat4 * __restrict mat, size_t count);
+
+CGLM_EXPORT
+void
+glmc_mat4_zero(mat4 mat);
+
+CGLM_EXPORT
+void
+glmc_mat4_pick3(mat4 mat, mat3 dest);
+
+CGLM_EXPORT
+void
+glmc_mat4_pick3t(mat4 mat, mat3 dest);
+
+CGLM_EXPORT
+void
+glmc_mat4_ins3(mat3 mat, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_mat4_mul(mat4 m1, mat4 m2, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_mat4_mulN(mat4 * __restrict matrices[], uint32_t len, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_mat4_mulv(mat4 m, vec4 v, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_mat4_mulv3(mat4 m, vec3 v, float last, vec3 dest);
+
+CGLM_EXPORT
+float
+glmc_mat4_trace(mat4 m);
+
+CGLM_EXPORT
+float
+glmc_mat4_trace3(mat4 m);
+
+CGLM_EXPORT
+void
+glmc_mat4_quat(mat4 m, versor dest);
+
+CGLM_EXPORT
+void
+glmc_mat4_transpose_to(mat4 m, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_mat4_transpose(mat4 m);
+
+CGLM_EXPORT
+void
+glmc_mat4_scale_p(mat4 m, float s);
+
+CGLM_EXPORT
+void
+glmc_mat4_scale(mat4 m, float s);
+
+CGLM_EXPORT
+float
+glmc_mat4_det(mat4 mat);
+
+CGLM_EXPORT
+void
+glmc_mat4_inv(mat4 mat, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_mat4_inv_precise(mat4 mat, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_mat4_inv_fast(mat4 mat, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_mat4_swap_col(mat4 mat, int col1, int col2);
+
+CGLM_EXPORT
+void
+glmc_mat4_swap_row(mat4 mat, int row1, int row2);
+
+CGLM_EXPORT
+float
+glmc_mat4_rmc(vec4 r, mat4 m, vec4 c);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_mat_h */
diff --git a/libs/cglm/include/cglm/call/plane.h b/libs/cglm/include/cglm/call/plane.h
new file mode 100644
index 0000000..f991121
--- /dev/null
+++ b/libs/cglm/include/cglm/call/plane.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_plane_h
+#define cglmc_plane_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_plane_normalize(vec4 plane);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_plane_h */
diff --git a/libs/cglm/include/cglm/call/project.h b/libs/cglm/include/cglm/call/project.h
new file mode 100644
index 0000000..991ba1d
--- /dev/null
+++ b/libs/cglm/include/cglm/call/project.h
@@ -0,0 +1,37 @@
+/*
+ * 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);
+
+CGLM_EXPORT
+void
+glmc_pickmatrix(vec2 center, vec2 size, vec4 vp, mat4 dest);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_project_h */
+
+
diff --git a/libs/cglm/include/cglm/call/quat.h b/libs/cglm/include/cglm/call/quat.h
new file mode 100644
index 0000000..1a2766d
--- /dev/null
+++ b/libs/cglm/include/cglm/call/quat.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_quat_h
+#define cglmc_quat_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_quat_identity(versor q);
+
+CGLM_EXPORT
+void
+glmc_quat_identity_array(versor * __restrict q, size_t count);
+
+CGLM_EXPORT
+void
+glmc_quat_init(versor q, float x, float y, float z, float w);
+
+CGLM_EXPORT
+void
+glmc_quat(versor q, float angle, float x, float y, float z);
+
+CGLM_EXPORT
+void
+glmc_quatv(versor q, float angle, vec3 axis);
+
+CGLM_EXPORT
+void
+glmc_quat_copy(versor q, versor dest);
+
+CGLM_EXPORT
+void
+glmc_quat_from_vecs(vec3 a, vec3 b, versor dest);
+
+CGLM_EXPORT
+float
+glmc_quat_norm(versor q);
+
+CGLM_EXPORT
+void
+glmc_quat_normalize_to(versor q, versor dest);
+
+CGLM_EXPORT
+void
+glmc_quat_normalize(versor q);
+
+CGLM_EXPORT
+float
+glmc_quat_dot(versor p, versor q);
+
+CGLM_EXPORT
+void
+glmc_quat_conjugate(versor q, versor dest);
+
+CGLM_EXPORT
+void
+glmc_quat_inv(versor q, versor dest);
+
+CGLM_EXPORT
+void
+glmc_quat_add(versor p, versor q, versor dest);
+
+CGLM_EXPORT
+void
+glmc_quat_sub(versor p, versor q, versor dest);
+
+CGLM_EXPORT
+float
+glmc_quat_real(versor q);
+
+CGLM_EXPORT
+void
+glmc_quat_imag(versor q, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_quat_imagn(versor q, vec3 dest);
+
+CGLM_EXPORT
+float
+glmc_quat_imaglen(versor q);
+
+CGLM_EXPORT
+float
+glmc_quat_angle(versor q);
+
+CGLM_EXPORT
+void
+glmc_quat_axis(versor q, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_quat_mul(versor p, versor q, versor dest);
+
+CGLM_EXPORT
+void
+glmc_quat_mat4(versor q, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_quat_mat4t(versor q, mat4 dest);
+
+CGLM_EXPORT
+void
+glmc_quat_mat3(versor q, mat3 dest);
+
+CGLM_EXPORT
+void
+glmc_quat_mat3t(versor q, mat3 dest);
+
+CGLM_EXPORT
+void
+glmc_quat_lerp(versor from, versor to, float t, versor dest);
+
+CGLM_EXPORT
+void
+glmc_quat_lerpc(versor from, versor to, float t, versor dest);
+
+CGLM_EXPORT
+void
+glmc_quat_nlerp(versor q, versor r, 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 up, versor dest);
+
+CGLM_EXPORT
+void
+glmc_quat_forp(vec3 from, vec3 to, 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
+}
+#endif
+#endif /* cglmc_quat_h */
diff --git a/libs/cglm/include/cglm/call/ray.h b/libs/cglm/include/cglm/call/ray.h
new file mode 100644
index 0000000..1fff055
--- /dev/null
+++ b/libs/cglm/include/cglm/call/ray.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_ray_h
+#define cglmc_ray_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "../cglm.h"
+
+CGLM_EXPORT
+bool
+glmc_ray_triangle(vec3 origin,
+ vec3 direction,
+ vec3 v0,
+ vec3 v1,
+ vec3 v2,
+ float *d);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_ray_h */
diff --git a/libs/cglm/include/cglm/call/sphere.h b/libs/cglm/include/cglm/call/sphere.h
new file mode 100644
index 0000000..9b96546
--- /dev/null
+++ b/libs/cglm/include/cglm/call/sphere.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_sphere_h
+#define cglmc_sphere_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+CGLM_EXPORT
+float
+glmc_sphere_radii(vec4 s);
+
+CGLM_EXPORT
+void
+glmc_sphere_transform(vec4 s, mat4 m, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_sphere_merge(vec4 s1, vec4 s2, vec4 dest);
+
+CGLM_EXPORT
+bool
+glmc_sphere_sphere(vec4 s1, vec4 s2);
+
+CGLM_EXPORT
+bool
+glmc_sphere_point(vec4 s, vec3 point);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_sphere_h */
diff --git a/libs/cglm/include/cglm/call/vec2.h b/libs/cglm/include/cglm/call/vec2.h
new file mode 100644
index 0000000..6e8101e
--- /dev/null
+++ b/libs/cglm/include/cglm/call/vec2.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_vec2_h
+#define cglmc_vec2_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_vec2(float * __restrict v, vec2 dest);
+
+CGLM_EXPORT
+void
+glmc_vec2_copy(vec2 a, vec2 dest);
+
+CGLM_EXPORT
+void
+glmc_vec2_zero(vec2 v);
+
+CGLM_EXPORT
+void
+glmc_vec2_one(vec2 v);
+
+CGLM_EXPORT
+float
+glmc_vec2_dot(vec2 a, vec2 b);
+
+CGLM_EXPORT
+float
+glmc_vec2_cross(vec2 a, vec2 b);
+
+CGLM_EXPORT
+float
+glmc_vec2_norm2(vec2 v);
+
+CGLM_EXPORT
+float
+glmc_vec2_norm(vec2 v);
+
+CGLM_EXPORT
+void
+glmc_vec2_add(vec2 a, vec2 b, vec2 dest);
+
+CGLM_EXPORT
+void
+glmc_vec2_adds(vec2 v, float s, vec2 dest);
+
+CGLM_EXPORT
+void
+glmc_vec2_sub(vec2 a, vec2 b, vec2 dest);
+
+CGLM_EXPORT
+void
+glmc_vec2_subs(vec2 v, float s, vec2 dest);
+
+CGLM_EXPORT
+void
+glmc_vec2_mul(vec2 a, vec2 b, vec2 dest);
+
+CGLM_EXPORT
+void
+glmc_vec2_scale(vec2 v, float s, vec2 dest);
+
+CGLM_EXPORT
+void
+glmc_vec2_scale_as(vec2 v, float s, vec2 dest);
+
+CGLM_EXPORT
+void
+glmc_vec2_div(vec2 a, vec2 b, vec2 dest);
+
+CGLM_EXPORT
+void
+glmc_vec2_divs(vec2 v, float s, vec2 dest);
+
+CGLM_EXPORT
+void
+glmc_vec2_addadd(vec2 a, vec2 b, vec2 dest);
+
+CGLM_EXPORT
+void
+glmc_vec2_subadd(vec2 a, vec2 b, vec2 dest);
+
+CGLM_EXPORT
+void
+glmc_vec2_muladd(vec2 a, vec2 b, vec2 dest);
+
+CGLM_EXPORT
+void
+glmc_vec2_muladds(vec2 a, float s, vec2 dest);
+
+CGLM_EXPORT
+void
+glmc_vec2_maxadd(vec2 a, vec2 b, vec2 dest);
+
+CGLM_EXPORT
+void
+glmc_vec2_minadd(vec2 a, vec2 b, vec2 dest);
+
+CGLM_EXPORT
+void
+glmc_vec2_negate_to(vec2 v, vec2 dest);
+
+CGLM_EXPORT
+void
+glmc_vec2_negate(vec2 v);
+
+CGLM_EXPORT
+void
+glmc_vec2_normalize(vec2 v);
+
+CGLM_EXPORT
+void
+glmc_vec2_normalize_to(vec2 v, vec2 dest);
+
+CGLM_EXPORT
+void
+glmc_vec2_rotate(vec2 v, float angle, vec2 dest);
+
+CGLM_EXPORT
+float
+glmc_vec2_distance2(vec2 a, vec2 b);
+
+CGLM_EXPORT
+float
+glmc_vec2_distance(vec2 a, vec2 b);
+
+CGLM_EXPORT
+void
+glmc_vec2_maxv(vec2 a, vec2 b, vec2 dest);
+
+CGLM_EXPORT
+void
+glmc_vec2_minv(vec2 a, vec2 b, vec2 dest);
+
+CGLM_EXPORT
+void
+glmc_vec2_clamp(vec2 v, float minval, float maxval);
+
+CGLM_EXPORT
+void
+glmc_vec2_lerp(vec2 from, vec2 to, float t, vec2 dest);
+
+CGLM_EXPORT
+void
+glmc_vec2_complex_mul(vec2 a, vec2 b, vec2 dest);
+
+CGLM_EXPORT
+void
+glmc_vec2_complex_div(vec2 a, vec2 b, vec2 dest);
+
+CGLM_EXPORT
+void
+glmc_vec2_complex_conjugate(vec2 a, vec2 dest);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_vec2_h */
diff --git a/libs/cglm/include/cglm/call/vec3.h b/libs/cglm/include/cglm/call/vec3.h
new file mode 100644
index 0000000..69fc0e2
--- /dev/null
+++ b/libs/cglm/include/cglm/call/vec3.h
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_vec3_h
+#define cglmc_vec3_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+/* DEPRECATED! use _copy, _ucopy versions */
+#define glmc_vec_dup(v, dest) glmc_vec3_copy(v, dest)
+#define glmc_vec3_flipsign(v) glmc_vec3_negate(v)
+#define glmc_vec3_flipsign_to(v, dest) glmc_vec3_negate_to(v, dest)
+#define glmc_vec3_inv(v) glmc_vec3_negate(v)
+#define glmc_vec3_inv_to(v, dest) glmc_vec3_negate_to(v, dest)
+
+CGLM_EXPORT
+void
+glmc_vec3(vec4 v4, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_vec3_copy(vec3 a, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_vec3_zero(vec3 v);
+
+CGLM_EXPORT
+void
+glmc_vec3_one(vec3 v);
+
+CGLM_EXPORT
+float
+glmc_vec3_dot(vec3 a, vec3 b);
+
+CGLM_EXPORT
+void
+glmc_vec3_cross(vec3 a, vec3 b, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_vec3_crossn(vec3 a, vec3 b, vec3 dest);
+
+CGLM_EXPORT
+float
+glmc_vec3_norm(vec3 v);
+
+CGLM_EXPORT
+float
+glmc_vec3_norm2(vec3 v);
+
+CGLM_EXPORT
+float
+glmc_vec3_norm_one(vec3 v);
+
+CGLM_EXPORT
+float
+glmc_vec3_norm_inf(vec3 v);
+
+CGLM_EXPORT
+void
+glmc_vec3_normalize_to(vec3 v, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_vec3_normalize(vec3 v);
+
+CGLM_EXPORT
+void
+glmc_vec3_add(vec3 a, vec3 b, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_vec3_adds(vec3 v, float s, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_vec3_sub(vec3 a, vec3 b, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_vec3_subs(vec3 v, float s, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_vec3_mul(vec3 a, vec3 b, vec3 d);
+
+CGLM_EXPORT
+void
+glmc_vec3_scale(vec3 v, float s, vec3 dest);
+
+CGLM_EXPORT
+void
+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
+float
+glmc_vec3_angle(vec3 a, vec3 b);
+
+CGLM_EXPORT
+void
+glmc_vec3_rotate(vec3 v, float angle, vec3 axis);
+
+CGLM_EXPORT
+void
+glmc_vec3_rotate_m4(mat4 m, vec3 v, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_vec3_rotate_m3(mat3 m, vec3 v, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_vec3_proj(vec3 a, vec3 b, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_vec3_center(vec3 a, vec3 b, vec3 dest);
+
+CGLM_EXPORT
+float
+glmc_vec3_distance2(vec3 a, vec3 b);
+
+CGLM_EXPORT
+float
+glmc_vec3_distance(vec3 a, vec3 b);
+
+CGLM_EXPORT
+void
+glmc_vec3_maxv(vec3 a, vec3 b, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_vec3_minv(vec3 a, vec3 b, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_vec3_clamp(vec3 v, float minVal, float maxVal);
+
+CGLM_EXPORT
+void
+glmc_vec3_ortho(vec3 v, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_vec3_lerp(vec3 from, vec3 to, float t, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_vec3_lerpc(vec3 from, vec3 to, float t, vec3 dest);
+
+CGLM_INLINE
+void
+glmc_vec3_mix(vec3 from, vec3 to, float t, vec3 dest) {
+ glmc_vec3_lerp(from, to, t, dest);
+}
+
+CGLM_INLINE
+void
+glmc_vec3_mixc(vec3 from, vec3 to, float t, vec3 dest) {
+ glmc_vec3_lerpc(from, to, t, dest);
+}
+
+CGLM_EXPORT
+void
+glmc_vec3_step_uni(float edge, vec3 x, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_vec3_step(vec3 edge, vec3 x, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_vec3_smoothstep_uni(float edge0, float edge1, vec3 x, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_vec3_smoothstep(vec3 edge0, vec3 edge1, vec3 x, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_vec3_smoothinterp(vec3 from, vec3 to, float t, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_vec3_smoothinterpc(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
+void
+glmc_vec3_fill(vec3 v, float val);
+
+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_abs(vec3 v, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_vec3_fract(vec3 v, vec3 dest);
+
+CGLM_EXPORT
+float
+glmc_vec3_hadd(vec3 v);
+
+CGLM_EXPORT
+void
+glmc_vec3_sqrt(vec3 v, vec3 dest);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_vec3_h */
diff --git a/libs/cglm/include/cglm/call/vec4.h b/libs/cglm/include/cglm/call/vec4.h
new file mode 100644
index 0000000..f56f599
--- /dev/null
+++ b/libs/cglm/include/cglm/call/vec4.h
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_vec4_h
+#define cglmc_vec4_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+/* DEPRECATED! use _copy, _ucopy versions */
+#define glmc_vec4_dup3(v, dest) glmc_vec4_copy3(v, dest)
+#define glmc_vec4_dup(v, dest) glmc_vec4_copy(v, dest)
+#define glmc_vec4_flipsign(v) glmc_vec4_negate(v)
+#define glmc_vec4_flipsign_to(v, dest) glmc_vec4_negate_to(v, dest)
+#define glmc_vec4_inv(v) glmc_vec4_negate(v)
+#define glmc_vec4_inv_to(v, dest) glmc_vec4_negate_to(v, dest)
+
+CGLM_EXPORT
+void
+glmc_vec4(vec3 v3, float last, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_zero(vec4 v);
+
+CGLM_EXPORT
+void
+glmc_vec4_one(vec4 v);
+
+CGLM_EXPORT
+void
+glmc_vec4_copy3(vec4 v, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_copy(vec4 v, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_ucopy(vec4 v, vec4 dest);
+
+CGLM_EXPORT
+float
+glmc_vec4_dot(vec4 a, vec4 b);
+
+CGLM_EXPORT
+float
+glmc_vec4_norm(vec4 v);
+
+CGLM_EXPORT
+float
+glmc_vec4_norm2(vec4 v);
+
+CGLM_EXPORT
+float
+glmc_vec4_norm_one(vec4 v);
+
+CGLM_EXPORT
+float
+glmc_vec4_norm_inf(vec4 v);
+
+CGLM_EXPORT
+void
+glmc_vec4_normalize_to(vec4 v, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_normalize(vec4 v);
+
+CGLM_EXPORT
+void
+glmc_vec4_add(vec4 a, vec4 b, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_adds(vec4 v, float s, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_sub(vec4 a, vec4 b, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_subs(vec4 v, float s, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_mul(vec4 a, vec4 b, vec4 d);
+
+CGLM_EXPORT
+void
+glmc_vec4_scale(vec4 v, float s, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_scale_as(vec4 v, float s, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_div(vec4 a, vec4 b, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_divs(vec4 v, float s, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_addadd(vec4 a, vec4 b, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_subadd(vec4 a, vec4 b, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_muladd(vec4 a, vec4 b, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_muladds(vec4 a, float s, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_maxadd(vec4 a, vec4 b, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_minadd(vec4 a, vec4 b, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_negate(vec4 v);
+
+CGLM_EXPORT
+void
+glmc_vec4_negate_to(vec4 v, vec4 dest);
+
+CGLM_EXPORT
+float
+glmc_vec4_distance(vec4 a, vec4 b);
+
+CGLM_EXPORT
+float
+glmc_vec4_distance2(vec4 a, vec4 b);
+
+CGLM_EXPORT
+void
+glmc_vec4_maxv(vec4 a, vec4 b, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_minv(vec4 a, vec4 b, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_clamp(vec4 v, float minVal, float maxVal);
+
+CGLM_EXPORT
+void
+glmc_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_lerpc(vec4 from, vec4 to, float t, vec4 dest);
+
+CGLM_INLINE
+void
+glmc_vec4_mix(vec4 from, vec4 to, float t, vec4 dest) {
+ glmc_vec4_lerp(from, to, t, dest);
+}
+
+CGLM_INLINE
+void
+glmc_vec4_mixc(vec4 from, vec4 to, float t, vec4 dest) {
+ glmc_vec4_lerpc(from, to, t, dest);
+}
+
+CGLM_EXPORT
+void
+glmc_vec4_step_uni(float edge, vec4 x, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_step(vec4 edge, vec4 x, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_smoothstep_uni(float edge0, float edge1, vec4 x, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_smoothstep(vec4 edge0, vec4 edge1, vec4 x, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_smoothinterp(vec4 from, vec4 to, float t, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_smoothinterpc(vec4 from, vec4 to, float t, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_cubic(float s, vec4 dest);
+
+/* ext */
+
+CGLM_EXPORT
+void
+glmc_vec4_mulv(vec4 a, vec4 b, vec4 d);
+
+CGLM_EXPORT
+void
+glmc_vec4_broadcast(float val, vec4 d);
+
+CGLM_EXPORT
+void
+glmc_vec4_fill(vec4 v, float val);
+
+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_abs(vec4 v, vec4 dest);
+
+CGLM_EXPORT
+void
+glmc_vec4_fract(vec4 v, vec4 dest);
+
+CGLM_EXPORT
+float
+glmc_vec4_hadd(vec4 v);
+
+CGLM_EXPORT
+void
+glmc_vec4_sqrt(vec4 v, vec4 dest);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_vec4_h */
+
diff --git a/libs/cglm/include/cglm/cam.h b/libs/cglm/include/cglm/cam.h
new file mode 100644
index 0000000..c8cfd42
--- /dev/null
+++ b/libs/cglm/include/cglm/cam.h
@@ -0,0 +1,582 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glm_frustum(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest)
+ CGLM_INLINE void glm_ortho(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest)
+ CGLM_INLINE void glm_ortho_aabb(vec3 box[2], mat4 dest)
+ CGLM_INLINE void glm_ortho_aabb_p(vec3 box[2], float padding, mat4 dest)
+ CGLM_INLINE void glm_ortho_aabb_pz(vec3 box[2], float padding, mat4 dest)
+ CGLM_INLINE void glm_ortho_default(float aspect, mat4 dest)
+ CGLM_INLINE void glm_ortho_default_s(float aspect, float size, mat4 dest)
+ CGLM_INLINE void glm_perspective(float fovy,
+ float aspect,
+ float nearZ,
+ float farZ,
+ mat4 dest)
+ CGLM_INLINE void glm_perspective_default(float aspect, mat4 dest)
+ CGLM_INLINE void glm_perspective_resize(float aspect, mat4 proj)
+ CGLM_INLINE void glm_lookat(vec3 eye, vec3 center, vec3 up, mat4 dest)
+ CGLM_INLINE void glm_look(vec3 eye, vec3 dir, vec3 up, mat4 dest)
+ CGLM_INLINE void glm_look_anyup(vec3 eye, vec3 dir, mat4 dest)
+ CGLM_INLINE void glm_persp_decomp(mat4 proj,
+ float *nearZ, float *farZ,
+ float *top, float *bottom,
+ float *left, float *right)
+ CGLM_INLINE void glm_persp_decompv(mat4 proj, float dest[6])
+ CGLM_INLINE void glm_persp_decomp_x(mat4 proj, float *left, float *right)
+ CGLM_INLINE void glm_persp_decomp_y(mat4 proj, float *top, float *bottom)
+ CGLM_INLINE void glm_persp_decomp_z(mat4 proj, float *nearv, float *farv)
+ CGLM_INLINE void glm_persp_decomp_far(mat4 proj, float *farZ)
+ CGLM_INLINE void glm_persp_decomp_near(mat4 proj, float *nearZ)
+ CGLM_INLINE float glm_persp_fovy(mat4 proj)
+ CGLM_INLINE float glm_persp_aspect(mat4 proj)
+ CGLM_INLINE void glm_persp_sizes(mat4 proj, float fovy, vec4 dest)
+ */
+
+#ifndef cglm_cam_h
+#define cglm_cam_h
+
+#include "common.h"
+#include "plane.h"
+
+#include "clipspace/persp.h"
+
+#ifndef CGLM_CLIPSPACE_INCLUDE_ALL
+# if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+# include "clipspace/ortho_lh_zo.h"
+# include "clipspace/persp_lh_zo.h"
+# include "clipspace/view_lh_zo.h"
+# elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+# include "clipspace/ortho_lh_no.h"
+# include "clipspace/persp_lh_no.h"
+# include "clipspace/view_lh_no.h"
+# elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+# include "clipspace/ortho_rh_zo.h"
+# include "clipspace/persp_rh_zo.h"
+# include "clipspace/view_rh_zo.h"
+# elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+# include "clipspace/ortho_rh_no.h"
+# include "clipspace/persp_rh_no.h"
+# include "clipspace/view_rh_no.h"
+# endif
+#else
+# include "clipspace/ortho_lh_zo.h"
+# include "clipspace/persp_lh_zo.h"
+# include "clipspace/ortho_lh_no.h"
+# include "clipspace/persp_lh_no.h"
+# include "clipspace/ortho_rh_zo.h"
+# include "clipspace/persp_rh_zo.h"
+# include "clipspace/ortho_rh_no.h"
+# include "clipspace/persp_rh_no.h"
+# include "clipspace/view_lh_zo.h"
+# include "clipspace/view_lh_no.h"
+# include "clipspace/view_rh_zo.h"
+# include "clipspace/view_rh_no.h"
+#endif
+
+/*!
+ * @brief set up perspective peprojection matrix
+ *
+ * @param[in] left viewport.left
+ * @param[in] right viewport.right
+ * @param[in] bottom viewport.bottom
+ * @param[in] top viewport.top
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping plane
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_frustum(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glm_frustum_lh_zo(left, right, bottom, top, nearZ, farZ, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glm_frustum_lh_no(left, right, bottom, top, nearZ, farZ, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glm_frustum_rh_zo(left, right, bottom, top, nearZ, farZ, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glm_frustum_rh_no(left, right, bottom, top, nearZ, farZ, dest);
+#endif
+}
+
+/*!
+ * @brief set up orthographic projection matrix
+ *
+ * @param[in] left viewport.left
+ * @param[in] right viewport.right
+ * @param[in] bottom viewport.bottom
+ * @param[in] top viewport.top
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping plane
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glm_ortho_lh_zo(left, right, bottom, top, nearZ, farZ, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glm_ortho_lh_no(left, right, bottom, top, nearZ, farZ, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glm_ortho_rh_zo(left, right, bottom, top, nearZ, farZ, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glm_ortho_rh_no(left, right, bottom, top, nearZ, farZ, dest);
+#endif
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_aabb(vec3 box[2], mat4 dest) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glm_ortho_aabb_lh_zo(box, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glm_ortho_aabb_lh_no(box, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glm_ortho_aabb_rh_zo(box, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glm_ortho_aabb_rh_no(box, dest);
+#endif
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[in] padding padding
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_aabb_p(vec3 box[2], float padding, mat4 dest) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glm_ortho_aabb_p_lh_zo(box, padding, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glm_ortho_aabb_p_lh_no(box, padding, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glm_ortho_aabb_p_rh_zo(box, padding, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glm_ortho_aabb_p_rh_no(box, padding, dest);
+#endif
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[in] padding padding for near and far
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_aabb_pz(vec3 box[2], float padding, mat4 dest) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glm_ortho_aabb_pz_lh_zo(box, padding, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glm_ortho_aabb_pz_lh_no(box, padding, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glm_ortho_aabb_pz_rh_zo(box, padding, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glm_ortho_aabb_pz_rh_no(box, padding, dest);
+#endif
+}
+
+/*!
+ * @brief set up unit orthographic projection matrix
+ *
+ * @param[in] aspect aspect ration ( width / height )
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_default(float aspect, mat4 dest) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glm_ortho_default_lh_zo(aspect, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glm_ortho_default_lh_no(aspect, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glm_ortho_default_rh_zo(aspect, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glm_ortho_default_rh_no(aspect, dest);
+#endif
+}
+
+/*!
+ * @brief set up orthographic projection matrix with given CUBE size
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in] size cube size
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_default_s(float aspect, float size, mat4 dest) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glm_ortho_default_s_lh_zo(aspect, size, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glm_ortho_default_s_lh_no(aspect, size, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glm_ortho_default_s_rh_zo(aspect, size, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glm_ortho_default_s_rh_no(aspect, size, dest);
+#endif
+}
+
+/*!
+ * @brief set up perspective projection matrix
+ *
+ * @param[in] fovy field of view angle
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping planes
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_perspective(float fovy, float aspect, float nearZ, float farZ, mat4 dest) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glm_perspective_lh_zo(fovy, aspect, nearZ, farZ, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glm_perspective_lh_no(fovy, aspect, nearZ, farZ, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glm_perspective_rh_zo(fovy, aspect, nearZ, farZ, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glm_perspective_rh_no(fovy, aspect, nearZ, farZ, dest);
+#endif
+}
+
+/*!
+ * @brief extend perspective projection matrix's far distance
+ *
+ * this function does not guarantee far >= near, be aware of that!
+ *
+ * @param[in, out] proj projection matrix to extend
+ * @param[in] deltaFar distance from existing far (negative to shink)
+ */
+CGLM_INLINE
+void
+glm_persp_move_far(mat4 proj, float deltaFar) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glm_persp_move_far_lh_zo(proj, deltaFar);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glm_persp_move_far_lh_no(proj, deltaFar);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glm_persp_move_far_rh_zo(proj, deltaFar);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glm_persp_move_far_rh_no(proj, deltaFar);
+#endif
+}
+
+/*!
+ * @brief set up perspective projection matrix with default near/far
+ * and angle values
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_perspective_default(float aspect, mat4 dest) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glm_perspective_default_lh_zo(aspect, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glm_perspective_default_lh_no(aspect, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glm_perspective_default_rh_zo(aspect, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glm_perspective_default_rh_no(aspect, dest);
+#endif
+}
+
+/*!
+ * @brief resize perspective matrix by aspect ratio ( width / height )
+ * this makes very easy to resize proj matrix when window /viewport
+ * reized
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in, out] proj perspective projection matrix
+ */
+CGLM_INLINE
+void
+glm_perspective_resize(float aspect, mat4 proj) {
+ if (proj[0][0] == 0.0f)
+ return;
+
+ proj[0][0] = proj[1][1] / aspect;
+}
+
+/*!
+ * @brief set up view matrix
+ *
+ * NOTE: The UP vector must not be parallel to the line of sight from
+ * the eye point to the reference point
+ *
+ * @param[in] eye eye vector
+ * @param[in] center center vector
+ * @param[in] up up vector
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_lookat(vec3 eye, vec3 center, vec3 up, mat4 dest) {
+#if CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_LH_BIT
+ glm_lookat_lh(eye, center, up, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_RH_BIT
+ glm_lookat_rh(eye, center, up, dest);
+#endif
+}
+
+/*!
+ * @brief set up view matrix
+ *
+ * convenient wrapper for lookat: if you only have direction not target self
+ * then this might be useful. Because you need to get target from direction.
+ *
+ * NOTE: The UP vector must not be parallel to the line of sight from
+ * the eye point to the reference point
+ *
+ * @param[in] eye eye vector
+ * @param[in] dir direction vector
+ * @param[in] up up vector
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_look(vec3 eye, vec3 dir, vec3 up, mat4 dest) {
+#if CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_LH_BIT
+ glm_look_lh(eye, dir, up, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_RH_BIT
+ glm_look_rh(eye, dir, up, dest);
+#endif
+}
+
+/*!
+ * @brief set up view matrix
+ *
+ * convenient wrapper for look: if you only have direction and if you don't
+ * care what UP vector is then this might be useful to create view matrix
+ *
+ * @param[in] eye eye vector
+ * @param[in] dir direction vector
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_look_anyup(vec3 eye, vec3 dir, mat4 dest) {
+#if CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_LH_BIT
+ glm_look_anyup_lh(eye, dir, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_RH_BIT
+ glm_look_anyup_rh(eye, dir, dest);
+#endif
+}
+
+/*!
+ * @brief decomposes frustum values of perspective projection.
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ * @param[out] farZ far
+ * @param[out] top top
+ * @param[out] bottom bottom
+ * @param[out] left left
+ * @param[out] right right
+ */
+CGLM_INLINE
+void
+glm_persp_decomp(mat4 proj,
+ float * __restrict nearZ, float * __restrict farZ,
+ float * __restrict top, float * __restrict bottom,
+ float * __restrict left, float * __restrict right) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glm_persp_decomp_lh_zo(proj, nearZ, farZ, top, bottom, left, right);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glm_persp_decomp_lh_no(proj, nearZ, farZ, top, bottom, left, right);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glm_persp_decomp_rh_zo(proj, nearZ, farZ, top, bottom, left, right);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glm_persp_decomp_rh_no(proj, nearZ, farZ, top, bottom, left, right);
+#endif
+}
+
+/*!
+ * @brief decomposes frustum values of perspective projection.
+ * this makes easy to get all values at once
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] dest array
+ */
+CGLM_INLINE
+void
+glm_persp_decompv(mat4 proj, float dest[6]) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glm_persp_decompv_lh_zo(proj, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glm_persp_decompv_lh_no(proj, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glm_persp_decompv_rh_zo(proj, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glm_persp_decompv_rh_no(proj, dest);
+#endif
+}
+
+/*!
+ * @brief decomposes left and right values of perspective projection.
+ * x stands for x axis (left / right axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] left left
+ * @param[out] right right
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_x(mat4 proj,
+ float * __restrict left,
+ float * __restrict right) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glm_persp_decomp_x_lh_zo(proj, left, right);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glm_persp_decomp_x_lh_no(proj, left, right);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glm_persp_decomp_x_rh_zo(proj, left, right);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glm_persp_decomp_x_rh_no(proj, left, right);
+#endif
+}
+
+/*!
+ * @brief decomposes top and bottom values of perspective projection.
+ * y stands for y axis (top / botom axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] top top
+ * @param[out] bottom bottom
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_y(mat4 proj,
+ float * __restrict top,
+ float * __restrict bottom) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glm_persp_decomp_y_lh_zo(proj, top, bottom);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glm_persp_decomp_y_lh_no(proj, top, bottom);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glm_persp_decomp_y_rh_zo(proj, top, bottom);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glm_persp_decomp_y_rh_no(proj, top, bottom);
+#endif
+}
+
+/*!
+ * @brief decomposes near and far values of perspective projection.
+ * z stands for z axis (near / far axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ * @param[out] farZ far
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_z(mat4 proj, float * __restrict nearZ, float * __restrict farZ) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glm_persp_decomp_z_lh_zo(proj, nearZ, farZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glm_persp_decomp_z_lh_no(proj, nearZ, farZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glm_persp_decomp_z_rh_zo(proj, nearZ, farZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glm_persp_decomp_z_rh_no(proj, nearZ, farZ);
+#endif
+}
+
+/*!
+ * @brief decomposes far value of perspective projection.
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] farZ far
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_far(mat4 proj, float * __restrict farZ) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glm_persp_decomp_far_lh_zo(proj, farZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glm_persp_decomp_far_lh_no(proj, farZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glm_persp_decomp_far_rh_zo(proj, farZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glm_persp_decomp_far_rh_no(proj, farZ);
+#endif
+}
+
+/*!
+ * @brief decomposes near value of perspective projection.
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_near(mat4 proj, float * __restrict nearZ) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glm_persp_decomp_near_lh_zo(proj, nearZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glm_persp_decomp_near_lh_no(proj, nearZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glm_persp_decomp_near_rh_zo(proj, nearZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glm_persp_decomp_near_rh_no(proj, nearZ);
+#endif
+}
+
+/*!
+ * @brief returns sizes of near and far planes of perspective projection
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[in] fovy fovy (see brief)
+ * @param[out] dest sizes order: [Wnear, Hnear, Wfar, Hfar]
+ */
+CGLM_INLINE
+void
+glm_persp_sizes(mat4 proj, float fovy, vec4 dest) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glm_persp_sizes_lh_zo(proj, fovy, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glm_persp_sizes_lh_no(proj, fovy, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glm_persp_sizes_rh_zo(proj, fovy, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glm_persp_sizes_rh_no(proj, fovy, dest);
+#endif
+}
+
+#endif /* cglm_cam_h */
diff --git a/libs/cglm/include/cglm/cglm.h b/libs/cglm/include/cglm/cglm.h
new file mode 100644
index 0000000..1828cb4
--- /dev/null
+++ b/libs/cglm/include/cglm/cglm.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_h
+#define cglm_h
+
+#include "common.h"
+#include "vec2.h"
+#include "vec3.h"
+#include "vec4.h"
+#include "ivec2.h"
+#include "ivec3.h"
+#include "ivec4.h"
+#include "mat4.h"
+#include "mat3.h"
+#include "mat2.h"
+#include "affine.h"
+#include "cam.h"
+#include "frustum.h"
+#include "quat.h"
+#include "euler.h"
+#include "plane.h"
+#include "box.h"
+#include "color.h"
+#include "util.h"
+#include "io.h"
+#include "project.h"
+#include "sphere.h"
+#include "ease.h"
+#include "curve.h"
+#include "bezier.h"
+#include "ray.h"
+#include "affine2d.h"
+
+#endif /* cglm_h */
diff --git a/libs/cglm/include/cglm/clipspace/ortho_lh_no.h b/libs/cglm/include/cglm/clipspace/ortho_lh_no.h
new file mode 100644
index 0000000..76c7a94
--- /dev/null
+++ b/libs/cglm/include/cglm/clipspace/ortho_lh_no.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glm_ortho_lh_no(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest)
+ CGLM_INLINE void glm_ortho_aabb_lh_no(vec3 box[2], mat4 dest)
+ CGLM_INLINE void glm_ortho_aabb_p_lh_no(vec3 box[2],
+ float padding,
+ mat4 dest)
+ CGLM_INLINE void glm_ortho_aabb_pz_lh_no(vec3 box[2],
+ float padding,
+ mat4 dest)
+ CGLM_INLINE void glm_ortho_default_lh_no(float aspect,
+ mat4 dest)
+ CGLM_INLINE void glm_ortho_default_s_lh_no(float aspect,
+ float size,
+ mat4 dest)
+ */
+
+#ifndef cglm_ortho_lh_no_h
+#define cglm_ortho_lh_no_h
+
+#include "../common.h"
+#include "../plane.h"
+#include "../mat4.h"
+
+/*!
+ * @brief set up orthographic projection matrix
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] left viewport.left
+ * @param[in] right viewport.right
+ * @param[in] bottom viewport.bottom
+ * @param[in] top viewport.top
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping plane
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_lh_no(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest) {
+ float rl, tb, fn;
+
+ glm_mat4_zero(dest);
+
+ rl = 1.0f / (right - left);
+ tb = 1.0f / (top - bottom);
+ fn =-1.0f / (farZ - nearZ);
+
+ dest[0][0] = 2.0f * rl;
+ dest[1][1] = 2.0f * tb;
+ dest[2][2] =-2.0f * fn;
+ dest[3][0] =-(right + left) * rl;
+ dest[3][1] =-(top + bottom) * tb;
+ dest[3][2] = (farZ + nearZ) * fn;
+ dest[3][3] = 1.0f;
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_aabb_lh_no(vec3 box[2], mat4 dest) {
+ glm_ortho_lh_no(box[0][0], box[1][0],
+ box[0][1], box[1][1],
+ -box[1][2], -box[0][2],
+ dest);
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[in] padding padding
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_aabb_p_lh_no(vec3 box[2], float padding, mat4 dest) {
+ glm_ortho_lh_no(box[0][0] - padding, box[1][0] + padding,
+ box[0][1] - padding, box[1][1] + padding,
+ -(box[1][2] + padding), -(box[0][2] - padding),
+ dest);
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[in] padding padding for near and far
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_aabb_pz_lh_no(vec3 box[2], float padding, mat4 dest) {
+ glm_ortho_lh_no(box[0][0], box[1][0],
+ box[0][1], box[1][1],
+ -(box[1][2] + padding), -(box[0][2] - padding),
+ dest);
+}
+
+/*!
+ * @brief set up unit orthographic projection matrix
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] aspect aspect ration ( width / height )
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_default_lh_no(float aspect, mat4 dest) {
+ if (aspect >= 1.0f) {
+ glm_ortho_lh_no(-aspect, aspect, -1.0f, 1.0f, -100.0f, 100.0f, dest);
+ return;
+ }
+
+ aspect = 1.0f / aspect;
+
+ glm_ortho_lh_no(-1.0f, 1.0f, -aspect, aspect, -100.0f, 100.0f, dest);
+}
+
+/*!
+ * @brief set up orthographic projection matrix with given CUBE size
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in] size cube size
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_default_s_lh_no(float aspect, float size, mat4 dest) {
+ if (aspect >= 1.0f) {
+ glm_ortho_lh_no(-size * aspect,
+ size * aspect,
+ -size,
+ size,
+ -size - 100.0f,
+ size + 100.0f,
+ dest);
+ return;
+ }
+
+ glm_ortho_lh_no(-size,
+ size,
+ -size / aspect,
+ size / aspect,
+ -size - 100.0f,
+ size + 100.0f,
+ dest);
+}
+
+#endif /*cglm_ortho_lh_no_h*/
diff --git a/libs/cglm/include/cglm/clipspace/ortho_lh_zo.h b/libs/cglm/include/cglm/clipspace/ortho_lh_zo.h
new file mode 100644
index 0000000..e45530d
--- /dev/null
+++ b/libs/cglm/include/cglm/clipspace/ortho_lh_zo.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glm_ortho_lh_zo(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest)
+ CGLM_INLINE void glm_ortho_aabb_lh_zo(vec3 box[2], mat4 dest)
+ CGLM_INLINE void glm_ortho_aabb_p_lh_zo(vec3 box[2],
+ float padding,
+ mat4 dest)
+ CGLM_INLINE void glm_ortho_aabb_pz_lh_zo(vec3 box[2],
+ float padding,
+ mat4 dest)
+ CGLM_INLINE void glm_ortho_default_lh_zo(float aspect,
+ mat4 dest)
+ CGLM_INLINE void glm_ortho_default_s_lh_zo(float aspect,
+ float size,
+ mat4 dest)
+ */
+
+#ifndef cglm_ortho_lh_zo_h
+#define cglm_ortho_lh_zo_h
+
+#include "../common.h"
+#include "../plane.h"
+#include "../mat4.h"
+
+/*!
+ * @brief set up orthographic projection matrix with a left-hand coordinate
+ * system and a clip-space of [0, 1].
+ *
+ * @param[in] left viewport.left
+ * @param[in] right viewport.right
+ * @param[in] bottom viewport.bottom
+ * @param[in] top viewport.top
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping plane
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_lh_zo(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest) {
+ float rl, tb, fn;
+
+ glm_mat4_zero(dest);
+
+ rl = 1.0f / (right - left);
+ tb = 1.0f / (top - bottom);
+ fn =-1.0f / (farZ - nearZ);
+
+ dest[0][0] = 2.0f * rl;
+ dest[1][1] = 2.0f * tb;
+ dest[2][2] =-fn;
+ dest[3][0] =-(right + left) * rl;
+ dest[3][1] =-(top + bottom) * tb;
+ dest[3][2] = nearZ * fn;
+ dest[3][3] = 1.0f;
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ * with a left-hand coordinate system and a clip-space of [0, 1].
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_aabb_lh_zo(vec3 box[2], mat4 dest) {
+ glm_ortho_lh_zo(box[0][0], box[1][0],
+ box[0][1], box[1][1],
+ -box[1][2], -box[0][2],
+ dest);
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ * with a left-hand coordinate system and a clip-space of [0, 1].
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[in] padding padding
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_aabb_p_lh_zo(vec3 box[2], float padding, mat4 dest) {
+ glm_ortho_lh_zo(box[0][0] - padding, box[1][0] + padding,
+ box[0][1] - padding, box[1][1] + padding,
+ -(box[1][2] + padding), -(box[0][2] - padding),
+ dest);
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ * with a left-hand coordinate system and a clip-space of [0, 1].
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[in] padding padding for near and far
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_aabb_pz_lh_zo(vec3 box[2], float padding, mat4 dest) {
+ glm_ortho_lh_zo(box[0][0], box[1][0],
+ box[0][1], box[1][1],
+ -(box[1][2] + padding), -(box[0][2] - padding),
+ dest);
+}
+
+/*!
+ * @brief set up unit orthographic projection matrix
+ * with a left-hand coordinate system and a clip-space of [0, 1].
+ *
+ * @param[in] aspect aspect ration ( width / height )
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_default_lh_zo(float aspect, mat4 dest) {
+ if (aspect >= 1.0f) {
+ glm_ortho_lh_zo(-aspect, aspect, -1.0f, 1.0f, -100.0f, 100.0f, dest);
+ return;
+ }
+
+ aspect = 1.0f / aspect;
+
+ glm_ortho_lh_zo(-1.0f, 1.0f, -aspect, aspect, -100.0f, 100.0f, dest);
+}
+
+/*!
+ * @brief set up orthographic projection matrix with given CUBE size
+ * with a left-hand coordinate system and a clip-space of [0, 1].
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in] size cube size
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_default_s_lh_zo(float aspect, float size, mat4 dest) {
+ if (aspect >= 1.0f) {
+ glm_ortho_lh_zo(-size * aspect,
+ size * aspect,
+ -size,
+ size,
+ -size - 100.0f,
+ size + 100.0f,
+ dest);
+ return;
+ }
+
+ glm_ortho_lh_zo(-size,
+ size,
+ -size / aspect,
+ size / aspect,
+ -size - 100.0f,
+ size + 100.0f,
+ dest);
+}
+
+#endif /*cglm_ortho_lh_zo_h*/
diff --git a/libs/cglm/include/cglm/clipspace/ortho_rh_no.h b/libs/cglm/include/cglm/clipspace/ortho_rh_no.h
new file mode 100644
index 0000000..aa7a906
--- /dev/null
+++ b/libs/cglm/include/cglm/clipspace/ortho_rh_no.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glm_ortho_rh_no(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest)
+ CGLM_INLINE void glm_ortho_aabb_rh_no(vec3 box[2], mat4 dest)
+ CGLM_INLINE void glm_ortho_aabb_p_rh_no(vec3 box[2],
+ float padding,
+ mat4 dest)
+ CGLM_INLINE void glm_ortho_aabb_pz_rh_no(vec3 box[2],
+ float padding,
+ mat4 dest)
+ CGLM_INLINE void glm_ortho_default_rh_no(float aspect,
+ mat4 dest)
+ CGLM_INLINE void glm_ortho_default_s_rh_no(float aspect,
+ float size,
+ mat4 dest)
+ */
+
+#ifndef cglm_ortho_rh_no_h
+#define cglm_ortho_rh_no_h
+
+#include "../common.h"
+#include "../plane.h"
+#include "../mat4.h"
+
+/*!
+ * @brief set up orthographic projection matrix
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] left viewport.left
+ * @param[in] right viewport.right
+ * @param[in] bottom viewport.bottom
+ * @param[in] top viewport.top
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping plane
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_rh_no(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest) {
+ float rl, tb, fn;
+
+ glm_mat4_zero(dest);
+
+ rl = 1.0f / (right - left);
+ tb = 1.0f / (top - bottom);
+ fn =-1.0f / (farZ - nearZ);
+
+ dest[0][0] = 2.0f * rl;
+ dest[1][1] = 2.0f * tb;
+ dest[2][2] = 2.0f * fn;
+ dest[3][0] =-(right + left) * rl;
+ dest[3][1] =-(top + bottom) * tb;
+ dest[3][2] = (farZ + nearZ) * fn;
+ dest[3][3] = 1.0f;
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_aabb_rh_no(vec3 box[2], mat4 dest) {
+ glm_ortho_rh_no(box[0][0], box[1][0],
+ box[0][1], box[1][1],
+ -box[1][2], -box[0][2],
+ dest);
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[in] padding padding
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_aabb_p_rh_no(vec3 box[2], float padding, mat4 dest) {
+ glm_ortho_rh_no(box[0][0] - padding, box[1][0] + padding,
+ box[0][1] - padding, box[1][1] + padding,
+ -(box[1][2] + padding), -(box[0][2] - padding),
+ dest);
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[in] padding padding for near and far
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_aabb_pz_rh_no(vec3 box[2], float padding, mat4 dest) {
+ glm_ortho_rh_no(box[0][0], box[1][0],
+ box[0][1], box[1][1],
+ -(box[1][2] + padding), -(box[0][2] - padding),
+ dest);
+}
+
+/*!
+ * @brief set up unit orthographic projection matrix
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] aspect aspect ration ( width / height )
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_default_rh_no(float aspect, mat4 dest) {
+ if (aspect >= 1.0f) {
+ glm_ortho_rh_no(-aspect, aspect, -1.0f, 1.0f, -100.0f, 100.0f, dest);
+ return;
+ }
+
+ aspect = 1.0f / aspect;
+
+ glm_ortho_rh_no(-1.0f, 1.0f, -aspect, aspect, -100.0f, 100.0f, dest);
+}
+
+/*!
+ * @brief set up orthographic projection matrix with given CUBE size
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in] size cube size
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_default_s_rh_no(float aspect, float size, mat4 dest) {
+ if (aspect >= 1.0f) {
+ glm_ortho_rh_no(-size * aspect,
+ size * aspect,
+ -size,
+ size,
+ -size - 100.0f,
+ size + 100.0f,
+ dest);
+ return;
+ }
+
+ glm_ortho_rh_no(-size,
+ size,
+ -size / aspect,
+ size / aspect,
+ -size - 100.0f,
+ size + 100.0f,
+ dest);
+}
+
+#endif /*cglm_ortho_rh_no_h*/
diff --git a/libs/cglm/include/cglm/clipspace/ortho_rh_zo.h b/libs/cglm/include/cglm/clipspace/ortho_rh_zo.h
new file mode 100644
index 0000000..7a0876c
--- /dev/null
+++ b/libs/cglm/include/cglm/clipspace/ortho_rh_zo.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glm_ortho_rh_zo(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest)
+ CGLM_INLINE void glm_ortho_aabb_rh_zo(vec3 box[2], mat4 dest)
+ CGLM_INLINE void glm_ortho_aabb_p_rh_zo(vec3 box[2],
+ float padding,
+ mat4 dest)
+ CGLM_INLINE void glm_ortho_aabb_pz_rh_zo(vec3 box[2],
+ float padding,
+ mat4 dest)
+ CGLM_INLINE void glm_ortho_default_rh_zo(float aspect,
+ mat4 dest)
+ CGLM_INLINE void glm_ortho_default_s_rh_zo(float aspect,
+ float size,
+ mat4 dest)
+ */
+
+#ifndef cglm_ortho_rh_zo_h
+#define cglm_ortho_rh_zo_h
+
+#include "../common.h"
+#include "../plane.h"
+#include "../mat4.h"
+
+/*!
+ * @brief set up orthographic projection matrix with a right-hand coordinate
+ * system and a clip-space of [0, 1].
+ *
+ * @param[in] left viewport.left
+ * @param[in] right viewport.right
+ * @param[in] bottom viewport.bottom
+ * @param[in] top viewport.top
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping plane
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_rh_zo(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest) {
+ float rl, tb, fn;
+
+ glm_mat4_zero(dest);
+
+ rl = 1.0f / (right - left);
+ tb = 1.0f / (top - bottom);
+ fn =-1.0f / (farZ - nearZ);
+
+ dest[0][0] = 2.0f * rl;
+ dest[1][1] = 2.0f * tb;
+ dest[2][2] = fn;
+ dest[3][0] =-(right + left) * rl;
+ dest[3][1] =-(top + bottom) * tb;
+ dest[3][2] = nearZ * fn;
+ dest[3][3] = 1.0f;
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ * with a right-hand coordinate system and a clip-space with depth
+ * values from zero to one.
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_aabb_rh_zo(vec3 box[2], mat4 dest) {
+ glm_ortho_rh_zo(box[0][0], box[1][0],
+ box[0][1], box[1][1],
+ -box[1][2], -box[0][2],
+ dest);
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ * with a right-hand coordinate system and a clip-space with depth
+ * values from zero to one.
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[in] padding padding
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_aabb_p_rh_zo(vec3 box[2], float padding, mat4 dest) {
+ glm_ortho_rh_zo(box[0][0] - padding, box[1][0] + padding,
+ box[0][1] - padding, box[1][1] + padding,
+ -(box[1][2] + padding), -(box[0][2] - padding),
+ dest);
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ * with a right-hand coordinate system and a clip-space with depth
+ * values from zero to one.
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[in] padding padding for near and far
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_aabb_pz_rh_zo(vec3 box[2], float padding, mat4 dest) {
+ glm_ortho_rh_zo(box[0][0], box[1][0],
+ box[0][1], box[1][1],
+ -(box[1][2] + padding), -(box[0][2] - padding),
+ dest);
+}
+
+/*!
+ * @brief set up unit orthographic projection matrix with a right-hand
+ * coordinate system and a clip-space of [0, 1].
+ *
+ * @param[in] aspect aspect ration ( width / height )
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_default_rh_zo(float aspect, mat4 dest) {
+ if (aspect >= 1.0f) {
+ glm_ortho_rh_zo(-aspect, aspect, -1.0f, 1.0f, -100.0f, 100.0f, dest);
+ return;
+ }
+
+ aspect = 1.0f / aspect;
+
+ glm_ortho_rh_zo(-1.0f, 1.0f, -aspect, aspect, -100.0f, 100.0f, dest);
+}
+
+/*!
+ * @brief set up orthographic projection matrix with given CUBE size
+ * with a right-hand coordinate system and a clip-space with depth
+ * values from zero to one.
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in] size cube size
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_ortho_default_s_rh_zo(float aspect, float size, mat4 dest) {
+ if (aspect >= 1.0f) {
+ glm_ortho_rh_zo(-size * aspect,
+ size * aspect,
+ -size,
+ size,
+ -size - 100.0f,
+ size + 100.0f,
+ dest);
+ return;
+ }
+
+ glm_ortho_rh_zo(-size,
+ size,
+ -size / aspect,
+ size / aspect,
+ -size - 100.0f,
+ size + 100.0f,
+ dest);
+}
+
+#endif /*cglm_ortho_rh_zo_h*/
diff --git a/libs/cglm/include/cglm/clipspace/persp.h b/libs/cglm/include/cglm/clipspace/persp.h
new file mode 100644
index 0000000..15aa715
--- /dev/null
+++ b/libs/cglm/include/cglm/clipspace/persp.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glm_persp_decomp_far(mat4 proj, float *farZ)
+ CGLM_INLINE float glm_persp_fovy(mat4 proj)
+ CGLM_INLINE float glm_persp_aspect(mat4 proj)
+ CGLM_INLINE void glm_persp_sizes(mat4 proj, float fovy, vec4 dest)
+ */
+
+#ifndef cglm_persp_h
+#define cglm_persp_h
+
+#include "../common.h"
+#include "../plane.h"
+#include "../mat4.h"
+
+/*!
+ * @brief returns field of view angle along the Y-axis (in radians)
+ *
+ * if you need to degrees, use glm_deg to convert it or use this:
+ * fovy_deg = glm_deg(glm_persp_fovy(projMatrix))
+ *
+ * @param[in] proj perspective projection matrix
+ */
+CGLM_INLINE
+float
+glm_persp_fovy(mat4 proj) {
+ return 2.0f * atanf(1.0f / proj[1][1]);
+}
+
+/*!
+ * @brief returns aspect ratio of perspective projection
+ *
+ * @param[in] proj perspective projection matrix
+ */
+CGLM_INLINE
+float
+glm_persp_aspect(mat4 proj) {
+ return proj[1][1] / proj[0][0];
+}
+
+#endif /* cglm_persp_h */
diff --git a/libs/cglm/include/cglm/clipspace/persp_lh_no.h b/libs/cglm/include/cglm/clipspace/persp_lh_no.h
new file mode 100644
index 0000000..703530e
--- /dev/null
+++ b/libs/cglm/include/cglm/clipspace/persp_lh_no.h
@@ -0,0 +1,395 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glm_frustum_lh_no(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest)
+ CGLM_INLINE void glm_perspective_lh_no(float fovy,
+ float aspect,
+ float nearZ,
+ float farZ,
+ mat4 dest)
+ CGLM_INLINE void glm_perspective_default_lh_no(float aspect, mat4 dest)
+ CGLM_INLINE void glm_perspective_resize_lh_no(float aspect, mat4 proj)
+ CGLM_INLINE void glm_persp_move_far_lh_no(mat4 proj,
+ float deltaFar)
+ CGLM_INLINE void glm_persp_decomp_lh_no(mat4 proj,
+ float * __restrict nearZ,
+ float * __restrict farZ,
+ float * __restrict top,
+ float * __restrict bottom,
+ float * __restrict left,
+ float * __restrict right)
+ CGLM_INLINE void glm_persp_decompv_lh_no(mat4 proj,
+ float dest[6])
+ CGLM_INLINE void glm_persp_decomp_x_lh_no(mat4 proj,
+ float * __restrict left,
+ float * __restrict right)
+ CGLM_INLINE void glm_persp_decomp_y_lh_no(mat4 proj,
+ float * __restrict top,
+ float * __restrict bottom)
+ CGLM_INLINE void glm_persp_decomp_z_lh_no(mat4 proj,
+ float * __restrict nearZ,
+ float * __restrict farZ)
+ CGLM_INLINE void glm_persp_decomp_far_lh_no(mat4 proj, float * __restrict farZ)
+ CGLM_INLINE void glm_persp_decomp_near_lh_no(mat4 proj, float * __restrict nearZ)
+ CGLM_INLINE void glm_persp_sizes_lh_no(mat4 proj, float fovy, vec4 dest)
+ */
+
+#ifndef cglm_persp_lh_no_h
+#define cglm_persp_lh_no_h
+
+#include "../common.h"
+#include "persp.h"
+
+/*!
+ * @brief set up perspective peprojection matrix
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] left viewport.left
+ * @param[in] right viewport.right
+ * @param[in] bottom viewport.bottom
+ * @param[in] top viewport.top
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping plane
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_frustum_lh_no(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest) {
+ float rl, tb, fn, nv;
+
+ glm_mat4_zero(dest);
+
+ rl = 1.0f / (right - left);
+ tb = 1.0f / (top - bottom);
+ fn =-1.0f / (farZ - nearZ);
+ nv = 2.0f * nearZ;
+
+ dest[0][0] = nv * rl;
+ dest[1][1] = nv * tb;
+ dest[2][0] = (right + left) * rl;
+ dest[2][1] = (top + bottom) * tb;
+ dest[2][2] =-(farZ + nearZ) * fn;
+ dest[2][3] = 1.0f;
+ dest[3][2] = farZ * nv * fn;
+}
+
+/*!
+ * @brief set up perspective projection matrix
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] fovy field of view angle
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping planes
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_perspective_lh_no(float fovy,
+ float aspect,
+ float nearZ,
+ float farZ,
+ mat4 dest) {
+ float f, fn;
+
+ glm_mat4_zero(dest);
+
+ f = 1.0f / tanf(fovy * 0.5f);
+ fn = 1.0f / (nearZ - farZ);
+
+ dest[0][0] = f / aspect;
+ dest[1][1] = f;
+ dest[2][2] =-(nearZ + farZ) * fn;
+ dest[2][3] = 1.0f;
+ dest[3][2] = 2.0f * nearZ * farZ * fn;
+
+}
+
+/*!
+ * @brief set up perspective projection matrix with default near/far
+ * and angle values with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_perspective_default_lh_no(float aspect, mat4 dest) {
+ glm_perspective_lh_no(GLM_PI_4f, aspect, 0.01f, 100.0f, dest);
+}
+
+/*!
+ * @brief resize perspective matrix by aspect ratio ( width / height )
+ * this makes very easy to resize proj matrix when window /viewport
+ * resized with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in, out] proj perspective projection matrix
+ */
+CGLM_INLINE
+void
+glm_perspective_resize_lh_no(float aspect, mat4 proj) {
+ if (proj[0][0] == 0.0f)
+ return;
+
+ proj[0][0] = proj[1][1] / aspect;
+}
+
+/*!
+ * @brief extend perspective projection matrix's far distance
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * this function does not guarantee far >= near, be aware of that!
+ *
+ * @param[in, out] proj projection matrix to extend
+ * @param[in] deltaFar distance from existing far (negative to shink)
+ */
+CGLM_INLINE
+void
+glm_persp_move_far_lh_no(mat4 proj, float deltaFar) {
+ float fn, farZ, nearZ, p22, p32;
+
+ p22 = -proj[2][2];
+ p32 = proj[3][2];
+
+ nearZ = p32 / (p22 - 1.0f);
+ farZ = p32 / (p22 + 1.0f) + deltaFar;
+ fn = 1.0f / (nearZ - farZ);
+
+ proj[2][2] = -(farZ + nearZ) * fn;
+ proj[3][2] = 2.0f * nearZ * farZ * fn;
+}
+
+/*!
+ * @brief decomposes frustum values of perspective projection
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ * @param[out] farZ far
+ * @param[out] top top
+ * @param[out] bottom bottom
+ * @param[out] left left
+ * @param[out] right right
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_lh_no(mat4 proj,
+ float * __restrict nearZ, float * __restrict farZ,
+ float * __restrict top, float * __restrict bottom,
+ float * __restrict left, float * __restrict right) {
+ float m00, m11, m20, m21, m22, m32, n, f;
+ float n_m11, n_m00;
+
+ m00 = proj[0][0];
+ m11 = proj[1][1];
+ m20 = proj[2][0];
+ m21 = proj[2][1];
+ m22 =-proj[2][2];
+ m32 = proj[3][2];
+
+ n = m32 / (m22 - 1.0f);
+ f = m32 / (m22 + 1.0f);
+
+ n_m11 = n / m11;
+ n_m00 = n / m00;
+
+ *nearZ = n;
+ *farZ = f;
+ *bottom = n_m11 * (m21 - 1.0f);
+ *top = n_m11 * (m21 + 1.0f);
+ *left = n_m00 * (m20 - 1.0f);
+ *right = n_m00 * (m20 + 1.0f);
+}
+
+/*!
+ * @brief decomposes frustum values of perspective projection
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ * this makes easy to get all values at once
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] dest array
+ */
+CGLM_INLINE
+void
+glm_persp_decompv_lh_no(mat4 proj, float dest[6]) {
+ glm_persp_decomp_lh_no(proj, &dest[0], &dest[1], &dest[2],
+ &dest[3], &dest[4], &dest[5]);
+}
+
+/*!
+ * @brief decomposes left and right values of perspective projection
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ * x stands for x axis (left / right axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] left left
+ * @param[out] right right
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_x_lh_no(mat4 proj,
+ float * __restrict left,
+ float * __restrict right) {
+ float nearZ, m20, m00, m22;
+
+ m00 = proj[0][0];
+ m20 = proj[2][0];
+ m22 =-proj[2][2];
+
+ nearZ = proj[3][2] / (m22 - 1.0f);
+ *left = nearZ * (m20 - 1.0f) / m00;
+ *right = nearZ * (m20 + 1.0f) / m00;
+}
+
+/*!
+ * @brief decomposes top and bottom values of perspective projection
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ * y stands for y axis (top / botom axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] top top
+ * @param[out] bottom bottom
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_y_lh_no(mat4 proj,
+ float * __restrict top,
+ float * __restrict bottom) {
+ float nearZ, m21, m11, m22;
+
+ m21 = proj[2][1];
+ m11 = proj[1][1];
+ m22 =-proj[2][2];
+
+ nearZ = proj[3][2] / (m22 - 1.0f);
+ *bottom = nearZ * (m21 - 1.0f) / m11;
+ *top = nearZ * (m21 + 1.0f) / m11;
+}
+
+/*!
+ * @brief decomposes near and far values of perspective projection
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ * z stands for z axis (near / far axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ * @param[out] farZ far
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_z_lh_no(mat4 proj,
+ float * __restrict nearZ,
+ float * __restrict farZ) {
+ float m32, m22;
+
+ m32 = proj[3][2];
+ m22 =-proj[2][2];
+
+ *nearZ = m32 / (m22 - 1.0f);
+ *farZ = m32 / (m22 + 1.0f);
+}
+
+/*!
+ * @brief decomposes far value of perspective projection
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] farZ far
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_far_lh_no(mat4 proj, float * __restrict farZ) {
+ *farZ = proj[3][2] / (-proj[2][2] + 1.0f);
+}
+
+/*!
+ * @brief decomposes near value of perspective projection
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_near_lh_no(mat4 proj, float * __restrict nearZ) {
+ *nearZ = proj[3][2] / (-proj[2][2] - 1.0f);
+}
+
+/*!
+ * @brief returns sizes of near and far planes of perspective projection
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[in] fovy fovy (see brief)
+ * @param[out] dest sizes order: [Wnear, Hnear, Wfar, Hfar]
+ */
+CGLM_INLINE
+void
+glm_persp_sizes_lh_no(mat4 proj, float fovy, vec4 dest) {
+ float t, a, nearZ, farZ;
+
+ t = 2.0f * tanf(fovy * 0.5f);
+ a = glm_persp_aspect(proj);
+
+ glm_persp_decomp_z_lh_no(proj, &nearZ, &farZ);
+
+ dest[1] = t * nearZ;
+ dest[3] = t * farZ;
+ dest[0] = a * dest[1];
+ dest[2] = a * dest[3];
+}
+
+/*!
+ * @brief returns field of view angle along the Y-axis (in radians)
+ * with a left-hand coordinate system and a clip-space of [-1, 1].
+ *
+ * if you need to degrees, use glm_deg to convert it or use this:
+ * fovy_deg = glm_deg(glm_persp_fovy(projMatrix))
+ *
+ * @param[in] proj perspective projection matrix
+ */
+CGLM_INLINE
+float
+glm_persp_fovy_lh_no(mat4 proj) {
+ return glm_persp_fovy(proj);
+}
+
+/*!
+ * @brief returns aspect ratio of perspective projection
+ * with a left-hand coordinate system and a clip-space of [-1, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ */
+CGLM_INLINE
+float
+glm_persp_aspect_lh_no(mat4 proj) {
+ return glm_persp_aspect(proj);
+}
+
+#endif /*cglm_cam_lh_no_h*/
diff --git a/libs/cglm/include/cglm/clipspace/persp_lh_zo.h b/libs/cglm/include/cglm/clipspace/persp_lh_zo.h
new file mode 100644
index 0000000..de89643
--- /dev/null
+++ b/libs/cglm/include/cglm/clipspace/persp_lh_zo.h
@@ -0,0 +1,387 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glm_frustum_lh_zo(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest)
+ CGLM_INLINE void glm_perspective_lh_zo(float fovy,
+ float aspect,
+ float nearZ,
+ float farZ,
+ mat4 dest)
+ CGLM_INLINE void glm_perspective_default_lh_zo(float aspect, mat4 dest)
+ CGLM_INLINE void glm_perspective_resize_lh_zo(float aspect, mat4 proj)
+ CGLM_INLINE void glm_persp_move_far_lh_zo(mat4 proj,
+ float deltaFar)
+ CGLM_INLINE void glm_persp_decomp_lh_zo(mat4 proj,
+ float * __restrict nearZ,
+ float * __restrict farZ,
+ float * __restrict top,
+ float * __restrict bottom,
+ float * __restrict left,
+ float * __restrict right)
+ CGLM_INLINE void glm_persp_decompv_lh_zo(mat4 proj,
+ float dest[6])
+ CGLM_INLINE void glm_persp_decomp_x_lh_zo(mat4 proj,
+ float * __restrict left,
+ float * __restrict right)
+ CGLM_INLINE void glm_persp_decomp_y_lh_zo(mat4 proj,
+ float * __restrict top,
+ float * __restrict bottom)
+ CGLM_INLINE void glm_persp_decomp_z_lh_zo(mat4 proj,
+ float * __restrict nearZ,
+ float * __restrict farZ)
+ CGLM_INLINE void glm_persp_decomp_far_lh_zo(mat4 proj, float * __restrict farZ)
+ CGLM_INLINE void glm_persp_decomp_near_lh_zo(mat4 proj, float * __restrict nearZ)
+ CGLM_INLINE void glm_persp_sizes_lh_zo(mat4 proj, float fovy, vec4 dest)
+ */
+
+#ifndef cglm_persp_lh_zo_h
+#define cglm_persp_lh_zo_h
+
+#include "../common.h"
+#include "persp.h"
+
+/*!
+ * @brief set up perspective peprojection matrix with a left-hand coordinate
+ * system and a clip-space of [0, 1].
+ *
+ * @param[in] left viewport.left
+ * @param[in] right viewport.right
+ * @param[in] bottom viewport.bottom
+ * @param[in] top viewport.top
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping plane
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_frustum_lh_zo(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest) {
+ float rl, tb, fn, nv;
+
+ glm_mat4_zero(dest);
+
+ rl = 1.0f / (right - left);
+ tb = 1.0f / (top - bottom);
+ fn =-1.0f / (farZ - nearZ);
+ nv = 2.0f * nearZ;
+
+ dest[0][0] = nv * rl;
+ dest[1][1] = nv * tb;
+ dest[2][0] = (right + left) * rl;
+ dest[2][1] = (top + bottom) * tb;
+ dest[2][2] =-farZ * fn;
+ dest[2][3] = 1.0f;
+ dest[3][2] = farZ * nearZ * fn;
+}
+
+/*!
+ * @brief set up perspective projection matrix with a left-hand coordinate
+ * system and a clip-space of [0, 1].
+ *
+ * @param[in] fovy field of view angle
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping planes
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_perspective_lh_zo(float fovy,
+ float aspect,
+ float nearZ,
+ float farZ,
+ mat4 dest) {
+ float f, fn;
+
+ glm_mat4_zero(dest);
+
+ f = 1.0f / tanf(fovy * 0.5f);
+ fn = 1.0f / (nearZ - farZ);
+
+ dest[0][0] = f / aspect;
+ dest[1][1] = f;
+ dest[2][2] =-farZ * fn;
+ dest[2][3] = 1.0f;
+ dest[3][2] = nearZ * farZ * fn;
+}
+
+/*!
+ * @brief extend perspective projection matrix's far distance with a
+ * left-hand coordinate system and a clip-space with depth values
+ * from zero to one.
+ *
+ * this function does not guarantee far >= near, be aware of that!
+ *
+ * @param[in, out] proj projection matrix to extend
+ * @param[in] deltaFar distance from existing far (negative to shink)
+ */
+CGLM_INLINE
+void
+glm_persp_move_far_lh_zo(mat4 proj, float deltaFar) {
+ float fn, farZ, nearZ, p22, p32;
+
+ p22 = -proj[2][2];
+ p32 = proj[3][2];
+
+ nearZ = p32 / p22;
+ farZ = p32 / (p22 + 1.0f) + deltaFar;
+ fn = 1.0f / (nearZ - farZ);
+
+ proj[2][2] = -farZ * fn;
+ proj[3][2] = nearZ * farZ * fn;
+}
+
+/*!
+ * @brief set up perspective projection matrix with default near/far
+ * and angle values with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_perspective_default_lh_zo(float aspect, mat4 dest) {
+ glm_perspective_lh_zo(GLM_PI_4f, aspect, 0.01f, 100.0f, dest);
+}
+
+/*!
+ * @brief resize perspective matrix by aspect ratio ( width / height )
+ * this makes very easy to resize proj matrix when window /viewport
+ * reized
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in, out] proj perspective projection matrix
+ */
+CGLM_INLINE
+void
+glm_perspective_resize_lh_zo(float aspect, mat4 proj) {
+ if (proj[0][0] == 0.0f)
+ return;
+
+ proj[0][0] = proj[1][1] / aspect;
+}
+
+/*!
+ * @brief decomposes frustum values of perspective projection
+ * with angle values with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ * @param[out] farZ far
+ * @param[out] top top
+ * @param[out] bottom bottom
+ * @param[out] left left
+ * @param[out] right right
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_lh_zo(mat4 proj,
+ float * __restrict nearZ, float * __restrict farZ,
+ float * __restrict top, float * __restrict bottom,
+ float * __restrict left, float * __restrict right) {
+ float m00, m11, m20, m21, m22, m32, n, f;
+ float n_m11, n_m00;
+
+ m00 = proj[0][0];
+ m11 = proj[1][1];
+ m20 = proj[2][0];
+ m21 = proj[2][1];
+ m22 =-proj[2][2];
+ m32 = proj[3][2];
+
+ n = m32 / m22;
+ f = m32 / (m22 + 1.0f);
+
+ n_m11 = n / m11;
+ n_m00 = n / m00;
+
+ *nearZ = n;
+ *farZ = f;
+ *bottom = n_m11 * (m21 - 1.0f);
+ *top = n_m11 * (m21 + 1.0f);
+ *left = n_m00 * (m20 - 1.0f);
+ *right = n_m00 * (m20 + 1.0f);
+}
+
+/*!
+ * @brief decomposes frustum values of perspective projection
+ * with angle values with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ * this makes easy to get all values at once
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] dest array
+ */
+CGLM_INLINE
+void
+glm_persp_decompv_lh_zo(mat4 proj, float dest[6]) {
+ glm_persp_decomp_lh_zo(proj, &dest[0], &dest[1], &dest[2],
+ &dest[3], &dest[4], &dest[5]);
+}
+
+/*!
+ * @brief decomposes left and right values of perspective projection (ZO).
+ * x stands for x axis (left / right axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] left left
+ * @param[out] right right
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_x_lh_zo(mat4 proj,
+ float * __restrict left,
+ float * __restrict right) {
+ float nearZ, m20, m00;
+
+ m00 = proj[0][0];
+ m20 = proj[2][0];
+
+ nearZ = proj[3][2] / (proj[3][3]);
+ *left = nearZ * (m20 - 1.0f) / m00;
+ *right = nearZ * (m20 + 1.0f) / m00;
+}
+
+/*!
+ * @brief decomposes top and bottom values of perspective projection
+ * with angle values with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ * y stands for y axis (top / bottom axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] top top
+ * @param[out] bottom bottom
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_y_lh_zo(mat4 proj,
+ float * __restrict top,
+ float * __restrict bottom) {
+ float nearZ, m21, m11;
+
+ m21 = proj[2][1];
+ m11 = proj[1][1];
+
+ nearZ = proj[3][2] / (proj[3][3]);
+ *bottom = nearZ * (m21 - 1) / m11;
+ *top = nearZ * (m21 + 1) / m11;
+}
+
+/*!
+ * @brief decomposes near and far values of perspective projection
+ * with angle values with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ * z stands for z axis (near / far axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ * @param[out] farZ far
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_z_lh_zo(mat4 proj,
+ float * __restrict nearZ,
+ float * __restrict farZ) {
+ float m32, m22;
+
+ m32 = proj[3][2];
+ m22 = -proj[2][2];
+
+ *nearZ = m32 / m22;
+ *farZ = m32 / (m22 + 1.0f);
+}
+
+/*!
+ * @brief decomposes far value of perspective projection
+ * with angle values with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] farZ far
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_far_lh_zo(mat4 proj, float * __restrict farZ) {
+ *farZ = proj[3][2] / (-proj[2][2] + 1.0f);
+}
+
+/*!
+ * @brief decomposes near value of perspective projection
+ * with angle values with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_near_lh_zo(mat4 proj, float * __restrict nearZ) {
+ *nearZ = proj[3][2] / -proj[2][2];
+}
+
+/*!
+ * @brief returns sizes of near and far planes of perspective projection
+ * with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[in] fovy fovy (see brief)
+ * @param[out] dest sizes order: [Wnear, Hnear, Wfar, Hfar]
+ */
+CGLM_INLINE
+void
+glm_persp_sizes_lh_zo(mat4 proj, float fovy, vec4 dest) {
+ float t, a, nearZ, farZ;
+
+ t = 2.0f * tanf(fovy * 0.5f);
+ a = glm_persp_aspect(proj);
+
+ glm_persp_decomp_z_lh_zo(proj, &nearZ, &farZ);
+
+ dest[1] = t * nearZ;
+ dest[3] = t * farZ;
+ dest[0] = a * dest[1];
+ dest[2] = a * dest[3];
+}
+
+/*!
+ * @brief returns field of view angle along the Y-axis (in radians)
+ * with a left-hand coordinate system and a clip-space of [0, 1].
+ *
+ * if you need to degrees, use glm_deg to convert it or use this:
+ * fovy_deg = glm_deg(glm_persp_fovy(projMatrix))
+ *
+ * @param[in] proj perspective projection matrix
+ */
+CGLM_INLINE
+float
+glm_persp_fovy_lh_zo(mat4 proj) {
+ return glm_persp_fovy(proj);
+}
+
+/*!
+ * @brief returns aspect ratio of perspective projection
+ * with a left-hand coordinate system and a clip-space of [0, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ */
+CGLM_INLINE
+float
+glm_persp_aspect_lh_zo(mat4 proj) {
+ return glm_persp_aspect(proj);
+}
+
+#endif /*cglm_persp_lh_zo_h*/
diff --git a/libs/cglm/include/cglm/clipspace/persp_rh_no.h b/libs/cglm/include/cglm/clipspace/persp_rh_no.h
new file mode 100644
index 0000000..021b7d8
--- /dev/null
+++ b/libs/cglm/include/cglm/clipspace/persp_rh_no.h
@@ -0,0 +1,395 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glm_frustum_rh_no(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest)
+ CGLM_INLINE void glm_perspective_rh_no(float fovy,
+ float aspect,
+ float nearZ,
+ float farZ,
+ mat4 dest)
+ CGLM_INLINE void glm_perspective_default_rh_no(float aspect, mat4 dest)
+ CGLM_INLINE void glm_perspective_resize_rh_no(float aspect, mat4 proj)
+ CGLM_INLINE void glm_persp_move_far_rh_no(mat4 proj,
+ float deltaFar)
+ CGLM_INLINE void glm_persp_decomp_rh_no(mat4 proj,
+ float * __restrict nearZ,
+ float * __restrict farZ,
+ float * __restrict top,
+ float * __restrict bottom,
+ float * __restrict left,
+ float * __restrict right)
+ CGLM_INLINE void glm_persp_decompv_rh_no(mat4 proj,
+ float dest[6])
+ CGLM_INLINE void glm_persp_decomp_x_rh_no(mat4 proj,
+ float * __restrict left,
+ float * __restrict right)
+ CGLM_INLINE void glm_persp_decomp_y_rh_no(mat4 proj,
+ float * __restrict top,
+ float * __restrict bottom)
+ CGLM_INLINE void glm_persp_decomp_z_rh_no(mat4 proj,
+ float * __restrict nearZ,
+ float * __restrict farZ)
+ CGLM_INLINE void glm_persp_decomp_far_rh_no(mat4 proj, float * __restrict farZ)
+ CGLM_INLINE void glm_persp_decomp_near_rh_no(mat4 proj, float * __restrict nearZ)
+ CGLM_INLINE void glm_persp_sizes_rh_no(mat4 proj, float fovy, vec4 dest)
+ */
+
+#ifndef cglm_persp_rh_no_h
+#define cglm_persp_rh_no_h
+
+#include "../common.h"
+#include "persp.h"
+
+/*!
+ * @brief set up perspective peprojection matrix
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] left viewport.left
+ * @param[in] right viewport.right
+ * @param[in] bottom viewport.bottom
+ * @param[in] top viewport.top
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping plane
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_frustum_rh_no(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest) {
+ float rl, tb, fn, nv;
+
+ glm_mat4_zero(dest);
+
+ rl = 1.0f / (right - left);
+ tb = 1.0f / (top - bottom);
+ fn =-1.0f / (farZ - nearZ);
+ nv = 2.0f * nearZ;
+
+ dest[0][0] = nv * rl;
+ dest[1][1] = nv * tb;
+ dest[2][0] = (right + left) * rl;
+ dest[2][1] = (top + bottom) * tb;
+ dest[2][2] = (farZ + nearZ) * fn;
+ dest[2][3] =-1.0f;
+ dest[3][2] = farZ * nv * fn;
+}
+
+/*!
+ * @brief set up perspective projection matrix
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] fovy field of view angle
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping planes
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_perspective_rh_no(float fovy,
+ float aspect,
+ float nearZ,
+ float farZ,
+ mat4 dest) {
+ float f, fn;
+
+ glm_mat4_zero(dest);
+
+ f = 1.0f / tanf(fovy * 0.5f);
+ fn = 1.0f / (nearZ - farZ);
+
+ dest[0][0] = f / aspect;
+ dest[1][1] = f;
+ dest[2][2] = (nearZ + farZ) * fn;
+ dest[2][3] =-1.0f;
+ dest[3][2] = 2.0f * nearZ * farZ * fn;
+
+}
+
+/*!
+ * @brief set up perspective projection matrix with default near/far
+ * and angle values with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_perspective_default_rh_no(float aspect, mat4 dest) {
+ glm_perspective_rh_no(GLM_PI_4f, aspect, 0.01f, 100.0f, dest);
+}
+
+/*!
+ * @brief resize perspective matrix by aspect ratio ( width / height )
+ * this makes very easy to resize proj matrix when window /viewport
+ * resized with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in, out] proj perspective projection matrix
+ */
+CGLM_INLINE
+void
+glm_perspective_resize_rh_no(float aspect, mat4 proj) {
+ if (proj[0][0] == 0.0f)
+ return;
+
+ proj[0][0] = proj[1][1] / aspect;
+}
+
+/*!
+ * @brief extend perspective projection matrix's far distance
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * this function does not guarantee far >= near, be aware of that!
+ *
+ * @param[in, out] proj projection matrix to extend
+ * @param[in] deltaFar distance from existing far (negative to shink)
+ */
+CGLM_INLINE
+void
+glm_persp_move_far_rh_no(mat4 proj, float deltaFar) {
+ float fn, farZ, nearZ, p22, p32;
+
+ p22 = proj[2][2];
+ p32 = proj[3][2];
+
+ nearZ = p32 / (p22 - 1.0f);
+ farZ = p32 / (p22 + 1.0f) + deltaFar;
+ fn = 1.0f / (nearZ - farZ);
+
+ proj[2][2] = (farZ + nearZ) * fn;
+ proj[3][2] = 2.0f * nearZ * farZ * fn;
+}
+
+/*!
+ * @brief decomposes frustum values of perspective projection
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ * @param[out] farZ far
+ * @param[out] top top
+ * @param[out] bottom bottom
+ * @param[out] left left
+ * @param[out] right right
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_rh_no(mat4 proj,
+ float * __restrict nearZ, float * __restrict farZ,
+ float * __restrict top, float * __restrict bottom,
+ float * __restrict left, float * __restrict right) {
+ float m00, m11, m20, m21, m22, m32, n, f;
+ float n_m11, n_m00;
+
+ m00 = proj[0][0];
+ m11 = proj[1][1];
+ m20 = proj[2][0];
+ m21 = proj[2][1];
+ m22 = proj[2][2];
+ m32 = proj[3][2];
+
+ n = m32 / (m22 - 1.0f);
+ f = m32 / (m22 + 1.0f);
+
+ n_m11 = n / m11;
+ n_m00 = n / m00;
+
+ *nearZ = n;
+ *farZ = f;
+ *bottom = n_m11 * (m21 - 1.0f);
+ *top = n_m11 * (m21 + 1.0f);
+ *left = n_m00 * (m20 - 1.0f);
+ *right = n_m00 * (m20 + 1.0f);
+}
+
+/*!
+ * @brief decomposes frustum values of perspective projection
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ * this makes easy to get all values at once
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] dest array
+ */
+CGLM_INLINE
+void
+glm_persp_decompv_rh_no(mat4 proj, float dest[6]) {
+ glm_persp_decomp_rh_no(proj, &dest[0], &dest[1], &dest[2],
+ &dest[3], &dest[4], &dest[5]);
+}
+
+/*!
+ * @brief decomposes left and right values of perspective projection
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ * x stands for x axis (left / right axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] left left
+ * @param[out] right right
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_x_rh_no(mat4 proj,
+ float * __restrict left,
+ float * __restrict right) {
+ float nearZ, m20, m00, m22;
+
+ m00 = proj[0][0];
+ m20 = proj[2][0];
+ m22 = proj[2][2];
+
+ nearZ = proj[3][2] / (m22 - 1.0f);
+ *left = nearZ * (m20 - 1.0f) / m00;
+ *right = nearZ * (m20 + 1.0f) / m00;
+}
+
+/*!
+ * @brief decomposes top and bottom values of perspective projection
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ * y stands for y axis (top / botom axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] top top
+ * @param[out] bottom bottom
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_y_rh_no(mat4 proj,
+ float * __restrict top,
+ float * __restrict bottom) {
+ float nearZ, m21, m11, m22;
+
+ m21 = proj[2][1];
+ m11 = proj[1][1];
+ m22 = proj[2][2];
+
+ nearZ = proj[3][2] / (m22 - 1.0f);
+ *bottom = nearZ * (m21 - 1.0f) / m11;
+ *top = nearZ * (m21 + 1.0f) / m11;
+}
+
+/*!
+ * @brief decomposes near and far values of perspective projection
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ * z stands for z axis (near / far axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ * @param[out] farZ far
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_z_rh_no(mat4 proj,
+ float * __restrict nearZ,
+ float * __restrict farZ) {
+ float m32, m22;
+
+ m32 = proj[3][2];
+ m22 = proj[2][2];
+
+ *nearZ = m32 / (m22 - 1.0f);
+ *farZ = m32 / (m22 + 1.0f);
+}
+
+/*!
+ * @brief decomposes far value of perspective projection
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] farZ far
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_far_rh_no(mat4 proj, float * __restrict farZ) {
+ *farZ = proj[3][2] / (proj[2][2] + 1.0f);
+}
+
+/*!
+ * @brief decomposes near value of perspective projection
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_near_rh_no(mat4 proj, float * __restrict nearZ) {
+ *nearZ = proj[3][2] / (proj[2][2] - 1.0f);
+}
+
+/*!
+ * @brief returns sizes of near and far planes of perspective projection
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[in] fovy fovy (see brief)
+ * @param[out] dest sizes order: [Wnear, Hnear, Wfar, Hfar]
+ */
+CGLM_INLINE
+void
+glm_persp_sizes_rh_no(mat4 proj, float fovy, vec4 dest) {
+ float t, a, nearZ, farZ;
+
+ t = 2.0f * tanf(fovy * 0.5f);
+ a = glm_persp_aspect(proj);
+
+ glm_persp_decomp_z_rh_no(proj, &nearZ, &farZ);
+
+ dest[1] = t * nearZ;
+ dest[3] = t * farZ;
+ dest[0] = a * dest[1];
+ dest[2] = a * dest[3];
+}
+
+/*!
+ * @brief returns field of view angle along the Y-axis (in radians)
+ * with a right-hand coordinate system and a clip-space of [-1, 1].
+ *
+ * if you need to degrees, use glm_deg to convert it or use this:
+ * fovy_deg = glm_deg(glm_persp_fovy(projMatrix))
+ *
+ * @param[in] proj perspective projection matrix
+ */
+CGLM_INLINE
+float
+glm_persp_fovy_rh_no(mat4 proj) {
+ return glm_persp_fovy(proj);
+}
+
+/*!
+ * @brief returns aspect ratio of perspective projection
+ * with a right-hand coordinate system and a clip-space of [-1, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ */
+CGLM_INLINE
+float
+glm_persp_aspect_rh_no(mat4 proj) {
+ return glm_persp_aspect(proj);
+}
+
+#endif /*cglm_cam_rh_no_h*/
diff --git a/libs/cglm/include/cglm/clipspace/persp_rh_zo.h b/libs/cglm/include/cglm/clipspace/persp_rh_zo.h
new file mode 100644
index 0000000..ce632b3
--- /dev/null
+++ b/libs/cglm/include/cglm/clipspace/persp_rh_zo.h
@@ -0,0 +1,389 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glm_frustum_rh_zo(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest)
+ CGLM_INLINE void glm_perspective_rh_zo(float fovy,
+ float aspect,
+ float nearZ,
+ float farZ,
+ mat4 dest)
+ CGLM_INLINE void glm_perspective_default_rh_zo(float aspect, mat4 dest)
+ CGLM_INLINE void glm_perspective_resize_rh_zo(float aspect, mat4 proj)
+ CGLM_INLINE void glm_persp_move_far_rh_zo(mat4 proj,
+ float deltaFar)
+ CGLM_INLINE void glm_persp_decomp_rh_zo(mat4 proj,
+ float * __restrict nearZ,
+ float * __restrict farZ,
+ float * __restrict top,
+ float * __restrict bottom,
+ float * __restrict left,
+ float * __restrict right)
+ CGLM_INLINE void glm_persp_decompv_rh_zo(mat4 proj,
+ float dest[6])
+ CGLM_INLINE void glm_persp_decomp_x_rh_zo(mat4 proj,
+ float * __restrict left,
+ float * __restrict right)
+ CGLM_INLINE void glm_persp_decomp_y_rh_zo(mat4 proj,
+ float * __restrict top,
+ float * __restrict bottom)
+ CGLM_INLINE void glm_persp_decomp_z_rh_zo(mat4 proj,
+ float * __restrict nearZ,
+ float * __restrict farZ)
+ CGLM_INLINE void glm_persp_decomp_far_rh_zo(mat4 proj, float * __restrict farZ)
+ CGLM_INLINE void glm_persp_decomp_near_rh_zo(mat4 proj, float * __restrict nearZ)
+ CGLM_INLINE void glm_persp_sizes_rh_zo(mat4 proj, float fovy, vec4 dest)
+ */
+
+#ifndef cglm_persp_rh_zo_h
+#define cglm_persp_rh_zo_h
+
+#include "../common.h"
+#include "persp.h"
+
+/*!
+ * @brief set up perspective peprojection matrix with a right-hand coordinate
+ * system and a clip-space of [0, 1].
+ *
+ * @param[in] left viewport.left
+ * @param[in] right viewport.right
+ * @param[in] bottom viewport.bottom
+ * @param[in] top viewport.top
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping plane
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_frustum_rh_zo(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ,
+ mat4 dest) {
+ float rl, tb, fn, nv;
+
+ glm_mat4_zero(dest);
+
+ rl = 1.0f / (right - left);
+ tb = 1.0f / (top - bottom);
+ fn =-1.0f / (farZ - nearZ);
+ nv = 2.0f * nearZ;
+
+ dest[0][0] = nv * rl;
+ dest[1][1] = nv * tb;
+ dest[2][0] = (right + left) * rl;
+ dest[2][1] = (top + bottom) * tb;
+ dest[2][2] = farZ * fn;
+ dest[2][3] =-1.0f;
+ dest[3][2] = farZ * nearZ * fn;
+}
+
+/*!
+ * @brief set up perspective projection matrix with a right-hand coordinate
+ * system and a clip-space of [0, 1].
+ *
+ * @param[in] fovy field of view angle
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping planes
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_perspective_rh_zo(float fovy,
+ float aspect,
+ float nearZ,
+ float farZ,
+ mat4 dest) {
+ float f, fn;
+
+ glm_mat4_zero(dest);
+
+ f = 1.0f / tanf(fovy * 0.5f);
+ fn = 1.0f / (nearZ - farZ);
+
+ dest[0][0] = f / aspect;
+ dest[1][1] = f;
+ dest[2][2] = farZ * fn;
+ dest[2][3] =-1.0f;
+ dest[3][2] = nearZ * farZ * fn;
+}
+
+/*!
+ * @brief set up perspective projection matrix with default near/far
+ * and angle values with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_perspective_default_rh_zo(float aspect, mat4 dest) {
+ glm_perspective_rh_zo(GLM_PI_4f, aspect, 0.01f, 100.0f, dest);
+}
+
+/*!
+ * @brief resize perspective matrix by aspect ratio ( width / height )
+ * this makes very easy to resize proj matrix when window /viewport
+ * resized with a right-hand coordinate system and a clip-space of
+ * [0, 1].
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in, out] proj perspective projection matrix
+ */
+CGLM_INLINE
+void
+glm_perspective_resize_rh_zo(float aspect, mat4 proj) {
+ if (proj[0][0] == 0.0f)
+ return;
+
+ proj[0][0] = proj[1][1] / aspect;
+}
+
+/*!
+ * @brief extend perspective projection matrix's far distance with a
+ * right-hand coordinate system and a clip-space of [0, 1].
+ *
+ * this function does not guarantee far >= near, be aware of that!
+ *
+ * @param[in, out] proj projection matrix to extend
+ * @param[in] deltaFar distance from existing far (negative to shink)
+ */
+CGLM_INLINE
+void
+glm_persp_move_far_rh_zo(mat4 proj, float deltaFar) {
+ float fn, farZ, nearZ, p22, p32;
+
+ p22 = proj[2][2];
+ p32 = proj[3][2];
+
+ nearZ = p32 / p22;
+ farZ = p32 / (p22 + 1.0f) + deltaFar;
+ fn = 1.0f / (nearZ - farZ);
+
+ proj[2][2] = farZ * fn;
+ proj[3][2] = nearZ * farZ * fn;
+}
+
+/*!
+ * @brief decomposes frustum values of perspective projection
+ * with angle values with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ * @param[out] farZ far
+ * @param[out] top top
+ * @param[out] bottom bottom
+ * @param[out] left left
+ * @param[out] right right
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_rh_zo(mat4 proj,
+ float * __restrict nearZ, float * __restrict farZ,
+ float * __restrict top, float * __restrict bottom,
+ float * __restrict left, float * __restrict right) {
+ float m00, m11, m20, m21, m22, m32, n, f;
+ float n_m11, n_m00;
+
+ m00 = proj[0][0];
+ m11 = proj[1][1];
+ m20 = proj[2][0];
+ m21 = proj[2][1];
+ m22 = proj[2][2];
+ m32 = proj[3][2];
+
+ n = m32 / m22;
+ f = m32 / (m22 + 1.0f);
+
+ n_m11 = n / m11;
+ n_m00 = n / m00;
+
+ *nearZ = n;
+ *farZ = f;
+ *bottom = n_m11 * (m21 - 1.0f);
+ *top = n_m11 * (m21 + 1.0f);
+ *left = n_m00 * (m20 - 1.0f);
+ *right = n_m00 * (m20 + 1.0f);
+}
+
+/*!
+ * @brief decomposes frustum values of perspective projection
+ * with angle values with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ * this makes easy to get all values at once
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] dest array
+ */
+CGLM_INLINE
+void
+glm_persp_decompv_rh_zo(mat4 proj, float dest[6]) {
+ glm_persp_decomp_rh_zo(proj, &dest[0], &dest[1], &dest[2],
+ &dest[3], &dest[4], &dest[5]);
+}
+
+/*!
+ * @brief decomposes left and right values of perspective projection (ZO).
+ * x stands for x axis (left / right axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] left left
+ * @param[out] right right
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_x_rh_zo(mat4 proj,
+ float * __restrict left,
+ float * __restrict right) {
+ float nearZ, m20, m00, m22;
+
+ m00 = proj[0][0];
+ m20 = proj[2][0];
+ m22 = proj[2][2];
+
+ nearZ = proj[3][2] / m22;
+ *left = nearZ * (m20 - 1.0f) / m00;
+ *right = nearZ * (m20 + 1.0f) / m00;
+}
+
+/*!
+ * @brief decomposes top and bottom values of perspective projection
+ * with angle values with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ * y stands for y axis (top / bottom axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] top top
+ * @param[out] bottom bottom
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_y_rh_zo(mat4 proj,
+ float * __restrict top,
+ float * __restrict bottom) {
+ float nearZ, m21, m11, m22;
+
+ m21 = proj[2][1];
+ m11 = proj[1][1];
+ m22 = proj[2][2];
+
+ nearZ = proj[3][2] / m22;
+ *bottom = nearZ * (m21 - 1) / m11;
+ *top = nearZ * (m21 + 1) / m11;
+}
+
+/*!
+ * @brief decomposes near and far values of perspective projection
+ * with angle values with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ * z stands for z axis (near / far axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ * @param[out] farZ far
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_z_rh_zo(mat4 proj,
+ float * __restrict nearZ,
+ float * __restrict farZ) {
+ float m32, m22;
+
+ m32 = proj[3][2];
+ m22 = proj[2][2];
+
+ *nearZ = m32 / m22;
+ *farZ = m32 / (m22 + 1.0f);
+}
+
+/*!
+ * @brief decomposes far value of perspective projection
+ * with angle values with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] farZ far
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_far_rh_zo(mat4 proj, float * __restrict farZ) {
+ *farZ = proj[3][2] / (proj[2][2] + 1.0f);
+}
+
+/*!
+ * @brief decomposes near value of perspective projection
+ * with angle values with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ */
+CGLM_INLINE
+void
+glm_persp_decomp_near_rh_zo(mat4 proj, float * __restrict nearZ) {
+ *nearZ = proj[3][2] / proj[2][2];
+}
+
+/*!
+ * @brief returns sizes of near and far planes of perspective projection
+ * with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[in] fovy fovy (see brief)
+ * @param[out] dest sizes order: [Wnear, Hnear, Wfar, Hfar]
+ */
+CGLM_INLINE
+void
+glm_persp_sizes_rh_zo(mat4 proj, float fovy, vec4 dest) {
+ float t, a, nearZ, farZ;
+
+ t = 2.0f * tanf(fovy * 0.5f);
+ a = glm_persp_aspect(proj);
+
+ glm_persp_decomp_z_rh_zo(proj, &nearZ, &farZ);
+
+ dest[1] = t * nearZ;
+ dest[3] = t * farZ;
+ dest[0] = a * dest[1];
+ dest[2] = a * dest[3];
+}
+
+/*!
+ * @brief returns field of view angle along the Y-axis (in radians)
+ * with a right-hand coordinate system and a clip-space of [0, 1].
+ *
+ * if you need to degrees, use glm_deg to convert it or use this:
+ * fovy_deg = glm_deg(glm_persp_fovy(projMatrix))
+ *
+ * @param[in] proj perspective projection matrix
+ */
+CGLM_INLINE
+float
+glm_persp_fovy_rh_zo(mat4 proj) {
+ return glm_persp_fovy(proj);
+}
+
+/*!
+ * @brief returns aspect ratio of perspective projection
+ * with a right-hand coordinate system and a clip-space of [0, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ */
+CGLM_INLINE
+float
+glm_persp_aspect_rh_zo(mat4 proj) {
+ return glm_persp_aspect(proj);
+}
+
+#endif /*cglm_persp_rh_zo_h*/
diff --git a/libs/cglm/include/cglm/clipspace/project_no.h b/libs/cglm/include/cglm/clipspace/project_no.h
new file mode 100644
index 0000000..7e74323
--- /dev/null
+++ b/libs/cglm/include/cglm/clipspace/project_no.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_project_no_h
+#define cglm_project_no_h
+
+#include "../common.h"
+#include "../vec3.h"
+#include "../vec4.h"
+#include "../mat4.h"
+
+/*!
+ * @brief maps the specified viewport coordinates into specified space [1]
+ * the matrix should contain projection matrix.
+ *
+ * if you don't have ( and don't want to have ) an inverse matrix then use
+ * glm_unproject version. You may use existing inverse of matrix in somewhere
+ * else, this is why glm_unprojecti exists to save save inversion cost
+ *
+ * [1] space:
+ * 1- if m = invProj: View Space
+ * 2- if m = invViewProj: World Space
+ * 3- if m = invMVP: Object Space
+ *
+ * You probably want to map the coordinates into object space
+ * so use invMVP as m
+ *
+ * Computing viewProj:
+ * glm_mat4_mul(proj, view, viewProj);
+ * glm_mat4_mul(viewProj, model, MVP);
+ * glm_mat4_inv(viewProj, invMVP);
+ *
+ * @param[in] pos point/position in viewport coordinates
+ * @param[in] invMat matrix (see brief)
+ * @param[in] vp viewport as [x, y, width, height]
+ * @param[out] dest unprojected coordinates
+ */
+CGLM_INLINE
+void
+glm_unprojecti_no(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 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_no(vec3 pos, mat4 m, vec4 vp, vec3 dest) {
+ CGLM_ALIGN(16) vec4 pos4;
+
+ 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_scale(pos4, 0.5f, pos4);
+ glm_vec4_adds(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_no_h */
diff --git a/libs/cglm/include/cglm/clipspace/project_zo.h b/libs/cglm/include/cglm/clipspace/project_zo.h
new file mode 100644
index 0000000..98e58af
--- /dev/null
+++ b/libs/cglm/include/cglm/clipspace/project_zo.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_project_zo_h
+#define cglm_project_zo_h
+
+#include "../common.h"
+#include "../vec3.h"
+#include "../vec4.h"
+#include "../mat4.h"
+
+/*!
+ * @brief maps the specified viewport coordinates into specified space [1]
+ * the matrix should contain projection matrix.
+ *
+ * if you don't have ( and don't want to have ) an inverse matrix then use
+ * glm_unproject version. You may use existing inverse of matrix in somewhere
+ * else, this is why glm_unprojecti exists to save save inversion cost
+ *
+ * [1] space:
+ * 1- if m = invProj: View Space
+ * 2- if m = invViewProj: World Space
+ * 3- if m = invMVP: Object Space
+ *
+ * You probably want to map the coordinates into object space
+ * so use invMVP as m
+ *
+ * Computing viewProj:
+ * glm_mat4_mul(proj, view, viewProj);
+ * glm_mat4_mul(viewProj, model, MVP);
+ * glm_mat4_inv(viewProj, invMVP);
+ *
+ * @param[in] pos point/position in viewport coordinates
+ * @param[in] invMat matrix (see brief)
+ * @param[in] vp viewport as [x, y, width, height]
+ * @param[out] dest unprojected coordinates
+ */
+CGLM_INLINE
+void
+glm_unprojecti_zo(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] = pos[2];
+ v[3] = 1.0f;
+
+ glm_mat4_mulv(invMat, v, v);
+ glm_vec4_scale(v, 1.0f / v[3], v);
+ glm_vec3(v, 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_zo(vec3 pos, mat4 m, vec4 vp, vec3 dest) {
+ CGLM_ALIGN(16) vec4 pos4;
+
+ 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 */
+
+ dest[2] = pos4[2];
+
+ glm_vec4_scale(pos4, 0.5f, pos4);
+ glm_vec4_adds(pos4, 0.5f, pos4);
+
+ dest[0] = pos4[0] * vp[2] + vp[0];
+ dest[1] = pos4[1] * vp[3] + vp[1];
+}
+
+#endif /* cglm_project_zo_h */
diff --git a/libs/cglm/include/cglm/clipspace/view_lh.h b/libs/cglm/include/cglm/clipspace/view_lh.h
new file mode 100644
index 0000000..5667694
--- /dev/null
+++ b/libs/cglm/include/cglm/clipspace/view_lh.h
@@ -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
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glm_lookat_lh(vec3 eye, vec3 center, vec3 up, mat4 dest)
+ CGLM_INLINE void glm_look_lh(vec3 eye, vec3 dir, vec3 up, mat4 dest)
+ CGLM_INLINE void glm_look_anyup_lh(vec3 eye, vec3 dir, mat4 dest)
+ */
+
+#ifndef cglm_view_lh_h
+#define cglm_view_lh_h
+
+#include "../common.h"
+#include "../plane.h"
+
+/*!
+ * @brief set up view matrix (LH)
+ *
+ * NOTE: The UP vector must not be parallel to the line of sight from
+ * the eye point to the reference point
+ *
+ * @param[in] eye eye vector
+ * @param[in] center center vector
+ * @param[in] up up vector
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_lookat_lh(vec3 eye, vec3 center, vec3 up, mat4 dest) {
+ CGLM_ALIGN(8) vec3 f, u, s;
+
+ glm_vec3_sub(center, eye, f);
+ glm_vec3_normalize(f);
+
+ glm_vec3_crossn(up, f, s);
+ glm_vec3_cross(f, s, u);
+
+ dest[0][0] = s[0];
+ dest[0][1] = u[0];
+ dest[0][2] = f[0];
+ dest[1][0] = s[1];
+ dest[1][1] = u[1];
+ dest[1][2] = f[1];
+ dest[2][0] = s[2];
+ dest[2][1] = u[2];
+ dest[2][2] = f[2];
+ dest[3][0] =-glm_vec3_dot(s, eye);
+ dest[3][1] =-glm_vec3_dot(u, eye);
+ dest[3][2] =-glm_vec3_dot(f, eye);
+ dest[0][3] = dest[1][3] = dest[2][3] = 0.0f;
+ dest[3][3] = 1.0f;
+}
+
+/*!
+ * @brief set up view matrix with left handed coordinate system
+ *
+ * convenient wrapper for lookat: if you only have direction not target self
+ * then this might be useful. Because you need to get target from direction.
+ *
+ * NOTE: The UP vector must not be parallel to the line of sight from
+ * the eye point to the reference point
+ *
+ * @param[in] eye eye vector
+ * @param[in] dir direction vector
+ * @param[in] up up vector
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_look_lh(vec3 eye, vec3 dir, vec3 up, mat4 dest) {
+ CGLM_ALIGN(8) vec3 target;
+ glm_vec3_add(eye, dir, target);
+ glm_lookat_lh(eye, target, up, dest);
+}
+
+/*!
+ * @brief set up view matrix with left handed coordinate system
+ *
+ * convenient wrapper for look: if you only have direction and if you don't
+ * care what UP vector is then this might be useful to create view matrix
+ *
+ * @param[in] eye eye vector
+ * @param[in] dir direction vector
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_look_anyup_lh(vec3 eye, vec3 dir, mat4 dest) {
+ CGLM_ALIGN(8) vec3 up;
+ glm_vec3_ortho(dir, up);
+ glm_look_lh(eye, dir, up, dest);
+}
+
+#endif /*cglm_view_lh_h*/
diff --git a/libs/cglm/include/cglm/clipspace/view_lh_no.h b/libs/cglm/include/cglm/clipspace/view_lh_no.h
new file mode 100644
index 0000000..454d903
--- /dev/null
+++ b/libs/cglm/include/cglm/clipspace/view_lh_no.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glm_lookat_lh_no(vec3 eye, vec3 center, vec3 up, mat4 dest)
+ CGLM_INLINE void glm_look_lh_no(vec3 eye, vec3 dir, vec3 up, mat4 dest)
+ CGLM_INLINE void glm_look_anyup_lh_no(vec3 eye, vec3 dir, mat4 dest)
+ */
+
+#ifndef cglm_view_lh_no_h
+#define cglm_view_lh_no_h
+
+#include "../common.h"
+#include "view_lh.h"
+
+/*!
+ * @brief set up view matrix with left handed coordinate system.
+ *
+ * NOTE: The UP vector must not be parallel to the line of sight from
+ * the eye point to the reference point
+ *
+ * @param[in] eye eye vector
+ * @param[in] center center vector
+ * @param[in] up up vector
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_lookat_lh_no(vec3 eye, vec3 center, vec3 up, mat4 dest) {
+ glm_lookat_lh(eye, center, up, dest);
+}
+
+/*!
+ * @brief set up view matrix with left handed coordinate system.
+ *
+ * convenient wrapper for lookat: if you only have direction not target self
+ * then this might be useful. Because you need to get target from direction.
+ *
+ * NOTE: The UP vector must not be parallel to the line of sight from
+ * the eye point to the reference point
+ *
+ * @param[in] eye eye vector
+ * @param[in] dir direction vector
+ * @param[in] up up vector
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_look_lh_no(vec3 eye, vec3 dir, vec3 up, mat4 dest) {
+ glm_look_lh(eye, dir, up, dest);
+}
+
+/*!
+ * @brief set up view matrix with left handed coordinate system.
+ *
+ * convenient wrapper for look: if you only have direction and if you don't
+ * care what UP vector is then this might be useful to create view matrix
+ *
+ * @param[in] eye eye vector
+ * @param[in] dir direction vector
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_look_anyup_lh_no(vec3 eye, vec3 dir, mat4 dest) {
+ glm_look_anyup_lh(eye, dir, dest);
+}
+
+#endif /*cglm_view_lh_no_h*/
diff --git a/libs/cglm/include/cglm/clipspace/view_lh_zo.h b/libs/cglm/include/cglm/clipspace/view_lh_zo.h
new file mode 100644
index 0000000..6b0c4d1
--- /dev/null
+++ b/libs/cglm/include/cglm/clipspace/view_lh_zo.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glm_lookat_lh_zo(vec3 eye, vec3 center, vec3 up, mat4 dest)
+ CGLM_INLINE void glm_look_lh_zo(vec3 eye, vec3 dir, vec3 up, mat4 dest)
+ CGLM_INLINE void glm_look_anyup_lh_zo(vec3 eye, vec3 dir, mat4 dest)
+ */
+
+#ifndef cglm_view_lh_zo_h
+#define cglm_view_lh_zo_h
+
+#include "../common.h"
+#include "view_lh.h"
+
+/*!
+ * @brief set up view matrix with left handed coordinate system.
+ *
+ * NOTE: The UP vector must not be parallel to the line of sight from
+ * the eye point to the reference point
+ *
+ * @param[in] eye eye vector
+ * @param[in] center center vector
+ * @param[in] up up vector
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_lookat_lh_zo(vec3 eye, vec3 center, vec3 up, mat4 dest) {
+ glm_lookat_lh(eye, center, up, dest);
+}
+
+/*!
+ * @brief set up view matrix with left handed coordinate system.
+ *
+ * convenient wrapper for lookat: if you only have direction not target self
+ * then this might be useful. Because you need to get target from direction.
+ *
+ * NOTE: The UP vector must not be parallel to the line of sight from
+ * the eye point to the reference point
+ *
+ * @param[in] eye eye vector
+ * @param[in] dir direction vector
+ * @param[in] up up vector
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_look_lh_zo(vec3 eye, vec3 dir, vec3 up, mat4 dest) {
+ glm_look_lh(eye, dir, up, dest);
+}
+
+/*!
+ * @brief set up view matrix with left handed coordinate system.
+ *
+ * convenient wrapper for look: if you only have direction and if you don't
+ * care what UP vector is then this might be useful to create view matrix
+ *
+ * @param[in] eye eye vector
+ * @param[in] dir direction vector
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_look_anyup_lh_zo(vec3 eye, vec3 dir, mat4 dest) {
+ glm_look_anyup_lh(eye, dir, dest);
+}
+
+#endif /*cglm_view_lh_zo_h*/
diff --git a/libs/cglm/include/cglm/clipspace/view_rh.h b/libs/cglm/include/cglm/clipspace/view_rh.h
new file mode 100644
index 0000000..51ec916
--- /dev/null
+++ b/libs/cglm/include/cglm/clipspace/view_rh.h
@@ -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
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glm_lookat_rh(vec3 eye, vec3 center, vec3 up, mat4 dest)
+ CGLM_INLINE void glm_look_rh(vec3 eye, vec3 dir, vec3 up, mat4 dest)
+ CGLM_INLINE void glm_look_anyup_rh(vec3 eye, vec3 dir, mat4 dest)
+ */
+
+#ifndef cglm_view_rh_h
+#define cglm_view_rh_h
+
+#include "../common.h"
+#include "../plane.h"
+
+/*!
+ * @brief set up view matrix with right handed coordinate system.
+ *
+ * NOTE: The UP vector must not be parallel to the line of sight from
+ * the eye point to the reference point
+ *
+ * @param[in] eye eye vector
+ * @param[in] center center vector
+ * @param[in] up up vector
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_lookat_rh(vec3 eye, vec3 center, vec3 up, mat4 dest) {
+ CGLM_ALIGN(8) vec3 f, u, s;
+
+ glm_vec3_sub(center, eye, f);
+ glm_vec3_normalize(f);
+
+ glm_vec3_crossn(f, up, s);
+ glm_vec3_cross(s, f, u);
+
+ dest[0][0] = s[0];
+ dest[0][1] = u[0];
+ dest[0][2] =-f[0];
+ dest[1][0] = s[1];
+ dest[1][1] = u[1];
+ dest[1][2] =-f[1];
+ dest[2][0] = s[2];
+ dest[2][1] = u[2];
+ dest[2][2] =-f[2];
+ dest[3][0] =-glm_vec3_dot(s, eye);
+ dest[3][1] =-glm_vec3_dot(u, eye);
+ dest[3][2] = glm_vec3_dot(f, eye);
+ dest[0][3] = dest[1][3] = dest[2][3] = 0.0f;
+ dest[3][3] = 1.0f;
+}
+
+/*!
+ * @brief set up view matrix with right handed coordinate system.
+ *
+ * convenient wrapper for lookat: if you only have direction not target self
+ * then this might be useful. Because you need to get target from direction.
+ *
+ * NOTE: The UP vector must not be parallel to the line of sight from
+ * the eye point to the reference point
+ *
+ * @param[in] eye eye vector
+ * @param[in] dir direction vector
+ * @param[in] up up vector
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_look_rh(vec3 eye, vec3 dir, vec3 up, mat4 dest) {
+ CGLM_ALIGN(8) vec3 target;
+ glm_vec3_add(eye, dir, target);
+ glm_lookat_rh(eye, target, up, dest);
+}
+
+/*!
+ * @brief set up view matrix with right handed coordinate system.
+ *
+ * convenient wrapper for look: if you only have direction and if you don't
+ * care what UP vector is then this might be useful to create view matrix
+ *
+ * @param[in] eye eye vector
+ * @param[in] dir direction vector
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_look_anyup_rh(vec3 eye, vec3 dir, mat4 dest) {
+ CGLM_ALIGN(8) vec3 up;
+ glm_vec3_ortho(dir, up);
+ glm_look_rh(eye, dir, up, dest);
+}
+
+#endif /*cglm_view_rh_h*/
diff --git a/libs/cglm/include/cglm/clipspace/view_rh_no.h b/libs/cglm/include/cglm/clipspace/view_rh_no.h
new file mode 100644
index 0000000..ca36d30
--- /dev/null
+++ b/libs/cglm/include/cglm/clipspace/view_rh_no.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glm_lookat_rh_no(vec3 eye, vec3 center, vec3 up, mat4 dest)
+ CGLM_INLINE void glm_look_rh_no(vec3 eye, vec3 dir, vec3 up, mat4 dest)
+ CGLM_INLINE void glm_look_anyup_rh_no(vec3 eye, vec3 dir, mat4 dest)
+ */
+
+#ifndef cglm_view_rh_no_h
+#define cglm_view_rh_no_h
+
+#include "../common.h"
+#include "view_rh.h"
+
+/*!
+ * @brief set up view matrix with right handed coordinate system.
+ *
+ * NOTE: The UP vector must not be parallel to the line of sight from
+ * the eye point to the reference point
+ *
+ * @param[in] eye eye vector
+ * @param[in] center center vector
+ * @param[in] up up vector
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_lookat_rh_no(vec3 eye, vec3 center, vec3 up, mat4 dest) {
+ glm_lookat_rh(eye, center, up, dest);
+}
+
+/*!
+ * @brief set up view matrix with right handed coordinate system.
+ *
+ * convenient wrapper for lookat: if you only have direction not target self
+ * then this might be useful. Because you need to get target from direction.
+ *
+ * NOTE: The UP vector must not be parallel to the line of sight from
+ * the eye point to the reference point
+ *
+ * @param[in] eye eye vector
+ * @param[in] dir direction vector
+ * @param[in] up up vector
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_look_rh_no(vec3 eye, vec3 dir, vec3 up, mat4 dest) {
+ glm_look_rh(eye, dir, up, dest);
+}
+
+/*!
+ * @brief set up view matrix with right handed coordinate system.
+ *
+ * convenient wrapper for look: if you only have direction and if you don't
+ * care what UP vector is then this might be useful to create view matrix
+ *
+ * @param[in] eye eye vector
+ * @param[in] dir direction vector
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_look_anyup_rh_no(vec3 eye, vec3 dir, mat4 dest) {
+ glm_look_anyup_rh(eye, dir, dest);
+}
+
+#endif /*cglm_view_rh_no_h*/
diff --git a/libs/cglm/include/cglm/clipspace/view_rh_zo.h b/libs/cglm/include/cglm/clipspace/view_rh_zo.h
new file mode 100644
index 0000000..1ad5c91
--- /dev/null
+++ b/libs/cglm/include/cglm/clipspace/view_rh_zo.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glm_lookat_rh_zo(vec3 eye, vec3 center, vec3 up, mat4 dest)
+ CGLM_INLINE void glm_look_rh_zo(vec3 eye, vec3 dir, vec3 up, mat4 dest)
+ CGLM_INLINE void glm_look_anyup_rh_zo(vec3 eye, vec3 dir, mat4 dest)
+ */
+
+#ifndef cglm_view_rh_zo_h
+#define cglm_view_rh_zo_h
+
+#include "../common.h"
+#include "view_rh.h"
+
+/*!
+ * @brief set up view matrix with right handed coordinate system.
+ *
+ * NOTE: The UP vector must not be parallel to the line of sight from
+ * the eye point to the reference point
+ *
+ * @param[in] eye eye vector
+ * @param[in] center center vector
+ * @param[in] up up vector
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_lookat_rh_zo(vec3 eye, vec3 center, vec3 up, mat4 dest) {
+ glm_lookat_rh(eye, center, up, dest);
+}
+
+/*!
+ * @brief set up view matrix with right handed coordinate system.
+ *
+ * convenient wrapper for lookat: if you only have direction not target self
+ * then this might be useful. Because you need to get target from direction.
+ *
+ * NOTE: The UP vector must not be parallel to the line of sight from
+ * the eye point to the reference point
+ *
+ * @param[in] eye eye vector
+ * @param[in] dir direction vector
+ * @param[in] up up vector
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_look_rh_zo(vec3 eye, vec3 dir, vec3 up, mat4 dest) {
+ glm_look_rh(eye, dir, up, dest);
+}
+
+/*!
+ * @brief set up view matrix with right handed coordinate system.
+ *
+ * convenient wrapper for look: if you only have direction and if you don't
+ * care what UP vector is then this might be useful to create view matrix
+ *
+ * @param[in] eye eye vector
+ * @param[in] dir direction vector
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_look_anyup_rh_zo(vec3 eye, vec3 dir, mat4 dest) {
+ glm_look_anyup_rh(eye, dir, dest);
+}
+
+#endif /*cglm_view_rh_zo_h*/
diff --git a/libs/cglm/include/cglm/color.h b/libs/cglm/include/cglm/color.h
new file mode 100644
index 0000000..69566ad
--- /dev/null
+++ b/libs/cglm/include/cglm/color.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_color_h
+#define cglm_color_h
+
+#include "common.h"
+#include "vec3.h"
+
+/*!
+ * @brief averages the color channels into one value
+ *
+ * @param[in] rgb RGB color
+ */
+CGLM_INLINE
+float
+glm_luminance(vec3 rgb) {
+ vec3 l = {0.212671f, 0.715160f, 0.072169f};
+ return glm_dot(rgb, l);
+}
+
+#endif /* cglm_color_h */
diff --git a/libs/cglm/include/cglm/common.h b/libs/cglm/include/cglm/common.h
new file mode 100644
index 0000000..261c9d7
--- /dev/null
+++ b/libs/cglm/include/cglm/common.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_common_h
+#define cglm_common_h
+
+#ifndef _USE_MATH_DEFINES
+# define _USE_MATH_DEFINES /* for windows */
+#endif
+
+#ifndef _CRT_SECURE_NO_WARNINGS
+# define _CRT_SECURE_NO_WARNINGS /* for windows */
+#endif
+
+#include <stdint.h>
+#include <stddef.h>
+#include <math.h>
+#include <float.h>
+#include <stdbool.h>
+
+#if defined(_MSC_VER)
+# ifdef CGLM_STATIC
+# define CGLM_EXPORT
+# elif defined(CGLM_EXPORTS)
+# define CGLM_EXPORT __declspec(dllexport)
+# else
+# define CGLM_EXPORT __declspec(dllimport)
+# endif
+# define CGLM_INLINE __forceinline
+#else
+# define CGLM_EXPORT __attribute__((visibility("default")))
+# define CGLM_INLINE static inline __attribute((always_inline))
+#endif
+
+#define GLM_SHUFFLE4(z, y, x, w) (((z) << 6) | ((y) << 4) | ((x) << 2) | (w))
+#define GLM_SHUFFLE3(z, y, x) (((z) << 4) | ((y) << 2) | (x))
+
+#include "types.h"
+#include "simd/intrin.h"
+
+#ifndef CGLM_USE_DEFAULT_EPSILON
+# ifndef GLM_FLT_EPSILON
+# define GLM_FLT_EPSILON 1e-5
+# endif
+#else
+# define GLM_FLT_EPSILON FLT_EPSILON
+#endif
+
+/*
+ * Clip control: define GLM_FORCE_DEPTH_ZERO_TO_ONE before including
+ * CGLM to use a clip space between 0 to 1.
+ * Coordinate system: define GLM_FORCE_LEFT_HANDED before including
+ * CGLM to use the left handed coordinate system by default.
+ */
+
+#define CGLM_CLIP_CONTROL_ZO_BIT (1 << 0) /* ZERO_TO_ONE */
+#define CGLM_CLIP_CONTROL_NO_BIT (1 << 1) /* NEGATIVE_ONE_TO_ONE */
+#define CGLM_CLIP_CONTROL_LH_BIT (1 << 2) /* LEFT_HANDED, For DirectX, Metal, Vulkan */
+#define CGLM_CLIP_CONTROL_RH_BIT (1 << 3) /* RIGHT_HANDED, For OpenGL, default in GLM */
+
+#define CGLM_CLIP_CONTROL_LH_ZO (CGLM_CLIP_CONTROL_LH_BIT | CGLM_CLIP_CONTROL_ZO_BIT)
+#define CGLM_CLIP_CONTROL_LH_NO (CGLM_CLIP_CONTROL_LH_BIT | CGLM_CLIP_CONTROL_NO_BIT)
+#define CGLM_CLIP_CONTROL_RH_ZO (CGLM_CLIP_CONTROL_RH_BIT | CGLM_CLIP_CONTROL_ZO_BIT)
+#define CGLM_CLIP_CONTROL_RH_NO (CGLM_CLIP_CONTROL_RH_BIT | CGLM_CLIP_CONTROL_NO_BIT)
+
+#ifdef CGLM_FORCE_DEPTH_ZERO_TO_ONE
+# ifdef CGLM_FORCE_LEFT_HANDED
+# define CGLM_CONFIG_CLIP_CONTROL CGLM_CLIP_CONTROL_LH_ZO
+# else
+# define CGLM_CONFIG_CLIP_CONTROL CGLM_CLIP_CONTROL_RH_ZO
+# endif
+#else
+# ifdef CGLM_FORCE_LEFT_HANDED
+# define CGLM_CONFIG_CLIP_CONTROL CGLM_CLIP_CONTROL_LH_NO
+# else
+# define CGLM_CONFIG_CLIP_CONTROL CGLM_CLIP_CONTROL_RH_NO
+# endif
+#endif
+
+#endif /* cglm_common_h */
diff --git a/libs/cglm/include/cglm/curve.h b/libs/cglm/include/cglm/curve.h
new file mode 100644
index 0000000..5033be5
--- /dev/null
+++ b/libs/cglm/include/cglm/curve.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_curve_h
+#define cglm_curve_h
+
+#include "common.h"
+#include "vec4.h"
+#include "mat4.h"
+
+/*!
+ * @brief helper function to calculate S*M*C multiplication for curves
+ *
+ * This function does not encourage you to use SMC,
+ * instead it is a helper if you use SMC.
+ *
+ * if you want to specify S as vector then use more generic glm_mat4_rmc() func.
+ *
+ * Example usage:
+ * B(s) = glm_smc(s, GLM_BEZIER_MAT, (vec4){p0, c0, c1, p1})
+ *
+ * @param[in] s parameter between 0 and 1 (this will be [s3, s2, s, 1])
+ * @param[in] m basis matrix
+ * @param[in] c position/control vector
+ *
+ * @return B(s)
+ */
+CGLM_INLINE
+float
+glm_smc(float s, mat4 m, vec4 c) {
+ vec4 vs;
+ glm_vec4_cubic(s, vs);
+ return glm_mat4_rmc(vs, m, c);
+}
+
+#endif /* cglm_curve_h */
diff --git a/libs/cglm/include/cglm/ease.h b/libs/cglm/include/cglm/ease.h
new file mode 100644
index 0000000..b40b75e
--- /dev/null
+++ b/libs/cglm/include/cglm/ease.h
@@ -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 */
diff --git a/libs/cglm/include/cglm/euler.h b/libs/cglm/include/cglm/euler.h
new file mode 100644
index 0000000..725a205
--- /dev/null
+++ b/libs/cglm/include/cglm/euler.h
@@ -0,0 +1,451 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ NOTE:
+ angles must be passed as [X-Angle, Y-Angle, Z-angle] order
+ For instance you don't pass angles as [Z-Angle, X-Angle, Y-angle] to
+ glm_euler_zxy funciton, All RELATED functions accept angles same order
+ which is [X, Y, Z].
+ */
+
+/*
+ Types:
+ enum glm_euler_seq
+
+ Functions:
+ CGLM_INLINE glm_euler_seq glm_euler_order(int newOrder[3]);
+ CGLM_INLINE void glm_euler_angles(mat4 m, vec3 dest);
+ CGLM_INLINE void glm_euler(vec3 angles, mat4 dest);
+ CGLM_INLINE void glm_euler_xyz(vec3 angles, mat4 dest);
+ CGLM_INLINE void glm_euler_zyx(vec3 angles, mat4 dest);
+ CGLM_INLINE void glm_euler_zxy(vec3 angles, mat4 dest);
+ CGLM_INLINE void glm_euler_xzy(vec3 angles, mat4 dest);
+ CGLM_INLINE void glm_euler_yzx(vec3 angles, mat4 dest);
+ CGLM_INLINE void glm_euler_yxz(vec3 angles, mat4 dest);
+ CGLM_INLINE void glm_euler_by_order(vec3 angles,
+ glm_euler_seq ord,
+ mat4 dest);
+ */
+
+#ifndef cglm_euler_h
+#define cglm_euler_h
+
+#include "common.h"
+
+/*!
+ * if you have axis order like vec3 orderVec = [0, 1, 2] or [0, 2, 1]...
+ * vector then you can convert it to this enum by doing this:
+ * @code
+ * glm_euler_seq order;
+ * order = orderVec[0] | orderVec[1] << 2 | orderVec[2] << 4;
+ * @endcode
+ * you may need to explicit cast if required
+ */
+typedef enum glm_euler_seq {
+ GLM_EULER_XYZ = 0 << 0 | 1 << 2 | 2 << 4,
+ GLM_EULER_XZY = 0 << 0 | 2 << 2 | 1 << 4,
+ GLM_EULER_YZX = 1 << 0 | 2 << 2 | 0 << 4,
+ GLM_EULER_YXZ = 1 << 0 | 0 << 2 | 2 << 4,
+ GLM_EULER_ZXY = 2 << 0 | 0 << 2 | 1 << 4,
+ GLM_EULER_ZYX = 2 << 0 | 1 << 2 | 0 << 4
+} glm_euler_seq;
+
+CGLM_INLINE
+glm_euler_seq
+glm_euler_order(int ord[3]) {
+ return (glm_euler_seq)(ord[0] << 0 | ord[1] << 2 | ord[2] << 4);
+}
+
+/*!
+ * @brief extract euler angles (in radians) using xyz order
+ *
+ * @param[in] m affine transform
+ * @param[out] dest angles vector [x, y, z]
+ */
+CGLM_INLINE
+void
+glm_euler_angles(mat4 m, vec3 dest) {
+ float m00, m01, m10, m11, m20, m21, m22;
+ float thetaX, thetaY, thetaZ;
+
+ m00 = m[0][0]; m10 = m[1][0]; m20 = m[2][0];
+ m01 = m[0][1]; m11 = m[1][1]; m21 = m[2][1];
+ m22 = m[2][2];
+
+ if (m20 < 1.0f) {
+ if (m20 > -1.0f) {
+ thetaY = asinf(m20);
+ thetaX = atan2f(-m21, m22);
+ thetaZ = atan2f(-m10, m00);
+ } else { /* m20 == -1 */
+ /* Not a unique solution */
+ thetaY = -GLM_PI_2f;
+ thetaX = -atan2f(m01, m11);
+ thetaZ = 0.0f;
+ }
+ } else { /* m20 == +1 */
+ thetaY = GLM_PI_2f;
+ thetaX = atan2f(m01, m11);
+ thetaZ = 0.0f;
+ }
+
+ dest[0] = thetaX;
+ dest[1] = thetaY;
+ dest[2] = thetaZ;
+}
+
+/*!
+ * @brief build rotation matrix from euler angles
+ *
+ * @param[in] angles angles as vector [Xangle, Yangle, Zangle]
+ * @param[out] dest rotation matrix
+ */
+CGLM_INLINE
+void
+glm_euler_xyz(vec3 angles, mat4 dest) {
+ float cx, cy, cz,
+ sx, sy, sz, czsx, cxcz, sysz;
+
+ sx = sinf(angles[0]); cx = cosf(angles[0]);
+ sy = sinf(angles[1]); cy = cosf(angles[1]);
+ sz = sinf(angles[2]); cz = cosf(angles[2]);
+
+ czsx = cz * sx;
+ cxcz = cx * cz;
+ sysz = sy * sz;
+
+ dest[0][0] = cy * cz;
+ dest[0][1] = czsx * sy + cx * sz;
+ dest[0][2] = -cxcz * sy + sx * sz;
+ dest[1][0] = -cy * sz;
+ dest[1][1] = cxcz - sx * sysz;
+ dest[1][2] = czsx + cx * sysz;
+ dest[2][0] = sy;
+ dest[2][1] = -cy * sx;
+ dest[2][2] = cx * cy;
+ dest[0][3] = 0.0f;
+ dest[1][3] = 0.0f;
+ dest[2][3] = 0.0f;
+ dest[3][0] = 0.0f;
+ dest[3][1] = 0.0f;
+ dest[3][2] = 0.0f;
+ dest[3][3] = 1.0f;
+}
+
+/*!
+ * @brief build rotation matrix from euler angles
+ *
+ * @param[in] angles angles as vector [Xangle, Yangle, Zangle]
+ * @param[out] dest rotation matrix
+ */
+CGLM_INLINE
+void
+glm_euler(vec3 angles, mat4 dest) {
+ glm_euler_xyz(angles, dest);
+}
+
+/*!
+ * @brief build rotation matrix from euler angles
+ *
+ * @param[in] angles angles as vector [Xangle, Yangle, Zangle]
+ * @param[out] dest rotation matrix
+ */
+CGLM_INLINE
+void
+glm_euler_xzy(vec3 angles, mat4 dest) {
+ float cx, cy, cz,
+ sx, sy, sz, sxsy, cysx, cxsy, cxcy;
+
+ sx = sinf(angles[0]); cx = cosf(angles[0]);
+ sy = sinf(angles[1]); cy = cosf(angles[1]);
+ sz = sinf(angles[2]); cz = cosf(angles[2]);
+
+ sxsy = sx * sy;
+ cysx = cy * sx;
+ cxsy = cx * sy;
+ cxcy = cx * cy;
+
+ dest[0][0] = cy * cz;
+ dest[0][1] = sxsy + cxcy * sz;
+ dest[0][2] = -cxsy + cysx * sz;
+ dest[1][0] = -sz;
+ dest[1][1] = cx * cz;
+ dest[1][2] = cz * sx;
+ dest[2][0] = cz * sy;
+ dest[2][1] = -cysx + cxsy * sz;
+ dest[2][2] = cxcy + sxsy * sz;
+ dest[0][3] = 0.0f;
+ dest[1][3] = 0.0f;
+ dest[2][3] = 0.0f;
+ dest[3][0] = 0.0f;
+ dest[3][1] = 0.0f;
+ dest[3][2] = 0.0f;
+ dest[3][3] = 1.0f;
+}
+
+
+/*!
+ * @brief build rotation matrix from euler angles
+ *
+ * @param[in] angles angles as vector [Xangle, Yangle, Zangle]
+ * @param[out] dest rotation matrix
+ */
+CGLM_INLINE
+void
+glm_euler_yxz(vec3 angles, mat4 dest) {
+ float cx, cy, cz,
+ sx, sy, sz, cycz, sysz, czsy, cysz;
+
+ sx = sinf(angles[0]); cx = cosf(angles[0]);
+ sy = sinf(angles[1]); cy = cosf(angles[1]);
+ sz = sinf(angles[2]); cz = cosf(angles[2]);
+
+ cycz = cy * cz;
+ sysz = sy * sz;
+ czsy = cz * sy;
+ cysz = cy * sz;
+
+ dest[0][0] = cycz + sx * sysz;
+ dest[0][1] = cx * sz;
+ dest[0][2] = -czsy + cysz * sx;
+ dest[1][0] = -cysz + czsy * sx;
+ dest[1][1] = cx * cz;
+ dest[1][2] = cycz * sx + sysz;
+ dest[2][0] = cx * sy;
+ dest[2][1] = -sx;
+ dest[2][2] = cx * cy;
+ dest[0][3] = 0.0f;
+ dest[1][3] = 0.0f;
+ dest[2][3] = 0.0f;
+ dest[3][0] = 0.0f;
+ dest[3][1] = 0.0f;
+ dest[3][2] = 0.0f;
+ dest[3][3] = 1.0f;
+}
+
+/*!
+ * @brief build rotation matrix from euler angles
+ *
+ * @param[in] angles angles as vector [Xangle, Yangle, Zangle]
+ * @param[out] dest rotation matrix
+ */
+CGLM_INLINE
+void
+glm_euler_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[out] dest rotation matrix
+ */
+CGLM_INLINE
+void
+glm_euler_by_order(vec3 angles, glm_euler_seq ord, mat4 dest) {
+ float cx, cy, cz,
+ sx, sy, sz;
+
+ float cycz, cysz, cysx, cxcy,
+ czsy, cxcz, czsx, cxsz,
+ 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]);
+
+ cycz = cy * cz; cysz = cy * sz;
+ cysx = cy * sx; cxcy = cx * cy;
+ czsy = cz * sy; cxcz = cx * cz;
+ czsx = cz * sx; cxsz = cx * sz;
+ sysz = sy * sz;
+
+ switch (ord) {
+ case GLM_EULER_XZY:
+ dest[0][0] = cycz;
+ dest[0][1] = sx * sy + cx * cysz;
+ dest[0][2] = -cx * sy + cysx * sz;
+ dest[1][0] = -sz;
+ dest[1][1] = cxcz;
+ dest[1][2] = czsx;
+ dest[2][0] = czsy;
+ dest[2][1] = -cysx + cx * sysz;
+ dest[2][2] = cxcy + sx * sysz;
+ break;
+ case GLM_EULER_XYZ:
+ dest[0][0] = cycz;
+ dest[0][1] = czsx * sy + cxsz;
+ dest[0][2] = -cx * czsy + sx * sz;
+ dest[1][0] = -cysz;
+ dest[1][1] = cxcz - sx * sysz;
+ dest[1][2] = czsx + cx * sysz;
+ dest[2][0] = sy;
+ dest[2][1] = -cysx;
+ dest[2][2] = cxcy;
+ break;
+ case GLM_EULER_YXZ:
+ dest[0][0] = cycz + sx * sysz;
+ dest[0][1] = cxsz;
+ dest[0][2] = -czsy + cysx * sz;
+ dest[1][0] = czsx * sy - cysz;
+ dest[1][1] = cxcz;
+ dest[1][2] = cycz * sx + sysz;
+ dest[2][0] = cx * sy;
+ dest[2][1] = -sx;
+ dest[2][2] = cxcy;
+ break;
+ case GLM_EULER_YZX:
+ dest[0][0] = cycz;
+ dest[0][1] = sz;
+ dest[0][2] = -czsy;
+ dest[1][0] = sx * sy - cx * cysz;
+ dest[1][1] = cxcz;
+ dest[1][2] = cysx + cx * sysz;
+ dest[2][0] = cx * sy + cysx * sz;
+ dest[2][1] = -czsx;
+ dest[2][2] = cxcy - sx * sysz;
+ break;
+ case GLM_EULER_ZXY:
+ dest[0][0] = cycz - sx * sysz;
+ dest[0][1] = czsx * sy + cysz;
+ dest[0][2] = -cx * sy;
+ dest[1][0] = -cxsz;
+ dest[1][1] = cxcz;
+ dest[1][2] = sx;
+ dest[2][0] = czsy + cysx * sz;
+ dest[2][1] = -cycz * sx + sysz;
+ dest[2][2] = cxcy;
+ break;
+ case GLM_EULER_ZYX:
+ dest[0][0] = cycz;
+ dest[0][1] = cysz;
+ dest[0][2] = -sy;
+ dest[1][0] = czsx * sy - cxsz;
+ dest[1][1] = cxcz + sx * sysz;
+ dest[1][2] = cysx;
+ dest[2][0] = cx * czsy + sx * sz;
+ dest[2][1] = -czsx + cx * sysz;
+ dest[2][2] = cxcy;
+ break;
+ }
+
+ 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;
+}
+
+#endif /* cglm_euler_h */
diff --git a/libs/cglm/include/cglm/frustum.h b/libs/cglm/include/cglm/frustum.h
new file mode 100644
index 0000000..5aa3c17
--- /dev/null
+++ b/libs/cglm/include/cglm/frustum.h
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_frustum_h
+#define cglm_frustum_h
+
+#include "common.h"
+#include "plane.h"
+#include "vec3.h"
+#include "vec4.h"
+#include "mat4.h"
+
+#define GLM_LBN 0 /* left bottom near */
+#define GLM_LTN 1 /* left top near */
+#define GLM_RTN 2 /* right top near */
+#define GLM_RBN 3 /* right bottom near */
+
+#define GLM_LBF 4 /* left bottom far */
+#define GLM_LTF 5 /* left top far */
+#define GLM_RTF 6 /* right top far */
+#define GLM_RBF 7 /* right bottom far */
+
+#define GLM_LEFT 0
+#define GLM_RIGHT 1
+#define GLM_BOTTOM 2
+#define GLM_TOP 3
+#define GLM_NEAR 4
+#define GLM_FAR 5
+
+/* you can override clip space coords
+ but you have to provide all with same name
+ e.g.: define GLM_CSCOORD_LBN {0.0f, 0.0f, 1.0f, 1.0f} */
+#ifndef GLM_CUSTOM_CLIPSPACE
+
+/* near */
+#define GLM_CSCOORD_LBN {-1.0f, -1.0f, -1.0f, 1.0f}
+#define GLM_CSCOORD_LTN {-1.0f, 1.0f, -1.0f, 1.0f}
+#define GLM_CSCOORD_RTN { 1.0f, 1.0f, -1.0f, 1.0f}
+#define GLM_CSCOORD_RBN { 1.0f, -1.0f, -1.0f, 1.0f}
+
+/* far */
+#define GLM_CSCOORD_LBF {-1.0f, -1.0f, 1.0f, 1.0f}
+#define GLM_CSCOORD_LTF {-1.0f, 1.0f, 1.0f, 1.0f}
+#define GLM_CSCOORD_RTF { 1.0f, 1.0f, 1.0f, 1.0f}
+#define GLM_CSCOORD_RBF { 1.0f, -1.0f, 1.0f, 1.0f}
+
+#endif
+
+/*!
+ * @brief extracts view frustum planes
+ *
+ * planes' space:
+ * 1- if m = proj: View Space
+ * 2- if m = viewProj: World Space
+ * 3- if m = MVP: Object Space
+ *
+ * You probably want to extract planes in world space so use viewProj as m
+ * Computing viewProj:
+ * glm_mat4_mul(proj, view, viewProj);
+ *
+ * Exracted planes order: [left, right, bottom, top, near, far]
+ *
+ * @param[in] m matrix (see brief)
+ * @param[out] dest extracted view frustum planes (see brief)
+ */
+CGLM_INLINE
+void
+glm_frustum_planes(mat4 m, vec4 dest[6]) {
+ mat4 t;
+
+ glm_mat4_transpose_to(m, t);
+
+ glm_vec4_add(t[3], t[0], dest[0]); /* left */
+ glm_vec4_sub(t[3], t[0], dest[1]); /* right */
+ glm_vec4_add(t[3], t[1], dest[2]); /* bottom */
+ glm_vec4_sub(t[3], t[1], dest[3]); /* top */
+ glm_vec4_add(t[3], t[2], dest[4]); /* near */
+ glm_vec4_sub(t[3], t[2], dest[5]); /* far */
+
+ glm_plane_normalize(dest[0]);
+ glm_plane_normalize(dest[1]);
+ glm_plane_normalize(dest[2]);
+ glm_plane_normalize(dest[3]);
+ glm_plane_normalize(dest[4]);
+ glm_plane_normalize(dest[5]);
+}
+
+/*!
+ * @brief extracts view frustum corners using clip-space coordinates
+ *
+ * corners' space:
+ * 1- if m = invViewProj: World Space
+ * 2- if m = invMVP: Object Space
+ *
+ * You probably want to extract corners in world space so use invViewProj
+ * Computing invViewProj:
+ * glm_mat4_mul(proj, view, viewProj);
+ * ...
+ * glm_mat4_inv(viewProj, invViewProj);
+ *
+ * if you have a near coord at i index, you can get it's far coord by i + 4
+ *
+ * Find center coordinates:
+ * for (j = 0; j < 4; j++) {
+ * glm_vec3_center(corners[i], corners[i + 4], centerCorners[i]);
+ * }
+ *
+ * @param[in] invMat matrix (see brief)
+ * @param[out] dest exracted view frustum corners (see brief)
+ */
+CGLM_INLINE
+void
+glm_frustum_corners(mat4 invMat, vec4 dest[8]) {
+ vec4 c[8];
+
+ /* indexOf(nearCoord) = indexOf(farCoord) + 4 */
+ vec4 csCoords[8] = {
+ GLM_CSCOORD_LBN,
+ GLM_CSCOORD_LTN,
+ GLM_CSCOORD_RTN,
+ GLM_CSCOORD_RBN,
+
+ GLM_CSCOORD_LBF,
+ GLM_CSCOORD_LTF,
+ GLM_CSCOORD_RTF,
+ GLM_CSCOORD_RBF
+ };
+
+ glm_mat4_mulv(invMat, csCoords[0], c[0]);
+ glm_mat4_mulv(invMat, csCoords[1], c[1]);
+ glm_mat4_mulv(invMat, csCoords[2], c[2]);
+ glm_mat4_mulv(invMat, csCoords[3], c[3]);
+ glm_mat4_mulv(invMat, csCoords[4], c[4]);
+ glm_mat4_mulv(invMat, csCoords[5], c[5]);
+ glm_mat4_mulv(invMat, csCoords[6], c[6]);
+ glm_mat4_mulv(invMat, csCoords[7], c[7]);
+
+ glm_vec4_scale(c[0], 1.0f / c[0][3], dest[0]);
+ glm_vec4_scale(c[1], 1.0f / c[1][3], dest[1]);
+ glm_vec4_scale(c[2], 1.0f / c[2][3], dest[2]);
+ glm_vec4_scale(c[3], 1.0f / c[3][3], dest[3]);
+ glm_vec4_scale(c[4], 1.0f / c[4][3], dest[4]);
+ glm_vec4_scale(c[5], 1.0f / c[5][3], dest[5]);
+ glm_vec4_scale(c[6], 1.0f / c[6][3], dest[6]);
+ glm_vec4_scale(c[7], 1.0f / c[7][3], dest[7]);
+}
+
+/*!
+ * @brief finds center of view frustum
+ *
+ * @param[in] corners view frustum corners
+ * @param[out] dest view frustum center
+ */
+CGLM_INLINE
+void
+glm_frustum_center(vec4 corners[8], vec4 dest) {
+ vec4 center;
+
+ glm_vec4_copy(corners[0], center);
+
+ glm_vec4_add(corners[1], center, center);
+ glm_vec4_add(corners[2], center, center);
+ glm_vec4_add(corners[3], center, center);
+ glm_vec4_add(corners[4], center, center);
+ glm_vec4_add(corners[5], center, center);
+ glm_vec4_add(corners[6], center, center);
+ glm_vec4_add(corners[7], center, center);
+
+ glm_vec4_scale(center, 0.125f, dest);
+}
+
+/*!
+ * @brief finds bounding box of frustum relative to given matrix e.g. view mat
+ *
+ * @param[in] corners view frustum corners
+ * @param[in] m matrix to convert existing conners
+ * @param[out] box bounding box as array [min, max]
+ */
+CGLM_INLINE
+void
+glm_frustum_box(vec4 corners[8], mat4 m, vec3 box[2]) {
+ vec4 v;
+ vec3 min, max;
+ int i;
+
+ glm_vec3_broadcast(FLT_MAX, min);
+ glm_vec3_broadcast(-FLT_MAX, max);
+
+ for (i = 0; i < 8; i++) {
+ glm_mat4_mulv(m, corners[i], v);
+
+ min[0] = glm_min(min[0], v[0]);
+ min[1] = glm_min(min[1], v[1]);
+ min[2] = glm_min(min[2], v[2]);
+
+ max[0] = glm_max(max[0], v[0]);
+ max[1] = glm_max(max[1], v[1]);
+ max[2] = glm_max(max[2], v[2]);
+ }
+
+ glm_vec3_copy(min, box[0]);
+ glm_vec3_copy(max, box[1]);
+}
+
+/*!
+ * @brief finds planes corners which is between near and far planes (parallel)
+ *
+ * this will be helpful if you want to split a frustum e.g. CSM/PSSM. This will
+ * find planes' corners but you will need to one more plane.
+ * Actually you have it, it is near, far or created previously with this func ;)
+ *
+ * @param[in] corners view frustum corners
+ * @param[in] splitDist split distance
+ * @param[in] farDist far distance (zFar)
+ * @param[out] planeCorners plane corners [LB, LT, RT, RB]
+ */
+CGLM_INLINE
+void
+glm_frustum_corners_at(vec4 corners[8],
+ float splitDist,
+ float farDist,
+ vec4 planeCorners[4]) {
+ vec4 corner;
+ float dist, sc;
+
+ /* because distance and scale is same for all */
+ dist = glm_vec3_distance(corners[GLM_RTF], corners[GLM_RTN]);
+ sc = dist * (splitDist / farDist);
+
+ /* left bottom */
+ glm_vec4_sub(corners[GLM_LBF], corners[GLM_LBN], corner);
+ glm_vec4_scale_as(corner, sc, corner);
+ glm_vec4_add(corners[GLM_LBN], corner, planeCorners[0]);
+
+ /* left top */
+ glm_vec4_sub(corners[GLM_LTF], corners[GLM_LTN], corner);
+ glm_vec4_scale_as(corner, sc, corner);
+ glm_vec4_add(corners[GLM_LTN], corner, planeCorners[1]);
+
+ /* right top */
+ glm_vec4_sub(corners[GLM_RTF], corners[GLM_RTN], corner);
+ glm_vec4_scale_as(corner, sc, corner);
+ glm_vec4_add(corners[GLM_RTN], corner, planeCorners[2]);
+
+ /* right bottom */
+ glm_vec4_sub(corners[GLM_RBF], corners[GLM_RBN], corner);
+ glm_vec4_scale_as(corner, sc, corner);
+ glm_vec4_add(corners[GLM_RBN], corner, planeCorners[3]);
+}
+
+#endif /* cglm_frustum_h */
diff --git a/libs/cglm/include/cglm/io.h b/libs/cglm/include/cglm/io.h
new file mode 100644
index 0000000..f625791
--- /dev/null
+++ b/libs/cglm/include/cglm/io.h
@@ -0,0 +1,344 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glm_mat4_print(mat4 matrix, FILE *ostream);
+ CGLM_INLINE void glm_mat3_print(mat3 matrix, FILE *ostream);
+ CGLM_INLINE void glm_vec4_print(vec4 vec, FILE *ostream);
+ CGLM_INLINE void glm_vec3_print(vec3 vec, FILE *ostream);
+ CGLM_INLINE void glm_ivec3_print(ivec3 vec, FILE *ostream);
+ CGLM_INLINE void glm_versor_print(versor vec, FILE *ostream);
+ */
+
+/*
+ cglm tried to enable print functions in debug mode and disable them in
+ release/production mode to eliminate printing costs.
+
+ if you need to force enable then define CGLM_DEFINE_PRINTS macro not DEBUG one
+
+ Print functions are enabled if:
+
+ - DEBUG or _DEBUG macro is defined (mostly defined automatically in debugging)
+ - CGLM_DEFINE_PRINTS macro is defined including release/production
+ which makes enabled printing always
+ - glmc_ calls for io are always prints
+
+ */
+
+/* DEPRECATED: CGLM_NO_PRINTS_NOOP (use CGLM_DEFINE_PRINTS) */
+
+#ifndef cglm_io_h
+#define cglm_io_h
+#if defined(DEBUG) || defined(_DEBUG) \
+ || defined(CGLM_DEFINE_PRINTS) || defined(CGLM_LIB_SRC) \
+ || defined(CGLM_NO_PRINTS_NOOP)
+
+#include "common.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef CGLM_PRINT_PRECISION
+# define CGLM_PRINT_PRECISION 5
+#endif
+
+#ifndef CGLM_PRINT_MAX_TO_SHORT
+# define CGLM_PRINT_MAX_TO_SHORT 1e5
+#endif
+
+#ifndef CGLM_PRINT_COLOR
+# define CGLM_PRINT_COLOR "\033[36m"
+#endif
+
+#ifndef CGLM_PRINT_COLOR_RESET
+# define CGLM_PRINT_COLOR_RESET "\033[0m"
+#endif
+
+CGLM_INLINE
+void
+glm_mat4_print(mat4 matrix,
+ FILE * __restrict ostream) {
+ char buff[16];
+ int i, j, cw[4], cwi;
+
+#define m 4
+#define n 4
+
+ fprintf(ostream, "Matrix (float%dx%d): " CGLM_PRINT_COLOR "\n" , m, n);
+
+ cw[0] = cw[1] = cw[2] = cw[3] = 0;
+
+ for (i = 0; i < m; i++) {
+ for (j = 0; j < n; j++) {
+ if (matrix[i][j] < CGLM_PRINT_MAX_TO_SHORT)
+ cwi = sprintf(buff, "% .*f", CGLM_PRINT_PRECISION, matrix[i][j]);
+ else
+ cwi = sprintf(buff, "% g", matrix[i][j]);
+ cw[i] = GLM_MAX(cw[i], cwi);
+ }
+ }
+
+ for (i = 0; i < m; i++) {
+ fprintf(ostream, " |");
+
+ for (j = 0; j < n; j++)
+ if (matrix[i][j] < CGLM_PRINT_MAX_TO_SHORT)
+ fprintf(ostream, " % *.*f", cw[j], CGLM_PRINT_PRECISION, matrix[j][i]);
+ else
+ fprintf(ostream, " % *g", cw[j], matrix[j][i]);
+
+ fprintf(ostream, " |\n");
+ }
+
+ fprintf(ostream, CGLM_PRINT_COLOR_RESET "\n");
+
+#undef m
+#undef n
+}
+
+
+CGLM_INLINE
+void
+glm_mat3_print(mat3 matrix,
+ FILE * __restrict ostream) {
+ char buff[16];
+ int i, j, cw[4], cwi;
+
+#define m 3
+#define n 3
+
+ fprintf(ostream, "Matrix (float%dx%d): " CGLM_PRINT_COLOR "\n", m, n);
+
+ cw[0] = cw[1] = cw[2] = 0;
+
+ for (i = 0; i < m; i++) {
+ for (j = 0; j < n; j++) {
+ if (matrix[i][j] < CGLM_PRINT_MAX_TO_SHORT)
+ cwi = sprintf(buff, "% .*f", CGLM_PRINT_PRECISION, matrix[i][j]);
+ else
+ cwi = sprintf(buff, "% g", matrix[i][j]);
+ cw[i] = GLM_MAX(cw[i], cwi);
+ }
+ }
+
+ for (i = 0; i < m; i++) {
+ fprintf(ostream, " |");
+
+ for (j = 0; j < n; j++)
+ if (matrix[i][j] < CGLM_PRINT_MAX_TO_SHORT)
+ fprintf(ostream, " % *.*f", cw[j], CGLM_PRINT_PRECISION, matrix[j][i]);
+ else
+ fprintf(ostream, " % *g", cw[j], matrix[j][i]);
+
+ fprintf(ostream, " |\n");
+ }
+
+ fprintf(ostream, CGLM_PRINT_COLOR_RESET "\n");
+
+#undef m
+#undef n
+}
+
+CGLM_INLINE
+void
+glm_mat2_print(mat2 matrix,
+ FILE * __restrict ostream) {
+ char buff[16];
+ int i, j, cw[4], cwi;
+
+#define m 2
+#define n 2
+
+ fprintf(ostream, "Matrix (float%dx%d): " CGLM_PRINT_COLOR "\n", m, n);
+
+ cw[0] = cw[1] = 0;
+
+ for (i = 0; i < m; i++) {
+ for (j = 0; j < n; j++) {
+ if (matrix[i][j] < CGLM_PRINT_MAX_TO_SHORT)
+ cwi = sprintf(buff, "% .*f", CGLM_PRINT_PRECISION, matrix[i][j]);
+ else
+ cwi = sprintf(buff, "% g", matrix[i][j]);
+ cw[i] = GLM_MAX(cw[i], cwi);
+ }
+ }
+
+ for (i = 0; i < m; i++) {
+ fprintf(ostream, " |");
+
+ for (j = 0; j < n; j++)
+ if (matrix[i][j] < CGLM_PRINT_MAX_TO_SHORT)
+ fprintf(ostream, " % *.*f", cw[j], CGLM_PRINT_PRECISION, matrix[j][i]);
+ else
+ fprintf(ostream, " % *g", cw[j], matrix[j][i]);
+
+ fprintf(ostream, " |\n");
+ }
+
+ fprintf(ostream, CGLM_PRINT_COLOR_RESET "\n");
+
+#undef m
+#undef n
+}
+
+CGLM_INLINE
+void
+glm_vec4_print(vec4 vec,
+ FILE * __restrict ostream) {
+ int i;
+
+#define m 4
+
+ fprintf(ostream, "Vector (float%d): " CGLM_PRINT_COLOR "\n (", m);
+
+ for (i = 0; i < m; i++) {
+ if (vec[i] < CGLM_PRINT_MAX_TO_SHORT)
+ fprintf(ostream, " % .*f", CGLM_PRINT_PRECISION, vec[i]);
+ else
+ fprintf(ostream, " % g", vec[i]);
+ }
+
+ fprintf(ostream, " )" CGLM_PRINT_COLOR_RESET "\n\n");
+
+#undef m
+}
+
+CGLM_INLINE
+void
+glm_vec3_print(vec3 vec,
+ FILE * __restrict ostream) {
+ int i;
+
+#define m 3
+
+ fprintf(ostream, "Vector (float%d): " CGLM_PRINT_COLOR "\n (", m);
+
+ for (i = 0; i < m; i++) {
+ if (vec[i] < CGLM_PRINT_MAX_TO_SHORT)
+ fprintf(ostream, " % .*f", CGLM_PRINT_PRECISION, vec[i]);
+ else
+ fprintf(ostream, " % g", vec[i]);
+ }
+
+ fprintf(ostream, " )" CGLM_PRINT_COLOR_RESET "\n\n");
+
+#undef m
+}
+
+CGLM_INLINE
+void
+glm_ivec3_print(ivec3 vec,
+ FILE * __restrict ostream) {
+ int i;
+
+#define m 3
+
+ fprintf(ostream, "Vector (int%d): " CGLM_PRINT_COLOR "\n (", m);
+
+ for (i = 0; i < m; i++)
+ fprintf(ostream, " % d", vec[i]);
+
+ fprintf(ostream, " )" CGLM_PRINT_COLOR_RESET "\n\n");
+
+#undef m
+}
+
+CGLM_INLINE
+void
+glm_vec2_print(vec2 vec,
+ FILE * __restrict ostream) {
+ int i;
+
+#define m 2
+
+ fprintf(ostream, "Vector (float%d): " CGLM_PRINT_COLOR "\n (", m);
+
+ for (i = 0; i < m; i++) {
+ if (vec[i] < CGLM_PRINT_MAX_TO_SHORT)
+ fprintf(ostream, " % .*f", CGLM_PRINT_PRECISION, vec[i]);
+ else
+ fprintf(ostream, " % g", vec[i]);
+ }
+
+ fprintf(ostream, " )" CGLM_PRINT_COLOR_RESET "\n\n");
+
+#undef m
+}
+
+CGLM_INLINE
+void
+glm_versor_print(versor vec,
+ FILE * __restrict ostream) {
+ int i;
+
+#define m 4
+
+ fprintf(ostream, "Quaternion (float%d): " CGLM_PRINT_COLOR "\n (", m);
+
+ for (i = 0; i < m; i++) {
+ if (vec[i] < CGLM_PRINT_MAX_TO_SHORT)
+ fprintf(ostream, " % .*f", CGLM_PRINT_PRECISION, vec[i]);
+ else
+ fprintf(ostream, " % g", vec[i]);
+ }
+
+
+ fprintf(ostream, " )" CGLM_PRINT_COLOR_RESET "\n\n");
+
+#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): " CGLM_PRINT_COLOR "\n", tag ? tag: "float");
+
+ for (i = 0; i < 2; i++) {
+ fprintf(ostream, " (");
+
+ for (j = 0; j < m; j++) {
+ if (bbox[i][j] < CGLM_PRINT_MAX_TO_SHORT)
+ fprintf(ostream, " % .*f", CGLM_PRINT_PRECISION, bbox[i][j]);
+ else
+ fprintf(ostream, " % g", bbox[i][j]);
+ }
+
+ fprintf(ostream, " )\n");
+ }
+
+ fprintf(ostream, CGLM_PRINT_COLOR_RESET "\n");
+
+#undef m
+}
+
+#else
+
+#include "common.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/* NOOP: Remove print from DEBUG */
+#define glm_mat4_print(v, s) (void)v; (void)s;
+#define glm_mat3_print(v, s) (void)v; (void)s;
+#define glm_mat2_print(v, s) (void)v; (void)s;
+#define glm_vec4_print(v, s) (void)v; (void)s;
+#define glm_vec3_print(v, s) (void)v; (void)s;
+#define glm_ivec3_print(v, s) (void)v; (void)s;
+#define glm_vec2_print(v, s) (void)v; (void)s;
+#define glm_versor_print(v, s) (void)v; (void)s;
+#define glm_aabb_print(v, t, s) (void)v; (void)t; (void)s;
+
+#endif
+#endif /* cglm_io_h */
diff --git a/libs/cglm/include/cglm/ivec2.h b/libs/cglm/include/cglm/ivec2.h
new file mode 100644
index 0000000..c1209a9
--- /dev/null
+++ b/libs/cglm/include/cglm/ivec2.h
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+FUNCTIONS:
+ CGLM_INLINE void glm_ivec2(int * __restrict v, ivec2 dest)
+ CGLM_INLINE void glm_ivec2_copy(ivec2 a, ivec2 dest)
+ CGLM_INLINE void glm_ivec2_zero(ivec2 v)
+ CGLM_INLINE void glm_ivec2_one(ivec2 v)
+ CGLM_INLINE void glm_ivec2_add(ivec2 a, ivec2 b, ivec2 dest)
+ CGLM_INLINE void glm_ivec2_adds(ivec2 v, int s, ivec2 dest)
+ CGLM_INLINE void glm_ivec2_sub(ivec2 a, ivec2 b, ivec2 dest)
+ CGLM_INLINE void glm_ivec2_subs(ivec2 v, int s, ivec2 dest)
+ CGLM_INLINE void glm_ivec2_mul(ivec2 a, ivec2 b, ivec2 dest)
+ CGLM_INLINE void glm_ivec2_scale(ivec2 v, int s, ivec2 dest)
+ CGLM_INLINE int glm_ivec2_distance2(ivec2 a, ivec2 b)
+ CGLM_INLINE float glm_ivec2_distance(ivec2 a, ivec2 b)
+ CGLM_INLINE void glm_ivec2_maxv(ivec2 a, ivec2 b, ivec2 dest)
+ CGLM_INLINE void glm_ivec2_minv(ivec2 a, ivec2 b, ivec2 dest)
+ CGLM_INLINE void glm_ivec2_clamp(ivec2 v, int minVal, int maxVal)
+ */
+
+#ifndef cglm_ivec2_h
+#define cglm_ivec2_h
+
+#include "common.h"
+
+/*!
+ * @brief init ivec2 using vec3 or vec4
+ *
+ * @param[in] v vector
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec2(int * __restrict v, ivec2 dest) {
+ dest[0] = v[0];
+ dest[1] = v[1];
+}
+
+/*!
+ * @brief copy all members of [a] to [dest]
+ *
+ * @param[in] a source vector
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec2_copy(ivec2 a, ivec2 dest) {
+ dest[0] = a[0];
+ dest[1] = a[1];
+}
+
+/*!
+ * @brief set all members of [v] to zero
+ *
+ * @param[out] v vector
+ */
+CGLM_INLINE
+void
+glm_ivec2_zero(ivec2 v) {
+ v[0] = v[1] = 0;
+}
+
+/*!
+ * @brief set all members of [v] to one
+ *
+ * @param[out] v vector
+ */
+CGLM_INLINE
+void
+glm_ivec2_one(ivec2 v) {
+ v[0] = v[1] = 1;
+}
+
+/*!
+ * @brief add vector [a] to vector [b] and store result in [dest]
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec2_add(ivec2 a, ivec2 b, ivec2 dest) {
+ dest[0] = a[0] + b[0];
+ dest[1] = a[1] + b[1];
+}
+
+/*!
+ * @brief add scalar s to vector [v] and store result in [dest]
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec2_adds(ivec2 v, int s, ivec2 dest) {
+ dest[0] = v[0] + s;
+ dest[1] = v[1] + s;
+}
+
+/*!
+ * @brief subtract vector [b] from vector [a] and store result in [dest]
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec2_sub(ivec2 a, ivec2 b, ivec2 dest) {
+ dest[0] = a[0] - b[0];
+ dest[1] = a[1] - b[1];
+}
+
+/*!
+ * @brief subtract scalar s from vector [v] and store result in [dest]
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec2_subs(ivec2 v, int s, ivec2 dest) {
+ dest[0] = v[0] - s;
+ dest[1] = v[1] - s;
+}
+
+/*!
+ * @brief multiply vector [a] with vector [b] and store result in [dest]
+ *
+ * @param[in] a frist vector
+ * @param[in] b second vector
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec2_mul(ivec2 a, ivec2 b, ivec2 dest) {
+ dest[0] = a[0] * b[0];
+ dest[1] = a[1] * b[1];
+}
+
+/*!
+ * @brief multiply vector [a] with scalar s and store result in [dest]
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec2_scale(ivec2 v, int s, ivec2 dest) {
+ dest[0] = v[0] * s;
+ dest[1] = v[1] * s;
+}
+
+/*!
+ * @brief squared distance between two vectors
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @return returns squared distance (distance * distance)
+ */
+CGLM_INLINE
+int
+glm_ivec2_distance2(ivec2 a, ivec2 b) {
+ int xd, yd;
+ xd = a[0] - b[0];
+ yd = a[1] - b[1];
+ return xd * xd + yd * yd;
+}
+
+/*!
+ * @brief distance between two vectors
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @return returns distance
+ */
+CGLM_INLINE
+float
+glm_ivec2_distance(ivec2 a, ivec2 b) {
+ return sqrtf((float)glm_ivec2_distance2(a, b));
+}
+
+/*!
+ * @brief set each member of dest to greater of vector a and b
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec2_maxv(ivec2 a, ivec2 b, ivec2 dest) {
+ dest[0] = a[0] > b[0] ? a[0] : b[0];
+ dest[1] = a[1] > b[1] ? a[1] : b[1];
+}
+
+/*!
+ * @brief set each member of dest to lesser of vector a and b
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec2_minv(ivec2 a, ivec2 b, ivec2 dest) {
+ dest[0] = a[0] < b[0] ? a[0] : b[0];
+ dest[1] = a[1] < b[1] ? a[1] : b[1];
+}
+
+/*!
+ * @brief clamp each member of [v] between minVal and maxVal (inclusive)
+ *
+ * @param[in, out] v vector
+ * @param[in] minVal minimum value
+ * @param[in] maxVal maximum value
+ */
+CGLM_INLINE
+void
+glm_ivec2_clamp(ivec2 v, int minVal, int maxVal) {
+ if (v[0] < minVal)
+ v[0] = minVal;
+ else if(v[0] > maxVal)
+ v[0] = maxVal;
+
+ if (v[1] < minVal)
+ v[1] = minVal;
+ else if(v[1] > maxVal)
+ v[1] = maxVal;
+}
+
+#endif /* cglm_ivec2_h */
diff --git a/libs/cglm/include/cglm/ivec3.h b/libs/cglm/include/cglm/ivec3.h
new file mode 100644
index 0000000..69f27f3
--- /dev/null
+++ b/libs/cglm/include/cglm/ivec3.h
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+FUNCTIONS:
+ CGLM_INLINE void glm_ivec3(ivec4 v4, ivec3 dest)
+ CGLM_INLINE void glm_ivec3_copy(ivec3 a, ivec3 dest)
+ CGLM_INLINE void glm_ivec3_zero(ivec3 v)
+ CGLM_INLINE void glm_ivec3_one(ivec3 v)
+ CGLM_INLINE void glm_ivec3_add(ivec3 a, ivec3 b, ivec3 dest)
+ CGLM_INLINE void glm_ivec3_adds(ivec3 v, int s, ivec3 dest)
+ CGLM_INLINE void glm_ivec3_sub(ivec3 a, ivec3 b, ivec3 dest)
+ CGLM_INLINE void glm_ivec3_subs(ivec3 v, int s, ivec3 dest)
+ CGLM_INLINE void glm_ivec3_mul(ivec3 a, ivec3 b, ivec3 dest)
+ CGLM_INLINE void glm_ivec3_scale(ivec3 v, int s, ivec3 dest)
+ CGLM_INLINE int glm_ivec3_distance2(ivec3 a, ivec3 b)
+ CGLM_INLINE float glm_ivec3_distance(ivec3 a, ivec3 b)
+ CGLM_INLINE void glm_ivec3_maxv(ivec3 a, ivec3 b, ivec3 dest)
+ CGLM_INLINE void glm_ivec3_minv(ivec3 a, ivec3 b, ivec3 dest)
+ CGLM_INLINE void glm_ivec3_clamp(ivec3 v, int minVal, int maxVal)
+ */
+
+#ifndef cglm_ivec3_h
+#define cglm_ivec3_h
+
+#include "common.h"
+
+/*!
+ * @brief init ivec3 using ivec4
+ *
+ * @param[in] v4 vector4
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec3(ivec4 v4, ivec3 dest) {
+ dest[0] = v4[0];
+ dest[1] = v4[1];
+ dest[2] = v4[2];
+}
+
+/*!
+ * @brief copy all members of [a] to [dest]
+ *
+ * @param[in] a source vector
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec3_copy(ivec3 a, ivec3 dest) {
+ dest[0] = a[0];
+ dest[1] = a[1];
+ dest[2] = a[2];
+}
+
+/*!
+ * @brief set all members of [v] to zero
+ *
+ * @param[out] v vector
+ */
+CGLM_INLINE
+void
+glm_ivec3_zero(ivec3 v) {
+ v[0] = v[1] = v[2] = 0;
+}
+
+/*!
+ * @brief set all members of [v] to one
+ *
+ * @param[out] v vector
+ */
+CGLM_INLINE
+void
+glm_ivec3_one(ivec3 v) {
+ v[0] = v[1] = v[2] = 1;
+}
+
+/*!
+ * @brief add vector [a] to vector [b] and store result in [dest]
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec3_add(ivec3 a, ivec3 b, ivec3 dest) {
+ dest[0] = a[0] + b[0];
+ dest[1] = a[1] + b[1];
+ dest[2] = a[2] + b[2];
+}
+
+/*!
+ * @brief add scalar s to vector [v] and store result in [dest]
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec3_adds(ivec3 v, int s, ivec3 dest) {
+ dest[0] = v[0] + s;
+ dest[1] = v[1] + s;
+ dest[2] = v[2] + s;
+}
+
+/*!
+ * @brief subtract vector [b] from vector [a] and store result in [dest]
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec3_sub(ivec3 a, ivec3 b, ivec3 dest) {
+ dest[0] = a[0] - b[0];
+ dest[1] = a[1] - b[1];
+ dest[2] = a[2] - b[2];
+}
+
+/*!
+ * @brief subtract scalar s from vector [v] and store result in [dest]
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec3_subs(ivec3 v, int s, ivec3 dest) {
+ dest[0] = v[0] - s;
+ dest[1] = v[1] - s;
+ dest[2] = v[2] - s;
+}
+
+/*!
+ * @brief multiply vector [a] with vector [b] and store result in [dest]
+ *
+ * @param[in] a frist vector
+ * @param[in] b second vector
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec3_mul(ivec3 a, ivec3 b, ivec3 dest) {
+ dest[0] = a[0] * b[0];
+ dest[1] = a[1] * b[1];
+ dest[2] = a[2] * b[2];
+}
+
+/*!
+ * @brief multiply vector [a] with scalar s and store result in [dest]
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec3_scale(ivec3 v, int s, ivec3 dest) {
+ dest[0] = v[0] * s;
+ dest[1] = v[1] * s;
+ dest[2] = v[2] * s;
+}
+
+/*!
+ * @brief squared distance between two vectors
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @return returns squared distance (distance * distance)
+ */
+CGLM_INLINE
+int
+glm_ivec3_distance2(ivec3 a, ivec3 b) {
+ int xd, yd, zd;
+ xd = a[0] - b[0];
+ yd = a[1] - b[1];
+ zd = a[2] - b[2];
+ return xd * xd + yd * yd + zd * zd;
+}
+
+/*!
+ * @brief distance between two vectors
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @return returns distance
+ */
+CGLM_INLINE
+float
+glm_ivec3_distance(ivec3 a, ivec3 b) {
+ return sqrtf((float)glm_ivec3_distance2(a, b));
+}
+
+/*!
+ * @brief set each member of dest to greater of vector a and b
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec3_maxv(ivec3 a, ivec3 b, ivec3 dest) {
+ dest[0] = a[0] > b[0] ? a[0] : b[0];
+ dest[1] = a[1] > b[1] ? a[1] : b[1];
+ dest[2] = a[2] > b[2] ? a[2] : b[2];
+}
+
+/*!
+ * @brief set each member of dest to lesser of vector a and b
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec3_minv(ivec3 a, ivec3 b, ivec3 dest) {
+ dest[0] = a[0] < b[0] ? a[0] : b[0];
+ dest[1] = a[1] < b[1] ? a[1] : b[1];
+ dest[2] = a[2] < b[2] ? a[2] : b[2];
+}
+
+/*!
+ * @brief clamp each member of [v] between minVal and maxVal (inclusive)
+ *
+ * @param[in, out] v vector
+ * @param[in] minVal minimum value
+ * @param[in] maxVal maximum value
+ */
+CGLM_INLINE
+void
+glm_ivec3_clamp(ivec3 v, int minVal, int maxVal) {
+ if (v[0] < minVal)
+ v[0] = minVal;
+ else if(v[0] > maxVal)
+ v[0] = maxVal;
+
+ if (v[1] < minVal)
+ v[1] = minVal;
+ else if(v[1] > maxVal)
+ v[1] = maxVal;
+
+ if (v[2] < minVal)
+ v[2] = minVal;
+ else if(v[2] > maxVal)
+ v[2] = maxVal;
+}
+
+#endif /* cglm_ivec3_h */
diff --git a/libs/cglm/include/cglm/ivec4.h b/libs/cglm/include/cglm/ivec4.h
new file mode 100644
index 0000000..363ee58
--- /dev/null
+++ b/libs/cglm/include/cglm/ivec4.h
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+FUNCTIONS:
+ CGLM_INLINE void glm_ivec4(ivec3 v3, int last, ivec4 dest)
+ CGLM_INLINE void glm_ivec4_copy(ivec4 a, ivec4 dest)
+ CGLM_INLINE void glm_ivec4_zero(ivec4 v)
+ CGLM_INLINE void glm_ivec4_one(ivec4 v)
+ CGLM_INLINE void glm_ivec4_add(ivec4 a, ivec4 b, ivec4 dest)
+ CGLM_INLINE void glm_ivec4_adds(ivec4 v, int s, ivec4 dest)
+ CGLM_INLINE void glm_ivec4_sub(ivec4 a, ivec4 b, ivec4 dest)
+ CGLM_INLINE void glm_ivec4_subs(ivec4 v, int s, ivec4 dest)
+ CGLM_INLINE void glm_ivec4_mul(ivec4 a, ivec4 b, ivec4 dest)
+ CGLM_INLINE void glm_ivec4_scale(ivec4 v, int s, ivec4 dest)
+ CGLM_INLINE int glm_ivec4_distance2(ivec4 a, ivec4 b)
+ CGLM_INLINE float glm_ivec4_distance(ivec4 a, ivec4 b)
+ CGLM_INLINE void glm_ivec4_maxv(ivec4 a, ivec4 b, ivec4 dest)
+ CGLM_INLINE void glm_ivec4_minv(ivec4 a, ivec4 b, ivec4 dest)
+ CGLM_INLINE void glm_ivec4_clamp(ivec4 v, int minVal, int maxVal)
+ */
+
+#ifndef cglm_ivec4_h
+#define cglm_ivec4_h
+
+#include "common.h"
+
+/*!
+ * @brief init ivec4 using ivec3
+ *
+ * @param[in] v3 vector3
+ * @param[in] last last item
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec4(ivec3 v3, int last, ivec4 dest) {
+ dest[0] = v3[0];
+ dest[1] = v3[1];
+ dest[2] = v3[2];
+ dest[3] = last;
+}
+
+/*!
+ * @brief copy all members of [a] to [dest]
+ *
+ * @param[in] a source vector
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec4_copy(ivec4 a, ivec4 dest) {
+ dest[0] = a[0];
+ dest[1] = a[1];
+ dest[2] = a[2];
+ dest[3] = a[3];
+}
+
+/*!
+ * @brief set all members of [v] to zero
+ *
+ * @param[out] v vector
+ */
+CGLM_INLINE
+void
+glm_ivec4_zero(ivec4 v) {
+ v[0] = v[1] = v[2] = v[3] = 0;
+}
+
+/*!
+ * @brief set all members of [v] to one
+ *
+ * @param[out] v vector
+ */
+CGLM_INLINE
+void
+glm_ivec4_one(ivec4 v) {
+ v[0] = v[1] = v[2] = v[3] = 1;
+}
+
+/*!
+ * @brief add vector [a] to vector [b] and store result in [dest]
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec4_add(ivec4 a, ivec4 b, ivec4 dest) {
+ dest[0] = a[0] + b[0];
+ dest[1] = a[1] + b[1];
+ dest[2] = a[2] + b[2];
+ dest[3] = a[3] + b[3];
+}
+
+/*!
+ * @brief add scalar s to vector [v] and store result in [dest]
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec4_adds(ivec4 v, int s, ivec4 dest) {
+ dest[0] = v[0] + s;
+ dest[1] = v[1] + s;
+ dest[2] = v[2] + s;
+ dest[3] = v[3] + s;
+}
+
+/*!
+ * @brief subtract vector [b] from vector [a] and store result in [dest]
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec4_sub(ivec4 a, ivec4 b, ivec4 dest) {
+ dest[0] = a[0] - b[0];
+ dest[1] = a[1] - b[1];
+ dest[2] = a[2] - b[2];
+ dest[3] = a[3] - b[3];
+}
+
+/*!
+ * @brief subtract scalar s from vector [v] and store result in [dest]
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec4_subs(ivec4 v, int s, ivec4 dest) {
+ dest[0] = v[0] - s;
+ dest[1] = v[1] - s;
+ dest[2] = v[2] - s;
+ dest[3] = v[3] - s;
+}
+
+/*!
+ * @brief multiply vector [a] with vector [b] and store result in [dest]
+ *
+ * @param[in] a frist vector
+ * @param[in] b second vector
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec4_mul(ivec4 a, ivec4 b, ivec4 dest) {
+ dest[0] = a[0] * b[0];
+ dest[1] = a[1] * b[1];
+ dest[2] = a[2] * b[2];
+ dest[3] = a[3] * b[3];
+}
+
+/*!
+ * @brief multiply vector [a] with scalar s and store result in [dest]
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec4_scale(ivec4 v, int s, ivec4 dest) {
+ dest[0] = v[0] * s;
+ dest[1] = v[1] * s;
+ dest[2] = v[2] * s;
+ dest[3] = v[3] * s;
+}
+
+/*!
+ * @brief squared distance between two vectors
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @return returns squared distance (distance * distance)
+ */
+CGLM_INLINE
+int
+glm_ivec4_distance2(ivec4 a, ivec4 b) {
+ int xd, yd, zd, wd;
+ xd = a[0] - b[0];
+ yd = a[1] - b[1];
+ zd = a[2] - b[2];
+ wd = a[3] - b[3];
+ return xd * xd + yd * yd + zd * zd + wd * wd;
+}
+
+/*!
+ * @brief distance between two vectors
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @return returns distance
+ */
+CGLM_INLINE
+float
+glm_ivec4_distance(ivec4 a, ivec4 b) {
+ return sqrtf((float)glm_ivec4_distance2(a, b));
+}
+
+/*!
+ * @brief set each member of dest to greater of vector a and b
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec4_maxv(ivec4 a, ivec4 b, ivec4 dest) {
+ dest[0] = a[0] > b[0] ? a[0] : b[0];
+ dest[1] = a[1] > b[1] ? a[1] : b[1];
+ dest[2] = a[2] > b[2] ? a[2] : b[2];
+ dest[3] = a[3] > b[3] ? a[3] : b[3];
+}
+
+/*!
+ * @brief set each member of dest to lesser of vector a and b
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_ivec4_minv(ivec4 a, ivec4 b, ivec4 dest) {
+ dest[0] = a[0] < b[0] ? a[0] : b[0];
+ dest[1] = a[1] < b[1] ? a[1] : b[1];
+ dest[2] = a[2] < b[2] ? a[2] : b[2];
+ dest[3] = a[3] < b[3] ? a[3] : b[3];
+}
+
+/*!
+ * @brief clamp each member of [v] between minVal and maxVal (inclusive)
+ *
+ * @param[in, out] v vector
+ * @param[in] minVal minimum value
+ * @param[in] maxVal maximum value
+ */
+CGLM_INLINE
+void
+glm_ivec4_clamp(ivec4 v, int minVal, int maxVal) {
+ if (v[0] < minVal)
+ v[0] = minVal;
+ else if(v[0] > maxVal)
+ v[0] = maxVal;
+
+ if (v[1] < minVal)
+ v[1] = minVal;
+ else if(v[1] > maxVal)
+ v[1] = maxVal;
+
+ if (v[2] < minVal)
+ v[2] = minVal;
+ else if(v[2] > maxVal)
+ v[2] = maxVal;
+
+ if (v[3] < minVal)
+ v[3] = minVal;
+ else if(v[3] > maxVal)
+ v[3] = maxVal;
+}
+
+#endif /* cglm_ivec4_h */
diff --git a/libs/cglm/include/cglm/mat2.h b/libs/cglm/include/cglm/mat2.h
new file mode 100644
index 0000000..871d6bd
--- /dev/null
+++ b/libs/cglm/include/cglm/mat2.h
@@ -0,0 +1,337 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Macros:
+ GLM_MAT2_IDENTITY_INIT
+ GLM_MAT2_ZERO_INIT
+ GLM_MAT2_IDENTITY
+ GLM_MAT2_ZERO
+
+ Functions:
+ CGLM_INLINE void glm_mat2_copy(mat2 mat, mat2 dest)
+ CGLM_INLINE void glm_mat2_identity(mat2 mat)
+ CGLM_INLINE void glm_mat2_identity_array(mat2 * restrict mat, size_t count)
+ CGLM_INLINE void glm_mat2_zero(mat2 mat)
+ CGLM_INLINE void glm_mat2_mul(mat2 m1, mat2 m2, mat2 dest)
+ CGLM_INLINE void glm_mat2_transpose_to(mat2 m, mat2 dest)
+ CGLM_INLINE void glm_mat2_transpose(mat2 m)
+ CGLM_INLINE void glm_mat2_mulv(mat2 m, vec2 v, vec2 dest)
+ CGLM_INLINE float glm_mat2_trace(mat2 m)
+ CGLM_INLINE void glm_mat2_scale(mat2 m, float s)
+ CGLM_INLINE float glm_mat2_det(mat2 mat)
+ CGLM_INLINE void glm_mat2_inv(mat2 mat, mat2 dest)
+ CGLM_INLINE void glm_mat2_swap_col(mat2 mat, int col1, int col2)
+ CGLM_INLINE void glm_mat2_swap_row(mat2 mat, int row1, int row2)
+ CGLM_INLINE float glm_mat2_rmc(vec2 r, mat2 m, vec2 c)
+ */
+
+#ifndef cglm_mat2_h
+#define cglm_mat2_h
+
+#include "common.h"
+#include "vec2.h"
+
+#ifdef CGLM_SSE_FP
+# include "simd/sse2/mat2.h"
+#endif
+
+#ifdef CGLM_NEON_FP
+# include "simd/neon/mat2.h"
+#endif
+
+#define GLM_MAT2_IDENTITY_INIT {{1.0f, 0.0f}, {0.0f, 1.0f}}
+#define GLM_MAT2_ZERO_INIT {{0.0f, 0.0f}, {0.0f, 0.0f}}
+
+/* for C only */
+#define GLM_MAT2_IDENTITY ((mat2)GLM_MAT2_IDENTITY_INIT)
+#define GLM_MAT2_ZERO ((mat2)GLM_MAT2_ZERO_INIT)
+
+/*!
+ * @brief copy all members of [mat] to [dest]
+ *
+ * @param[in] mat source
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_mat2_copy(mat2 mat, mat2 dest) {
+ glm_vec4_ucopy(mat[0], dest[0]);
+}
+
+/*!
+ * @brief make given matrix identity. It is identical with below,
+ * but it is more easy to do that with this func especially for members
+ * e.g. glm_mat2_identity(aStruct->aMatrix);
+ *
+ * @code
+ * glm_mat2_copy(GLM_MAT2_IDENTITY, mat); // C only
+ *
+ * // or
+ * mat2 mat = GLM_MAT2_IDENTITY_INIT;
+ * @endcode
+ *
+ * @param[in, out] mat destination
+ */
+CGLM_INLINE
+void
+glm_mat2_identity(mat2 mat) {
+ CGLM_ALIGN_MAT mat2 t = GLM_MAT2_IDENTITY_INIT;
+ glm_mat2_copy(t, mat);
+}
+
+/*!
+ * @brief make given matrix array's each element identity matrix
+ *
+ * @param[in, out] mat matrix array (must be aligned (16)
+ * if alignment is not disabled)
+ *
+ * @param[in] count count of matrices
+ */
+CGLM_INLINE
+void
+glm_mat2_identity_array(mat2 * __restrict mat, size_t count) {
+ CGLM_ALIGN_MAT mat2 t = GLM_MAT2_IDENTITY_INIT;
+ size_t i;
+
+ for (i = 0; i < count; i++) {
+ glm_mat2_copy(t, mat[i]);
+ }
+}
+
+/*!
+ * @brief make given matrix zero.
+ *
+ * @param[in, out] mat matrix
+ */
+CGLM_INLINE
+void
+glm_mat2_zero(mat2 mat) {
+ CGLM_ALIGN_MAT mat2 t = GLM_MAT2_ZERO_INIT;
+ glm_mat2_copy(t, mat);
+}
+
+/*!
+ * @brief multiply m1 and m2 to dest
+ *
+ * m1, m2 and dest matrices can be same matrix, it is possible to write this:
+ *
+ * @code
+ * mat2 m = GLM_MAT2_IDENTITY_INIT;
+ * glm_mat2_mul(m, m, m);
+ * @endcode
+ *
+ * @param[in] m1 left matrix
+ * @param[in] m2 right matrix
+ * @param[out] dest destination matrix
+ */
+CGLM_INLINE
+void
+glm_mat2_mul(mat2 m1, mat2 m2, mat2 dest) {
+#if defined( __SSE__ ) || defined( __SSE2__ )
+ glm_mat2_mul_sse2(m1, m2, dest);
+#elif defined(CGLM_NEON_FP)
+ glm_mat2_mul_neon(m1, m2, dest);
+#else
+ float a00 = m1[0][0], a01 = m1[0][1],
+ a10 = m1[1][0], a11 = m1[1][1],
+ b00 = m2[0][0], b01 = m2[0][1],
+ b10 = m2[1][0], b11 = m2[1][1];
+
+ dest[0][0] = a00 * b00 + a10 * b01;
+ dest[0][1] = a01 * b00 + a11 * b01;
+ dest[1][0] = a00 * b10 + a10 * b11;
+ dest[1][1] = a01 * b10 + a11 * b11;
+#endif
+}
+
+/*!
+ * @brief transpose mat2 and store in dest
+ *
+ * source matrix will not be transposed unless dest is m
+ *
+ * @param[in] m matrix
+ * @param[out] dest result
+ */
+CGLM_INLINE
+void
+glm_mat2_transpose_to(mat2 m, mat2 dest) {
+#if defined( __SSE__ ) || defined( __SSE2__ )
+ glm_mat2_transp_sse2(m, dest);
+#else
+ dest[0][0] = m[0][0];
+ dest[0][1] = m[1][0];
+ dest[1][0] = m[0][1];
+ dest[1][1] = m[1][1];
+#endif
+}
+
+/*!
+ * @brief tranpose mat2 and store result in same matrix
+ *
+ * @param[in, out] m source and dest
+ */
+CGLM_INLINE
+void
+glm_mat2_transpose(mat2 m) {
+ float tmp;
+ tmp = m[0][1];
+ m[0][1] = m[1][0];
+ m[1][0] = tmp;
+}
+
+/*!
+ * @brief multiply mat2 with vec2 (column vector) and store in dest vector
+ *
+ * @param[in] m mat2 (left)
+ * @param[in] v vec2 (right, column vector)
+ * @param[out] dest vec2 (result, column vector)
+ */
+CGLM_INLINE
+void
+glm_mat2_mulv(mat2 m, vec2 v, vec2 dest) {
+ dest[0] = m[0][0] * v[0] + m[1][0] * v[1];
+ dest[1] = m[0][1] * v[0] + m[1][1] * v[1];
+}
+
+/*!
+ * @brief trace of matrix
+ *
+ * sum of the elements on the main diagonal from upper left to the lower right
+ *
+ * @param[in] m matrix
+ */
+CGLM_INLINE
+float
+glm_mat2_trace(mat2 m) {
+ return m[0][0] + m[1][1];
+}
+
+/*!
+ * @brief scale (multiply with scalar) matrix
+ *
+ * multiply matrix with scalar
+ *
+ * @param[in, out] m matrix
+ * @param[in] s scalar
+ */
+CGLM_INLINE
+void
+glm_mat2_scale(mat2 m, float s) {
+#if defined( __SSE__ ) || defined( __SSE2__ )
+ glmm_store(m[0], _mm_mul_ps(_mm_loadu_ps(m[0]), _mm_set1_ps(s)));
+#elif defined(CGLM_NEON_FP)
+ vst1q_f32(m[0], vmulq_f32(vld1q_f32(m[0]), vdupq_n_f32(s)));
+#else
+ m[0][0] = m[0][0] * s;
+ m[0][1] = m[0][1] * s;
+ m[1][0] = m[1][0] * s;
+ m[1][1] = m[1][1] * s;
+#endif
+}
+
+/*!
+ * @brief mat2 determinant
+ *
+ * @param[in] mat matrix
+ *
+ * @return determinant
+ */
+CGLM_INLINE
+float
+glm_mat2_det(mat2 mat) {
+ return mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1];
+}
+
+/*!
+ * @brief inverse mat2 and store in dest
+ *
+ * @param[in] mat matrix
+ * @param[out] dest inverse matrix
+ */
+CGLM_INLINE
+void
+glm_mat2_inv(mat2 mat, mat2 dest) {
+ float det;
+ float a = mat[0][0], b = mat[0][1],
+ c = mat[1][0], d = mat[1][1];
+
+ det = 1.0f / (a * d - b * c);
+
+ dest[0][0] = d * det;
+ dest[0][1] = -b * det;
+ dest[1][0] = -c * det;
+ dest[1][1] = a * det;
+}
+
+/*!
+ * @brief swap two matrix columns
+ *
+ * @param[in,out] mat matrix
+ * @param[in] col1 col1
+ * @param[in] col2 col2
+ */
+CGLM_INLINE
+void
+glm_mat2_swap_col(mat2 mat, int col1, int col2) {
+ float a, b;
+
+ a = mat[col1][0];
+ b = mat[col1][1];
+
+ mat[col1][0] = mat[col2][0];
+ mat[col1][1] = mat[col2][1];
+
+ mat[col2][0] = a;
+ mat[col2][1] = b;
+}
+
+/*!
+ * @brief swap two matrix rows
+ *
+ * @param[in,out] mat matrix
+ * @param[in] row1 row1
+ * @param[in] row2 row2
+ */
+CGLM_INLINE
+void
+glm_mat2_swap_row(mat2 mat, int row1, int row2) {
+ float a, b;
+
+ a = mat[0][row1];
+ b = mat[1][row1];
+
+ mat[0][row1] = mat[0][row2];
+ mat[1][row1] = mat[1][row2];
+
+ mat[0][row2] = a;
+ mat[1][row2] = b;
+}
+
+/*!
+ * @brief helper for R (row vector) * M (matrix) * C (column vector)
+ *
+ * rmc stands for Row * Matrix * Column
+ *
+ * the result is scalar because R * M = Matrix1x2 (row vector),
+ * then Matrix1x2 * Vec2 (column vector) = Matrix1x1 (Scalar)
+ *
+ * @param[in] r row vector or matrix1x2
+ * @param[in] m matrix2x2
+ * @param[in] c column vector or matrix2x1
+ *
+ * @return scalar value e.g. Matrix1x1
+ */
+CGLM_INLINE
+float
+glm_mat2_rmc(vec2 r, mat2 m, vec2 c) {
+ vec2 tmp;
+ glm_mat2_mulv(m, c, tmp);
+ return glm_vec2_dot(r, tmp);
+}
+
+#endif /* cglm_mat2_h */
diff --git a/libs/cglm/include/cglm/mat3.h b/libs/cglm/include/cglm/mat3.h
new file mode 100644
index 0000000..0b29f97
--- /dev/null
+++ b/libs/cglm/include/cglm/mat3.h
@@ -0,0 +1,424 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Macros:
+ GLM_MAT3_IDENTITY_INIT
+ GLM_MAT3_ZERO_INIT
+ GLM_MAT3_IDENTITY
+ GLM_MAT3_ZERO
+ glm_mat3_dup(mat, dest)
+
+ Functions:
+ CGLM_INLINE void glm_mat3_copy(mat3 mat, mat3 dest);
+ CGLM_INLINE void glm_mat3_identity(mat3 mat);
+ CGLM_INLINE void glm_mat3_identity_array(mat3 * restrict mat, size_t count);
+ CGLM_INLINE void glm_mat3_zero(mat3 mat);
+ CGLM_INLINE void glm_mat3_mul(mat3 m1, mat3 m2, mat3 dest);
+ CGLM_INLINE void glm_mat3_transpose_to(mat3 m, mat3 dest);
+ CGLM_INLINE void glm_mat3_transpose(mat3 m);
+ CGLM_INLINE void glm_mat3_mulv(mat3 m, vec3 v, vec3 dest);
+ CGLM_INLINE float glm_mat3_trace(mat3 m);
+ CGLM_INLINE void glm_mat3_quat(mat3 m, versor dest);
+ CGLM_INLINE void glm_mat3_scale(mat3 m, float s);
+ CGLM_INLINE float glm_mat3_det(mat3 mat);
+ CGLM_INLINE void glm_mat3_inv(mat3 mat, mat3 dest);
+ CGLM_INLINE void glm_mat3_swap_col(mat3 mat, int col1, int col2);
+ CGLM_INLINE void glm_mat3_swap_row(mat3 mat, int row1, int row2);
+ CGLM_INLINE float glm_mat3_rmc(vec3 r, mat3 m, vec3 c);
+ */
+
+#ifndef cglm_mat3_h
+#define cglm_mat3_h
+
+#include "common.h"
+#include "vec3.h"
+
+#ifdef CGLM_SSE_FP
+# include "simd/sse2/mat3.h"
+#endif
+
+#define GLM_MAT3_IDENTITY_INIT {{1.0f, 0.0f, 0.0f}, \
+ {0.0f, 1.0f, 0.0f}, \
+ {0.0f, 0.0f, 1.0f}}
+#define GLM_MAT3_ZERO_INIT {{0.0f, 0.0f, 0.0f}, \
+ {0.0f, 0.0f, 0.0f}, \
+ {0.0f, 0.0f, 0.0f}}
+
+
+/* for C only */
+#define GLM_MAT3_IDENTITY ((mat3)GLM_MAT3_IDENTITY_INIT)
+#define GLM_MAT3_ZERO ((mat3)GLM_MAT3_ZERO_INIT)
+
+/* DEPRECATED! use _copy, _ucopy versions */
+#define glm_mat3_dup(mat, dest) glm_mat3_copy(mat, dest)
+
+/*!
+ * @brief copy all members of [mat] to [dest]
+ *
+ * @param[in] mat source
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_mat3_copy(mat3 mat, mat3 dest) {
+ dest[0][0] = mat[0][0];
+ dest[0][1] = mat[0][1];
+ dest[0][2] = mat[0][2];
+
+ dest[1][0] = mat[1][0];
+ dest[1][1] = mat[1][1];
+ dest[1][2] = mat[1][2];
+
+ dest[2][0] = mat[2][0];
+ dest[2][1] = mat[2][1];
+ dest[2][2] = mat[2][2];
+}
+
+/*!
+ * @brief make given matrix identity. It is identical with below,
+ * but it is more easy to do that with this func especially for members
+ * e.g. glm_mat3_identity(aStruct->aMatrix);
+ *
+ * @code
+ * glm_mat3_copy(GLM_MAT3_IDENTITY, mat); // C only
+ *
+ * // or
+ * mat3 mat = GLM_MAT3_IDENTITY_INIT;
+ * @endcode
+ *
+ * @param[in, out] mat destination
+ */
+CGLM_INLINE
+void
+glm_mat3_identity(mat3 mat) {
+ CGLM_ALIGN_MAT mat3 t = GLM_MAT3_IDENTITY_INIT;
+ glm_mat3_copy(t, mat);
+}
+
+/*!
+ * @brief make given matrix array's each element identity matrix
+ *
+ * @param[in, out] mat matrix array (must be aligned (16/32)
+ * if alignment is not disabled)
+ *
+ * @param[in] count count of matrices
+ */
+CGLM_INLINE
+void
+glm_mat3_identity_array(mat3 * __restrict mat, size_t count) {
+ CGLM_ALIGN_MAT mat3 t = GLM_MAT3_IDENTITY_INIT;
+ size_t i;
+
+ for (i = 0; i < count; i++) {
+ glm_mat3_copy(t, mat[i]);
+ }
+}
+
+/*!
+ * @brief make given matrix zero.
+ *
+ * @param[in, out] mat matrix
+ */
+CGLM_INLINE
+void
+glm_mat3_zero(mat3 mat) {
+ CGLM_ALIGN_MAT mat3 t = GLM_MAT3_ZERO_INIT;
+ glm_mat3_copy(t, mat);
+}
+
+/*!
+ * @brief multiply m1 and m2 to dest
+ *
+ * m1, m2 and dest matrices can be same matrix, it is possible to write this:
+ *
+ * @code
+ * mat3 m = GLM_MAT3_IDENTITY_INIT;
+ * glm_mat3_mul(m, m, m);
+ * @endcode
+ *
+ * @param[in] m1 left matrix
+ * @param[in] m2 right matrix
+ * @param[out] dest destination matrix
+ */
+CGLM_INLINE
+void
+glm_mat3_mul(mat3 m1, mat3 m2, mat3 dest) {
+#if defined( __SSE__ ) || defined( __SSE2__ )
+ glm_mat3_mul_sse2(m1, m2, dest);
+#else
+ float a00 = m1[0][0], a01 = m1[0][1], a02 = m1[0][2],
+ a10 = m1[1][0], a11 = m1[1][1], a12 = m1[1][2],
+ a20 = m1[2][0], a21 = m1[2][1], a22 = m1[2][2],
+
+ 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[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[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;
+#endif
+}
+
+/*!
+ * @brief transpose mat3 and store in dest
+ *
+ * source matrix will not be transposed unless dest is m
+ *
+ * @param[in] m matrix
+ * @param[out] dest result
+ */
+CGLM_INLINE
+void
+glm_mat3_transpose_to(mat3 m, mat3 dest) {
+ dest[0][0] = m[0][0];
+ dest[0][1] = m[1][0];
+ dest[0][2] = m[2][0];
+ dest[1][0] = m[0][1];
+ dest[1][1] = m[1][1];
+ dest[1][2] = m[2][1];
+ dest[2][0] = m[0][2];
+ dest[2][1] = m[1][2];
+ dest[2][2] = m[2][2];
+}
+
+/*!
+ * @brief tranpose mat3 and store result in same matrix
+ *
+ * @param[in, out] m source and dest
+ */
+CGLM_INLINE
+void
+glm_mat3_transpose(mat3 m) {
+ CGLM_ALIGN_MAT mat3 tmp;
+
+ tmp[0][1] = m[1][0];
+ tmp[0][2] = m[2][0];
+ tmp[1][0] = m[0][1];
+ tmp[1][2] = m[2][1];
+ tmp[2][0] = m[0][2];
+ tmp[2][1] = m[1][2];
+
+ m[0][1] = tmp[0][1];
+ m[0][2] = tmp[0][2];
+ m[1][0] = tmp[1][0];
+ m[1][2] = tmp[1][2];
+ m[2][0] = tmp[2][0];
+ m[2][1] = tmp[2][1];
+}
+
+/*!
+ * @brief multiply mat3 with vec3 (column vector) and store in dest vector
+ *
+ * @param[in] m mat3 (left)
+ * @param[in] v vec3 (right, column vector)
+ * @param[out] dest vec3 (result, column vector)
+ */
+CGLM_INLINE
+void
+glm_mat3_mulv(mat3 m, vec3 v, vec3 dest) {
+ vec3 res;
+ res[0] = m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2];
+ res[1] = m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2];
+ res[2] = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2];
+ glm_vec3_copy(res, dest);
+}
+
+/*!
+ * @brief trace of matrix
+ *
+ * sum of the elements on the main diagonal from upper left to the lower right
+ *
+ * @param[in] m matrix
+ */
+CGLM_INLINE
+float
+glm_mat3_trace(mat3 m) {
+ return m[0][0] + m[1][1] + m[2][2];
+}
+
+/*!
+ * @brief convert mat3 to quaternion
+ *
+ * @param[in] m rotation matrix
+ * @param[out] dest destination quaternion
+ */
+CGLM_INLINE
+void
+glm_mat3_quat(mat3 m, versor dest) {
+ float trace, r, rinv;
+
+ /* it seems using like m12 instead of m[1][2] causes extra instructions */
+
+ trace = m[0][0] + m[1][1] + m[2][2];
+ if (trace >= 0.0f) {
+ r = sqrtf(1.0f + trace);
+ rinv = 0.5f / r;
+
+ dest[0] = rinv * (m[1][2] - m[2][1]);
+ dest[1] = rinv * (m[2][0] - m[0][2]);
+ dest[2] = rinv * (m[0][1] - m[1][0]);
+ dest[3] = r * 0.5f;
+ } else if (m[0][0] >= m[1][1] && m[0][0] >= m[2][2]) {
+ r = sqrtf(1.0f - m[1][1] - m[2][2] + m[0][0]);
+ rinv = 0.5f / r;
+
+ dest[0] = r * 0.5f;
+ dest[1] = rinv * (m[0][1] + m[1][0]);
+ dest[2] = rinv * (m[0][2] + m[2][0]);
+ dest[3] = rinv * (m[1][2] - m[2][1]);
+ } else if (m[1][1] >= m[2][2]) {
+ r = sqrtf(1.0f - m[0][0] - m[2][2] + m[1][1]);
+ rinv = 0.5f / r;
+
+ dest[0] = rinv * (m[0][1] + m[1][0]);
+ dest[1] = r * 0.5f;
+ dest[2] = rinv * (m[1][2] + m[2][1]);
+ dest[3] = rinv * (m[2][0] - m[0][2]);
+ } else {
+ r = sqrtf(1.0f - m[0][0] - m[1][1] + m[2][2]);
+ rinv = 0.5f / r;
+
+ dest[0] = rinv * (m[0][2] + m[2][0]);
+ dest[1] = rinv * (m[1][2] + m[2][1]);
+ dest[2] = r * 0.5f;
+ dest[3] = rinv * (m[0][1] - m[1][0]);
+ }
+}
+
+/*!
+ * @brief scale (multiply with scalar) matrix
+ *
+ * multiply matrix with scalar
+ *
+ * @param[in, out] m matrix
+ * @param[in] s scalar
+ */
+CGLM_INLINE
+void
+glm_mat3_scale(mat3 m, float s) {
+ m[0][0] *= s; m[0][1] *= s; m[0][2] *= s;
+ m[1][0] *= s; m[1][1] *= s; m[1][2] *= s;
+ m[2][0] *= s; m[2][1] *= s; m[2][2] *= s;
+}
+
+/*!
+ * @brief mat3 determinant
+ *
+ * @param[in] mat matrix
+ *
+ * @return determinant
+ */
+CGLM_INLINE
+float
+glm_mat3_det(mat3 mat) {
+ float a = mat[0][0], b = mat[0][1], c = mat[0][2],
+ d = mat[1][0], e = mat[1][1], f = mat[1][2],
+ g = mat[2][0], h = mat[2][1], i = mat[2][2];
+
+ return a * (e * i - h * f) - d * (b * i - c * h) + g * (b * f - c * e);
+}
+
+/*!
+ * @brief inverse mat3 and store in dest
+ *
+ * @param[in] mat matrix
+ * @param[out] dest inverse matrix
+ */
+CGLM_INLINE
+void
+glm_mat3_inv(mat3 mat, mat3 dest) {
+ float det;
+ float a = mat[0][0], b = mat[0][1], c = mat[0][2],
+ d = mat[1][0], e = mat[1][1], f = mat[1][2],
+ g = mat[2][0], h = mat[2][1], i = mat[2][2];
+
+ dest[0][0] = e * i - f * h;
+ dest[0][1] = -(b * i - h * c);
+ dest[0][2] = b * f - e * c;
+ dest[1][0] = -(d * i - g * f);
+ dest[1][1] = a * i - c * g;
+ dest[1][2] = -(a * f - d * c);
+ dest[2][0] = d * h - g * e;
+ dest[2][1] = -(a * h - g * b);
+ dest[2][2] = a * e - b * d;
+
+ det = 1.0f / (a * dest[0][0] + b * dest[1][0] + c * dest[2][0]);
+
+ glm_mat3_scale(dest, det);
+}
+
+/*!
+ * @brief swap two matrix columns
+ *
+ * @param[in,out] mat matrix
+ * @param[in] col1 col1
+ * @param[in] col2 col2
+ */
+CGLM_INLINE
+void
+glm_mat3_swap_col(mat3 mat, int col1, int col2) {
+ vec3 tmp;
+ glm_vec3_copy(mat[col1], tmp);
+ glm_vec3_copy(mat[col2], mat[col1]);
+ glm_vec3_copy(tmp, mat[col2]);
+}
+
+/*!
+ * @brief swap two matrix rows
+ *
+ * @param[in,out] mat matrix
+ * @param[in] row1 row1
+ * @param[in] row2 row2
+ */
+CGLM_INLINE
+void
+glm_mat3_swap_row(mat3 mat, int row1, int row2) {
+ vec3 tmp;
+ tmp[0] = mat[0][row1];
+ tmp[1] = mat[1][row1];
+ tmp[2] = mat[2][row1];
+
+ mat[0][row1] = mat[0][row2];
+ mat[1][row1] = mat[1][row2];
+ mat[2][row1] = mat[2][row2];
+
+ mat[0][row2] = tmp[0];
+ mat[1][row2] = tmp[1];
+ mat[2][row2] = tmp[2];
+}
+
+/*!
+ * @brief helper for R (row vector) * M (matrix) * C (column vector)
+ *
+ * rmc stands for Row * Matrix * Column
+ *
+ * the result is scalar because R * M = Matrix1x3 (row vector),
+ * then Matrix1x3 * Vec3 (column vector) = Matrix1x1 (Scalar)
+ *
+ * @param[in] r row vector or matrix1x3
+ * @param[in] m matrix3x3
+ * @param[in] c column vector or matrix3x1
+ *
+ * @return scalar value e.g. Matrix1x1
+ */
+CGLM_INLINE
+float
+glm_mat3_rmc(vec3 r, mat3 m, vec3 c) {
+ vec3 tmp;
+ glm_mat3_mulv(m, c, tmp);
+ return glm_vec3_dot(r, tmp);
+}
+
+#endif /* cglm_mat3_h */
diff --git a/libs/cglm/include/cglm/mat4.h b/libs/cglm/include/cglm/mat4.h
new file mode 100644
index 0000000..04cfece
--- /dev/null
+++ b/libs/cglm/include/cglm/mat4.h
@@ -0,0 +1,754 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*!
+ * Most of functions in this header are optimized manually with SIMD
+ * if available. You dont need to call/incude SIMD headers manually
+ */
+
+/*
+ Macros:
+ GLM_MAT4_IDENTITY_INIT
+ GLM_MAT4_ZERO_INIT
+ GLM_MAT4_IDENTITY
+ GLM_MAT4_ZERO
+
+ Functions:
+ CGLM_INLINE void glm_mat4_ucopy(mat4 mat, mat4 dest);
+ CGLM_INLINE void glm_mat4_copy(mat4 mat, mat4 dest);
+ CGLM_INLINE void glm_mat4_identity(mat4 mat);
+ CGLM_INLINE void glm_mat4_identity_array(mat4 * restrict mat, size_t count);
+ CGLM_INLINE void glm_mat4_zero(mat4 mat);
+ CGLM_INLINE void glm_mat4_pick3(mat4 mat, mat3 dest);
+ CGLM_INLINE void glm_mat4_pick3t(mat4 mat, mat3 dest);
+ CGLM_INLINE void glm_mat4_ins3(mat3 mat, mat4 dest);
+ CGLM_INLINE void glm_mat4_mul(mat4 m1, mat4 m2, mat4 dest);
+ CGLM_INLINE void glm_mat4_mulN(mat4 *matrices[], int len, mat4 dest);
+ CGLM_INLINE void glm_mat4_mulv(mat4 m, vec4 v, vec4 dest);
+ CGLM_INLINE void glm_mat4_mulv3(mat4 m, vec3 v, vec3 dest);
+ CGLM_INLINE float glm_mat4_trace(mat4 m);
+ CGLM_INLINE float glm_mat4_trace3(mat4 m);
+ CGLM_INLINE void glm_mat4_quat(mat4 m, versor dest) ;
+ CGLM_INLINE void glm_mat4_transpose_to(mat4 m, mat4 dest);
+ CGLM_INLINE void glm_mat4_transpose(mat4 m);
+ CGLM_INLINE void glm_mat4_scale_p(mat4 m, float s);
+ CGLM_INLINE void glm_mat4_scale(mat4 m, float s);
+ CGLM_INLINE float glm_mat4_det(mat4 mat);
+ CGLM_INLINE void glm_mat4_inv(mat4 mat, mat4 dest);
+ CGLM_INLINE void glm_mat4_inv_fast(mat4 mat, mat4 dest);
+ CGLM_INLINE void glm_mat4_swap_col(mat4 mat, int col1, int col2);
+ CGLM_INLINE void glm_mat4_swap_row(mat4 mat, int row1, int row2);
+ CGLM_INLINE float glm_mat4_rmc(vec4 r, mat4 m, vec4 c);
+ */
+
+#ifndef cglm_mat_h
+#define cglm_mat_h
+
+#include "common.h"
+#include "vec4.h"
+#include "vec3.h"
+
+#ifdef CGLM_SSE_FP
+# include "simd/sse2/mat4.h"
+#endif
+
+#ifdef CGLM_AVX_FP
+# include "simd/avx/mat4.h"
+#endif
+
+#ifdef CGLM_NEON_FP
+# include "simd/neon/mat4.h"
+#endif
+
+#ifdef DEBUG
+# include <assert.h>
+#endif
+
+#define GLM_MAT4_IDENTITY_INIT {{1.0f, 0.0f, 0.0f, 0.0f}, \
+ {0.0f, 1.0f, 0.0f, 0.0f}, \
+ {0.0f, 0.0f, 1.0f, 0.0f}, \
+ {0.0f, 0.0f, 0.0f, 1.0f}}
+
+#define GLM_MAT4_ZERO_INIT {{0.0f, 0.0f, 0.0f, 0.0f}, \
+ {0.0f, 0.0f, 0.0f, 0.0f}, \
+ {0.0f, 0.0f, 0.0f, 0.0f}, \
+ {0.0f, 0.0f, 0.0f, 0.0f}}
+
+/* for C only */
+#define GLM_MAT4_IDENTITY ((mat4)GLM_MAT4_IDENTITY_INIT)
+#define GLM_MAT4_ZERO ((mat4)GLM_MAT4_ZERO_INIT)
+
+/* DEPRECATED! use _copy, _ucopy versions */
+#define glm_mat4_udup(mat, dest) glm_mat4_ucopy(mat, dest)
+#define glm_mat4_dup(mat, dest) glm_mat4_copy(mat, dest)
+
+/* DEPRECATED! default is precise now. */
+#define glm_mat4_inv_precise(mat, dest) glm_mat4_inv(mat, dest)
+
+/*!
+ * @brief copy all members of [mat] to [dest]
+ *
+ * matrix may not be aligned, u stands for unaligned, this may be useful when
+ * copying a matrix from external source e.g. asset importer...
+ *
+ * @param[in] mat source
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_mat4_ucopy(mat4 mat, mat4 dest) {
+ dest[0][0] = mat[0][0]; dest[1][0] = mat[1][0];
+ dest[0][1] = mat[0][1]; dest[1][1] = mat[1][1];
+ dest[0][2] = mat[0][2]; dest[1][2] = mat[1][2];
+ dest[0][3] = mat[0][3]; dest[1][3] = mat[1][3];
+
+ dest[2][0] = mat[2][0]; dest[3][0] = mat[3][0];
+ dest[2][1] = mat[2][1]; dest[3][1] = mat[3][1];
+ dest[2][2] = mat[2][2]; dest[3][2] = mat[3][2];
+ dest[2][3] = mat[2][3]; dest[3][3] = mat[3][3];
+}
+
+/*!
+ * @brief copy all members of [mat] to [dest]
+ *
+ * @param[in] mat source
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_mat4_copy(mat4 mat, mat4 dest) {
+#ifdef __AVX__
+ glmm_store256(dest[0], glmm_load256(mat[0]));
+ glmm_store256(dest[2], glmm_load256(mat[2]));
+#elif defined( __SSE__ ) || defined( __SSE2__ )
+ glmm_store(dest[0], glmm_load(mat[0]));
+ glmm_store(dest[1], glmm_load(mat[1]));
+ glmm_store(dest[2], glmm_load(mat[2]));
+ glmm_store(dest[3], glmm_load(mat[3]));
+#elif defined(CGLM_NEON_FP)
+ vst1q_f32(dest[0], vld1q_f32(mat[0]));
+ vst1q_f32(dest[1], vld1q_f32(mat[1]));
+ vst1q_f32(dest[2], vld1q_f32(mat[2]));
+ vst1q_f32(dest[3], vld1q_f32(mat[3]));
+#else
+ glm_mat4_ucopy(mat, dest);
+#endif
+}
+
+/*!
+ * @brief make given matrix identity. It is identical with below,
+ * but it is more easy to do that with this func especially for members
+ * e.g. glm_mat4_identity(aStruct->aMatrix);
+ *
+ * @code
+ * glm_mat4_copy(GLM_MAT4_IDENTITY, mat); // C only
+ *
+ * // or
+ * mat4 mat = GLM_MAT4_IDENTITY_INIT;
+ * @endcode
+ *
+ * @param[in, out] mat destination
+ */
+CGLM_INLINE
+void
+glm_mat4_identity(mat4 mat) {
+ CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT;
+ glm_mat4_copy(t, mat);
+}
+
+/*!
+ * @brief make given matrix array's each element identity matrix
+ *
+ * @param[in, out] mat matrix array (must be aligned (16/32)
+ * if alignment is not disabled)
+ *
+ * @param[in] count count of matrices
+ */
+CGLM_INLINE
+void
+glm_mat4_identity_array(mat4 * __restrict mat, size_t count) {
+ CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT;
+ size_t i;
+
+ for (i = 0; i < count; i++) {
+ glm_mat4_copy(t, mat[i]);
+ }
+}
+
+/*!
+ * @brief make given matrix zero.
+ *
+ * @param[in, out] mat matrix
+ */
+CGLM_INLINE
+void
+glm_mat4_zero(mat4 mat) {
+#ifdef __AVX__
+ __m256 y0;
+ y0 = _mm256_setzero_ps();
+ glmm_store256(mat[0], y0);
+ glmm_store256(mat[2], y0);
+#elif defined( __SSE__ ) || defined( __SSE2__ )
+ glmm_128 x0;
+ x0 = _mm_setzero_ps();
+ glmm_store(mat[0], x0);
+ glmm_store(mat[1], x0);
+ glmm_store(mat[2], x0);
+ glmm_store(mat[3], x0);
+#elif defined(CGLM_NEON_FP)
+ glmm_128 x0;
+ x0 = vdupq_n_f32(0.0f);
+ vst1q_f32(mat[0], x0);
+ vst1q_f32(mat[1], x0);
+ vst1q_f32(mat[2], x0);
+ vst1q_f32(mat[3], x0);
+#else
+ CGLM_ALIGN_MAT mat4 t = GLM_MAT4_ZERO_INIT;
+ glm_mat4_copy(t, mat);
+#endif
+}
+
+/*!
+ * @brief copy upper-left of mat4 to mat3
+ *
+ * @param[in] mat source
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_mat4_pick3(mat4 mat, mat3 dest) {
+ dest[0][0] = mat[0][0];
+ dest[0][1] = mat[0][1];
+ dest[0][2] = mat[0][2];
+
+ dest[1][0] = mat[1][0];
+ dest[1][1] = mat[1][1];
+ dest[1][2] = mat[1][2];
+
+ dest[2][0] = mat[2][0];
+ dest[2][1] = mat[2][1];
+ dest[2][2] = mat[2][2];
+}
+
+/*!
+ * @brief copy upper-left of mat4 to mat3 (transposed)
+ *
+ * the postfix t stands for transpose
+ *
+ * @param[in] mat source
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_mat4_pick3t(mat4 mat, mat3 dest) {
+ dest[0][0] = mat[0][0];
+ dest[0][1] = mat[1][0];
+ dest[0][2] = mat[2][0];
+
+ dest[1][0] = mat[0][1];
+ dest[1][1] = mat[1][1];
+ dest[1][2] = mat[2][1];
+
+ dest[2][0] = mat[0][2];
+ dest[2][1] = mat[1][2];
+ dest[2][2] = mat[2][2];
+}
+
+/*!
+ * @brief copy mat3 to mat4's upper-left
+ *
+ * @param[in] mat source
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_mat4_ins3(mat3 mat, mat4 dest) {
+ dest[0][0] = mat[0][0];
+ dest[0][1] = mat[0][1];
+ dest[0][2] = mat[0][2];
+
+ dest[1][0] = mat[1][0];
+ dest[1][1] = mat[1][1];
+ dest[1][2] = mat[1][2];
+
+ dest[2][0] = mat[2][0];
+ dest[2][1] = mat[2][1];
+ dest[2][2] = mat[2][2];
+}
+
+/*!
+ * @brief multiply m1 and m2 to dest
+ *
+ * m1, m2 and dest matrices can be same matrix, it is possible to write this:
+ *
+ * @code
+ * mat4 m = GLM_MAT4_IDENTITY_INIT;
+ * glm_mat4_mul(m, m, m);
+ * @endcode
+ *
+ * @param[in] m1 left matrix
+ * @param[in] m2 right matrix
+ * @param[out] dest destination matrix
+ */
+CGLM_INLINE
+void
+glm_mat4_mul(mat4 m1, mat4 m2, mat4 dest) {
+#ifdef __AVX__
+ glm_mat4_mul_avx(m1, m2, dest);
+#elif defined( __SSE__ ) || defined( __SSE2__ )
+ glm_mat4_mul_sse2(m1, m2, dest);
+#elif defined(CGLM_NEON_FP)
+ glm_mat4_mul_neon(m1, m2, dest);
+#else
+ float a00 = m1[0][0], a01 = m1[0][1], a02 = m1[0][2], a03 = m1[0][3],
+ 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], b03 = m2[0][3],
+ b10 = m2[1][0], b11 = m2[1][1], b12 = m2[1][2], b13 = m2[1][3],
+ b20 = m2[2][0], b21 = m2[2][1], b22 = m2[2][2], b23 = m2[2][3],
+ b30 = m2[3][0], b31 = m2[3][1], b32 = m2[3][2], b33 = m2[3][3];
+
+ dest[0][0] = a00 * b00 + a10 * b01 + a20 * b02 + a30 * b03;
+ dest[0][1] = a01 * b00 + a11 * b01 + a21 * b02 + a31 * b03;
+ dest[0][2] = a02 * b00 + a12 * b01 + a22 * b02 + a32 * b03;
+ dest[0][3] = a03 * b00 + a13 * b01 + a23 * b02 + a33 * b03;
+ dest[1][0] = a00 * b10 + a10 * b11 + a20 * b12 + a30 * b13;
+ dest[1][1] = a01 * b10 + a11 * b11 + a21 * b12 + a31 * b13;
+ dest[1][2] = a02 * b10 + a12 * b11 + a22 * b12 + a32 * b13;
+ dest[1][3] = a03 * b10 + a13 * b11 + a23 * b12 + a33 * b13;
+ dest[2][0] = a00 * b20 + a10 * b21 + a20 * b22 + a30 * b23;
+ dest[2][1] = a01 * b20 + a11 * b21 + a21 * b22 + a31 * b23;
+ dest[2][2] = a02 * b20 + a12 * b21 + a22 * b22 + a32 * b23;
+ dest[2][3] = a03 * b20 + a13 * b21 + a23 * b22 + a33 * b23;
+ dest[3][0] = a00 * b30 + a10 * b31 + a20 * b32 + a30 * b33;
+ dest[3][1] = a01 * b30 + a11 * b31 + a21 * b32 + a31 * b33;
+ dest[3][2] = a02 * b30 + a12 * b31 + a22 * b32 + a32 * b33;
+ dest[3][3] = a03 * b30 + a13 * b31 + a23 * b32 + a33 * b33;
+#endif
+}
+
+/*!
+ * @brief mupliply N mat4 matrices and store result in dest
+ *
+ * this function lets you multiply multiple (more than two or more...) matrices
+ * <br><br>multiplication will be done in loop, this may reduce instructions
+ * size but if <b>len</b> is too small then compiler may unroll whole loop,
+ * usage:
+ * @code
+ * mat m1, m2, m3, m4, res;
+ *
+ * glm_mat4_mulN((mat4 *[]){&m1, &m2, &m3, &m4}, 4, res);
+ * @endcode
+ *
+ * @warning matrices parameter is pointer array not mat4 array!
+ *
+ * @param[in] matrices mat4 * array
+ * @param[in] len matrices count
+ * @param[out] dest result
+ */
+CGLM_INLINE
+void
+glm_mat4_mulN(mat4 * __restrict matrices[], uint32_t len, mat4 dest) {
+ uint32_t i;
+
+#ifdef DEBUG
+ assert(len > 1 && "there must be least 2 matrices to go!");
+#endif
+
+ glm_mat4_mul(*matrices[0], *matrices[1], dest);
+
+ for (i = 2; i < len; i++)
+ glm_mat4_mul(dest, *matrices[i], dest);
+}
+
+/*!
+ * @brief multiply mat4 with vec4 (column vector) and store in dest vector
+ *
+ * @param[in] m mat4 (left)
+ * @param[in] v vec4 (right, column vector)
+ * @param[out] dest vec4 (result, column vector)
+ */
+CGLM_INLINE
+void
+glm_mat4_mulv(mat4 m, vec4 v, vec4 dest) {
+#if defined( __SSE__ ) || defined( __SSE2__ )
+ glm_mat4_mulv_sse2(m, v, dest);
+#elif defined(CGLM_NEON_FP)
+ glm_mat4_mulv_neon(m, v, dest);
+#else
+ vec4 res;
+ res[0] = m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2] + m[3][0] * v[3];
+ res[1] = m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2] + m[3][1] * v[3];
+ res[2] = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2] * v[3];
+ res[3] = m[0][3] * v[0] + m[1][3] * v[1] + m[2][3] * v[2] + m[3][3] * v[3];
+ glm_vec4_copy(res, dest);
+#endif
+}
+
+/*!
+ * @brief trace of matrix
+ *
+ * sum of the elements on the main diagonal from upper left to the lower right
+ *
+ * @param[in] m matrix
+ */
+CGLM_INLINE
+float
+glm_mat4_trace(mat4 m) {
+ return m[0][0] + m[1][1] + m[2][2] + m[3][3];
+}
+
+/*!
+ * @brief trace of matrix (rotation part)
+ *
+ * sum of the elements on the main diagonal from upper left to the lower right
+ *
+ * @param[in] m matrix
+ */
+CGLM_INLINE
+float
+glm_mat4_trace3(mat4 m) {
+ return m[0][0] + m[1][1] + m[2][2];
+}
+
+/*!
+ * @brief convert mat4's rotation part to quaternion
+ *
+ * @param[in] m affine matrix
+ * @param[out] dest destination quaternion
+ */
+CGLM_INLINE
+void
+glm_mat4_quat(mat4 m, versor dest) {
+ float trace, r, rinv;
+
+ /* it seems using like m12 instead of m[1][2] causes extra instructions */
+
+ trace = m[0][0] + m[1][1] + m[2][2];
+ if (trace >= 0.0f) {
+ r = sqrtf(1.0f + trace);
+ rinv = 0.5f / r;
+
+ dest[0] = rinv * (m[1][2] - m[2][1]);
+ dest[1] = rinv * (m[2][0] - m[0][2]);
+ dest[2] = rinv * (m[0][1] - m[1][0]);
+ dest[3] = r * 0.5f;
+ } else if (m[0][0] >= m[1][1] && m[0][0] >= m[2][2]) {
+ r = sqrtf(1.0f - m[1][1] - m[2][2] + m[0][0]);
+ rinv = 0.5f / r;
+
+ dest[0] = r * 0.5f;
+ dest[1] = rinv * (m[0][1] + m[1][0]);
+ dest[2] = rinv * (m[0][2] + m[2][0]);
+ dest[3] = rinv * (m[1][2] - m[2][1]);
+ } else if (m[1][1] >= m[2][2]) {
+ r = sqrtf(1.0f - m[0][0] - m[2][2] + m[1][1]);
+ rinv = 0.5f / r;
+
+ dest[0] = rinv * (m[0][1] + m[1][0]);
+ dest[1] = r * 0.5f;
+ dest[2] = rinv * (m[1][2] + m[2][1]);
+ dest[3] = rinv * (m[2][0] - m[0][2]);
+ } else {
+ r = sqrtf(1.0f - m[0][0] - m[1][1] + m[2][2]);
+ rinv = 0.5f / r;
+
+ dest[0] = rinv * (m[0][2] + m[2][0]);
+ dest[1] = rinv * (m[1][2] + m[2][1]);
+ dest[2] = r * 0.5f;
+ dest[3] = rinv * (m[0][1] - m[1][0]);
+ }
+}
+
+/*!
+ * @brief multiply vector with mat4
+ *
+ * actually the result is vec4, after multiplication the last component
+ * is trimmed. if you need it don't use this func.
+ *
+ * @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);
+}
+
+/*!
+ * @brief transpose mat4 and store in dest
+ *
+ * source matrix will not be transposed unless dest is m
+ *
+ * @param[in] m matrix
+ * @param[out] dest result
+ */
+CGLM_INLINE
+void
+glm_mat4_transpose_to(mat4 m, mat4 dest) {
+#if defined( __SSE__ ) || defined( __SSE2__ )
+ glm_mat4_transp_sse2(m, dest);
+#elif defined(CGLM_NEON_FP)
+ glm_mat4_transp_neon(m, dest);
+#else
+ dest[0][0] = m[0][0]; dest[1][0] = m[0][1];
+ dest[0][1] = m[1][0]; dest[1][1] = m[1][1];
+ dest[0][2] = m[2][0]; dest[1][2] = m[2][1];
+ dest[0][3] = m[3][0]; dest[1][3] = m[3][1];
+ dest[2][0] = m[0][2]; dest[3][0] = m[0][3];
+ dest[2][1] = m[1][2]; dest[3][1] = m[1][3];
+ dest[2][2] = m[2][2]; dest[3][2] = m[2][3];
+ dest[2][3] = m[3][2]; dest[3][3] = m[3][3];
+#endif
+}
+
+/*!
+ * @brief tranpose mat4 and store result in same matrix
+ *
+ * @param[in, out] m source and dest
+ */
+CGLM_INLINE
+void
+glm_mat4_transpose(mat4 m) {
+#if defined( __SSE__ ) || defined( __SSE2__ )
+ glm_mat4_transp_sse2(m, m);
+#elif defined(CGLM_NEON_FP)
+ glm_mat4_transp_neon(m, m);
+#else
+ mat4 d;
+ glm_mat4_transpose_to(m, d);
+ glm_mat4_ucopy(d, m);
+#endif
+}
+
+/*!
+ * @brief scale (multiply with scalar) matrix without simd optimization
+ *
+ * multiply matrix with scalar
+ *
+ * @param[in, out] m matrix
+ * @param[in] s scalar
+ */
+CGLM_INLINE
+void
+glm_mat4_scale_p(mat4 m, float s) {
+ m[0][0] *= s; m[0][1] *= s; m[0][2] *= s; m[0][3] *= s;
+ m[1][0] *= s; m[1][1] *= s; m[1][2] *= s; m[1][3] *= s;
+ m[2][0] *= s; m[2][1] *= s; m[2][2] *= s; m[2][3] *= s;
+ m[3][0] *= s; m[3][1] *= s; m[3][2] *= s; m[3][3] *= s;
+}
+
+/*!
+ * @brief scale (multiply with scalar) matrix
+ *
+ * multiply matrix with scalar
+ *
+ * @param[in, out] m matrix
+ * @param[in] s scalar
+ */
+CGLM_INLINE
+void
+glm_mat4_scale(mat4 m, float s) {
+#ifdef __AVX__
+ glm_mat4_scale_avx(m, s);
+#elif defined( __SSE__ ) || defined( __SSE2__ )
+ glm_mat4_scale_sse2(m, s);
+#elif defined(CGLM_NEON_FP)
+ glm_mat4_scale_neon(m, s);
+#else
+ glm_mat4_scale_p(m, s);
+#endif
+}
+
+/*!
+ * @brief mat4 determinant
+ *
+ * @param[in] mat matrix
+ *
+ * @return determinant
+ */
+CGLM_INLINE
+float
+glm_mat4_det(mat4 mat) {
+#if defined( __SSE__ ) || defined( __SSE2__ )
+ return glm_mat4_det_sse2(mat);
+#elif defined(CGLM_NEON_FP)
+ return glm_mat4_det_neon(mat);
+#else
+ /* [square] det(A) = det(At) */
+ float t[6];
+ float a = mat[0][0], b = mat[0][1], c = mat[0][2], d = mat[0][3],
+ e = mat[1][0], f = mat[1][1], g = mat[1][2], h = mat[1][3],
+ i = mat[2][0], j = mat[2][1], k = mat[2][2], l = mat[2][3],
+ m = mat[3][0], n = mat[3][1], o = mat[3][2], p = mat[3][3];
+
+ t[0] = k * p - o * l;
+ t[1] = j * p - n * l;
+ t[2] = j * o - n * k;
+ t[3] = i * p - m * l;
+ t[4] = i * o - m * k;
+ t[5] = i * n - m * j;
+
+ return a * (f * t[0] - g * t[1] + h * t[2])
+ - b * (e * t[0] - g * t[3] + h * t[4])
+ + c * (e * t[1] - f * t[3] + h * t[5])
+ - d * (e * t[2] - f * t[4] + g * t[5]);
+#endif
+}
+
+/*!
+ * @brief inverse mat4 and store in dest
+ *
+ * @param[in] mat matrix
+ * @param[out] dest inverse matrix
+ */
+CGLM_INLINE
+void
+glm_mat4_inv(mat4 mat, mat4 dest) {
+#if defined( __SSE__ ) || defined( __SSE2__ )
+ glm_mat4_inv_sse2(mat, dest);
+#elif defined(CGLM_NEON_FP)
+ glm_mat4_inv_neon(mat, dest);
+#else
+ float t[6];
+ float det;
+ float a = mat[0][0], b = mat[0][1], c = mat[0][2], d = mat[0][3],
+ e = mat[1][0], f = mat[1][1], g = mat[1][2], h = mat[1][3],
+ i = mat[2][0], j = mat[2][1], k = mat[2][2], l = mat[2][3],
+ m = mat[3][0], n = mat[3][1], o = mat[3][2], p = mat[3][3];
+
+ t[0] = k * p - o * l; t[1] = j * p - n * l; t[2] = j * o - n * k;
+ t[3] = i * p - m * l; t[4] = i * o - m * k; t[5] = i * n - m * j;
+
+ dest[0][0] = f * t[0] - g * t[1] + h * t[2];
+ dest[1][0] =-(e * t[0] - g * t[3] + h * t[4]);
+ dest[2][0] = e * t[1] - f * t[3] + h * t[5];
+ dest[3][0] =-(e * t[2] - f * t[4] + g * t[5]);
+
+ dest[0][1] =-(b * t[0] - c * t[1] + d * t[2]);
+ dest[1][1] = a * t[0] - c * t[3] + d * t[4];
+ dest[2][1] =-(a * t[1] - b * t[3] + d * t[5]);
+ dest[3][1] = a * t[2] - b * t[4] + c * t[5];
+
+ t[0] = g * p - o * h; t[1] = f * p - n * h; t[2] = f * o - n * g;
+ t[3] = e * p - m * h; t[4] = e * o - m * g; t[5] = e * n - m * f;
+
+ dest[0][2] = b * t[0] - c * t[1] + d * t[2];
+ dest[1][2] =-(a * t[0] - c * t[3] + d * t[4]);
+ dest[2][2] = a * t[1] - b * t[3] + d * t[5];
+ dest[3][2] =-(a * t[2] - b * t[4] + c * t[5]);
+
+ t[0] = g * l - k * h; t[1] = f * l - j * h; t[2] = f * k - j * g;
+ t[3] = e * l - i * h; t[4] = e * k - i * g; t[5] = e * j - i * f;
+
+ dest[0][3] =-(b * t[0] - c * t[1] + d * t[2]);
+ dest[1][3] = a * t[0] - c * t[3] + d * t[4];
+ dest[2][3] =-(a * t[1] - b * t[3] + d * t[5]);
+ dest[3][3] = a * t[2] - b * t[4] + c * t[5];
+
+ det = 1.0f / (a * dest[0][0] + b * dest[1][0]
+ + c * dest[2][0] + d * dest[3][0]);
+
+ glm_mat4_scale_p(dest, det);
+#endif
+}
+
+/*!
+ * @brief inverse mat4 and store in dest
+ *
+ * this func uses reciprocal approximation without extra corrections
+ * e.g Newton-Raphson. this should work faster than normal,
+ * to get more precise use glm_mat4_inv version.
+ *
+ * NOTE: You will lose precision, glm_mat4_inv is more accurate
+ *
+ * @param[in] mat matrix
+ * @param[out] dest inverse matrix
+ */
+CGLM_INLINE
+void
+glm_mat4_inv_fast(mat4 mat, mat4 dest) {
+#if defined( __SSE__ ) || defined( __SSE2__ )
+ glm_mat4_inv_fast_sse2(mat, dest);
+#else
+ glm_mat4_inv(mat, dest);
+#endif
+}
+
+/*!
+ * @brief swap two matrix columns
+ *
+ * @param[in,out] mat matrix
+ * @param[in] col1 col1
+ * @param[in] col2 col2
+ */
+CGLM_INLINE
+void
+glm_mat4_swap_col(mat4 mat, int col1, int col2) {
+ CGLM_ALIGN(16) vec4 tmp;
+ glm_vec4_copy(mat[col1], tmp);
+ glm_vec4_copy(mat[col2], mat[col1]);
+ glm_vec4_copy(tmp, mat[col2]);
+}
+
+/*!
+ * @brief swap two matrix rows
+ *
+ * @param[in,out] mat matrix
+ * @param[in] row1 row1
+ * @param[in] row2 row2
+ */
+CGLM_INLINE
+void
+glm_mat4_swap_row(mat4 mat, int row1, int row2) {
+ CGLM_ALIGN(16) vec4 tmp;
+ tmp[0] = mat[0][row1];
+ tmp[1] = mat[1][row1];
+ tmp[2] = mat[2][row1];
+ tmp[3] = mat[3][row1];
+
+ mat[0][row1] = mat[0][row2];
+ mat[1][row1] = mat[1][row2];
+ mat[2][row1] = mat[2][row2];
+ mat[3][row1] = mat[3][row2];
+
+ mat[0][row2] = tmp[0];
+ mat[1][row2] = tmp[1];
+ mat[2][row2] = tmp[2];
+ mat[3][row2] = tmp[3];
+}
+
+/*!
+ * @brief helper for R (row vector) * M (matrix) * C (column vector)
+ *
+ * rmc stands for Row * Matrix * Column
+ *
+ * the result is scalar because R * M = Matrix1x4 (row vector),
+ * then Matrix1x4 * Vec4 (column vector) = Matrix1x1 (Scalar)
+ *
+ * @param[in] r row vector or matrix1x4
+ * @param[in] m matrix4x4
+ * @param[in] c column vector or matrix4x1
+ *
+ * @return scalar value e.g. B(s)
+ */
+CGLM_INLINE
+float
+glm_mat4_rmc(vec4 r, mat4 m, vec4 c) {
+ vec4 tmp;
+ glm_mat4_mulv(m, c, tmp);
+ return glm_vec4_dot(r, tmp);
+}
+
+#endif /* cglm_mat_h */
diff --git a/libs/cglm/include/cglm/plane.h b/libs/cglm/include/cglm/plane.h
new file mode 100644
index 0000000..0504373
--- /dev/null
+++ b/libs/cglm/include/cglm/plane.h
@@ -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
+ */
+
+#ifndef cglm_plane_h
+#define cglm_plane_h
+
+#include "common.h"
+#include "vec3.h"
+#include "vec4.h"
+
+/*
+ Plane equation: Ax + By + Cz + D = 0;
+
+ It stored in vec4 as [A, B, C, D]. (A, B, C) is normal and D is distance
+*/
+
+/*
+ Functions:
+ CGLM_INLINE void glm_plane_normalize(vec4 plane);
+ */
+
+/*!
+ * @brief normalizes a plane
+ *
+ * @param[in, out] plane plane to normalize
+ */
+CGLM_INLINE
+void
+glm_plane_normalize(vec4 plane) {
+ float norm;
+
+ if ((norm = glm_vec3_norm(plane)) == 0.0f) {
+ glm_vec4_zero(plane);
+ return;
+ }
+
+ glm_vec4_scale(plane, 1.0f / norm, plane);
+}
+
+#endif /* cglm_plane_h */
diff --git a/libs/cglm/include/cglm/project.h b/libs/cglm/include/cglm/project.h
new file mode 100644
index 0000000..f52d3a0
--- /dev/null
+++ b/libs/cglm/include/cglm/project.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_project_h
+#define cglm_project_h
+
+#include "common.h"
+#include "vec3.h"
+#include "vec4.h"
+#include "mat4.h"
+
+#ifndef CGLM_CLIPSPACE_INCLUDE_ALL
+# if CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_ZO_BIT
+# include "clipspace/project_zo.h"
+# elif CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_NO_BIT
+# include "clipspace/project_no.h"
+# endif
+#else
+# include "clipspace/project_zo.h"
+# include "clipspace/project_no.h"
+#endif
+
+/*!
+ * @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) {
+#if CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_ZO_BIT
+ glm_unprojecti_zo(pos, invMat, vp, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_NO_BIT
+ glm_unprojecti_no(pos, invMat, vp, dest);
+#endif
+}
+
+/*!
+ * @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) {
+#if CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_ZO_BIT
+ glm_project_zo(pos, m, vp, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_NO_BIT
+ glm_project_no(pos, m, vp, dest);
+#endif
+}
+
+/*!
+ * @brief define a picking region
+ *
+ * @param[in] center center [x, y] of a picking region in window coordinates
+ * @param[in] size size [width, height] of the picking region in window coordinates
+ * @param[in] vp viewport as [x, y, width, height]
+ * @param[out] dest projected coordinates
+ */
+CGLM_INLINE
+void
+glm_pickmatrix(vec2 center, vec2 size, vec4 vp, mat4 dest) {
+ mat4 res;
+ vec3 v;
+
+ if (size[0] <= 0.0f || size[1] <= 0.0f)
+ return;
+
+ /* Translate and scale the picked region to the entire window */
+ v[0] = (vp[2] - 2.0f * (center[0] - vp[0])) / size[0];
+ v[1] = (vp[3] - 2.0f * (center[1] - vp[1])) / size[1];
+ v[2] = 0.0f;
+
+ glm_translate_make(res, v);
+
+ v[0] = vp[2] / size[0];
+ v[1] = vp[3] / size[1];
+ v[2] = 1.0f;
+
+ glm_scale(res, v);
+
+ glm_mat4_copy(res, dest);
+}
+
+#endif /* cglm_project_h */
diff --git a/libs/cglm/include/cglm/quat.h b/libs/cglm/include/cglm/quat.h
new file mode 100644
index 0000000..c76fa03
--- /dev/null
+++ b/libs/cglm/include/cglm/quat.h
@@ -0,0 +1,867 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Macros:
+ GLM_QUAT_IDENTITY_INIT
+ GLM_QUAT_IDENTITY
+
+ Functions:
+ CGLM_INLINE void glm_quat_identity(versor q);
+ CGLM_INLINE void glm_quat_init(versor q, float x, float y, float z, float w);
+ CGLM_INLINE void glm_quat(versor q, float angle, float x, float y, float z);
+ CGLM_INLINE void glm_quatv(versor q, float angle, vec3 axis);
+ CGLM_INLINE void glm_quat_copy(versor q, versor dest);
+ CGLM_INLINE void glm_quat_from_vecs(vec3 a, vec3 b, versor dest);
+ CGLM_INLINE float glm_quat_norm(versor q);
+ CGLM_INLINE void glm_quat_normalize(versor q);
+ CGLM_INLINE void glm_quat_normalize_to(versor q, versor dest);
+ CGLM_INLINE float glm_quat_dot(versor p, versor q);
+ CGLM_INLINE void glm_quat_conjugate(versor q, versor dest);
+ CGLM_INLINE void glm_quat_inv(versor q, versor dest);
+ CGLM_INLINE void glm_quat_add(versor p, versor q, versor dest);
+ CGLM_INLINE void glm_quat_sub(versor p, versor q, versor dest);
+ CGLM_INLINE float glm_quat_real(versor q);
+ CGLM_INLINE void glm_quat_imag(versor q, vec3 dest);
+ CGLM_INLINE void glm_quat_imagn(versor q, vec3 dest);
+ CGLM_INLINE float glm_quat_imaglen(versor q);
+ CGLM_INLINE float glm_quat_angle(versor q);
+ CGLM_INLINE void glm_quat_axis(versor q, vec3 dest);
+ CGLM_INLINE void glm_quat_mul(versor p, versor q, versor dest);
+ CGLM_INLINE void glm_quat_mat4(versor q, mat4 dest);
+ CGLM_INLINE void glm_quat_mat4t(versor q, mat4 dest);
+ CGLM_INLINE void glm_quat_mat3(versor q, mat3 dest);
+ CGLM_INLINE void glm_quat_mat3t(versor q, mat3 dest);
+ CGLM_INLINE void glm_quat_lerp(versor from, versor to, float t, versor dest);
+ CGLM_INLINE void glm_quat_lerpc(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_nlerp(versor q, versor r, float t, versor dest);
+ CGLM_INLINE void glm_quat_look(vec3 eye, versor ori, mat4 dest);
+ CGLM_INLINE void glm_quat_for(vec3 dir, vec3 fwd, vec3 up, versor dest);
+ CGLM_INLINE void glm_quat_forp(vec3 from,
+ vec3 to,
+ vec3 fwd,
+ vec3 up,
+ versor dest);
+ CGLM_INLINE void glm_quat_rotatev(versor q, vec3 v, vec3 dest);
+ CGLM_INLINE void glm_quat_rotate(mat4 m, versor q, mat4 dest);
+ */
+
+#ifndef cglm_quat_h
+#define cglm_quat_h
+
+#include "common.h"
+#include "vec3.h"
+#include "vec4.h"
+#include "mat4.h"
+#include "mat3.h"
+#include "affine-mat.h"
+#include "affine.h"
+
+#ifdef CGLM_SSE_FP
+# include "simd/sse2/quat.h"
+#endif
+
+#ifdef CGLM_NEON_FP
+# include "simd/neon/quat.h"
+#endif
+
+CGLM_INLINE void glm_quat_normalize(versor q);
+
+/*
+ * IMPORTANT:
+ * ----------------------------------------------------------------------------
+ * cglm stores quat as [x, y, z, w] since v0.3.6
+ *
+ * it was [w, x, y, z] before v0.3.6 it has been changed to [x, y, z, w]
+ * with v0.3.6 version.
+ * ----------------------------------------------------------------------------
+ */
+
+#define GLM_QUAT_IDENTITY_INIT {0.0f, 0.0f, 0.0f, 1.0f}
+#define GLM_QUAT_IDENTITY ((versor)GLM_QUAT_IDENTITY_INIT)
+
+/*!
+ * @brief makes given quat to identity
+ *
+ * @param[in, out] q quaternion
+ */
+CGLM_INLINE
+void
+glm_quat_identity(versor q) {
+ CGLM_ALIGN(16) versor v = GLM_QUAT_IDENTITY_INIT;
+ glm_vec4_copy(v, q);
+}
+
+/*!
+ * @brief make given quaternion array's each element identity quaternion
+ *
+ * @param[in, out] q quat array (must be aligned (16)
+ * if alignment is not disabled)
+ *
+ * @param[in] count count of quaternions
+ */
+CGLM_INLINE
+void
+glm_quat_identity_array(versor * __restrict q, size_t count) {
+ CGLM_ALIGN(16) versor v = GLM_QUAT_IDENTITY_INIT;
+ size_t i;
+
+ for (i = 0; i < count; i++) {
+ glm_vec4_copy(v, q[i]);
+ }
+}
+
+/*!
+ * @brief inits quaterion with raw values
+ *
+ * @param[out] q quaternion
+ * @param[in] x x
+ * @param[in] y y
+ * @param[in] z z
+ * @param[in] w w (real part)
+ */
+CGLM_INLINE
+void
+glm_quat_init(versor q, float x, float y, float z, float w) {
+ q[0] = x;
+ q[1] = y;
+ q[2] = z;
+ q[3] = w;
+}
+
+/*!
+ * @brief creates NEW quaternion with axis vector
+ *
+ * @param[out] q quaternion
+ * @param[in] angle angle (radians)
+ * @param[in] axis axis
+ */
+CGLM_INLINE
+void
+glm_quatv(versor q, float angle, vec3 axis) {
+ CGLM_ALIGN(8) vec3 k;
+ float a, c, s;
+
+ a = angle * 0.5f;
+ c = cosf(a);
+ s = sinf(a);
+
+ glm_normalize_to(axis, k);
+
+ q[0] = s * k[0];
+ q[1] = s * k[1];
+ q[2] = s * k[2];
+ q[3] = c;
+}
+
+/*!
+ * @brief creates NEW quaternion with individual axis components
+ *
+ * @param[out] q quaternion
+ * @param[in] angle angle (radians)
+ * @param[in] x axis.x
+ * @param[in] y axis.y
+ * @param[in] z axis.z
+ */
+CGLM_INLINE
+void
+glm_quat(versor q, float angle, float x, float y, float z) {
+ CGLM_ALIGN(8) vec3 axis = {x, y, z};
+ glm_quatv(q, angle, axis);
+}
+
+/*!
+ * @brief copy quaternion to another one
+ *
+ * @param[in] q quaternion
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_quat_copy(versor q, versor dest) {
+ glm_vec4_copy(q, dest);
+}
+
+/*!
+ * @brief compute quaternion rotating vector A to vector B
+ *
+ * @param[in] a vec3 (must have unit length)
+ * @param[in] b vec3 (must have unit length)
+ * @param[out] dest quaternion (of unit length)
+ */
+CGLM_INLINE
+void
+glm_quat_from_vecs(vec3 a, vec3 b, versor dest) {
+ CGLM_ALIGN(8) vec3 axis;
+ float cos_theta;
+ float cos_half_theta;
+
+ cos_theta = glm_vec3_dot(a, b);
+ if (cos_theta >= 1.f - GLM_FLT_EPSILON) { /* a ∥ b */
+ glm_quat_identity(dest);
+ return;
+ }
+ if (cos_theta < -1.f + GLM_FLT_EPSILON) { /* angle(a, b) = π */
+ glm_vec3_ortho(a, axis);
+ cos_half_theta = 0.f; /* cos π/2 */
+ } else {
+ glm_vec3_cross(a, b, axis);
+ cos_half_theta = 1.0f + cos_theta; /* cos 0 + cos θ */
+ }
+
+ glm_quat_init(dest, axis[0], axis[1], axis[2], cos_half_theta);
+ glm_quat_normalize(dest);
+}
+
+/*!
+ * @brief returns norm (magnitude) of quaternion
+ *
+ * @param[in] q quaternion
+ */
+CGLM_INLINE
+float
+glm_quat_norm(versor q) {
+ return glm_vec4_norm(q);
+}
+
+/*!
+ * @brief normalize quaternion and store result in dest
+ *
+ * @param[in] q quaternion to normalze
+ * @param[out] dest destination quaternion
+ */
+CGLM_INLINE
+void
+glm_quat_normalize_to(versor q, versor dest) {
+#if defined( __SSE2__ ) || defined( __SSE2__ )
+ __m128 xdot, x0;
+ float dot;
+
+ x0 = glmm_load(q);
+ xdot = glmm_vdot(x0, x0);
+ dot = _mm_cvtss_f32(xdot);
+
+ if (dot <= 0.0f) {
+ glm_quat_identity(dest);
+ return;
+ }
+
+ glmm_store(dest, _mm_div_ps(x0, _mm_sqrt_ps(xdot)));
+#else
+ float dot;
+
+ dot = glm_vec4_norm2(q);
+
+ if (dot <= 0.0f) {
+ glm_quat_identity(dest);
+ return;
+ }
+
+ glm_vec4_scale(q, 1.0f / sqrtf(dot), dest);
+#endif
+}
+
+/*!
+ * @brief normalize quaternion
+ *
+ * @param[in, out] q quaternion
+ */
+CGLM_INLINE
+void
+glm_quat_normalize(versor q) {
+ glm_quat_normalize_to(q, q);
+}
+
+/*!
+ * @brief dot product of two quaternion
+ *
+ * @param[in] p quaternion 1
+ * @param[in] q quaternion 2
+ */
+CGLM_INLINE
+float
+glm_quat_dot(versor p, versor q) {
+ return glm_vec4_dot(p, q);
+}
+
+/*!
+ * @brief conjugate of quaternion
+ *
+ * @param[in] q quaternion
+ * @param[out] dest conjugate
+ */
+CGLM_INLINE
+void
+glm_quat_conjugate(versor q, versor dest) {
+ glm_vec4_negate_to(q, dest);
+ dest[3] = -dest[3];
+}
+
+/*!
+ * @brief inverse of non-zero quaternion
+ *
+ * @param[in] q quaternion
+ * @param[out] dest inverse quaternion
+ */
+CGLM_INLINE
+void
+glm_quat_inv(versor q, versor dest) {
+ CGLM_ALIGN(16) versor conj;
+ glm_quat_conjugate(q, conj);
+ glm_vec4_scale(conj, 1.0f / glm_vec4_norm2(q), dest);
+}
+
+/*!
+ * @brief add (componentwise) two quaternions and store result in dest
+ *
+ * @param[in] p quaternion 1
+ * @param[in] q quaternion 2
+ * @param[out] dest result quaternion
+ */
+CGLM_INLINE
+void
+glm_quat_add(versor p, versor q, versor dest) {
+ glm_vec4_add(p, q, dest);
+}
+
+/*!
+ * @brief subtract (componentwise) two quaternions and store result in dest
+ *
+ * @param[in] p quaternion 1
+ * @param[in] q quaternion 2
+ * @param[out] dest result quaternion
+ */
+CGLM_INLINE
+void
+glm_quat_sub(versor p, versor q, versor dest) {
+ glm_vec4_sub(p, q, dest);
+}
+
+/*!
+ * @brief returns real part of quaternion
+ *
+ * @param[in] q quaternion
+ */
+CGLM_INLINE
+float
+glm_quat_real(versor q) {
+ return q[3];
+}
+
+/*!
+ * @brief returns imaginary part of quaternion
+ *
+ * @param[in] q quaternion
+ * @param[out] dest imag
+ */
+CGLM_INLINE
+void
+glm_quat_imag(versor q, vec3 dest) {
+ dest[0] = q[0];
+ dest[1] = q[1];
+ dest[2] = q[2];
+}
+
+/*!
+ * @brief returns normalized imaginary part of quaternion
+ *
+ * @param[in] q quaternion
+ */
+CGLM_INLINE
+void
+glm_quat_imagn(versor q, vec3 dest) {
+ glm_normalize_to(q, dest);
+}
+
+/*!
+ * @brief returns length of imaginary part of quaternion
+ *
+ * @param[in] q quaternion
+ */
+CGLM_INLINE
+float
+glm_quat_imaglen(versor q) {
+ return glm_vec3_norm(q);
+}
+
+/*!
+ * @brief returns angle of quaternion
+ *
+ * @param[in] q quaternion
+ */
+CGLM_INLINE
+float
+glm_quat_angle(versor q) {
+ /*
+ sin(theta / 2) = length(x*x + y*y + z*z)
+ cos(theta / 2) = w
+ theta = 2 * atan(sin(theta / 2) / cos(theta / 2))
+ */
+ return 2.0f * atan2f(glm_quat_imaglen(q), glm_quat_real(q));
+}
+
+/*!
+ * @brief axis of quaternion
+ *
+ * @param[in] q quaternion
+ * @param[out] dest axis of quaternion
+ */
+CGLM_INLINE
+void
+glm_quat_axis(versor q, vec3 dest) {
+ glm_quat_imagn(q, dest);
+}
+
+/*!
+ * @brief multiplies two quaternion and stores result in dest
+ * this is also called Hamilton Product
+ *
+ * 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);
+#elif defined(CGLM_NEON_FP)
+ glm_quat_mul_neon(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
+}
+
+/*!
+ * @brief convert quaternion to mat4
+ *
+ * @param[in] q quaternion
+ * @param[out] dest result matrix
+ */
+CGLM_INLINE
+void
+glm_quat_mat4(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[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;
+
+ 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 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)
+ * @param[out] dest result quaternion
+ */
+CGLM_INLINE
+void
+glm_quat_lerp(versor from, versor to, float t, versor dest) {
+ glm_vec4_lerp(from, to, t, dest);
+}
+
+/*!
+ * @brief interpolates between two quaternions
+ * using 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_lerpc(versor from, versor to, float t, versor dest) {
+ glm_vec4_lerpc(from, to, t, dest);
+}
+
+/*!
+ * @brief interpolates between two quaternions
+ * taking the shortest rotation path using
+ * normalized linear interpolation (NLERP)
+ *
+ * @param[in] from from
+ * @param[in] to to
+ * @param[in] t interpolant (amount)
+ * @param[out] dest result quaternion
+ */
+CGLM_INLINE
+void
+glm_quat_nlerp(versor from, versor to, float t, versor dest) {
+ versor target;
+ float dot;
+
+ dot = glm_vec4_dot(from, to);
+
+ glm_vec4_scale(to, (dot >= 0) ? 1.0f : -1.0f, target);
+ glm_quat_lerp(from, target, t, dest);
+ glm_quat_normalize(dest);
+}
+
+/*!
+ * @brief interpolates between two quaternions
+ * using spherical linear interpolation (SLERP)
+ *
+ * @param[in] from from
+ * @param[in] to to
+ * @param[in] t amout
+ * @param[out] dest result quaternion
+ */
+CGLM_INLINE
+void
+glm_quat_slerp(versor from, versor to, float t, versor dest) {
+ CGLM_ALIGN(16) vec4 q1, q2;
+ float cosTheta, sinTheta, angle;
+
+ cosTheta = glm_quat_dot(from, to);
+ glm_quat_copy(from, q1);
+
+ if (fabsf(cosTheta) >= 1.0f) {
+ glm_quat_copy(q1, dest);
+ return;
+ }
+
+ if (cosTheta < 0.0f) {
+ glm_vec4_negate(q1);
+ cosTheta = -cosTheta;
+ }
+
+ sinTheta = sqrtf(1.0f - cosTheta * cosTheta);
+
+ /* LERP to avoid zero division */
+ if (fabsf(sinTheta) < 0.001f) {
+ glm_quat_lerp(from, to, t, dest);
+ return;
+ }
+
+ /* SLERP */
+ angle = acosf(cosTheta);
+ glm_vec4_scale(q1, sinf((1.0f - t) * angle), q1);
+ glm_vec4_scale(to, sinf(t * angle), q2);
+
+ glm_vec4_add(q1, q2, q1);
+ glm_vec4_scale(q1, 1.0f / sinTheta, dest);
+}
+
+/*!
+ * @brief creates view matrix using quaternion as camera orientation
+ *
+ * @param[in] eye eye
+ * @param[in] ori orientation in world space as quaternion
+ * @param[out] dest view matrix
+ */
+CGLM_INLINE
+void
+glm_quat_look(vec3 eye, versor ori, mat4 dest) {
+ /* orientation */
+ glm_quat_mat4t(ori, dest);
+
+ /* translate */
+ glm_mat4_mulv3(dest, eye, 1.0f, dest[3]);
+ glm_vec3_negate(dest[3]);
+}
+
+/*!
+ * @brief creates look rotation quaternion
+ *
+ * @param[in] dir direction to look
+ * @param[in] up up vector
+ * @param[out] dest destination quaternion
+ */
+CGLM_INLINE
+void
+glm_quat_for(vec3 dir, vec3 up, versor dest) {
+ CGLM_ALIGN_MAT mat3 m;
+
+ glm_vec3_normalize_to(dir, m[2]);
+
+ /* No need to negate in LH, but we use RH here */
+ glm_vec3_negate(m[2]);
+
+ glm_vec3_crossn(up, m[2], m[0]);
+ glm_vec3_cross(m[2], m[0], m[1]);
+
+ glm_mat3_quat(m, dest);
+}
+
+/*!
+ * @brief creates look rotation quaternion using source and
+ * destination positions p suffix stands for position
+ *
+ * @param[in] from source point
+ * @param[in] to destination point
+ * @param[in] up up vector
+ * @param[out] dest destination quaternion
+ */
+CGLM_INLINE
+void
+glm_quat_forp(vec3 from, vec3 to, vec3 up, versor dest) {
+ CGLM_ALIGN(8) vec3 dir;
+ glm_vec3_sub(to, from, dir);
+ glm_quat_for(dir, 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 */
diff --git a/libs/cglm/include/cglm/ray.h b/libs/cglm/include/cglm/ray.h
new file mode 100644
index 0000000..ced1ad6
--- /dev/null
+++ b/libs/cglm/include/cglm/ray.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE bool glm_line_triangle_intersect(vec3 origin,
+ vec3 direction,
+ vec3 v0,
+ vec3 v1,
+ vec3 v2,
+ float *d);
+*/
+
+#ifndef cglm_ray_h
+#define cglm_ray_h
+
+#include "vec3.h"
+
+/*!
+ * @brief Möller–Trumbore ray-triangle intersection algorithm
+ *
+ * @param[in] origin origin of ray
+ * @param[in] direction direction of ray
+ * @param[in] v0 first vertex of triangle
+ * @param[in] v1 second vertex of triangle
+ * @param[in] v2 third vertex of triangle
+ * @param[in, out] d distance to intersection
+ * @return whether there is intersection
+ */
+
+CGLM_INLINE
+bool
+glm_ray_triangle(vec3 origin,
+ vec3 direction,
+ vec3 v0,
+ vec3 v1,
+ vec3 v2,
+ float *d) {
+ vec3 edge1, edge2, p, t, q;
+ float det, inv_det, u, v, dist;
+ const float epsilon = 0.000001f;
+
+ glm_vec3_sub(v1, v0, edge1);
+ glm_vec3_sub(v2, v0, edge2);
+ glm_vec3_cross(direction, edge2, p);
+
+ det = glm_vec3_dot(edge1, p);
+ if (det > -epsilon && det < epsilon)
+ return false;
+
+ inv_det = 1.0f / det;
+
+ glm_vec3_sub(origin, v0, t);
+
+ u = inv_det * glm_vec3_dot(t, p);
+ if (u < 0.0f || u > 1.0f)
+ return false;
+
+ glm_vec3_cross(t, edge1, q);
+
+ v = inv_det * glm_vec3_dot(direction, q);
+ if (v < 0.0f || u + v > 1.0f)
+ return false;
+
+ dist = inv_det * glm_vec3_dot(edge2, q);
+
+ if (d)
+ *d = dist;
+
+ return dist > epsilon;
+}
+
+#endif
diff --git a/libs/cglm/include/cglm/simd/arm.h b/libs/cglm/include/cglm/simd/arm.h
new file mode 100644
index 0000000..50cec46
--- /dev/null
+++ b/libs/cglm/include/cglm/simd/arm.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_simd_arm_h
+#define cglm_simd_arm_h
+#include "intrin.h"
+#ifdef CGLM_SIMD_ARM
+
+#if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || defined(__aarch64__)
+# define CGLM_ARM64 1
+#endif
+
+#define glmm_load(p) vld1q_f32(p)
+#define glmm_store(p, a) vst1q_f32(p, a)
+
+#define glmm_set1(x) vdupq_n_f32(x)
+#define glmm_128 float32x4_t
+
+#define glmm_splat_x(x) vdupq_lane_f32(vget_low_f32(x), 0)
+#define glmm_splat_y(x) vdupq_lane_f32(vget_low_f32(x), 1)
+#define glmm_splat_z(x) vdupq_lane_f32(vget_high_f32(x), 0)
+#define glmm_splat_w(x) vdupq_lane_f32(vget_high_f32(x), 1)
+
+#define glmm_xor(a, b) \
+ vreinterpretq_f32_s32(veorq_s32(vreinterpretq_s32_f32(a), \
+ vreinterpretq_s32_f32(b)))
+
+#define glmm_swplane(v) vextq_f32(v, v, 2)
+#define glmm_low(x) vget_low_f32(x)
+#define glmm_high(x) vget_high_f32(x)
+
+#define glmm_combine_ll(x, y) vcombine_f32(vget_low_f32(x), vget_low_f32(y))
+#define glmm_combine_hl(x, y) vcombine_f32(vget_high_f32(x), vget_low_f32(y))
+#define glmm_combine_lh(x, y) vcombine_f32(vget_low_f32(x), vget_high_f32(y))
+#define glmm_combine_hh(x, y) vcombine_f32(vget_high_f32(x), vget_high_f32(y))
+
+static inline
+float32x4_t
+glmm_abs(float32x4_t v) {
+ return vabsq_f32(v);
+}
+
+static inline
+float32x4_t
+glmm_vhadd(float32x4_t v) {
+ return vaddq_f32(vaddq_f32(glmm_splat_x(v), glmm_splat_y(v)),
+ vaddq_f32(glmm_splat_z(v), glmm_splat_w(v)));
+ /*
+ this seems slower:
+ v = vaddq_f32(v, vrev64q_f32(v));
+ return vaddq_f32(v, vcombine_f32(vget_high_f32(v), vget_low_f32(v)));
+ */
+}
+
+static inline
+float
+glmm_hadd(float32x4_t v) {
+#if CGLM_ARM64
+ return vaddvq_f32(v);
+#else
+ v = vaddq_f32(v, vrev64q_f32(v));
+ v = vaddq_f32(v, vcombine_f32(vget_high_f32(v), vget_low_f32(v)));
+ return vgetq_lane_f32(v, 0);
+#endif
+}
+
+static inline
+float
+glmm_hmin(float32x4_t v) {
+ float32x2_t t;
+ t = vpmin_f32(vget_low_f32(v), vget_high_f32(v));
+ t = vpmin_f32(t, t);
+ return vget_lane_f32(t, 0);
+}
+
+static inline
+float
+glmm_hmax(float32x4_t v) {
+ float32x2_t t;
+ t = vpmax_f32(vget_low_f32(v), vget_high_f32(v));
+ t = vpmax_f32(t, t);
+ return vget_lane_f32(t, 0);
+}
+
+static inline
+float
+glmm_dot(float32x4_t a, float32x4_t b) {
+ return glmm_hadd(vmulq_f32(a, b));
+}
+
+static inline
+float
+glmm_norm(float32x4_t a) {
+ return sqrtf(glmm_dot(a, a));
+}
+
+static inline
+float
+glmm_norm2(float32x4_t a) {
+ return glmm_dot(a, a);
+}
+
+static inline
+float
+glmm_norm_one(float32x4_t a) {
+ return glmm_hadd(glmm_abs(a));
+}
+
+static inline
+float
+glmm_norm_inf(float32x4_t a) {
+ return glmm_hmax(glmm_abs(a));
+}
+
+static inline
+float32x4_t
+glmm_div(float32x4_t a, float32x4_t b) {
+#if CGLM_ARM64
+ return vdivq_f32(a, b);
+#else
+ /* 2 iterations of Newton-Raphson refinement of reciprocal */
+ float32x4_t r0, r1;
+ r0 = vrecpeq_f32(b);
+ r1 = vrecpsq_f32(r0, b);
+ r0 = vmulq_f32(r1, r0);
+ r1 = vrecpsq_f32(r0, b);
+ r0 = vmulq_f32(r1, r0);
+ return vmulq_f32(a, r0);
+#endif
+}
+
+static inline
+float32x4_t
+glmm_fmadd(float32x4_t a, float32x4_t b, float32x4_t c) {
+#if CGLM_ARM64
+ return vfmaq_f32(c, a, b); /* why vfmaq_f32 is slower than vmlaq_f32 ??? */
+#else
+ return vmlaq_f32(c, a, b);
+#endif
+}
+
+static inline
+float32x4_t
+glmm_fnmadd(float32x4_t a, float32x4_t b, float32x4_t c) {
+#if CGLM_ARM64
+ return vfmsq_f32(c, a, b);
+#else
+ return vmlsq_f32(c, a, b);
+#endif
+}
+
+static inline
+float32x4_t
+glmm_fmsub(float32x4_t a, float32x4_t b, float32x4_t c) {
+#if CGLM_ARM64
+ return vfmsq_f32(c, a, b);
+#else
+ return vmlsq_f32(c, a, b);
+#endif
+}
+
+static inline
+float32x4_t
+glmm_fnmsub(float32x4_t a, float32x4_t b, float32x4_t c) {
+ return vsubq_f32(vdupq_n_f32(0.0f), glmm_fmadd(a, b, c));
+}
+
+#endif
+#endif /* cglm_simd_arm_h */
diff --git a/libs/cglm/include/cglm/simd/avx/affine.h b/libs/cglm/include/cglm/simd/avx/affine.h
new file mode 100644
index 0000000..b02ff0c
--- /dev/null
+++ b/libs/cglm/include/cglm/simd/avx/affine.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_affine_mat_avx_h
+#define cglm_affine_mat_avx_h
+#ifdef __AVX__
+
+#include "../../common.h"
+#include "../intrin.h"
+
+#include <immintrin.h>
+
+CGLM_INLINE
+void
+glm_mul_avx(mat4 m1, mat4 m2, mat4 dest) {
+ /* D = R * L (Column-Major) */
+
+ __m256 y0, y1, y2, y3, y4, y5, y6, y7, y8, y9;
+
+ y0 = glmm_load256(m2[0]); /* h g f e d c b a */
+ y1 = glmm_load256(m2[2]); /* p o n m l k j i */
+
+ y2 = glmm_load256(m1[0]); /* h g f e d c b a */
+ y3 = glmm_load256(m1[2]); /* p o n m l k j i */
+
+ /* 0x03: 0b00000011 */
+ y4 = _mm256_permute2f128_ps(y2, y2, 0x03); /* d c b a h g f e */
+ y5 = _mm256_permute2f128_ps(y3, y3, 0x03); /* l k j i p o n m */
+
+ /* f f f f a a a a */
+ /* h h h h c c c c */
+ /* e e e e b b b b */
+ /* g g g g d d d d */
+ y6 = _mm256_permutevar_ps(y0, _mm256_set_epi32(1, 1, 1, 1, 0, 0, 0, 0));
+ y7 = _mm256_permutevar_ps(y0, _mm256_set_epi32(3, 3, 3, 3, 2, 2, 2, 2));
+ y8 = _mm256_permutevar_ps(y0, _mm256_set_epi32(0, 0, 0, 0, 1, 1, 1, 1));
+ y9 = _mm256_permutevar_ps(y0, _mm256_set_epi32(2, 2, 2, 2, 3, 3, 3, 3));
+
+ glmm_store256(dest[0],
+ _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6),
+ _mm256_mul_ps(y3, y7)),
+ _mm256_add_ps(_mm256_mul_ps(y4, y8),
+ _mm256_mul_ps(y5, y9))));
+
+ /* n n n n i i i i */
+ /* p p p p k k k k */
+ /* m m m m j j j j */
+ /* o o o o l l l l */
+ y6 = _mm256_permutevar_ps(y1, _mm256_set_epi32(1, 1, 1, 1, 0, 0, 0, 0));
+ y7 = _mm256_permutevar_ps(y1, _mm256_set_epi32(3, 3, 3, 3, 2, 2, 2, 2));
+ 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));
+
+ glmm_store256(dest[2],
+ _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6),
+ _mm256_mul_ps(y3, y7)),
+ _mm256_add_ps(_mm256_mul_ps(y4, y8),
+ _mm256_mul_ps(y5, y9))));
+}
+
+#endif
+#endif /* cglm_affine_mat_avx_h */
diff --git a/libs/cglm/include/cglm/simd/avx/mat4.h b/libs/cglm/include/cglm/simd/avx/mat4.h
new file mode 100644
index 0000000..e8c36c8
--- /dev/null
+++ b/libs/cglm/include/cglm/simd/avx/mat4.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_mat_simd_avx_h
+#define cglm_mat_simd_avx_h
+#ifdef __AVX__
+
+#include "../../common.h"
+#include "../intrin.h"
+
+#include <immintrin.h>
+
+CGLM_INLINE
+void
+glm_mat4_scale_avx(mat4 m, float s) {
+ __m256 y0;
+ y0 = _mm256_set1_ps(s);
+
+ glmm_store256(m[0], _mm256_mul_ps(y0, glmm_load256(m[0])));
+ glmm_store256(m[2], _mm256_mul_ps(y0, glmm_load256(m[2])));
+}
+
+CGLM_INLINE
+void
+glm_mat4_mul_avx(mat4 m1, mat4 m2, mat4 dest) {
+ /* D = R * L (Column-Major) */
+
+ __m256 y0, y1, y2, y3, y4, y5, y6, y7, y8, y9;
+
+ y0 = glmm_load256(m2[0]); /* h g f e d c b a */
+ y1 = glmm_load256(m2[2]); /* p o n m l k j i */
+
+ y2 = glmm_load256(m1[0]); /* h g f e d c b a */
+ y3 = glmm_load256(m1[2]); /* p o n m l k j i */
+
+ /* 0x03: 0b00000011 */
+ y4 = _mm256_permute2f128_ps(y2, y2, 0x03); /* d c b a h g f e */
+ y5 = _mm256_permute2f128_ps(y3, y3, 0x03); /* l k j i p o n m */
+
+ /* f f f f a a a a */
+ /* h h h h c c c c */
+ /* e e e e b b b b */
+ /* g g g g d d d d */
+ y6 = _mm256_permutevar_ps(y0, _mm256_set_epi32(1, 1, 1, 1, 0, 0, 0, 0));
+ y7 = _mm256_permutevar_ps(y0, _mm256_set_epi32(3, 3, 3, 3, 2, 2, 2, 2));
+ y8 = _mm256_permutevar_ps(y0, _mm256_set_epi32(0, 0, 0, 0, 1, 1, 1, 1));
+ y9 = _mm256_permutevar_ps(y0, _mm256_set_epi32(2, 2, 2, 2, 3, 3, 3, 3));
+
+ glmm_store256(dest[0],
+ _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6),
+ _mm256_mul_ps(y3, y7)),
+ _mm256_add_ps(_mm256_mul_ps(y4, y8),
+ _mm256_mul_ps(y5, y9))));
+
+ /* n n n n i i i i */
+ /* p p p p k k k k */
+ /* m m m m j j j j */
+ /* o o o o l l l l */
+ y6 = _mm256_permutevar_ps(y1, _mm256_set_epi32(1, 1, 1, 1, 0, 0, 0, 0));
+ y7 = _mm256_permutevar_ps(y1, _mm256_set_epi32(3, 3, 3, 3, 2, 2, 2, 2));
+ 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));
+
+ glmm_store256(dest[2],
+ _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6),
+ _mm256_mul_ps(y3, y7)),
+ _mm256_add_ps(_mm256_mul_ps(y4, y8),
+ _mm256_mul_ps(y5, y9))));
+}
+
+#endif
+#endif /* cglm_mat_simd_avx_h */
diff --git a/libs/cglm/include/cglm/simd/intrin.h b/libs/cglm/include/cglm/simd/intrin.h
new file mode 100644
index 0000000..a6ca5b0
--- /dev/null
+++ b/libs/cglm/include/cglm/simd/intrin.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_intrin_h
+#define cglm_intrin_h
+
+#if defined( _MSC_VER )
+# if (defined(_M_AMD64) || defined(_M_X64)) || _M_IX86_FP == 2
+# ifndef __SSE2__
+# define __SSE2__
+# endif
+# elif _M_IX86_FP == 1
+# ifndef __SSE__
+# define __SSE__
+# endif
+# endif
+/* do not use alignment for older visual studio versions */
+# if _MSC_VER < 1913 /* Visual Studio 2017 version 15.6 */
+# define CGLM_ALL_UNALIGNED
+# endif
+#endif
+
+#if defined( __SSE__ ) || defined( __SSE2__ )
+# include <xmmintrin.h>
+# include <emmintrin.h>
+# define CGLM_SSE_FP 1
+# ifndef CGLM_SIMD_x86
+# define CGLM_SIMD_x86
+# endif
+#endif
+
+#if defined(__SSE3__)
+# include <pmmintrin.h>
+# ifndef CGLM_SIMD_x86
+# define CGLM_SIMD_x86
+# endif
+#endif
+
+#if defined(__SSE4_1__)
+# include <smmintrin.h>
+# ifndef CGLM_SIMD_x86
+# define CGLM_SIMD_x86
+# endif
+#endif
+
+#if defined(__SSE4_2__)
+# include <nmmintrin.h>
+# ifndef CGLM_SIMD_x86
+# define CGLM_SIMD_x86
+# endif
+#endif
+
+#ifdef __AVX__
+# include <immintrin.h>
+# define CGLM_AVX_FP 1
+# ifndef CGLM_SIMD_x86
+# define CGLM_SIMD_x86
+# endif
+#endif
+
+/* ARM Neon */
+#if defined(__ARM_NEON)
+# include <arm_neon.h>
+# if defined(__ARM_NEON_FP)
+# define CGLM_NEON_FP 1
+# ifndef CGLM_SIMD_ARM
+# define CGLM_SIMD_ARM
+# endif
+# endif
+#endif
+
+#if defined(CGLM_SIMD_x86) || defined(CGLM_NEON_FP)
+# ifndef CGLM_SIMD
+# define CGLM_SIMD
+# endif
+#endif
+
+#if defined(CGLM_SIMD_x86)
+# include "x86.h"
+#endif
+
+#if defined(CGLM_SIMD_ARM)
+# include "arm.h"
+#endif
+
+#endif /* cglm_intrin_h */
diff --git a/libs/cglm/include/cglm/simd/neon/affine.h b/libs/cglm/include/cglm/simd/neon/affine.h
new file mode 100644
index 0000000..da0a350
--- /dev/null
+++ b/libs/cglm/include/cglm/simd/neon/affine.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_affine_neon_h
+#define cglm_affine_neon_h
+#if defined(__ARM_NEON_FP)
+
+#include "../../common.h"
+#include "../intrin.h"
+
+CGLM_INLINE
+void
+glm_mul_neon(mat4 m1, mat4 m2, mat4 dest) {
+ /* D = R * L (Column-Major) */
+
+ glmm_128 l, r0, r1, r2, r3, v0, v1, v2, v3;
+
+ l = glmm_load(m1[0]);
+ r0 = glmm_load(m2[0]);
+ r1 = glmm_load(m2[1]);
+ r2 = glmm_load(m2[2]);
+ r3 = glmm_load(m2[3]);
+
+ v0 = vmulq_f32(glmm_splat_x(r0), l);
+ v1 = vmulq_f32(glmm_splat_x(r1), l);
+ v2 = vmulq_f32(glmm_splat_x(r2), l);
+ v3 = vmulq_f32(glmm_splat_x(r3), l);
+
+ l = glmm_load(m1[1]);
+ v0 = glmm_fmadd(glmm_splat_y(r0), l, v0);
+ v1 = glmm_fmadd(glmm_splat_y(r1), l, v1);
+ v2 = glmm_fmadd(glmm_splat_y(r2), l, v2);
+ v3 = glmm_fmadd(glmm_splat_y(r3), l, v3);
+
+ l = glmm_load(m1[2]);
+ v0 = glmm_fmadd(glmm_splat_z(r0), l, v0);
+ v1 = glmm_fmadd(glmm_splat_z(r1), l, v1);
+ v2 = glmm_fmadd(glmm_splat_z(r2), l, v2);
+ v3 = glmm_fmadd(glmm_splat_z(r3), l, v3);
+
+ v3 = glmm_fmadd(glmm_splat_w(r3), glmm_load(m1[3]), v3);
+
+ glmm_store(dest[0], v0);
+ glmm_store(dest[1], v1);
+ glmm_store(dest[2], v2);
+ glmm_store(dest[3], v3);
+}
+
+CGLM_INLINE
+void
+glm_mul_rot_neon(mat4 m1, mat4 m2, mat4 dest) {
+ /* D = R * L (Column-Major) */
+
+ glmm_128 l, r0, r1, r2, v0, v1, v2;
+
+ l = glmm_load(m1[0]);
+ r0 = glmm_load(m2[0]);
+ r1 = glmm_load(m2[1]);
+ r2 = glmm_load(m2[2]);
+
+ v0 = vmulq_f32(glmm_splat_x(r0), l);
+ v1 = vmulq_f32(glmm_splat_x(r1), l);
+ v2 = vmulq_f32(glmm_splat_x(r2), l);
+
+ l = glmm_load(m1[1]);
+ v0 = glmm_fmadd(glmm_splat_y(r0), l, v0);
+ v1 = glmm_fmadd(glmm_splat_y(r1), l, v1);
+ v2 = glmm_fmadd(glmm_splat_y(r2), l, v2);
+
+ l = glmm_load(m1[2]);
+ v0 = glmm_fmadd(glmm_splat_z(r0), l, v0);
+ v1 = glmm_fmadd(glmm_splat_z(r1), l, v1);
+ v2 = glmm_fmadd(glmm_splat_z(r2), l, v2);
+
+ glmm_store(dest[0], v0);
+ glmm_store(dest[1], v1);
+ glmm_store(dest[2], v2);
+ glmm_store(dest[3], glmm_load(m1[3]));
+}
+
+CGLM_INLINE
+void
+glm_inv_tr_neon(mat4 mat) {
+ float32x4x4_t vmat;
+ glmm_128 r0, r1, r2, x0;
+
+ vmat = vld4q_f32(mat[0]);
+ r0 = vmat.val[0];
+ r1 = vmat.val[1];
+ r2 = vmat.val[2];
+
+ x0 = glmm_fmadd(r0, glmm_splat_w(r0),
+ glmm_fmadd(r1, glmm_splat_w(r1),
+ vmulq_f32(r2, glmm_splat_w(r2))));
+ x0 = vnegq_f32(x0);
+
+ glmm_store(mat[0], r0);
+ glmm_store(mat[1], r1);
+ glmm_store(mat[2], r2);
+ glmm_store(mat[3], x0);
+
+ mat[0][3] = 0.0f;
+ mat[1][3] = 0.0f;
+ mat[2][3] = 0.0f;
+ mat[3][3] = 1.0f;
+
+ /* TODO: ?
+ zo = vget_high_f32(r3);
+ vst1_lane_f32(&mat[0][3], zo, 0);
+ vst1_lane_f32(&mat[1][3], zo, 0);
+ vst1_lane_f32(&mat[2][3], zo, 0);
+ vst1_lane_f32(&mat[3][3], zo, 1);
+ */
+}
+
+#endif
+#endif /* cglm_affine_neon_h */
diff --git a/libs/cglm/include/cglm/simd/neon/mat2.h b/libs/cglm/include/cglm/simd/neon/mat2.h
new file mode 100644
index 0000000..471ebea
--- /dev/null
+++ b/libs/cglm/include/cglm/simd/neon/mat2.h
@@ -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
+ */
+
+#ifndef cglm_mat2_neon_h
+#define cglm_mat2_neon_h
+#if defined(__ARM_NEON_FP)
+
+#include "../../common.h"
+#include "../intrin.h"
+
+CGLM_INLINE
+void
+glm_mat2_mul_neon(mat2 m1, mat2 m2, mat2 dest) {
+ float32x4x2_t a1;
+ glmm_128 x0, x1, x2;
+ float32x2_t dc, ba;
+
+ x1 = glmm_load(m1[0]); /* d c b a */
+ x2 = glmm_load(m2[0]); /* h g f e */
+
+ dc = vget_high_f32(x1);
+ ba = vget_low_f32(x1);
+
+ /* g g e e, h h f f */
+ a1 = vtrnq_f32(x2, x2);
+
+ /*
+ dest[0][0] = a * e + c * f;
+ dest[0][1] = b * e + d * f;
+ dest[1][0] = a * g + c * h;
+ dest[1][1] = b * g + d * h;
+ */
+ x0 = glmm_fmadd(vcombine_f32(ba, ba), a1.val[0],
+ vmulq_f32(vcombine_f32(dc, dc), a1.val[1]));
+
+ glmm_store(dest[0], x0);
+}
+
+#endif
+#endif /* cglm_mat2_neon_h */
diff --git a/libs/cglm/include/cglm/simd/neon/mat4.h b/libs/cglm/include/cglm/simd/neon/mat4.h
new file mode 100644
index 0000000..5b9f014
--- /dev/null
+++ b/libs/cglm/include/cglm/simd/neon/mat4.h
@@ -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_mat4_neon_h
+#define cglm_mat4_neon_h
+#if defined(__ARM_NEON_FP)
+
+#include "../../common.h"
+#include "../intrin.h"
+
+CGLM_INLINE
+void
+glm_mat4_scale_neon(mat4 m, float s) {
+ float32x4_t v0;
+
+ v0 = vdupq_n_f32(s);
+
+ vst1q_f32(m[0], vmulq_f32(vld1q_f32(m[0]), v0));
+ vst1q_f32(m[1], vmulq_f32(vld1q_f32(m[1]), v0));
+ vst1q_f32(m[2], vmulq_f32(vld1q_f32(m[2]), v0));
+ vst1q_f32(m[3], vmulq_f32(vld1q_f32(m[3]), v0));
+}
+
+CGLM_INLINE
+void
+glm_mat4_transp_neon(mat4 m, mat4 dest) {
+ float32x4x4_t vmat;
+
+ vmat = vld4q_f32(m[0]);
+
+ vst1q_f32(dest[0], vmat.val[0]);
+ vst1q_f32(dest[1], vmat.val[1]);
+ vst1q_f32(dest[2], vmat.val[2]);
+ vst1q_f32(dest[3], vmat.val[3]);
+}
+
+CGLM_INLINE
+void
+glm_mat4_mul_neon(mat4 m1, mat4 m2, mat4 dest) {
+ /* D = R * L (Column-Major) */
+
+ glmm_128 l, r0, r1, r2, r3, v0, v1, v2, v3;
+
+ l = glmm_load(m1[0]);
+ r0 = glmm_load(m2[0]);
+ r1 = glmm_load(m2[1]);
+ r2 = glmm_load(m2[2]);
+ r3 = glmm_load(m2[3]);
+
+ v0 = vmulq_f32(glmm_splat_x(r0), l);
+ v1 = vmulq_f32(glmm_splat_x(r1), l);
+ v2 = vmulq_f32(glmm_splat_x(r2), l);
+ v3 = vmulq_f32(glmm_splat_x(r3), l);
+
+ l = glmm_load(m1[1]);
+ v0 = glmm_fmadd(glmm_splat_y(r0), l, v0);
+ v1 = glmm_fmadd(glmm_splat_y(r1), l, v1);
+ v2 = glmm_fmadd(glmm_splat_y(r2), l, v2);
+ v3 = glmm_fmadd(glmm_splat_y(r3), l, v3);
+
+ l = glmm_load(m1[2]);
+ v0 = glmm_fmadd(glmm_splat_z(r0), l, v0);
+ v1 = glmm_fmadd(glmm_splat_z(r1), l, v1);
+ v2 = glmm_fmadd(glmm_splat_z(r2), l, v2);
+ v3 = glmm_fmadd(glmm_splat_z(r3), l, v3);
+
+ l = glmm_load(m1[3]);
+ v0 = glmm_fmadd(glmm_splat_w(r0), l, v0);
+ v1 = glmm_fmadd(glmm_splat_w(r1), l, v1);
+ v2 = glmm_fmadd(glmm_splat_w(r2), l, v2);
+ v3 = glmm_fmadd(glmm_splat_w(r3), l, v3);
+
+ glmm_store(dest[0], v0);
+ glmm_store(dest[1], v1);
+ glmm_store(dest[2], v2);
+ glmm_store(dest[3], v3);
+}
+
+CGLM_INLINE
+void
+glm_mat4_mulv_neon(mat4 m, vec4 v, vec4 dest) {
+ float32x4_t l0, l1, l2, l3;
+ float32x2_t vlo, vhi;
+
+ l0 = vld1q_f32(m[0]);
+ l1 = vld1q_f32(m[1]);
+ l2 = vld1q_f32(m[2]);
+ l3 = vld1q_f32(m[3]);
+
+ vlo = vld1_f32(&v[0]);
+ vhi = vld1_f32(&v[2]);
+
+ l0 = vmulq_lane_f32(l0, vlo, 0);
+ l0 = vmlaq_lane_f32(l0, l1, vlo, 1);
+ l0 = vmlaq_lane_f32(l0, l2, vhi, 0);
+ l0 = vmlaq_lane_f32(l0, l3, vhi, 1);
+
+ vst1q_f32(dest, l0);
+}
+
+CGLM_INLINE
+float
+glm_mat4_det_neon(mat4 mat) {
+ float32x4_t r0, r1, r2, r3, x0, x1, x2;
+ float32x2_t ij, op, mn, kl, nn, mm, jj, ii, gh, ef, t12, t34;
+ float32x4x2_t a1;
+ float32x4_t x3 = { 0.f, -0.f, 0.f, -0.f };
+
+ /* 127 <- 0, [square] det(A) = det(At) */
+ r0 = glmm_load(mat[0]); /* d c b a */
+ r1 = vrev64q_f32(glmm_load(mat[1])); /* g h e f */
+ r2 = vrev64q_f32(glmm_load(mat[2])); /* l k i j */
+ r3 = vrev64q_f32(glmm_load(mat[3])); /* o p m n */
+
+ gh = vget_high_f32(r1);
+ ef = vget_low_f32(r1);
+ kl = vget_high_f32(r2);
+ ij = vget_low_f32(r2);
+ op = vget_high_f32(r3);
+ mn = vget_low_f32(r3);
+ mm = vdup_lane_f32(mn, 1);
+ nn = vdup_lane_f32(mn, 0);
+ ii = vdup_lane_f32(ij, 1);
+ jj = vdup_lane_f32(ij, 0);
+
+ /*
+ t[1] = j * p - n * l;
+ t[2] = j * o - n * k;
+ t[3] = i * p - m * l;
+ t[4] = i * o - m * k;
+ */
+ x0 = glmm_fnmadd(vcombine_f32(kl, kl), vcombine_f32(nn, mm),
+ vmulq_f32(vcombine_f32(op, op), vcombine_f32(jj, ii)));
+
+ t12 = vget_low_f32(x0);
+ t34 = vget_high_f32(x0);
+
+ /* 1 3 1 3 2 4 2 4 */
+ a1 = vuzpq_f32(x0, x0);
+
+ /*
+ t[0] = k * p - o * l;
+ t[0] = k * p - o * l;
+ t[5] = i * n - m * j;
+ t[5] = i * n - m * j;
+ */
+ x1 = glmm_fnmadd(vcombine_f32(vdup_lane_f32(kl, 0), jj),
+ vcombine_f32(vdup_lane_f32(op, 1), mm),
+ vmulq_f32(vcombine_f32(vdup_lane_f32(op, 0), nn),
+ vcombine_f32(vdup_lane_f32(kl, 1), ii)));
+
+ /*
+ a * (f * t[0] - g * t[1] + h * t[2])
+ - b * (e * t[0] - g * t[3] + h * t[4])
+ + c * (e * t[1] - f * t[3] + h * t[5])
+ - d * (e * t[2] - f * t[4] + g * t[5])
+ */
+ x2 = glmm_fnmadd(vcombine_f32(vdup_lane_f32(gh, 1), vdup_lane_f32(ef, 0)),
+ vcombine_f32(vget_low_f32(a1.val[0]), t34),
+ vmulq_f32(vcombine_f32(ef, vdup_lane_f32(ef, 1)),
+ vcombine_f32(vget_low_f32(x1), t12)));
+
+ x2 = glmm_fmadd(vcombine_f32(vdup_lane_f32(gh, 0), gh),
+ vcombine_f32(vget_low_f32(a1.val[1]), vget_high_f32(x1)), x2);
+
+ x2 = glmm_xor(x2, x3);
+
+ return glmm_hadd(vmulq_f32(x2, r0));
+}
+
+CGLM_INLINE
+void
+glm_mat4_inv_neon(mat4 mat, mat4 dest) {
+ float32x4_t r0, r1, r2, r3,
+ v0, v1, v2, v3,
+ t0, t1, t2, t3, t4, t5,
+ x0, x1, x2, x3, x4, x5, x6, x7, x8;
+ float32x4x2_t a1;
+ float32x2_t lp, ko, hg, jn, im, fe, ae, bf, cg, dh;
+ float32x4_t x9 = { -0.f, 0.f, -0.f, 0.f };
+
+ x8 = vrev64q_f32(x9);
+
+ /* 127 <- 0 */
+ r0 = glmm_load(mat[0]); /* d c b a */
+ r1 = glmm_load(mat[1]); /* h g f e */
+ r2 = glmm_load(mat[2]); /* l k j i */
+ r3 = glmm_load(mat[3]); /* p o n m */
+
+ /* l p k o, j n i m */
+ a1 = vzipq_f32(r3, r2);
+
+ jn = vget_high_f32(a1.val[0]);
+ im = vget_low_f32(a1.val[0]);
+ lp = vget_high_f32(a1.val[1]);
+ ko = vget_low_f32(a1.val[1]);
+ hg = vget_high_f32(r1);
+
+ x1 = vcombine_f32(vdup_lane_f32(lp, 0), lp); /* l p p p */
+ x2 = vcombine_f32(vdup_lane_f32(ko, 0), ko); /* k o o o */
+ x0 = vcombine_f32(vdup_lane_f32(lp, 1), vdup_lane_f32(hg, 1)); /* h h l l */
+ x3 = vcombine_f32(vdup_lane_f32(ko, 1), vdup_lane_f32(hg, 0)); /* g g k k */
+
+ /* t1[0] = k * p - o * l;
+ t1[0] = k * p - o * l;
+ t2[0] = g * p - o * h;
+ t3[0] = g * l - k * h; */
+ t0 = glmm_fnmadd(x2, x0, vmulq_f32(x3, x1));
+
+ fe = vget_low_f32(r1);
+ x4 = vcombine_f32(vdup_lane_f32(jn, 0), jn); /* j n n n */
+ x5 = vcombine_f32(vdup_lane_f32(jn, 1), vdup_lane_f32(fe, 1)); /* f f j j */
+
+ /* t1[1] = j * p - n * l;
+ t1[1] = j * p - n * l;
+ t2[1] = f * p - n * h;
+ t3[1] = f * l - j * h; */
+ t1 = glmm_fnmadd(x4, x0, vmulq_f32(x5, x1));
+
+ /* t1[2] = j * o - n * k
+ t1[2] = j * o - n * k;
+ t2[2] = f * o - n * g;
+ t3[2] = f * k - j * g; */
+ t2 = glmm_fnmadd(x4, x3, vmulq_f32(x5, x2));
+
+ x6 = vcombine_f32(vdup_lane_f32(im, 1), vdup_lane_f32(fe, 0)); /* e e i i */
+ x7 = vcombine_f32(vdup_lane_f32(im, 0), im); /* i m m m */
+
+ /* t1[3] = i * p - m * l;
+ t1[3] = i * p - m * l;
+ t2[3] = e * p - m * h;
+ t3[3] = e * l - i * h; */
+ t3 = glmm_fnmadd(x7, x0, vmulq_f32(x6, x1));
+
+ /* t1[4] = i * o - m * k;
+ t1[4] = i * o - m * k;
+ t2[4] = e * o - m * g;
+ t3[4] = e * k - i * g; */
+ t4 = glmm_fnmadd(x7, x3, vmulq_f32(x6, x2));
+
+ /* t1[5] = i * n - m * j;
+ t1[5] = i * n - m * j;
+ t2[5] = e * n - m * f;
+ t3[5] = e * j - i * f; */
+ t5 = glmm_fnmadd(x7, x5, vmulq_f32(x6, x4));
+
+ /* h d f b, g c e a */
+ a1 = vtrnq_f32(r0, r1);
+
+ x4 = vrev64q_f32(a1.val[0]); /* c g a e */
+ x5 = vrev64q_f32(a1.val[1]); /* d h b f */
+
+ ae = vget_low_f32(x4);
+ cg = vget_high_f32(x4);
+ bf = vget_low_f32(x5);
+ dh = vget_high_f32(x5);
+
+ x0 = vcombine_f32(ae, vdup_lane_f32(ae, 1)); /* a a a e */
+ x1 = vcombine_f32(bf, vdup_lane_f32(bf, 1)); /* b b b f */
+ x2 = vcombine_f32(cg, vdup_lane_f32(cg, 1)); /* c c c g */
+ x3 = vcombine_f32(dh, vdup_lane_f32(dh, 1)); /* d d d h */
+
+ /*
+ dest[0][0] = f * t1[0] - g * t1[1] + h * t1[2];
+ dest[0][1] =-(b * t1[0] - c * t1[1] + d * t1[2]);
+ dest[0][2] = b * t2[0] - c * t2[1] + d * t2[2];
+ dest[0][3] =-(b * t3[0] - c * t3[1] + d * t3[2]); */
+ v0 = glmm_xor(glmm_fmadd(x3, t2, glmm_fnmadd(x2, t1, vmulq_f32(x1, t0))), x8);
+
+ /*
+ dest[2][0] = e * t1[1] - f * t1[3] + h * t1[5];
+ dest[2][1] =-(a * t1[1] - b * t1[3] + d * t1[5]);
+ dest[2][2] = a * t2[1] - b * t2[3] + d * t2[5];
+ dest[2][3] =-(a * t3[1] - b * t3[3] + d * t3[5]);*/
+ v2 = glmm_xor(glmm_fmadd(x3, t5, glmm_fnmadd(x1, t3, vmulq_f32(x0, t1))), x8);
+
+ /*
+ dest[1][0] =-(e * t1[0] - g * t1[3] + h * t1[4]);
+ dest[1][1] = a * t1[0] - c * t1[3] + d * t1[4];
+ dest[1][2] =-(a * t2[0] - c * t2[3] + d * t2[4]);
+ dest[1][3] = a * t3[0] - c * t3[3] + d * t3[4]; */
+ v1 = glmm_xor(glmm_fmadd(x3, t4, glmm_fnmadd(x2, t3, vmulq_f32(x0, t0))), x9);
+
+ /*
+ dest[3][0] =-(e * t1[2] - f * t1[4] + g * t1[5]);
+ dest[3][1] = a * t1[2] - b * t1[4] + c * t1[5];
+ dest[3][2] =-(a * t2[2] - b * t2[4] + c * t2[5]);
+ dest[3][3] = a * t3[2] - b * t3[4] + c * t3[5]; */
+ v3 = glmm_xor(glmm_fmadd(x2, t5, glmm_fnmadd(x1, t4, vmulq_f32(x0, t2))), x9);
+
+ /* determinant */
+ x0 = vcombine_f32(vget_low_f32(vzipq_f32(v0, v1).val[0]),
+ vget_low_f32(vzipq_f32(v2, v3).val[0]));
+
+ /*
+ x0 = glmm_div(glmm_set1(1.0f), glmm_vhadd(vmulq_f32(x0, r0)));
+
+ glmm_store(dest[0], vmulq_f32(v0, x0));
+ glmm_store(dest[1], vmulq_f32(v1, x0));
+ glmm_store(dest[2], vmulq_f32(v2, x0));
+ glmm_store(dest[3], vmulq_f32(v3, x0));
+ */
+
+ x0 = glmm_vhadd(vmulq_f32(x0, r0));
+
+ glmm_store(dest[0], glmm_div(v0, x0));
+ glmm_store(dest[1], glmm_div(v1, x0));
+ glmm_store(dest[2], glmm_div(v2, x0));
+ glmm_store(dest[3], glmm_div(v3, x0));
+}
+
+#endif
+#endif /* cglm_mat4_neon_h */
diff --git a/libs/cglm/include/cglm/simd/neon/quat.h b/libs/cglm/include/cglm/simd/neon/quat.h
new file mode 100644
index 0000000..f6b9e99
--- /dev/null
+++ b/libs/cglm/include/cglm/simd/neon/quat.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_quat_neon_h
+#define cglm_quat_neon_h
+#if defined(__ARM_NEON_FP)
+
+#include "../../common.h"
+#include "../intrin.h"
+
+CGLM_INLINE
+void
+glm_quat_mul_neon(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
+ */
+
+ glmm_128 xp, xq, xqr, r, x, y, z, s2, s3;
+ glmm_128 s1 = {-0.f, 0.f, 0.f, -0.f};
+ float32x2_t qh, ql;
+
+ xp = glmm_load(p); /* 3 2 1 0 */
+ xq = glmm_load(q);
+
+ r = vmulq_f32(glmm_splat_w(xp), xq);
+ x = glmm_splat_x(xp);
+ y = glmm_splat_y(xp);
+ z = glmm_splat_z(xp);
+
+ ql = vget_high_f32(s1);
+ s3 = vcombine_f32(ql, ql);
+ s2 = vzipq_f32(s3, s3).val[0];
+
+ xqr = vrev64q_f32(xq);
+ qh = vget_high_f32(xqr);
+ ql = vget_low_f32(xqr);
+
+ r = glmm_fmadd(glmm_xor(x, s3), vcombine_f32(qh, ql), r);
+
+ r = glmm_fmadd(glmm_xor(y, s2), vcombine_f32(vget_high_f32(xq),
+ vget_low_f32(xq)), r);
+
+ r = glmm_fmadd(glmm_xor(z, s1), vcombine_f32(ql, qh), r);
+
+ glmm_store(dest, r);
+}
+
+#endif
+#endif /* cglm_quat_neon_h */
diff --git a/libs/cglm/include/cglm/simd/sse2/affine.h b/libs/cglm/include/cglm/simd/sse2/affine.h
new file mode 100644
index 0000000..99edaa0
--- /dev/null
+++ b/libs/cglm/include/cglm/simd/sse2/affine.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_affine_mat_sse2_h
+#define cglm_affine_mat_sse2_h
+#if defined( __SSE__ ) || defined( __SSE2__ )
+
+#include "../../common.h"
+#include "../intrin.h"
+
+CGLM_INLINE
+void
+glm_mul_sse2(mat4 m1, mat4 m2, mat4 dest) {
+ /* D = R * L (Column-Major) */
+ glmm_128 l, r0, r1, r2, r3, v0, v1, v2, v3;
+
+ l = glmm_load(m1[0]);
+ r0 = glmm_load(m2[0]);
+ r1 = glmm_load(m2[1]);
+ r2 = glmm_load(m2[2]);
+ r3 = glmm_load(m2[3]);
+
+ v0 = _mm_mul_ps(glmm_splat_x(r0), l);
+ v1 = _mm_mul_ps(glmm_splat_x(r1), l);
+ v2 = _mm_mul_ps(glmm_splat_x(r2), l);
+ v3 = _mm_mul_ps(glmm_splat_x(r3), l);
+
+ l = glmm_load(m1[1]);
+ v0 = glmm_fmadd(glmm_splat_y(r0), l, v0);
+ v1 = glmm_fmadd(glmm_splat_y(r1), l, v1);
+ v2 = glmm_fmadd(glmm_splat_y(r2), l, v2);
+ v3 = glmm_fmadd(glmm_splat_y(r3), l, v3);
+
+ l = glmm_load(m1[2]);
+ v0 = glmm_fmadd(glmm_splat_z(r0), l, v0);
+ v1 = glmm_fmadd(glmm_splat_z(r1), l, v1);
+ v2 = glmm_fmadd(glmm_splat_z(r2), l, v2);
+ v3 = glmm_fmadd(glmm_splat_z(r3), l, v3);
+
+ l = glmm_load(m1[3]);
+ v3 = glmm_fmadd(glmm_splat_w(r3), l, v3);
+
+ glmm_store(dest[0], v0);
+ glmm_store(dest[1], v1);
+ glmm_store(dest[2], v2);
+ glmm_store(dest[3], v3);
+}
+
+CGLM_INLINE
+void
+glm_mul_rot_sse2(mat4 m1, mat4 m2, mat4 dest) {
+ /* D = R * L (Column-Major) */
+
+ glmm_128 l, r0, r1, r2, v0, v1, v2;
+
+ l = glmm_load(m1[0]);
+ r0 = glmm_load(m2[0]);
+ r1 = glmm_load(m2[1]);
+ r2 = glmm_load(m2[2]);
+
+ v0 = _mm_mul_ps(glmm_splat_x(r0), l);
+ v1 = _mm_mul_ps(glmm_splat_x(r1), l);
+ v2 = _mm_mul_ps(glmm_splat_x(r2), l);
+
+ l = glmm_load(m1[1]);
+ v0 = glmm_fmadd(glmm_splat_y(r0), l, v0);
+ v1 = glmm_fmadd(glmm_splat_y(r1), l, v1);
+ v2 = glmm_fmadd(glmm_splat_y(r2), l, v2);
+
+ l = glmm_load(m1[2]);
+ v0 = glmm_fmadd(glmm_splat_z(r0), l, v0);
+ v1 = glmm_fmadd(glmm_splat_z(r1), l, v1);
+ v2 = glmm_fmadd(glmm_splat_z(r2), l, v2);
+
+ glmm_store(dest[0], v0);
+ glmm_store(dest[1], v1);
+ glmm_store(dest[2], v2);
+ glmm_store(dest[3], glmm_load(m1[3]));
+}
+
+CGLM_INLINE
+void
+glm_inv_tr_sse2(mat4 mat) {
+ __m128 r0, r1, r2, r3, x0, x1, x2, x3, x4, x5;
+
+ r0 = glmm_load(mat[0]);
+ r1 = glmm_load(mat[1]);
+ r2 = glmm_load(mat[2]);
+ r3 = glmm_load(mat[3]);
+ x1 = _mm_set_ps(1.0f, 0.0f, 0.0f, 0.0f);
+
+ _MM_TRANSPOSE4_PS(r0, r1, r2, x1);
+
+ x2 = glmm_shuff1(r3, 0, 0, 0, 0);
+ x3 = glmm_shuff1(r3, 1, 1, 1, 1);
+ x4 = glmm_shuff1(r3, 2, 2, 2, 2);
+ x5 = _mm_set1_ps(-0.f);
+
+ x0 = glmm_fmadd(r0, x2, glmm_fmadd(r1, x3, _mm_mul_ps(r2, x4)));
+ x0 = _mm_xor_ps(x0, x5);
+
+ x0 = _mm_add_ps(x0, x1);
+
+ glmm_store(mat[0], r0);
+ glmm_store(mat[1], r1);
+ glmm_store(mat[2], r2);
+ glmm_store(mat[3], x0);
+}
+
+#endif
+#endif /* cglm_affine_mat_sse2_h */
diff --git a/libs/cglm/include/cglm/simd/sse2/mat2.h b/libs/cglm/include/cglm/simd/sse2/mat2.h
new file mode 100644
index 0000000..31b3a29
--- /dev/null
+++ b/libs/cglm/include/cglm/simd/sse2/mat2.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_mat2_sse_h
+#define cglm_mat2_sse_h
+#if defined( __SSE__ ) || defined( __SSE2__ )
+
+#include "../../common.h"
+#include "../intrin.h"
+
+CGLM_INLINE
+void
+glm_mat2_mul_sse2(mat2 m1, mat2 m2, mat2 dest) {
+ __m128 x0, x1, x2, x3, x4;
+
+ x1 = glmm_load(m1[0]); /* d c b a */
+ x2 = glmm_load(m2[0]); /* h g f e */
+
+ x3 = glmm_shuff1(x2, 2, 2, 0, 0);
+ x4 = glmm_shuff1(x2, 3, 3, 1, 1);
+ x0 = _mm_movelh_ps(x1, x1);
+ x2 = _mm_movehl_ps(x1, x1);
+
+ /*
+ dest[0][0] = a * e + c * f;
+ dest[0][1] = b * e + d * f;
+ dest[1][0] = a * g + c * h;
+ dest[1][1] = b * g + d * h;
+ */
+ x0 = glmm_fmadd(x0, x3, _mm_mul_ps(x2, x4));
+
+ glmm_store(dest[0], x0);
+}
+
+CGLM_INLINE
+void
+glm_mat2_transp_sse2(mat2 m, mat2 dest) {
+ /* d c b a */
+ /* d b c a */
+ glmm_store(dest[0], glmm_shuff1(glmm_load(m[0]), 3, 1, 2, 0));
+}
+
+#endif
+#endif /* cglm_mat2_sse_h */
diff --git a/libs/cglm/include/cglm/simd/sse2/mat3.h b/libs/cglm/include/cglm/simd/sse2/mat3.h
new file mode 100644
index 0000000..f07320c
--- /dev/null
+++ b/libs/cglm/include/cglm/simd/sse2/mat3.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_mat3_sse_h
+#define cglm_mat3_sse_h
+#if defined( __SSE__ ) || defined( __SSE2__ )
+
+#include "../../common.h"
+#include "../intrin.h"
+
+CGLM_INLINE
+void
+glm_mat3_mul_sse2(mat3 m1, mat3 m2, mat3 dest) {
+ __m128 l0, l1, l2, r0, r1, r2, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9;
+
+ l0 = _mm_loadu_ps(m1[0]);
+ l1 = _mm_loadu_ps(&m1[1][1]);
+
+ r0 = _mm_loadu_ps(m2[0]);
+ r1 = _mm_loadu_ps(&m2[1][1]);
+
+ x8 = glmm_shuff1(l0, 0, 2, 1, 0); /* a00 a02 a01 a00 */
+ x1 = glmm_shuff1(r0, 3, 0, 0, 0); /* b10 b00 b00 b00 */
+ x2 = _mm_shuffle_ps(l0, l1, _MM_SHUFFLE(1, 0, 3, 3)); /* a12 a11 a10 a10 */
+ x3 = _mm_shuffle_ps(r0, r1, _MM_SHUFFLE(2, 0, 3, 1)); /* b20 b11 b10 b01 */
+ x0 = _mm_mul_ps(x8, x1);
+
+ x6 = glmm_shuff1(l0, 1, 0, 2, 1); /* a01 a00 a02 a01 */
+ x7 = glmm_shuff1(x3, 3, 3, 1, 1); /* b20 b20 b10 b10 */
+ l2 = _mm_load_ss(&m1[2][2]);
+ r2 = _mm_load_ss(&m2[2][2]);
+ x1 = _mm_mul_ps(x6, x7);
+ l2 = glmm_shuff1(l2, 0, 0, 1, 0); /* a22 a22 0.f a22 */
+ r2 = glmm_shuff1(r2, 0, 0, 1, 0); /* b22 b22 0.f b22 */
+
+ x4 = glmm_shuff1(x2, 0, 3, 2, 0); /* a10 a12 a11 a10 */
+ x5 = glmm_shuff1(x2, 2, 0, 3, 2); /* a11 a10 a12 a11 */
+ x6 = glmm_shuff1(x3, 2, 0, 0, 0); /* b11 b01 b01 b01 */
+ x2 = glmm_shuff1(r1, 3, 3, 0, 0); /* b21 b21 b11 b11 */
+
+ x8 = _mm_unpackhi_ps(x8, x4); /* a10 a00 a12 a02 */
+ x9 = _mm_unpackhi_ps(x7, x2); /* b21 b20 b21 b20 */
+
+ x0 = glmm_fmadd(x4, x6, x0);
+ x1 = glmm_fmadd(x5, x2, x1);
+
+ x2 = _mm_movehl_ps(l2, l1); /* a22 a22 a21 a20 */
+ x3 = glmm_shuff1(x2, 0, 2, 1, 0); /* a20 a22 a21 a20 */
+ x2 = glmm_shuff1(x2, 1, 0, 2, 1); /* a21 a20 a22 a21 */
+ x4 = _mm_shuffle_ps(r0, r1, _MM_SHUFFLE(1, 1, 2, 2)); /* b12 b12 b02 b02 */
+
+ x5 = glmm_shuff1(x4, 3, 0, 0, 0); /* b12 b02 b02 b02 */
+ x4 = _mm_movehl_ps(r2, x4); /* b22 b22 b12 b12 */
+ x0 = glmm_fmadd(x3, x5, x0);
+ x1 = glmm_fmadd(x2, x4, x1);
+
+ /*
+ Dot Product : dest[2][2] = a02 * b20 +
+ a12 * b21 +
+ a22 * b22 +
+ 0 * 00 */
+ x2 = _mm_movelh_ps(x8, l2); /* 0.f a22 a12 a02 */
+ x3 = _mm_movelh_ps(x9, r2); /* 0.f b22 b21 b20 */
+ x2 = glmm_vdots(x2, x3);
+
+ _mm_storeu_ps(&dest[0][0], x0);
+ _mm_storeu_ps(&dest[1][1], x1);
+ _mm_store_ss (&dest[2][2], x2);
+}
+
+#endif
+#endif /* cglm_mat3_sse_h */
diff --git a/libs/cglm/include/cglm/simd/sse2/mat4.h b/libs/cglm/include/cglm/simd/sse2/mat4.h
new file mode 100644
index 0000000..5c78499
--- /dev/null
+++ b/libs/cglm/include/cglm/simd/sse2/mat4.h
@@ -0,0 +1,434 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_mat_sse_h
+#define cglm_mat_sse_h
+#if defined( __SSE__ ) || defined( __SSE2__ )
+
+#include "../../common.h"
+#include "../intrin.h"
+
+#define glm_mat4_inv_precise_sse2(mat, dest) glm_mat4_inv_sse2(mat, dest)
+
+CGLM_INLINE
+void
+glm_mat4_scale_sse2(mat4 m, float s) {
+ __m128 x0;
+ x0 = _mm_set1_ps(s);
+
+ glmm_store(m[0], _mm_mul_ps(glmm_load(m[0]), x0));
+ glmm_store(m[1], _mm_mul_ps(glmm_load(m[1]), x0));
+ glmm_store(m[2], _mm_mul_ps(glmm_load(m[2]), x0));
+ glmm_store(m[3], _mm_mul_ps(glmm_load(m[3]), x0));
+}
+
+CGLM_INLINE
+void
+glm_mat4_transp_sse2(mat4 m, mat4 dest) {
+ __m128 r0, r1, r2, r3;
+
+ r0 = glmm_load(m[0]);
+ r1 = glmm_load(m[1]);
+ r2 = glmm_load(m[2]);
+ r3 = glmm_load(m[3]);
+
+ _MM_TRANSPOSE4_PS(r0, r1, r2, r3);
+
+ glmm_store(dest[0], r0);
+ glmm_store(dest[1], r1);
+ glmm_store(dest[2], r2);
+ glmm_store(dest[3], r3);
+}
+
+CGLM_INLINE
+void
+glm_mat4_mul_sse2(mat4 m1, mat4 m2, mat4 dest) {
+ /* D = R * L (Column-Major) */
+
+ glmm_128 l, r0, r1, r2, r3, v0, v1, v2, v3;
+
+ l = glmm_load(m1[0]);
+ r0 = glmm_load(m2[0]);
+ r1 = glmm_load(m2[1]);
+ r2 = glmm_load(m2[2]);
+ r3 = glmm_load(m2[3]);
+
+ v0 = _mm_mul_ps(glmm_splat_x(r0), l);
+ v1 = _mm_mul_ps(glmm_splat_x(r1), l);
+ v2 = _mm_mul_ps(glmm_splat_x(r2), l);
+ v3 = _mm_mul_ps(glmm_splat_x(r3), l);
+
+ l = glmm_load(m1[1]);
+ v0 = glmm_fmadd(glmm_splat_y(r0), l, v0);
+ v1 = glmm_fmadd(glmm_splat_y(r1), l, v1);
+ v2 = glmm_fmadd(glmm_splat_y(r2), l, v2);
+ v3 = glmm_fmadd(glmm_splat_y(r3), l, v3);
+
+ l = glmm_load(m1[2]);
+ v0 = glmm_fmadd(glmm_splat_z(r0), l, v0);
+ v1 = glmm_fmadd(glmm_splat_z(r1), l, v1);
+ v2 = glmm_fmadd(glmm_splat_z(r2), l, v2);
+ v3 = glmm_fmadd(glmm_splat_z(r3), l, v3);
+
+ l = glmm_load(m1[3]);
+ v0 = glmm_fmadd(glmm_splat_w(r0), l, v0);
+ v1 = glmm_fmadd(glmm_splat_w(r1), l, v1);
+ v2 = glmm_fmadd(glmm_splat_w(r2), l, v2);
+ v3 = glmm_fmadd(glmm_splat_w(r3), l, v3);
+
+ glmm_store(dest[0], v0);
+ glmm_store(dest[1], v1);
+ glmm_store(dest[2], v2);
+ glmm_store(dest[3], v3);
+}
+
+CGLM_INLINE
+void
+glm_mat4_mulv_sse2(mat4 m, vec4 v, vec4 dest) {
+ __m128 x0, x1, m0, m1, m2, m3, v0, v1, v2, v3;
+
+ m0 = glmm_load(m[0]);
+ m1 = glmm_load(m[1]);
+ m2 = glmm_load(m[2]);
+ m3 = glmm_load(m[3]);
+
+ x0 = glmm_load(v);
+ v0 = glmm_splat_x(x0);
+ v1 = glmm_splat_y(x0);
+ v2 = glmm_splat_z(x0);
+ v3 = glmm_splat_w(x0);
+
+ x1 = _mm_mul_ps(m3, v3);
+ x1 = glmm_fmadd(m2, v2, x1);
+ x1 = glmm_fmadd(m1, v1, x1);
+ x1 = glmm_fmadd(m0, v0, x1);
+
+ glmm_store(dest, x1);
+}
+
+CGLM_INLINE
+float
+glm_mat4_det_sse2(mat4 mat) {
+ __m128 r0, r1, r2, r3, x0, x1, x2;
+
+ /* 127 <- 0, [square] det(A) = det(At) */
+ r0 = glmm_load(mat[0]); /* d c b a */
+ r1 = glmm_load(mat[1]); /* h g f e */
+ r2 = glmm_load(mat[2]); /* l k j i */
+ r3 = glmm_load(mat[3]); /* p o n m */
+
+ /*
+ t[1] = j * p - n * l;
+ t[2] = j * o - n * k;
+ t[3] = i * p - m * l;
+ t[4] = i * o - m * k;
+ */
+ x0 = glmm_fnmadd(glmm_shuff1(r3, 0, 0, 1, 1), glmm_shuff1(r2, 2, 3, 2, 3),
+ _mm_mul_ps(glmm_shuff1(r2, 0, 0, 1, 1),
+ glmm_shuff1(r3, 2, 3, 2, 3)));
+ /*
+ t[0] = k * p - o * l;
+ t[0] = k * p - o * l;
+ t[5] = i * n - m * j;
+ t[5] = i * n - m * j;
+ */
+ x1 = glmm_fnmadd(glmm_shuff1(r3, 0, 0, 2, 2), glmm_shuff1(r2, 1, 1, 3, 3),
+ _mm_mul_ps(glmm_shuff1(r2, 0, 0, 2, 2),
+ glmm_shuff1(r3, 1, 1, 3, 3)));
+
+ /*
+ a * (f * t[0] - g * t[1] + h * t[2])
+ - b * (e * t[0] - g * t[3] + h * t[4])
+ + c * (e * t[1] - f * t[3] + h * t[5])
+ - d * (e * t[2] - f * t[4] + g * t[5])
+ */
+ x2 = glmm_fnmadd(glmm_shuff1(r1, 1, 1, 2, 2), glmm_shuff1(x0, 3, 2, 2, 0),
+ _mm_mul_ps(glmm_shuff1(r1, 0, 0, 0, 1),
+ _mm_shuffle_ps(x1, x0, _MM_SHUFFLE(1, 0, 0, 0))));
+ x2 = glmm_fmadd(glmm_shuff1(r1, 2, 3, 3, 3),
+ _mm_shuffle_ps(x0, x1, _MM_SHUFFLE(2, 2, 3, 1)),
+ x2);
+
+ x2 = _mm_xor_ps(x2, _mm_set_ps(-0.f, 0.f, -0.f, 0.f));
+
+ return glmm_hadd(_mm_mul_ps(x2, r0));
+}
+
+CGLM_INLINE
+void
+glm_mat4_inv_fast_sse2(mat4 mat, mat4 dest) {
+ __m128 r0, r1, r2, r3,
+ v0, v1, v2, v3,
+ t0, t1, t2, t3, t4, t5,
+ x0, x1, x2, x3, x4, x5, x6, x7, x8, x9;
+
+ x8 = _mm_set_ps(-0.f, 0.f, -0.f, 0.f);
+ x9 = glmm_shuff1(x8, 2, 1, 2, 1);
+
+ /* 127 <- 0 */
+ r0 = glmm_load(mat[0]); /* d c b a */
+ r1 = glmm_load(mat[1]); /* h g f e */
+ r2 = glmm_load(mat[2]); /* l k j i */
+ r3 = glmm_load(mat[3]); /* p o n m */
+
+ x0 = _mm_movehl_ps(r3, r2); /* p o l k */
+ x3 = _mm_movelh_ps(r2, r3); /* n m j i */
+ x1 = glmm_shuff1(x0, 1, 3, 3 ,3); /* l p p p */
+ x2 = glmm_shuff1(x0, 0, 2, 2, 2); /* k o o o */
+ x4 = glmm_shuff1(x3, 1, 3, 3, 3); /* j n n n */
+ x7 = glmm_shuff1(x3, 0, 2, 2, 2); /* i m m m */
+
+ x6 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(0, 0, 0, 0)); /* e e i i */
+ x5 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(1, 1, 1, 1)); /* f f j j */
+ x3 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(2, 2, 2, 2)); /* g g k k */
+ x0 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(3, 3, 3, 3)); /* h h l l */
+
+ t0 = _mm_mul_ps(x3, x1);
+ t1 = _mm_mul_ps(x5, x1);
+ t2 = _mm_mul_ps(x5, x2);
+ t3 = _mm_mul_ps(x6, x1);
+ t4 = _mm_mul_ps(x6, x2);
+ t5 = _mm_mul_ps(x6, x4);
+
+ /* t1[0] = k * p - o * l;
+ t1[0] = k * p - o * l;
+ t2[0] = g * p - o * h;
+ t3[0] = g * l - k * h; */
+ t0 = glmm_fnmadd(x2, x0, t0);
+
+ /* t1[1] = j * p - n * l;
+ t1[1] = j * p - n * l;
+ t2[1] = f * p - n * h;
+ t3[1] = f * l - j * h; */
+ t1 = glmm_fnmadd(x4, x0, t1);
+
+ /* t1[2] = j * o - n * k
+ t1[2] = j * o - n * k;
+ t2[2] = f * o - n * g;
+ t3[2] = f * k - j * g; */
+ t2 = glmm_fnmadd(x4, x3, t2);
+
+ /* t1[3] = i * p - m * l;
+ t1[3] = i * p - m * l;
+ t2[3] = e * p - m * h;
+ t3[3] = e * l - i * h; */
+ t3 = glmm_fnmadd(x7, x0, t3);
+
+ /* t1[4] = i * o - m * k;
+ t1[4] = i * o - m * k;
+ t2[4] = e * o - m * g;
+ t3[4] = e * k - i * g; */
+ t4 = glmm_fnmadd(x7, x3, t4);
+
+ /* t1[5] = i * n - m * j;
+ t1[5] = i * n - m * j;
+ t2[5] = e * n - m * f;
+ t3[5] = e * j - i * f; */
+ t5 = glmm_fnmadd(x7, x5, t5);
+
+ x4 = _mm_movelh_ps(r0, r1); /* f e b a */
+ x5 = _mm_movehl_ps(r1, r0); /* h g d c */
+
+ x0 = glmm_shuff1(x4, 0, 0, 0, 2); /* a a a e */
+ x1 = glmm_shuff1(x4, 1, 1, 1, 3); /* b b b f */
+ x2 = glmm_shuff1(x5, 0, 0, 0, 2); /* c c c g */
+ x3 = glmm_shuff1(x5, 1, 1, 1, 3); /* d d d h */
+
+ v2 = _mm_mul_ps(x0, t1);
+ v1 = _mm_mul_ps(x0, t0);
+ v3 = _mm_mul_ps(x0, t2);
+ v0 = _mm_mul_ps(x1, t0);
+
+ v2 = glmm_fnmadd(x1, t3, v2);
+ v3 = glmm_fnmadd(x1, t4, v3);
+ v0 = glmm_fnmadd(x2, t1, v0);
+ v1 = glmm_fnmadd(x2, t3, v1);
+
+ v3 = glmm_fmadd(x2, t5, v3);
+ v0 = glmm_fmadd(x3, t2, v0);
+ v2 = glmm_fmadd(x3, t5, v2);
+ v1 = glmm_fmadd(x3, t4, v1);
+
+ /*
+ dest[0][0] = f * t1[0] - g * t1[1] + h * t1[2];
+ dest[0][1] =-(b * t1[0] - c * t1[1] + d * t1[2]);
+ dest[0][2] = b * t2[0] - c * t2[1] + d * t2[2];
+ dest[0][3] =-(b * t3[0] - c * t3[1] + d * t3[2]); */
+ v0 = _mm_xor_ps(v0, x8);
+
+ /*
+ dest[2][0] = e * t1[1] - f * t1[3] + h * t1[5];
+ dest[2][1] =-(a * t1[1] - b * t1[3] + d * t1[5]);
+ dest[2][2] = a * t2[1] - b * t2[3] + d * t2[5];
+ dest[2][3] =-(a * t3[1] - b * t3[3] + d * t3[5]);*/
+ v2 = _mm_xor_ps(v2, x8);
+
+ /*
+ dest[1][0] =-(e * t1[0] - g * t1[3] + h * t1[4]);
+ dest[1][1] = a * t1[0] - c * t1[3] + d * t1[4];
+ dest[1][2] =-(a * t2[0] - c * t2[3] + d * t2[4]);
+ dest[1][3] = a * t3[0] - c * t3[3] + d * t3[4]; */
+ v1 = _mm_xor_ps(v1, x9);
+
+ /*
+ dest[3][0] =-(e * t1[2] - f * t1[4] + g * t1[5]);
+ dest[3][1] = a * t1[2] - b * t1[4] + c * t1[5];
+ dest[3][2] =-(a * t2[2] - b * t2[4] + c * t2[5]);
+ dest[3][3] = a * t3[2] - b * t3[4] + c * t3[5]; */
+ v3 = _mm_xor_ps(v3, x9);
+
+ /* determinant */
+ x0 = _mm_shuffle_ps(v0, v1, _MM_SHUFFLE(0, 0, 0, 0));
+ x1 = _mm_shuffle_ps(v2, v3, _MM_SHUFFLE(0, 0, 0, 0));
+ x0 = _mm_shuffle_ps(x0, x1, _MM_SHUFFLE(2, 0, 2, 0));
+
+ x0 = _mm_rcp_ps(glmm_vhadd(_mm_mul_ps(x0, r0)));
+
+ glmm_store(dest[0], _mm_mul_ps(v0, x0));
+ glmm_store(dest[1], _mm_mul_ps(v1, x0));
+ glmm_store(dest[2], _mm_mul_ps(v2, x0));
+ glmm_store(dest[3], _mm_mul_ps(v3, x0));
+}
+
+CGLM_INLINE
+void
+glm_mat4_inv_sse2(mat4 mat, mat4 dest) {
+ __m128 r0, r1, r2, r3,
+ v0, v1, v2, v3,
+ t0, t1, t2, t3, t4, t5,
+ x0, x1, x2, x3, x4, x5, x6, x7, x8, x9;
+
+ x8 = _mm_set_ps(-0.f, 0.f, -0.f, 0.f);
+ x9 = glmm_shuff1(x8, 2, 1, 2, 1);
+
+ /* 127 <- 0 */
+ r0 = glmm_load(mat[0]); /* d c b a */
+ r1 = glmm_load(mat[1]); /* h g f e */
+ r2 = glmm_load(mat[2]); /* l k j i */
+ r3 = glmm_load(mat[3]); /* p o n m */
+
+ x0 = _mm_movehl_ps(r3, r2); /* p o l k */
+ x3 = _mm_movelh_ps(r2, r3); /* n m j i */
+ x1 = glmm_shuff1(x0, 1, 3, 3 ,3); /* l p p p */
+ x2 = glmm_shuff1(x0, 0, 2, 2, 2); /* k o o o */
+ x4 = glmm_shuff1(x3, 1, 3, 3, 3); /* j n n n */
+ x7 = glmm_shuff1(x3, 0, 2, 2, 2); /* i m m m */
+
+ x6 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(0, 0, 0, 0)); /* e e i i */
+ x5 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(1, 1, 1, 1)); /* f f j j */
+ x3 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(2, 2, 2, 2)); /* g g k k */
+ x0 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(3, 3, 3, 3)); /* h h l l */
+
+ t0 = _mm_mul_ps(x3, x1);
+ t1 = _mm_mul_ps(x5, x1);
+ t2 = _mm_mul_ps(x5, x2);
+ t3 = _mm_mul_ps(x6, x1);
+ t4 = _mm_mul_ps(x6, x2);
+ t5 = _mm_mul_ps(x6, x4);
+
+ /* t1[0] = k * p - o * l;
+ t1[0] = k * p - o * l;
+ t2[0] = g * p - o * h;
+ t3[0] = g * l - k * h; */
+ t0 = glmm_fnmadd(x2, x0, t0);
+
+ /* t1[1] = j * p - n * l;
+ t1[1] = j * p - n * l;
+ t2[1] = f * p - n * h;
+ t3[1] = f * l - j * h; */
+ t1 = glmm_fnmadd(x4, x0, t1);
+
+ /* t1[2] = j * o - n * k
+ t1[2] = j * o - n * k;
+ t2[2] = f * o - n * g;
+ t3[2] = f * k - j * g; */
+ t2 = glmm_fnmadd(x4, x3, t2);
+
+ /* t1[3] = i * p - m * l;
+ t1[3] = i * p - m * l;
+ t2[3] = e * p - m * h;
+ t3[3] = e * l - i * h; */
+ t3 = glmm_fnmadd(x7, x0, t3);
+
+ /* t1[4] = i * o - m * k;
+ t1[4] = i * o - m * k;
+ t2[4] = e * o - m * g;
+ t3[4] = e * k - i * g; */
+ t4 = glmm_fnmadd(x7, x3, t4);
+
+ /* t1[5] = i * n - m * j;
+ t1[5] = i * n - m * j;
+ t2[5] = e * n - m * f;
+ t3[5] = e * j - i * f; */
+ t5 = glmm_fnmadd(x7, x5, t5);
+
+ x4 = _mm_movelh_ps(r0, r1); /* f e b a */
+ x5 = _mm_movehl_ps(r1, r0); /* h g d c */
+
+ x0 = glmm_shuff1(x4, 0, 0, 0, 2); /* a a a e */
+ x1 = glmm_shuff1(x4, 1, 1, 1, 3); /* b b b f */
+ x2 = glmm_shuff1(x5, 0, 0, 0, 2); /* c c c g */
+ x3 = glmm_shuff1(x5, 1, 1, 1, 3); /* d d d h */
+
+ v2 = _mm_mul_ps(x0, t1);
+ v1 = _mm_mul_ps(x0, t0);
+ v3 = _mm_mul_ps(x0, t2);
+ v0 = _mm_mul_ps(x1, t0);
+
+ v2 = glmm_fnmadd(x1, t3, v2);
+ v3 = glmm_fnmadd(x1, t4, v3);
+ v0 = glmm_fnmadd(x2, t1, v0);
+ v1 = glmm_fnmadd(x2, t3, v1);
+
+ v3 = glmm_fmadd(x2, t5, v3);
+ v0 = glmm_fmadd(x3, t2, v0);
+ v2 = glmm_fmadd(x3, t5, v2);
+ v1 = glmm_fmadd(x3, t4, v1);
+
+ /*
+ dest[0][0] = f * t1[0] - g * t1[1] + h * t1[2];
+ dest[0][1] =-(b * t1[0] - c * t1[1] + d * t1[2]);
+ dest[0][2] = b * t2[0] - c * t2[1] + d * t2[2];
+ dest[0][3] =-(b * t3[0] - c * t3[1] + d * t3[2]); */
+ v0 = _mm_xor_ps(v0, x8);
+
+ /*
+ dest[2][0] = e * t1[1] - f * t1[3] + h * t1[5];
+ dest[2][1] =-(a * t1[1] - b * t1[3] + d * t1[5]);
+ dest[2][2] = a * t2[1] - b * t2[3] + d * t2[5];
+ dest[2][3] =-(a * t3[1] - b * t3[3] + d * t3[5]);*/
+ v2 = _mm_xor_ps(v2, x8);
+
+ /*
+ dest[1][0] =-(e * t1[0] - g * t1[3] + h * t1[4]);
+ dest[1][1] = a * t1[0] - c * t1[3] + d * t1[4];
+ dest[1][2] =-(a * t2[0] - c * t2[3] + d * t2[4]);
+ dest[1][3] = a * t3[0] - c * t3[3] + d * t3[4]; */
+ v1 = _mm_xor_ps(v1, x9);
+
+ /*
+ dest[3][0] =-(e * t1[2] - f * t1[4] + g * t1[5]);
+ dest[3][1] = a * t1[2] - b * t1[4] + c * t1[5];
+ dest[3][2] =-(a * t2[2] - b * t2[4] + c * t2[5]);
+ dest[3][3] = a * t3[2] - b * t3[4] + c * t3[5]; */
+ v3 = _mm_xor_ps(v3, x9);
+
+ /* determinant */
+ x0 = _mm_shuffle_ps(v0, v1, _MM_SHUFFLE(0, 0, 0, 0));
+ x1 = _mm_shuffle_ps(v2, v3, _MM_SHUFFLE(0, 0, 0, 0));
+ x0 = _mm_shuffle_ps(x0, x1, _MM_SHUFFLE(2, 0, 2, 0));
+
+ x0 = _mm_div_ps(_mm_set1_ps(1.0f), glmm_vhadd(_mm_mul_ps(x0, r0)));
+
+ glmm_store(dest[0], _mm_mul_ps(v0, x0));
+ glmm_store(dest[1], _mm_mul_ps(v1, x0));
+ glmm_store(dest[2], _mm_mul_ps(v2, x0));
+ glmm_store(dest[3], _mm_mul_ps(v3, x0));
+}
+
+#endif
+#endif /* cglm_mat_sse_h */
diff --git a/libs/cglm/include/cglm/simd/sse2/quat.h b/libs/cglm/include/cglm/simd/sse2/quat.h
new file mode 100644
index 0000000..94850cc
--- /dev/null
+++ b/libs/cglm/include/cglm/simd/sse2/quat.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_quat_simd_h
+#define cglm_quat_simd_h
+#if defined( __SSE__ ) || defined( __SSE2__ )
+
+#include "../../common.h"
+#include "../intrin.h"
+
+CGLM_INLINE
+void
+glm_quat_mul_sse2(versor p, versor q, versor dest) {
+ /*
+ + (a1 b2 + b1 a2 + c1 d2 − d1 c2)i
+ + (a1 c2 − b1 d2 + c1 a2 + d1 b2)j
+ + (a1 d2 + b1 c2 − c1 b2 + d1 a2)k
+ a1 a2 − b1 b2 − c1 c2 − d1 d2
+ */
+
+ __m128 xp, xq, x1, x2, x3, r, x, y, z;
+
+ xp = glmm_load(p); /* 3 2 1 0 */
+ xq = glmm_load(q);
+ x1 = _mm_set_ps(-0.f, 0.f, -0.f, 0.f); /* TODO: _mm_set1_ss() + shuff ? */
+ r = _mm_mul_ps(glmm_splat_w(xp), xq);
+
+ x2 = _mm_unpackhi_ps(x1, x1);
+ x3 = glmm_shuff1(x1, 3, 2, 0, 1);
+ x = glmm_splat_x(xp);
+ y = glmm_splat_y(xp);
+ z = glmm_splat_z(xp);
+
+ x = _mm_xor_ps(x, x1);
+ y = _mm_xor_ps(y, x2);
+ z = _mm_xor_ps(z, x3);
+
+ x1 = glmm_shuff1(xq, 0, 1, 2, 3);
+ x2 = glmm_shuff1(xq, 1, 0, 3, 2);
+ x3 = glmm_shuff1(xq, 2, 3, 0, 1);
+
+ r = glmm_fmadd(x, x1, r);
+ r = glmm_fmadd(y, x2, r);
+ r = glmm_fmadd(z, x3, r);
+
+ glmm_store(dest, r);
+}
+
+#endif
+#endif /* cglm_quat_simd_h */
diff --git a/libs/cglm/include/cglm/simd/x86.h b/libs/cglm/include/cglm/simd/x86.h
new file mode 100644
index 0000000..dbbd0f8
--- /dev/null
+++ b/libs/cglm/include/cglm/simd/x86.h
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_simd_x86_h
+#define cglm_simd_x86_h
+#include "intrin.h"
+#ifdef CGLM_SIMD_x86
+
+#ifdef CGLM_ALL_UNALIGNED
+# define glmm_load(p) _mm_loadu_ps(p)
+# define glmm_store(p, a) _mm_storeu_ps(p, a)
+#else
+# define glmm_load(p) _mm_load_ps(p)
+# define glmm_store(p, a) _mm_store_ps(p, a)
+#endif
+
+#define glmm_set1(x) _mm_set1_ps(x)
+#define glmm_128 __m128
+
+#ifdef CGLM_USE_INT_DOMAIN
+# define glmm_shuff1(xmm, z, y, x, w) \
+ _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(xmm), \
+ _MM_SHUFFLE(z, y, x, w)))
+#else
+# define glmm_shuff1(xmm, z, y, x, w) \
+ _mm_shuffle_ps(xmm, xmm, _MM_SHUFFLE(z, y, x, w))
+#endif
+
+#define glmm_splat(x, lane) glmm_shuff1(x, lane, lane, lane, lane)
+
+#define glmm_splat_x(x) glmm_splat(x, 0)
+#define glmm_splat_y(x) glmm_splat(x, 1)
+#define glmm_splat_z(x) glmm_splat(x, 2)
+#define glmm_splat_w(x) glmm_splat(x, 3)
+
+/* glmm_shuff1x() is DEPRECATED!, use glmm_splat() */
+#define glmm_shuff1x(xmm, x) glmm_shuff1(xmm, x, x, x, x)
+
+#define glmm_shuff2(a, b, z0, y0, x0, w0, z1, y1, x1, w1) \
+ glmm_shuff1(_mm_shuffle_ps(a, b, _MM_SHUFFLE(z0, y0, x0, w0)), \
+ z1, y1, x1, w1)
+
+#ifdef __AVX__
+# ifdef CGLM_ALL_UNALIGNED
+# define glmm_load256(p) _mm256_loadu_ps(p)
+# define glmm_store256(p, a) _mm256_storeu_ps(p, a)
+# else
+# define glmm_load256(p) _mm256_load_ps(p)
+# define glmm_store256(p, a) _mm256_store_ps(p, a)
+# endif
+#endif
+
+static inline
+__m128
+glmm_abs(__m128 x) {
+ return _mm_andnot_ps(_mm_set1_ps(-0.0f), x);
+}
+
+static inline
+__m128
+glmm_vhadd(__m128 v) {
+ __m128 x0;
+ x0 = _mm_add_ps(v, glmm_shuff1(v, 0, 1, 2, 3));
+ x0 = _mm_add_ps(x0, glmm_shuff1(x0, 1, 0, 0, 1));
+ return x0;
+}
+
+static inline
+__m128
+glmm_vhadds(__m128 v) {
+#if defined(__SSE3__)
+ __m128 shuf, sums;
+ shuf = _mm_movehdup_ps(v);
+ sums = _mm_add_ps(v, shuf);
+ shuf = _mm_movehl_ps(shuf, sums);
+ sums = _mm_add_ss(sums, shuf);
+ return sums;
+#else
+ __m128 shuf, sums;
+ shuf = glmm_shuff1(v, 2, 3, 0, 1);
+ sums = _mm_add_ps(v, shuf);
+ shuf = _mm_movehl_ps(shuf, sums);
+ sums = _mm_add_ss(sums, shuf);
+ return sums;
+#endif
+}
+
+static inline
+float
+glmm_hadd(__m128 v) {
+ return _mm_cvtss_f32(glmm_vhadds(v));
+}
+
+static inline
+__m128
+glmm_vhmin(__m128 v) {
+ __m128 x0, x1, x2;
+ x0 = _mm_movehl_ps(v, v); /* [2, 3, 2, 3] */
+ x1 = _mm_min_ps(x0, v); /* [0|2, 1|3, 2|2, 3|3] */
+ x2 = glmm_splat(x1, 1); /* [1|3, 1|3, 1|3, 1|3] */
+ return _mm_min_ss(x1, x2);
+}
+
+static inline
+float
+glmm_hmin(__m128 v) {
+ return _mm_cvtss_f32(glmm_vhmin(v));
+}
+
+static inline
+__m128
+glmm_vhmax(__m128 v) {
+ __m128 x0, x1, x2;
+ x0 = _mm_movehl_ps(v, v); /* [2, 3, 2, 3] */
+ x1 = _mm_max_ps(x0, v); /* [0|2, 1|3, 2|2, 3|3] */
+ x2 = glmm_splat(x1, 1); /* [1|3, 1|3, 1|3, 1|3] */
+ return _mm_max_ss(x1, x2);
+}
+
+static inline
+float
+glmm_hmax(__m128 v) {
+ return _mm_cvtss_f32(glmm_vhmax(v));
+}
+
+static inline
+__m128
+glmm_vdots(__m128 a, __m128 b) {
+#if (defined(__SSE4_1__) || defined(__SSE4_2__)) && defined(CGLM_SSE4_DOT)
+ return _mm_dp_ps(a, b, 0xFF);
+#elif defined(__SSE3__) && defined(CGLM_SSE3_DOT)
+ __m128 x0, x1;
+ x0 = _mm_mul_ps(a, b);
+ x1 = _mm_hadd_ps(x0, x0);
+ return _mm_hadd_ps(x1, x1);
+#else
+ return glmm_vhadds(_mm_mul_ps(a, b));
+#endif
+}
+
+static inline
+__m128
+glmm_vdot(__m128 a, __m128 b) {
+#if (defined(__SSE4_1__) || defined(__SSE4_2__)) && defined(CGLM_SSE4_DOT)
+ return _mm_dp_ps(a, b, 0xFF);
+#elif defined(__SSE3__) && defined(CGLM_SSE3_DOT)
+ __m128 x0, x1;
+ x0 = _mm_mul_ps(a, b);
+ x1 = _mm_hadd_ps(x0, x0);
+ return _mm_hadd_ps(x1, x1);
+#else
+ __m128 x0;
+ x0 = _mm_mul_ps(a, b);
+ x0 = _mm_add_ps(x0, glmm_shuff1(x0, 1, 0, 3, 2));
+ return _mm_add_ps(x0, glmm_shuff1(x0, 0, 1, 0, 1));
+#endif
+}
+
+static inline
+float
+glmm_dot(__m128 a, __m128 b) {
+ return _mm_cvtss_f32(glmm_vdots(a, b));
+}
+
+static inline
+float
+glmm_norm(__m128 a) {
+ return _mm_cvtss_f32(_mm_sqrt_ss(glmm_vhadds(_mm_mul_ps(a, a))));
+}
+
+static inline
+float
+glmm_norm2(__m128 a) {
+ return _mm_cvtss_f32(glmm_vhadds(_mm_mul_ps(a, a)));
+}
+
+static inline
+float
+glmm_norm_one(__m128 a) {
+ return _mm_cvtss_f32(glmm_vhadds(glmm_abs(a)));
+}
+
+static inline
+float
+glmm_norm_inf(__m128 a) {
+ return _mm_cvtss_f32(glmm_vhmax(glmm_abs(a)));
+}
+
+static inline
+__m128
+glmm_load3(float v[3]) {
+ __m128i xy;
+ __m128 z;
+
+ xy = _mm_loadl_epi64(CGLM_CASTPTR_ASSUME_ALIGNED(v, const __m128i));
+ z = _mm_load_ss(&v[2]);
+
+ return _mm_movelh_ps(_mm_castsi128_ps(xy), z);
+}
+
+static inline
+void
+glmm_store3(float v[3], __m128 vx) {
+ _mm_storel_pi(CGLM_CASTPTR_ASSUME_ALIGNED(v, __m64), vx);
+ _mm_store_ss(&v[2], glmm_shuff1(vx, 2, 2, 2, 2));
+}
+
+static inline
+__m128
+glmm_div(__m128 a, __m128 b) {
+ return _mm_div_ps(a, b);
+}
+
+/* enable FMA macro for MSVC? */
+#if defined(_MSC_VER) && !defined(__FMA__) && defined(__AVX2__)
+# define __FMA__ 1
+#endif
+
+static inline
+__m128
+glmm_fmadd(__m128 a, __m128 b, __m128 c) {
+#ifdef __FMA__
+ return _mm_fmadd_ps(a, b, c);
+#else
+ return _mm_add_ps(c, _mm_mul_ps(a, b));
+#endif
+}
+
+static inline
+__m128
+glmm_fnmadd(__m128 a, __m128 b, __m128 c) {
+#ifdef __FMA__
+ return _mm_fnmadd_ps(a, b, c);
+#else
+ return _mm_sub_ps(c, _mm_mul_ps(a, b));
+#endif
+}
+
+static inline
+__m128
+glmm_fmsub(__m128 a, __m128 b, __m128 c) {
+#ifdef __FMA__
+ return _mm_fmsub_ps(a, b, c);
+#else
+ return _mm_sub_ps(_mm_mul_ps(a, b), c);
+#endif
+}
+
+static inline
+__m128
+glmm_fnmsub(__m128 a, __m128 b, __m128 c) {
+#ifdef __FMA__
+ return _mm_fnmsub_ps(a, b, c);
+#else
+ return _mm_xor_ps(_mm_add_ps(_mm_mul_ps(a, b), c), _mm_set1_ps(-0.0f));
+#endif
+}
+
+#if defined(__AVX__)
+static inline
+__m256
+glmm256_fmadd(__m256 a, __m256 b, __m256 c) {
+#ifdef __FMA__
+ return _mm256_fmadd_ps(a, b, c);
+#else
+ return _mm256_add_ps(c, _mm256_mul_ps(a, b));
+#endif
+}
+
+static inline
+__m256
+glmm256_fnmadd(__m256 a, __m256 b, __m256 c) {
+#ifdef __FMA__
+ return _mm256_fnmadd_ps(a, b, c);
+#else
+ return _mm256_sub_ps(c, _mm256_mul_ps(a, b));
+#endif
+}
+
+static inline
+__m256
+glmm256_fmsub(__m256 a, __m256 b, __m256 c) {
+#ifdef __FMA__
+ return _mm256_fmsub_ps(a, b, c);
+#else
+ return _mm256_sub_ps(_mm256_mul_ps(a, b), c);
+#endif
+}
+
+static inline
+__m256
+glmm256_fnmsub(__m256 a, __m256 b, __m256 c) {
+#ifdef __FMA__
+ return _mm256_fmsub_ps(a, b, c);
+#else
+ return _mm256_xor_ps(_mm256_sub_ps(_mm256_mul_ps(a, b), c),
+ _mm256_set1_ps(-0.0f));
+#endif
+}
+#endif
+
+#endif
+#endif /* cglm_simd_x86_h */
diff --git a/libs/cglm/include/cglm/sphere.h b/libs/cglm/include/cglm/sphere.h
new file mode 100644
index 0000000..334b83a
--- /dev/null
+++ b/libs/cglm/include/cglm/sphere.h
@@ -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 */
diff --git a/libs/cglm/include/cglm/struct.h b/libs/cglm/include/cglm/struct.h
new file mode 100644
index 0000000..871525a
--- /dev/null
+++ b/libs/cglm/include/cglm/struct.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_structs_h
+#define cglm_structs_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "cglm.h"
+#include "types-struct.h"
+#include "struct/vec2.h"
+#include "struct/vec3.h"
+#include "struct/vec4.h"
+#include "struct/mat2.h"
+#include "struct/mat3.h"
+#include "struct/mat4.h"
+#include "struct/affine.h"
+#include "struct/frustum.h"
+#include "struct/plane.h"
+#include "struct/box.h"
+#include "struct/color.h"
+#include "struct/io.h"
+#include "struct/cam.h"
+#include "struct/quat.h"
+#include "struct/euler.h"
+#include "struct/project.h"
+#include "struct/sphere.h"
+#include "struct/curve.h"
+#include "struct/affine2d.h"
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglm_structs_h */
diff --git a/libs/cglm/include/cglm/struct/affine.h b/libs/cglm/include/cglm/struct/affine.h
new file mode 100644
index 0000000..cd23226
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/affine.h
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE mat4s glms_translate(mat4s m, vec3s v);
+ CGLM_INLINE mat4s glms_translate_x(mat4s m, float x);
+ CGLM_INLINE mat4s glms_translate_y(mat4s m, float y);
+ CGLM_INLINE mat4s glms_translate_z(mat4s m, float z);
+ CGLM_INLINE mat4s glms_translate_make(vec3s v);
+ CGLM_INLINE mat4s glms_scale_to(mat4s m, vec3s v);
+ CGLM_INLINE mat4s glms_scale_make(vec3s v);
+ CGLM_INLINE mat4s glms_scale(mat4s m, vec3s v);
+ CGLM_INLINE mat4s glms_scale_uni(mat4s m, float s);
+ CGLM_INLINE mat4s glms_rotate_x(mat4s m, float angle);
+ CGLM_INLINE mat4s glms_rotate_y(mat4s m, float angle);
+ CGLM_INLINE mat4s glms_rotate_z(mat4s m, float angle);
+ CGLM_INLINE mat4s glms_rotate_make(float angle, vec3s axis);
+ CGLM_INLINE mat4s glms_rotate(mat4s m, float angle, vec3s axis);
+ CGLM_INLINE mat4s glms_rotate_at(mat4s m, vec3s pivot, float angle, vec3s axis);
+ CGLM_INLINE mat4s glms_rotate_atm(mat4s m, vec3s pivot, float angle, vec3s axis);
+ CGLM_INLINE vec3s glms_decompose_scalev(mat4s m);
+ CGLM_INLINE bool glms_uniscaled(mat4s m);
+ CGLM_INLINE void glms_decompose_rs(mat4s m, mat4s * r, vec3s * s);
+ CGLM_INLINE void glms_decompose(mat4s m, vec4s t, mat4s * r, vec3s * s);
+ */
+
+#ifndef cglms_affines_h
+#define cglms_affines_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../affine.h"
+#include "vec3.h"
+#include "vec4.h"
+#include "mat4.h"
+
+/*!
+ * @brief translate existing transform matrix by v vector
+ * and stores result in same matrix
+ *
+ * @param[in] m affine transfrom
+ * @param[in] v translate vector [x, y, z]
+ * @returns affine transfrom
+ */
+CGLM_INLINE
+mat4s
+glms_translate(mat4s m, vec3s v) {
+ glm_translate(m.raw, v.raw);
+ return m;
+}
+
+/*!
+ * @brief translate existing transform matrix by x factor
+ *
+ * @param[in] m affine transfrom
+ * @param[in] x x factor
+ * @returns affine transfrom
+ */
+CGLM_INLINE
+mat4s
+glms_translate_x(mat4s m, float x) {
+ glm_translate_x(m.raw, x);
+ return m;
+}
+
+/*!
+ * @brief translate existing transform matrix by y factor
+ *
+ * @param[in] m affine transfrom
+ * @param[in] y y factor
+ * @returns affine transfrom
+ */
+CGLM_INLINE
+mat4s
+glms_translate_y(mat4s m, float y) {
+ glm_translate_y(m.raw, y);
+ return m;
+}
+
+/*!
+ * @brief translate existing transform matrix by z factor
+ *
+ * @param[in] m affine transfrom
+ * @param[in] z z factor
+ * @returns affine transfrom
+ */
+CGLM_INLINE
+mat4s
+glms_translate_z(mat4s m, float z) {
+ glm_translate_z(m.raw, z);
+ return m;
+}
+
+/*!
+ * @brief creates NEW translate transform matrix by v vector
+ *
+ * @param[in] v translate vector [x, y, z]
+ * @returns affine transfrom
+ */
+CGLM_INLINE
+mat4s
+glms_translate_make(vec3s v) {
+ mat4s m;
+ glm_translate_make(m.raw, v.raw);
+ return m;
+}
+
+/*!
+ * @brief creates NEW scale matrix by v vector
+ *
+ * @param[in] v scale vector [x, y, z]
+ * @returns affine transfrom
+ */
+CGLM_INLINE
+mat4s
+glms_scale_make(vec3s v) {
+ mat4s m;
+ glm_scale_make(m.raw, v.raw);
+ return m;
+}
+
+/*!
+ * @brief scales existing transform matrix by v vector
+ * and stores result in same matrix
+ *
+ * @param[in] m affine transfrom
+ * @param[in] v scale vector [x, y, z]
+ * @returns affine transfrom
+ */
+CGLM_INLINE
+mat4s
+glms_scale(mat4s m, vec3s v) {
+ mat4s r;
+ glm_scale_to(m.raw, v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief applies uniform scale to existing transform matrix v = [s, s, s]
+ * and stores result in same matrix
+ *
+ * @param[in] m affine transfrom
+ * @param[in] s scale factor
+ * @returns affine transfrom
+ */
+CGLM_INLINE
+mat4s
+glms_scale_uni(mat4s m, float s) {
+ glm_scale_uni(m.raw, s);
+ return m;
+}
+
+/*!
+ * @brief rotate existing transform matrix around X axis by angle
+ * and store result in dest
+ *
+ * @param[in] m affine transfrom
+ * @param[in] angle angle (radians)
+ * @returns rotated matrix
+ */
+CGLM_INLINE
+mat4s
+glms_rotate_x(mat4s m, float angle) {
+ mat4s r;
+ glm_rotate_x(m.raw, angle, r.raw);
+ return r;
+}
+
+/*!
+ * @brief rotate existing transform matrix around Y axis by angle
+ * and store result in dest
+ *
+ * @param[in] m affine transfrom
+ * @param[in] angle angle (radians)
+ * @returns rotated matrix
+ */
+CGLM_INLINE
+mat4s
+glms_rotate_y(mat4s m, float angle) {
+ mat4s r;
+ glm_rotate_y(m.raw, angle, r.raw);
+ return r;
+}
+
+/*!
+ * @brief rotate existing transform matrix around Z axis by angle
+ * and store result in dest
+ *
+ * @param[in] m affine transfrom
+ * @param[in] angle angle (radians)
+ * @returns rotated matrix
+ */
+CGLM_INLINE
+mat4s
+glms_rotate_z(mat4s m, float angle) {
+ mat4s r;
+ glm_rotate_z(m.raw, angle, r.raw);
+ return r;
+}
+
+/*!
+ * @brief creates NEW rotation matrix by angle and axis
+ *
+ * axis will be normalized so you don't need to normalize it
+ *
+ * @param[in] angle angle (radians)
+ * @param[in] axis axis
+ * @returns affine transfrom
+ */
+CGLM_INLINE
+mat4s
+glms_rotate_make(float angle, vec3s axis) {
+ mat4s m;
+ glm_rotate_make(m.raw, angle, axis.raw);
+ return m;
+}
+
+/*!
+ * @brief rotate existing transform matrix around given axis by angle
+ *
+ * @param[in] m affine transfrom
+ * @param[in] angle angle (radians)
+ * @param[in] axis axis
+ * @returns affine transfrom
+ */
+CGLM_INLINE
+mat4s
+glms_rotate(mat4s m, float angle, vec3s axis) {
+ glm_rotate(m.raw, angle, axis.raw);
+ return m;
+}
+
+/*!
+ * @brief rotate existing transform
+ * around given axis by angle at given pivot point (rotation center)
+ *
+ * @param[in] m affine transfrom
+ * @param[in] pivot rotation center
+ * @param[in] angle angle (radians)
+ * @param[in] axis axis
+ * @returns affine transfrom
+ */
+CGLM_INLINE
+mat4s
+glms_rotate_at(mat4s m, vec3s pivot, float angle, vec3s axis) {
+ glm_rotate_at(m.raw, pivot.raw, angle, axis.raw);
+ return m;
+}
+
+/*!
+ * @brief creates NEW rotation matrix by angle and axis at given point
+ *
+ * this creates rotation matrix, it assumes you don't have a matrix
+ *
+ * this should work faster than glm_rotate_at because it reduces
+ * one glm_translate.
+ *
+ * @param[in] m affine transfrom
+ * @param[in] pivot rotation center
+ * @param[in] angle angle (radians)
+ * @param[in] axis axis
+ * @returns affine transfrom
+ */
+CGLM_INLINE
+mat4s
+glms_rotate_atm(mat4s m, vec3s pivot, float angle, vec3s axis) {
+ glm_rotate_atm(m.raw, pivot.raw, angle, axis.raw);
+ return m;
+}
+
+/*!
+ * @brief decompose scale vector
+ *
+ * @param[in] m affine transform
+ * @returns scale vector (Sx, Sy, Sz)
+ */
+CGLM_INLINE
+vec3s
+glms_decompose_scalev(mat4s m) {
+ vec3s r;
+ glm_decompose_scalev(m.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief returns true if matrix is uniform scaled. This is helpful for
+ * creating normal matrix.
+ *
+ * @param[in] m m
+ *
+ * @return boolean
+ */
+CGLM_INLINE
+bool
+glms_uniscaled(mat4s m) {
+ return glm_uniscaled(m.raw);
+}
+
+/*!
+ * @brief decompose rotation matrix (mat4) and scale vector [Sx, Sy, Sz]
+ * DON'T pass projected matrix here
+ *
+ * @param[in] m affine transform
+ * @param[out] r rotation matrix
+ * @param[out] s scale matrix
+ */
+CGLM_INLINE
+void
+glms_decompose_rs(mat4s m, mat4s * __restrict r, vec3s * __restrict s) {
+ glm_decompose_rs(m.raw, r->raw, s->raw);
+}
+
+/*!
+ * @brief decompose affine transform, TODO: extract shear factors.
+ * DON'T pass projected matrix here
+ *
+ * @param[in] m affine transfrom
+ * @param[out] t translation vector
+ * @param[out] r rotation matrix (mat4)
+ * @param[out] s scaling vector [X, Y, Z]
+ */
+CGLM_INLINE
+void
+glms_decompose(mat4s m, vec4s * __restrict t, mat4s * __restrict r, vec3s * __restrict s) {
+ glm_decompose(m.raw, t->raw, r->raw, s->raw);
+}
+
+#endif /* cglms_affines_h */
diff --git a/libs/cglm/include/cglm/struct/affine2d.h b/libs/cglm/include/cglm/struct/affine2d.h
new file mode 100644
index 0000000..412bd47
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/affine2d.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE mat3s glms_translate2d(mat3 m, vec2 v)
+ CGLM_INLINE mat3s glms_translate2d_x(mat3s m, float x)
+ CGLM_INLINE mat3s glms_translate2d_y(mat3s m, float y)
+ CGLM_INLINE mat3s glms_translate2d_make(vec2s v)
+ CGLM_INLINE mat3s glms_scale2d_make(vec2s v)
+ CGLM_INLINE mat3s glms_scale2d(mat3s m, vec2s v)
+ CGLM_INLINE mat3s glms_scale2d_uni(mat3s m, float s)
+ CGLM_INLINE mat3s glms_rotate2d_make(float angle)
+ CGLM_INLINE mat3s glms_rotate2d(mat3s m, float angle)
+ CGLM_INLINE mat3s glms_rotate2d_to(mat3s m, float angle)
+ */
+
+#ifndef cglms_affine2ds_h
+#define cglms_affine2ds_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../affine2d.h"
+#include "vec3.h"
+#include "mat3.h"
+
+/*!
+ * @brief translate existing 2d transform matrix by v vector
+ * and stores result in same matrix
+ *
+ * @param[in] m affine transfrom
+ * @param[in] v translate vector [x, y]
+ * @returns affine transfrom
+ */
+CGLM_INLINE
+mat3s
+glms_translate2d(mat3s m, vec2s v) {
+ glm_translate2d(m.raw, v.raw);
+ return m;
+}
+
+/*!
+ * @brief translate existing 2d transform matrix by x factor
+ *
+ * @param[in] m affine transfrom
+ * @param[in] x x factor
+ * @returns affine transfrom
+ */
+CGLM_INLINE
+mat3s
+glms_translate2d_x(mat3s m, float x) {
+ glm_translate2d_x(m.raw, x);
+ return m;
+}
+
+/*!
+ * @brief translate existing 2d transform matrix by y factor
+ *
+ * @param[in] m affine transfrom
+ * @param[in] y y factor
+ * @returns affine transfrom
+ */
+CGLM_INLINE
+mat3s
+glms_translate2d_y(mat3s m, float y) {
+ glm_translate2d_y(m.raw, y);
+ return m;
+}
+
+/*!
+ * @brief creates NEW translate 2d transform matrix by v vector
+ *
+ * @param[in] v translate vector [x, y]
+ * @returns affine transfrom
+ */
+CGLM_INLINE
+mat3s
+glms_translate2d_make(vec2s v) {
+ mat3s m;
+ glm_translate2d_make(m.raw, v.raw);
+ return m;
+}
+
+/*!
+ * @brief creates NEW 2d scale matrix by v vector
+ *
+ * @param[in] v scale vector [x, y]
+ * @returns affine transfrom
+ */
+CGLM_INLINE
+mat3s
+glms_scale2d_make(vec2s v) {
+ mat3s m;
+ glm_scale2d_make(m.raw, v.raw);
+ return m;
+}
+
+/*!
+ * @brief scales existing 2d transform matrix by v vector
+ * and stores result in same matrix
+ *
+ * @param[in] m affine transfrom
+ * @param[in] v scale vector [x, y, z]
+ * @returns affine transfrom
+ */
+CGLM_INLINE
+mat3s
+glms_scale2d(mat3s m, vec2s v) {
+ mat3s r;
+ glm_scale2d_to(m.raw, v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief applies uniform scale to existing 2d transform matrix v = [s, s, s]
+ * and stores result in same matrix
+ *
+ * @param[in] m affine transfrom
+ * @param[in] s scale factor
+ * @returns affine transfrom
+ */
+CGLM_INLINE
+mat3s
+glms_scale2d_uni(mat3s m, float s) {
+ glm_scale2d_uni(m.raw, s);
+ return m;
+}
+
+/*!
+ * @brief creates NEW 2d rotation matrix by angle and axis
+ *
+ * axis will be normalized so you don't need to normalize it
+ *
+ * @param[in] angle angle (radians)
+ * @returns affine transfrom
+ */
+CGLM_INLINE
+mat3s
+glms_rotate2d_make(float angle) {
+ mat3s m;
+ glm_rotate2d_make(m.raw, angle);
+ return m;
+}
+
+/*!
+ * @brief rotate existing 2d transform matrix around given axis by angle
+ *
+ * @param[in] m affine transfrom
+ * @param[in] angle angle (radians)
+ * @returns affine transfrom
+ */
+CGLM_INLINE
+mat3s
+glms_rotate2d(mat3s m, float angle) {
+ glm_rotate2d(m.raw, angle);
+ return m;
+}
+
+/*!
+ * @brief rotate existing 2d transform matrix around given axis by angle
+ *
+ * @param[in] m affine transfrom
+ * @param[in] angle angle (radians)
+ * @returns affine transfrom
+ */
+CGLM_INLINE
+mat3s
+glms_rotate2d_to(mat3s m, float angle) {
+ glm_rotate2d(m.raw, angle);
+ return m;
+}
+
+#endif /* cglms_affine2ds_h */
diff --git a/libs/cglm/include/cglm/struct/box.h b/libs/cglm/include/cglm/struct/box.h
new file mode 100644
index 0000000..a55884f
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/box.h
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglms_boxs_h
+#define cglms_boxs_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../box.h"
+#include "vec3.h"
+#include "vec4.h"
+#include "mat4.h"
+
+/*!
+ * @brief apply transform to Axis-Aligned Bounding Box
+ *
+ * @param[in] box bounding box
+ * @param[in] m transform matrix
+ * @param[out] dest transformed bounding box
+ */
+CGLM_INLINE
+void
+glms_aabb_transform(vec3s box[2], mat4s m, vec3s dest[2]) {
+ vec3 rawBox[2];
+ vec3 rawDest[2];
+
+ glms_vec3_unpack(rawBox, box, 2);
+ glm_aabb_transform(rawBox, m.raw, rawDest);
+ glms_vec3_pack(dest, rawDest, 2);
+}
+
+/*!
+ * @brief merges two AABB bounding box and creates new one
+ *
+ * two box must be in same space, if one of box is in different space then
+ * you should consider to convert it's space by glm_box_space
+ *
+ * @param[in] box1 bounding box 1
+ * @param[in] box2 bounding box 2
+ * @param[out] dest merged bounding box
+ */
+CGLM_INLINE
+void
+glms_aabb_merge(vec3s box1[2], vec3s box2[2], vec3s dest[2]) {
+ vec3 rawBox1[2];
+ vec3 rawBox2[2];
+ vec3 rawDest[2];
+
+ glms_vec3_unpack(rawBox1, box1, 2);
+ glms_vec3_unpack(rawBox2, box2, 2);
+ glm_aabb_merge(rawBox1, rawBox2, rawDest);
+ glms_vec3_pack(dest, rawDest, 2);
+}
+
+/*!
+ * @brief crops a bounding box with another one.
+ *
+ * this could be useful for gettng a bbox which fits with view frustum and
+ * object bounding boxes. In this case you crop view frustum box with objects
+ * box
+ *
+ * @param[in] box bounding box 1
+ * @param[in] cropBox crop box
+ * @param[out] dest cropped bounding box
+ */
+CGLM_INLINE
+void
+glms_aabb_crop(vec3s box[2], vec3s cropBox[2], vec3s dest[2]) {
+ vec3 rawBox[2];
+ vec3 rawCropBox[2];
+ vec3 rawDest[2];
+
+ glms_vec3_unpack(rawBox, box, 2);
+ glms_vec3_unpack(rawCropBox, cropBox, 2);
+ glm_aabb_crop(rawBox, rawCropBox, rawDest);
+ glms_vec3_pack(dest, rawDest, 2);
+}
+
+/*!
+ * @brief crops a bounding box with another one.
+ *
+ * this could be useful for gettng a bbox which fits with view frustum and
+ * object bounding boxes. In this case you crop view frustum box with objects
+ * box
+ *
+ * @param[in] box bounding box
+ * @param[in] cropBox crop box
+ * @param[in] clampBox miniumum box
+ * @param[out] dest cropped bounding box
+ */
+CGLM_INLINE
+void
+glms_aabb_crop_until(vec3s box[2],
+ vec3s cropBox[2],
+ vec3s clampBox[2],
+ vec3s dest[2]) {
+ glms_aabb_crop(box, cropBox, dest);
+ glms_aabb_merge(clampBox, dest, dest);
+}
+
+/*!
+ * @brief check if AABB intersects with frustum planes
+ *
+ * this could be useful for frustum culling using AABB.
+ *
+ * OPTIMIZATION HINT:
+ * if planes order is similar to LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR
+ * then this method should run even faster because it would only use two
+ * planes if object is not inside the two planes
+ * fortunately cglm extracts planes as this order! just pass what you got!
+ *
+ * @param[in] box bounding box
+ * @param[in] planes frustum planes
+ */
+CGLM_INLINE
+bool
+glms_aabb_frustum(vec3s box[2], vec4s planes[6]) {
+ vec3 rawBox[2];
+ vec4 rawPlanes[6];
+
+ glms_vec3_unpack(rawBox, box, 2);
+ glms_vec4_unpack(rawPlanes, planes, 6);
+ return glm_aabb_frustum(rawBox, rawPlanes);
+}
+
+/*!
+ * @brief invalidate AABB min and max values
+ *
+ * @param[in, out] box bounding box
+ */
+CGLM_INLINE
+void
+glms_aabb_invalidate(vec3s box[2]) {
+ box[0] = glms_vec3_broadcast(FLT_MAX);
+ box[1] = glms_vec3_broadcast(-FLT_MAX);
+}
+
+/*!
+ * @brief check if AABB is valid or not
+ *
+ * @param[in] box bounding box
+ */
+CGLM_INLINE
+bool
+glms_aabb_isvalid(vec3s box[2]) {
+ vec3 rawBox[2];
+ glms_vec3_unpack(rawBox, box, 2);
+ return glm_aabb_isvalid(rawBox);
+}
+
+/*!
+ * @brief distance between of min and max
+ *
+ * @param[in] box bounding box
+ */
+CGLM_INLINE
+float
+glms_aabb_size(vec3s box[2]) {
+ return glm_vec3_distance(box[0].raw, box[1].raw);
+}
+
+/*!
+ * @brief radius of sphere which surrounds AABB
+ *
+ * @param[in] box bounding box
+ */
+CGLM_INLINE
+float
+glms_aabb_radius(vec3s box[2]) {
+ return glms_aabb_size(box) * 0.5f;
+}
+
+/*!
+ * @brief computes center point of AABB
+ *
+ * @param[in] box bounding box
+ * @returns center of bounding box
+ */
+CGLM_INLINE
+vec3s
+glms_aabb_center(vec3s box[2]) {
+ return glms_vec3_center(box[0], box[1]);
+}
+
+/*!
+ * @brief check if two AABB intersects
+ *
+ * @param[in] box bounding box
+ * @param[in] other other bounding box
+ */
+CGLM_INLINE
+bool
+glms_aabb_aabb(vec3s box[2], vec3s other[2]) {
+ vec3 rawBox[2];
+ vec3 rawOther[2];
+
+ glms_vec3_unpack(rawBox, box, 2);
+ glms_vec3_unpack(rawOther, other, 2);
+ return glm_aabb_aabb(rawBox, rawOther);
+}
+
+/*!
+ * @brief check if AABB intersects with sphere
+ *
+ * https://github.com/erich666/GraphicsGems/blob/master/gems/BoxSphere.c
+ * Solid Box - Solid Sphere test.
+ *
+ * @param[in] box solid bounding box
+ * @param[in] s solid sphere
+ */
+CGLM_INLINE
+bool
+glms_aabb_sphere(vec3s box[2], vec4s s) {
+ vec3 rawBox[2];
+
+ glms_vec3_unpack(rawBox, box, 2);
+ return glm_aabb_sphere(rawBox, s.raw);
+}
+
+/*!
+ * @brief check if point is inside of AABB
+ *
+ * @param[in] box bounding box
+ * @param[in] point point
+ */
+CGLM_INLINE
+bool
+glms_aabb_point(vec3s box[2], vec3s point) {
+ vec3 rawBox[2];
+
+ glms_vec3_unpack(rawBox, box, 2);
+ return glm_aabb_point(rawBox, point.raw);
+}
+
+/*!
+ * @brief check if AABB contains other AABB
+ *
+ * @param[in] box bounding box
+ * @param[in] other other bounding box
+ */
+CGLM_INLINE
+bool
+glms_aabb_contains(vec3s box[2], vec3s other[2]) {
+ vec3 rawBox[2];
+ vec3 rawOther[2];
+
+ glms_vec3_unpack(rawBox, box, 2);
+ glms_vec3_unpack(rawOther, other, 2);
+ return glm_aabb_contains(rawBox, rawOther);
+}
+
+#endif /* cglms_boxs_h */
diff --git a/libs/cglm/include/cglm/struct/cam.h b/libs/cglm/include/cglm/struct/cam.h
new file mode 100644
index 0000000..2a92af7
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/cam.h
@@ -0,0 +1,646 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE mat4s glms_frustum(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ)
+ CGLM_INLINE mat4s glms_ortho(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ)
+ CGLM_INLINE mat4s glms_ortho_aabb(vec3s box[2]);
+ CGLM_INLINE mat4s glms_ortho_aabb_p(vec3s box[2], float padding);
+ CGLM_INLINE mat4s glms_ortho_aabb_pz(vec3s box[2], float padding);
+ CGLM_INLINE mat4s glms_ortho_default(float aspect)
+ CGLM_INLINE mat4s glms_ortho_default_s(float aspect, float size)
+ CGLM_INLINE mat4s glms_perspective(float fovy,
+ float aspect,
+ float nearZ,
+ float farZ)
+ CGLM_INLINE void glms_persp_move_far(mat4s proj, float deltaFar)
+ CGLM_INLINE mat4s glms_perspective_default(float aspect)
+ CGLM_INLINE void glms_perspective_resize(mat4s proj, float aspect)
+ CGLM_INLINE mat4s glms_lookat(vec3s eye, vec3s center, vec3s up)
+ CGLM_INLINE mat4s glms_look(vec3s eye, vec3s dir, vec3s up)
+ CGLM_INLINE mat4s glms_look_anyup(vec3s eye, vec3s dir)
+ CGLM_INLINE void glms_persp_decomp(mat4s proj,
+ float *nearv, float *farv,
+ float *top, float *bottom,
+ float *left, float *right)
+ CGLM_INLINE void glms_persp_decompv(mat4s proj, float dest[6])
+ CGLM_INLINE void glms_persp_decomp_x(mat4s proj, float *left, float *right)
+ CGLM_INLINE void glms_persp_decomp_y(mat4s proj, float *top, float *bottom)
+ CGLM_INLINE void glms_persp_decomp_z(mat4s proj, float *nearv, float *farv)
+ CGLM_INLINE void glms_persp_decomp_far(mat4s proj, float *farZ)
+ CGLM_INLINE void glms_persp_decomp_near(mat4s proj, float *nearZ)
+ CGLM_INLINE float glms_persp_fovy(mat4s proj)
+ CGLM_INLINE float glms_persp_aspect(mat4s proj)
+ CGLM_INLINE vec4s glms_persp_sizes(mat4s proj, float fovy)
+ */
+
+#ifndef cglms_cam_h
+#define cglms_cam_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../plane.h"
+#include "../cam.h"
+
+#ifndef CGLM_CLIPSPACE_INCLUDE_ALL
+# if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+# include "clipspace/ortho_lh_zo.h"
+# include "clipspace/persp_lh_zo.h"
+# include "clipspace/view_lh_zo.h"
+# elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+# include "clipspace/ortho_lh_no.h"
+# include "clipspace/persp_lh_no.h"
+# include "clipspace/view_lh_no.h"
+# elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+# include "clipspace/ortho_rh_zo.h"
+# include "clipspace/persp_rh_zo.h"
+# include "clipspace/view_rh_zo.h"
+# elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+# include "clipspace/ortho_rh_no.h"
+# include "clipspace/persp_rh_no.h"
+# include "clipspace/view_rh_no.h"
+# endif
+#else
+# include "clipspace/ortho_lh_zo.h"
+# include "clipspace/persp_lh_zo.h"
+# include "clipspace/ortho_lh_no.h"
+# include "clipspace/persp_lh_no.h"
+# include "clipspace/ortho_rh_zo.h"
+# include "clipspace/persp_rh_zo.h"
+# include "clipspace/ortho_rh_no.h"
+# include "clipspace/persp_rh_no.h"
+# include "clipspace/view_lh_zo.h"
+# include "clipspace/view_lh_no.h"
+# include "clipspace/view_rh_zo.h"
+# include "clipspace/view_rh_no.h"
+#endif
+
+/*!
+ * @brief set up perspective peprojection matrix
+ *
+ * @param[in] left viewport.left
+ * @param[in] right viewport.right
+ * @param[in] bottom viewport.bottom
+ * @param[in] top viewport.top
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping plane
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_frustum(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ return glms_frustum_lh_zo(left, right, bottom, top, nearZ, farZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ return glms_frustum_lh_no(left, right, bottom, top, nearZ, farZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ return glms_frustum_rh_zo(left, right, bottom, top, nearZ, farZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ return glms_frustum_rh_no(left, right, bottom, top, nearZ, farZ);
+#endif
+}
+
+/*!
+ * @brief set up orthographic projection matrix
+ *
+ * @param[in] left viewport.left
+ * @param[in] right viewport.right
+ * @param[in] bottom viewport.bottom
+ * @param[in] top viewport.top
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping plane
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ return glms_ortho_lh_zo(left, right, bottom, top, nearZ, farZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ return glms_ortho_lh_no(left, right, bottom, top, nearZ, farZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ return glms_ortho_rh_zo(left, right, bottom, top, nearZ, farZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ return glms_ortho_rh_no(left, right, bottom, top, nearZ, farZ);
+#endif
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_aabb(vec3s box[2]) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ return glms_ortho_aabb_lh_zo(box);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ return glms_ortho_aabb_lh_no(box);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ return glms_ortho_aabb_rh_zo(box);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ return glms_ortho_aabb_rh_no(box);
+#endif
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[in] padding padding
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_aabb_p(vec3s box[2], float padding) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ return glms_ortho_aabb_p_lh_zo(box, padding);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ return glms_ortho_aabb_p_lh_no(box, padding);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ return glms_ortho_aabb_p_rh_zo(box, padding);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ return glms_ortho_aabb_p_rh_no(box, padding);
+#endif
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[in] padding padding for near and far
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_aabb_pz(vec3s box[2], float padding) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ return glms_ortho_aabb_pz_lh_zo(box, padding);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ return glms_ortho_aabb_pz_lh_no(box, padding);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ return glms_ortho_aabb_pz_rh_zo(box, padding);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ return glms_ortho_aabb_pz_rh_no(box, padding);
+#endif
+}
+
+/*!
+ * @brief set up unit orthographic projection matrix
+ *
+ * @param[in] aspect aspect ration ( width / height )
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_default(float aspect) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ return glms_ortho_default_lh_zo(aspect);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ return glms_ortho_default_lh_no(aspect);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ return glms_ortho_default_rh_zo(aspect);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ return glms_ortho_default_rh_no(aspect);
+#endif
+}
+
+/*!
+ * @brief set up orthographic projection matrix with given CUBE size
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in] size cube size
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_default_s(float aspect, float size) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ return glms_ortho_default_s_lh_zo(aspect, size);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ return glms_ortho_default_s_lh_no(aspect, size);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ return glms_ortho_default_s_rh_zo(aspect, size);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ return glms_ortho_default_s_rh_no(aspect, size);
+#endif
+}
+
+/*!
+ * @brief set up perspective projection matrix
+ *
+ * @param[in] fovy field of view angle
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping planes
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_perspective(float fovy, float aspect, float nearZ, float farZ) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ return glms_perspective_lh_zo(fovy, aspect, nearZ, farZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ return glms_perspective_lh_no(fovy, aspect, nearZ, farZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ return glms_perspective_rh_zo(fovy, aspect, nearZ, farZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ return glms_perspective_rh_no(fovy, aspect, nearZ, farZ);
+#endif
+}
+
+/*!
+ * @brief extend perspective projection matrix's far distance
+ *
+ * NOTE: if you dodn't want to create new matrix then use array api on struct.raw
+ * like glm_persp_move_far(prooj.raw, deltaFar) to avoid create new mat4
+ * each time
+ *
+ * this function does not guarantee far >= near, be aware of that!
+ *
+ * @param[in, out] proj projection matrix to extend
+ * @param[in] deltaFar distance from existing far (negative to shink)
+ */
+CGLM_INLINE
+mat4s
+glms_persp_move_far(mat4s proj, float deltaFar) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ return glms_persp_move_far_lh_zo(proj, deltaFar);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ return glms_persp_move_far_lh_no(proj, deltaFar);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ return glms_persp_move_far_rh_zo(proj, deltaFar);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ return glms_persp_move_far_rh_no(proj, deltaFar);
+#endif
+}
+
+/*!
+ * @brief set up perspective projection matrix with default near/far
+ * and angle values
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_perspective_default(float aspect) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ return glms_perspective_default_lh_zo(aspect);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ return glms_perspective_default_lh_no(aspect);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ return glms_perspective_default_rh_zo(aspect);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ return glms_perspective_default_rh_no(aspect);
+#endif
+}
+
+/*!
+ * @brief resize perspective matrix by aspect ratio ( width / height )
+ * this makes very easy to resize proj matrix when window /viewport
+ * reized
+ *
+ * NOTE: if you dodn't want to create new matrix then use array api on struct.raw
+ * like glms_perspective_resize(proj.raw, aspect) to avoid create new mat4
+ * each time
+ *
+ * @param[in, out] proj perspective projection matrix
+ * @param[in] aspect aspect ratio ( width / height )
+ */
+CGLM_INLINE
+mat4s
+glms_perspective_resize(mat4s proj, float aspect) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ return glms_perspective_resize_lh_zo(proj, aspect);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ return glms_perspective_resize_lh_no(proj, aspect);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ return glms_perspective_resize_rh_zo(proj, aspect);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ return glms_perspective_resize_rh_no(proj, aspect);
+#endif
+}
+
+/*!
+ * @brief set up view matrix
+ *
+ * NOTE: The UP vector must not be parallel to the line of sight from
+ * the eye point to the reference point
+ *
+ * @param[in] eye eye vector
+ * @param[in] center center vector
+ * @param[in] up up vector
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_lookat(vec3s eye, vec3s center, vec3s up) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ return glms_lookat_lh_zo(eye, center, up);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ return glms_lookat_lh_no(eye, center, up);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ return glms_lookat_rh_zo(eye, center, up);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ return glms_lookat_rh_no(eye, center, up);
+#endif
+}
+
+/*!
+ * @brief set up view matrix
+ *
+ * convenient wrapper for lookat: if you only have direction not target self
+ * then this might be useful. Because you need to get target from direction.
+ *
+ * NOTE: The UP vector must not be parallel to the line of sight from
+ * the eye point to the reference point
+ *
+ * @param[in] eye eye vector
+ * @param[in] dir direction vector
+ * @param[in] up up vector
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_look(vec3s eye, vec3s dir, vec3s up) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ return glms_look_lh_zo(eye, dir, up);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ return glms_look_lh_no(eye, dir, up);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ return glms_look_rh_zo(eye, dir, up);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ return glms_look_rh_no(eye, dir, up);
+#endif
+}
+
+/*!
+ * @brief set up view matrix
+ *
+ * convenient wrapper for look: if you only have direction and if you don't
+ * care what UP vector is then this might be useful to create view matrix
+ *
+ * @param[in] eye eye vector
+ * @param[in] dir direction vector
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_look_anyup(vec3s eye, vec3s dir) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ return glms_look_anyup_lh_zo(eye, dir);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ return glms_look_anyup_lh_no(eye, dir);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ return glms_look_anyup_rh_zo(eye, dir);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ return glms_look_anyup_rh_no(eye, dir);
+#endif
+}
+
+/*!
+ * @brief decomposes frustum values of perspective projection.
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ * @param[out] farZ far
+ * @param[out] top top
+ * @param[out] bottom bottom
+ * @param[out] left left
+ * @param[out] right right
+ */
+CGLM_INLINE
+void
+glms_persp_decomp(mat4s proj,
+ float * __restrict nearZ, float * __restrict farZ,
+ float * __restrict top, float * __restrict bottom,
+ float * __restrict left, float * __restrict right) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glms_persp_decomp_lh_zo(proj, nearZ, farZ, top, bottom, left, right);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glms_persp_decomp_lh_no(proj, nearZ, farZ, top, bottom, left, right);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glms_persp_decomp_rh_zo(proj, nearZ, farZ, top, bottom, left, right);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glms_persp_decomp_rh_no(proj, nearZ, farZ, top, bottom, left, right);
+#endif
+}
+
+/*!
+ * @brief decomposes frustum values of perspective projection.
+ * this makes easy to get all values at once
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] dest array
+ */
+CGLM_INLINE
+void
+glms_persp_decompv(mat4s proj, float dest[6]) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glms_persp_decompv_lh_zo(proj, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glms_persp_decompv_lh_no(proj, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glms_persp_decompv_rh_zo(proj, dest);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glms_persp_decompv_rh_no(proj, dest);
+#endif
+}
+
+/*!
+ * @brief decomposes left and right values of perspective projection.
+ * x stands for x axis (left / right axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] left left
+ * @param[out] right right
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_x(mat4s proj,
+ float * __restrict left,
+ float * __restrict right) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glms_persp_decomp_x_lh_zo(proj, left, right);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glms_persp_decomp_x_lh_no(proj, left, right);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glms_persp_decomp_x_rh_zo(proj, left, right);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glms_persp_decomp_x_rh_no(proj, left, right);
+#endif
+}
+
+/*!
+ * @brief decomposes top and bottom values of perspective projection.
+ * y stands for y axis (top / botom axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] top top
+ * @param[out] bottom bottom
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_y(mat4s proj,
+ float * __restrict top,
+ float * __restrict bottom) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glms_persp_decomp_y_lh_zo(proj, top, bottom);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glms_persp_decomp_y_lh_no(proj, top, bottom);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glms_persp_decomp_y_rh_zo(proj, top, bottom);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glms_persp_decomp_y_rh_no(proj, top, bottom);
+#endif
+}
+
+/*!
+ * @brief decomposes near and far values of perspective projection.
+ * z stands for z axis (near / far axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ * @param[out] farZ far
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_z(mat4s proj,
+ float * __restrict nearZ,
+ float * __restrict farZ) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glms_persp_decomp_z_lh_zo(proj, nearZ, farZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glms_persp_decomp_z_lh_no(proj, nearZ, farZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glms_persp_decomp_z_rh_zo(proj, nearZ, farZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glms_persp_decomp_z_rh_no(proj, nearZ, farZ);
+#endif
+}
+
+/*!
+ * @brief decomposes far value of perspective projection.
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] farZ far
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_far(mat4s proj, float * __restrict farZ) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glms_persp_decomp_far_lh_zo(proj, farZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glms_persp_decomp_far_lh_no(proj, farZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glms_persp_decomp_far_rh_zo(proj, farZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glms_persp_decomp_far_rh_no(proj, farZ);
+#endif
+}
+
+/*!
+ * @brief decomposes near value of perspective projection.
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_near(mat4s proj, float * __restrict nearZ) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ glms_persp_decomp_near_lh_zo(proj, nearZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ glms_persp_decomp_near_lh_no(proj, nearZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ glms_persp_decomp_near_rh_zo(proj, nearZ);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ glms_persp_decomp_near_rh_no(proj, nearZ);
+#endif
+}
+
+/*!
+ * @brief returns field of view angle along the Y-axis (in radians)
+ *
+ * if you need to degrees, use glm_deg to convert it or use this:
+ * fovy_deg = glm_deg(glm_persp_fovy(projMatrix))
+ *
+ * @param[in] proj perspective projection matrix
+ */
+CGLM_INLINE
+float
+glms_persp_fovy(mat4s proj) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ return glms_persp_fovy_lh_zo(proj);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ return glms_persp_fovy_lh_no(proj);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ return glms_persp_fovy_rh_zo(proj);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ return glms_persp_fovy_rh_no(proj);
+#endif
+}
+
+/*!
+ * @brief returns aspect ratio of perspective projection
+ *
+ * @param[in] proj perspective projection matrix
+ */
+CGLM_INLINE
+float
+glms_persp_aspect(mat4s proj) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ return glms_persp_aspect_lh_zo(proj);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ return glms_persp_aspect_lh_no(proj);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ return glms_persp_aspect_rh_zo(proj);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ return glms_persp_aspect_rh_no(proj);
+#endif
+}
+
+/*!
+ * @brief returns sizes of near and far planes of perspective projection
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[in] fovy fovy (see brief)
+ * @returns sizes as vector, sizes order: [Wnear, Hnear, Wfar, Hfar]
+ */
+CGLM_INLINE
+vec4s
+glms_persp_sizes(mat4s proj, float fovy) {
+#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
+ return glms_persp_sizes_lh_zo(proj, fovy);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
+ return glms_persp_sizes_lh_no(proj, fovy);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
+ return glms_persp_sizes_rh_zo(proj, fovy);
+#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
+ return glms_persp_sizes_rh_no(proj, fovy);
+#endif
+}
+
+#endif /* cglms_cam_h */
diff --git a/libs/cglm/include/cglm/struct/clipspace/ortho_lh_no.h b/libs/cglm/include/cglm/struct/clipspace/ortho_lh_no.h
new file mode 100644
index 0000000..9a22ff5
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/clipspace/ortho_lh_no.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), htt../opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE mat4s glms_ortho_lh_no(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ)
+ CGLM_INLINE mat4s glms_ortho_aabb_lh_no(vec3s box[2]);
+ CGLM_INLINE mat4s glms_ortho_aabb_p_lh_no(vec3s box[2], float padding);
+ CGLM_INLINE mat4s glms_ortho_aabb_pz_lh_no(vec3s box[2], float padding);
+ CGLM_INLINE mat4s glms_ortho_default_lh_no(float aspect)
+ CGLM_INLINE mat4s glms_ortho_default_s_lh_no(float aspect, float size)
+ */
+
+#ifndef cglms_ortho_lh_no_h
+#define cglms_ortho_lh_no_h
+
+#include "../../common.h"
+#include "../../types-struct.h"
+#include "../../plane.h"
+#include "../../cam.h"
+
+/*!
+ * @brief set up orthographic projection matrix
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] left viewport.left
+ * @param[in] right viewport.right
+ * @param[in] bottom viewport.bottom
+ * @param[in] top viewport.top
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping plane
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_lh_no(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ) {
+ mat4s dest;
+ glm_ortho_lh_no(left, right, bottom, top, nearZ, farZ, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_aabb_lh_no(vec3s box[2]) {
+ mat4s dest;
+ vec3 rawBox[2];
+
+ glms_vec3_unpack(rawBox, box, 2);
+ glm_ortho_aabb_lh_no(rawBox, dest.raw);
+
+ return dest;
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[in] padding padding
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_aabb_p_lh_no(vec3s box[2], float padding) {
+ mat4s dest;
+ vec3 rawBox[2];
+
+ glms_vec3_unpack(rawBox, box, 2);
+ glm_ortho_aabb_p_lh_no(rawBox, padding, dest.raw);
+
+ return dest;
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[in] padding padding for near and far
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_aabb_pz_lh_no(vec3s box[2], float padding) {
+ mat4s dest;
+ vec3 rawBox[2];
+
+ glms_vec3_unpack(rawBox, box, 2);
+ glm_ortho_aabb_pz_lh_no(rawBox, padding, dest.raw);
+
+ return dest;
+}
+
+/*!
+ * @brief set up unit orthographic projection matrix
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] aspect aspect ration ( width / height )
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_default_lh_no(float aspect) {
+ mat4s dest;
+ glm_ortho_default_lh_no(aspect, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief set up orthographic projection matrix with given CUBE size
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in] size cube size
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_default_s_lh_no(float aspect, float size) {
+ mat4s dest;
+ glm_ortho_default_s_lh_no(aspect, size, dest.raw);
+ return dest;
+}
+
+#endif /* cglms_ortho_lh_no_h */
diff --git a/libs/cglm/include/cglm/struct/clipspace/ortho_lh_zo.h b/libs/cglm/include/cglm/struct/clipspace/ortho_lh_zo.h
new file mode 100644
index 0000000..09f4731
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/clipspace/ortho_lh_zo.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), htt../opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE mat4s glms_ortho_lh_zo(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ)
+ CGLM_INLINE mat4s glms_ortho_aabb_lh_zo(vec3s box[2]);
+ CGLM_INLINE mat4s glms_ortho_aabb_p_lh_zo(vec3s box[2], float padding);
+ CGLM_INLINE mat4s glms_ortho_aabb_pz_lh_zo(vec3s box[2], float padding);
+ CGLM_INLINE mat4s glms_ortho_default_lh_zo(float aspect)
+ CGLM_INLINE mat4s glms_ortho_default_s_lh_zo(float aspect, float size)
+ */
+
+#ifndef cglms_ortho_lh_zo_h
+#define cglms_ortho_lh_zo_h
+
+#include "../../common.h"
+#include "../../types-struct.h"
+#include "../../plane.h"
+#include "../../cam.h"
+
+/*!
+ * @brief set up orthographic projection matrix
+ * with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] left viewport.left
+ * @param[in] right viewport.right
+ * @param[in] bottom viewport.bottom
+ * @param[in] top viewport.top
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping plane
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_lh_zo(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ) {
+ mat4s dest;
+ glm_ortho_lh_zo(left, right, bottom, top, nearZ, farZ, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ * with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_aabb_lh_zo(vec3s box[2]) {
+ mat4s dest;
+ vec3 rawBox[2];
+
+ glms_vec3_unpack(rawBox, box, 2);
+ glm_ortho_aabb_lh_zo(rawBox, dest.raw);
+
+ return dest;
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ * with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[in] padding padding
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_aabb_p_lh_zo(vec3s box[2], float padding) {
+ mat4s dest;
+ vec3 rawBox[2];
+
+ glms_vec3_unpack(rawBox, box, 2);
+ glm_ortho_aabb_p_lh_zo(rawBox, padding, dest.raw);
+
+ return dest;
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ * with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[in] padding padding for near and far
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_aabb_pz_lh_zo(vec3s box[2], float padding) {
+ mat4s dest;
+ vec3 rawBox[2];
+
+ glms_vec3_unpack(rawBox, box, 2);
+ glm_ortho_aabb_pz_lh_zo(rawBox, padding, dest.raw);
+
+ return dest;
+}
+
+/*!
+ * @brief set up unit orthographic projection matrix
+ * with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] aspect aspect ration ( width / height )
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_default_lh_zo(float aspect) {
+ mat4s dest;
+ glm_ortho_default_lh_zo(aspect, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief set up orthographic projection matrix with given CUBE size
+ * with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in] size cube size
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_default_s_lh_zo(float aspect, float size) {
+ mat4s dest;
+ glm_ortho_default_s_lh_zo(aspect, size, dest.raw);
+ return dest;
+}
+
+#endif /* cglms_ortho_lh_zo_h */
diff --git a/libs/cglm/include/cglm/struct/clipspace/ortho_rh_no.h b/libs/cglm/include/cglm/struct/clipspace/ortho_rh_no.h
new file mode 100644
index 0000000..28bd275
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/clipspace/ortho_rh_no.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), htt../opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE mat4s glms_ortho_rh_no(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ)
+ CGLM_INLINE mat4s glms_ortho_aabb_rh_no(vec3s box[2]);
+ CGLM_INLINE mat4s glms_ortho_aabb_p_rh_no(vec3s box[2], float padding);
+ CGLM_INLINE mat4s glms_ortho_aabb_pz_rh_no(vec3s box[2], float padding);
+ CGLM_INLINE mat4s glms_ortho_default_rh_no(float aspect)
+ CGLM_INLINE mat4s glms_ortho_default_s_rh_no(float aspect, float size)
+ */
+
+#ifndef cglms_ortho_rh_no_h
+#define cglms_ortho_rh_no_h
+
+#include "../../common.h"
+#include "../../types-struct.h"
+#include "../../plane.h"
+#include "../../cam.h"
+
+/*!
+ * @brief set up orthographic projection matrix
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] left viewport.left
+ * @param[in] right viewport.right
+ * @param[in] bottom viewport.bottom
+ * @param[in] top viewport.top
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping plane
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_rh_no(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ) {
+ mat4s dest;
+ glm_ortho_rh_no(left, right, bottom, top, nearZ, farZ, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_aabb_rh_no(vec3s box[2]) {
+ mat4s dest;
+ vec3 rawBox[2];
+
+ glms_vec3_unpack(rawBox, box, 2);
+ glm_ortho_aabb_rh_no(rawBox, dest.raw);
+
+ return dest;
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[in] padding padding
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_aabb_p_rh_no(vec3s box[2], float padding) {
+ mat4s dest;
+ vec3 rawBox[2];
+
+ glms_vec3_unpack(rawBox, box, 2);
+ glm_ortho_aabb_p_rh_no(rawBox, padding, dest.raw);
+
+ return dest;
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[in] padding padding for near and far
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_aabb_pz_rh_no(vec3s box[2], float padding) {
+ mat4s dest;
+ vec3 rawBox[2];
+
+ glms_vec3_unpack(rawBox, box, 2);
+ glm_ortho_aabb_pz_rh_no(rawBox, padding, dest.raw);
+
+ return dest;
+}
+
+/*!
+ * @brief set up unit orthographic projection matrix
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] aspect aspect ration ( width / height )
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_default_rh_no(float aspect) {
+ mat4s dest;
+ glm_ortho_default_rh_no(aspect, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief set up orthographic projection matrix with given CUBE size
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in] size cube size
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_default_s_rh_no(float aspect, float size) {
+ mat4s dest;
+ glm_ortho_default_s_rh_no(aspect, size, dest.raw);
+ return dest;
+}
+
+#endif /* cglms_ortho_rh_no_h */
diff --git a/libs/cglm/include/cglm/struct/clipspace/ortho_rh_zo.h b/libs/cglm/include/cglm/struct/clipspace/ortho_rh_zo.h
new file mode 100644
index 0000000..0758d62
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/clipspace/ortho_rh_zo.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), htt../opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE mat4s glms_ortho_rh_zo(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ)
+ CGLM_INLINE mat4s glms_ortho_aabb_rh_zo(vec3s box[2]);
+ CGLM_INLINE mat4s glms_ortho_aabb_p_rh_zo(vec3s box[2], float padding);
+ CGLM_INLINE mat4s glms_ortho_aabb_pz_rh_zo(vec3s box[2], float padding);
+ CGLM_INLINE mat4s glms_ortho_default_rh_zo(float aspect)
+ CGLM_INLINE mat4s glms_ortho_default_s_rh_zo(float aspect, float size)
+ */
+
+#ifndef cglms_ortho_rh_zo_h
+#define cglms_ortho_rh_zo_h
+
+#include "../../common.h"
+#include "../../types-struct.h"
+#include "../../plane.h"
+#include "../../cam.h"
+
+/*!
+ * @brief set up orthographic projection matrix
+ * with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] left viewport.left
+ * @param[in] right viewport.right
+ * @param[in] bottom viewport.bottom
+ * @param[in] top viewport.top
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping plane
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_rh_zo(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ) {
+ mat4s dest;
+ glm_ortho_rh_zo(left, right, bottom, top, nearZ, farZ, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ * with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_aabb_rh_zo(vec3s box[2]) {
+ mat4s dest;
+ vec3 rawBox[2];
+
+ glms_vec3_unpack(rawBox, box, 2);
+ glm_ortho_aabb_rh_zo(rawBox, dest.raw);
+
+ return dest;
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ * with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[in] padding padding
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_aabb_p_rh_zo(vec3s box[2], float padding) {
+ mat4s dest;
+ vec3 rawBox[2];
+
+ glms_vec3_unpack(rawBox, box, 2);
+ glm_ortho_aabb_p_rh_zo(rawBox, padding, dest.raw);
+
+ return dest;
+}
+
+/*!
+ * @brief set up orthographic projection matrix using bounding box
+ * with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * bounding box (AABB) must be in view space
+ *
+ * @param[in] box AABB
+ * @param[in] padding padding for near and far
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_aabb_pz_rh_zo(vec3s box[2], float padding) {
+ mat4s dest;
+ vec3 rawBox[2];
+
+ glms_vec3_unpack(rawBox, box, 2);
+ glm_ortho_aabb_pz_rh_zo(rawBox, padding, dest.raw);
+
+ return dest;
+}
+
+/*!
+ * @brief set up unit orthographic projection matrix
+ * with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] aspect aspect ration ( width / height )
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_default_rh_zo(float aspect) {
+ mat4s dest;
+ glm_ortho_default_rh_zo(aspect, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief set up orthographic projection matrix with given CUBE size
+ * with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in] size cube size
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_ortho_default_s_rh_zo(float aspect, float size) {
+ mat4s dest;
+ glm_ortho_default_s_rh_zo(aspect, size, dest.raw);
+ return dest;
+}
+
+#endif /* cglms_ortho_rh_zo_h */
diff --git a/libs/cglm/include/cglm/struct/clipspace/persp_lh_no.h b/libs/cglm/include/cglm/struct/clipspace/persp_lh_no.h
new file mode 100644
index 0000000..1c1bb68
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/clipspace/persp_lh_no.h
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), htt../opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE mat4s glms_frustum_lh_no(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ)
+ CGLM_INLINE mat4s glms_perspective_lh_no(float fovy,
+ float aspect,
+ float nearZ,
+ float farZ)
+ CGLM_INLINE void glms_persp_move_far_lh_no(mat4s proj, float deltaFar)
+ CGLM_INLINE mat4s glms_perspective_default_lh_no(float aspect)
+ CGLM_INLINE void glms_perspective_resize_lh_no(mat4s proj, float aspect)
+ CGLM_INLINE void glms_persp_decomp_lh_no(mat4s proj,
+ float *nearv, float *farv,
+ float *top, float *bottom,
+ float *left, float *right)
+ CGLM_INLINE void glms_persp_decompv_lh_no(mat4s proj, float dest[6])
+ CGLM_INLINE void glms_persp_decomp_x_lh_no(mat4s proj, float *left, float *right)
+ CGLM_INLINE void glms_persp_decomp_y_lh_no(mat4s proj, float *top, float *bottom)
+ CGLM_INLINE void glms_persp_decomp_z_lh_no(mat4s proj, float *nearv, float *farv)
+ CGLM_INLINE void glms_persp_decomp_far_lh_no(mat4s proj, float *farZ)
+ CGLM_INLINE void glms_persp_decomp_near_lh_no(mat4s proj, float *nearZ)
+ CGLM_INLINE float glms_persp_fovy_lh_no(mat4s proj)
+ CGLM_INLINE float glms_persp_aspect_lh_no(mat4s proj)
+ CGLM_INLINE vec4s glms_persp_sizes_lh_no(mat4s proj, float fovy)
+ */
+
+#ifndef cglms_persp_lh_no_h
+#define cglms_persp_lh_no_h
+
+#include "../../common.h"
+#include "../../types-struct.h"
+#include "../../plane.h"
+#include "../../cam.h"
+
+/*!
+ * @brief set up perspective peprojection matrix
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] left viewport.left
+ * @param[in] right viewport.right
+ * @param[in] bottom viewport.bottom
+ * @param[in] top viewport.top
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping plane
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_frustum_lh_no(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ) {
+ mat4s dest;
+ glm_frustum_lh_no(left, right, bottom, top, nearZ, farZ, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief set up perspective projection matrix
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] fovy field of view angle
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping planes
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_perspective_lh_no(float fovy, float aspect, float nearZ, float farZ) {
+ mat4s dest;
+ glm_perspective_lh_no(fovy, aspect, nearZ, farZ, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief extend perspective projection matrix's far distance
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * NOTE: if you dodn't want to create new matrix then use array api on struct.raw
+ * like glms_persp_move_far_lh_no(prooj.raw, deltaFar) to avoid create new mat4
+ * each time
+ *
+ * this function does not guarantee far >= near, be aware of that!
+ *
+ * @param[in, out] proj projection matrix to extend
+ * @param[in] deltaFar distance from existing far (negative to shink)
+ */
+CGLM_INLINE
+mat4s
+glms_persp_move_far_lh_no(mat4s proj, float deltaFar) {
+ mat4s dest;
+ dest = proj;
+ glm_persp_move_far_lh_no(dest.raw, deltaFar);
+ return dest;
+}
+
+/*!
+ * @brief set up perspective projection matrix with default near/far
+ * and angle values with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_perspective_default_lh_no(float aspect) {
+ mat4s dest;
+ glm_perspective_default_lh_no(aspect, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief resize perspective matrix by aspect ratio ( width / height )
+ * this makes very easy to resize proj matrix when window /viewport
+ * reized with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * NOTE: if you dodn't want to create new matrix then use array api on struct.raw
+ * like glm_perspective_resize_lh_no(proj.raw, aspect) to avoid create new mat4
+ * each time
+ *
+ * @param[in, out] proj perspective projection matrix
+ * @param[in] aspect aspect ratio ( width / height )
+ */
+CGLM_INLINE
+mat4s
+glms_perspective_resize_lh_no(mat4s proj, float aspect) {
+ mat4s dest;
+ dest = proj;
+ glm_perspective_resize_lh_no(aspect, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief decomposes frustum values of perspective projection.
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ * @param[out] farZ far
+ * @param[out] top top
+ * @param[out] bottom bottom
+ * @param[out] left left
+ * @param[out] right right
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_lh_no(mat4s proj,
+ float * __restrict nearZ, float * __restrict farZ,
+ float * __restrict top, float * __restrict bottom,
+ float * __restrict left, float * __restrict right) {
+ glm_persp_decomp_lh_no(proj.raw, nearZ, farZ, top, bottom, left, right);
+}
+
+/*!
+ * @brief decomposes frustum values of perspective projection.
+ * this makes easy to get all values at once
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] dest array
+ */
+CGLM_INLINE
+void
+glms_persp_decompv_lh_no(mat4s proj, float dest[6]) {
+ glm_persp_decompv_lh_no(proj.raw, dest);
+}
+
+/*!
+ * @brief decomposes left and right values of perspective projection
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ * x stands for x axis (left / right axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] left left
+ * @param[out] right right
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_x_lh_no(mat4s proj,
+ float * __restrict left,
+ float * __restrict right) {
+ glm_persp_decomp_x_lh_no(proj.raw, left, right);
+}
+
+/*!
+ * @brief decomposes top and bottom values of perspective projection
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ * y stands for y axis (top / botom axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] top top
+ * @param[out] bottom bottom
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_y_lh_no(mat4s proj,
+ float * __restrict top,
+ float * __restrict bottom) {
+ glm_persp_decomp_y_lh_no(proj.raw, top, bottom);
+}
+
+/*!
+ * @brief decomposes near and far values of perspective projection
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ * z stands for z axis (near / far axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ * @param[out] farZ far
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_z_lh_no(mat4s proj,
+ float * __restrict nearZ,
+ float * __restrict farZ) {
+ glm_persp_decomp_z_lh_no(proj.raw, nearZ, farZ);
+}
+
+/*!
+ * @brief decomposes far value of perspective projection
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] farZ far
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_far_lh_no(mat4s proj, float * __restrict farZ) {
+ glm_persp_decomp_far_lh_no(proj.raw, farZ);
+}
+
+/*!
+ * @brief decomposes near value of perspective projection
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_near_lh_no(mat4s proj, float * __restrict nearZ) {
+ glm_persp_decomp_near_lh_no(proj.raw, nearZ);
+}
+
+/*!
+ * @brief returns field of view angle along the Y-axis (in radians)
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * if you need to degrees, use glm_deg to convert it or use this:
+ * fovy_deg = glm_deg(glm_persp_fovy(projMatrix))
+ *
+ * @param[in] proj perspective projection matrix
+ */
+CGLM_INLINE
+float
+glms_persp_fovy_lh_no(mat4s proj) {
+ return glm_persp_fovy_lh_no(proj.raw);
+}
+
+/*!
+ * @brief returns aspect ratio of perspective projection
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ */
+CGLM_INLINE
+float
+glms_persp_aspect_lh_no(mat4s proj) {
+ return glm_persp_aspect_lh_no(proj.raw);
+}
+
+/*!
+ * @brief returns sizes of near and far planes of perspective projection
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[in] fovy fovy (see brief)
+ * @returns sizes as vector, sizes order: [Wnear, Hnear, Wfar, Hfar]
+ */
+CGLM_INLINE
+vec4s
+glms_persp_sizes_lh_no(mat4s proj, float fovy) {
+ vec4s dest;
+ glm_persp_sizes_lh_no(proj.raw, fovy, dest.raw);
+ return dest;
+}
+
+#endif /* cglms_persp_lh_no_h */
diff --git a/libs/cglm/include/cglm/struct/clipspace/persp_lh_zo.h b/libs/cglm/include/cglm/struct/clipspace/persp_lh_zo.h
new file mode 100644
index 0000000..230301f
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/clipspace/persp_lh_zo.h
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), htt../opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE mat4s glms_frustum_lh_zo(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ)
+ CGLM_INLINE mat4s glms_perspective_lh_zo(float fovy,
+ float aspect,
+ float nearZ,
+ float farZ)
+ CGLM_INLINE void glms_persp_move_far_lh_zo(mat4s proj, float deltaFar)
+ CGLM_INLINE mat4s glms_perspective_default_lh_zo(float aspect)
+ CGLM_INLINE void glms_perspective_resize_lh_zo(mat4s proj, float aspect)
+ CGLM_INLINE void glms_persp_decomp_lh_zo(mat4s proj,
+ float *nearv, float *farv,
+ float *top, float *bottom,
+ float *left, float *right)
+ CGLM_INLINE void glms_persp_decompv_lh_zo(mat4s proj, float dest[6])
+ CGLM_INLINE void glms_persp_decomp_x_lh_zo(mat4s proj, float *left, float *right)
+ CGLM_INLINE void glms_persp_decomp_y_lh_zo(mat4s proj, float *top, float *bottom)
+ CGLM_INLINE void glms_persp_decomp_z_lh_zo(mat4s proj, float *nearv, float *farv)
+ CGLM_INLINE void glms_persp_decomp_far_lh_zo(mat4s proj, float *farZ)
+ CGLM_INLINE void glms_persp_decomp_near_lh_zo(mat4s proj, float *nearZ)
+ CGLM_INLINE float glms_persp_fovy_lh_zo(mat4s proj)
+ CGLM_INLINE float glms_persp_aspect_lh_zo(mat4s proj)
+ CGLM_INLINE vec4s glms_persp_sizes_lh_zo(mat4s proj, float fovy)
+ */
+
+#ifndef cglms_persp_lh_zo_h
+#define cglms_persp_lh_zo_h
+
+#include "../../common.h"
+#include "../../types-struct.h"
+#include "../../plane.h"
+#include "../../cam.h"
+
+/*!
+ * @brief set up perspective peprojection matrix
+ * with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] left viewport.left
+ * @param[in] right viewport.right
+ * @param[in] bottom viewport.bottom
+ * @param[in] top viewport.top
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping plane
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_frustum_lh_zo(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ) {
+ mat4s dest;
+ glm_frustum_lh_zo(left, right, bottom, top, nearZ, farZ, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief set up perspective projection matrix
+ * with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] fovy field of view angle
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping planes
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_perspective_lh_zo(float fovy, float aspect, float nearZ, float farZ) {
+ mat4s dest;
+ glm_perspective_lh_zo(fovy, aspect, nearZ, farZ, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief extend perspective projection matrix's far distance
+ * with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * NOTE: if you dodn't want to create new matrix then use array api on struct.raw
+ * like glms_persp_move_far_lh_zo(prooj.raw, deltaFar) to avoid create new mat4
+ * each time
+ *
+ * this function does not guarantee far >= near, be aware of that!
+ *
+ * @param[in, out] proj projection matrix to extend
+ * @param[in] deltaFar distance from existing far (negative to shink)
+ */
+CGLM_INLINE
+mat4s
+glms_persp_move_far_lh_zo(mat4s proj, float deltaFar) {
+ mat4s dest;
+ dest = proj;
+ glm_persp_move_far_lh_zo(dest.raw, deltaFar);
+ return dest;
+}
+
+/*!
+ * @brief set up perspective projection matrix with default near/far
+ * and angle values with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_perspective_default_lh_zo(float aspect) {
+ mat4s dest;
+ glm_perspective_default_lh_zo(aspect, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief resize perspective matrix by aspect ratio ( width / height )
+ * this makes very easy to resize proj matrix when window /viewport
+ * reized with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * NOTE: if you dodn't want to create new matrix then use array api on struct.raw
+ * like glms_perspective_resize_lh_zo(proj.raw, aspect) to avoid create new mat4
+ * each time
+ *
+ * @param[in, out] proj perspective projection matrix
+ * @param[in] aspect aspect ratio ( width / height )
+ */
+CGLM_INLINE
+mat4s
+glms_perspective_resize_lh_zo(mat4s proj, float aspect) {
+ mat4s dest;
+ dest = proj;
+ glm_perspective_resize_lh_zo(aspect, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief decomposes frustum values of perspective projection.
+ * with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ * @param[out] farZ far
+ * @param[out] top top
+ * @param[out] bottom bottom
+ * @param[out] left left
+ * @param[out] right right
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_lh_zo(mat4s proj,
+ float * __restrict nearZ, float * __restrict farZ,
+ float * __restrict top, float * __restrict bottom,
+ float * __restrict left, float * __restrict right) {
+ glm_persp_decomp_lh_zo(proj.raw, nearZ, farZ, top, bottom, left, right);
+}
+
+/*!
+ * @brief decomposes frustum values of perspective projection.
+ * this makes easy to get all values at once
+ * with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] dest array
+ */
+CGLM_INLINE
+void
+glms_persp_decompv_lh_zo(mat4s proj, float dest[6]) {
+ glm_persp_decompv_lh_zo(proj.raw, dest);
+}
+
+/*!
+ * @brief decomposes left and right values of perspective projection
+ * with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ * x stands for x axis (left / right axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] left left
+ * @param[out] right right
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_x_lh_zo(mat4s proj,
+ float * __restrict left,
+ float * __restrict right) {
+ glm_persp_decomp_x_lh_zo(proj.raw, left, right);
+}
+
+/*!
+ * @brief decomposes top and bottom values of perspective projection
+ * with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ * y stands for y axis (top / botom axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] top top
+ * @param[out] bottom bottom
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_y_lh_zo(mat4s proj,
+ float * __restrict top,
+ float * __restrict bottom) {
+ glm_persp_decomp_y_lh_zo(proj.raw, top, bottom);
+}
+
+/*!
+ * @brief decomposes near and far values of perspective projection
+ * with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ * z stands for z axis (near / far axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ * @param[out] farZ far
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_z_lh_zo(mat4s proj,
+ float * __restrict nearZ,
+ float * __restrict farZ) {
+ glm_persp_decomp_z_lh_zo(proj.raw, nearZ, farZ);
+}
+
+/*!
+ * @brief decomposes far value of perspective projection
+ * with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] farZ far
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_far_lh_zo(mat4s proj, float * __restrict farZ) {
+ glm_persp_decomp_far_lh_zo(proj.raw, farZ);
+}
+
+/*!
+ * @brief decomposes near value of perspective projection
+ * with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_near_lh_zo(mat4s proj, float * __restrict nearZ) {
+ glm_persp_decomp_near_lh_zo(proj.raw, nearZ);
+}
+
+/*!
+ * @brief returns field of view angle along the Y-axis (in radians)
+ * with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * if you need to degrees, use glm_deg to convert it or use this:
+ * fovy_deg = glm_deg(glm_persp_fovy(projMatrix))
+ *
+ * @param[in] proj perspective projection matrix
+ */
+CGLM_INLINE
+float
+glms_persp_fovy_lh_zo(mat4s proj) {
+ return glm_persp_fovy_lh_zo(proj.raw);
+}
+
+/*!
+ * @brief returns aspect ratio of perspective projection
+ * with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ */
+CGLM_INLINE
+float
+glms_persp_aspect_lh_zo(mat4s proj) {
+ return glm_persp_aspect_lh_zo(proj.raw);
+}
+
+/*!
+ * @brief returns sizes of near and far planes of perspective projection
+ * with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[in] fovy fovy (see brief)
+ * @returns sizes as vector, sizes order: [Wnear, Hnear, Wfar, Hfar]
+ */
+CGLM_INLINE
+vec4s
+glms_persp_sizes_lh_zo(mat4s proj, float fovy) {
+ vec4s dest;
+ glm_persp_sizes_lh_zo(proj.raw, fovy, dest.raw);
+ return dest;
+}
+
+#endif /* cglms_persp_lh_zo_h */
diff --git a/libs/cglm/include/cglm/struct/clipspace/persp_rh_no.h b/libs/cglm/include/cglm/struct/clipspace/persp_rh_no.h
new file mode 100644
index 0000000..7170e9a
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/clipspace/persp_rh_no.h
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), htt../opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE mat4s glms_frustum_rh_no(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ)
+ CGLM_INLINE mat4s glms_perspective_rh_no(float fovy,
+ float aspect,
+ float nearZ,
+ float farZ)
+ CGLM_INLINE void glms_persp_move_far_rh_no(mat4s proj, float deltaFar)
+ CGLM_INLINE mat4s glms_perspective_default_rh_no(float aspect)
+ CGLM_INLINE void glms_perspective_resize_rh_no(mat4s proj, float aspect)
+ CGLM_INLINE void glms_persp_decomp_rh_no(mat4s proj,
+ float *nearv, float *farv,
+ float *top, float *bottom,
+ float *left, float *right)
+ CGLM_INLINE void glms_persp_decompv_rh_no(mat4s proj, float dest[6])
+ CGLM_INLINE void glms_persp_decomp_x_rh_no(mat4s proj, float *left, float *right)
+ CGLM_INLINE void glms_persp_decomp_y_rh_no(mat4s proj, float *top, float *bottom)
+ CGLM_INLINE void glms_persp_decomp_z_rh_no(mat4s proj, float *nearv, float *farv)
+ CGLM_INLINE void glms_persp_decomp_far_rh_no(mat4s proj, float *farZ)
+ CGLM_INLINE void glms_persp_decomp_near_rh_no(mat4s proj, float *nearZ)
+ CGLM_INLINE float glms_persp_fovy_rh_no(mat4s proj)
+ CGLM_INLINE float glms_persp_aspect_rh_no(mat4s proj)
+ CGLM_INLINE vec4s glms_persp_sizes_rh_no(mat4s proj, float fovy)
+ */
+
+#ifndef cglms_persp_rh_no_h
+#define cglms_persp_rh_no_h
+
+#include "../../common.h"
+#include "../../types-struct.h"
+#include "../../plane.h"
+#include "../../cam.h"
+
+/*!
+ * @brief set up perspective peprojection matrix
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] left viewport.left
+ * @param[in] right viewport.right
+ * @param[in] bottom viewport.bottom
+ * @param[in] top viewport.top
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping plane
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_frustum_rh_no(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ) {
+ mat4s dest;
+ glm_frustum_rh_no(left, right, bottom, top, nearZ, farZ, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief set up perspective projection matrix
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] fovy field of view angle
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping planes
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_perspective_rh_no(float fovy, float aspect, float nearZ, float farZ) {
+ mat4s dest;
+ glm_perspective_rh_no(fovy, aspect, nearZ, farZ, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief extend perspective projection matrix's far distance
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * NOTE: if you dodn't want to create new matrix then use array api on struct.raw
+ * like glms_persp_move_far_rh_no(prooj.raw, deltaFar) to avoid create new mat4
+ * each time
+ * s
+ * this function does not guarantee far >= near, be aware of that!
+ *
+ * @param[in, out] proj projection matrix to extend
+ * @param[in] deltaFar distance from existing far (negative to shink)
+ */
+CGLM_INLINE
+mat4s
+glms_persp_move_far_rh_no(mat4s proj, float deltaFar) {
+ mat4s dest;
+ dest = proj;
+ glm_persp_move_far_rh_no(dest.raw, deltaFar);
+ return dest;
+}
+
+/*!
+ * @brief set up perspective projection matrix with default near/far
+ * and angle values with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_perspective_default_rh_no(float aspect) {
+ mat4s dest;
+ glm_perspective_default_rh_no(aspect, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief resize perspective matrix by aspect ratio ( width / height )
+ * this makes very easy to resize proj matrix when window /viewport
+ * reized with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * NOTE: if you dodn't want to create new matrix then use array api on struct.raw
+ * like glm_perspective_resize_rh_no(proj.raw, aspect) to avoid create new mat4
+ * each time
+ *
+ * @param[in, out] proj perspective projection matrix
+ * @param[in] aspect aspect ratio ( width / height )
+ */
+CGLM_INLINE
+mat4s
+glms_perspective_resize_rh_no(mat4s proj, float aspect) {
+ mat4s dest;
+ dest = proj;
+ glm_perspective_resize_rh_no(aspect, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief decomposes frustum values of perspective projection.
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ * @param[out] farZ far
+ * @param[out] top top
+ * @param[out] bottom bottom
+ * @param[out] left left
+ * @param[out] right right
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_rh_no(mat4s proj,
+ float * __restrict nearZ, float * __restrict farZ,
+ float * __restrict top, float * __restrict bottom,
+ float * __restrict left, float * __restrict right) {
+ glm_persp_decomp_rh_no(proj.raw, nearZ, farZ, top, bottom, left, right);
+}
+
+/*!
+ * @brief decomposes frustum values of perspective projection.
+ * this makes easy to get all values at once
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] dest array
+ */
+CGLM_INLINE
+void
+glms_persp_decompv_rh_no(mat4s proj, float dest[6]) {
+ glm_persp_decompv_rh_no(proj.raw, dest);
+}
+
+/*!
+ * @brief decomposes left and right values of perspective projection
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ * x stands for x axis (left / right axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] left left
+ * @param[out] right right
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_x_rh_no(mat4s proj,
+ float * __restrict left,
+ float * __restrict right) {
+ glm_persp_decomp_x_rh_no(proj.raw, left, right);
+}
+
+/*!
+ * @brief decomposes top and bottom values of perspective projection
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ * y stands for y axis (top / botom axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] top top
+ * @param[out] bottom bottom
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_y_rh_no(mat4s proj,
+ float * __restrict top,
+ float * __restrict bottom) {
+ glm_persp_decomp_y_rh_no(proj.raw, top, bottom);
+}
+
+/*!
+ * @brief decomposes near and far values of perspective projection
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ * z stands for z axis (near / far axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ * @param[out] farZ far
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_z_rh_no(mat4s proj,
+ float * __restrict nearZ,
+ float * __restrict farZ) {
+ glm_persp_decomp_z_rh_no(proj.raw, nearZ, farZ);
+}
+
+/*!
+ * @brief decomposes far value of perspective projection
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] farZ far
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_far_rh_no(mat4s proj, float * __restrict farZ) {
+ glm_persp_decomp_far_rh_no(proj.raw, farZ);
+}
+
+/*!
+ * @brief decomposes near value of perspective projection
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_near_rh_no(mat4s proj, float * __restrict nearZ) {
+ glm_persp_decomp_near_rh_no(proj.raw, nearZ);
+}
+
+/*!
+ * @brief returns field of view angle along the Y-axis (in radians)
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * if you need to degrees, use glm_deg to convert it or use this:
+ * fovy_deg = glm_deg(glm_persp_fovy(projMatrix))
+ *
+ * @param[in] proj perspective projection matrix
+ */
+CGLM_INLINE
+float
+glms_persp_fovy_rh_no(mat4s proj) {
+ return glm_persp_fovy_rh_no(proj.raw);
+}
+
+/*!
+ * @brief returns aspect ratio of perspective projection
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ */
+CGLM_INLINE
+float
+glms_persp_aspect_rh_no(mat4s proj) {
+ return glm_persp_aspect_rh_no(proj.raw);
+}
+
+/*!
+ * @brief returns sizes of near and far planes of perspective projection
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[in] fovy fovy (see brief)
+ * @returns sizes as vector, sizes order: [Wnear, Hnear, Wfar, Hfar]
+ */
+CGLM_INLINE
+vec4s
+glms_persp_sizes_rh_no(mat4s proj, float fovy) {
+ vec4s dest;
+ glm_persp_sizes_rh_no(proj.raw, fovy, dest.raw);
+ return dest;
+}
+
+#endif /* cglms_persp_rh_no_h */
diff --git a/libs/cglm/include/cglm/struct/clipspace/persp_rh_zo.h b/libs/cglm/include/cglm/struct/clipspace/persp_rh_zo.h
new file mode 100644
index 0000000..ff4d8de
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/clipspace/persp_rh_zo.h
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), htt../opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE mat4s glms_frustum_rh_zo(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ)
+ CGLM_INLINE mat4s glms_perspective_rh_zo(float fovy,
+ float aspect,
+ float nearZ,
+ float farZ)
+ CGLM_INLINE void glms_persp_move_far_rh_zo(mat4s proj, float deltaFar)
+ CGLM_INLINE mat4s glms_perspective_default_rh_zo(float aspect)
+ CGLM_INLINE void glms_perspective_resize_rh_zo(mat4s proj, float aspect)
+ CGLM_INLINE void glms_persp_decomp_rh_zo(mat4s proj,
+ float *nearv, float *farv,
+ float *top, float *bottom,
+ float *left, float *right)
+ CGLM_INLINE void glms_persp_decompv_rh_zo(mat4s proj, float dest[6])
+ CGLM_INLINE void glms_persp_decomp_x_rh_zo(mat4s proj, float *left, float *right)
+ CGLM_INLINE void glms_persp_decomp_y_rh_zo(mat4s proj, float *top, float *bottom)
+ CGLM_INLINE void glms_persp_decomp_z_rh_zo(mat4s proj, float *nearv, float *farv)
+ CGLM_INLINE void glms_persp_decomp_far_rh_zo(mat4s proj, float *farZ)
+ CGLM_INLINE void glms_persp_decomp_near_rh_zo(mat4s proj, float *nearZ)
+ CGLM_INLINE float glms_persp_fovy_rh_zo(mat4s proj)
+ CGLM_INLINE float glms_persp_aspect_rh_zo(mat4s proj)
+ CGLM_INLINE vec4s glms_persp_sizes_rh_zo(mat4s proj, float fovy)
+ */
+
+#ifndef cglms_persp_rh_zo_h
+#define cglms_persp_rh_zo_h
+
+#include "../../common.h"
+#include "../../types-struct.h"
+#include "../../plane.h"
+#include "../../cam.h"
+
+/*!
+ * @brief set up perspective peprojection matrix
+ * with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] left viewport.left
+ * @param[in] right viewport.right
+ * @param[in] bottom viewport.bottom
+ * @param[in] top viewport.top
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping plane
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_frustum_rh_zo(float left, float right,
+ float bottom, float top,
+ float nearZ, float farZ) {
+ mat4s dest;
+ glm_frustum_rh_zo(left, right, bottom, top, nearZ, farZ, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief set up perspective projection matrix
+ * with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] fovy field of view angle
+ * @param[in] aspect aspect ratio ( width / height )
+ * @param[in] nearZ near clipping plane
+ * @param[in] farZ far clipping planes
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_perspective_rh_zo(float fovy, float aspect, float nearZ, float farZ) {
+ mat4s dest;
+ glm_perspective_rh_zo(fovy, aspect, nearZ, farZ, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief extend perspective projection matrix's far distance
+ * with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * NOTE: if you dodn't want to create new matrix then use array api on struct.raw
+ * like glms_persp_move_far_rh_zo(prooj.raw, deltaFar) to avoid create new mat4
+ * each time
+ *
+ * this function does not guarantee far >= near, be aware of that!
+ *
+ * @param[in, out] proj projection matrix to extend
+ * @param[in] deltaFar distance from existing far (negative to shink)
+ */
+CGLM_INLINE
+mat4s
+glms_persp_move_far_rh_zo(mat4s proj, float deltaFar) {
+ mat4s dest;
+ dest = proj;
+ glm_persp_move_far_rh_zo(dest.raw, deltaFar);
+ return dest;
+}
+
+/*!
+ * @brief set up perspective projection matrix with default near/far
+ * and angle values with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] aspect aspect ratio ( width / height )
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_perspective_default_rh_zo(float aspect) {
+ mat4s dest;
+ glm_perspective_default_rh_zo(aspect, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief resize perspective matrix by aspect ratio ( width / height )
+ * this makes very easy to resize proj matrix when window /viewport
+ * reized with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * NOTE: if you dodn't want to create new matrix then use array api on struct.raw
+ * like glm_perspective_resize_rh_zo(proj.raw, aspect) to avoid create new mat4
+ * each time
+ *
+ * @param[in, out] proj perspective projection matrix
+ * @param[in] aspect aspect ratio ( width / height )
+ */
+CGLM_INLINE
+mat4s
+glms_perspective_resize_rh_zo(mat4s proj, float aspect) {
+ mat4s dest;
+ dest = proj;
+ glm_perspective_resize_rh_zo(aspect, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief decomposes frustum values of perspective projection.
+ * with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ * @param[out] farZ far
+ * @param[out] top top
+ * @param[out] bottom bottom
+ * @param[out] left left
+ * @param[out] right right
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_rh_zo(mat4s proj,
+ float * __restrict nearZ, float * __restrict farZ,
+ float * __restrict top, float * __restrict bottom,
+ float * __restrict left, float * __restrict right) {
+ glm_persp_decomp_rh_zo(proj.raw, nearZ, farZ, top, bottom, left, right);
+}
+
+/*!
+ * @brief decomposes frustum values of perspective projection.
+ * this makes easy to get all values at once
+ * with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] dest array
+ */
+CGLM_INLINE
+void
+glms_persp_decompv_rh_zo(mat4s proj, float dest[6]) {
+ glm_persp_decompv_rh_zo(proj.raw, dest);
+}
+
+/*!
+ * @brief decomposes left and right values of perspective projection
+ * with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ * x stands for x axis (left / right axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] left left
+ * @param[out] right right
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_x_rh_zo(mat4s proj,
+ float * __restrict left,
+ float * __restrict right) {
+ glm_persp_decomp_x_rh_zo(proj.raw, left, right);
+}
+
+/*!
+ * @brief decomposes top and bottom values of perspective projection
+ * with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ * y stands for y axis (top / botom axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] top top
+ * @param[out] bottom bottom
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_y_rh_zo(mat4s proj,
+ float * __restrict top,
+ float * __restrict bottom) {
+ glm_persp_decomp_y_rh_zo(proj.raw, top, bottom);
+}
+
+/*!
+ * @brief decomposes near and far values of perspective projection
+ * with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ * z stands for z axis (near / far axis)
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ * @param[out] farZ far
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_z_rh_zo(mat4s proj,
+ float * __restrict nearZ,
+ float * __restrict farZ) {
+ glm_persp_decomp_z_rh_zo(proj.raw, nearZ, farZ);
+}
+
+/*!
+ * @brief decomposes far value of perspective projection
+ * with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] farZ far
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_far_rh_zo(mat4s proj, float * __restrict farZ) {
+ glm_persp_decomp_far_rh_zo(proj.raw, farZ);
+}
+
+/*!
+ * @brief decomposes near value of perspective projection
+ * with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[out] nearZ near
+ */
+CGLM_INLINE
+void
+glms_persp_decomp_near_rh_zo(mat4s proj, float * __restrict nearZ) {
+ glm_persp_decomp_near_rh_zo(proj.raw, nearZ);
+}
+
+/*!
+ * @brief returns field of view angle along the Y-axis (in radians)
+ * with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * if you need to degrees, use glm_deg to convert it or use this:
+ * fovy_deg = glm_deg(glm_persp_fovy(projMatrix))
+ *
+ * @param[in] proj perspective projection matrix
+ */
+CGLM_INLINE
+float
+glms_persp_fovy_rh_zo(mat4s proj) {
+ return glm_persp_fovy_rh_zo(proj.raw);
+}
+
+/*!
+ * @brief returns aspect ratio of perspective projection
+ * with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ */
+CGLM_INLINE
+float
+glms_persp_aspect_rh_zo(mat4s proj) {
+ return glm_persp_aspect_rh_zo(proj.raw);
+}
+
+/*!
+ * @brief returns sizes of near and far planes of perspective projection
+ * with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * @param[in] proj perspective projection matrix
+ * @param[in] fovy fovy (see brief)
+ * @returns sizes as vector, sizes order: [Wnear, Hnear, Wfar, Hfar]
+ */
+CGLM_INLINE
+vec4s
+glms_persp_sizes_rh_zo(mat4s proj, float fovy) {
+ vec4s dest;
+ glm_persp_sizes_rh_zo(proj.raw, fovy, dest.raw);
+ return dest;
+}
+
+#endif /* cglms_persp_rh_zo_h */
diff --git a/libs/cglm/include/cglm/struct/clipspace/view_lh_no.h b/libs/cglm/include/cglm/struct/clipspace/view_lh_no.h
new file mode 100644
index 0000000..bb5eed6
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/clipspace/view_lh_no.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), htt../opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE mat4s glms_lookat_lh_no(vec3s eye, vec3s center, vec3s up)
+ CGLM_INLINE mat4s glms_look_lh_no(vec3s eye, vec3s dir, vec3s up)
+ CGLM_INLINE mat4s glms_look_anyup_lh_no(vec3s eye, vec3s dir)
+ */
+
+#ifndef cglms_view_lh_no_h
+#define cglms_view_lh_no_h
+
+#include "../../common.h"
+#include "../../types-struct.h"
+#include "../../plane.h"
+#include "../../cam.h"
+
+/*!
+ * @brief set up view matrix
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * NOTE: The UP vector must not be parallel to the line of sight from
+ * the eye point to the reference point
+ *
+ * @param[in] eye eye vector
+ * @param[in] center center vector
+ * @param[in] up up vector
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_lookat_lh_no(vec3s eye, vec3s center, vec3s up) {
+ mat4s dest;
+ glm_lookat_lh_no(eye.raw, center.raw, up.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief set up view matrix
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * convenient wrapper for lookat: if you only have direction not target self
+ * then this might be useful. Because you need to get target from direction.
+ *
+ * NOTE: The UP vector must not be parallel to the line of sight from
+ * the eye point to the reference point
+ *
+ * @param[in] eye eye vector
+ * @param[in] dir direction vector
+ * @param[in] up up vector
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_look_lh_no(vec3s eye, vec3s dir, vec3s up) {
+ mat4s dest;
+ glm_look_lh_no(eye.raw, dir.raw, up.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief set up view matrix
+ * with a left-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * convenient wrapper for look: if you only have direction and if you don't
+ * care what UP vector is then this might be useful to create view matrix
+ *
+ * @param[in] eye eye vector
+ * @param[in] dir direction vector
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_look_anyup_lh_no(vec3s eye, vec3s dir) {
+ mat4s dest;
+ glm_look_anyup_lh_no(eye.raw, dir.raw, dest.raw);
+ return dest;
+}
+
+#endif /* cglms_view_lh_no_h */
diff --git a/libs/cglm/include/cglm/struct/clipspace/view_lh_zo.h b/libs/cglm/include/cglm/struct/clipspace/view_lh_zo.h
new file mode 100644
index 0000000..322fdf6
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/clipspace/view_lh_zo.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), htt../opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE mat4s glms_lookat_lh_zo(vec3s eye, vec3s center, vec3s up)
+ CGLM_INLINE mat4s glms_look_lh_zo(vec3s eye, vec3s dir, vec3s up)
+ CGLM_INLINE mat4s glms_look_anyup_lh_zo(vec3s eye, vec3s dir)
+ */
+
+#ifndef cglms_view_lh_zo_h
+#define cglms_view_lh_zo_h
+
+#include "../../common.h"
+#include "../../types-struct.h"
+#include "../../plane.h"
+#include "../../cam.h"
+
+/*!
+ * @brief set up view matrix
+ * with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * NOTE: The UP vector must not be parallel to the line of sight from
+ * the eye point to the reference point
+ *
+ * @param[in] eye eye vector
+ * @param[in] center center vector
+ * @param[in] up up vector
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_lookat_lh_zo(vec3s eye, vec3s center, vec3s up) {
+ mat4s dest;
+ glm_lookat_lh_zo(eye.raw, center.raw, up.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief set up view matrix
+ * with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * convenient wrapper for lookat: if you only have direction not target self
+ * then this might be useful. Because you need to get target from direction.
+ *
+ * NOTE: The UP vector must not be parallel to the line of sight from
+ * the eye point to the reference point
+ *
+ * @param[in] eye eye vector
+ * @param[in] dir direction vector
+ * @param[in] up up vector
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_look_lh_zo(vec3s eye, vec3s dir, vec3s up) {
+ mat4s dest;
+ glm_look_lh_zo(eye.raw, dir.raw, up.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief set up view matrix
+ * with a left-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * convenient wrapper for look: if you only have direction and if you don't
+ * care what UP vector is then this might be useful to create view matrix
+ *
+ * @param[in] eye eye vector
+ * @param[in] dir direction vector
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_look_anyup_lh_zo(vec3s eye, vec3s dir) {
+ mat4s dest;
+ glm_look_anyup_lh_zo(eye.raw, dir.raw, dest.raw);
+ return dest;
+}
+
+#endif /* cglms_view_lh_zo_h */
diff --git a/libs/cglm/include/cglm/struct/clipspace/view_rh_no.h b/libs/cglm/include/cglm/struct/clipspace/view_rh_no.h
new file mode 100644
index 0000000..df82b1d
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/clipspace/view_rh_no.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), htt../opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE mat4s glms_lookat_rh_no(vec3s eye, vec3s center, vec3s up)
+ CGLM_INLINE mat4s glms_look_rh_no(vec3s eye, vec3s dir, vec3s up)
+ CGLM_INLINE mat4s glms_look_anyup_rh_no(vec3s eye, vec3s dir)
+ */
+
+#ifndef cglms_view_rh_no_h
+#define cglms_view_rh_no_h
+
+#include "../../common.h"
+#include "../../types-struct.h"
+#include "../../plane.h"
+#include "../../cam.h"
+
+/*!
+ * @brief set up view matrix
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * NOTE: The UP vector must not be parallel to the line of sight from
+ * the eye point to the reference point
+ *
+ * @param[in] eye eye vector
+ * @param[in] center center vector
+ * @param[in] up up vector
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_lookat_rh_no(vec3s eye, vec3s center, vec3s up) {
+ mat4s dest;
+ glm_lookat_rh_no(eye.raw, center.raw, up.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief set up view matrix
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * convenient wrapper for lookat: if you only have direction not target self
+ * then this might be useful. Because you need to get target from direction.
+ *
+ * NOTE: The UP vector must not be parallel to the line of sight from
+ * the eye point to the reference point
+ *
+ * @param[in] eye eye vector
+ * @param[in] dir direction vector
+ * @param[in] up up vector
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_look_rh_no(vec3s eye, vec3s dir, vec3s up) {
+ mat4s dest;
+ glm_look_rh_no(eye.raw, dir.raw, up.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief set up view matrix
+ * with a right-hand coordinate system and a
+ * clip-space of [-1, 1].
+ *
+ * convenient wrapper for look: if you only have direction and if you don't
+ * care what UP vector is then this might be useful to create view matrix
+ *
+ * @param[in] eye eye vector
+ * @param[in] dir direction vector
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_look_anyup_rh_no(vec3s eye, vec3s dir) {
+ mat4s dest;
+ glm_look_anyup_rh_no(eye.raw, dir.raw, dest.raw);
+ return dest;
+}
+
+#endif /* cglms_view_rh_no_h */
diff --git a/libs/cglm/include/cglm/struct/clipspace/view_rh_zo.h b/libs/cglm/include/cglm/struct/clipspace/view_rh_zo.h
new file mode 100644
index 0000000..5097bc8
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/clipspace/view_rh_zo.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), htt../opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE mat4s glms_lookat_rh_zo(vec3s eye, vec3s center, vec3s up)
+ CGLM_INLINE mat4s glms_look_rh_zo(vec3s eye, vec3s dir, vec3s up)
+ CGLM_INLINE mat4s glms_look_anyup_rh_zo(vec3s eye, vec3s dir)
+ */
+
+#ifndef cglms_view_rh_zo_h
+#define cglms_view_rh_zo_h
+
+#include "../../common.h"
+#include "../../types-struct.h"
+#include "../../plane.h"
+#include "../../cam.h"
+
+/*!
+ * @brief set up view matrix
+ * with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * NOTE: The UP vector must not be parallel to the line of sight from
+ * the eye point to the reference point
+ *
+ * @param[in] eye eye vector
+ * @param[in] center center vector
+ * @param[in] up up vector
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_lookat_rh_zo(vec3s eye, vec3s center, vec3s up) {
+ mat4s dest;
+ glm_lookat_rh_zo(eye.raw, center.raw, up.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief set up view matrix
+ * with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * convenient wrapper for lookat: if you only have direction not target self
+ * then this might be useful. Because you need to get target from direction.
+ *
+ * NOTE: The UP vector must not be parallel to the line of sight from
+ * the eye point to the reference point
+ *
+ * @param[in] eye eye vector
+ * @param[in] dir direction vector
+ * @param[in] up up vector
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_look_rh_zo(vec3s eye, vec3s dir, vec3s up) {
+ mat4s dest;
+ glm_look_rh_zo(eye.raw, dir.raw, up.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief set up view matrix
+ * with a right-hand coordinate system and a
+ * clip-space of [0, 1].
+ *
+ * convenient wrapper for look: if you only have direction and if you don't
+ * care what UP vector is then this might be useful to create view matrix
+ *
+ * @param[in] eye eye vector
+ * @param[in] dir direction vector
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_look_anyup_rh_zo(vec3s eye, vec3s dir) {
+ mat4s dest;
+ glm_look_anyup_rh_zo(eye.raw, dir.raw, dest.raw);
+ return dest;
+}
+
+#endif /* cglms_view_rh_zo_h */
diff --git a/libs/cglm/include/cglm/struct/color.h b/libs/cglm/include/cglm/struct/color.h
new file mode 100644
index 0000000..3ce78da
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/color.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglms_colors_h
+#define cglms_colors_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../color.h"
+#include "vec3.h"
+
+/*!
+ * @brief averages the color channels into one value
+ *
+ * @param[in] rgb RGB color
+ */
+CGLM_INLINE
+float
+glms_luminance(vec3s rgb) {
+ return glm_luminance(rgb.raw);
+}
+
+#endif /* cglms_colors_h */
diff --git a/libs/cglm/include/cglm/struct/curve.h b/libs/cglm/include/cglm/struct/curve.h
new file mode 100644
index 0000000..53ea359
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/curve.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglms_curves_h
+#define cglms_curves_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../curve.h"
+#include "vec4.h"
+#include "mat4.h"
+
+/*!
+ * @brief helper function to calculate S*M*C multiplication for curves
+ *
+ * This function does not encourage you to use SMC,
+ * instead it is a helper if you use SMC.
+ *
+ * if you want to specify S as vector then use more generic glm_mat4_rmc() func.
+ *
+ * Example usage:
+ * B(s) = glm_smc(s, GLM_BEZIER_MAT, (vec4){p0, c0, c1, p1})
+ *
+ * @param[in] s parameter between 0 and 1 (this will be [s3, s2, s, 1])
+ * @param[in] m basis matrix
+ * @param[in] c position/control vector
+ *
+ * @return B(s)
+ */
+CGLM_INLINE
+float
+glms_smc(float s, mat4s m, vec4s c) {
+ return glm_smc(s, m.raw, c.raw);
+}
+
+#endif /* cglms_curves_h */
diff --git a/libs/cglm/include/cglm/struct/euler.h b/libs/cglm/include/cglm/struct/euler.h
new file mode 100644
index 0000000..6575930
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/euler.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ NOTE:
+ angles must be passed as [X-Angle, Y-Angle, Z-angle] order
+ For instance you don't pass angles as [Z-Angle, X-Angle, Y-angle] to
+ glm_euler_zxy funciton, All RELATED functions accept angles same order
+ which is [X, Y, Z].
+ */
+
+/*
+ Types:
+ enum glm_euler_seq
+
+ Functions:
+ CGLM_INLINE vec3s glms_euler_angles(mat4s m)
+ CGLM_INLINE mat4s glms_euler_xyz(vec3s angles)
+ CGLM_INLINE mat4s glms_euler_xzy(vec3s angles)
+ CGLM_INLINE mat4s glms_euler_yxz(vec3s angles)
+ CGLM_INLINE mat4s glms_euler_yzx(vec3s angles)
+ CGLM_INLINE mat4s glms_euler_zxy(vec3s angles)
+ CGLM_INLINE mat4s glms_euler_zyx(vec3s angles)
+ CGLM_INLINE mat4s glms_euler_by_order(vec3s angles, glm_euler_seq ord)
+ */
+
+#ifndef cglms_euler_h
+#define cglms_euler_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../euler.h"
+
+/*!
+ * @brief extract euler angles (in radians) using xyz order
+ *
+ * @param[in] m affine transform
+ * @returns angles vector [x, y, z]
+ */
+CGLM_INLINE
+vec3s
+glms_euler_angles(mat4s m) {
+ vec3s dest;
+ glm_euler_angles(m.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief build rotation matrix from euler angles
+ *
+ * @param[in] angles angles as vector [Xangle, Yangle, Zangle]
+ * @returns rotation matrix
+ */
+CGLM_INLINE
+mat4s
+glms_euler_xyz(vec3s angles) {
+ mat4s dest;
+ glm_euler_xyz(angles.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief build rotation matrix from euler angles
+ *
+ * @param[in] angles angles as vector [Xangle, Yangle, Zangle]
+ * @returns rotation matrix
+ */
+CGLM_INLINE
+mat4s
+glms_euler_xzy(vec3s angles) {
+ mat4s dest;
+ glm_euler_xzy(angles.raw, dest.raw);
+ return dest;
+}
+
+
+/*!
+ * @brief build rotation matrix from euler angles
+ *
+ * @param[in] angles angles as vector [Xangle, Yangle, Zangle]
+ * @returns rotation matrix
+ */
+CGLM_INLINE
+mat4s
+glms_euler_yxz(vec3s angles) {
+ mat4s dest;
+ glm_euler_yxz(angles.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief build rotation matrix from euler angles
+ *
+ * @param[in] angles angles as vector [Xangle, Yangle, Zangle]
+ * @returns rotation matrix
+ */
+CGLM_INLINE
+mat4s
+glms_euler_yzx(vec3s angles) {
+ mat4s dest;
+ glm_euler_yzx(angles.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief build rotation matrix from euler angles
+ *
+ * @param[in] angles angles as vector [Xangle, Yangle, Zangle]
+ * @returns rotation matrix
+ */
+CGLM_INLINE
+mat4s
+glms_euler_zxy(vec3s angles) {
+ mat4s dest;
+ glm_euler_zxy(angles.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief build rotation matrix from euler angles
+ *
+ * @param[in] angles angles as vector [Xangle, Yangle, Zangle]
+ * @returns rotation matrix
+ */
+CGLM_INLINE
+mat4s
+glms_euler_zyx(vec3s angles) {
+ mat4s dest;
+ glm_euler_zyx(angles.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief build rotation matrix from euler angles
+ *
+ * @param[in] angles angles as vector [Xangle, Yangle, Zangle]
+ * @param[in] ord euler order
+ * @returns rotation matrix
+ */
+CGLM_INLINE
+mat4s
+glms_euler_by_order(vec3s angles, glm_euler_seq ord) {
+ mat4s dest;
+ glm_euler_by_order(angles.raw, ord, dest.raw);
+ return dest;
+}
+
+#endif /* cglms_euler_h */
diff --git a/libs/cglm/include/cglm/struct/frustum.h b/libs/cglm/include/cglm/struct/frustum.h
new file mode 100644
index 0000000..2c51d6d
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/frustum.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglms_frustums_h
+#define cglms_frustums_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../frustum.h"
+#include "plane.h"
+#include "vec3.h"
+#include "vec4.h"
+#include "mat4.h"
+
+/* you can override clip space coords
+ but you have to provide all with same name
+ e.g.: define GLM_CSCOORD_LBN {0.0f, 0.0f, 1.0f, 1.0f} */
+#ifndef GLM_CUSTOM_CLIPSPACE
+
+/* near */
+#define GLMS_CSCOORD_LBN {-1.0f, -1.0f, -1.0f, 1.0f}
+#define GLMS_CSCOORD_LTN {-1.0f, 1.0f, -1.0f, 1.0f}
+#define GLMS_CSCOORD_RTN { 1.0f, 1.0f, -1.0f, 1.0f}
+#define GLMS_CSCOORD_RBN { 1.0f, -1.0f, -1.0f, 1.0f}
+
+/* far */
+#define GLMS_CSCOORD_LBF {-1.0f, -1.0f, 1.0f, 1.0f}
+#define GLMS_CSCOORD_LTF {-1.0f, 1.0f, 1.0f, 1.0f}
+#define GLMS_CSCOORD_RTF { 1.0f, 1.0f, 1.0f, 1.0f}
+#define GLMS_CSCOORD_RBF { 1.0f, -1.0f, 1.0f, 1.0f}
+
+#endif
+
+/*!
+ * @brief extracts view frustum planes
+ *
+ * planes' space:
+ * 1- if m = proj: View Space
+ * 2- if m = viewProj: World Space
+ * 3- if m = MVP: Object Space
+ *
+ * You probably want to extract planes in world space so use viewProj as m
+ * Computing viewProj:
+ * glm_mat4_mul(proj, view, viewProj);
+ *
+ * Exracted planes order: [left, right, bottom, top, near, far]
+ *
+ * @param[in] m matrix (see brief)
+ * @param[out] dest extracted view frustum planes (see brief)
+ */
+CGLM_INLINE
+void
+glms_frustum_planes(mat4s m, vec4s dest[6]) {
+ vec4 rawDest[6];
+ glm_frustum_planes(m.raw, rawDest);
+ glms_vec4_pack(dest, rawDest, 6);
+}
+
+/*!
+ * @brief extracts view frustum corners using clip-space coordinates
+ *
+ * corners' space:
+ * 1- if m = invViewProj: World Space
+ * 2- if m = invMVP: Object Space
+ *
+ * You probably want to extract corners in world space so use invViewProj
+ * Computing invViewProj:
+ * glm_mat4_mul(proj, view, viewProj);
+ * ...
+ * glm_mat4_inv(viewProj, invViewProj);
+ *
+ * if you have a near coord at i index, you can get it's far coord by i + 4
+ *
+ * Find center coordinates:
+ * for (j = 0; j < 4; j++) {
+ * glm_vec3_center(corners[i], corners[i + 4], centerCorners[i]);
+ * }
+ *
+ * @param[in] invMat matrix (see brief)
+ * @param[out] dest exracted view frustum corners (see brief)
+ */
+CGLM_INLINE
+void
+glms_frustum_corners(mat4s invMat, vec4s dest[8]) {
+ vec4 rawDest[8];
+ glm_frustum_corners(invMat.raw, rawDest);
+ glms_vec4_pack(dest, rawDest, 8);
+}
+
+/*!
+ * @brief finds center of view frustum
+ *
+ * @param[in] corners view frustum corners
+ * @returns view frustum center
+ */
+CGLM_INLINE
+vec4s
+glms_frustum_center(vec4s corners[8]) {
+ vec4 rawCorners[8];
+ vec4s r;
+
+ glms_vec4_unpack(rawCorners, corners, 8);
+ glm_frustum_center(rawCorners, r.raw);
+ return r;
+}
+
+/*!
+ * @brief finds bounding box of frustum relative to given matrix e.g. view mat
+ *
+ * @param[in] corners view frustum corners
+ * @param[in] m matrix to convert existing conners
+ * @param[out] box bounding box as array [min, max]
+ */
+CGLM_INLINE
+void
+glms_frustum_box(vec4s corners[8], mat4s m, vec3s box[2]) {
+ vec4 rawCorners[8];
+ vec3 rawBox[2];
+
+ glms_vec4_unpack(rawCorners, corners, 8);
+ glm_frustum_box(rawCorners, m.raw, rawBox);
+ glms_vec3_pack(box, rawBox, 2);
+}
+
+/*!
+ * @brief finds planes corners which is between near and far planes (parallel)
+ *
+ * this will be helpful if you want to split a frustum e.g. CSM/PSSM. This will
+ * find planes' corners but you will need to one more plane.
+ * Actually you have it, it is near, far or created previously with this func ;)
+ *
+ * @param[in] corners view frustum corners
+ * @param[in] splitDist split distance
+ * @param[in] farDist far distance (zFar)
+ * @param[out] planeCorners plane corners [LB, LT, RT, RB]
+ */
+CGLM_INLINE
+void
+glms_frustum_corners_at(vec4s corners[8],
+ float splitDist,
+ float farDist,
+ vec4s planeCorners[4]) {
+ vec4 rawCorners[8];
+ vec4 rawPlaneCorners[4];
+
+ glms_vec4_unpack(rawCorners, corners, 8);
+ glm_frustum_corners_at(rawCorners, splitDist, farDist, rawPlaneCorners);
+ glms_vec4_pack(planeCorners, rawPlaneCorners, 8);
+}
+
+#endif /* cglms_frustums_h */
diff --git a/libs/cglm/include/cglm/struct/io.h b/libs/cglm/include/cglm/struct/io.h
new file mode 100644
index 0000000..ec28129
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/io.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glm_mat4_print(mat4 matrix, FILE *ostream);
+ CGLM_INLINE void glm_mat3_print(mat3 matrix, FILE *ostream);
+ CGLM_INLINE void glm_vec4_print(vec4 vec, FILE *ostream);
+ CGLM_INLINE void glm_vec3_print(vec3 vec, FILE *ostream);
+ CGLM_INLINE void glm_ivec3_print(ivec3 vec, FILE *ostream);
+ CGLM_INLINE void glm_versor_print(versor vec, FILE *ostream);
+ */
+
+#ifndef cglms_ios_h
+#define cglms_ios_h
+
+#include "../common.h"
+#include "../io.h"
+#include "mat4.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+CGLM_INLINE
+void
+glms_mat4_print(mat4s matrix,
+ FILE * __restrict ostream) {
+
+ glm_mat4_print(matrix.raw, ostream);
+}
+
+CGLM_INLINE
+void
+glms_mat3_print(mat3s matrix,
+ FILE * __restrict ostream) {
+ glm_mat3_print(matrix.raw, ostream);
+}
+
+CGLM_INLINE
+void
+glms_vec4_print(vec4s vec,
+ FILE * __restrict ostream) {
+ glm_vec4_print(vec.raw, ostream);
+}
+
+CGLM_INLINE
+void
+glms_vec3_print(vec3s vec,
+ FILE * __restrict ostream) {
+ glm_vec3_print(vec.raw, ostream);
+}
+
+CGLM_INLINE
+void
+glms_ivec3_print(ivec3s vec,
+ FILE * __restrict ostream) {
+ glm_ivec3_print(vec.raw, ostream);
+}
+
+CGLM_INLINE
+void
+glms_versor_print(versors vec,
+ FILE * __restrict ostream) {
+ glm_versor_print(vec.raw, ostream);
+}
+
+CGLM_INLINE
+void
+glms_aabb_print(vec3s bbox[2],
+ const char * __restrict tag,
+ FILE * __restrict ostream) {
+ vec3 rawBbox[2];
+
+ glms_vec3_unpack(rawBbox, bbox, 2);
+ glm_aabb_print(rawBbox, tag, ostream);
+}
+
+#endif /* cglms_ios_h */
diff --git a/libs/cglm/include/cglm/struct/mat2.h b/libs/cglm/include/cglm/struct/mat2.h
new file mode 100644
index 0000000..a8ee27f
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/mat2.h
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Macros:
+ GLM_MAT2_IDENTITY_INIT
+ GLM_MAT2_ZERO_INIT
+ GLM_MAT2_IDENTITY
+ GLM_MAT2_ZERO
+
+ Functions:
+ CGLM_INLINE void glms_mat2_identity(mat2 mat)
+ CGLM_INLINE void glms_mat2_identity_array(mat2 * restrict mat, size_t count)
+ CGLM_INLINE void glms_mat2_zero(mat2 mat)
+ CGLM_INLINE void glms_mat2_mul(mat2 m1, mat2 m2, mat2 dest)
+ CGLM_INLINE void glms_mat2_transpose_to(mat2 m, mat2 dest)
+ CGLM_INLINE void glms_mat2_transpose(mat2 m)
+ CGLM_INLINE void glms_mat2_mulv(mat2 m, vec2 v, vec2 dest)
+ CGLM_INLINE float glms_mat2_trace(mat2 m)
+ CGLM_INLINE void glms_mat2_scale(mat2 m, float s)
+ CGLM_INLINE float glms_mat2_det(mat2 mat)
+ CGLM_INLINE void glms_mat2_inv(mat2 mat, mat2 dest)
+ CGLM_INLINE void glms_mat2_swap_col(mat2 mat, int col1, int col2)
+ CGLM_INLINE void glms_mat2_swap_row(mat2 mat, int row1, int row2)
+ CGLM_INLINE float glms_mat2_rmc(vec2 r, mat2 m, vec2 c)
+ */
+
+#ifndef cglms_mat2_h
+#define cglms_mat2_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../mat2.h"
+
+#define GLMS_MAT2_IDENTITY_INIT {GLM_MAT2_IDENTITY_INIT}
+#define GLMS_MAT2_ZERO_INIT {GLM_MAT2_ZERO_INIT}
+
+/* for C only */
+#define GLMS_MAT2_IDENTITY ((mat3s)GLMS_MAT2_IDENTITY_INIT)
+#define GLMS_MAT2_ZERO ((mat3s)GLMS_MAT2_ZERO_INIT)
+
+/*!
+ * @brief make given matrix identity. It is identical with below,
+ * but it is more easy to do that with this func especially for members
+ * e.g. glm_mat2_identity(aStruct->aMatrix);
+ *
+ * @code
+ * glm_mat2_copy(GLM_MAT2_IDENTITY, mat); // C only
+ *
+ * // or
+ * mat2 mat = GLM_MAT2_IDENTITY_INIT;
+ * @endcode
+ *
+ * @returns identity matrix
+ */
+CGLM_INLINE
+mat2s
+glms_mat2_identity(void) {
+ mat2s r;
+ glm_mat2_identity(r.raw);
+ return r;
+}
+
+/*!
+ * @brief make given matrix array's each element identity matrix
+ *
+ * @param[in, out] mat matrix array (must be aligned (16)
+ * if alignment is not disabled)
+ *
+ * @param[in] count count of matrices
+ */
+CGLM_INLINE
+void
+glms_mat2_identity_array(mat2s * __restrict mat, size_t count) {
+ CGLM_ALIGN_MAT mat2s t = GLMS_MAT2_IDENTITY_INIT;
+ size_t i;
+
+ for (i = 0; i < count; i++) {
+ glm_mat2_copy(t.raw, mat[i].raw);
+ }
+}
+
+/*!
+ * @brief make given matrix zero.
+ *
+ * @returns matrix
+ */
+CGLM_INLINE
+mat2s
+glms_mat2_zero(void) {
+ mat2s r;
+ glm_mat2_zero(r.raw);
+ return r;
+}
+
+/*!
+ * @brief multiply m1 and m2 to dest
+ *
+ * m1, m2 and dest matrices can be same matrix, it is possible to write this:
+ *
+ * @code
+ * mat2 m = GLM_MAT2_IDENTITY_INIT;
+ * glm_mat2_mul(m, m, m);
+ * @endcode
+ *
+ * @param[in] m1 left matrix
+ * @param[in] m2 right matrix
+ *
+ * @returns matrix
+ */
+CGLM_INLINE
+mat2s
+glms_mat2_mul(mat2s m1, mat2s m2) {
+ mat2s r;
+ glm_mat2_mul(m1.raw, m2.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief transpose mat2
+ *
+ * @param[in] m matrix to transpose
+ *
+ * @returns transposed matrix
+ */
+CGLM_INLINE
+mat2s
+glms_mat2_transpose(mat2s m) {
+ glm_mat2_transpose(m.raw);
+ return m;
+}
+
+/*!
+ * @brief multiply mat2 with vec2 (column vector) and store in dest vector
+ *
+ * @param[in] m mat2 (left)
+ * @param[in] v vec2 (right, column vector)
+ * @returns vec2 (result, column vector)
+ */
+CGLM_INLINE
+vec2s
+glms_mat2_mulv(mat2s m, vec2s v) {
+ vec2s r;
+ glm_mat2_mulv(m.raw, v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief trace of matrix
+ *
+ * sum of the elements on the main diagonal from upper left to the lower right
+ *
+ * @param[in] m matrix
+ */
+CGLM_INLINE
+float
+glms_mat2_trace(mat2s m) {
+ return glm_mat2_trace(m.raw);
+}
+
+/*!
+ * @brief scale (multiply with scalar) matrix
+ *
+ * multiply matrix with scalar
+ *
+ * @param[in, out] m matrix
+ * @param[in] s scalar
+ * @returns matrix
+ */
+CGLM_INLINE
+mat2s
+glms_mat2_scale(mat2s m, float s) {
+ glm_mat2_scale(m.raw, s);
+ return m;
+}
+
+/*!
+ * @brief mat2 determinant
+ *
+ * @param[in] mat matrix
+ *
+ * @return determinant
+ */
+CGLM_INLINE
+float
+glms_mat2_det(mat2s mat) {
+ return glm_mat2_det(mat.raw);
+}
+
+/*!
+ * @brief inverse mat2 and store in dest
+ *
+ * @param[in] mat matrix
+ * @returns matrix
+ */
+CGLM_INLINE
+mat2s
+glms_mat2_inv(mat2s mat) {
+ mat2s r;
+ glm_mat2_inv(mat.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief swap two matrix columns
+ *
+ * @param[in] mat matrix
+ * @param[in] col1 col1
+ * @param[in] col2 col2
+ * @returns matrix
+ */
+CGLM_INLINE
+mat2s
+glms_mat2_swap_col(mat2s mat, int col1, int col2) {
+ glm_mat2_swap_col(mat.raw, col1, col2);
+ return mat;
+}
+
+/*!
+ * @brief swap two matrix rows
+ *
+ * @param[in] mat matrix
+ * @param[in] row1 row1
+ * @param[in] row2 row2
+ * @returns matrix
+ */
+CGLM_INLINE
+mat2s
+glms_mat2_swap_row(mat2s mat, int row1, int row2) {
+ glm_mat2_swap_row(mat.raw, row1, row2);
+ return mat;
+}
+
+/*!
+ * @brief helper for R (row vector) * M (matrix) * C (column vector)
+ *
+ * rmc stands for Row * Matrix * Column
+ *
+ * the result is scalar because R * M = Matrix1x2 (row vector),
+ * then Matrix1x2 * Vec2 (column vector) = Matrix1x1 (Scalar)
+ *
+ * @param[in] r row vector or matrix1x2
+ * @param[in] m matrix2x2
+ * @param[in] c column vector or matrix2x1
+ *
+ * @return scalar value e.g. Matrix1x1
+ */
+CGLM_INLINE
+float
+glms_mat2_rmc(vec2s r, mat2s m, vec2s c) {
+ return glm_mat2_rmc(r.raw, m.raw, c.raw);
+}
+
+#endif /* cglms_mat2_h */
diff --git a/libs/cglm/include/cglm/struct/mat3.h b/libs/cglm/include/cglm/struct/mat3.h
new file mode 100644
index 0000000..53a7273
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/mat3.h
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Macros:
+ GLMS_MAT3_IDENTITY_INIT
+ GLMS_MAT3_ZERO_INIT
+ GLMS_MAT3_IDENTITY
+ GLMS_MAT3_ZERO
+
+ Functions:
+ CGLM_INLINE mat3s glms_mat3_copy(mat3s mat);
+ CGLM_INLINE mat3s glms_mat3_identity(void);
+ CGLM_INLINE void glms_mat3_identity_array(mat3s * __restrict mat, size_t count);
+ CGLM_INLINE mat3s glms_mat3_zero(void);
+ CGLM_INLINE mat3s glms_mat3_mul(mat3s m1, mat3s m2);
+ CGLM_INLINE ma3s glms_mat3_transpose(mat3s m);
+ CGLM_INLINE vec3s glms_mat3_mulv(mat3s m, vec3s v);
+ CGLM_INLINE float glms_mat3_trace(mat3s m);
+ CGLM_INLINE versor glms_mat3_quat(mat3s m);
+ CGLM_INLINE mat3s glms_mat3_scale(mat3s m, float s);
+ CGLM_INLINE float glms_mat3_det(mat3s mat);
+ CGLM_INLINE mat3s glms_mat3_inv(mat3s mat);
+ CGLM_INLINE mat3s glms_mat3_swap_col(mat3s mat, int col1, int col2);
+ CGLM_INLINE mat3s glms_mat3_swap_row(mat3s mat, int row1, int row2);
+ CGLM_INLINE float glms_mat3_rmc(vec3s r, mat3s m, vec3s c);
+ */
+
+#ifndef cglms_mat3s_h
+#define cglms_mat3s_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../mat3.h"
+#include "vec3.h"
+
+#define GLMS_MAT3_IDENTITY_INIT {GLM_MAT3_IDENTITY_INIT}
+#define GLMS_MAT3_ZERO_INIT {GLM_MAT3_ZERO_INIT}
+
+/* for C only */
+#define GLMS_MAT3_IDENTITY ((mat3s)GLMS_MAT3_IDENTITY_INIT)
+#define GLMS_MAT3_ZERO ((mat3s)GLMS_MAT3_ZERO_INIT)
+
+/*!
+ * @brief copy all members of [mat] to [dest]
+ *
+ * @param[in] mat source
+ * @returns destination
+ */
+CGLM_INLINE
+mat3s
+glms_mat3_copy(mat3s mat) {
+ mat3s r;
+ glm_mat3_copy(mat.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief make given matrix identity. It is identical with below,
+ * but it is more easy to do that with this func especially for members
+ * e.g. glm_mat3_identity(aStruct->aMatrix);
+ *
+ * @code
+ * glm_mat3_copy(GLM_MAT3_IDENTITY, mat); // C only
+ *
+ * // or
+ * mat3 mat = GLM_MAT3_IDENTITY_INIT;
+ * @endcode
+ *
+ * @returns destination
+ */
+CGLM_INLINE
+mat3s
+glms_mat3_identity(void) {
+ mat3s r;
+ glm_mat3_identity(r.raw);
+ return r;
+}
+
+/*!
+ * @brief make given matrix array's each element identity matrix
+ *
+ * @param[in, out] mat matrix array (must be aligned (16/32)
+ * if alignment is not disabled)
+ *
+ * @param[in] count count of matrices
+ */
+CGLM_INLINE
+void
+glms_mat3_identity_array(mat3s * __restrict mat, size_t count) {
+ CGLM_ALIGN_MAT mat3s t = GLMS_MAT3_IDENTITY_INIT;
+ size_t i;
+
+ for (i = 0; i < count; i++) {
+ glm_mat3_copy(t.raw, mat[i].raw);
+ }
+}
+
+/*!
+ * @brief make given matrix zero.
+ *
+ * @returns matrix
+ */
+CGLM_INLINE
+mat3s
+glms_mat3_zero(void) {
+ mat3s r;
+ glm_mat3_zero(r.raw);
+ return r;
+}
+
+/*!
+ * @brief multiply m1 and m2 to dest
+ *
+ * m1, m2 and dest matrices can be same matrix, it is possible to write this:
+ *
+ * @code
+ * mat3 m = GLM_MAT3_IDENTITY_INIT;
+ * glm_mat3_mul(m, m, m);
+ * @endcode
+ *
+ * @param[in] m1 left matrix
+ * @param[in] m2 right matrix
+ * @returns destination matrix
+ */
+CGLM_INLINE
+mat3s
+glms_mat3_mul(mat3s m1, mat3s m2) {
+ mat3s r;
+ glm_mat3_mul(m1.raw, m2.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief tranpose mat3 and store result in same matrix
+ *
+ * @param[in, out] m source and dest
+ */
+CGLM_INLINE
+mat3s
+glms_mat3_transpose(mat3s m) {
+ glm_mat3_transpose(m.raw);
+ return m;
+}
+
+/*!
+ * @brief multiply mat3 with vec3 (column vector) and store in dest vector
+ *
+ * @param[in] m mat3 (left)
+ * @param[in] v vec3 (right, column vector)
+ * @returns vec3 (result, column vector)
+ */
+CGLM_INLINE
+vec3s
+glms_mat3_mulv(mat3s m, vec3s v) {
+ vec3s r;
+ glm_mat3_mulv(m.raw, v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief trace of matrix
+ *
+ * sum of the elements on the main diagonal from upper left to the lower right
+ *
+ * @param[in] m matrix
+ */
+CGLM_INLINE
+float
+glms_mat3_trace(mat3s m) {
+ return glm_mat3_trace(m.raw);
+}
+
+/*!
+ * @brief convert mat3 to quaternion
+ *
+ * @param[in] m rotation matrix
+ * @returns destination quaternion
+ */
+CGLM_INLINE
+versors
+glms_mat3_quat(mat3s m) {
+ versors r;
+ glm_mat3_quat(m.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief scale (multiply with scalar) matrix
+ *
+ * multiply matrix with scalar
+ *
+ * @param[in] m matrix
+ * @param[in] s scalar
+ * @returns scaled matrix
+ */
+CGLM_INLINE
+mat3s
+glms_mat3_scale(mat3s m, float s) {
+ glm_mat3_scale(m.raw, s);
+ return m;
+}
+
+/*!
+ * @brief mat3 determinant
+ *
+ * @param[in] mat matrix
+ *
+ * @return determinant
+ */
+CGLM_INLINE
+float
+glms_mat3_det(mat3s mat) {
+ return glm_mat3_det(mat.raw);
+}
+
+/*!
+ * @brief inverse mat3 and store in dest
+ *
+ * @param[in] mat matrix
+ * @returns inverse matrix
+ */
+CGLM_INLINE
+mat3s
+glms_mat3_inv(mat3s mat) {
+ mat3s r;
+ glm_mat3_inv(mat.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief swap two matrix columns
+ *
+ * @param[in] mat matrix
+ * @param[in] col1 col1
+ * @param[in] col2 col2
+ * @returns matrix
+ */
+CGLM_INLINE
+mat3s
+glms_mat3_swap_col(mat3s mat, int col1, int col2) {
+ glm_mat3_swap_col(mat.raw, col1, col2);
+ return mat;
+}
+
+/*!
+ * @brief swap two matrix rows
+ *
+ * @param[in] mat matrix
+ * @param[in] row1 row1
+ * @param[in] row2 row2
+ * @returns matrix
+ */
+CGLM_INLINE
+mat3s
+glms_mat3_swap_row(mat3s mat, int row1, int row2) {
+ glm_mat3_swap_row(mat.raw, row1, row2);
+ return mat;
+}
+
+/*!
+ * @brief helper for R (row vector) * M (matrix) * C (column vector)
+ *
+ * rmc stands for Row * Matrix * Column
+ *
+ * the result is scalar because R * M = Matrix1x3 (row vector),
+ * then Matrix1x3 * Vec3 (column vector) = Matrix1x1 (Scalar)
+ *
+ * @param[in] r row vector or matrix1x3
+ * @param[in] m matrix3x3
+ * @param[in] c column vector or matrix3x1
+ *
+ * @return scalar value e.g. Matrix1x1
+ */
+CGLM_INLINE
+float
+glms_mat3_rmc(vec3s r, mat3s m, vec3s c) {
+ return glm_mat3_rmc(r.raw, m.raw, c.raw);
+}
+
+#endif /* cglms_mat3s_h */
diff --git a/libs/cglm/include/cglm/struct/mat4.h b/libs/cglm/include/cglm/struct/mat4.h
new file mode 100644
index 0000000..28f80a3
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/mat4.h
@@ -0,0 +1,459 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*!
+ * Most of functions in this header are optimized manually with SIMD
+ * if available. You dont need to call/incude SIMD headers manually
+ */
+
+/*
+ Macros:
+ GLMS_MAT4_IDENTITY_INIT
+ GLMS_MAT4_ZERO_INIT
+ GLMS_MAT4_IDENTITY
+ GLMS_MAT4_ZERO
+
+ Functions:
+ CGLM_INLINE mat4s glms_mat4_ucopy(mat4s mat);
+ CGLM_INLINE mat4s glms_mat4_copy(mat4s mat);
+ CGLM_INLINE mat4s glms_mat4_identity(void);
+ CGLM_INLINE void glms_mat4_identity_array(mat4s * __restrict mat, size_t count);
+ CGLM_INLINE mat4s glms_mat4_zero(void);
+ CGLM_INLINE mat3s glms_mat4_pick3(mat4s mat);
+ CGLM_INLINE mat3s glms_mat4_pick3t(mat4s mat);
+ CGLM_INLINE mat4s glms_mat4_ins3(mat3s mat);
+ CGLM_INLINE mat4s glms_mat4_mul(mat4s m1, mat4s m2);
+ CGLM_INLINE mat4s glms_mat4_mulN(mat4s * __restrict matrices[], uint32_t len);
+ CGLM_INLINE vec4s glms_mat4_mulv(mat4s m, vec4s v);
+ CGLM_INLINE float glms_mat4_trace(mat4s m);
+ CGLM_INLINE float glms_mat4_trace3(mat4s m);
+ CGLM_INLINE versors glms_mat4_quat(mat4s m);
+ CGLM_INLINE vec3s glms_mat4_mulv3(mat4s m, vec3s v, float last);
+ CGLM_INLINE mat4s glms_mat4_transpose(mat4s m);
+ CGLM_INLINE mat4s glms_mat4_scale_p(mat4s m, float s);
+ CGLM_INLINE mat4s glms_mat4_scale(mat4s m, float s);
+ CGLM_INLINE float glms_mat4_det(mat4s mat);
+ CGLM_INLINE mat4s glms_mat4_inv(mat4s mat);
+ CGLM_INLINE mat4s glms_mat4_inv_fast(mat4s mat);
+ CGLM_INLINE mat4s glms_mat4_swap_col(mat4s mat, int col1, int col2);
+ CGLM_INLINE mat4s glms_mat4_swap_row(mat4s mat, int row1, int row2);
+ CGLM_INLINE float glms_mat4_rmc(vec4s r, mat4s m, vec4s c);
+ */
+
+#ifndef cglms_mat4s_h
+#define cglms_mat4s_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../mat4.h"
+#include "vec4.h"
+#include "vec3.h"
+
+#define GLMS_MAT4_IDENTITY_INIT {GLM_MAT4_IDENTITY_INIT}
+#define GLMS_MAT4_ZERO_INIT {GLM_MAT4_ZERO_INIT}
+
+/* for C only */
+#define GLMS_MAT4_IDENTITY ((mat4s)GLMS_MAT4_IDENTITY_INIT)
+#define GLMS_MAT4_ZERO ((mat4s)GLMS_MAT4_ZERO_INIT)
+
+/*!
+ * @brief copy all members of [mat] to [dest]
+ *
+ * matrix may not be aligned, u stands for unaligned, this may be useful when
+ * copying a matrix from external source e.g. asset importer...
+ *
+ * @param[in] mat source
+ * @returns destination
+ */
+CGLM_INLINE
+mat4s
+glms_mat4_ucopy(mat4s mat) {
+ mat4s r;
+ glm_mat4_ucopy(mat.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief copy all members of [mat] to [dest]
+ *
+ * @param[in] mat source
+ * @returns destination
+ */
+CGLM_INLINE
+mat4s
+glms_mat4_copy(mat4s mat) {
+ mat4s r;
+ glm_mat4_copy(mat.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief make given matrix identity. It is identical with below,
+ * but it is more easy to do that with this func especially for members
+ * e.g. glm_mat4_identity(aStruct->aMatrix);
+ *
+ * @code
+ * glm_mat4_copy(GLM_MAT4_IDENTITY, mat); // C only
+ *
+ * // or
+ * mat4 mat = GLM_MAT4_IDENTITY_INIT;
+ * @endcode
+ *
+ * @retuns destination
+ */
+CGLM_INLINE
+mat4s
+glms_mat4_identity(void) {
+ mat4s r;
+ glm_mat4_identity(r.raw);
+ return r;
+}
+
+/*!
+ * @brief make given matrix array's each element identity matrix
+ *
+ * @param[in, out] mat matrix array (must be aligned (16/32)
+ * if alignment is not disabled)
+ *
+ * @param[in] count count of matrices
+ */
+CGLM_INLINE
+void
+glms_mat4_identity_array(mat4s * __restrict mat, size_t count) {
+ CGLM_ALIGN_MAT mat4s t = GLMS_MAT4_IDENTITY_INIT;
+ size_t i;
+
+ for (i = 0; i < count; i++) {
+ glm_mat4_copy(t.raw, mat[i].raw);
+ }
+}
+
+/*!
+ * @brief make given matrix zero.
+ *
+ * @returns matrix
+ */
+CGLM_INLINE
+mat4s
+glms_mat4_zero(void) {
+ mat4s r;
+ glm_mat4_zero(r.raw);
+ return r;
+}
+
+/*!
+ * @brief copy upper-left of mat4 to mat3
+ *
+ * @param[in] mat source
+ * @returns destination
+ */
+CGLM_INLINE
+mat3s
+glms_mat4_pick3(mat4s mat) {
+ mat3s r;
+ glm_mat4_pick3(mat.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief copy upper-left of mat4 to mat3 (transposed)
+ *
+ * the postfix t stands for transpose
+ *
+ * @param[in] mat source
+ * @returns destination
+ */
+CGLM_INLINE
+mat3s
+glms_mat4_pick3t(mat4s mat) {
+ mat3s r;
+ glm_mat4_pick3t(mat.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief copy mat3 to mat4's upper-left
+ *
+ * @param[in] mat source
+ * @returns destination
+ */
+CGLM_INLINE
+mat4s
+glms_mat4_ins3(mat3s mat) {
+ mat4s r;
+ glm_mat4_ins3(mat.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief multiply m1 and m2 to dest
+ *
+ * m1, m2 and dest matrices can be same matrix, it is possible to write this:
+ *
+ * @code
+ * mat4 m = GLM_MAT4_IDENTITY_INIT;
+ * glm_mat4_mul(m, m, m);
+ * @endcode
+ *
+ * @param[in] m1 left matrix
+ * @param[in] m2 right matrix
+ * @returns destination matrix
+ */
+CGLM_INLINE
+mat4s
+glms_mat4_mul(mat4s m1, mat4s m2) {
+ mat4s r;
+ glm_mat4_mul(m1.raw, m2.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief mupliply N mat4 matrices and store result in dest
+ *
+ * this function lets you multiply multiple (more than two or more...) matrices
+ * <br><br>multiplication will be done in loop, this may reduce instructions
+ * size but if <b>len</b> is too small then compiler may unroll whole loop,
+ * usage:
+ * @code
+ * mat m1, m2, m3, m4, res;
+ *
+ * res = glm_mat4_mulN((mat4 *[]){&m1, &m2, &m3, &m4}, 4);
+ * @endcode
+ *
+ * @warning matrices parameter is pointer array not mat4 array!
+ *
+ * @param[in] matrices mat4 * array
+ * @param[in] len matrices count
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_mat4_mulN(mat4s * __restrict matrices[], uint32_t len) {
+ CGLM_ALIGN_MAT mat4s r = GLMS_MAT4_IDENTITY_INIT;
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ r = glms_mat4_mul(r, *matrices[i]);
+ }
+
+ return r;
+}
+
+/*!
+ * @brief multiply mat4 with vec4 (column vector) and store in dest vector
+ *
+ * @param[in] m mat4 (left)
+ * @param[in] v vec4 (right, column vector)
+ * @returns vec4 (result, column vector)
+ */
+CGLM_INLINE
+vec4s
+glms_mat4_mulv(mat4s m, vec4s v) {
+ vec4s r;
+ glm_mat4_mulv(m.raw, v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief trace of matrix
+ *
+ * sum of the elements on the main diagonal from upper left to the lower right
+ *
+ * @param[in] m matrix
+ */
+CGLM_INLINE
+float
+glms_mat4_trace(mat4s m) {
+ return glm_mat4_trace(m.raw);
+}
+
+/*!
+ * @brief trace of matrix (rotation part)
+ *
+ * sum of the elements on the main diagonal from upper left to the lower right
+ *
+ * @param[in] m matrix
+ */
+CGLM_INLINE
+float
+glms_mat4_trace3(mat4s m) {
+ return glm_mat4_trace3(m.raw);
+}
+
+/*!
+ * @brief convert mat4's rotation part to quaternion
+ *
+ * @param[in] m affine matrix
+ * @returns destination quaternion
+ */
+CGLM_INLINE
+versors
+glms_mat4_quat(mat4s m) {
+ versors r;
+ glm_mat4_quat(m.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief multiply vector with mat4
+ *
+ * @param[in] m mat4(affine transform)
+ * @param[in] v vec3
+ * @param[in] last 4th item to make it vec4
+ * @returns result vector (vec3)
+ */
+CGLM_INLINE
+vec3s
+glms_mat4_mulv3(mat4s m, vec3s v, float last) {
+ vec3s r;
+ glm_mat4_mulv3(m.raw, v.raw, last, r.raw);
+ return r;
+}
+
+/*!
+ * @brief tranpose mat4 and store result in same matrix
+ *
+ * @param[in] m source
+ * @returns result
+ */
+CGLM_INLINE
+mat4s
+glms_mat4_transpose(mat4s m) {
+ glm_mat4_transpose(m.raw);
+ return m;
+}
+
+/*!
+ * @brief scale (multiply with scalar) matrix without simd optimization
+ *
+ * multiply matrix with scalar
+ *
+ * @param[in] m matrix
+ * @param[in] s scalar
+ * @returns matrix
+ */
+CGLM_INLINE
+mat4s
+glms_mat4_scale_p(mat4s m, float s) {
+ glm_mat4_scale_p(m.raw, s);
+ return m;
+}
+
+/*!
+ * @brief scale (multiply with scalar) matrix
+ *
+ * multiply matrix with scalar
+ *
+ * @param[in] m matrix
+ * @param[in] s scalar
+ * @returns matrix
+ */
+CGLM_INLINE
+mat4s
+glms_mat4_scale(mat4s m, float s) {
+ glm_mat4_scale(m.raw, s);
+ return m;
+}
+
+/*!
+ * @brief mat4 determinant
+ *
+ * @param[in] mat matrix
+ *
+ * @return determinant
+ */
+CGLM_INLINE
+float
+glms_mat4_det(mat4s mat) {
+ return glm_mat4_det(mat.raw);
+}
+
+/*!
+ * @brief inverse mat4 and store in dest
+ *
+ * @param[in] mat matrix
+ * @returns inverse matrix
+ */
+CGLM_INLINE
+mat4s
+glms_mat4_inv(mat4s mat) {
+ mat4s r;
+ glm_mat4_inv(mat.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief inverse mat4 and store in dest
+ *
+ * this func uses reciprocal approximation without extra corrections
+ * e.g Newton-Raphson. this should work faster than normal,
+ * to get more precise use glm_mat4_inv version.
+ *
+ * NOTE: You will lose precision, glm_mat4_inv is more accurate
+ *
+ * @param[in] mat matrix
+ * @returns inverse matrix
+ */
+CGLM_INLINE
+mat4s
+glms_mat4_inv_fast(mat4s mat) {
+ mat4s r;
+ glm_mat4_inv_fast(mat.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief swap two matrix columns
+ *
+ * @param[in] mat matrix
+ * @param[in] col1 col1
+ * @param[in] col2 col2
+ * @returns matrix
+ */
+CGLM_INLINE
+mat4s
+glms_mat4_swap_col(mat4s mat, int col1, int col2) {
+ glm_mat4_swap_col(mat.raw, col1, col2);
+ return mat;
+}
+
+/*!
+ * @brief swap two matrix rows
+ *
+ * @param[in] mat matrix
+ * @param[in] row1 row1
+ * @param[in] row2 row2
+ * @returns matrix
+ */
+CGLM_INLINE
+mat4s
+glms_mat4_swap_row(mat4s mat, int row1, int row2) {
+ glm_mat4_swap_row(mat.raw, row1, row2);
+ return mat;
+}
+
+/*!
+ * @brief helper for R (row vector) * M (matrix) * C (column vector)
+ *
+ * rmc stands for Row * Matrix * Column
+ *
+ * the result is scalar because R * M = Matrix1x4 (row vector),
+ * then Matrix1x4 * Vec4 (column vector) = Matrix1x1 (Scalar)
+ *
+ * @param[in] r row vector or matrix1x4
+ * @param[in] m matrix4x4
+ * @param[in] c column vector or matrix4x1
+ *
+ * @return scalar value e.g. B(s)
+ */
+CGLM_INLINE
+float
+glms_mat4_rmc(vec4s r, mat4s m, vec4s c) {
+ return glm_mat4_rmc(r.raw, m.raw, c.raw);
+}
+
+#endif /* cglms_mat4s_h */
diff --git a/libs/cglm/include/cglm/struct/plane.h b/libs/cglm/include/cglm/struct/plane.h
new file mode 100644
index 0000000..6a84ac7
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/plane.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglms_planes_h
+#define cglms_planes_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../plane.h"
+#include "vec4.h"
+
+/*
+ Plane equation: Ax + By + Cz + D = 0;
+
+ It stored in vec4 as [A, B, C, D]. (A, B, C) is normal and D is distance
+*/
+
+/*
+ Functions:
+ CGLM_INLINE vec4s glms_plane_normalize(vec4s plane);
+ */
+
+/*!
+ * @brief normalizes a plane
+ *
+ * @param[in] plane plane to normalize
+ * @returns normalized plane
+ */
+CGLM_INLINE
+vec4s
+glms_plane_normalize(vec4s plane) {
+ glm_plane_normalize(plane.raw);
+ return plane;
+}
+
+#endif /* cglms_planes_h */
diff --git a/libs/cglm/include/cglm/struct/project.h b/libs/cglm/include/cglm/struct/project.h
new file mode 100644
index 0000000..00f76ff
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/project.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglms_projects_h
+#define cglms_projects_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../project.h"
+#include "vec3.h"
+#include "vec4.h"
+#include "mat4.h"
+
+/*!
+ * @brief maps the specified viewport coordinates into specified space [1]
+ * the matrix should contain projection matrix.
+ *
+ * if you don't have ( and don't want to have ) an inverse matrix then use
+ * glm_unproject version. You may use existing inverse of matrix in somewhere
+ * else, this is why glm_unprojecti exists to save save inversion cost
+ *
+ * [1] space:
+ * 1- if m = invProj: View Space
+ * 2- if m = invViewProj: World Space
+ * 3- if m = invMVP: Object Space
+ *
+ * You probably want to map the coordinates into object space
+ * so use invMVP as m
+ *
+ * Computing viewProj:
+ * glm_mat4_mul(proj, view, viewProj);
+ * glm_mat4_mul(viewProj, model, MVP);
+ * glm_mat4_inv(viewProj, invMVP);
+ *
+ * @param[in] pos point/position in viewport coordinates
+ * @param[in] invMat matrix (see brief)
+ * @param[in] vp viewport as [x, y, width, height]
+ * @returns unprojected coordinates
+ */
+CGLM_INLINE
+vec3s
+glms_unprojecti(vec3s pos, mat4s invMat, vec4s vp) {
+ vec3s r;
+ glm_unprojecti(pos.raw, invMat.raw, vp.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief maps the specified viewport coordinates into specified space [1]
+ * the matrix should contain projection matrix.
+ *
+ * this is same as glm_unprojecti except this function get inverse matrix for
+ * you.
+ *
+ * [1] space:
+ * 1- if m = proj: View Space
+ * 2- if m = viewProj: World Space
+ * 3- if m = MVP: Object Space
+ *
+ * You probably want to map the coordinates into object space
+ * so use MVP as m
+ *
+ * Computing viewProj and MVP:
+ * glm_mat4_mul(proj, view, viewProj);
+ * glm_mat4_mul(viewProj, model, MVP);
+ *
+ * @param[in] pos point/position in viewport coordinates
+ * @param[in] m matrix (see brief)
+ * @param[in] vp viewport as [x, y, width, height]
+ * @returns unprojected coordinates
+ */
+CGLM_INLINE
+vec3s
+glms_unproject(vec3s pos, mat4s m, vec4s vp) {
+ vec3s r;
+ glm_unproject(pos.raw, m.raw, vp.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief map object coordinates to window coordinates
+ *
+ * Computing MVP:
+ * glm_mat4_mul(proj, view, viewProj);
+ * glm_mat4_mul(viewProj, model, MVP);
+ *
+ * @param[in] pos object coordinates
+ * @param[in] m MVP matrix
+ * @param[in] vp viewport as [x, y, width, height]
+ * @returns projected coordinates
+ */
+CGLM_INLINE
+vec3s
+glms_project(vec3s pos, mat4s m, vec4s vp) {
+ vec3s r;
+ glm_project(pos.raw, m.raw, vp.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief define a picking region
+ *
+ * @param[in] center center [x, y] of a picking region in window coordinates
+ * @param[in] size size [width, height] of the picking region in window coordinates
+ * @param[in] vp viewport as [x, y, width, height]
+ * @returns projected coordinates
+ */
+CGLM_INLINE
+mat4s
+glms_pickmatrix(vec2s center, vec2s size, vec4s vp) {
+ mat4s res;
+ glm_pickmatrix(center.raw, size.raw, vp.raw, res.raw);
+ return res;
+}
+
+#endif /* cglms_projects_h */
diff --git a/libs/cglm/include/cglm/struct/quat.h b/libs/cglm/include/cglm/struct/quat.h
new file mode 100644
index 0000000..d69675b
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/quat.h
@@ -0,0 +1,565 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Macros:
+ GLMS_QUAT_IDENTITY_INIT
+ GLMS_QUAT_IDENTITY
+
+ Functions:
+ CGLM_INLINE versors glms_quat_identity(void)
+ CGLM_INLINE void glms_quat_identity_array(versor *q, size_t count)
+ CGLM_INLINE versors glms_quat_init(float x, float y, float z, float w)
+ CGLM_INLINE versors glms_quatv(float angle, vec3s axis)
+ CGLM_INLINE versors glms_quat(float angle, float x, float y, float z)
+ CGLM_INLINE versors glms_quat_from_vecs(vec3s a, vec3s b)
+ CGLM_INLINE float glms_quat_norm(versors q)
+ CGLM_INLINE versors glms_quat_normalize(versors q)
+ CGLM_INLINE float glms_quat_dot(versors p, versors q)
+ CGLM_INLINE versors glms_quat_conjugate(versors q)
+ CGLM_INLINE versors glms_quat_inv(versors q)
+ CGLM_INLINE versors glms_quat_add(versors p, versors q)
+ CGLM_INLINE versors glms_quat_sub(versors p, versors q)
+ CGLM_INLINE vec3s glms_quat_imagn(versors q)
+ CGLM_INLINE float glms_quat_imaglen(versors q)
+ CGLM_INLINE float glms_quat_angle(versors q)
+ CGLM_INLINE vec3s glms_quat_axis(versors q)
+ CGLM_INLINE versors glms_quat_mul(versors p, versors q)
+ CGLM_INLINE mat4s glms_quat_mat4(versors q)
+ CGLM_INLINE mat4s glms_quat_mat4t(versors q)
+ CGLM_INLINE mat3s glms_quat_mat3(versors q)
+ CGLM_INLINE mat3s glms_quat_mat3t(versors q)
+ CGLM_INLINE versors glms_quat_lerp(versors from, versors to, float t)
+ CGLM_INLINE versors glms_quat_lerpc(versors from, versors to, float t)
+ CGLM_INLINE versors glms_quat_nlerp(versors from, versors to, float t)
+ CGLM_INLINE versors glms_quat_slerp(versors from, versors to, float t)
+ CGLM_INLINE mat4s. glms_quat_look(vec3s eye, versors ori)
+ CGLM_INLINE versors glms_quat_for(vec3s dir, vec3s fwd, vec3s up)
+ CGLM_INLINE versors glms_quat_forp(vec3s from, vec3s to, vec3s fwd, vec3s up)
+ CGLM_INLINE vec3s glms_quat_rotatev(versors q, vec3s v)
+ CGLM_INLINE mat4s glms_quat_rotate(mat4s m, versors q)
+ CGLM_INLINE mat4s glms_quat_rotate_at(mat4s m, versors q, vec3s pivot)
+ CGLM_INLINE mat4s glms_quat_rotate_atm(versors q, vec3s pivot)
+ */
+
+#ifndef cglms_quat_h
+#define cglms_quat_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../plane.h"
+#include "../quat.h"
+
+/*
+ * IMPORTANT:
+ * ----------------------------------------------------------------------------
+ * cglm stores quat as [x, y, z, w] since v0.3.6
+ *
+ * it was [w, x, y, z] before v0.3.6 it has been changed to [x, y, z, w]
+ * with v0.3.6 version.
+ * ----------------------------------------------------------------------------
+ */
+
+#define GLMS_QUAT_IDENTITY_INIT {GLM_QUAT_IDENTITY_INIT}
+#define GLMS_QUAT_IDENTITY ((versors)GLMS_QUAT_IDENTITY_INIT)
+
+/*!
+ * @brief makes given quat to identity
+ *
+ * @returns identity quaternion
+ */
+CGLM_INLINE
+versors
+glms_quat_identity(void) {
+ versors dest;
+ glm_quat_identity(dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief make given quaternion array's each element identity quaternion
+ *
+ * @param[in, out] q quat array (must be aligned (16)
+ * if alignment is not disabled)
+ *
+ * @param[in] count count of quaternions
+ */
+CGLM_INLINE
+void
+glms_quat_identity_array(versors * __restrict q, size_t count) {
+ CGLM_ALIGN(16) versor v = GLM_QUAT_IDENTITY_INIT;
+ size_t i;
+
+ for (i = 0; i < count; i++) {
+ glm_vec4_copy(v, q[i].raw);
+ }
+}
+
+/*!
+ * @brief inits quaterion with raw values
+ *
+ * @param[in] x x
+ * @param[in] y y
+ * @param[in] z z
+ * @param[in] w w (real part)
+ * @returns quaternion
+ */
+CGLM_INLINE
+versors
+glms_quat_init(float x, float y, float z, float w) {
+ versors dest;
+ glm_quat_init(dest.raw, x, y, z, w);
+ return dest;
+}
+
+/*!
+ * @brief creates NEW quaternion with axis vector
+ *
+ * @param[in] angle angle (radians)
+ * @param[in] axis axis
+ * @returns quaternion
+ */
+CGLM_INLINE
+versors
+glms_quatv(float angle, vec3s axis) {
+ versors dest;
+ glm_quatv(dest.raw, angle, axis.raw);
+ return dest;
+}
+
+/*!
+ * @brief creates NEW quaternion with individual axis components
+ *
+ * @param[in] angle angle (radians)
+ * @param[in] x axis.x
+ * @param[in] y axis.y
+ * @param[in] z axis.z
+ * @returns quaternion
+ */
+CGLM_INLINE
+versors
+glms_quat(float angle, float x, float y, float z) {
+ versors dest;
+ glm_quat(dest.raw, angle, x, y, z);
+ return dest;
+}
+
+/*!
+ * @brief compute quaternion rotating vector A to vector B
+ *
+ * @param[in] a vec3 (must have unit length)
+ * @param[in] b vec3 (must have unit length)
+ * @returns quaternion (of unit length)
+ */
+CGLM_INLINE
+versors
+glms_quat_from_vecs(vec3s a, vec3s b) {
+ versors dest;
+ glm_quat_from_vecs(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief returns norm (magnitude) of quaternion
+ *
+ * @param[in] q quaternion
+ */
+CGLM_INLINE
+float
+glms_quat_norm(versors q) {
+ return glm_quat_norm(q.raw);
+}
+
+/*!
+ * @brief normalize quaternion
+ *
+ * @param[in] q quaternion
+ * @returns quaternion
+ */
+CGLM_INLINE
+versors
+glms_quat_normalize(versors q) {
+ versors dest;
+ glm_quat_normalize_to(q.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief dot product of two quaternion
+ *
+ * @param[in] p quaternion 1
+ * @param[in] q quaternion 2
+ * @returns dot product
+ */
+CGLM_INLINE
+float
+glms_quat_dot(versors p, versors q) {
+ return glm_quat_dot(p.raw, q.raw);
+}
+
+/*!
+ * @brief conjugate of quaternion
+ *
+ * @param[in] q quaternion
+ * @returns conjugate
+ */
+CGLM_INLINE
+versors
+glms_quat_conjugate(versors q) {
+ versors dest;
+ glm_quat_conjugate(q.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief inverse of non-zero quaternion
+ *
+ * @param[in] q quaternion
+ * @returns inverse quaternion
+ */
+CGLM_INLINE
+versors
+glms_quat_inv(versors q) {
+ versors dest;
+ glm_quat_inv(q.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief add (componentwise) two quaternions and store result in dest
+ *
+ * @param[in] p quaternion 1
+ * @param[in] q quaternion 2
+ * @returns result quaternion
+ */
+CGLM_INLINE
+versors
+glms_quat_add(versors p, versors q) {
+ versors dest;
+ glm_quat_add(p.raw, q.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief subtract (componentwise) two quaternions and store result in dest
+ *
+ * @param[in] p quaternion 1
+ * @param[in] q quaternion 2
+ * @returns result quaternion
+ */
+CGLM_INLINE
+versors
+glms_quat_sub(versors p, versors q) {
+ versors dest;
+ glm_quat_sub(p.raw, q.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief returns normalized imaginary part of quaternion
+ *
+ * @param[in] q quaternion
+ */
+CGLM_INLINE
+vec3s
+glms_quat_imagn(versors q) {
+ vec3s dest;
+ glm_normalize_to(q.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief returns length of imaginary part of quaternion
+ *
+ * @param[in] q quaternion
+ */
+CGLM_INLINE
+float
+glms_quat_imaglen(versors q) {
+ return glm_quat_imaglen(q.raw);
+}
+
+/*!
+ * @brief returns angle of quaternion
+ *
+ * @param[in] q quaternion
+ */
+CGLM_INLINE
+float
+glms_quat_angle(versors q) {
+ return glm_quat_angle(q.raw);
+}
+
+/*!
+ * @brief axis of quaternion
+ *
+ * @param[in] q quaternion
+ * @returns axis of quaternion
+ */
+CGLM_INLINE
+vec3s
+glms_quat_axis(versors q) {
+ vec3s dest;
+ glm_quat_axis(q.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief multiplies two quaternion and stores result in dest
+ * this is also called Hamilton Product
+ *
+ * According to WikiPedia:
+ * The product of two rotation quaternions [clarification needed] will be
+ * equivalent to the rotation q followed by the rotation p
+ *
+ * @param[in] p quaternion 1
+ * @param[in] q quaternion 2
+ * @returns result quaternion
+ */
+CGLM_INLINE
+versors
+glms_quat_mul(versors p, versors q) {
+ versors dest;
+ glm_quat_mul(p.raw, q.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief convert quaternion to mat4
+ *
+ * @param[in] q quaternion
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat4s
+glms_quat_mat4(versors q) {
+ mat4s dest;
+ glm_quat_mat4(q.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief convert quaternion to mat4 (transposed)
+ *
+ * @param[in] q quaternion
+ * @returns result matrix as transposed
+ */
+CGLM_INLINE
+mat4s
+glms_quat_mat4t(versors q) {
+ mat4s dest;
+ glm_quat_mat4t(q.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief convert quaternion to mat3
+ *
+ * @param[in] q quaternion
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat3s
+glms_quat_mat3(versors q) {
+ mat3s dest;
+ glm_quat_mat3(q.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief convert quaternion to mat3 (transposed)
+ *
+ * @param[in] q quaternion
+ * @returns result matrix
+ */
+CGLM_INLINE
+mat3s
+glms_quat_mat3t(versors q) {
+ mat3s dest;
+ glm_quat_mat3t(q.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief interpolates between two quaternions
+ * using linear interpolation (LERP)
+ *
+ * @param[in] from from
+ * @param[in] to to
+ * @param[in] t interpolant (amount)
+ * @returns result quaternion
+ */
+CGLM_INLINE
+versors
+glms_quat_lerp(versors from, versors to, float t) {
+ versors dest;
+ glm_quat_lerp(from.raw, to.raw, t, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief interpolates between two quaternions
+ * using linear interpolation (LERP)
+ *
+ * @param[in] from from
+ * @param[in] to to
+ * @param[in] t interpolant (amount) clamped between 0 and 1
+ * @returns result quaternion
+ */
+CGLM_INLINE
+versors
+glms_quat_lerpc(versors from, versors to, float t) {
+ versors dest;
+ glm_quat_lerpc(from.raw, to.raw, t, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief interpolates between two quaternions
+ * taking the shortest rotation path using
+ * normalized linear interpolation (NLERP)
+ *
+ * @param[in] from from
+ * @param[in] to to
+ * @param[in] t interpolant (amount)
+ * @returns result quaternion
+ */
+CGLM_INLINE
+versors
+glms_quat_nlerp(versors from, versors to, float t) {
+ versors dest;
+ glm_quat_nlerp(from.raw, to.raw, t, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief interpolates between two quaternions
+ * using spherical linear interpolation (SLERP)
+ *
+ * @param[in] from from
+ * @param[in] to to
+ * @param[in] t amout
+ * @returns result quaternion
+ */
+CGLM_INLINE
+versors
+glms_quat_slerp(versors from, versors to, float t) {
+ versors dest;
+ glm_quat_slerp(from.raw, to.raw, t, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief creates view matrix using quaternion as camera orientation
+ *
+ * @param[in] eye eye
+ * @param[in] ori orientation in world space as quaternion
+ * @returns view matrix
+ */
+CGLM_INLINE
+mat4s
+glms_quat_look(vec3s eye, versors ori) {
+ mat4s dest;
+ glm_quat_look(eye.raw, ori.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief creates look rotation quaternion
+ *
+ * @param[in] dir direction to look
+ * @param[in] up up vector
+ * @returns destination quaternion
+ */
+CGLM_INLINE
+versors
+glms_quat_for(vec3s dir, vec3s up) {
+ versors dest;
+ glm_quat_for(dir.raw, up.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief creates look rotation quaternion using source and
+ * destination positions p suffix stands for position
+ *
+ * @param[in] from source point
+ * @param[in] to destination point
+ * @param[in] up up vector
+ * @returns destination quaternion
+ */
+CGLM_INLINE
+versors
+glms_quat_forp(vec3s from, vec3s to, vec3s up) {
+ versors dest;
+ glm_quat_forp(from.raw, to.raw, up.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief rotate vector using using quaternion
+ *
+ * @param[in] q quaternion
+ * @param[in] v vector to rotate
+ * @returns rotated vector
+ */
+CGLM_INLINE
+vec3s
+glms_quat_rotatev(versors q, vec3s v) {
+ vec3s dest;
+ glm_quat_rotatev(q.raw, v.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief rotate existing transform matrix using quaternion
+ *
+ * @param[in] m existing transform matrix
+ * @param[in] q quaternion
+ * @returns rotated matrix/transform
+ */
+CGLM_INLINE
+mat4s
+glms_quat_rotate(mat4s m, versors q) {
+ glm_quat_rotate(m.raw, q.raw, m.raw);
+ return m;
+}
+
+/*!
+ * @brief rotate existing transform matrix using quaternion at pivot point
+ *
+ * @param[in, out] m existing transform matrix
+ * @param[in] q quaternion
+ * @returns pivot
+ */
+CGLM_INLINE
+mat4s
+glms_quat_rotate_at(mat4s m, versors q, vec3s pivot) {
+ glm_quat_rotate_at(m.raw, q.raw, pivot.raw);
+ return m;
+}
+
+/*!
+ * @brief rotate NEW transform matrix using quaternion at pivot point
+ *
+ * this creates rotation matrix, it assumes you don't have a matrix
+ *
+ * this should work faster than glm_quat_rotate_at because it reduces
+ * one glm_translate.
+ *
+ * @param[in] q quaternion
+ * @returns pivot
+ */
+CGLM_INLINE
+mat4s
+glms_quat_rotate_atm(versors q, vec3s pivot) {
+ mat4s dest;
+ glm_quat_rotate_atm(dest.raw, q.raw, pivot.raw);
+ return dest;
+}
+
+#endif /* cglms_quat_h */
diff --git a/libs/cglm/include/cglm/struct/sphere.h b/libs/cglm/include/cglm/struct/sphere.h
new file mode 100644
index 0000000..9859c72
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/sphere.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglms_spheres_h
+#define cglms_spheres_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../sphere.h"
+#include "mat4.h"
+
+/*
+ Sphere Representation in cglm: [center.x, center.y, center.z, radii]
+
+ You could use this representation or you can convert it to vec4 before call
+ any function
+ */
+
+/*!
+ * @brief helper for getting sphere radius
+ *
+ * @param[in] s sphere
+ *
+ * @return returns radii
+ */
+CGLM_INLINE
+float
+glms_sphere_radii(vec4s s) {
+ return glm_sphere_radii(s.raw);
+}
+
+/*!
+ * @brief apply transform to sphere, it is just wrapper for glm_mat4_mulv3
+ *
+ * @param[in] s sphere
+ * @param[in] m transform matrix
+ * @returns transformed sphere
+ */
+CGLM_INLINE
+vec4s
+glms_sphere_transform(vec4s s, mat4s m) {
+ vec4s r;
+ glm_sphere_transform(s.raw, m.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief merges two spheres and creates a new one
+ *
+ * two sphere must be in same space, for instance if one in world space then
+ * the other must be in world space too, not in local space.
+ *
+ * @param[in] s1 sphere 1
+ * @param[in] s2 sphere 2
+ * returns merged/extended sphere
+ */
+CGLM_INLINE
+vec4s
+glms_sphere_merge(vec4s s1, vec4s s2) {
+ vec4s r;
+ glm_sphere_merge(s1.raw, s2.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief check if two sphere intersects
+ *
+ * @param[in] s1 sphere
+ * @param[in] s2 other sphere
+ */
+CGLM_INLINE
+bool
+glms_sphere_sphere(vec4s s1, vec4s s2) {
+ return glm_sphere_sphere(s1.raw, s2.raw);
+}
+
+/*!
+ * @brief check if sphere intersects with point
+ *
+ * @param[in] s sphere
+ * @param[in] point point
+ */
+CGLM_INLINE
+bool
+glms_sphere_point(vec4s s, vec3s point) {
+ return glm_sphere_point(s.raw, point.raw);
+}
+
+#endif /* cglms_spheres_h */
diff --git a/libs/cglm/include/cglm/struct/vec2-ext.h b/libs/cglm/include/cglm/struct/vec2-ext.h
new file mode 100644
index 0000000..5d6682d
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/vec2-ext.h
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*!
+ * @brief SIMD like functions
+ */
+
+/*
+ Functions:
+ CGLM_INLINE vec2s glms_vec2_fill(float val)
+ CGLM_INLINE bool glms_vec2_eq(vec2s v, float val)
+ CGLM_INLINE bool glms_vec2_eq_eps(vec2s v, float val)
+ CGLM_INLINE bool glms_vec2_eq_all(vec2s v)
+ CGLM_INLINE bool glms_vec2_eqv(vec2s a, vec2s b)
+ CGLM_INLINE bool glms_vec2_eqv_eps(vec2s a, vec2s b)
+ CGLM_INLINE float glms_vec2_max(vec2s v)
+ CGLM_INLINE float glms_vec2_min(vec2s v)
+ CGLM_INLINE bool glms_vec2_isnan(vec2s v)
+ CGLM_INLINE bool glms_vec2_isinf(vec2s v)
+ CGLM_INLINE bool glms_vec2_isvalid(vec2s v)
+ CGLM_INLINE vec2s glms_vec2_sign(vec2s v)
+ CGLM_INLINE vec2s glms_vec2_sqrt(vec2s v)
+ */
+
+#ifndef cglms_vec2s_ext_h
+#define cglms_vec2s_ext_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../util.h"
+#include "../vec2-ext.h"
+
+/*!
+ * @brief fill a vector with specified value
+ *
+ * @param[in] val value
+ * @returns dest
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_fill(float val) {
+ vec2s r;
+ glm_vec2_fill(r.raw, val);
+ return r;
+}
+
+/*!
+ * @brief check if vector is equal to value (without epsilon)
+ *
+ * @param[in] v vector
+ * @param[in] val value
+ */
+CGLM_INLINE
+bool
+glms_vec2_eq(vec2s v, float val) {
+ return glm_vec2_eq(v.raw, val);
+}
+
+/*!
+ * @brief check if vector is equal to value (with epsilon)
+ *
+ * @param[in] v vector
+ * @param[in] val value
+ */
+CGLM_INLINE
+bool
+glms_vec2_eq_eps(vec2s v, float val) {
+ return glm_vec2_eq_eps(v.raw, val);
+}
+
+/*!
+ * @brief check if vectors members are equal (without epsilon)
+ *
+ * @param[in] v vector
+ */
+CGLM_INLINE
+bool
+glms_vec2_eq_all(vec2s v) {
+ return glm_vec2_eq_all(v.raw);
+}
+
+/*!
+ * @brief check if vector is equal to another (without epsilon)
+ *
+ * @param[in] a vector
+ * @param[in] b vector
+ */
+CGLM_INLINE
+bool
+glms_vec2_eqv(vec2s a, vec2s b) {
+ return glm_vec2_eqv(a.raw, b.raw);
+}
+
+/*!
+ * @brief check if vector is equal to another (with epsilon)
+ *
+ * @param[in] a vector
+ * @param[in] b vector
+ */
+CGLM_INLINE
+bool
+glms_vec2_eqv_eps(vec2s a, vec2s b) {
+ return glm_vec2_eqv_eps(a.raw, b.raw);
+}
+
+/*!
+ * @brief max value of vector
+ *
+ * @param[in] v vector
+ */
+CGLM_INLINE
+float
+glms_vec2_max(vec2s v) {
+ return glm_vec2_max(v.raw);
+}
+
+/*!
+ * @brief min value of vector
+ *
+ * @param[in] v vector
+ */
+CGLM_INLINE
+float
+glms_vec2_min(vec2s v) {
+ return glm_vec2_min(v.raw);
+}
+
+/*!
+ * @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
+glms_vec2_isnan(vec2s v) {
+ return glm_vec2_isnan(v.raw);
+}
+
+/*!
+ * @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
+glms_vec2_isinf(vec2s v) {
+ return glm_vec2_isinf(v.raw);
+}
+
+/*!
+ * @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
+glms_vec2_isvalid(vec2s v) {
+ return glm_vec2_isvalid(v.raw);
+}
+
+/*!
+ * @brief get sign of 32 bit float as +1, -1, 0
+ *
+ * Important: It returns 0 for zero/NaN input
+ *
+ * @param v vector
+ * @returns sign vector
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_sign(vec2s v) {
+ vec2s r;
+ glm_vec2_sign(v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief square root of each vector item
+ *
+ * @param[in] v vector
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_sqrt(vec2s v) {
+ vec2s r;
+ glm_vec2_sqrt(v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief treat vectors as complex numbers and multiply them as such.
+ *
+ * @param[in] a left number
+ * @param[in] b right number
+ * @param[out] dest destination number
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_complex_mul(vec2s a, vec2s b, vec2s dest) {
+ glm_vec2_complex_mul(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief treat vectors as complex numbers and divide them as such.
+ *
+ * @param[in] a left number (numerator)
+ * @param[in] b right number (denominator)
+ * @param[out] dest destination number
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_complex_div(vec2s a, vec2s b, vec2s dest) {
+ glm_vec2_complex_div(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief treat the vector as a complex number and conjugate it as such.
+ *
+ * @param[in] a the number
+ * @param[out] dest destination number
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_complex_conjugate(vec2s a, vec2s dest) {
+ glm_vec2_complex_conjugate(a.raw, dest.raw);
+ return dest;
+}
+
+#endif /* cglms_vec2s_ext_h */
diff --git a/libs/cglm/include/cglm/struct/vec2.h b/libs/cglm/include/cglm/struct/vec2.h
new file mode 100644
index 0000000..60f66d3
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/vec2.h
@@ -0,0 +1,561 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Macros:
+ GLMS_VEC2_ONE_INIT
+ GLMS_VEC2_ZERO_INIT
+ GLMS_VEC2_ONE
+ GLMS_VEC2_ZERO
+
+ Functions:
+ CGLM_INLINE vec2s glms_vec2(vec3s v3)
+ CGLM_INLINE void glms_vec2_pack(vec2s dst[], vec2 src[], size_t len)
+ CGLM_INLINE void glms_vec2_unpack(vec2 dst[], vec2s src[], size_t len)
+ CGLM_INLINE vec2s glms_vec2_zero(void)
+ CGLM_INLINE vec2s glms_vec2_one(void)
+ CGLM_INLINE float glms_vec2_dot(vec2s a, vec2s b)
+ CGLM_INLINE float glms_vec2_cross(vec2s a, vec2s b)
+ CGLM_INLINE float glms_vec2_norm2(vec2s v)
+ CGLM_INLINE float glms_vec2_norm(vec2s v)
+ CGLM_INLINE vec2s glms_vec2_add(vec2s a, vec2s b)
+ CGLM_INLINE vec2s glms_vec2_adds(vec2s a, float s)
+ CGLM_INLINE vec2s glms_vec2_sub(vec2s a, vec2s b)
+ CGLM_INLINE vec2s glms_vec2_subs(vec2s a, float s)
+ CGLM_INLINE vec2s glms_vec2_mul(vec2s a, vec2s b)
+ CGLM_INLINE vec2s glms_vec2_scale(vec2s v, float s)
+ CGLM_INLINE vec2s glms_vec2_scale_as(vec2s v, float s)
+ CGLM_INLINE vec2s glms_vec2_div(vec2s a, vec2s b)
+ CGLM_INLINE vec2s glms_vec2_divs(vec2s a, float s)
+ CGLM_INLINE vec2s glms_vec2_addadd(vec2s a, vec2s b, vec2s dest)
+ CGLM_INLINE vec2s glms_vec2_subadd(vec2s a, vec2s b, vec2s dest)
+ CGLM_INLINE vec2s glms_vec2_muladd(vec2s a, vec2s b, vec2s dest)
+ CGLM_INLINE vec2s glms_vec2_muladds(vec2s a, float s, vec2s dest)
+ CGLM_INLINE vec2s glms_vec2_maxadd(vec2s a, vec2s b, vec2s dest)
+ CGLM_INLINE vec2s glms_vec2_minadd(vec2s a, vec2s b, vec2s dest)
+ CGLM_INLINE vec2s glms_vec2_negate(vec2s v)
+ CGLM_INLINE vec2s glms_vec2_normalize(vec2s v)
+ CGLM_INLINE vec2s glms_vec2_rotate(vec2s v, float angle, vec2s axis)
+ CGLM_INLINE float glms_vec2_distance(vec2s a, vec2s b)
+ CGLM_INLINE float glms_vec2_distance2(vec2s a, vec2s b)
+ CGLM_INLINE vec2s glms_vec2_maxv(vec2s a, vec2s b)
+ CGLM_INLINE vec2s glms_vec2_minv(vec2s a, vec2s b)
+ CGLM_INLINE vec2s glms_vec2_clamp(vec2s v, float minVal, float maxVal)
+ CGLM_INLINE vec2s glms_vec2_lerp(vec2s from, vec2s to, float t)
+ */
+
+#ifndef cglms_vec2s_h
+#define cglms_vec2s_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../util.h"
+#include "../vec2.h"
+#include "vec2-ext.h"
+
+#define GLMS_VEC2_ONE_INIT {GLM_VEC2_ONE_INIT}
+#define GLMS_VEC2_ZERO_INIT {GLM_VEC2_ZERO_INIT}
+
+#define GLMS_VEC2_ONE ((vec2s)GLMS_VEC2_ONE_INIT)
+#define GLMS_VEC2_ZERO ((vec2s)GLMS_VEC2_ZERO_INIT)
+
+/*!
+ * @brief init vec2 using vec2
+ *
+ * @param[in] v3 vector3
+ * @returns destination
+ */
+CGLM_INLINE
+vec2s
+glms_vec2(vec3s v3) {
+ vec2s r;
+ glm_vec2(v3.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief pack an array of vec2 into an array of vec2s
+ *
+ * @param[out] dst array of vec2
+ * @param[in] src array of vec2s
+ * @param[in] len number of elements
+ */
+CGLM_INLINE
+void
+glms_vec2_pack(vec2s dst[], vec2 src[], size_t len) {
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ glm_vec2_copy(src[i], dst[i].raw);
+ }
+}
+
+/*!
+ * @brief unpack an array of vec2s into an array of vec2
+ *
+ * @param[out] dst array of vec2s
+ * @param[in] src array of vec2
+ * @param[in] len number of elements
+ */
+CGLM_INLINE
+void
+glms_vec2_unpack(vec2 dst[], vec2s src[], size_t len) {
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ glm_vec2_copy(src[i].raw, dst[i]);
+ }
+}
+
+/*!
+ * @brief make vector zero
+ *
+ * @returns zero vector
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_zero(void) {
+ vec2s r;
+ glm_vec2_zero(r.raw);
+ return r;
+}
+
+/*!
+ * @brief make vector one
+ *
+ * @returns one vector
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_one(void) {
+ vec2s r;
+ glm_vec2_one(r.raw);
+ return r;
+}
+
+/*!
+ * @brief vec2 dot product
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ *
+ * @return dot product
+ */
+CGLM_INLINE
+float
+glms_vec2_dot(vec2s a, vec2s b) {
+ return glm_vec2_dot(a.raw, b.raw);
+}
+
+/*!
+ * @brief vec2 cross product
+ *
+ * REF: http://allenchou.net/2013/07/cross-product-of-2d-vectors/
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ *
+ * @return Z component of cross product
+ */
+CGLM_INLINE
+float
+glms_vec2_cross(vec2s a, vec2s b) {
+ return glm_vec2_cross(a.raw, b.raw);
+}
+
+/*!
+ * @brief norm * norm (magnitude) of vec
+ *
+ * we can use this func instead of calling norm * norm, because it would call
+ * sqrtf fuction twice but with this func we can avoid func call, maybe this is
+ * not good name for this func
+ *
+ * @param[in] v vector
+ *
+ * @return norm * norm
+ */
+CGLM_INLINE
+float
+glms_vec2_norm2(vec2s v) {
+ return glm_vec2_norm2(v.raw);
+}
+
+/*!
+ * @brief norm (magnitude) of vec2
+ *
+ * @param[in] v vector
+ *
+ * @return norm
+ */
+CGLM_INLINE
+float
+glms_vec2_norm(vec2s v) {
+ return glm_vec2_norm(v.raw);
+}
+
+/*!
+ * @brief add a vector to b vector store result in dest
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_add(vec2s a, vec2s b) {
+ vec2s r;
+ glm_vec2_add(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief add scalar to v vector store result in dest (d = v + s)
+ *
+ * @param[in] a vector
+ * @param[in] s scalar
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_adds(vec2s a, float s) {
+ vec2s r;
+ glm_vec2_adds(a.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief subtract b vector from a vector store result in dest
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_sub(vec2s a, vec2s b) {
+ vec2s r;
+ glm_vec2_sub(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief subtract scalar from v vector store result in dest (d = v - s)
+ *
+ * @param[in] a vector
+ * @param[in] s scalar
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_subs(vec2s a, float s) {
+ vec2s r;
+ glm_vec2_subs(a.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief multiply two vector (component-wise multiplication)
+ *
+ * @param a vector1
+ * @param b vector2
+ * @returns v3 = (a[0] * b[0], a[1] * b[1], a[2] * b[2])
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_mul(vec2s a, vec2s b) {
+ vec2s r;
+ glm_vec2_mul(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief multiply/scale vec2 vector with scalar: result = v * s
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_scale(vec2s v, float s) {
+ vec2s r;
+ glm_vec2_scale(v.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief make vec2 vector scale as specified: result = unit(v) * s
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_scale_as(vec2s v, float s) {
+ vec2s r;
+ glm_vec2_scale_as(v.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief div vector with another component-wise division: d = a / b
+ *
+ * @param[in] a vector 1
+ * @param[in] b vector 2
+ * @returns result = (a[0]/b[0], a[1]/b[1], a[2]/b[2])
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_div(vec2s a, vec2s b) {
+ vec2s r;
+ glm_vec2_div(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief div vector with scalar: d = v / s
+ *
+ * @param[in] a vector
+ * @param[in] s scalar
+ * @returns result = (a[0]/s, a[1]/s, a[2]/s)
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_divs(vec2s a, float s) {
+ vec2s r;
+ glm_vec2_divs(a.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @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
+ * @returns dest += (a + b)
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_addadd(vec2s a, vec2s b, vec2s dest) {
+ glm_vec2_addadd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @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
+ * @returns dest += (a + b)
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_subadd(vec2s a, vec2s b, vec2s dest) {
+ glm_vec2_subadd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @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
+ * @returns dest += (a * b)
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_muladd(vec2s a, vec2s b, vec2s dest) {
+ glm_vec2_muladd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @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
+ * @returns dest += (a * b)
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_muladds(vec2s a, float s, vec2s dest) {
+ glm_vec2_muladds(a.raw, s, dest.raw);
+ return dest;
+}
+
+/*!
+ * @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
+ * @returns dest += max(a, b)
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_maxadd(vec2s a, vec2s b, vec2s dest) {
+ glm_vec2_maxadd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief add min of two vector to result/dest
+ *
+ * it applies += operator so dest must be initialized
+ *
+ * @param[in] a vector 1
+ * @param[in] b vector 2
+ * @returns dest += min(a, b)
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_minadd(vec2s a, vec2s b, vec2s dest) {
+ glm_vec2_minadd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief negate vector components
+ *
+ * @param[in] v vector
+ * @returns negated vector
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_negate(vec2s v) {
+ glm_vec2_negate(v.raw);
+ return v;
+}
+
+/*!
+ * @brief normalize vec2 and store result in same vec
+ *
+ * @param[in] v vector
+ * @returns normalized vector
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_normalize(vec2s v) {
+ glm_vec2_normalize(v.raw);
+ return v;
+}
+
+/*!
+ * @brief rotate vec2 by angle using Rodrigues' rotation formula
+ *
+ * @param[in] v vector
+ * @param[in] angle angle by radians
+ * @returns rotated vector
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_rotate(vec2s v, float angle) {
+ vec2s r;
+ glm_vec2_rotate(v.raw, angle, r.raw);
+ return r;
+}
+
+/**
+ * @brief distance between two vectors
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @return distance
+ */
+CGLM_INLINE
+float
+glms_vec2_distance(vec2s a, vec2s b) {
+ return glm_vec2_distance(a.raw, b.raw);
+}
+
+/**
+ * @brief squared distance between two vectors
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @return squared distance (distance * distance)
+ */
+CGLM_INLINE
+float
+glms_vec2_distance2(vec2s a, vec2s b) {
+ return glm_vec2_distance2(a.raw, b.raw);
+}
+
+/*!
+ * @brief max values of vectors
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @returns destination
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_maxv(vec2s a, vec2s b) {
+ vec2s r;
+ glm_vec2_maxv(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief min values of vectors
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @returns destination
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_minv(vec2s a, vec2s b) {
+ vec2s r;
+ glm_vec2_minv(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief clamp vector's individual members between min and max values
+ *
+ * @param[in] v vector
+ * @param[in] minVal minimum value
+ * @param[in] maxVal maximum value
+ * @returns clamped vector
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_clamp(vec2s v, float minVal, float maxVal) {
+ glm_vec2_clamp(v.raw, minVal, maxVal);
+ return v;
+}
+
+/*!
+ * @brief linear interpolation between two vectors
+ *
+ * formula: from + s * (to - from)
+ *
+ * @param[in] from from value
+ * @param[in] to to value
+ * @param[in] t interpolant (amount)
+ * @returns destination
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_lerp(vec2s from, vec2s to, float t) {
+ vec2s r;
+ glm_vec2_lerp(from.raw, to.raw, t, r.raw);
+ return r;
+}
+
+#endif /* cglms_vec2s_h */
diff --git a/libs/cglm/include/cglm/struct/vec3-ext.h b/libs/cglm/include/cglm/struct/vec3-ext.h
new file mode 100644
index 0000000..8e5ca70
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/vec3-ext.h
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*!
+ * @brief SIMD like functions
+ */
+
+/*
+ Functions:
+ CGLM_INLINE vec3s glms_vec3_broadcast(float val);
+ CGLM_INLINE vec3s glms_vec3_fill(float val);
+ CGLM_INLINE bool glms_vec3_eq(vec3s v, float val);
+ CGLM_INLINE bool glms_vec3_eq_eps(vec3s v, float val);
+ CGLM_INLINE bool glms_vec3_eq_all(vec3s v);
+ CGLM_INLINE bool glms_vec3_eqv(vec3s a, vec3s b);
+ CGLM_INLINE bool glms_vec3_eqv_eps(vec3s a, vec3s b);
+ CGLM_INLINE float glms_vec3_max(vec3s v);
+ CGLM_INLINE float glms_vec3_min(vec3s v);
+ CGLM_INLINE bool glms_vec3_isnan(vec3s v);
+ CGLM_INLINE bool glms_vec3_isinf(vec3s v);
+ CGLM_INLINE bool glms_vec3_isvalid(vec3s v);
+ CGLM_INLINE vec3s glms_vec3_sign(vec3s v);
+ CGLM_INLINE vec3s glms_vec3_abs(vec3s v);
+ CGLM_INLINE vec3s glms_vec3_fract(vec3s v);
+ CGLM_INLINE float glms_vec3_hadd(vec3s v);
+ CGLM_INLINE vec3s glms_vec3_sqrt(vec3s v);
+ */
+
+#ifndef cglms_vec3s_ext_h
+#define cglms_vec3s_ext_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../util.h"
+#include "../vec3-ext.h"
+
+/*!
+ * @brief fill a vector with specified value
+ *
+ * @param[in] val value
+ * @returns dest
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_broadcast(float val) {
+ vec3s r;
+ glm_vec3_broadcast(val, r.raw);
+ return r;
+}
+
+/*!
+ * @brief fill a vector with specified value
+ *
+ * @param[in] val value
+ * @returns dest
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_fill(float val) {
+ vec3s r;
+ glm_vec3_fill(r.raw, val);
+ return r;
+}
+
+/*!
+ * @brief check if vector is equal to value (without epsilon)
+ *
+ * @param[in] v vector
+ * @param[in] val value
+ */
+CGLM_INLINE
+bool
+glms_vec3_eq(vec3s v, float val) {
+ return glm_vec3_eq(v.raw, val);
+}
+
+/*!
+ * @brief check if vector is equal to value (with epsilon)
+ *
+ * @param[in] v vector
+ * @param[in] val value
+ */
+CGLM_INLINE
+bool
+glms_vec3_eq_eps(vec3s v, float val) {
+ return glm_vec3_eq_eps(v.raw, val);
+}
+
+/*!
+ * @brief check if vectors members are equal (without epsilon)
+ *
+ * @param[in] v vector
+ */
+CGLM_INLINE
+bool
+glms_vec3_eq_all(vec3s v) {
+ return glm_vec3_eq_all(v.raw);
+}
+
+/*!
+ * @brief check if vector is equal to another (without epsilon)
+ *
+ * @param[in] a vector
+ * @param[in] b vector
+ */
+CGLM_INLINE
+bool
+glms_vec3_eqv(vec3s a, vec3s b) {
+ return glm_vec3_eqv(a.raw, b.raw);
+}
+
+/*!
+ * @brief check if vector is equal to another (with epsilon)
+ *
+ * @param[in] a vector
+ * @param[in] b vector
+ */
+CGLM_INLINE
+bool
+glms_vec3_eqv_eps(vec3s a, vec3s b) {
+ return glm_vec3_eqv_eps(a.raw, b.raw);
+}
+
+/*!
+ * @brief max value of vector
+ *
+ * @param[in] v vector
+ */
+CGLM_INLINE
+float
+glms_vec3_max(vec3s v) {
+ return glm_vec3_max(v.raw);
+}
+
+/*!
+ * @brief min value of vector
+ *
+ * @param[in] v vector
+ */
+CGLM_INLINE
+float
+glms_vec3_min(vec3s v) {
+ return glm_vec3_min(v.raw);
+}
+
+/*!
+ * @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
+glms_vec3_isnan(vec3s v) {
+ return glm_vec3_isnan(v.raw);
+}
+
+/*!
+ * @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
+glms_vec3_isinf(vec3s v) {
+ return glm_vec3_isinf(v.raw);
+}
+
+/*!
+ * @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
+glms_vec3_isvalid(vec3s v) {
+ return glm_vec3_isvalid(v.raw);
+}
+
+/*!
+ * @brief get sign of 32 bit float as +1, -1, 0
+ *
+ * Important: It returns 0 for zero/NaN input
+ *
+ * @param v vector
+ * @returns sign vector
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_sign(vec3s v) {
+ vec3s r;
+ glm_vec3_sign(v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief absolute value of each vector item
+ *
+ * @param[in] v vector
+ * @return destination vector
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_abs(vec3s v) {
+ vec3s r;
+ glm_vec3_abs(v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief fractional part of each vector item
+ *
+ * @param[in] v vector
+ * @return dest destination vector
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_fract(vec3s v) {
+ vec3s r;
+ glm_vec3_fract(v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief vector reduction by summation
+ * @warning could overflow
+ *
+ * @param[in] v vector
+ * @return sum of all vector's elements
+ */
+CGLM_INLINE
+float
+glms_vec3_hadd(vec3s v) {
+ return glm_vec3_hadd(v.raw);
+}
+
+/*!
+ * @brief square root of each vector item
+ *
+ * @param[in] v vector
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_sqrt(vec3s v) {
+ vec3s r;
+ glm_vec3_sqrt(v.raw, r.raw);
+ return r;
+}
+
+#endif /* cglms_vec3s_ext_h */
diff --git a/libs/cglm/include/cglm/struct/vec3.h b/libs/cglm/include/cglm/struct/vec3.h
new file mode 100644
index 0000000..7fa5b06
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/vec3.h
@@ -0,0 +1,970 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Macros:
+ GLMS_VEC3_ONE_INIT
+ GLMS_VEC3_ZERO_INIT
+ GLMS_VEC3_ONE
+ GLMS_VEC3_ZERO
+ GLMS_YUP
+ GLMS_ZUP
+ GLMS_XUP
+
+ Functions:
+ CGLM_INLINE vec3s glms_vec3(vec4s v4);
+ CGLM_INLINE void glms_vec3_pack(vec3s dst[], vec3 src[], size_t len);
+ CGLM_INLINE void glms_vec3_unpack(vec3 dst[], vec3s src[], size_t len);
+ CGLM_INLINE vec3s glms_vec3_zero(void);
+ CGLM_INLINE vec3s glms_vec3_one(void);
+ CGLM_INLINE float glms_vec3_dot(vec3s a, vec3s b);
+ CGLM_INLINE float glms_vec3_norm2(vec3s v);
+ CGLM_INLINE float glms_vec3_norm(vec3s v);
+ CGLM_INLINE float glms_vec3_norm_one(vec3s v);
+ CGLM_INLINE float glms_vec3_norm_inf(vec3s v);
+ CGLM_INLINE vec3s glms_vec3_add(vec3s a, vec3s b);
+ CGLM_INLINE vec3s glms_vec3_adds(vec3s a, float s);
+ CGLM_INLINE vec3s glms_vec3_sub(vec3s a, vec3s b);
+ CGLM_INLINE vec3s glms_vec3_subs(vec3s a, float s);
+ CGLM_INLINE vec3s glms_vec3_mul(vec3s a, vec3s b);
+ CGLM_INLINE vec3s glms_vec3_scale(vec3s v, float s);
+ CGLM_INLINE vec3s glms_vec3_scale_as(vec3s v, float s);
+ CGLM_INLINE vec3s glms_vec3_div(vec3s a, vec3s b);
+ CGLM_INLINE vec3s glms_vec3_divs(vec3s a, float s);
+ CGLM_INLINE vec3s glms_vec3_addadd(vec3s a, vec3s b, vec3s dest);
+ CGLM_INLINE vec3s glms_vec3_subadd(vec3s a, vec3s b, vec3s dest);
+ CGLM_INLINE vec3s glms_vec3_muladd(vec3s a, vec3s b, vec3s dest);
+ CGLM_INLINE vec3s glms_vec3_muladds(vec3s a, float s, vec3s dest);
+ CGLM_INLINE vec3s glms_vec3_maxadd(vec3s a, vec3s b, vec3s dest);
+ CGLM_INLINE vec3s glms_vec3_minadd(vec3s a, vec3s b, vec3s dest);
+ CGLM_INLINE vec3s glms_vec3_flipsign(vec3s v);
+ CGLM_INLINE vec3s glms_vec3_negate(vec3s v);
+ CGLM_INLINE vec3s glms_vec3_inv(vec3s v);
+ CGLM_INLINE vec3s glms_vec3_normalize(vec3s v);
+ CGLM_INLINE vec3s glms_vec3_cross(vec3s a, vec3s b);
+ CGLM_INLINE vec3s glms_vec3_crossn(vec3s a, vec3s b);
+ CGLM_INLINE float glms_vec3_angle(vec3s a, vec3s b);
+ CGLM_INLINE vec3s glms_vec3_rotate(vec3s v, float angle, vec3s axis);
+ CGLM_INLINE vec3s glms_vec3_rotate_m4(mat4s m, vec3s v);
+ CGLM_INLINE vec3s glms_vec3_rotate_m3(mat3s m, vec3s v);
+ CGLM_INLINE vec3s glms_vec3_proj(vec3s a, vec3s b);
+ CGLM_INLINE vec3s glms_vec3_center(vec3s a, vec3s b);
+ CGLM_INLINE float glms_vec3_distance(vec3s a, vec3s b);
+ CGLM_INLINE float glms_vec3_distance2(vec3s a, vec3s b);
+ CGLM_INLINE vec3s glms_vec3_maxv(vec3s a, vec3s b);
+ CGLM_INLINE vec3s glms_vec3_minv(vec3s a, vec3s b);
+ CGLM_INLINE vec3s glms_vec3_ortho(vec3s v);
+ CGLM_INLINE vec3s glms_vec3_clamp(vec3s v, float minVal, float maxVal);
+ CGLM_INLINE vec3s glms_vec3_lerp(vec3s from, vec3s to, float t);
+ CGLM_INLINE vec3s glms_vec3_lerpc(vec3s from, vec3s to, float t);
+ CGLM_INLINE vec3s glms_vec3_mix(vec3s from, vec3s to, float t);
+ CGLM_INLINE vec3s glms_vec3_mixc(vec3s from, vec3s to, float t);
+ CGLM_INLINE vec3s glms_vec3_step_uni(float edge, vec3s x);
+ CGLM_INLINE vec3s glms_vec3_step(vec3s edge, vec3s x);
+ CGLM_INLINE vec3s glms_vec3_smoothstep_uni(float edge0, float edge1, vec3s x);
+ CGLM_INLINE vec3s glms_vec3_smoothstep(vec3s edge0, vec3s edge1, vec3s x);
+ CGLM_INLINE vec3s glms_vec3_smoothinterp(vec3s from, vec3s to, float t);
+ CGLM_INLINE vec3s glms_vec3_smoothinterpc(vec3s from, vec3s to, float t);
+ CGLM_INLINE vec3s glms_vec3_swizzle(vec3s v, int mask);
+
+ Convenient:
+ CGLM_INLINE vec3s glms_cross(vec3s a, vec3s b);
+ CGLM_INLINE float glms_dot(vec3s a, vec3s b);
+ CGLM_INLINE vec3s glms_normalize(vec3s v);
+ */
+
+#ifndef cglms_vec3s_h
+#define cglms_vec3s_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../util.h"
+#include "../vec3.h"
+#include "vec3-ext.h"
+
+#define GLMS_VEC3_ONE_INIT {GLM_VEC3_ONE_INIT}
+#define GLMS_VEC3_ZERO_INIT {GLM_VEC3_ZERO_INIT}
+
+#define GLMS_VEC3_ONE ((vec3s)GLMS_VEC3_ONE_INIT)
+#define GLMS_VEC3_ZERO ((vec3s)GLMS_VEC3_ZERO_INIT)
+
+#define GLMS_YUP ((vec3s){{0.0f, 1.0f, 0.0f}})
+#define GLMS_ZUP ((vec3s){{0.0f, 0.0f, 1.0f}})
+#define GLMS_XUP ((vec3s){{1.0f, 0.0f, 0.0f}})
+
+/*!
+ * @brief init vec3 using vec4
+ *
+ * @param[in] v4 vector4
+ * @returns destination
+ */
+CGLM_INLINE
+vec3s
+glms_vec3(vec4s v4) {
+ vec3s r;
+ glm_vec3(v4.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief pack an array of vec3 into an array of vec3s
+ *
+ * @param[out] dst array of vec3
+ * @param[in] src array of vec3s
+ * @param[in] len number of elements
+ */
+CGLM_INLINE
+void
+glms_vec3_pack(vec3s dst[], vec3 src[], size_t len) {
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ glm_vec3_copy(src[i], dst[i].raw);
+ }
+}
+
+/*!
+ * @brief unpack an array of vec3s into an array of vec3
+ *
+ * @param[out] dst array of vec3s
+ * @param[in] src array of vec3
+ * @param[in] len number of elements
+ */
+CGLM_INLINE
+void
+glms_vec3_unpack(vec3 dst[], vec3s src[], size_t len) {
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ glm_vec3_copy(src[i].raw, dst[i]);
+ }
+}
+
+/*!
+ * @brief make vector zero
+ *
+ * @returns zero vector
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_zero(void) {
+ vec3s r;
+ glm_vec3_zero(r.raw);
+ return r;
+}
+
+/*!
+ * @brief make vector one
+ *
+ * @returns one vector
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_one(void) {
+ vec3s r;
+ glm_vec3_one(r.raw);
+ return r;
+}
+
+/*!
+ * @brief vec3 dot product
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ *
+ * @return dot product
+ */
+CGLM_INLINE
+float
+glms_vec3_dot(vec3s a, vec3s b) {
+ return glm_vec3_dot(a.raw, b.raw);
+}
+
+/*!
+ * @brief norm * norm (magnitude) of vec
+ *
+ * we can use this func instead of calling norm * norm, because it would call
+ * sqrtf fuction twice but with this func we can avoid func call, maybe this is
+ * not good name for this func
+ *
+ * @param[in] v vector
+ *
+ * @return norm * norm
+ */
+CGLM_INLINE
+float
+glms_vec3_norm2(vec3s v) {
+ return glm_vec3_norm2(v.raw);
+}
+
+/*!
+ * @brief norm (magnitude) of vec3
+ *
+ * @param[in] v vector
+ *
+ * @return norm
+ */
+CGLM_INLINE
+float
+glms_vec3_norm(vec3s v) {
+ return glm_vec3_norm(v.raw);
+}
+
+/*!
+ * @brief L1 norm of vec3
+ * Also known as Manhattan Distance or Taxicab norm.
+ * L1 Norm is the sum of the magnitudes of the vectors in a space.
+ * It is calculated as the sum of the absolute values of the vector components.
+ * In this norm, all the components of the vector are weighted equally.
+ *
+ * This computes:
+ * R = |v[0]| + |v[1]| + |v[2]|
+ *
+ * @param[in] v vector
+ *
+ * @return L1 norm
+ */
+CGLM_INLINE
+float
+glms_vec3_norm_one(vec3s v) {
+ return glm_vec3_norm_one(v.raw);
+}
+
+/*!
+ * @brief Infinity norm of vec3
+ * Also known as Maximum norm.
+ * Infinity Norm is the largest magnitude among each element of a vector.
+ * It is calculated as the maximum of the absolute values of the vector components.
+ *
+ * This computes:
+ * inf norm = max(|v[0]|, |v[1]|, |v[2]|)
+ *
+ * @param[in] v vector
+ *
+ * @return Infinity norm
+ */
+CGLM_INLINE
+float
+glms_vec3_norm_inf(vec3s v) {
+ return glm_vec3_norm_inf(v.raw);
+}
+
+/*!
+ * @brief add a vector to b vector store result in dest
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_add(vec3s a, vec3s b) {
+ vec3s r;
+ glm_vec3_add(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief add scalar to v vector store result in dest (d = v + s)
+ *
+ * @param[in] a vector
+ * @param[in] s scalar
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_adds(vec3s a, float s) {
+ vec3s r;
+ glm_vec3_adds(a.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief subtract b vector from a vector store result in dest
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_sub(vec3s a, vec3s b) {
+ vec3s r;
+ glm_vec3_sub(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief subtract scalar from v vector store result in dest (d = v - s)
+ *
+ * @param[in] a vector
+ * @param[in] s scalar
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_subs(vec3s a, float s) {
+ vec3s r;
+ glm_vec3_subs(a.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief multiply two vector (component-wise multiplication)
+ *
+ * @param a vector1
+ * @param b vector2
+ * @returns v3 = (a[0] * b[0], a[1] * b[1], a[2] * b[2])
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_mul(vec3s a, vec3s b) {
+ vec3s r;
+ glm_vec3_mul(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief multiply/scale vec3 vector with scalar: result = v * s
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_scale(vec3s v, float s) {
+ vec3s r;
+ glm_vec3_scale(v.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief make vec3 vector scale as specified: result = unit(v) * s
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_scale_as(vec3s v, float s) {
+ vec3s r;
+ glm_vec3_scale_as(v.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief div vector with another component-wise division: d = a / b
+ *
+ * @param[in] a vector 1
+ * @param[in] b vector 2
+ * @returns result = (a[0]/b[0], a[1]/b[1], a[2]/b[2])
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_div(vec3s a, vec3s b) {
+ vec3s r;
+ glm_vec3_div(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief div vector with scalar: d = v / s
+ *
+ * @param[in] a vector
+ * @param[in] s scalar
+ * @returns result = (a[0]/s, a[1]/s, a[2]/s)
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_divs(vec3s a, float s) {
+ vec3s r;
+ glm_vec3_divs(a.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @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
+ * @returns dest += (a + b)
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_addadd(vec3s a, vec3s b, vec3s dest) {
+ glm_vec3_addadd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @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
+ * @returns dest += (a + b)
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_subadd(vec3s a, vec3s b, vec3s dest) {
+ glm_vec3_subadd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @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
+ * @returns dest += (a * b)
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_muladd(vec3s a, vec3s b, vec3s dest) {
+ glm_vec3_muladd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @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
+ * @returns dest += (a * b)
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_muladds(vec3s a, float s, vec3s dest) {
+ glm_vec3_muladds(a.raw, s, dest.raw);
+ return dest;
+}
+
+/*!
+ * @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
+ * @returns dest += max(a, b)
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_maxadd(vec3s a, vec3s b, vec3s dest) {
+ glm_vec3_maxadd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief add min of two vector to result/dest
+ *
+ * it applies += operator so dest must be initialized
+ *
+ * @param[in] a vector 1
+ * @param[in] b vector 2
+ * @returns dest += min(a, b)
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_minadd(vec3s a, vec3s b, vec3s dest) {
+ glm_vec3_minadd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief negate vector components and store result in dest
+ *
+ * @param[in] v vector
+ * @returns result vector
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_flipsign(vec3s v) {
+ glm_vec3_flipsign(v.raw);
+ return v;
+}
+
+/*!
+ * @brief negate vector components
+ *
+ * @param[in] v vector
+ * @returns negated vector
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_negate(vec3s v) {
+ glm_vec3_negate(v.raw);
+ return v;
+}
+
+/*!
+ * @brief normalize vec3 and store result in same vec
+ *
+ * @param[in] v vector
+ * @returns normalized vector
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_normalize(vec3s v) {
+ glm_vec3_normalize(v.raw);
+ return v;
+}
+
+/*!
+ * @brief cross product of two vector (RH)
+ *
+ * @param[in] a vector 1
+ * @param[in] b vector 2
+ * @returns destination
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_cross(vec3s a, vec3s b) {
+ vec3s r;
+ glm_vec3_cross(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief cross product of two vector (RH) and normalize the result
+ *
+ * @param[in] a vector 1
+ * @param[in] b vector 2
+ * @returns destination
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_crossn(vec3s a, vec3s b) {
+ vec3s r;
+ glm_vec3_crossn(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief angle betwen two vector
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ *
+ * @return angle as radians
+ */
+CGLM_INLINE
+float
+glms_vec3_angle(vec3s a, vec3s b) {
+ return glm_vec3_angle(a.raw, b.raw);
+}
+
+/*!
+ * @brief rotate vec3 around axis by angle using Rodrigues' rotation formula
+ *
+ * @param[in] v vector
+ * @param[in] axis axis vector (must be unit vector)
+ * @param[in] angle angle by radians
+ * @returns rotated vector
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_rotate(vec3s v, float angle, vec3s axis) {
+ glm_vec3_rotate(v.raw, angle, axis.raw);
+ return v;
+}
+
+/*!
+ * @brief apply rotation matrix to vector
+ *
+ * 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
+ * @returns rotated vector
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_rotate_m4(mat4s m, vec3s v) {
+ vec3s r;
+ glm_vec3_rotate_m4(m.raw, v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief apply rotation matrix to vector
+ *
+ * @param[in] m affine matrix or rot matrix
+ * @param[in] v vector
+ * @returns rotated vector
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_rotate_m3(mat3s m, vec3s v) {
+ vec3s r;
+ glm_vec3_rotate_m3(m.raw, v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief project a vector onto b vector
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @returns projected vector
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_proj(vec3s a, vec3s b) {
+ vec3s r;
+ glm_vec3_proj(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/**
+ * @brief find center point of two vector
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @returns center point
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_center(vec3s a, vec3s b) {
+ vec3s r;
+ glm_vec3_center(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/**
+ * @brief distance between two vectors
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @return distance
+ */
+CGLM_INLINE
+float
+glms_vec3_distance(vec3s a, vec3s b) {
+ return glm_vec3_distance(a.raw, b.raw);
+}
+
+/**
+ * @brief squared distance between two vectors
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @return squared distance (distance * distance)
+ */
+CGLM_INLINE
+float
+glms_vec3_distance2(vec3s a, vec3s b) {
+ return glm_vec3_distance2(a.raw, b.raw);
+}
+
+/*!
+ * @brief max values of vectors
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @returns destination
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_maxv(vec3s a, vec3s b) {
+ vec3s r;
+ glm_vec3_maxv(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief min values of vectors
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @returns destination
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_minv(vec3s a, vec3s b) {
+ vec3s r;
+ glm_vec3_minv(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief possible orthogonal/perpendicular vector
+ *
+ * @param[in] v vector
+ * @returns orthogonal/perpendicular vector
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_ortho(vec3s v) {
+ vec3s r;
+ glm_vec3_ortho(v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief clamp vector's individual members between min and max values
+ *
+ * @param[in] v vector
+ * @param[in] minVal minimum value
+ * @param[in] maxVal maximum value
+ * @returns clamped vector
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_clamp(vec3s v, float minVal, float maxVal) {
+ glm_vec3_clamp(v.raw, minVal, maxVal);
+ return v;
+}
+
+/*!
+ * @brief linear interpolation between two vectors
+ *
+ * formula: from + s * (to - from)
+ *
+ * @param[in] from from value
+ * @param[in] to to value
+ * @param[in] t interpolant (amount)
+ * @returns destination
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_lerp(vec3s from, vec3s to, float t) {
+ vec3s r;
+ glm_vec3_lerp(from.raw, to.raw, t, r.raw);
+ return r;
+}
+
+/*!
+ * @brief linear interpolation between two vectors (clamped)
+ *
+ * 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
+ * @returns destination
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_lerpc(vec3s from, vec3s to, float t) {
+ vec3s r;
+ glm_vec3_lerpc(from.raw, to.raw, t, r.raw);
+ return r;
+}
+
+/*!
+ * @brief linear interpolation between two vectors
+ *
+ * formula: from + s * (to - from)
+ *
+ * @param[in] from from value
+ * @param[in] to to value
+ * @param[in] t interpolant (amount)
+ * @returns destination
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_mix(vec3s from, vec3s to, float t) {
+ vec3s r;
+ glm_vec3_mix(from.raw, to.raw, t, r.raw);
+ return r;
+}
+
+/*!
+ * @brief linear interpolation between two vectors (clamped)
+ *
+ * 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
+ * @returns destination
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_mixc(vec3s from, vec3s to, float t) {
+ vec3s r;
+ glm_vec3_mixc(from.raw, to.raw, t, r.raw);
+ return r;
+}
+
+/*!
+ * @brief threshold function (unidimensional)
+ *
+ * @param[in] edge threshold
+ * @param[in] x value to test against threshold
+ * @returns 0.0 if x < edge, else 1.0
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_step_uni(float edge, vec3s x) {
+ vec3s r;
+ glm_vec3_step_uni(edge, x.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief threshold function
+ *
+ * @param[in] edge threshold
+ * @param[in] x value to test against threshold
+ * @returns 0.0 if x < edge, else 1.0
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_step(vec3s edge, vec3s x) {
+ vec3s r;
+ glm_vec3_step(edge.raw, x.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief threshold function with a smooth transition (unidimensional)
+ *
+ * @param[in] edge0 low threshold
+ * @param[in] edge1 high threshold
+ * @param[in] x value to test against threshold
+ * @returns destination
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_smoothstep_uni(float edge0, float edge1, vec3s x) {
+ vec3s r;
+ glm_vec3_smoothstep_uni(edge0, edge1, x.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief threshold function with a smooth transition
+ *
+ * @param[in] edge0 low threshold
+ * @param[in] edge1 high threshold
+ * @param[in] x value to test against threshold
+ * @returns destination
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_smoothstep(vec3s edge0, vec3s edge1, vec3s x) {
+ vec3s r;
+ glm_vec3_smoothstep(edge0.raw, edge1.raw, x.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief smooth Hermite interpolation between two vectors
+ *
+ * formula: from + s * (to - from)
+ *
+ * @param[in] from from value
+ * @param[in] to to value
+ * @param[in] t interpolant (amount)
+ * @returns destination
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_smoothinterp(vec3s from, vec3s to, float t) {
+ vec3s r;
+ glm_vec3_smoothinterp(from.raw, to.raw, t, r.raw);
+ return r;
+}
+
+/*!
+ * @brief smooth Hermite interpolation between two vectors (clamped)
+ *
+ * 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
+ * @returns destination
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_smoothinterpc(vec3s from, vec3s to, float t) {
+ vec3s r;
+ glm_vec3_smoothinterpc(from.raw, to.raw, t, r.raw);
+ return r;
+}
+
+/*!
+ * @brief vec3 cross product
+ *
+ * this is just convenient wrapper
+ *
+ * @param[in] a source 1
+ * @param[in] b source 2
+ * @returns destination
+ */
+CGLM_INLINE
+vec3s
+glms_cross(vec3s a, vec3s b) {
+ vec3s r;
+ glm_cross(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief vec3 dot product
+ *
+ * this is just convenient wrapper
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @return dot product
+ */
+CGLM_INLINE
+float
+glms_dot(vec3s a, vec3s b) {
+ return glm_dot(a.raw, b.raw);
+}
+
+/*!
+ * @brief normalize vec3 and store result in same vec
+ *
+ * this is just convenient wrapper
+ *
+ * @param[in] v vector
+ * @returns normalized vector
+ */
+CGLM_INLINE
+vec3s
+glms_normalize(vec3s v) {
+ glm_normalize(v.raw);
+ return v;
+}
+
+/*!
+ * @brief swizzle vector components
+ *
+ * you can use existin masks e.g. GLM_XXX, GLM_ZYX
+ *
+ * @param[in] v source
+ * @param[in] mask mask
+ * @returns swizzled vector
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_swizzle(vec3s v, int mask) {
+ vec3s dest;
+ glm_vec3_swizzle(v.raw, mask, dest.raw);
+ return dest;
+}
+
+#endif /* cglms_vec3s_h */
diff --git a/libs/cglm/include/cglm/struct/vec4-ext.h b/libs/cglm/include/cglm/struct/vec4-ext.h
new file mode 100644
index 0000000..d5cddec
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/vec4-ext.h
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*!
+ * @brief SIMD like functions
+ */
+
+/*
+ Functions:
+ CGLM_INLINE vec4s glms_vec4_broadcast(float val);
+ CGLM_INLINE vec4s glms_vec4_fill(float val);
+ CGLM_INLINE bool glms_vec4_eq(vec4s v, float val);
+ CGLM_INLINE bool glms_vec4_eq_eps(vec4s v, float val);
+ CGLM_INLINE bool glms_vec4_eq_all(vec4s v);
+ CGLM_INLINE bool glms_vec4_eqv(vec4s a, vec4s b);
+ CGLM_INLINE bool glms_vec4_eqv_eps(vec4s a, vec4s b);
+ CGLM_INLINE float glms_vec4_max(vec4s v);
+ CGLM_INLINE float glms_vec4_min(vec4s v);
+ CGLM_INLINE bool glms_vec4_isnan(vec4s v);
+ CGLM_INLINE bool glms_vec4_isinf(vec4s v);
+ CGLM_INLINE bool glms_vec4_isvalid(vec4s v);
+ CGLM_INLINE vec4s glms_vec4_sign(vec4s v);
+ CGLM_INLINE vec4s glms_vec4_abs(vec4s v);
+ CGLM_INLINE vec4s glms_vec4_fract(vec4s v);
+ CGLM_INLINE float glms_vec4_hadd(vec4s v);
+ CGLM_INLINE vec4s glms_vec4_sqrt(vec4s v);
+ */
+
+#ifndef cglms_vec4s_ext_h
+#define cglms_vec4s_ext_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../util.h"
+#include "../vec4-ext.h"
+
+/*!
+ * @brief fill a vector with specified value
+ *
+ * @param val value
+ * @returns dest
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_broadcast(float val) {
+ vec4s r;
+ glm_vec4_broadcast(val, r.raw);
+ return r;
+}
+
+/*!
+ * @brief fill a vector with specified value
+ *
+ * @param val value
+ * @returns dest
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_fill(float val) {
+ vec4s r;
+ glm_vec4_fill(r.raw, val);
+ return r;
+}
+
+/*!
+ * @brief check if vector is equal to value (without epsilon)
+ *
+ * @param v vector
+ * @param val value
+ */
+CGLM_INLINE
+bool
+glms_vec4_eq(vec4s v, float val) {
+ return glm_vec4_eq(v.raw, val);
+}
+
+/*!
+ * @brief check if vector is equal to value (with epsilon)
+ *
+ * @param v vector
+ * @param val value
+ */
+CGLM_INLINE
+bool
+glms_vec4_eq_eps(vec4s v, float val) {
+ return glm_vec4_eq_eps(v.raw, val);
+}
+
+/*!
+ * @brief check if vectors members are equal (without epsilon)
+ *
+ * @param v vector
+ */
+CGLM_INLINE
+bool
+glms_vec4_eq_all(vec4s v) {
+ return glm_vec4_eq_all(v.raw);
+}
+
+/*!
+ * @brief check if vector is equal to another (without epsilon)
+ *
+ * @param a vector
+ * @param b vector
+ */
+CGLM_INLINE
+bool
+glms_vec4_eqv(vec4s a, vec4s b) {
+ return glm_vec4_eqv(a.raw, b.raw);
+}
+
+/*!
+ * @brief check if vector is equal to another (with epsilon)
+ *
+ * @param a vector
+ * @param b vector
+ */
+CGLM_INLINE
+bool
+glms_vec4_eqv_eps(vec4s a, vec4s b) {
+ return glm_vec4_eqv_eps(a.raw, b.raw);
+}
+
+/*!
+ * @brief max value of vector
+ *
+ * @param v vector
+ */
+CGLM_INLINE
+float
+glms_vec4_max(vec4s v) {
+ return glm_vec4_max(v.raw);
+}
+
+/*!
+ * @brief min value of vector
+ *
+ * @param v vector
+ */
+CGLM_INLINE
+float
+glms_vec4_min(vec4s v) {
+ return glm_vec4_min(v.raw);
+}
+
+/*!
+ * @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
+glms_vec4_isnan(vec4s v) {
+ return glm_vec4_isnan(v.raw);
+}
+
+/*!
+ * @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
+glms_vec4_isinf(vec4s v) {
+ return glm_vec4_isinf(v.raw);
+}
+
+/*!
+ * @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
+glms_vec4_isvalid(vec4s v) {
+ return glm_vec4_isvalid(v.raw);
+}
+
+/*!
+ * @brief get sign of 32 bit float as +1, -1, 0
+ *
+ * Important: It returns 0 for zero/NaN input
+ *
+ * @param v vector
+ * @returns sign vector
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_sign(vec4s v) {
+ vec4s r;
+ glm_vec4_sign(v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief absolute value of each vector item
+ *
+ * @param[in] v vector
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_abs(vec4s v) {
+ vec4s r;
+ glm_vec4_abs(v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief fractional part of each vector item
+ *
+ * @param[in] v vector
+ * @returns dest destination vector
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_fract(vec4s v) {
+ vec4s r;
+ glm_vec4_fract(v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief vector reduction by summation
+ * @warning could overflow
+ *
+ * @param[in] v vector
+ * @return sum of all vector's elements
+ */
+CGLM_INLINE
+float
+glms_vec4_hadd(vec4s v) {
+ return glm_vec4_hadd(v.raw);
+}
+
+/*!
+ * @brief square root of each vector item
+ *
+ * @param[in] v vector
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_sqrt(vec4s v) {
+ vec4s r;
+ glm_vec4_sqrt(v.raw, r.raw);
+ return r;
+}
+
+#endif /* cglms_vec4s_ext_h */
diff --git a/libs/cglm/include/cglm/struct/vec4.h b/libs/cglm/include/cglm/struct/vec4.h
new file mode 100644
index 0000000..4469cb2
--- /dev/null
+++ b/libs/cglm/include/cglm/struct/vec4.h
@@ -0,0 +1,814 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Macros:
+ GLMS_VEC4_ONE_INIT
+ GLMS_VEC4_BLACK_INIT
+ GLMS_VEC4_ZERO_INIT
+ GLMS_VEC4_ONE
+ GLMS_VEC4_BLACK
+ GLMS_VEC4_ZERO
+
+ Functions:
+ CGLM_INLINE vec4s glms_vec4(vec3s v3, float last);
+ CGLM_INLINE vec3s glms_vec4_copy3(vec4s v);
+ CGLM_INLINE vec4s glms_vec4_copy(vec4s v);
+ CGLM_INLINE vec4s glms_vec4_ucopy(vec4s v);
+ CGLM_INLINE void glms_vec4_pack(vec4s dst[], vec4 src[], size_t len);
+ CGLM_INLINE void glms_vec4_unpack(vec4 dst[], vec4s src[], size_t len);
+ CGLM_INLINE float glms_vec4_dot(vec4s a, vec4s b);
+ CGLM_INLINE float glms_vec4_norm2(vec4s v);
+ CGLM_INLINE float glms_vec4_norm(vec4s v);
+ CGLM_INLINE float glms_vec4_norm_one(vec4s v);
+ CGLM_INLINE float glms_vec4_norm_inf(vec4s v);
+ CGLM_INLINE vec4s glms_vec4_add(vec4s a, vec4s b);
+ CGLM_INLINE vec4s glms_vec4_adds(vec4s v, float s);
+ CGLM_INLINE vec4s glms_vec4_sub(vec4s a, vec4s b);
+ CGLM_INLINE vec4s glms_vec4_subs(vec4s v, float s);
+ CGLM_INLINE vec4s glms_vec4_mul(vec4s a, vec4s b);
+ CGLM_INLINE vec4s glms_vec4_scale(vec4s v, float s);
+ CGLM_INLINE vec4s glms_vec4_scale_as(vec4s v, float s);
+ CGLM_INLINE vec4s glms_vec4_div(vec4s a, vec4s b);
+ CGLM_INLINE vec4s glms_vec4_divs(vec4s v, float s);
+ CGLM_INLINE vec4s glms_vec4_addadd(vec4s a, vec4s b, vec4s dest);
+ CGLM_INLINE vec4s glms_vec4_subadd(vec4s a, vec4s b, vec4s dest);
+ CGLM_INLINE vec4s glms_vec4_muladd(vec4s a, vec4s b, vec4s dest);
+ CGLM_INLINE vec4s glms_vec4_muladds(vec4s a, float s, vec4s dest);
+ CGLM_INLINE vec4s glms_vec4_maxadd(vec4s a, vec4s b, vec4s dest);
+ CGLM_INLINE vec4s glms_vec4_minadd(vec4s a, vec4s b, vec4s dest);
+ CGLM_INLINE vec4s glms_vec4_negate(vec4s v);
+ CGLM_INLINE vec4s glms_vec4_inv(vec4s v);
+ CGLM_INLINE vec4s glms_vec4_normalize(vec4s v);
+ CGLM_INLINE float glms_vec4_distance(vec4s a, vec4s b);
+ CGLM_INLINE float glms_vec4_distance2(vec4s a, vec4s b);
+ CGLM_INLINE vec4s glms_vec4_maxv(vec4s a, vec4s b);
+ CGLM_INLINE vec4s glms_vec4_minv(vec4s a, vec4s b);
+ CGLM_INLINE vec4s glms_vec4_clamp(vec4s v, float minVal, float maxVal);
+ CGLM_INLINE vec4s glms_vec4_lerp(vec4s from, vec4s to, float t);
+ CGLM_INLINE vec4s glms_vec4_lerpc(vec4s from, vec4s to, float t);
+ CGLM_INLINE vec4s glms_vec4_mix(vec4s from, vec4s to, float t);
+ CGLM_INLINE vec4s glms_vec4_mixc(vec4s from, vec4s to, float t);
+ CGLM_INLINE vec4s glms_vec4_step_uni(float edge, vec4s x);
+ CGLM_INLINE vec4s glms_vec4_step(vec4s edge, vec4s x);
+ CGLM_INLINE vec4s glms_vec4_smoothstep_uni(float edge0, float edge1, vec4s x);
+ CGLM_INLINE vec4s glms_vec4_smoothstep(vec4s edge0, vec4s edge1, vec4s x);
+ CGLM_INLINE vec4s glms_vec4_smoothinterp(vec4s from, vec4s to, float t);
+ CGLM_INLINE vec4s glms_vec4_smoothinterpc(vec4s from, vec4s to, float t);
+ CGLM_INLINE vec4s glms_vec4_cubic(float s);
+ CGLM_INLINE vec4s glms_vec4_swizzle(vec4s v, int mask);
+ */
+
+#ifndef cglms_vec4s_h
+#define cglms_vec4s_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../util.h"
+#include "../vec4.h"
+#include "vec4-ext.h"
+
+#define GLMS_VEC4_ONE_INIT {GLM_VEC4_ONE_INIT}
+#define GLMS_VEC4_BLACK_INIT {GLM_VEC4_BLACK_INIT}
+#define GLMS_VEC4_ZERO_INIT {GLM_VEC4_ZERO_INIT}
+
+#define GLMS_VEC4_ONE ((vec4s)GLM_VEC4_ONE_INIT)
+#define GLMS_VEC4_BLACK ((vec4s)GLM_VEC4_BLACK_INIT)
+#define GLMS_VEC4_ZERO ((vec4s)GLM_VEC4_ZERO_INIT)
+
+/*!
+ * @brief init vec4 using vec3
+ *
+ * @param[in] v3 vector3
+ * @param[in] last last item
+ * @returns destination
+ */
+CGLM_INLINE
+vec4s
+glms_vec4(vec3s v3, float last) {
+ vec4s r;
+ glm_vec4(v3.raw, last, r.raw);
+ return r;
+}
+
+/*!
+ * @brief copy first 3 members of [a] to [dest]
+ *
+ * @param[in] v source
+ * @returns vec3
+ */
+CGLM_INLINE
+vec3s
+glms_vec4_copy3(vec4s v) {
+ vec3s r;
+ glm_vec4_copy3(v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief copy all members of [a] to [dest]
+ *
+ * @param[in] v source
+ * @returns destination
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_copy(vec4s v) {
+ vec4s r;
+ glm_vec4_copy(v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief copy all members of [a] to [dest]
+ *
+ * alignment is not required
+ *
+ * @param[in] v source
+ * @returns destination
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_ucopy(vec4s v) {
+ vec4s r;
+ glm_vec4_ucopy(v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief pack an array of vec4 into an array of vec4s
+ *
+ * @param[out] dst array of vec4
+ * @param[in] src array of vec4s
+ * @param[in] len number of elements
+ */
+CGLM_INLINE
+void
+glms_vec4_pack(vec4s dst[], vec4 src[], size_t len) {
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ glm_vec4_copy(src[i], dst[i].raw);
+ }
+}
+
+/*!
+ * @brief unpack an array of vec4s into an array of vec4
+ *
+ * @param[out] dst array of vec4s
+ * @param[in] src array of vec4
+ * @param[in] len number of elements
+ */
+CGLM_INLINE
+void
+glms_vec4_unpack(vec4 dst[], vec4s src[], size_t len) {
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ glm_vec4_copy(src[i].raw, dst[i]);
+ }
+}
+
+/*!
+ * @brief make vector zero
+ *
+ * @returns zero vector
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_zero(void) {
+ vec4s r;
+ glm_vec4_zero(r.raw);
+ return r;
+}
+
+/*!
+ * @brief make vector one
+ *
+ * @returns one vector
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_one(void) {
+ vec4s r;
+ glm_vec4_one(r.raw);
+ return r;
+}
+
+/*!
+ * @brief vec4 dot product
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ *
+ * @return dot product
+ */
+CGLM_INLINE
+float
+glms_vec4_dot(vec4s a, vec4s b) {
+ return glm_vec4_dot(a.raw, b.raw);
+}
+
+/*!
+ * @brief norm * norm (magnitude) of vec
+ *
+ * we can use this func instead of calling norm * norm, because it would call
+ * sqrtf fuction twice but with this func we can avoid func call, maybe this is
+ * not good name for this func
+ *
+ * @param[in] v vec4
+ *
+ * @return norm * norm
+ */
+CGLM_INLINE
+float
+glms_vec4_norm2(vec4s v) {
+ return glm_vec4_norm2(v.raw);
+}
+
+/*!
+ * @brief norm (magnitude) of vec4
+ *
+ * @param[in] v vector
+ *
+ * @return norm
+ */
+CGLM_INLINE
+float
+glms_vec4_norm(vec4s v) {
+ return glm_vec4_norm(v.raw);
+}
+
+/*!
+ * @brief L1 norm of vec4
+ * Also known as Manhattan Distance or Taxicab norm.
+ * L1 Norm is the sum of the magnitudes of the vectors in a space.
+ * It is calculated as the sum of the absolute values of the vector components.
+ * In this norm, all the components of the vector are weighted equally.
+ *
+ * This computes:
+ * R = |v[0]| + |v[1]| + |v[2]| + |v[3]|
+ *
+ * @param[in] v vector
+ *
+ * @return L1 norm
+ */
+CGLM_INLINE
+float
+glms_vec4_norm_one(vec4s v) {
+ return glm_vec4_norm_one(v.raw);
+}
+
+/*!
+ * @brief Infinity norm of vec4
+ * Also known as Maximum norm.
+ * Infinity Norm is the largest magnitude among each element of a vector.
+ * It is calculated as the maximum of the absolute values of the vector components.
+ *
+ * This computes:
+ * inf norm = max(|v[0]|, |v[1]|, |v[2]|, |v[3]|)
+ *
+ * @param[in] v vector
+ *
+ * @return Infinity norm
+ */
+CGLM_INLINE
+float
+glms_vec4_norm_inf(vec4s v) {
+ return glm_vec4_norm_inf(v.raw);
+}
+
+/*!
+ * @brief add b vector to a vector store result in dest
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_add(vec4s a, vec4s b) {
+ vec4s r;
+ glm_vec4_add(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief add scalar to v vector store result in dest (d = v + vec(s))
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_adds(vec4s v, float s) {
+ vec4s r;
+ glm_vec4_adds(v.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief subtract b vector from a vector store result in dest (d = a - b)
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_sub(vec4s a, vec4s b) {
+ vec4s r;
+ glm_vec4_sub(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief subtract scalar from v vector store result in dest (d = v - vec(s))
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_subs(vec4s v, float s) {
+ vec4s r;
+ glm_vec4_subs(v.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief multiply two vector (component-wise multiplication)
+ *
+ * @param a vector1
+ * @param b vector2
+ * @returns dest = (a[0] * b[0], a[1] * b[1], a[2] * b[2], a[3] * b[3])
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_mul(vec4s a, vec4s b) {
+ vec4s r;
+ glm_vec4_mul(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief multiply/scale vec4 vector with scalar: result = v * s
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_scale(vec4s v, float s) {
+ vec4s r;
+ glm_vec4_scale(v.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief make vec4 vector scale as specified: result = unit(v) * s
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_scale_as(vec4s v, float s) {
+ vec4s r;
+ glm_vec4_scale_as(v.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief div vector with another component-wise division: d = a / b
+ *
+ * @param[in] a vector 1
+ * @param[in] b vector 2
+ * @returns result = (a[0]/b[0], a[1]/b[1], a[2]/b[2], a[3]/b[3])
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_div(vec4s a, vec4s b) {
+ vec4s r;
+ glm_vec4_div(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief div vec4 vector with scalar: d = v / s
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_divs(vec4s v, float s) {
+ vec4s r;
+ glm_vec4_divs(v.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @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
+ * @returns dest += (a + b)
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_addadd(vec4s a, vec4s b, vec4s dest) {
+ glm_vec4_addadd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @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
+ * @returns dest += (a - b)
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_subadd(vec4s a, vec4s b, vec4s dest) {
+ glm_vec4_subadd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @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
+ * @returns dest += (a * b)
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_muladd(vec4s a, vec4s b, vec4s dest) {
+ glm_vec4_muladd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @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
+ * @returns dest += (a * b)
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_muladds(vec4s a, float s, vec4s dest) {
+ glm_vec4_muladds(a.raw, s, dest.raw);
+ return dest;
+}
+
+/*!
+ * @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
+ * @returns dest += max(a, b)
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_maxadd(vec4s a, vec4s b, vec4s dest) {
+ glm_vec4_maxadd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief add min of two vector to result/dest
+ *
+ * it applies += operator so dest must be initialized
+ *
+ * @param[in] a vector 1
+ * @param[in] b vector 2
+ * @returns dest += min(a, b)
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_minadd(vec4s a, vec4s b, vec4s dest) {
+ glm_vec4_minadd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief negate vector components and store result in dest
+ *
+ * @param[in] v vector
+ * @returns result vector
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_negate(vec4s v) {
+ glm_vec4_negate(v.raw);
+ return v;
+}
+
+/*!
+ * @brief normalize vec4 and store result in same vec
+ *
+ * @param[in] v vector
+ * @returns normalized vector
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_normalize(vec4s v) {
+ glm_vec4_normalize(v.raw);
+ return v;
+}
+
+/**
+ * @brief distance between two vectors
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @return returns distance
+ */
+CGLM_INLINE
+float
+glms_vec4_distance(vec4s a, vec4s b) {
+ return glm_vec4_distance(a.raw, b.raw);
+}
+
+/**
+ * @brief squared distance between two vectors
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @return returns squared distance
+ */
+CGLM_INLINE
+float
+glms_vec4_distance2(vec4s a, vec4s b) {
+ return glm_vec4_distance2(a.raw, b.raw);
+}
+
+/*!
+ * @brief max values of vectors
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @returns destination
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_maxv(vec4s a, vec4s b) {
+ vec4s r;
+ glm_vec4_maxv(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief min values of vectors
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @returns destination
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_minv(vec4s a, vec4s b) {
+ vec4s r;
+ glm_vec4_minv(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief clamp vector's individual members between min and max values
+ *
+ * @param[in] v vector
+ * @param[in] minVal minimum value
+ * @param[in] maxVal maximum value
+ * @returns clamped vector
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_clamp(vec4s v, float minVal, float maxVal) {
+ glm_vec4_clamp(v.raw, minVal, maxVal);
+ return v;
+}
+
+/*!
+ * @brief linear interpolation between two vectors
+ *
+ * formula: from + s * (to - from)
+ *
+ * @param[in] from from value
+ * @param[in] to to value
+ * @param[in] t interpolant (amount)
+ * @returns destination
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_lerp(vec4s from, vec4s to, float t) {
+ vec4s r;
+ glm_vec4_lerp(from.raw, to.raw, t, r.raw);
+ return r;
+}
+
+/*!
+ * @brief linear interpolation between two vectors (clamped)
+ *
+ * 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
+ * @returns destination
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_lerpc(vec4s from, vec4s to, float t) {
+ vec4s r;
+ glm_vec4_lerpc(from.raw, to.raw, t, r.raw);
+ return r;
+}
+
+/*!
+ * @brief linear interpolation between two vectors
+ *
+ * formula: from + s * (to - from)
+ *
+ * @param[in] from from value
+ * @param[in] to to value
+ * @param[in] t interpolant (amount)
+ * @returns destination
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_mix(vec4s from, vec4s to, float t) {
+ vec4s r;
+ glm_vec4_mix(from.raw, to.raw, t, r.raw);
+ return r;
+}
+
+/*!
+ * @brief linear interpolation between two vectors (clamped)
+ *
+ * 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
+ * @returns destination
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_mixc(vec4s from, vec4s to, float t) {
+ vec4s r;
+ glm_vec4_mixc(from.raw, to.raw, t, r.raw);
+ return r;
+}
+
+/*!
+ * @brief threshold function (unidimensional)
+ *
+ * @param[in] edge threshold
+ * @param[in] x value to test against threshold
+ * @returns 0.0 if x < edge, else 1.0
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_step_uni(float edge, vec4s x) {
+ vec4s r;
+ glm_vec4_step_uni(edge, x.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief threshold function
+ *
+ * @param[in] edge threshold
+ * @param[in] x value to test against threshold
+ * @returns 0.0 if x < edge, else 1.0
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_step(vec4s edge, vec4s x) {
+ vec4s r;
+ glm_vec4_step(edge.raw, x.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief threshold function with a smooth transition (unidimensional)
+ *
+ * @param[in] edge0 low threshold
+ * @param[in] edge1 high threshold
+ * @param[in] x value to test against threshold
+ * @returns destination
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_smoothstep_uni(float edge0, float edge1, vec4s x) {
+ vec4s r;
+ glm_vec4_smoothstep_uni(edge0, edge1, x.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief threshold function with a smooth transition
+ *
+ * @param[in] edge0 low threshold
+ * @param[in] edge1 high threshold
+ * @param[in] x value to test against threshold
+ * @returns destination
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_smoothstep(vec4s edge0, vec4s edge1, vec4s x) {
+ vec4s r;
+ glm_vec4_smoothstep(edge0.raw, edge1.raw, x.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief smooth Hermite interpolation between two vectors
+ *
+ * formula: from + s * (to - from)
+ *
+ * @param[in] from from value
+ * @param[in] to to value
+ * @param[in] t interpolant (amount)
+ * @returns destination
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_smoothinterp(vec4s from, vec4s to, float t) {
+ vec4s r;
+ glm_vec4_smoothinterp(from.raw, to.raw, t, r.raw);
+ return r;
+}
+
+/*!
+ * @brief smooth Hermite interpolation between two vectors (clamped)
+ *
+ * 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
+ * @returns destination
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_smoothinterpc(vec4s from, vec4s to, float t) {
+ vec4s r;
+ glm_vec4_smoothinterpc(from.raw, to.raw, t, r.raw);
+ return r;
+}
+
+/*!
+ * @brief helper to fill vec4 as [S^3, S^2, S, 1]
+ *
+ * @param[in] s parameter
+ * @returns destination
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_cubic(float s) {
+ vec4s r;
+ glm_vec4_cubic(s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief swizzle vector components
+ *
+ * you can use existin masks e.g. GLM_XXXX, GLM_WZYX
+ *
+ * @param[in] v source
+ * @param[in] mask mask
+ * @returns swizzled vector
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_swizzle(vec4s v, int mask) {
+ vec4s dest;
+ glm_vec4_swizzle(v.raw, mask, dest.raw);
+ return dest;
+}
+
+#endif /* cglms_vec4s_h */
diff --git a/libs/cglm/include/cglm/types-struct.h b/libs/cglm/include/cglm/types-struct.h
new file mode 100644
index 0000000..1d91097
--- /dev/null
+++ b/libs/cglm/include/cglm/types-struct.h
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_types_struct_h
+#define cglm_types_struct_h
+
+#include "types.h"
+
+/*
+ * Anonymous structs are available since C11, but we'd like to be compatible
+ * with C99 and C89 too. So let's figure out if we should be using them or not.
+ * It's simply a convenience feature, you can e.g. build the library with
+ * anonymous structs and your application without them and they'll still be
+ * compatible, cglm doesn't use the anonymous structs internally.
+ */
+#ifndef CGLM_USE_ANONYMOUS_STRUCT
+ /* If the user doesn't explicitly specify if they want anonymous structs or
+ * not, then we'll try to intuit an appropriate choice. */
+# if defined(CGLM_NO_ANONYMOUS_STRUCT)
+ /* The user has defined CGLM_NO_ANONYMOUS_STRUCT. This used to be the
+ * only #define governing the use of anonymous structs, so for backward
+ * compatibility, we still honor that choice and disable them. */
+# define CGLM_USE_ANONYMOUS_STRUCT 0
+# elif __STDC_VERSION__ >= 20112L || defined(_MSVC_VER)
+ /* We're compiling for C11 or this is the MSVC compiler. In either
+ * case, anonymous structs are available, so use them. */
+# define CGLM_USE_ANONYMOUS_STRUCT 1
+# elif defined(_MSC_VER) && (_MSC_VER >= 1900) /* Visual Studio 2015 */
+ /* We can support anonymous structs
+ * since Visual Studio 2015 or 2017 (1910) maybe? */
+# define CGLM_USE_ANONYMOUS_STRUCT 1
+# else
+ /* Otherwise, we're presumably building for C99 or C89 and can't rely
+ * on anonymous structs being available. Turn them off. */
+# define CGLM_USE_ANONYMOUS_STRUCT 0
+# endif
+#endif
+
+typedef union vec2s {
+ vec2 raw;
+#if CGLM_USE_ANONYMOUS_STRUCT
+ struct {
+ float x;
+ float y;
+ };
+
+ struct {
+ float r;
+ float i;
+ };
+
+ struct {
+ float u;
+ float v;
+ };
+
+ struct {
+ float s;
+ float t;
+ };
+#endif
+} vec2s;
+
+typedef union vec3s {
+ vec3 raw;
+#if CGLM_USE_ANONYMOUS_STRUCT
+ struct {
+ float x;
+ float y;
+ float z;
+ };
+
+ struct {
+ float r;
+ float g;
+ float b;
+ };
+#endif
+} vec3s;
+
+typedef union ivec2s {
+ ivec2 raw;
+#if CGLM_USE_ANONYMOUS_STRUCT
+ struct {
+ int x;
+ int y;
+ };
+
+ struct {
+ int r;
+ int i;
+ };
+
+ struct {
+ int u;
+ int v;
+ };
+
+ struct {
+ int s;
+ int t;
+ };
+#endif
+} ivec2s;
+
+typedef union ivec3s {
+ ivec3 raw;
+#if CGLM_USE_ANONYMOUS_STRUCT
+ struct {
+ int x;
+ int y;
+ int z;
+ };
+
+ struct {
+ int r;
+ int g;
+ int b;
+ };
+#endif
+} ivec3s;
+
+typedef union ivec4s {
+ ivec4 raw;
+#if CGLM_USE_ANONYMOUS_STRUCT
+ struct {
+ int x;
+ int y;
+ int z;
+ int w;
+ };
+
+ struct {
+ int r;
+ int g;
+ int b;
+ int a;
+ };
+#endif
+} ivec4s;
+
+typedef union CGLM_ALIGN_IF(16) vec4s {
+ vec4 raw;
+#if CGLM_USE_ANONYMOUS_STRUCT
+ struct {
+ float x;
+ float y;
+ float z;
+ float w;
+ };
+
+ struct {
+ float r;
+ float g;
+ float b;
+ float a;
+ };
+#endif
+} vec4s;
+
+typedef union CGLM_ALIGN_IF(16) versors {
+ vec4 raw;
+#if CGLM_USE_ANONYMOUS_STRUCT
+ struct {
+ float x;
+ float y;
+ float z;
+ float w;
+ };
+
+ struct {
+ vec3s imag;
+ float real;
+ };
+#endif
+} versors;
+
+typedef union mat2s {
+ mat2 raw;
+ vec2s col[2];
+#if CGLM_USE_ANONYMOUS_STRUCT
+ struct {
+ float m00, m01;
+ float m10, m11;
+ };
+#endif
+} mat2s;
+
+typedef union mat3s {
+ mat3 raw;
+ vec3s col[3];
+#if CGLM_USE_ANONYMOUS_STRUCT
+ struct {
+ float m00, m01, m02;
+ float m10, m11, m12;
+ float m20, m21, m22;
+ };
+#endif
+} mat3s;
+
+typedef union CGLM_ALIGN_MAT mat4s {
+ mat4 raw;
+ vec4s col[4];
+#if CGLM_USE_ANONYMOUS_STRUCT
+ struct {
+ float m00, m01, m02, m03;
+ float m10, m11, m12, m13;
+ float m20, m21, m22, m23;
+ float m30, m31, m32, m33;
+ };
+#endif
+} mat4s;
+
+#endif /* cglm_types_struct_h */
diff --git a/libs/cglm/include/cglm/types.h b/libs/cglm/include/cglm/types.h
new file mode 100644
index 0000000..a671c5a
--- /dev/null
+++ b/libs/cglm/include/cglm/types.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_types_h
+#define cglm_types_h
+
+#if defined(_MSC_VER)
+/* 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
+# define CGLM_ALIGN(X) __attribute((aligned(X)))
+#endif
+
+#ifndef CGLM_ALL_UNALIGNED
+# define CGLM_ALIGN_IF(X) CGLM_ALIGN(X)
+#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
+
+#ifdef __GNUC__
+# define CGLM_ASSUME_ALIGNED(expr, alignment) \
+ __builtin_assume_aligned((expr), (alignment))
+#else
+# define CGLM_ASSUME_ALIGNED(expr, alignment) (expr)
+#endif
+
+#define CGLM_CASTPTR_ASSUME_ALIGNED(expr, type) \
+ ((type*)CGLM_ASSUME_ALIGNED((expr), __alignof__(type)))
+
+typedef int ivec2[2];
+typedef int ivec3[3];
+typedef int ivec4[4];
+
+typedef float vec2[2];
+typedef float vec3[3];
+typedef CGLM_ALIGN_IF(16) float vec4[4];
+typedef vec4 versor; /* |x, y, z, w| -> w is the last */
+typedef vec3 mat3[3];
+typedef CGLM_ALIGN_IF(16) vec2 mat2[2];
+typedef CGLM_ALIGN_MAT vec4 mat4[4];
+
+/*
+ Important: cglm stores quaternion as [x, y, z, w] in memory since v0.4.0
+ it was [w, x, y, z] before v0.4.0 ( v0.3.5 and earlier ). w is real part.
+*/
+
+#define GLM_E 2.71828182845904523536028747135266250 /* e */
+#define GLM_LOG2E 1.44269504088896340735992468100189214 /* log2(e) */
+#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 */
diff --git a/libs/cglm/include/cglm/util.h b/libs/cglm/include/cglm/util.h
new file mode 100644
index 0000000..53b1ed5
--- /dev/null
+++ b/libs/cglm/include/cglm/util.h
@@ -0,0 +1,343 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE int glm_sign(int val);
+ CGLM_INLINE float glm_signf(float val);
+ CGLM_INLINE float glm_rad(float deg);
+ CGLM_INLINE float glm_deg(float rad);
+ CGLM_INLINE void glm_make_rad(float *deg);
+ CGLM_INLINE void glm_make_deg(float *rad);
+ CGLM_INLINE float glm_pow2(float x);
+ CGLM_INLINE float glm_min(float a, float b);
+ CGLM_INLINE float glm_max(float a, float b);
+ CGLM_INLINE float glm_clamp(float val, float minVal, float maxVal);
+ CGLM_INLINE float glm_clamp_zo(float val, float minVal, float maxVal);
+ CGLM_INLINE float glm_lerp(float from, float to, float t);
+ CGLM_INLINE float glm_lerpc(float from, float to, float t);
+ CGLM_INLINE float glm_step(float edge, float x);
+ CGLM_INLINE float glm_smooth(float t);
+ CGLM_INLINE float glm_smoothstep(float edge0, float edge1, float x);
+ CGLM_INLINE float glm_smoothinterp(float from, float to, float t);
+ CGLM_INLINE float glm_smoothinterpc(float from, float to, float t);
+ CGLM_INLINE bool glm_eq(float a, float b);
+ CGLM_INLINE float glm_percent(float from, float to, float current);
+ CGLM_INLINE float glm_percentc(float from, float to, float current);
+ */
+
+#ifndef cglm_util_h
+#define cglm_util_h
+
+#include "common.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, -1, 0
+ *
+ * Important: It returns 0 for zero input
+ *
+ * @param val integer value
+ */
+CGLM_INLINE
+int
+glm_sign(int val) {
+ 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
+ *
+ * @param[in] deg angle in degrees
+ */
+CGLM_INLINE
+float
+glm_rad(float deg) {
+ return deg * GLM_PIf / 180.0f;
+}
+
+/*!
+ * @brief convert radians to degree
+ *
+ * @param[in] rad angle in radians
+ */
+CGLM_INLINE
+float
+glm_deg(float rad) {
+ return rad * 180.0f / GLM_PIf;
+}
+
+/*!
+ * @brief convert exsisting degree to radians. this will override degrees value
+ *
+ * @param[in, out] deg pointer to angle in degrees
+ */
+CGLM_INLINE
+void
+glm_make_rad(float *deg) {
+ *deg = *deg * GLM_PIf / 180.0f;
+}
+
+/*!
+ * @brief convert exsisting radians to degree. this will override radians value
+ *
+ * @param[in, out] rad pointer to angle in radians
+ */
+CGLM_INLINE
+void
+glm_make_deg(float *rad) {
+ *rad = *rad * 180.0f / GLM_PIf;
+}
+
+/*!
+ * @brief multiplies given parameter with itself = x * x or powf(x, 2)
+ *
+ * @param[in] x x
+ */
+CGLM_INLINE
+float
+glm_pow2(float x) {
+ return x * x;
+}
+
+/*!
+ * @brief find minimum of given two values
+ *
+ * @param[in] a number 1
+ * @param[in] b number 2
+ */
+CGLM_INLINE
+float
+glm_min(float a, float b) {
+ if (a < b)
+ return a;
+ return b;
+}
+
+/*!
+ * @brief find maximum of given two values
+ *
+ * @param[in] a number 1
+ * @param[in] b number 2
+ */
+CGLM_INLINE
+float
+glm_max(float a, float b) {
+ if (a > b)
+ return a;
+ 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 numbers
+ *
+ * formula: from + t * (to - from)
+ *
+ * @param[in] from from value
+ * @param[in] to to value
+ * @param[in] t interpolant (amount)
+ */
+CGLM_INLINE
+float
+glm_lerp(float from, float to, float t) {
+ return from + t * (to - from);
+}
+
+/*!
+ * @brief clamped linear interpolation between two numbers
+ *
+ * formula: from + t * (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_lerpc(float from, float to, float t) {
+ return glm_lerp(from, to, glm_clamp_zo(t));
+}
+
+/*!
+ * @brief threshold function
+ *
+ * @param[in] edge threshold
+ * @param[in] x value to test against threshold
+ * @return returns 0.0 if x < edge, else 1.0
+ */
+CGLM_INLINE
+float
+glm_step(float edge, float x) {
+ /* branching - no type conversion */
+ return (x < edge) ? 0.0f : 1.0f;
+ /*
+ * An alternative implementation without branching
+ * but with type conversion could be:
+ * return !(x < edge);
+ */
+}
+
+/*!
+ * @brief smooth Hermite interpolation
+ *
+ * formula: t^2 * (3-2t)
+ *
+ * @param[in] t interpolant (amount)
+ */
+CGLM_INLINE
+float
+glm_smooth(float t) {
+ return t * t * (3.0f - 2.0f * t);
+}
+
+/*!
+ * @brief threshold function with a smooth transition (according to OpenCL specs)
+ *
+ * formula: t^2 * (3-2t)
+ *
+ * @param[in] edge0 low threshold
+ * @param[in] edge1 high threshold
+ * @param[in] x interpolant (amount)
+ */
+CGLM_INLINE
+float
+glm_smoothstep(float edge0, float edge1, float x) {
+ float t;
+ t = glm_clamp_zo((x - edge0) / (edge1 - edge0));
+ return glm_smooth(t);
+}
+
+/*!
+ * @brief smoothstep interpolation between two numbers
+ *
+ * formula: from + smoothstep(t) * (to - from)
+ *
+ * @param[in] from from value
+ * @param[in] to to value
+ * @param[in] t interpolant (amount)
+ */
+CGLM_INLINE
+float
+glm_smoothinterp(float from, float to, float t) {
+ return from + glm_smooth(t) * (to - from);
+}
+
+/*!
+ * @brief clamped smoothstep interpolation between two numbers
+ *
+ * formula: from + smoothstep(t) * (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_smoothinterpc(float from, float to, float t) {
+ return glm_smoothinterp(from, to, glm_clamp_zo(t));
+}
+
+/*!
+ * @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) <= GLM_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_zo(glm_percent(from, to, current));
+}
+
+/*!
+* @brief swap two float values
+*
+* @param[in] a float value 1 (pointer)
+* @param[in] b float value 2 (pointer)
+*/
+CGLM_INLINE
+void
+glm_swapf(float * __restrict a, float * __restrict b) {
+ float t;
+ t = *a;
+ *a = *b;
+ *b = t;
+}
+
+#endif /* cglm_util_h */
diff --git a/libs/cglm/include/cglm/vec2-ext.h b/libs/cglm/include/cglm/vec2-ext.h
new file mode 100644
index 0000000..388c5e2
--- /dev/null
+++ b/libs/cglm/include/cglm/vec2-ext.h
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glm_vec2_fill(vec2 v, float val)
+ CGLM_INLINE bool glm_vec2_eq(vec2 v, float val);
+ CGLM_INLINE bool glm_vec2_eq_eps(vec2 v, float val);
+ CGLM_INLINE bool glm_vec2_eq_all(vec2 v);
+ CGLM_INLINE bool glm_vec2_eqv(vec2 a, vec2 b);
+ CGLM_INLINE bool glm_vec2_eqv_eps(vec2 a, vec2 b);
+ CGLM_INLINE float glm_vec2_max(vec2 v);
+ CGLM_INLINE float glm_vec2_min(vec2 v);
+ CGLM_INLINE bool glm_vec2_isnan(vec2 v);
+ CGLM_INLINE bool glm_vec2_isinf(vec2 v);
+ CGLM_INLINE bool glm_vec2_isvalid(vec2 v);
+ CGLM_INLINE void glm_vec2_sign(vec2 v, vec2 dest);
+ CGLM_INLINE void glm_vec2_sqrt(vec2 v, vec2 dest);
+ CGLM_INLINE void glm_vec2_complex_mul(vec2 a, vec2 b, vec2 dest)
+ CGLM_INLINE void glm_vec2_complex_div(vec2 a, vec2 b, vec2 dest)
+ CGLM_INLINE void glm_vec2_complex_conjugate(vec2 a, vec2 dest)
+ */
+
+#ifndef cglm_vec2_ext_h
+#define cglm_vec2_ext_h
+
+#include "common.h"
+#include "util.h"
+
+/*!
+ * @brief fill a vector with specified value
+ *
+ * @param[out] v dest
+ * @param[in] val value
+ */
+CGLM_INLINE
+void
+glm_vec2_fill(vec2 v, float val) {
+ v[0] = v[1] = val;
+}
+
+/*!
+ * @brief check if vector is equal to value (without epsilon)
+ *
+ * @param[in] v vector
+ * @param[in] val value
+ */
+CGLM_INLINE
+bool
+glm_vec2_eq(vec2 v, float val) {
+ return v[0] == val && v[0] == v[1];
+}
+
+/*!
+ * @brief check if vector is equal to value (with epsilon)
+ *
+ * @param[in] v vector
+ * @param[in] val value
+ */
+CGLM_INLINE
+bool
+glm_vec2_eq_eps(vec2 v, float val) {
+ return fabsf(v[0] - val) <= GLM_FLT_EPSILON
+ && fabsf(v[1] - val) <= GLM_FLT_EPSILON;
+}
+
+/*!
+ * @brief check if vectors members are equal (without epsilon)
+ *
+ * @param[in] v vector
+ */
+CGLM_INLINE
+bool
+glm_vec2_eq_all(vec2 v) {
+ return glm_vec2_eq_eps(v, v[0]);
+}
+
+/*!
+ * @brief check if vector is equal to another (without epsilon)
+ *
+ * @param[in] a vector
+ * @param[in] b vector
+ */
+CGLM_INLINE
+bool
+glm_vec2_eqv(vec2 a, vec2 b) {
+ return a[0] == b[0] && a[1] == b[1];
+}
+
+/*!
+ * @brief check if vector is equal to another (with epsilon)
+ *
+ * @param[in] a vector
+ * @param[in] b vector
+ */
+CGLM_INLINE
+bool
+glm_vec2_eqv_eps(vec2 a, vec2 b) {
+ return fabsf(a[0] - b[0]) <= GLM_FLT_EPSILON
+ && fabsf(a[1] - b[1]) <= GLM_FLT_EPSILON;
+}
+
+/*!
+ * @brief max value of vector
+ *
+ * @param[in] v vector
+ */
+CGLM_INLINE
+float
+glm_vec2_max(vec2 v) {
+ return glm_max(v[0], v[1]);
+}
+
+/*!
+ * @brief min value of vector
+ *
+ * @param[in] v vector
+ */
+CGLM_INLINE
+float
+glm_vec2_min(vec2 v) {
+ return glm_min(v[0], v[1]);
+}
+
+/*!
+ * @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_vec2_isnan(vec2 v) {
+ return isnan(v[0]) || isnan(v[1]);
+}
+
+/*!
+ * @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_vec2_isinf(vec2 v) {
+ return isinf(v[0]) || isinf(v[1]);
+}
+
+/*!
+ * @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_vec2_isvalid(vec2 v) {
+ return !glm_vec2_isnan(v) && !glm_vec2_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_vec2_sign(vec2 v, vec2 dest) {
+ dest[0] = glm_signf(v[0]);
+ dest[1] = glm_signf(v[1]);
+}
+
+/*!
+ * @brief square root of each vector item
+ *
+ * @param[in] v vector
+ * @param[out] dest destination vector
+ */
+CGLM_INLINE
+void
+glm_vec2_sqrt(vec2 v, vec2 dest) {
+ dest[0] = sqrtf(v[0]);
+ dest[1] = sqrtf(v[1]);
+}
+
+/*!
+ * @brief treat vectors as complex numbers and multiply them as such.
+ *
+ * @param[in] a left number
+ * @param[in] b right number
+ * @param[out] dest destination number
+ */
+CGLM_INLINE
+void
+glm_vec2_complex_mul(vec2 a, vec2 b, vec2 dest) {
+ float tr, ti;
+ tr = a[0] * b[0] - a[1] * b[1];
+ ti = a[0] * b[1] + a[1] * b[0];
+ dest[0] = tr;
+ dest[1] = ti;
+}
+
+/*!
+ * @brief treat vectors as complex numbers and divide them as such.
+ *
+ * @param[in] a left number (numerator)
+ * @param[in] b right number (denominator)
+ * @param[out] dest destination number
+ */
+CGLM_INLINE
+void
+glm_vec2_complex_div(vec2 a, vec2 b, vec2 dest) {
+ float tr, ti;
+ float const ibnorm2 = 1.0f / (b[0] * b[0] + b[1] * b[1]);
+ tr = ibnorm2 * (a[0] * b[0] + a[1] * b[1]);
+ ti = ibnorm2 * (a[1] * b[0] - a[0] * b[1]);
+ dest[0] = tr;
+ dest[1] = ti;
+}
+
+/*!
+ * @brief treat the vector as a complex number and conjugate it as such.
+ *
+ * @param[in] a the number
+ * @param[out] dest destination number
+ */
+CGLM_INLINE
+void
+glm_vec2_complex_conjugate(vec2 a, vec2 dest) {
+ dest[0] = a[0];
+ dest[1] = -a[1];
+}
+
+
+#endif /* cglm_vec2_ext_h */
diff --git a/libs/cglm/include/cglm/vec2.h b/libs/cglm/include/cglm/vec2.h
new file mode 100644
index 0000000..73ecea9
--- /dev/null
+++ b/libs/cglm/include/cglm/vec2.h
@@ -0,0 +1,585 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Macros:
+ GLM_VEC2_ONE_INIT
+ GLM_VEC2_ZERO_INIT
+ GLM_VEC2_ONE
+ GLM_VEC2_ZERO
+
+ Functions:
+ CGLM_INLINE void glm_vec2(float * __restrict v, vec2 dest)
+ CGLM_INLINE void glm_vec2_copy(vec2 a, vec2 dest)
+ CGLM_INLINE void glm_vec2_zero(vec2 v)
+ CGLM_INLINE void glm_vec2_one(vec2 v)
+ CGLM_INLINE float glm_vec2_dot(vec2 a, vec2 b)
+ CGLM_INLINE float glm_vec2_cross(vec2 a, vec2 b)
+ CGLM_INLINE float glm_vec2_norm2(vec2 v)
+ CGLM_INLINE float glm_vec2_norm(vec2 vec)
+ CGLM_INLINE void glm_vec2_add(vec2 a, vec2 b, vec2 dest)
+ CGLM_INLINE void glm_vec2_adds(vec2 v, float s, vec2 dest)
+ CGLM_INLINE void glm_vec2_sub(vec2 a, vec2 b, vec2 dest)
+ CGLM_INLINE void glm_vec2_subs(vec2 v, float s, vec2 dest)
+ CGLM_INLINE void glm_vec2_mul(vec2 a, vec2 b, vec2 d)
+ CGLM_INLINE void glm_vec2_scale(vec2 v, float s, vec2 dest)
+ CGLM_INLINE void glm_vec2_scale_as(vec2 v, float s, vec2 dest)
+ CGLM_INLINE void glm_vec2_div(vec2 a, vec2 b, vec2 dest)
+ CGLM_INLINE void glm_vec2_divs(vec2 v, float s, vec2 dest)
+ CGLM_INLINE void glm_vec2_addadd(vec2 a, vec2 b, vec2 dest)
+ CGLM_INLINE void glm_vec2_subadd(vec2 a, vec2 b, vec2 dest)
+ CGLM_INLINE void glm_vec2_muladd(vec2 a, vec2 b, vec2 dest)
+ CGLM_INLINE void glm_vec2_muladds(vec2 a, float s, vec2 dest)
+ CGLM_INLINE void glm_vec2_maxadd(vec2 a, vec2 b, vec2 dest)
+ CGLM_INLINE void glm_vec2_minadd(vec2 a, vec2 b, vec2 dest)
+ CGLM_INLINE void glm_vec2_negate_to(vec2 v, vec2 dest)
+ CGLM_INLINE void glm_vec2_negate(vec2 v)
+ CGLM_INLINE void glm_vec2_normalize(vec2 v)
+ CGLM_INLINE void glm_vec2_normalize_to(vec2 vec, vec2 dest)
+ CGLM_INLINE void glm_vec2_rotate(vec2 v, float angle, vec2 dest)
+ CGLM_INLINE float glm_vec2_distance2(vec2 a, vec2 b)
+ CGLM_INLINE float glm_vec2_distance(vec2 a, vec2 b)
+ CGLM_INLINE void glm_vec2_maxv(vec2 v1, vec2 v2, vec2 dest)
+ CGLM_INLINE void glm_vec2_minv(vec2 v1, vec2 v2, vec2 dest)
+ CGLM_INLINE void glm_vec2_clamp(vec2 v, float minVal, float maxVal)
+ CGLM_INLINE void glm_vec2_lerp(vec2 from, vec2 to, float t, vec2 dest)
+
+ */
+
+#ifndef cglm_vec2_h
+#define cglm_vec2_h
+
+#include "common.h"
+#include "util.h"
+#include "vec2-ext.h"
+
+#define GLM_VEC2_ONE_INIT {1.0f, 1.0f}
+#define GLM_VEC2_ZERO_INIT {0.0f, 0.0f}
+
+#define GLM_VEC2_ONE ((vec2)GLM_VEC2_ONE_INIT)
+#define GLM_VEC2_ZERO ((vec2)GLM_VEC2_ZERO_INIT)
+
+/*!
+ * @brief init vec2 using another vector
+ *
+ * @param[in] v a vector
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec2(float * __restrict v, vec2 dest) {
+ dest[0] = v[0];
+ dest[1] = v[1];
+}
+
+/*!
+ * @brief copy all members of [a] to [dest]
+ *
+ * @param[in] a source
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec2_copy(vec2 a, vec2 dest) {
+ dest[0] = a[0];
+ dest[1] = a[1];
+}
+
+/*!
+ * @brief make vector zero
+ *
+ * @param[in, out] v vector
+ */
+CGLM_INLINE
+void
+glm_vec2_zero(vec2 v) {
+ v[0] = v[1] = 0.0f;
+}
+
+/*!
+ * @brief make vector one
+ *
+ * @param[in, out] v vector
+ */
+CGLM_INLINE
+void
+glm_vec2_one(vec2 v) {
+ v[0] = v[1] = 1.0f;
+}
+
+/*!
+ * @brief vec2 dot product
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ *
+ * @return dot product
+ */
+CGLM_INLINE
+float
+glm_vec2_dot(vec2 a, vec2 b) {
+ return a[0] * b[0] + a[1] * b[1];
+}
+
+/*!
+ * @brief vec2 cross product
+ *
+ * REF: http://allenchou.net/2013/07/cross-product-of-2d-vectors/
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ *
+ * @return Z component of cross product
+ */
+CGLM_INLINE
+float
+glm_vec2_cross(vec2 a, vec2 b) {
+ /* just calculate the z-component */
+ return a[0] * b[1] - a[1] * b[0];
+}
+
+/*!
+ * @brief norm * norm (magnitude) of vec
+ *
+ * we can use this func instead of calling norm * norm, because it would call
+ * sqrtf fuction twice but with this func we can avoid func call, maybe this is
+ * not good name for this func
+ *
+ * @param[in] v vector
+ *
+ * @return norm * norm
+ */
+CGLM_INLINE
+float
+glm_vec2_norm2(vec2 v) {
+ return glm_vec2_dot(v, v);
+}
+
+/*!
+ * @brief norm (magnitude) of vec2
+ *
+ * @param[in] vec vector
+ *
+ * @return norm
+ */
+CGLM_INLINE
+float
+glm_vec2_norm(vec2 vec) {
+ return sqrtf(glm_vec2_norm2(vec));
+}
+
+/*!
+ * @brief add a vector to b vector store result in dest
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @param[out] dest destination vector
+ */
+CGLM_INLINE
+void
+glm_vec2_add(vec2 a, vec2 b, vec2 dest) {
+ dest[0] = a[0] + b[0];
+ dest[1] = a[1] + b[1];
+}
+
+/*!
+ * @brief add scalar to 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_vec2_adds(vec2 v, float s, vec2 dest) {
+ dest[0] = v[0] + s;
+ dest[1] = v[1] + 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_vec2_sub(vec2 a, vec2 b, vec2 dest) {
+ dest[0] = a[0] - b[0];
+ dest[1] = a[1] - b[1];
+}
+
+/*!
+ * @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_vec2_subs(vec2 v, float s, vec2 dest) {
+ dest[0] = v[0] - s;
+ dest[1] = v[1] - s;
+}
+
+/*!
+ * @brief multiply two vector (component-wise multiplication)
+ *
+ * @param a v1
+ * @param b v2
+ * @param dest v3 = (a[0] * b[0], a[1] * b[1])
+ */
+CGLM_INLINE
+void
+glm_vec2_mul(vec2 a, vec2 b, vec2 dest) {
+ dest[0] = a[0] * b[0];
+ dest[1] = a[1] * b[1];
+}
+
+/*!
+ * @brief multiply/scale vector with scalar: result = v * s
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @param[out] dest destination vector
+ */
+CGLM_INLINE
+void
+glm_vec2_scale(vec2 v, float s, vec2 dest) {
+ dest[0] = v[0] * s;
+ dest[1] = v[1] * s;
+}
+
+/*!
+ * @brief scale as vector specified: result = unit(v) * s
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @param[out] dest destination vector
+ */
+CGLM_INLINE
+void
+glm_vec2_scale_as(vec2 v, float s, vec2 dest) {
+ float norm;
+ norm = glm_vec2_norm(v);
+
+ if (norm == 0.0f) {
+ glm_vec2_zero(dest);
+ return;
+ }
+
+ glm_vec2_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])
+ */
+CGLM_INLINE
+void
+glm_vec2_div(vec2 a, vec2 b, vec2 dest) {
+ dest[0] = a[0] / b[0];
+ dest[1] = a[1] / b[1];
+}
+
+/*!
+ * @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)
+ */
+CGLM_INLINE
+void
+glm_vec2_divs(vec2 v, float s, vec2 dest) {
+ dest[0] = v[0] / s;
+ dest[1] = v[1] / 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_vec2_addadd(vec2 a, vec2 b, vec2 dest) {
+ dest[0] += a[0] + b[0];
+ dest[1] += a[1] + b[1];
+}
+
+/*!
+ * @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_vec2_subadd(vec2 a, vec2 b, vec2 dest) {
+ dest[0] += a[0] - b[0];
+ dest[1] += a[1] - b[1];
+}
+
+/*!
+ * @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_vec2_muladd(vec2 a, vec2 b, vec2 dest) {
+ dest[0] += a[0] * b[0];
+ dest[1] += a[1] * b[1];
+}
+
+/*!
+ * @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_vec2_muladds(vec2 a, float s, vec2 dest) {
+ dest[0] += a[0] * s;
+ dest[1] += a[1] * 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_vec2_maxadd(vec2 a, vec2 b, vec2 dest) {
+ dest[0] += glm_max(a[0], b[0]);
+ dest[1] += glm_max(a[1], b[1]);
+}
+
+/*!
+ * @brief add min 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 += min(a, b)
+ */
+CGLM_INLINE
+void
+glm_vec2_minadd(vec2 a, vec2 b, vec2 dest) {
+ dest[0] += glm_min(a[0], b[0]);
+ dest[1] += glm_min(a[1], b[1]);
+}
+
+/*!
+ * @brief negate vector components and store result in dest
+ *
+ * @param[in] v vector
+ * @param[out] dest result vector
+ */
+CGLM_INLINE
+void
+glm_vec2_negate_to(vec2 v, vec2 dest) {
+ dest[0] = -v[0];
+ dest[1] = -v[1];
+}
+
+/*!
+ * @brief negate vector components
+ *
+ * @param[in, out] v vector
+ */
+CGLM_INLINE
+void
+glm_vec2_negate(vec2 v) {
+ glm_vec2_negate_to(v, v);
+}
+
+/*!
+ * @brief normalize vector and store result in same vec
+ *
+ * @param[in, out] v vector
+ */
+CGLM_INLINE
+void
+glm_vec2_normalize(vec2 v) {
+ float norm;
+
+ norm = glm_vec2_norm(v);
+
+ if (norm == 0.0f) {
+ v[0] = v[1] = 0.0f;
+ return;
+ }
+
+ glm_vec2_scale(v, 1.0f / norm, v);
+}
+
+/*!
+ * @brief normalize vector to dest
+ *
+ * @param[in] v source
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec2_normalize_to(vec2 v, vec2 dest) {
+ float norm;
+
+ norm = glm_vec2_norm(v);
+
+ if (norm == 0.0f) {
+ glm_vec2_zero(dest);
+ return;
+ }
+
+ glm_vec2_scale(v, 1.0f / norm, dest);
+}
+
+/*!
+ * @brief rotate vec2 around origin by angle (CCW: counterclockwise)
+ *
+ * Formula:
+ * 𝑥2 = cos(a)𝑥1 − sin(a)𝑦1
+ * 𝑦2 = sin(a)𝑥1 + cos(a)𝑦1
+ *
+ * @param[in] v vector to rotate
+ * @param[in] angle angle by radians
+ * @param[out] dest destination vector
+ */
+CGLM_INLINE
+void
+glm_vec2_rotate(vec2 v, float angle, vec2 dest) {
+ float c, s, x1, y1;
+
+ c = cosf(angle);
+ s = sinf(angle);
+
+ x1 = v[0];
+ y1 = v[1];
+
+ dest[0] = c * x1 - s * y1;
+ dest[1] = s * x1 + c * y1;
+}
+
+/**
+ * @brief squared distance between two vectors
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @return returns squared distance (distance * distance)
+ */
+CGLM_INLINE
+float
+glm_vec2_distance2(vec2 a, vec2 b) {
+ return glm_pow2(b[0] - a[0]) + glm_pow2(b[1] - a[1]);
+}
+
+/**
+ * @brief distance between two vectors
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @return returns distance
+ */
+CGLM_INLINE
+float
+glm_vec2_distance(vec2 a, vec2 b) {
+ return sqrtf(glm_vec2_distance2(a, b));
+}
+
+/*!
+ * @brief max values of vectors
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec2_maxv(vec2 a, vec2 b, vec2 dest) {
+ dest[0] = glm_max(a[0], b[0]);
+ dest[1] = glm_max(a[1], b[1]);
+}
+
+/*!
+ * @brief min values of vectors
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec2_minv(vec2 a, vec2 b, vec2 dest) {
+ dest[0] = glm_min(a[0], b[0]);
+ dest[1] = glm_min(a[1], b[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_vec2_clamp(vec2 v, float minval, float maxval) {
+ v[0] = glm_clamp(v[0], minval, maxval);
+ v[1] = glm_clamp(v[1], 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_vec2_lerp(vec2 from, vec2 to, float t, vec2 dest) {
+ vec2 s, v;
+
+ /* from + s * (to - from) */
+ glm_vec2_fill(s, glm_clamp_zo(t));
+ glm_vec2_sub(to, from, v);
+ glm_vec2_mul(s, v, v);
+ glm_vec2_add(from, v, dest);
+}
+
+#endif /* cglm_vec2_h */
diff --git a/libs/cglm/include/cglm/vec3-ext.h b/libs/cglm/include/cglm/vec3-ext.h
new file mode 100644
index 0000000..802f4cb
--- /dev/null
+++ b/libs/cglm/include/cglm/vec3-ext.h
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*!
+ * @brief SIMD like functions
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glm_vec3_broadcast(float val, vec3 d);
+ CGLM_INLINE void glm_vec3_fill(vec3 v, float val);
+ CGLM_INLINE bool glm_vec3_eq(vec3 v, float val);
+ CGLM_INLINE bool glm_vec3_eq_eps(vec3 v, float val);
+ CGLM_INLINE bool glm_vec3_eq_all(vec3 v);
+ CGLM_INLINE bool glm_vec3_eqv(vec3 a, vec3 b);
+ CGLM_INLINE bool glm_vec3_eqv_eps(vec3 a, vec3 b);
+ CGLM_INLINE float glm_vec3_max(vec3 v);
+ CGLM_INLINE float glm_vec3_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_abs(vec3 v, vec3 dest);
+ CGLM_INLINE void glm_vec3_fract(vec3 v, vec3 dest);
+ CGLM_INLINE float glm_vec3_hadd(vec3 v);
+ CGLM_INLINE void glm_vec3_sqrt(vec3 v, vec3 dest);
+ */
+
+#ifndef cglm_vec3_ext_h
+#define cglm_vec3_ext_h
+
+#include "common.h"
+#include "util.h"
+
+/*!
+ * @brief fill a vector with specified value
+ *
+ * @param[in] val value
+ * @param[out] d dest
+ */
+CGLM_INLINE
+void
+glm_vec3_broadcast(float val, vec3 d) {
+ d[0] = d[1] = d[2] = val;
+}
+
+/*!
+ * @brief fill a vector with specified value
+ *
+ * @param[out] v dest
+ * @param[in] val value
+ */
+CGLM_INLINE
+void
+glm_vec3_fill(vec3 v, float val) {
+ v[0] = v[1] = v[2] = val;
+}
+
+/*!
+ * @brief check if vector is equal to value (without epsilon)
+ *
+ * @param[in] v vector
+ * @param[in] val value
+ */
+CGLM_INLINE
+bool
+glm_vec3_eq(vec3 v, float val) {
+ return v[0] == val && v[0] == v[1] && v[0] == v[2];
+}
+
+/*!
+ * @brief check if vector is equal to value (with epsilon)
+ *
+ * @param[in] v vector
+ * @param[in] val value
+ */
+CGLM_INLINE
+bool
+glm_vec3_eq_eps(vec3 v, float val) {
+ return fabsf(v[0] - val) <= GLM_FLT_EPSILON
+ && fabsf(v[1] - val) <= GLM_FLT_EPSILON
+ && fabsf(v[2] - val) <= GLM_FLT_EPSILON;
+}
+
+/*!
+ * @brief check if vectors members are equal (without epsilon)
+ *
+ * @param[in] v vector
+ */
+CGLM_INLINE
+bool
+glm_vec3_eq_all(vec3 v) {
+ return glm_vec3_eq_eps(v, v[0]);
+}
+
+/*!
+ * @brief check if vector is equal to another (without epsilon)
+ *
+ * @param[in] a vector
+ * @param[in] b vector
+ */
+CGLM_INLINE
+bool
+glm_vec3_eqv(vec3 a, vec3 b) {
+ return a[0] == b[0]
+ && a[1] == b[1]
+ && a[2] == b[2];
+}
+
+/*!
+ * @brief check if vector is equal to another (with epsilon)
+ *
+ * @param[in] a vector
+ * @param[in] b vector
+ */
+CGLM_INLINE
+bool
+glm_vec3_eqv_eps(vec3 a, vec3 b) {
+ return fabsf(a[0] - b[0]) <= GLM_FLT_EPSILON
+ && fabsf(a[1] - b[1]) <= GLM_FLT_EPSILON
+ && fabsf(a[2] - b[2]) <= GLM_FLT_EPSILON;
+}
+
+/*!
+ * @brief max value of vector
+ *
+ * @param[in] v vector
+ */
+CGLM_INLINE
+float
+glm_vec3_max(vec3 v) {
+ float max;
+
+ max = v[0];
+ if (v[1] > max)
+ max = v[1];
+ if (v[2] > max)
+ max = v[2];
+
+ return max;
+}
+
+/*!
+ * @brief min value of vector
+ *
+ * @param[in] v vector
+ */
+CGLM_INLINE
+float
+glm_vec3_min(vec3 v) {
+ float min;
+
+ min = v[0];
+ if (v[1] < min)
+ min = v[1];
+ if (v[2] < min)
+ min = v[2];
+
+ 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 absolute value of each vector item
+ *
+ * @param[in] v vector
+ * @param[out] dest destination vector
+ */
+CGLM_INLINE
+void
+glm_vec3_abs(vec3 v, vec3 dest) {
+ dest[0] = fabsf(v[0]);
+ dest[1] = fabsf(v[1]);
+ dest[2] = fabsf(v[2]);
+}
+
+/*!
+ * @brief fractional part of each vector item
+ *
+ * @param[in] v vector
+ * @param[out] dest destination vector
+ */
+CGLM_INLINE
+void
+glm_vec3_fract(vec3 v, vec3 dest) {
+ dest[0] = fminf(v[0] - floorf(v[0]), 0.999999940395355224609375f);
+ dest[1] = fminf(v[1] - floorf(v[1]), 0.999999940395355224609375f);
+ dest[2] = fminf(v[2] - floorf(v[2]), 0.999999940395355224609375f);
+}
+
+/*!
+ * @brief vector reduction by summation
+ * @warning could overflow
+ *
+ * @param[in] v vector
+ * @return sum of all vector's elements
+ */
+CGLM_INLINE
+float
+glm_vec3_hadd(vec3 v) {
+ return v[0] + v[1] + 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 */
diff --git a/libs/cglm/include/cglm/vec3.h b/libs/cglm/include/cglm/vec3.h
new file mode 100644
index 0000000..b9fff9c
--- /dev/null
+++ b/libs/cglm/include/cglm/vec3.h
@@ -0,0 +1,1082 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Macros:
+ GLM_VEC3_ONE_INIT
+ GLM_VEC3_ZERO_INIT
+ GLM_VEC3_ONE
+ GLM_VEC3_ZERO
+ GLM_YUP
+ GLM_ZUP
+ GLM_XUP
+
+ Functions:
+ CGLM_INLINE void glm_vec3(vec4 v4, vec3 dest);
+ CGLM_INLINE void glm_vec3_copy(vec3 a, vec3 dest);
+ CGLM_INLINE void glm_vec3_zero(vec3 v);
+ CGLM_INLINE void glm_vec3_one(vec3 v);
+ CGLM_INLINE float glm_vec3_dot(vec3 a, vec3 b);
+ CGLM_INLINE float glm_vec3_norm2(vec3 v);
+ CGLM_INLINE float glm_vec3_norm(vec3 v);
+ CGLM_INLINE float glm_vec3_norm_one(vec3 v);
+ CGLM_INLINE float glm_vec3_norm_inf(vec3 v);
+ CGLM_INLINE void glm_vec3_add(vec3 a, vec3 b, vec3 dest);
+ CGLM_INLINE void glm_vec3_adds(vec3 a, float s, vec3 dest);
+ CGLM_INLINE void glm_vec3_sub(vec3 a, vec3 b, vec3 dest);
+ CGLM_INLINE void glm_vec3_subs(vec3 a, float s, vec3 dest);
+ CGLM_INLINE void glm_vec3_mul(vec3 a, vec3 b, vec3 dest);
+ CGLM_INLINE void glm_vec3_scale(vec3 v, float s, vec3 dest);
+ CGLM_INLINE void glm_vec3_scale_as(vec3 v, float s, vec3 dest);
+ CGLM_INLINE void glm_vec3_div(vec3 a, vec3 b, vec3 dest);
+ CGLM_INLINE void glm_vec3_divs(vec3 a, float s, vec3 dest);
+ CGLM_INLINE void glm_vec3_addadd(vec3 a, vec3 b, vec3 dest);
+ CGLM_INLINE void glm_vec3_subadd(vec3 a, vec3 b, vec3 dest);
+ CGLM_INLINE void glm_vec3_muladd(vec3 a, vec3 b, vec3 dest);
+ CGLM_INLINE void glm_vec3_muladds(vec3 a, float s, vec3 dest);
+ CGLM_INLINE void glm_vec3_maxadd(vec3 a, vec3 b, vec3 dest);
+ CGLM_INLINE void glm_vec3_minadd(vec3 a, vec3 b, 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 void glm_vec3_cross(vec3 a, vec3 b, vec3 d);
+ CGLM_INLINE void glm_vec3_crossn(vec3 a, vec3 b, vec3 dest);
+ 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_distance(vec3 a, vec3 b);
+ 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);
+ CGLM_INLINE void glm_vec3_lerpc(vec3 from, vec3 to, float t, vec3 dest);
+ CGLM_INLINE void glm_vec3_mix(vec3 from, vec3 to, float t, vec3 dest);
+ CGLM_INLINE void glm_vec3_mixc(vec3 from, vec3 to, float t, vec3 dest);
+ CGLM_INLINE void glm_vec3_step_uni(float edge, vec3 x, vec3 dest);
+ CGLM_INLINE void glm_vec3_step(vec3 edge, vec3 x, vec3 dest);
+ CGLM_INLINE void glm_vec3_smoothstep_uni(float edge0, float edge1, vec3 x, vec3 dest);
+ CGLM_INLINE void glm_vec3_smoothstep(vec3 edge0, vec3 edge1, vec3 x, vec3 dest);
+ CGLM_INLINE void glm_vec3_smoothinterp(vec3 from, vec3 to, float t, vec3 dest);
+ CGLM_INLINE void glm_vec3_smoothinterpc(vec3 from, vec3 to, float t, vec3 dest);
+ CGLM_INLINE void glm_vec3_swizzle(vec3 v, int mask, vec3 dest);
+
+ Convenient:
+ CGLM_INLINE void glm_cross(vec3 a, vec3 b, vec3 d);
+ CGLM_INLINE float glm_dot(vec3 a, vec3 b);
+ CGLM_INLINE void glm_normalize(vec3 v);
+ 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
+#define cglm_vec3_h
+
+#include "common.h"
+#include "vec4.h"
+#include "vec3-ext.h"
+#include "util.h"
+
+/* DEPRECATED! use _copy, _ucopy versions */
+#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_ZERO_INIT {0.0f, 0.0f, 0.0f}
+
+#define GLM_VEC3_ONE ((vec3)GLM_VEC3_ONE_INIT)
+#define GLM_VEC3_ZERO ((vec3)GLM_VEC3_ZERO_INIT)
+
+#define GLM_YUP ((vec3){0.0f, 1.0f, 0.0f})
+#define GLM_ZUP ((vec3){0.0f, 0.0f, 1.0f})
+#define GLM_XUP ((vec3){1.0f, 0.0f, 0.0f})
+#define GLM_FORWARD ((vec3){0.0f, 0.0f, -1.0f})
+
+#define GLM_XXX GLM_SHUFFLE3(0, 0, 0)
+#define GLM_YYY GLM_SHUFFLE3(1, 1, 1)
+#define GLM_ZZZ GLM_SHUFFLE3(2, 2, 2)
+#define GLM_ZYX GLM_SHUFFLE3(0, 1, 2)
+
+/*!
+ * @brief init vec3 using vec4
+ *
+ * @param[in] v4 vector4
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec3(vec4 v4, vec3 dest) {
+ dest[0] = v4[0];
+ dest[1] = v4[1];
+ dest[2] = v4[2];
+}
+
+/*!
+ * @brief copy all members of [a] to [dest]
+ *
+ * @param[in] a source
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec3_copy(vec3 a, vec3 dest) {
+ dest[0] = a[0];
+ dest[1] = a[1];
+ 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
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ *
+ * @return dot product
+ */
+CGLM_INLINE
+float
+glm_vec3_dot(vec3 a, vec3 b) {
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+}
+
+/*!
+ * @brief norm * norm (magnitude) of vec
+ *
+ * we can use this func instead of calling norm * norm, because it would call
+ * sqrtf fuction twice but with this func we can avoid func call, maybe this is
+ * not good name for this func
+ *
+ * @param[in] v vector
+ *
+ * @return norm * norm
+ */
+CGLM_INLINE
+float
+glm_vec3_norm2(vec3 v) {
+ return glm_vec3_dot(v, v);
+}
+
+/*!
+ * @brief euclidean norm (magnitude), also called L2 norm
+ * this will give magnitude of vector in euclidean space
+ *
+ * @param[in] v vector
+ *
+ * @return norm
+ */
+CGLM_INLINE
+float
+glm_vec3_norm(vec3 v) {
+ return sqrtf(glm_vec3_norm2(v));
+}
+
+/*!
+ * @brief L1 norm of vec3
+ * Also known as Manhattan Distance or Taxicab norm.
+ * L1 Norm is the sum of the magnitudes of the vectors in a space.
+ * It is calculated as the sum of the absolute values of the vector components.
+ * In this norm, all the components of the vector are weighted equally.
+ *
+ * This computes:
+ * R = |v[0]| + |v[1]| + |v[2]|
+ *
+ * @param[in] v vector
+ *
+ * @return L1 norm
+ */
+CGLM_INLINE
+float
+glm_vec3_norm_one(vec3 v) {
+ vec3 t;
+ glm_vec3_abs(v, t);
+ return glm_vec3_hadd(t);
+}
+
+/*!
+ * @brief infinity norm of vec3
+ * Also known as Maximum norm.
+ * Infinity Norm is the largest magnitude among each element of a vector.
+ * It is calculated as the maximum of the absolute values of the vector components.
+ *
+ * This computes:
+ * inf norm = max(|v[0]|, |v[1]|, |v[2]|)
+ *
+ * @param[in] v vector
+ *
+ * @return infinity norm
+ */
+CGLM_INLINE
+float
+glm_vec3_norm_inf(vec3 v) {
+ vec3 t;
+ glm_vec3_abs(v, t);
+ return glm_vec3_max(t);
+}
+
+/*!
+ * @brief add a vector to b vector store result in dest
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @param[out] dest destination vector
+ */
+CGLM_INLINE
+void
+glm_vec3_add(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 add scalar to 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_adds(vec3 v, float s, vec3 dest) {
+ dest[0] = v[0] + s;
+ dest[1] = v[1] + s;
+ 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];
+}
+
+/*!
+ * @brief multiply/scale vec3 vector with scalar: result = v * s
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @param[out] dest destination vector
+ */
+CGLM_INLINE
+void
+glm_vec3_scale(vec3 v, float s, vec3 dest) {
+ dest[0] = v[0] * s;
+ dest[1] = v[1] * s;
+ dest[2] = v[2] * s;
+}
+
+/*!
+ * @brief make vec3 vector scale as specified: result = unit(v) * s
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @param[out] dest destination vector
+ */
+CGLM_INLINE
+void
+glm_vec3_scale_as(vec3 v, float s, vec3 dest) {
+ float norm;
+ norm = glm_vec3_norm(v);
+
+ if (norm == 0.0f) {
+ glm_vec3_zero(dest);
+ return;
+ }
+
+ glm_vec3_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])
+ */
+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 1
+ * @param[in] b vector 2
+ * @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
+ */
+CGLM_INLINE
+void
+glm_vec3_negate(vec3 v) {
+ glm_vec3_negate_to(v, v);
+}
+
+/*!
+ * @brief normalize vec3 and store result in same vec
+ *
+ * @param[in, out] v vector
+ */
+CGLM_INLINE
+void
+glm_vec3_normalize(vec3 v) {
+ float norm;
+
+ norm = glm_vec3_norm(v);
+
+ if (norm == 0.0f) {
+ v[0] = v[1] = v[2] = 0.0f;
+ return;
+ }
+
+ glm_vec3_scale(v, 1.0f / norm, v);
+}
+
+/*!
+ * @brief normalize vec3 to dest
+ *
+ * @param[in] v source
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec3_normalize_to(vec3 v, vec3 dest) {
+ float norm;
+
+ norm = glm_vec3_norm(v);
+
+ if (norm == 0.0f) {
+ glm_vec3_zero(dest);
+ return;
+ }
+
+ glm_vec3_scale(v, 1.0f / norm, dest);
+}
+
+/*!
+ * @brief cross product of two vector (RH)
+ *
+ * @param[in] a vector 1
+ * @param[in] b vector 2
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec3_cross(vec3 a, vec3 b, vec3 dest) {
+ vec3 c;
+ /* (u2.v3 - u3.v2, u3.v1 - u1.v3, u1.v2 - u2.v1) */
+ c[0] = a[1] * b[2] - a[2] * b[1];
+ c[1] = a[2] * b[0] - a[0] * b[2];
+ c[2] = a[0] * b[1] - a[1] * b[0];
+ glm_vec3_copy(c, dest);
+}
+
+/*!
+ * @brief cross product of two vector (RH) and normalize the result
+ *
+ * @param[in] a vector 1
+ * @param[in] b vector 2
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec3_crossn(vec3 a, vec3 b, vec3 dest) {
+ glm_vec3_cross(a, b, dest);
+ glm_vec3_normalize(dest);
+}
+
+/*!
+ * @brief angle betwen two vector
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ *
+ * @return angle as radians
+ */
+CGLM_INLINE
+float
+glm_vec3_angle(vec3 a, vec3 b) {
+ float norm, dot;
+
+ /* maybe compiler generate approximation instruction (rcp) */
+ norm = 1.0f / (glm_vec3_norm(a) * glm_vec3_norm(b));
+ dot = glm_vec3_dot(a, b) * norm;
+
+ if (dot > 1.0f)
+ return 0.0f;
+ else if (dot < -1.0f)
+ return CGLM_PI;
+
+ return acosf(dot);
+}
+
+/*!
+ * @brief rotate vec3 around axis by angle using Rodrigues' rotation formula
+ *
+ * @param[in, out] v vector
+ * @param[in] axis axis vector (must be unit vector)
+ * @param[in] angle angle by radians
+ */
+CGLM_INLINE
+void
+glm_vec3_rotate(vec3 v, float angle, vec3 axis) {
+ vec3 v1, v2, k;
+ float c, s;
+
+ c = cosf(angle);
+ s = sinf(angle);
+
+ glm_vec3_normalize_to(axis, k);
+
+ /* Right Hand, Rodrigues' rotation formula:
+ v = v*cos(t) + (kxv)sin(t) + k*(k.v)(1 - cos(t))
+ */
+ glm_vec3_scale(v, c, v1);
+
+ glm_vec3_cross(k, v, v2);
+ glm_vec3_scale(v2, s, v2);
+
+ glm_vec3_add(v1, v2, v1);
+
+ glm_vec3_scale(k, glm_vec3_dot(k, v) * (1.0f - c), v2);
+ glm_vec3_add(v1, v2, v);
+}
+
+/*!
+ * @brief apply rotation matrix to vector
+ *
+ * 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_vec4_normalize_to(m[0], x);
+ 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);
+}
+
+/*!
+ * @brief apply rotation matrix to vector
+ *
+ * @param[in] m affine matrix or rot matrix
+ * @param[in] v vector
+ * @param[out] dest rotated vector
+ */
+CGLM_INLINE
+void
+glm_vec3_rotate_m3(mat3 m, vec3 v, vec3 dest) {
+ vec4 res, x, y, z;
+
+ glm_vec4(m[0], 0.0f, x);
+ glm_vec4(m[1], 0.0f, y);
+ glm_vec4(m[2], 0.0f, z);
+
+ glm_vec4_normalize(x);
+ glm_vec4_normalize(y);
+ glm_vec4_normalize(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);
+}
+
+/*!
+ * @brief project a vector onto b vector
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @param[out] dest projected vector
+ */
+CGLM_INLINE
+void
+glm_vec3_proj(vec3 a, vec3 b, vec3 dest) {
+ glm_vec3_scale(b,
+ glm_vec3_dot(a, b) / glm_vec3_norm2(b),
+ dest);
+}
+
+/**
+ * @brief find center point of two vector
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @param[out] dest center point
+ */
+CGLM_INLINE
+void
+glm_vec3_center(vec3 a, vec3 b, vec3 dest) {
+ glm_vec3_add(a, b, 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(a[0] - b[0])
+ + glm_pow2(a[1] - b[1])
+ + glm_pow2(a[2] - b[2]);
+}
+
+/**
+ * @brief distance between two vectors
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @return returns distance
+ */
+CGLM_INLINE
+float
+glm_vec3_distance(vec3 a, vec3 b) {
+ return sqrtf(glm_vec3_distance2(a, b));
+}
+
+/*!
+ * @brief max values of vectors
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec3_maxv(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 min values of vectors
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec3_minv(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 possible orthogonal/perpendicular vector
+ *
+ * @param[in] v vector
+ * @param[out] dest orthogonal/perpendicular vector
+ */
+CGLM_INLINE
+void
+glm_vec3_ortho(vec3 v, vec3 dest) {
+ float ignore;
+ float f = modff(fabsf(v[0]) + 0.5f, &ignore);
+ vec3 result = {-v[1], v[0] - f * v[2], f * v[1]};
+ glm_vec3_copy(result, dest);
+}
+
+/*!
+ * @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 vectors
+ *
+ * formula: from + s * (to - from)
+ *
+ * @param[in] from from value
+ * @param[in] to to value
+ * @param[in] t interpolant (amount)
+ * @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(t, s);
+ glm_vec3_sub(to, from, v);
+ glm_vec3_mul(s, v, v);
+ glm_vec3_add(from, v, dest);
+}
+
+/*!
+ * @brief linear interpolation between two vectors (clamped)
+ *
+ * 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_lerpc(vec3 from, vec3 to, float t, vec3 dest) {
+ glm_vec3_lerp(from, to, glm_clamp_zo(t), dest);
+}
+
+/*!
+ * @brief linear interpolation between two vectors
+ *
+ * formula: from + s * (to - from)
+ *
+ * @param[in] from from value
+ * @param[in] to to value
+ * @param[in] t interpolant (amount)
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec3_mix(vec3 from, vec3 to, float t, vec3 dest) {
+ glm_vec3_lerp(from, to, t, dest);
+}
+
+/*!
+ * @brief linear interpolation between two vectors (clamped)
+ *
+ * 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_mixc(vec3 from, vec3 to, float t, vec3 dest) {
+ glm_vec3_lerpc(from, to, t, dest);
+}
+
+/*!
+ * @brief threshold function (unidimensional)
+ *
+ * @param[in] edge threshold
+ * @param[in] x value to test against threshold
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec3_step_uni(float edge, vec3 x, vec3 dest) {
+ dest[0] = glm_step(edge, x[0]);
+ dest[1] = glm_step(edge, x[1]);
+ dest[2] = glm_step(edge, x[2]);
+}
+
+/*!
+ * @brief threshold function
+ *
+ * @param[in] edge threshold
+ * @param[in] x value to test against threshold
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec3_step(vec3 edge, vec3 x, vec3 dest) {
+ dest[0] = glm_step(edge[0], x[0]);
+ dest[1] = glm_step(edge[1], x[1]);
+ dest[2] = glm_step(edge[2], x[2]);
+}
+
+/*!
+ * @brief threshold function with a smooth transition (unidimensional)
+ *
+ * @param[in] edge0 low threshold
+ * @param[in] edge1 high threshold
+ * @param[in] x value to test against threshold
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec3_smoothstep_uni(float edge0, float edge1, vec3 x, vec3 dest) {
+ dest[0] = glm_smoothstep(edge0, edge1, x[0]);
+ dest[1] = glm_smoothstep(edge0, edge1, x[1]);
+ dest[2] = glm_smoothstep(edge0, edge1, x[2]);
+}
+
+/*!
+ * @brief threshold function with a smooth transition
+ *
+ * @param[in] edge0 low threshold
+ * @param[in] edge1 high threshold
+ * @param[in] x value to test against threshold
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec3_smoothstep(vec3 edge0, vec3 edge1, vec3 x, vec3 dest) {
+ dest[0] = glm_smoothstep(edge0[0], edge1[0], x[0]);
+ dest[1] = glm_smoothstep(edge0[1], edge1[1], x[1]);
+ dest[2] = glm_smoothstep(edge0[2], edge1[2], x[2]);
+}
+
+/*!
+ * @brief smooth Hermite interpolation between two vectors
+ *
+ * formula: from + s * (to - from)
+ *
+ * @param[in] from from value
+ * @param[in] to to value
+ * @param[in] t interpolant (amount)
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec3_smoothinterp(vec3 from, vec3 to, float t, vec3 dest) {
+ vec3 s, v;
+
+ /* from + s * (to - from) */
+ glm_vec3_broadcast(glm_smooth(t), s);
+ glm_vec3_sub(to, from, v);
+ glm_vec3_mul(s, v, v);
+ glm_vec3_add(from, v, dest);
+}
+
+/*!
+ * @brief smooth Hermite interpolation between two vectors (clamped)
+ *
+ * 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_smoothinterpc(vec3 from, vec3 to, float t, vec3 dest) {
+ glm_vec3_smoothinterp(from, to, glm_clamp_zo(t), dest);
+}
+
+/*!
+ * @brief swizzle vector components
+ *
+ * you can use existin masks e.g. GLM_XXX, GLM_ZYX
+ *
+ * @param[in] v source
+ * @param[in] mask mask
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec3_swizzle(vec3 v, int mask, vec3 dest) {
+ vec3 t;
+
+ t[0] = v[(mask & (3 << 0))];
+ t[1] = v[(mask & (3 << 2)) >> 2];
+ t[2] = v[(mask & (3 << 4)) >> 4];
+
+ glm_vec3_copy(t, dest);
+}
+
+/*!
+ * @brief vec3 cross product
+ *
+ * this is just convenient wrapper
+ *
+ * @param[in] a source 1
+ * @param[in] b source 2
+ * @param[out] d destination
+ */
+CGLM_INLINE
+void
+glm_cross(vec3 a, vec3 b, vec3 d) {
+ glm_vec3_cross(a, b, d);
+}
+
+/*!
+ * @brief vec3 dot product
+ *
+ * this is just convenient wrapper
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ *
+ * @return dot product
+ */
+CGLM_INLINE
+float
+glm_dot(vec3 a, vec3 b) {
+ return glm_vec3_dot(a, b);
+}
+
+/*!
+ * @brief normalize vec3 and store result in same vec
+ *
+ * this is just convenient wrapper
+ *
+ * @param[in, out] v vector
+ */
+CGLM_INLINE
+void
+glm_normalize(vec3 v) {
+ glm_vec3_normalize(v);
+}
+
+/*!
+ * @brief normalize vec3 to dest
+ *
+ * this is just convenient wrapper
+ *
+ * @param[in] v source
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_normalize_to(vec3 v, vec3 dest) {
+ glm_vec3_normalize_to(v, dest);
+}
+
+#endif /* cglm_vec3_h */
diff --git a/libs/cglm/include/cglm/vec4-ext.h b/libs/cglm/include/cglm/vec4-ext.h
new file mode 100644
index 0000000..e4e20cb
--- /dev/null
+++ b/libs/cglm/include/cglm/vec4-ext.h
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*!
+ * @brief SIMD like functions
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glm_vec4_broadcast(float val, vec4 d);
+ CGLM_INLINE void glm_vec4_fill(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_all(vec4 v);
+ CGLM_INLINE bool glm_vec4_eqv(vec4 a, vec4 b);
+ CGLM_INLINE bool glm_vec4_eqv_eps(vec4 a, vec4 b);
+ CGLM_INLINE float glm_vec4_max(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_abs(vec4 v, vec4 dest);
+ CGLM_INLINE void glm_vec4_fract(vec4 v, vec4 dest);
+ CGLM_INLINE float glm_vec4_hadd(vec4 v);
+ CGLM_INLINE void glm_vec4_sqrt(vec4 v, vec4 dest);
+ */
+
+#ifndef cglm_vec4_ext_h
+#define cglm_vec4_ext_h
+
+#include "common.h"
+#include "vec3-ext.h"
+
+/*!
+ * @brief fill a vector with specified value
+ *
+ * @param val value
+ * @param d dest
+ */
+CGLM_INLINE
+void
+glm_vec4_broadcast(float val, vec4 d) {
+#if defined( __SSE__ ) || defined( __SSE2__ )
+ glmm_store(d, _mm_set1_ps(val));
+#else
+ d[0] = d[1] = d[2] = d[3] = val;
+#endif
+}
+
+/*!
+ * @brief fill a vector with specified value
+ *
+ * @param v dest
+ * @param val value
+ */
+CGLM_INLINE
+void
+glm_vec4_fill(vec4 v, float val) {
+#if defined( __SSE__ ) || defined( __SSE2__ )
+ glmm_store(v, _mm_set1_ps(val));
+#else
+ v[0] = v[1] = v[2] = v[3] = val;
+#endif
+}
+
+/*!
+ * @brief check if vector is equal to value (without epsilon)
+ *
+ * @param v vector
+ * @param val value
+ */
+CGLM_INLINE
+bool
+glm_vec4_eq(vec4 v, float val) {
+ return v[0] == val
+ && v[0] == v[1]
+ && v[0] == v[2]
+ && v[0] == v[3];
+}
+
+/*!
+ * @brief check if vector is equal to value (with epsilon)
+ *
+ * @param v vector
+ * @param val value
+ */
+CGLM_INLINE
+bool
+glm_vec4_eq_eps(vec4 v, float val) {
+ return fabsf(v[0] - val) <= GLM_FLT_EPSILON
+ && fabsf(v[1] - val) <= GLM_FLT_EPSILON
+ && fabsf(v[2] - val) <= GLM_FLT_EPSILON
+ && fabsf(v[3] - val) <= GLM_FLT_EPSILON;
+}
+
+/*!
+ * @brief check if vectors members are equal (without epsilon)
+ *
+ * @param v vector
+ */
+CGLM_INLINE
+bool
+glm_vec4_eq_all(vec4 v) {
+ return glm_vec4_eq_eps(v, v[0]);
+}
+
+/*!
+ * @brief check if vector is equal to another (without epsilon)
+ *
+ * @param a vector
+ * @param b vector
+ */
+CGLM_INLINE
+bool
+glm_vec4_eqv(vec4 a, vec4 b) {
+ return a[0] == b[0]
+ && a[1] == b[1]
+ && a[2] == b[2]
+ && a[3] == b[3];
+}
+
+/*!
+ * @brief check if vector is equal to another (with epsilon)
+ *
+ * @param a vector
+ * @param b vector
+ */
+CGLM_INLINE
+bool
+glm_vec4_eqv_eps(vec4 a, vec4 b) {
+ return fabsf(a[0] - b[0]) <= GLM_FLT_EPSILON
+ && fabsf(a[1] - b[1]) <= GLM_FLT_EPSILON
+ && fabsf(a[2] - b[2]) <= GLM_FLT_EPSILON
+ && fabsf(a[3] - b[3]) <= GLM_FLT_EPSILON;
+}
+
+/*!
+ * @brief max value of vector
+ *
+ * @param v vector
+ */
+CGLM_INLINE
+float
+glm_vec4_max(vec4 v) {
+ float max;
+
+ max = glm_vec3_max(v);
+ if (v[3] > max)
+ max = v[3];
+
+ return max;
+}
+
+/*!
+ * @brief min value of vector
+ *
+ * @param v vector
+ */
+CGLM_INLINE
+float
+glm_vec4_min(vec4 v) {
+ float min;
+
+ min = glm_vec3_min(v);
+ if (v[3] < min)
+ min = v[3];
+
+ return min;
+}
+
+/*!
+ * @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_splat(x1, 2);
+
+ x3 = _mm_and_ps(_mm_cmpgt_ps(x0, x2), glmm_splat(x1, 1));
+ x4 = _mm_and_ps(_mm_cmplt_ps(x0, x2), glmm_splat(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 absolute value of each vector item
+ *
+ * @param[in] v vector
+ * @param[out] dest destination vector
+ */
+CGLM_INLINE
+void
+glm_vec4_abs(vec4 v, vec4 dest) {
+#if defined( __SSE__ ) || defined( __SSE2__ )
+ glmm_store(dest, glmm_abs(glmm_load(v)));
+#elif defined(CGLM_NEON_FP)
+ vst1q_f32(dest, vabsq_f32(vld1q_f32(v)));
+#else
+ dest[0] = fabsf(v[0]);
+ dest[1] = fabsf(v[1]);
+ dest[2] = fabsf(v[2]);
+ dest[3] = fabsf(v[3]);
+#endif
+}
+
+/*!
+ * @brief fractional part of each vector item
+ *
+ * @param[in] v vector
+ * @param[out] dest destination vector
+ */
+CGLM_INLINE
+void
+glm_vec4_fract(vec4 v, vec4 dest) {
+ dest[0] = fminf(v[0] - floorf(v[0]), 0.999999940395355224609375f);
+ dest[1] = fminf(v[1] - floorf(v[1]), 0.999999940395355224609375f);
+ dest[2] = fminf(v[2] - floorf(v[2]), 0.999999940395355224609375f);
+ dest[3] = fminf(v[3] - floorf(v[3]), 0.999999940395355224609375f);
+}
+
+/*!
+ * @brief vector reduction by summation
+ * @warning could overflow
+ *
+ * @param[in] v vector
+ * @return sum of all vector's elements
+ */
+CGLM_INLINE
+float
+glm_vec4_hadd(vec4 v) {
+#if defined( __SSE__ ) || defined( __SSE2__ )
+ return glmm_hadd(glmm_load(v));
+#else
+ return v[0] + v[1] + v[2] + 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 */
diff --git a/libs/cglm/include/cglm/vec4.h b/libs/cglm/include/cglm/vec4.h
new file mode 100644
index 0000000..8e95ec5
--- /dev/null
+++ b/libs/cglm/include/cglm/vec4.h
@@ -0,0 +1,1066 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Macros:
+ GLM_VEC4_ONE_INIT
+ GLM_VEC4_BLACK_INIT
+ GLM_VEC4_ZERO_INIT
+ GLM_VEC4_ONE
+ GLM_VEC4_BLACK
+ GLM_VEC4_ZERO
+
+ Functions:
+ 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_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_norm2(vec4 v);
+ CGLM_INLINE float glm_vec4_norm(vec4 v);
+ CGLM_INLINE float glm_vec4_norm_one(vec4 v);
+ CGLM_INLINE float glm_vec4_norm_inf(vec4 v);
+ CGLM_INLINE void glm_vec4_add(vec4 a, vec4 b, 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_as(vec4 v, float s, vec4 dest);
+ 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_to(vec4 v, vec4 dest);
+ CGLM_INLINE void glm_vec4_normalize(vec4 v);
+ CGLM_INLINE void glm_vec4_normalize_to(vec4 vec, vec4 dest);
+ CGLM_INLINE float glm_vec4_distance(vec4 a, vec4 b);
+ CGLM_INLINE float glm_vec4_distance2(vec4 a, vec4 b);
+ CGLM_INLINE void glm_vec4_maxv(vec4 a, vec4 b, 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);
+ CGLM_INLINE void glm_vec4_lerpc(vec4 from, vec4 to, float t, vec4 dest);
+ CGLM_INLINE void glm_vec4_step_uni(float edge, vec4 x, vec4 dest);
+ CGLM_INLINE void glm_vec4_step(vec4 edge, vec4 x, vec4 dest);
+ CGLM_INLINE void glm_vec4_smoothstep_uni(float edge0, float edge1, vec4 x, vec4 dest);
+ CGLM_INLINE void glm_vec4_smoothstep(vec4 edge0, vec4 edge1, vec4 x, vec4 dest);
+ CGLM_INLINE void glm_vec4_smoothinterp(vec4 from, vec4 to, float t, vec4 dest);
+ CGLM_INLINE void glm_vec4_smoothinterpc(vec4 from, vec4 to, float t, vec4 dest);
+ CGLM_INLINE void glm_vec4_swizzle(vec4 v, int mask, 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
+#define cglm_vec4_h
+
+#include "common.h"
+#include "vec4-ext.h"
+#include "util.h"
+
+/* DEPRECATED! functions */
+#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_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_BLACK_INIT {0.0f, 0.0f, 0.0f, 1.0f}
+#define GLM_VEC4_ZERO_INIT {0.0f, 0.0f, 0.0f, 0.0f}
+
+#define GLM_VEC4_ONE ((vec4)GLM_VEC4_ONE_INIT)
+#define GLM_VEC4_BLACK ((vec4)GLM_VEC4_BLACK_INIT)
+#define GLM_VEC4_ZERO ((vec4)GLM_VEC4_ZERO_INIT)
+
+#define GLM_XXXX GLM_SHUFFLE4(0, 0, 0, 0)
+#define GLM_YYYY GLM_SHUFFLE4(1, 1, 1, 1)
+#define GLM_ZZZZ GLM_SHUFFLE4(2, 2, 2, 2)
+#define GLM_WWWW GLM_SHUFFLE4(3, 3, 3, 3)
+#define GLM_WZYX GLM_SHUFFLE4(0, 1, 2, 3)
+
+/*!
+ * @brief init vec4 using vec3
+ *
+ * @param[in] v3 vector3
+ * @param[in] last last item
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec4(vec3 v3, float last, vec4 dest) {
+ dest[0] = v3[0];
+ dest[1] = v3[1];
+ dest[2] = v3[2];
+ dest[3] = last;
+}
+
+/*!
+ * @brief copy first 3 members of [a] to [dest]
+ *
+ * @param[in] a source
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec4_copy3(vec4 a, vec3 dest) {
+ dest[0] = a[0];
+ dest[1] = a[1];
+ dest[2] = a[2];
+}
+
+/*!
+ * @brief copy all members of [a] to [dest]
+ *
+ * @param[in] v source
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec4_copy(vec4 v, vec4 dest) {
+#if defined( __SSE__ ) || defined( __SSE2__ )
+ glmm_store(dest, glmm_load(v));
+#elif defined(CGLM_NEON_FP)
+ vst1q_f32(dest, vld1q_f32(v));
+#else
+ dest[0] = v[0];
+ dest[1] = v[1];
+ dest[2] = v[2];
+ dest[3] = v[3];
+#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());
+#elif defined(CGLM_NEON_FP)
+ vst1q_f32(v, vdupq_n_f32(0.0f));
+#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));
+#elif defined(CGLM_NEON_FP)
+ vst1q_f32(v, vdupq_n_f32(1.0f));
+#else
+ v[0] = 1.0f;
+ v[1] = 1.0f;
+ v[2] = 1.0f;
+ v[3] = 1.0f;
+#endif
+}
+
+/*!
+ * @brief vec4 dot product
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ *
+ * @return dot product
+ */
+CGLM_INLINE
+float
+glm_vec4_dot(vec4 a, vec4 b) {
+#if defined(CGLM_SIMD)
+ return glmm_dot(glmm_load(a), glmm_load(b));
+#else
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
+#endif
+}
+
+/*!
+ * @brief norm * norm (magnitude) of vec
+ *
+ * we can use this func instead of calling norm * norm, because it would call
+ * sqrtf fuction twice but with this func we can avoid func call, maybe this is
+ * not good name for this func
+ *
+ * @param[in] v vec4
+ *
+ * @return norm * norm
+ */
+CGLM_INLINE
+float
+glm_vec4_norm2(vec4 v) {
+ return glm_vec4_dot(v, v);
+}
+
+/*!
+ * @brief euclidean norm (magnitude), also called L2 norm
+ * this will give magnitude of vector in euclidean space
+ *
+ * @param[in] v vector
+ *
+ * @return norm
+ */
+CGLM_INLINE
+float
+glm_vec4_norm(vec4 v) {
+#if defined(CGLM_SIMD)
+ return glmm_norm(glmm_load(v));
+#else
+ return sqrtf(glm_vec4_dot(v, v));
+#endif
+}
+
+/*!
+ * @brief L1 norm of vec4
+ * Also known as Manhattan Distance or Taxicab norm.
+ * L1 Norm is the sum of the magnitudes of the vectors in a space.
+ * It is calculated as the sum of the absolute values of the vector components.
+ * In this norm, all the components of the vector are weighted equally.
+ *
+ * This computes:
+ * L1 norm = |v[0]| + |v[1]| + |v[2]| + |v[3]|
+ *
+ * @param[in] v vector
+ *
+ * @return L1 norm
+ */
+CGLM_INLINE
+float
+glm_vec4_norm_one(vec4 v) {
+#if defined(CGLM_SIMD)
+ return glmm_norm_one(glmm_load(v));
+#else
+ vec4 t;
+ glm_vec4_abs(v, t);
+ return glm_vec4_hadd(t);
+#endif
+}
+
+/*!
+ * @brief infinity norm of vec4
+ * Also known as Maximum norm.
+ * Infinity Norm is the largest magnitude among each element of a vector.
+ * It is calculated as the maximum of the absolute values of the vector components.
+ *
+ * This computes:
+ * inf norm = max(|v[0]|, |v[1]|, |v[2]|, |v[3]|)
+ *
+ * @param[in] v vector
+ *
+ * @return infinity norm
+ */
+CGLM_INLINE
+float
+glm_vec4_norm_inf(vec4 v) {
+#if defined(CGLM_SIMD)
+ return glmm_norm_inf(glmm_load(v));
+#else
+ vec4 t;
+ glm_vec4_abs(v, t);
+ return glm_vec4_max(t);
+#endif
+}
+
+/*!
+ * @brief add b vector to a vector store result in dest
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @param[out] dest destination vector
+ */
+CGLM_INLINE
+void
+glm_vec4_add(vec4 a, vec4 b, vec4 dest) {
+#if defined( __SSE__ ) || defined( __SSE2__ )
+ glmm_store(dest, _mm_add_ps(glmm_load(a), glmm_load(b)));
+#elif defined(CGLM_NEON_FP)
+ vst1q_f32(dest, vaddq_f32(vld1q_f32(a), vld1q_f32(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 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)));
+#elif defined(CGLM_NEON_FP)
+ vst1q_f32(dest, vaddq_f32(vld1q_f32(v), vdupq_n_f32(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)));
+#elif defined(CGLM_NEON_FP)
+ vst1q_f32(dest, vsubq_f32(vld1q_f32(a), vld1q_f32(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)));
+#elif defined(CGLM_NEON_FP)
+ vst1q_f32(dest, vsubq_f32(vld1q_f32(v), vdupq_n_f32(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 dest 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)));
+#elif defined(CGLM_NEON_FP)
+ vst1q_f32(dest, vmulq_f32(vld1q_f32(a), vld1q_f32(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 multiply/scale vec4 vector with scalar: result = v * s
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @param[out] dest destination vector
+ */
+CGLM_INLINE
+void
+glm_vec4_scale(vec4 v, float s, vec4 dest) {
+#if defined( __SSE__ ) || defined( __SSE2__ )
+ glmm_store(dest, _mm_mul_ps(glmm_load(v), _mm_set1_ps(s)));
+#elif defined(CGLM_NEON_FP)
+ vst1q_f32(dest, vmulq_f32(vld1q_f32(v), vdupq_n_f32(s)));
+#else
+ dest[0] = v[0] * s;
+ dest[1] = v[1] * s;
+ dest[2] = v[2] * s;
+ dest[3] = v[3] * s;
+#endif
+}
+
+/*!
+ * @brief make vec4 vector scale as specified: result = unit(v) * s
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @param[out] dest destination vector
+ */
+CGLM_INLINE
+void
+glm_vec4_scale_as(vec4 v, float s, vec4 dest) {
+ float norm;
+ norm = glm_vec4_norm(v);
+
+ if (norm == 0.0f) {
+ glm_vec4_zero(dest);
+ return;
+ }
+
+ 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(CGLM_SIMD)
+ glmm_store(dest, glmm_div(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))));
+#elif defined(CGLM_NEON_FP)
+ vst1q_f32(dest, vaddq_f32(vld1q_f32(dest),
+ vaddq_f32(vld1q_f32(a),
+ vld1q_f32(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))));
+#elif defined(CGLM_NEON_FP)
+ vst1q_f32(dest, vaddq_f32(vld1q_f32(dest),
+ vsubq_f32(vld1q_f32(a),
+ vld1q_f32(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(CGLM_SIMD)
+ glmm_store(dest, glmm_fmadd(glmm_load(a), glmm_load(b), glmm_load(dest)));
+#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(CGLM_SIMD)
+ glmm_store(dest, glmm_fmadd(glmm_load(a), glmm_set1(s), glmm_load(dest)));
+#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))));
+#elif defined(CGLM_NEON_FP)
+ vst1q_f32(dest, vaddq_f32(vld1q_f32(dest),
+ vmaxq_f32(vld1q_f32(a),
+ vld1q_f32(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 1
+ * @param[in] b vector 2
+ * @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))));
+#elif defined(CGLM_NEON_FP)
+ vst1q_f32(dest, vaddq_f32(vld1q_f32(dest),
+ vminq_f32(vld1q_f32(a),
+ vld1q_f32(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)));
+#elif defined(CGLM_NEON_FP)
+ vst1q_f32(dest, vnegq_f32(vld1q_f32(v)));
+#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
+ *
+ * @param[in, out] v vector
+ */
+CGLM_INLINE
+void
+glm_vec4_negate(vec4 v) {
+ glm_vec4_negate_to(v, v);
+}
+
+/*!
+ * @brief normalize vec4 to dest
+ *
+ * @param[in] v source
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec4_normalize_to(vec4 v, vec4 dest) {
+#if defined( __SSE__ ) || defined( __SSE2__ )
+ __m128 xdot, x0;
+ float dot;
+
+ x0 = glmm_load(v);
+ xdot = glmm_vdot(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
+}
+
+/*!
+ * @brief normalize vec4 and store result in same vec
+ *
+ * @param[in, out] v vector
+ */
+CGLM_INLINE
+void
+glm_vec4_normalize(vec4 v) {
+ glm_vec4_normalize_to(v, v);
+}
+
+/**
+ * @brief distance between two vectors
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @return returns distance
+ */
+CGLM_INLINE
+float
+glm_vec4_distance(vec4 a, vec4 b) {
+#if defined( __SSE__ ) || defined( __SSE2__ )
+ return glmm_norm(_mm_sub_ps(glmm_load(a), glmm_load(b)));
+#elif defined(CGLM_NEON_FP)
+ return glmm_norm(vsubq_f32(glmm_load(a), glmm_load(b)));
+#else
+ return sqrtf(glm_pow2(a[0] - b[0])
+ + glm_pow2(a[1] - b[1])
+ + glm_pow2(a[2] - b[2])
+ + glm_pow2(a[3] - b[3]));
+#endif
+}
+
+/**
+ * @brief squared distance between two vectors
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @return returns squared distance
+ */
+CGLM_INLINE
+float
+glm_vec4_distance2(vec4 a, vec4 b) {
+#if defined( __SSE__ ) || defined( __SSE2__ )
+ return glmm_norm2(_mm_sub_ps(glmm_load(a), glmm_load(b)));
+#elif defined(CGLM_NEON_FP)
+ return glmm_norm2(vsubq_f32(glmm_load(a), glmm_load(b)));
+#else
+ return glm_pow2(a[0] - b[0])
+ + glm_pow2(a[1] - b[1])
+ + glm_pow2(a[2] - b[2])
+ + glm_pow2(a[3] - b[3]);
+#endif
+}
+
+/*!
+ * @brief max values of vectors
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec4_maxv(vec4 a, vec4 b, vec4 dest) {
+#if defined( __SSE__ ) || defined( __SSE2__ )
+ glmm_store(dest, _mm_max_ps(glmm_load(a), glmm_load(b)));
+#elif defined(CGLM_NEON_FP)
+ vst1q_f32(dest, vmaxq_f32(vld1q_f32(a), vld1q_f32(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 min values of vectors
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec4_minv(vec4 a, vec4 b, vec4 dest) {
+#if defined( __SSE__ ) || defined( __SSE2__ )
+ glmm_store(dest, _mm_min_ps(glmm_load(a), glmm_load(b)));
+#elif defined(CGLM_NEON_FP)
+ vst1q_f32(dest, vminq_f32(vld1q_f32(a), vld1q_f32(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 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)));
+#elif defined(CGLM_NEON_FP)
+ vst1q_f32(v, vminq_f32(vmaxq_f32(vld1q_f32(v), vdupq_n_f32(minVal)),
+ vdupq_n_f32(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 vectors
+ *
+ * formula: from + t * (to - from)
+ *
+ * @param[in] from from value
+ * @param[in] to to value
+ * @param[in] t interpolant (amount)
+ * @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(t, s);
+ glm_vec4_sub(to, from, v);
+ glm_vec4_mul(s, v, v);
+ glm_vec4_add(from, v, dest);
+}
+
+/*!
+ * @brief linear interpolation between two vectors (clamped)
+ *
+ * formula: from + t * (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_lerpc(vec4 from, vec4 to, float t, vec4 dest) {
+ glm_vec4_lerp(from, to, glm_clamp_zo(t), dest);
+}
+
+/*!
+ * @brief linear interpolation between two vectors
+ *
+ * formula: from + t * (to - from)
+ *
+ * @param[in] from from value
+ * @param[in] to to value
+ * @param[in] t interpolant (amount)
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec4_mix(vec4 from, vec4 to, float t, vec4 dest) {
+ glm_vec4_lerp(from, to, t, dest);
+}
+
+/*!
+ * @brief linear interpolation between two vectors (clamped)
+ *
+ * formula: from + t * (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_mixc(vec4 from, vec4 to, float t, vec4 dest) {
+ glm_vec4_lerpc(from, to, t, dest);
+}
+
+/*!
+ * @brief threshold function (unidimensional)
+ *
+ * @param[in] edge threshold
+ * @param[in] x value to test against threshold
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec4_step_uni(float edge, vec4 x, vec4 dest) {
+ dest[0] = glm_step(edge, x[0]);
+ dest[1] = glm_step(edge, x[1]);
+ dest[2] = glm_step(edge, x[2]);
+ dest[3] = glm_step(edge, x[3]);
+}
+
+/*!
+ * @brief threshold function
+ *
+ * @param[in] edge threshold
+ * @param[in] x value to test against threshold
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec4_step(vec4 edge, vec4 x, vec4 dest) {
+ dest[0] = glm_step(edge[0], x[0]);
+ dest[1] = glm_step(edge[1], x[1]);
+ dest[2] = glm_step(edge[2], x[2]);
+ dest[3] = glm_step(edge[3], x[3]);
+}
+
+/*!
+ * @brief threshold function with a smooth transition (unidimensional)
+ *
+ * @param[in] edge0 low threshold
+ * @param[in] edge1 high threshold
+ * @param[in] x value to test against threshold
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec4_smoothstep_uni(float edge0, float edge1, vec4 x, vec4 dest) {
+ dest[0] = glm_smoothstep(edge0, edge1, x[0]);
+ dest[1] = glm_smoothstep(edge0, edge1, x[1]);
+ dest[2] = glm_smoothstep(edge0, edge1, x[2]);
+ dest[3] = glm_smoothstep(edge0, edge1, x[3]);
+}
+
+/*!
+ * @brief threshold function with a smooth transition
+ *
+ * @param[in] edge0 low threshold
+ * @param[in] edge1 high threshold
+ * @param[in] x value to test against threshold
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec4_smoothstep(vec4 edge0, vec4 edge1, vec4 x, vec4 dest) {
+ dest[0] = glm_smoothstep(edge0[0], edge1[0], x[0]);
+ dest[1] = glm_smoothstep(edge0[1], edge1[1], x[1]);
+ dest[2] = glm_smoothstep(edge0[2], edge1[2], x[2]);
+ dest[3] = glm_smoothstep(edge0[3], edge1[3], x[3]);
+}
+
+/*!
+ * @brief smooth Hermite interpolation between two vectors
+ *
+ * formula: t^2 * (3 - 2*t)
+ *
+ * @param[in] from from value
+ * @param[in] to to value
+ * @param[in] t interpolant (amount)
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec4_smoothinterp(vec4 from, vec4 to, float t, vec4 dest) {
+ vec4 s, v;
+
+ /* from + smoothstep * (to - from) */
+ glm_vec4_broadcast(glm_smooth(t), s);
+ glm_vec4_sub(to, from, v);
+ glm_vec4_mul(s, v, v);
+ glm_vec4_add(from, v, dest);
+}
+
+/*!
+ * @brief smooth Hermite interpolation between two vectors (clamped)
+ *
+ * formula: t^2 * (3 - 2*t)
+ *
+ * @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_smoothinterpc(vec4 from, vec4 to, float t, vec4 dest) {
+ glm_vec4_smoothinterp(from, to, glm_clamp_zo(t), dest);
+}
+
+/*!
+ * @brief helper to fill vec4 as [S^3, S^2, S, 1]
+ *
+ * @param[in] s parameter
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec4_cubic(float s, vec4 dest) {
+ float ss;
+
+ ss = s * s;
+
+ dest[0] = ss * s;
+ dest[1] = ss;
+ dest[2] = s;
+ dest[3] = 1.0f;
+}
+
+/*!
+ * @brief swizzle vector components
+ *
+ * you can use existin masks e.g. GLM_XXXX, GLM_WZYX
+ *
+ * @param[in] v source
+ * @param[in] mask mask
+ * @param[out] dest destination
+ */
+CGLM_INLINE
+void
+glm_vec4_swizzle(vec4 v, int mask, vec4 dest) {
+ vec4 t;
+
+ t[0] = v[(mask & (3 << 0))];
+ t[1] = v[(mask & (3 << 2)) >> 2];
+ t[2] = v[(mask & (3 << 4)) >> 4];
+ t[3] = v[(mask & (3 << 6)) >> 6];
+
+ glm_vec4_copy(t, dest);
+}
+
+#endif /* cglm_vec4_h */
diff --git a/libs/cglm/include/cglm/version.h b/libs/cglm/include/cglm/version.h
new file mode 100644
index 0000000..b31eae6
--- /dev/null
+++ b/libs/cglm/include/cglm/version.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_version_h
+#define cglm_version_h
+
+#define CGLM_VERSION_MAJOR 0
+#define CGLM_VERSION_MINOR 8
+#define CGLM_VERSION_PATCH 6
+
+#endif /* cglm_version_h */
diff --git a/libs/cglm/include/module.modulemap b/libs/cglm/include/module.modulemap
new file mode 100644
index 0000000..40b8b9f
--- /dev/null
+++ b/libs/cglm/include/module.modulemap
@@ -0,0 +1,14 @@
+module cglm {
+ header "cglm/cglm.h"
+ header "cglm/struct.h"
+
+ export *
+}
+
+module cglmc {
+ header "cglm/cglm.h"
+ header "cglm/struct.h"
+ header "cglm/call.h"
+
+ export *
+}