summaryrefslogtreecommitdiff
path: root/include/cglm/struct
diff options
context:
space:
mode:
Diffstat (limited to 'include/cglm/struct')
-rw-r--r--include/cglm/struct/aabb2d.h253
-rw-r--r--include/cglm/struct/affine-mat.h90
-rw-r--r--include/cglm/struct/affine-post.h184
-rw-r--r--include/cglm/struct/affine-pre.h184
-rw-r--r--include/cglm/struct/affine.h201
-rw-r--r--include/cglm/struct/affine2d.h177
-rw-r--r--include/cglm/struct/box.h259
-rw-r--r--include/cglm/struct/cam.h646
-rw-r--r--include/cglm/struct/clipspace/ortho_lh_no.h154
-rw-r--r--include/cglm/struct/clipspace/ortho_lh_zo.h154
-rw-r--r--include/cglm/struct/clipspace/ortho_rh_no.h154
-rw-r--r--include/cglm/struct/clipspace/ortho_rh_zo.h154
-rw-r--r--include/cglm/struct/clipspace/persp_lh_no.h312
-rw-r--r--include/cglm/struct/clipspace/persp_lh_zo.h312
-rw-r--r--include/cglm/struct/clipspace/persp_rh_no.h312
-rw-r--r--include/cglm/struct/clipspace/persp_rh_zo.h312
-rw-r--r--include/cglm/struct/clipspace/project_no.h98
-rw-r--r--include/cglm/struct/clipspace/project_zo.h98
-rw-r--r--include/cglm/struct/clipspace/view_lh_no.h89
-rw-r--r--include/cglm/struct/clipspace/view_lh_zo.h89
-rw-r--r--include/cglm/struct/clipspace/view_rh_no.h89
-rw-r--r--include/cglm/struct/clipspace/view_rh_zo.h89
-rw-r--r--include/cglm/struct/color.h27
-rw-r--r--include/cglm/struct/curve.h40
-rw-r--r--include/cglm/struct/euler.h249
-rw-r--r--include/cglm/struct/frustum.h155
-rw-r--r--include/cglm/struct/handed/euler_to_quat_lh.h115
-rw-r--r--include/cglm/struct/handed/euler_to_quat_rh.h115
-rw-r--r--include/cglm/struct/io.h107
-rw-r--r--include/cglm/struct/ivec2.h708
-rw-r--r--include/cglm/struct/ivec3.h725
-rw-r--r--include/cglm/struct/ivec4.h588
-rw-r--r--include/cglm/struct/mat2.h274
-rw-r--r--include/cglm/struct/mat2x3.h125
-rw-r--r--include/cglm/struct/mat2x4.h125
-rw-r--r--include/cglm/struct/mat3.h322
-rw-r--r--include/cglm/struct/mat3x2.h125
-rw-r--r--include/cglm/struct/mat3x4.h125
-rw-r--r--include/cglm/struct/mat4.h496
-rw-r--r--include/cglm/struct/mat4x2.h126
-rw-r--r--include/cglm/struct/mat4x3.h125
-rw-r--r--include/cglm/struct/noise.h57
-rw-r--r--include/cglm/struct/plane.h40
-rw-r--r--include/cglm/struct/project.h162
-rw-r--r--include/cglm/struct/quat.h601
-rw-r--r--include/cglm/struct/ray.h86
-rw-r--r--include/cglm/struct/sphere.h93
-rw-r--r--include/cglm/struct/vec2-ext.h337
-rw-r--r--include/cglm/struct/vec2.h747
-rw-r--r--include/cglm/struct/vec3-ext.h325
-rw-r--r--include/cglm/struct/vec3.h1132
-rw-r--r--include/cglm/struct/vec4-ext.h325
-rw-r--r--include/cglm/struct/vec4.h961
53 files changed, 13948 insertions, 0 deletions
diff --git a/include/cglm/struct/aabb2d.h b/include/cglm/struct/aabb2d.h
new file mode 100644
index 0000000..9077069
--- /dev/null
+++ b/include/cglm/struct/aabb2d.h
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglms_aabb2ds_h
+#define cglms_aabb2ds_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../aabb2d.h"
+#include "vec2.h"
+#include "vec4.h"
+#include "mat4.h"
+
+/* api definition */
+#define glms_aabb2d_(NAME) CGLM_STRUCTAPI(aabb2d, NAME)
+
+/*!
+ * @brief apply transform to Axis-Aligned Bounding Box
+ *
+ * @param[in] aabb bounding box
+ * @param[in] m transform matrix
+ * @param[out] dest transformed bounding box
+ */
+CGLM_INLINE
+void
+glms_aabb2d_(transform)(vec2s aabb[2], mat3s m, vec2s dest[2]) {
+ vec2 rawAabb[2];
+ vec2 rawDest[2];
+
+ glms_vec2_(unpack)(rawAabb, aabb, 2);
+ glm_aabb2d_transform(rawAabb, m.raw, rawDest);
+ glms_vec2_(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] aabb1 bounding box 1
+ * @param[in] aabb2 bounding box 2
+ * @param[out] dest merged bounding box
+ */
+CGLM_INLINE
+void
+glms_aabb2d_(merge)(vec2s aabb1[2], vec2s aabb2[2], vec2s dest[2]) {
+ vec2 rawAabb1[2];
+ vec2 rawAabb2[2];
+ vec2 rawDest[2];
+
+ glms_vec2_(unpack)(rawAabb1, aabb1, 2);
+ glms_vec2_(unpack)(rawAabb2, aabb2, 2);
+ glm_aabb2d_merge(rawAabb1, rawAabb2, rawDest);
+ glms_vec2_(pack)(dest, rawDest, 2);
+}
+
+/*!
+ * @brief crops a bounding box with another one.
+ *
+ * this could be useful for getting a bbox which fits with view frustum and
+ * object bounding boxes. In this case you crop view frustum box with objects
+ * box
+ *
+ * @param[in] aabb bounding box 1
+ * @param[in] cropAabb crop box
+ * @param[out] dest cropped bounding box
+ */
+CGLM_INLINE
+void
+glms_aabb2d_(crop)(vec2s aabb[2], vec2s cropAabb[2], vec2s dest[2]) {
+ vec2 rawAabb[2];
+ vec2 rawCropAabb[2];
+ vec2 rawDest[2];
+
+ glms_vec2_(unpack)(rawAabb, aabb, 2);
+ glms_vec2_(unpack)(rawCropAabb, cropAabb, 2);
+ glm_aabb2d_crop(rawAabb, rawCropAabb, rawDest);
+ glms_vec2_(pack)(dest, rawDest, 2);
+}
+
+/*!
+ * @brief crops a bounding box with another one.
+ *
+ * this could be useful for getting a bbox which fits with view frustum and
+ * object bounding boxes. In this case you crop view frustum box with objects
+ * box
+ *
+ * @param[in] aabb bounding box
+ * @param[in] cropAabb crop box
+ * @param[in] clampAabb minimum box
+ * @param[out] dest cropped bounding box
+ */
+CGLM_INLINE
+void
+glms_aabb2d_(crop_until)(vec2s aabb[2],
+ vec2s cropAabb[2],
+ vec2s clampAabb[2],
+ vec2s dest[2]) {
+ glms_aabb2d_(crop)(aabb, cropAabb, dest);
+ glms_aabb2d_(merge)(clampAabb, dest, dest);
+}
+
+/*!
+ * @brief invalidate AABB min and max values
+ *
+ * @param[in, out] aabb bounding box
+ */
+CGLM_INLINE
+void
+glms_aabb2d_(invalidate)(vec2s box[2]) {
+ box[0] = glms_vec2_(fill)(FLT_MAX);
+ box[1] = glms_vec2_(fill)(-FLT_MAX);
+}
+
+/*!
+ * @brief check if AABB is valid or not
+ *
+ * @param[in] aabb bounding box
+ */
+CGLM_INLINE
+bool
+glms_aabb2d_(isvalid)(vec2s aabb[2]) {
+ vec2 rawAabb[2];
+ glms_vec2_(unpack)(rawAabb, aabb, 2);
+ return glm_aabb2d_isvalid(rawAabb);
+}
+
+/*!
+ * @brief distance between of min and max
+ *
+ * @param[in] aabb bounding box
+ */
+CGLM_INLINE
+float
+glms_aabb2d_(diag)(vec2s aabb[2]) {
+ vec2 rawAabb[2];
+ glms_vec2_(unpack)(rawAabb, aabb, 2);
+ return glm_aabb2d_diag(rawAabb);
+}
+
+
+/*!
+ * @brief size of aabb
+ *
+ * @param[in] aabb bounding aabb
+ * @param[out] dest size
+ */
+CGLM_INLINE
+vec2s
+glms_aabb2d_(sizev)(vec2s aabb[2]) {
+ vec2s size;
+ vec2 rawAabb[2];
+ glms_vec2_(unpack)(rawAabb, aabb, 2);
+ glm_aabb2d_sizev(rawAabb, size.raw);
+ return size;
+}
+
+/*!
+ * @brief radius of sphere which surrounds AABB
+ *
+ * @param[in] aabb bounding box
+ */
+CGLM_INLINE
+float
+glms_aabb2d_(radius)(vec2s aabb[2]) {
+ return glms_aabb2d_(size)(aabb) * 0.5f;
+}
+
+/*!
+ * @brief computes center point of AABB
+ *
+ * @param[in] aabb bounding box
+ * @returns center of bounding box
+ */
+CGLM_INLINE
+vec2s
+glms_aabb2d_(center)(vec2s aabb[2]) {
+ return glms_vec2_(center)(aabb[0], aabb[1]);
+}
+
+/*!
+ * @brief check if two AABB intersects
+ *
+ * @param[in] aabb bounding box
+ * @param[in] other other bounding box
+ */
+CGLM_INLINE
+bool
+glms_aabb2d_(aabb)(vec2s aabb[2], vec2s other[2]) {
+ vec2 rawAabb[2];
+ vec2 rawOther[2];
+
+ glms_vec2_(unpack)(rawAabb, aabb, 2);
+ glms_vec2_(unpack)(rawOther, other, 2);
+ return glm_aabb2d_aabb(rawAabb, rawOther);
+}
+
+/*!
+ * @brief check if AABB intersects with a circle
+ *
+ * https://github.com/erich666/GraphicsGems/blob/master/gems/BoxSphere.c
+ * Solid Box - Solid Sphere test.
+ *
+ * @param[in] aabb solid bounding box
+ * @param[in] s solid sphere
+ */
+CGLM_INLINE
+bool
+glms_aabb2d_(circle)(vec2s aabb[2], vec3s c) {
+ vec2 rawAabb[2];
+
+ glms_vec2_(unpack)(rawAabb, aabb, 2);
+ return glm_aabb2d_circle(rawAabb, c.raw);
+}
+
+/*!
+ * @brief check if point is inside of AABB
+ *
+ * @param[in] aabb bounding box
+ * @param[in] point point
+ */
+CGLM_INLINE
+bool
+glms_aabb2d_(point)(vec2s aabb[2], vec2s point) {
+ vec2 rawAabb[2];
+
+ glms_vec2_(unpack)(rawAabb, aabb, 2);
+ return glm_aabb2d_point(rawAabb, point.raw);
+}
+
+/*!
+ * @brief check if AABB contains other AABB
+ *
+ * @param[in] box bounding box
+ * @param[in] other other bounding box
+ */
+CGLM_INLINE
+bool
+glms_aabb2d_(contains)(vec2s aabb[2], vec2s other[2]) {
+ vec2 rawAabb[2];
+ vec2 rawOther[2];
+
+ glms_vec2_(unpack)(rawAabb, aabb, 2);
+ glms_vec2_(unpack)(rawOther, other, 2);
+ return glm_aabb2d_contains(rawAabb, rawOther);
+}
+
+#endif /* cglms_aabb2ds_h */
diff --git a/include/cglm/struct/affine-mat.h b/include/cglm/struct/affine-mat.h
new file mode 100644
index 0000000..e1d4ff3
--- /dev/null
+++ b/include/cglm/struct/affine-mat.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
+ */
+
+/*
+ Functions:
+ CGLM_INLINE mat4s glms_mul(mat4 m1, mat4 m2);
+ CGLM_INLINE mat4s glms_mul_rot(mat4 m1, mat4 m2);
+ CGLM_INLINE mat4s glms_inv_tr();
+ */
+
+#ifndef cglms_affine_mat_h
+#define cglms_affine_mat_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../affine-mat.h"
+#include "vec3.h"
+#include "vec4.h"
+#include "mat4.h"
+
+/*!
+ * @brief this is similar to glms_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
+ * @returns destination matrix
+ */
+CGLM_INLINE
+mat4s
+glms_mul(mat4s m1, mat4s m2){
+ mat4s r;
+ glm_mul(m1.raw, m2.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @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
+ * @returns destination matrix
+ */
+CGLM_INLINE
+mat4s
+glms_mul_rot(mat4s m1, mat4s m2){
+ mat4s r;
+ glm_mul_rot(m1.raw, m2.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief inverse orthonormal rotation + translation matrix (ridig-body)
+ *
+ * @code
+ * X = | R T | X' = | R' -R'T |
+ * | 0 1 | | 0 1 |
+ * @endcode
+ *
+ * @param[in] m matrix
+ * @returns destination matrix
+ */
+CGLM_INLINE
+mat4s
+glms_inv_tr(mat4s m){
+ glm_inv_tr(m.raw);
+ return m;
+}
+#endif /* cglms_affine_mat_h */
diff --git a/include/cglm/struct/affine-post.h b/include/cglm/struct/affine-post.h
new file mode 100644
index 0000000..e155660
--- /dev/null
+++ b/include/cglm/struct/affine-post.h
@@ -0,0 +1,184 @@
+/*
+ * 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_translated(mat4s m, vec3s v);
+ CGLM_INLINE mat4s glms_translated_x(mat4s m, float x);
+ CGLM_INLINE mat4s glms_translated_y(mat4s m, float y);
+ CGLM_INLINE mat4s glms_translated_z(mat4s m, float z);
+ CGLM_INLINE mat4s glms_rotated_x(mat4s m, float angle);
+ CGLM_INLINE mat4s glms_rotated_y(mat4s m, float angle);
+ CGLM_INLINE mat4s glms_rotated_z(mat4s m, float angle);
+ CGLM_INLINE mat4s glms_rotated(mat4s m, float angle, vec3s axis);
+ CGLM_INLINE mat4s glms_rotated_at(mat4s m, vec3s pivot, float angle, vec3s axis);
+ CGLM_INLINE mat4s glms_spinned(mat4s m, float angle, vec3s axis);
+ */
+
+#ifndef cglms_affines_post_h
+#define cglms_affines_post_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 transform
+ * @param[in] v translate vector [x, y, z]
+ * @returns affine transform
+ */
+CGLM_INLINE
+mat4s
+glms_translated(mat4s m, vec3s v) {
+ glm_translated(m.raw, v.raw);
+ return m;
+}
+
+/*!
+ * @brief translate existing transform matrix by x factor
+ *
+ * @param[in] m affine transform
+ * @param[in] x x factor
+ * @returns affine transform
+ */
+CGLM_INLINE
+mat4s
+glms_translated_x(mat4s m, float x) {
+ glm_translated_x(m.raw, x);
+ return m;
+}
+
+/*!
+ * @brief translate existing transform matrix by y factor
+ *
+ * @param[in] m affine transform
+ * @param[in] y y factor
+ * @returns affine transform
+ */
+CGLM_INLINE
+mat4s
+glms_translated_y(mat4s m, float y) {
+ glm_translated_y(m.raw, y);
+ return m;
+}
+
+/*!
+ * @brief translate existing transform matrix by z factor
+ *
+ * @param[in] m affine transform
+ * @param[in] z z factor
+ * @returns affine transform
+ */
+CGLM_INLINE
+mat4s
+glms_translated_z(mat4s m, float z) {
+ glm_translated_z(m.raw, z);
+ return m;
+}
+
+/*!
+ * @brief rotate existing transform matrix around X axis by angle
+ * and store result in dest
+ *
+ * @param[in] m affine transform
+ * @param[in] angle angle (radians)
+ * @returns rotated matrix
+ */
+CGLM_INLINE
+mat4s
+glms_rotated_x(mat4s m, float angle) {
+ mat4s r;
+ glm_rotated_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 transform
+ * @param[in] angle angle (radians)
+ * @returns rotated matrix
+ */
+CGLM_INLINE
+mat4s
+glms_rotated_y(mat4s m, float angle) {
+ mat4s r;
+ glm_rotated_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 transform
+ * @param[in] angle angle (radians)
+ * @returns rotated matrix
+ */
+CGLM_INLINE
+mat4s
+glms_rotated_z(mat4s m, float angle) {
+ mat4s r;
+ glm_rotated_z(m.raw, angle, r.raw);
+ return r;
+}
+
+/*!
+ * @brief rotate existing transform matrix around given axis by angle
+ *
+ * @param[in] m affine transform
+ * @param[in] angle angle (radians)
+ * @param[in] axis axis
+ * @returns affine transform
+ */
+CGLM_INLINE
+mat4s
+glms_rotated(mat4s m, float angle, vec3s axis) {
+ glm_rotated(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 transform
+ * @param[in] pivot rotation center
+ * @param[in] angle angle (radians)
+ * @param[in] axis axis
+ * @returns affine transform
+ */
+CGLM_INLINE
+mat4s
+glms_rotated_at(mat4s m, vec3s pivot, float angle, vec3s axis) {
+ glm_rotated_at(m.raw, pivot.raw, angle, axis.raw);
+ return m;
+}
+
+/*!
+ * @brief rotate existing transform matrix around given axis by angle around self (doesn't affected by position)
+ *
+ * @param[in] m affine transform
+ * @param[in] angle angle (radians)
+ * @param[in] axis axis
+ * @returns affine transform
+ */
+CGLM_INLINE
+mat4s
+glms_spinned(mat4s m, float angle, vec3s axis) {
+ glm_spinned(m.raw, angle, axis.raw);
+ return m;
+}
+
+#endif /* cglms_affines_post_h */
diff --git a/include/cglm/struct/affine-pre.h b/include/cglm/struct/affine-pre.h
new file mode 100644
index 0000000..e323ffa
--- /dev/null
+++ b/include/cglm/struct/affine-pre.h
@@ -0,0 +1,184 @@
+/*
+ * 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_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(mat4s m, float angle, vec3s axis);
+ CGLM_INLINE mat4s glms_rotate_at(mat4s m, vec3s pivot, float angle, vec3s axis);
+ CGLM_INLINE mat4s glms_spin(mat4s m, float angle, vec3s axis);
+ */
+
+#ifndef cglms_affines_pre_h
+#define cglms_affines_pre_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 transform
+ * @param[in] v translate vector [x, y, z]
+ * @returns affine transform
+ */
+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 transform
+ * @param[in] x x factor
+ * @returns affine transform
+ */
+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 transform
+ * @param[in] y y factor
+ * @returns affine transform
+ */
+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 transform
+ * @param[in] z z factor
+ * @returns affine transform
+ */
+CGLM_INLINE
+mat4s
+glms_translate_z(mat4s m, float z) {
+ glm_translate_z(m.raw, z);
+ return m;
+}
+
+/*!
+ * @brief rotate existing transform matrix around X axis by angle
+ * and store result in dest
+ *
+ * @param[in] m affine transform
+ * @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 transform
+ * @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 transform
+ * @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 rotate existing transform matrix around given axis by angle
+ *
+ * @param[in] m affine transform
+ * @param[in] angle angle (radians)
+ * @param[in] axis axis
+ * @returns affine transform
+ */
+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 transform
+ * @param[in] pivot rotation center
+ * @param[in] angle angle (radians)
+ * @param[in] axis axis
+ * @returns affine transform
+ */
+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 rotate existing transform matrix around given axis by angle around self (doesn't affected by position)
+ *
+ * @param[in] m affine transform
+ * @param[in] angle angle (radians)
+ * @param[in] axis axis
+ * @returns affine transform
+ */
+CGLM_INLINE
+mat4s
+glms_spin(mat4s m, float angle, vec3s axis) {
+ glm_spin(m.raw, angle, axis.raw);
+ return m;
+}
+
+#endif /* cglms_affines_pre_h */
diff --git a/include/cglm/struct/affine.h b/include/cglm/struct/affine.h
new file mode 100644
index 0000000..37f11be
--- /dev/null
+++ b/include/cglm/struct/affine.h
@@ -0,0 +1,201 @@
+/*
+ * 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(vec3s pivot, float angle, vec3s axis);
+ CGLM_INLINE mat4s glms_spin(mat4s m, float angle, vec3s axis);
+ CGLM_INLINE vec3s glms_decompose_scalev(mat4s m);
+ CGLM_INLINE bool glms_uniscaled(mat4s m);
+ CGLM_INLINE void glms_decompose_rs(mat4s m, mat4s * r, vec3s * s);
+ 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"
+#include "affine-mat.h"
+
+/*!
+ * @brief creates NEW translate transform matrix by v vector
+ *
+ * @param[in] v translate vector [x, y, z]
+ * @returns affine transform
+ */
+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 transform
+ */
+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 transform
+ * @param[in] v scale vector [x, y, z]
+ * @returns affine transform
+ */
+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 transform
+ * @param[in] s scale factor
+ * @returns affine transform
+ */
+CGLM_INLINE
+mat4s
+glms_scale_uni(mat4s m, float s) {
+ glm_scale_uni(m.raw, s);
+ return m;
+}
+
+/*!
+ * @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 transform
+ */
+CGLM_INLINE
+mat4s
+glms_rotate_make(float angle, vec3s axis) {
+ mat4s m;
+ glm_rotate_make(m.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] pivot rotation center
+ * @param[in] angle angle (radians)
+ * @param[in] axis axis
+ * @returns affine transform
+ */
+CGLM_INLINE
+mat4s
+glms_rotate_atm(vec3s pivot, float angle, vec3s axis) {
+ mat4s m;
+ 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 transform
+ * @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);
+}
+
+#include "affine-pre.h"
+#include "affine-post.h"
+
+#endif /* cglms_affines_h */
diff --git a/include/cglm/struct/affine2d.h b/include/cglm/struct/affine2d.h
new file mode 100644
index 0000000..ade7c32
--- /dev/null
+++ b/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 transform
+ * @param[in] v translate vector [x, y]
+ * @returns affine transform
+ */
+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 transform
+ * @param[in] x x factor
+ * @returns affine transform
+ */
+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 transform
+ * @param[in] y y factor
+ * @returns affine transform
+ */
+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 transform
+ */
+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 transform
+ */
+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 transform
+ * @param[in] v scale vector [x, y, z]
+ * @returns affine transform
+ */
+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 transform
+ * @param[in] s scale factor
+ * @returns affine transform
+ */
+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 transform
+ */
+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 transform
+ * @param[in] angle angle (radians)
+ * @returns affine transform
+ */
+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 transform
+ * @param[in] angle angle (radians)
+ * @returns affine transform
+ */
+CGLM_INLINE
+mat3s
+glms_rotate2d_to(mat3s m, float angle) {
+ glm_rotate2d(m.raw, angle);
+ return m;
+}
+
+#endif /* cglms_affine2ds_h */
diff --git a/include/cglm/struct/box.h b/include/cglm/struct/box.h
new file mode 100644
index 0000000..ac32328
--- /dev/null
+++ b/include/cglm/struct/box.h
@@ -0,0 +1,259 @@
+/*
+ * 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"
+
+/* api definition */
+#define glms_aabb_(NAME) CGLM_STRUCTAPI(aabb, NAME)
+
+/*!
+ * @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 getting 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 getting 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 minimum 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/include/cglm/struct/cam.h b/include/cglm/struct/cam.h
new file mode 100644
index 0000000..ab6cbbb
--- /dev/null
+++ b/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 / bottom 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/include/cglm/struct/clipspace/ortho_lh_no.h b/include/cglm/struct/clipspace/ortho_lh_no.h
new file mode 100644
index 0000000..a743fdf
--- /dev/null
+++ b/include/cglm/struct/clipspace/ortho_lh_no.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
+ */
+
+/*
+ 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"
+#include "../vec3.h"
+#include "../../clipspace/ortho_lh_no.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/include/cglm/struct/clipspace/ortho_lh_zo.h b/include/cglm/struct/clipspace/ortho_lh_zo.h
new file mode 100644
index 0000000..4f15656
--- /dev/null
+++ b/include/cglm/struct/clipspace/ortho_lh_zo.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
+ */
+
+/*
+ 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"
+#include "../vec3.h"
+#include "../../clipspace/ortho_lh_zo.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/include/cglm/struct/clipspace/ortho_rh_no.h b/include/cglm/struct/clipspace/ortho_rh_no.h
new file mode 100644
index 0000000..ecb4d32
--- /dev/null
+++ b/include/cglm/struct/clipspace/ortho_rh_no.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
+ */
+
+/*
+ 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"
+#include "../vec3.h"
+#include "../../clipspace/ortho_rh_no.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/include/cglm/struct/clipspace/ortho_rh_zo.h b/include/cglm/struct/clipspace/ortho_rh_zo.h
new file mode 100644
index 0000000..2d50ee1
--- /dev/null
+++ b/include/cglm/struct/clipspace/ortho_rh_zo.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
+ */
+
+/*
+ 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"
+#include "../vec3.h"
+#include "../../clipspace/ortho_rh_zo.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/include/cglm/struct/clipspace/persp_lh_no.h b/include/cglm/struct/clipspace/persp_lh_no.h
new file mode 100644
index 0000000..bc35ca0
--- /dev/null
+++ b/include/cglm/struct/clipspace/persp_lh_no.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
+ */
+
+/*
+ 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"
+#include "../../clipspace/persp_lh_no.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 / bottom 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/include/cglm/struct/clipspace/persp_lh_zo.h b/include/cglm/struct/clipspace/persp_lh_zo.h
new file mode 100644
index 0000000..29af065
--- /dev/null
+++ b/include/cglm/struct/clipspace/persp_lh_zo.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
+ */
+
+/*
+ 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"
+#include "../../clipspace/persp_lh_zo.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 / bottom 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/include/cglm/struct/clipspace/persp_rh_no.h b/include/cglm/struct/clipspace/persp_rh_no.h
new file mode 100644
index 0000000..7120fdf
--- /dev/null
+++ b/include/cglm/struct/clipspace/persp_rh_no.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
+ */
+
+/*
+ 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"
+#include "../../clipspace/persp_rh_no.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 / bottom 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/include/cglm/struct/clipspace/persp_rh_zo.h b/include/cglm/struct/clipspace/persp_rh_zo.h
new file mode 100644
index 0000000..e3585a2
--- /dev/null
+++ b/include/cglm/struct/clipspace/persp_rh_zo.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
+ */
+
+/*
+ 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"
+#include "../../clipspace/persp_rh_zo.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 / bottom 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/include/cglm/struct/clipspace/project_no.h b/include/cglm/struct/clipspace/project_no.h
new file mode 100644
index 0000000..1a28d47
--- /dev/null
+++ b/include/cglm/struct/clipspace/project_no.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE vec3s glms_unprojecti_no(vec3s pos, mat4s invMat, vec4s vp)
+ CGLM_INLINE vec3s glms_project_no(vec3s pos, mat4s m, vec4s vp)
+ CGLM_INLINE float glms_project_z_no(vec3s v, mat4s m)
+ */
+
+#ifndef cglms_project_no_h
+#define cglms_project_no_h
+
+#include "../../common.h"
+#include "../../types-struct.h"
+#include "../../plane.h"
+#include "../../cam.h"
+#include "../../clipspace/project_no.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_no(vec3s pos, mat4s invMat, vec4s vp) {
+ vec3s dest;
+ glm_unprojecti_no(pos.raw, invMat.raw, vp.raw, dest.raw);
+ return 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]
+ *
+ * @returns projected coordinates
+ */
+CGLM_INLINE
+vec3s
+glms_project_no(vec3s pos, mat4s m, vec4s vp) {
+ vec3s dest;
+ glm_project_no(pos.raw, m.raw, vp.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief map object's z coordinate to window coordinates
+ *
+ * Computing MVP:
+ * glm_mat4_mul(proj, view, viewProj);
+ * glm_mat4_mul(viewProj, model, MVP);
+ *
+ * @param[in] v object coordinates
+ * @param[in] m MVP matrix
+ *
+ * @returns projected z coordinate
+ */
+CGLM_INLINE
+float
+glms_project_z_no(vec3s v, mat4s m) {
+ return glm_project_z_no(v.raw, m.raw);
+}
+
+#endif /* cglms_project_rh_no_h */
diff --git a/include/cglm/struct/clipspace/project_zo.h b/include/cglm/struct/clipspace/project_zo.h
new file mode 100644
index 0000000..13065f1
--- /dev/null
+++ b/include/cglm/struct/clipspace/project_zo.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE vec3s glms_unprojecti_no(vec3s pos, mat4s invMat, vec4s vp)
+ CGLM_INLINE vec3s glms_project_no(vec3s pos, mat4s m, vec4s vp)
+ CGLM_INLINE float glms_project_z_zo(vec3s v, mat4s m)
+ */
+
+#ifndef cglms_project_zo_h
+#define cglms_project_zo_h
+
+#include "../../common.h"
+#include "../../types-struct.h"
+#include "../../plane.h"
+#include "../../cam.h"
+#include "../../clipspace/project_zo.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_zo(vec3s pos, mat4s invMat, vec4s vp) {
+ vec3s dest;
+ glm_unprojecti_zo(pos.raw, invMat.raw, vp.raw, dest.raw);
+ return 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]
+ *
+ * @returns projected coordinates
+ */
+CGLM_INLINE
+vec3s
+glms_project_zo(vec3s pos, mat4s m, vec4s vp) {
+ vec3s dest;
+ glm_project_zo(pos.raw, m.raw, vp.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief map object's z coordinate to window coordinates
+ *
+ * Computing MVP:
+ * glm_mat4_mul(proj, view, viewProj);
+ * glm_mat4_mul(viewProj, model, MVP);
+ *
+ * @param[in] v object coordinates
+ * @param[in] m MVP matrix
+ *
+ * @returns projected z coordinate
+ */
+CGLM_INLINE
+float
+glms_project_z_zo(vec3s v, mat4s m) {
+ return glm_project_z_zo(v.raw, m.raw);
+}
+
+#endif /* cglm_project_zo_h */
diff --git a/include/cglm/struct/clipspace/view_lh_no.h b/include/cglm/struct/clipspace/view_lh_no.h
new file mode 100644
index 0000000..e4ca5ba
--- /dev/null
+++ b/include/cglm/struct/clipspace/view_lh_no.h
@@ -0,0 +1,89 @@
+/*
+ * 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_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"
+#include "../../clipspace/view_lh_no.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/include/cglm/struct/clipspace/view_lh_zo.h b/include/cglm/struct/clipspace/view_lh_zo.h
new file mode 100644
index 0000000..ac1ada9
--- /dev/null
+++ b/include/cglm/struct/clipspace/view_lh_zo.h
@@ -0,0 +1,89 @@
+/*
+ * 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_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"
+#include "../../clipspace/view_lh_zo.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/include/cglm/struct/clipspace/view_rh_no.h b/include/cglm/struct/clipspace/view_rh_no.h
new file mode 100644
index 0000000..99b03c3
--- /dev/null
+++ b/include/cglm/struct/clipspace/view_rh_no.h
@@ -0,0 +1,89 @@
+/*
+ * 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_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"
+#include "../../clipspace/view_rh_no.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/include/cglm/struct/clipspace/view_rh_zo.h b/include/cglm/struct/clipspace/view_rh_zo.h
new file mode 100644
index 0000000..14ffe32
--- /dev/null
+++ b/include/cglm/struct/clipspace/view_rh_zo.h
@@ -0,0 +1,89 @@
+/*
+ * 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_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"
+#include "../../clipspace/view_rh_zo.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/include/cglm/struct/color.h b/include/cglm/struct/color.h
new file mode 100644
index 0000000..3ce78da
--- /dev/null
+++ b/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/include/cglm/struct/curve.h b/include/cglm/struct/curve.h
new file mode 100644
index 0000000..53ea359
--- /dev/null
+++ b/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/include/cglm/struct/euler.h b/include/cglm/struct/euler.h
new file mode 100644
index 0000000..19697f7
--- /dev/null
+++ b/include/cglm/struct/euler.h
@@ -0,0 +1,249 @@
+/*
+ * 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 function, 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)
+ CGLM_INLINE versors glms_euler_xyz_quat(vec3s angles)
+ CGLM_INLINE versors glms_euler_xzy_quat(vec3s angles)
+ CGLM_INLINE versors glms_euler_yxz_quat(vec3s angles)
+ CGLM_INLINE versors glms_euler_yzx_quat(vec3s angles)
+ CGLM_INLINE versors glms_euler_zxy_quat(vec3s angles)
+ CGLM_INLINE versors glms_euler_zyx_quat(vec3s angles)
+ */
+
+#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;
+}
+
+/*!
+ * @brief creates NEW quaternion using rotation angles and does
+ * rotations in x y z order (roll pitch yaw)
+ *
+ * @param[in] angles angles x y z (radians)
+ * @returns quaternion
+ */
+CGLM_INLINE
+versors
+glms_euler_xyz_quat(vec3s angles) {
+ versors dest;
+ glm_euler_xyz_quat(angles.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief creates NEW quaternion using rotation angles and does
+ * rotations in x z y order (roll yaw pitch)
+ *
+ * @param[in] angles angles x y z (radians)
+ * @returns quaternion
+ */
+CGLM_INLINE
+versors
+glms_euler_xzy_quat(vec3s angles) {
+ versors dest;
+ glm_euler_xzy_quat(angles.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief creates NEW quaternion using rotation angles and does
+ * rotations in y x z order (pitch roll yaw)
+ *
+ * @param[in] angles angles x y z (radians)
+ * @returns quaternion
+ */
+CGLM_INLINE
+versors
+glms_euler_yxz_quat(vec3s angles) {
+ versors dest;
+ glm_euler_yxz_quat(angles.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief creates NEW quaternion using rotation angles and does
+ * rotations in y z x order (pitch yaw roll)
+ *
+ * @param[in] angles angles x y z (radians)
+ * @returns quaternion
+ */
+CGLM_INLINE
+versors
+glms_euler_yzx_quat(vec3s angles) {
+ versors dest;
+ glm_euler_yzx_quat(angles.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief creates NEW quaternion using rotation angles and does
+ * rotations in z x y order (yaw roll pitch)
+ *
+ * @param[in] angles angles x y z (radians)
+ * @returns quaternion
+ */
+CGLM_INLINE
+versors
+glms_euler_zxy_quat(vec3s angles) {
+ versors dest;
+ glm_euler_zxy_quat(angles.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief creates NEW quaternion using rotation angles and does
+ * rotations in z y x order (yaw pitch roll)
+ *
+ * @param[in] angles angles x y z (radians)
+ * @returns quaternion
+ */
+CGLM_INLINE
+versors
+glms_euler_zyx_quat(vec3s angles) {
+ versors dest;
+ glm_euler_zyx_quat(angles.raw, dest.raw);
+ return dest;
+}
+
+
+#endif /* cglms_euler_h */
diff --git a/include/cglm/struct/frustum.h b/include/cglm/struct/frustum.h
new file mode 100644
index 0000000..81b5b7b
--- /dev/null
+++ b/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/include/cglm/struct/handed/euler_to_quat_lh.h b/include/cglm/struct/handed/euler_to_quat_lh.h
new file mode 100644
index 0000000..3964e51
--- /dev/null
+++ b/include/cglm/struct/handed/euler_to_quat_lh.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
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glms_euler_xyz_quat_lh(vec3 angles, versor dest);
+ CGLM_INLINE void glms_euler_xzy_quat_lh(vec3 angles, versor dest);
+ CGLM_INLINE void glms_euler_yxz_quat_lh(vec3 angles, versor dest);
+ CGLM_INLINE void glms_euler_yzx_quat_lh(vec3 angles, versor dest);
+ CGLM_INLINE void glms_euler_zxy_quat_lh(vec3 angles, versor dest);
+ CGLM_INLINE void glms_euler_zyx_quat_lh(vec3 angles, versor dest);
+ */
+
+#ifndef cglms_euler_to_quat_lh_h
+#define cglms_euler_to_quat_lh_h
+
+#include "../common.h"
+
+
+/*!
+ * @brief creates NEW quaternion using rotation angles and does
+ * rotations in x y z order in left hand (roll pitch yaw)
+ *
+ * @param[in] angles angles x y z (radians)
+ * @param[out] dest quaternion
+ */
+CGLM_INLINE
+versors
+glms_euler_xyz_quat_lh(vec3s angles) {
+ versors dest;
+ glm_euler_xyz_quat_lh(angles.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief creates NEW quaternion using rotation angles and does
+ * rotations in x z y order in left hand (roll yaw pitch)
+ *
+ * @param[in] angles angles x y z (radians)
+ * @param[out] dest quaternion
+ */
+CGLM_INLINE
+versors
+glms_euler_xzy_quat_lh(vec3s angles) {
+ versors dest;
+ glm_euler_xzy_quat_lh(angles.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief creates NEW quaternion using rotation angles and does
+ * rotations in y x z order in left hand (pitch roll yaw)
+ *
+ * @param[in] angles angles x y z (radians)
+ * @param[out] dest quaternion
+ */
+CGLM_INLINE
+versors
+glms_euler_yxz_quat_lh(vec3s angles) {
+ versors dest;
+ glm_euler_yxz_quat_lh(angles.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief creates NEW quaternion using rotation angles and does
+ * rotations in y z x order in left hand (pitch yaw roll)
+ *
+ * @param[in] angles angles x y z (radians)
+ * @param[out] dest quaternion
+ */
+CGLM_INLINE
+versors
+glms_euler_yzx_quat_lh(vec3s angles) {
+ versors dest;
+ glm_euler_yzx_quat_lh(angles.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief creates NEW quaternion using rotation angles and does
+ * rotations in z x y order in left hand (yaw roll pitch)
+ *
+ * @param[in] angles angles x y z (radians)
+ * @param[out] dest quaternion
+ */
+CGLM_INLINE
+versors
+glms_euler_zxy_quat_lh(vec3s angles) {
+ versors dest;
+ glm_euler_zxy_quat_lh(angles.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief creates NEW quaternion using rotation angles and does
+ * rotations in z y x order in left hand (yaw pitch roll)
+ *
+ * @param[in] angles angles x y z (radians)
+ * @param[out] dest quaternion
+ */
+CGLM_INLINE
+versors
+glms_euler_zyx_quat_lh(vec3s angles) {
+ versors dest;
+ glm_euler_zyx_quat_lh(angles.raw, dest.raw);
+ return dest;
+}
+
+
+#endif /* cglms_euler_to_quat_lh_h */
diff --git a/include/cglm/struct/handed/euler_to_quat_rh.h b/include/cglm/struct/handed/euler_to_quat_rh.h
new file mode 100644
index 0000000..6c7f400
--- /dev/null
+++ b/include/cglm/struct/handed/euler_to_quat_rh.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
+ */
+
+/*
+ Functions:
+ CGLM_INLINE void glms_euler_xyz_quat_rh(vec3 angles, versor dest);
+ CGLM_INLINE void glms_euler_xzy_quat_rh(vec3 angles, versor dest);
+ CGLM_INLINE void glms_euler_yxz_quat_rh(vec3 angles, versor dest);
+ CGLM_INLINE void glms_euler_yzx_quat_rh(vec3 angles, versor dest);
+ CGLM_INLINE void glms_euler_zxy_quat_rh(vec3 angles, versor dest);
+ CGLM_INLINE void glms_euler_zyx_quat_rh(vec3 angles, versor dest);
+ */
+
+#ifndef cglms_euler_to_quat_rh_h
+#define cglms_euler_to_quat_rh_h
+
+#include "../common.h"
+
+
+/*!
+ * @brief creates NEW quaternion using rotation angles and does
+ * rotations in x y z order in right hand (roll pitch yaw)
+ *
+ * @param[in] angles angles x y z (radians)
+ * @param[out] dest quaternion
+ */
+CGLM_INLINE
+versors
+glms_euler_xyz_quat_rh(vec3s angles) {
+ versors dest;
+ glm_euler_xyz_quat_rh(angles.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief creates NEW quaternion using rotation angles and does
+ * rotations in x z y order in right hand (roll yaw pitch)
+ *
+ * @param[in] angles angles x y z (radians)
+ * @param[out] dest quaternion
+ */
+CGLM_INLINE
+versors
+glms_euler_xzy_quat_rh(vec3s angles) {
+ versors dest;
+ glm_euler_xzy_quat_rh(angles.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief creates NEW quaternion using rotation angles and does
+ * rotations in y x z order in right hand (pitch roll yaw)
+ *
+ * @param[in] angles angles x y z (radians)
+ * @param[out] dest quaternion
+ */
+CGLM_INLINE
+versors
+glms_euler_yxz_quat_rh(vec3s angles) {
+ versors dest;
+ glm_euler_yxz_quat_rh(angles.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief creates NEW quaternion using rotation angles and does
+ * rotations in y z x order in right hand (pitch yaw roll)
+ *
+ * @param[in] angles angles x y z (radians)
+ * @param[out] dest quaternion
+ */
+CGLM_INLINE
+versors
+glms_euler_yzx_quat_rh(vec3s angles) {
+ versors dest;
+ glm_euler_yzx_quat_rh(angles.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief creates NEW quaternion using rotation angles and does
+ * rotations in z x y order in right hand (yaw roll pitch)
+ *
+ * @param[in] angles angles x y z (radians)
+ * @param[out] dest quaternion
+ */
+CGLM_INLINE
+versors
+glms_euler_zxy_quat_rh(vec3s angles) {
+ versors dest;
+ glm_euler_zxy_quat_rh(angles.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief creates NEW quaternion using rotation angles and does
+ * rotations in z y x order in right hand (yaw pitch roll)
+ *
+ * @param[in] angles angles x y z (radians)
+ * @param[out] dest quaternion
+ */
+CGLM_INLINE
+versors
+glms_euler_zyx_quat_rh(vec3s angles) {
+ versors dest;
+ glm_euler_zyx_quat_rh(angles.raw, dest.raw);
+ return dest;
+}
+
+
+#endif /* cglms_euler_to_quat_rh_h */
diff --git a/include/cglm/struct/io.h b/include/cglm/struct/io.h
new file mode 100644
index 0000000..900c2a8
--- /dev/null
+++ b/include/cglm/struct/io.h
@@ -0,0 +1,107 @@
+/*
+ * 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 glms_mat4_print(mat4s matrix, FILE *ostream);
+ CGLM_INLINE void glms_mat3_print(mat3s matrix, FILE *ostream);
+ CGLM_INLINE void glms_vec4_print(vec4s vec, FILE *ostream);
+ CGLM_INLINE void glms_ivec4_print(ivec3s vec, FILE *ostream);
+ CGLM_INLINE void glms_vec3_print(vec3s vec, FILE *ostream);
+ CGLM_INLINE void glms_ivec3_print(ivec3s vec, FILE *ostream);
+ CGLM_INLINE void glms_vec2_print(vec2s vec, FILE *ostream);
+ CGLM_INLINE void glms_ivec2_print(ivec3s vec, FILE *ostream);
+ CGLM_INLINE void glms_versor_print(versor vec, FILE *ostream);
+ CGLM_INLINE void glms_aabb_print(vec3s bbox[2], const char *tag, 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_ivec4_print(ivec4s vec,
+ FILE * __restrict ostream) {
+ glm_ivec4_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_vec2_print(vec2s vec,
+ FILE * __restrict ostream) {
+ glm_vec2_print(vec.raw, ostream);
+}
+
+CGLM_INLINE
+void
+glms_ivec2_print(ivec2s vec,
+ FILE * __restrict ostream) {
+ glm_ivec2_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/include/cglm/struct/ivec2.h b/include/cglm/struct/ivec2.h
new file mode 100644
index 0000000..d53c9f6
--- /dev/null
+++ b/include/cglm/struct/ivec2.h
@@ -0,0 +1,708 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Macros:
+ GLMS_IVEC2_ONE_INIT
+ GLMS_IVEC2_ZERO_INIT
+ GLMS_IVEC2_ONE
+ GLMS_IVEC2_ZERO
+
+ Functions:
+ CGLM_INLINE ivec2s glms_ivec2(int * __restrict v)
+ CGLM_INLINE void glms_ivec2_pack(ivec2s dst[], ivec2s src[], size_t len)
+ CGLM_INLINE void glms_ivec2_unpack(ivec2 dst[], ivec2 src[], size_t len)
+ CGLM_INLINE ivec2s glms_ivec2_zero(ivec2s v)
+ CGLM_INLINE ivec2s glms_ivec2_one(ivec2s v)
+ CGLM_INLINE int glms_ivec2_dot(ivec2s a, ivec2s b)
+ CGLM_INLINE int glms_ivec2_cross(ivec2s a, ivec2s b)
+ CGLM_INLINE ivec2s glms_ivec2_add(ivec2s a, ivec2s b)
+ CGLM_INLINE ivec2s glms_ivec2_adds(ivec2s v, int s)
+ CGLM_INLINE ivec2s glms_ivec2_sub(ivec2s a, ivec2s b)
+ CGLM_INLINE ivec2s glms_ivec2_subs(ivec2s v, int s)
+ CGLM_INLINE ivec2s glms_ivec2_mul(ivec2s a, ivec2s b)
+ CGLM_INLINE ivec2s glms_ivec2_scale(ivec2s v, int s)
+ CGLM_INLINE ivec2s glms_ivec2_div(ivec2s a, ivec2s b)
+ CGLM_INLINE ivec2s glms_ivec2_divs(ivec2s v, int s)
+ CGLM_INLINE ivec2s glms_ivec2_mod(ivec2s a, ivec2s b)
+ CGLM_INLINE ivec2s glms_ivec2_addadd(ivec2s a, ivec2s b)
+ CGLM_INLINE ivec2s glms_ivec2_addadds(ivec2s a, int s)
+ CGLM_INLINE ivec2s glms_ivec2_subadd(ivec2s a, ivec2s b)
+ CGLM_INLINE ivec2s glms_ivec2_subadds(ivec2s a, int s)
+ CGLM_INLINE ivec2s glms_ivec2_muladd(ivec2s a, ivec2s b)
+ CGLM_INLINE ivec2s glms_ivec2_muladds(ivec2s a, int s)
+ CGLM_INLINE ivec2s glms_ivec2_maxadd(ivec2s a, ivec2s b)
+ CGLM_INLINE ivec2s glms_ivec2_minadd(ivec2s a, ivec2s b)
+ CGLM_INLINE ivec2s glms_ivec2_subsub(ivec2s a, ivec2s b)
+ CGLM_INLINE ivec2s glms_ivec2_subsubs(ivec2s a, int s)
+ CGLM_INLINE ivec2s glms_ivec2_addsub(ivec2s a, ivec2s b)
+ CGLM_INLINE ivec2s glms_ivec2_addsubs(ivec2s a, int s)
+ CGLM_INLINE ivec2s glms_ivec2_mulsub(ivec2s a, ivec2s b)
+ CGLM_INLINE ivec2s glms_ivec2_mulsubs(ivec2s a, int s)
+ CGLM_INLINE ivec2s glms_ivec2_maxsub(ivec2s a, ivec2s b)
+ CGLM_INLINE ivec2s glms_ivec2_minsub(ivec2s a, ivec2s b)
+ CGLM_INLINE int glms_ivec2_distance2(ivec2s a, ivec2s b)
+ CGLM_INLINE float glms_ivec2_distance(ivec2s a, ivec2s b)
+ CGLM_INLINE ivec2s glms_ivec2_fill(int val)
+ CGLM_INLINE bool glms_ivec2_eq(ivec2s v, int val);
+ CGLM_INLINE bool glms_ivec2_eqv(ivec2s a, ivec2s b);
+ CGLM_INLINE ivec2s glms_ivec2_maxv(ivec2s a, ivec2s b)
+ CGLM_INLINE ivec2s glms_ivec2_minv(ivec2s a, ivec2s b)
+ CGLM_INLINE ivec2s glms_ivec2_clamp(ivec2s v, int minVal, int maxVal)
+ CGLM_INLINE ivec2s glms_ivec2_abs(ivec2s v)
+ */
+
+#ifndef cglms_ivec2_h
+#define cglms_ivec2_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../ivec2.h"
+
+#define glms_ivec2_(NAME) CGLM_STRUCTAPI(ivec2, NAME)
+
+#define GLMS_IVEC2_ONE_INIT {GLM_IVEC2_ONE_INIT}
+#define GLMS_IVEC2_ZERO_INIT {GLM_IVEC2_ZERO_INIT}
+
+#define GLMS_IVEC2_ONE ((ivec2s)GLMS_IVEC2_ONE_INIT)
+#define GLMS_IVEC2_ZERO ((ivec2s)GLMS_IVEC2_ZERO_INIT)
+
+/*!
+ * @brief init ivec2 using ivec3 or ivec4
+ *
+ * @param[in] v vector
+ * @returns destination
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2(int * __restrict v) {
+ ivec2s r;
+ glm_ivec2(v, r.raw);
+ return r;
+}
+
+/*!
+ * @brief pack an array of ivec2 into an array of ivec2s
+ *
+ * @param[out] dst array of ivec2s
+ * @param[in] src array of ivec2
+ * @param[in] len number of elements
+ */
+CGLM_INLINE
+void
+glms_ivec2_(pack)(ivec2s dst[], ivec2 src[], size_t len) {
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ glm_ivec2_copy(src[i], dst[i].raw);
+ }
+}
+
+/*!
+ * @brief unpack an array of ivec2s into an array of ivec2
+ *
+ * @param[out] dst array of ivec2
+ * @param[in] src array of ivec2s
+ * @param[in] len number of elements
+ */
+CGLM_INLINE
+void
+glms_ivec2_(unpack)(ivec2 dst[], ivec2s src[], size_t len) {
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ glm_ivec2_copy(src[i].raw, dst[i]);
+ }
+}
+
+/*!
+ * @brief set all members of [v] to zero
+ *
+ * @returns vector
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(zero)(void) {
+ ivec2s r;
+ glm_ivec2_zero(r.raw);
+ return r;
+}
+
+/*!
+ * @brief set all members of [v] to one
+ *
+ * @returns vector
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(one)(void) {
+ ivec2s r;
+ glm_ivec2_one(r.raw);
+ return r;
+}
+
+/*!
+ * @brief ivec2 dot product
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ *
+ * @return dot product
+ */
+CGLM_INLINE
+int
+glms_ivec2_(dot)(ivec2s a, ivec2s b) {
+ return glm_ivec2_dot(a.raw, b.raw);
+}
+
+/*!
+ * @brief ivec2 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
+int
+glms_ivec2_(cross)(ivec2s a, ivec2s b) {
+ return glm_ivec2_cross(a.raw, b.raw);
+}
+
+/*!
+ * @brief add vector [a] to vector [b] and store result in [dest]
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @returns destination
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(add)(ivec2s a, ivec2s b) {
+ ivec2s r;
+ glm_ivec2_add(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief add scalar s to vector [v] and store result in [dest]
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @returns destination
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(adds)(ivec2s v, int s) {
+ ivec2s r;
+ glm_ivec2_adds(v.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief subtract vector [b] from vector [a] and store result in [dest]
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @returns destination
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(sub)(ivec2s a, ivec2s b) {
+ ivec2s r;
+ glm_ivec2_sub(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief subtract scalar s from vector [v] and store result in [dest]
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @returns destination
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(subs)(ivec2s v, int s) {
+ ivec2s r;
+ glm_ivec2_subs(v.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief multiply vector [a] with vector [b] and store result in [dest]
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @returns destination
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(mul)(ivec2s a, ivec2s b) {
+ ivec2s r;
+ glm_ivec2_mul(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief multiply vector [a] with scalar s and store result in [dest]
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @returns destination
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(scale)(ivec2s v, int s) {
+ ivec2s r;
+ glm_ivec2_scale(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])
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(div)(ivec2s a, ivec2s b) {
+ ivec2s r;
+ glm_ivec2_div(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief div vector with scalar: d = v / s
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @returns result = (a[0]/s, a[1]/s)
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(divs)(ivec2s v, int s) {
+ ivec2s r;
+ glm_ivec2_divs(v.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief mod vector with another component-wise modulo: d = a % b
+ *
+ * @param[in] a vector 1
+ * @param[in] b vector 2
+ * @returns result = (a[0]%b[0], a[1]%b[1])
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(mod)(ivec2s a, ivec2s b) {
+ ivec2s r;
+ glm_ivec2_mod(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief add vector [a] with vector [b] and add result to vector [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[in] dest dest += (a + b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(addadd)(ivec2s a, ivec2s b, ivec2s dest) {
+ glm_ivec2_addadd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief add scalar [s] onto vector [a] and add result to vector [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a vector
+ * @param[in] s scalar
+ * @param[in] dest dest += (a + s)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(addadds)(ivec2s a, int s, ivec2s dest) {
+ glm_ivec2_addadds(a.raw, s, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief subtract vector [a] from vector [b] and add result to [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[in] dest dest += (a - b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(subadd)(ivec2s a, ivec2s b, ivec2s dest) {
+ glm_ivec2_subadd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief subtract scalar [s] from vector [a] and add result to [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a first
+ * @param[in] s scalar
+ * @param[in] dest dest += (a - s)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(subadds)(ivec2s a, int s, ivec2s dest) {
+ glm_ivec2_subadds(a.raw, s, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief multiply vector [a] with vector [b] and add result to [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[in] dest dest += (a * b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(muladd)(ivec2s a, ivec2s b, ivec2s dest) {
+ glm_ivec2_muladd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief multiply vector [a] with scalar [s] and add result to [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a vector
+ * @param[in] s scalar
+ * @param[in] dest dest += (a * s)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(muladds)(ivec2s a, int s, ivec2s dest) {
+ glm_ivec2_muladds(a.raw, s, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief add maximum of vector [a] and vector [b] to vector [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[in] dest dest += max(a, b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(maxadd)(ivec2s a, ivec2s b, ivec2s dest) {
+ glm_ivec2_maxadd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief add minimum of vector [a] and vector [b] to vector [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[in] dest dest += min(a, b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(minadd)(ivec2s a, ivec2s b, ivec2s dest) {
+ glm_ivec2_minadd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief subtract vector [a] from vector [b] and subtract result from [dest]
+ *
+ * applies -= operator so dest must be initialized
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[in] dest dest -= (a - b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(subsub)(ivec2s a, ivec2s b, ivec2s dest) {
+ glm_ivec2_subsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief subtract scalar [s] from vector [a] and subtract result from [dest]
+ *
+ * applies -= operator so dest must be initialized
+ *
+ * @param[in] a vector
+ * @param[in] s scalar
+ * @param[in] dest dest -= (a - s)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(subsubs)(ivec2s a, int s, ivec2s dest) {
+ glm_ivec2_subsubs(a.raw, s, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief add vector [a] to vector [b] and subtract the result from [dest]
+ *
+ * applies -= operator so dest must be initialized
+ *
+ * @param[in] a vector
+ * @param[in] b scalar
+ * @param[in] dest dest -= (a + b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(addsub)(ivec2s a, ivec2s b, ivec2s dest) {
+ glm_ivec2_addsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief add scalar [s] to vector [a] and subtract the result from [dest]
+ *
+ * applies -= operator so dest must be initialized
+ *
+ * @param[in] a vector
+ * @param[in] s scalar
+ * @param[in] dest dest -= (a + b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(addsubs)(ivec2s a, int s, ivec2s dest) {
+ glm_ivec2_addsubs(a.raw, s, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief multiply vector [a] and vector [b] and subtract the result from [dest]
+ *
+ * applies -= operator so dest must be initialized
+ *
+ * @param[in] a vector
+ * @param[in] b scalar
+ * @param[in] dest dest -= (a * b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(mulsub)(ivec2s a, ivec2s b, ivec2s dest) {
+ glm_ivec2_mulsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief multiply vector [a] with scalar [s] and subtract the result from [dest]
+ *
+ * applies -= operator so dest must be initialized
+ *
+ * @param[in] a vector
+ * @param[in] s scalar
+ * @param[in] dest dest -= (a * s)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(mulsubs)(ivec2s a, int s, ivec2s dest) {
+ glm_ivec2_mulsubs(a.raw, s, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief subtract maximum of vector [a] and vector [b] from vector [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[in] dest dest -= max(a, b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(maxsub)(ivec2s a, ivec2s b, ivec2s dest) {
+ glm_ivec2_maxsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief subtract minimum of vector [a] and vector [b] from vector [dest]
+ *
+ * applies -= operator so dest must be initialized
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[in] dest dest -= min(a, b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(minsub)(ivec2s a, ivec2s b, ivec2s dest) {
+ glm_ivec2_minsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @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
+glms_ivec2_(distance2)(ivec2s a, ivec2s b) {
+ return glm_ivec2_distance2(a.raw, b.raw);
+}
+
+/*!
+ * @brief distance between two vectors
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @return returns distance
+ */
+CGLM_INLINE
+float
+glms_ivec2_(distance)(ivec2s a, ivec2s b) {
+ return glm_ivec2_distance(a.raw, b.raw);
+}
+
+/*!
+ * @brief fill a vector with specified value
+ *
+ * @param[in] val value
+ * @returns dest
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(fill)(int val) {
+ ivec2s r;
+ glm_ivec2_fill(r.raw, val);
+ return r;
+}
+
+/*!
+ * @brief check if vector is equal to value
+ *
+ * @param[in] v vector
+ * @param[in] val value
+ */
+CGLM_INLINE
+bool
+glms_ivec2_(eq)(ivec2s v, int val) {
+ return glm_ivec2_eq(v.raw, val);
+}
+
+/*!
+ * @brief check if vector is equal to another
+ *
+ * @param[in] a vector
+ * @param[in] b vector
+ */
+CGLM_INLINE
+bool
+glms_ivec2_(eqv)(ivec2s a, ivec2s b) {
+ return glm_ivec2_eqv(a.raw, b.raw);
+}
+
+/*!
+ * @brief set each member of dest to greater of vector a and b
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @returns destination
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(maxv)(ivec2s a, ivec2s b) {
+ ivec2s r;
+ glm_ivec2_maxv(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief set each member of dest to lesser of vector a and b
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @returns destination
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(minv)(ivec2s a, ivec2s b) {
+ ivec2s r;
+ glm_ivec2_minv(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief clamp each member of [v] between minVal and maxVal (inclusive)
+ *
+ * @param[in] v vector
+ * @param[in] minVal minimum value
+ * @param[in] maxVal maximum value
+ * @returns clamped vector
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(clamp)(ivec2s v, int minVal, int maxVal) {
+ glm_ivec2_clamp(v.raw, minVal, maxVal);
+ return v;
+}
+
+/*!
+ * @brief absolute value of v
+ *
+ * @param[in] v vector
+ * @returns destination
+ */
+CGLM_INLINE
+ivec2s
+glms_ivec2_(abs)(ivec2s v) {
+ ivec2s r;
+ glm_ivec2_abs(v.raw, r.raw);
+ return r;
+}
+
+#endif /* cglms_ivec2_h */
diff --git a/include/cglm/struct/ivec3.h b/include/cglm/struct/ivec3.h
new file mode 100644
index 0000000..c2c5f3b
--- /dev/null
+++ b/include/cglm/struct/ivec3.h
@@ -0,0 +1,725 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Macros:
+ GLMS_IVEC3_ONE_INIT
+ GLMS_IVEC3_ZERO_INIT
+ GLMS_IVEC3_ONE
+ GLMS_IVEC3_ZERO
+
+ Functions:
+ CGLM_INLINE ivec3s glms_ivec3(ivec4s v4)
+ CGLM_INLINE void glms_ivec3_pack(ivec3s dst[], ivec3 src[], size_t len)
+ CGLM_INLINE void glms_ivec3_unpack(ivec3 dst[], ivec3s src[], size_t len)
+ CGLM_INLINE ivec3s glms_ivec3_zero(void)
+ CGLM_INLINE ivec3s glms_ivec3_one(void)
+ CGLM_INLINE int glms_ivec3_dot(ivec3s a, ivec3s b)
+ CGLM_INLINE int glms_ivec3_norm2(ivec3s v)
+ CGLM_INLINE int glms_ivec3_norm(ivec3s v)
+ CGLM_INLINE ivec3s glms_ivec3_add(ivec3s a, ivec3s b)
+ CGLM_INLINE ivec3s glms_ivec3_adds(ivec3s v, int s)
+ CGLM_INLINE ivec3s glms_ivec3_sub(ivec3s a, ivec3s b)
+ CGLM_INLINE ivec3s glms_ivec3_subs(ivec3s v, int s)
+ CGLM_INLINE ivec3s glms_ivec3_mul(ivec3s a, ivec3s b)
+ CGLM_INLINE ivec3s glms_ivec3_scale(ivec3s v, int s)
+ CGLM_INLINE ivec3s glms_ivec3_div(ivec3s a, ivec3s b)
+ CGLM_INLINE ivec3s glms_ivec3_divs(ivec3s v, int s)
+ CGLM_INLINE ivec3s glms_ivec3_mod(ivec3s a, ivec3s b)
+ CGLM_INLINE ivec3s glms_ivec3_addadd(ivec3s a, ivec3s b, ivec3s dest)
+ CGLM_INLINE ivec3s glms_ivec3_addadds(ivec3s a, int s, ivec3s dest)
+ CGLM_INLINE ivec3s glms_ivec3_subadd(ivec3s a, ivec3s b, ivec3s dest)
+ CGLM_INLINE ivec3s glms_ivec3_subadds(ivec3s a, int s, ivec3s dest)
+ CGLM_INLINE ivec3s glms_ivec3_muladd(ivec3s a, ivec3s b, ivec3s dest)
+ CGLM_INLINE ivec3s glms_ivec3_muladds(ivec3s a, int s, ivec3s dest)
+ CGLM_INLINE ivec3s glms_ivec3_minadd(ivec3s a, ivec3s b, ivec3s dest)
+ CGLM_INLINE ivec3s glms_ivec3_subsub(ivec3s a, ivec3s b, ivec3s dest)
+ CGLM_INLINE ivec3s glms_ivec3_subsubs(ivec3s a, int s, ivec3s dest)
+ CGLM_INLINE ivec3s glms_ivec3_addsub(ivec3s a, ivec3s b, ivec3s dest)
+ CGLM_INLINE ivec3s glms_ivec3_addsubs(ivec3s a, int s, ivec3s dest)
+ CGLM_INLINE ivec3s glms_ivec3_mulsub(ivec3s a, ivec3s b, ivec3s dest)
+ CGLM_INLINE ivec3s glms_ivec3_mulsubs(ivec3s a, int s, ivec3s dest)
+ CGLM_INLINE ivec3s glms_ivec3_maxsub(ivec3s a, ivec3s b, ivec3s dest)
+ CGLM_INLINE ivec3s glms_ivec3_minsub(ivec3s a, ivec3s b, ivec3s dest)
+ CGLM_INLINE int glms_ivec3_distance2(ivec3s a, ivec3s b)
+ CGLM_INLINE float glms_ivec3_distance(ivec3s a, ivec3s b)
+ CGLM_INLINE ivec3s glms_ivec3_fill(int val)
+ CGLM_INLINE bool glms_ivec3_eq(ivec3s v, int val)
+ CGLM_INLINE bool glms_ivec3_eqv(ivec3s a, ivec3s b)
+ CGLM_INLINE ivec3s glms_ivec3_maxv(ivec3s a, ivec3s b)
+ CGLM_INLINE ivec3s glms_ivec3_minv(ivec3s a, ivec3s b)
+ CGLM_INLINE ivec3s glms_ivec3_clamp(ivec3s v, int minVal, int maxVal)
+ CGLM_INLINE ivec3s glms_ivec3_abs(ivec3s v)
+ */
+
+#ifndef cglms_ivec3_h
+#define cglms_ivec3_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../ivec3.h"
+
+#define glms_ivec3_(NAME) CGLM_STRUCTAPI(ivec3, NAME)
+
+#define GLMS_IVEC3_ONE_INIT {GLM_IVEC3_ONE_INIT}
+#define GLMS_IVEC3_ZERO_INIT {GLM_IVEC3_ZERO_INIT}
+
+#define GLMS_IVEC3_ONE ((ivec3s)GLMS_IVEC3_ONE_INIT)
+#define GLMS_IVEC3_ZERO ((ivec3s)GLMS_IVEC3_ZERO_INIT)
+
+/*!
+ * @brief init ivec3 using ivec4
+ *
+ * @param[in] v4 vector4
+ * @returns destination
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3(ivec4s v4) {
+ ivec3s r;
+ glm_ivec3(v4.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief pack an array of ivec3 into an array of ivec3s
+ *
+ * @param[out] dst array of ivec3s
+ * @param[in] src array of ivec3
+ * @param[in] len number of elements
+ */
+CGLM_INLINE
+void
+glms_ivec3_(pack)(ivec3s dst[], ivec3 src[], size_t len) {
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ glm_ivec3_copy(src[i], dst[i].raw);
+ }
+}
+
+/*!
+ * @brief unpack an array of ivec3s into an array of ivec3
+ *
+ * @param[out] dst array of ivec3
+ * @param[in] src array of ivec3s
+ * @param[in] len number of elements
+ */
+CGLM_INLINE
+void
+glms_ivec3_(unpack)(ivec3 dst[], ivec3s src[], size_t len) {
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ glm_ivec3_copy(src[i].raw, dst[i]);
+ }
+}
+
+/*!
+ * @brief set all members of [v] to zero
+ *
+ * @returns vector
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(zero)(void) {
+ ivec3s r;
+ glm_ivec3_zero(r.raw);
+ return r;
+}
+
+/*!
+ * @brief set all members of [v] to one
+ *
+ * @returns vector
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(one)(void) {
+ ivec3s r;
+ glm_ivec3_one(r.raw);
+ return r;
+}
+
+/*!
+ * @brief ivec3 dot product
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ *
+ * @return dot product
+ */
+CGLM_INLINE
+int
+glms_ivec3_(dot)(ivec3s a, ivec3s b) {
+ return glm_ivec3_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 function 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
+int
+glms_ivec3_(norm2)(ivec3s v) {
+ return glm_ivec3_norm2(v.raw);
+}
+
+/*!
+ * @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
+int
+glms_ivec3_(norm)(ivec3s v) {
+ return glm_ivec3_norm(v.raw);
+}
+
+/*!
+ * @brief add vector [a] to vector [b] and store result in [dest]
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @returns destination
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(add)(ivec3s a, ivec3s b) {
+ ivec3s r;
+ glm_ivec3_add(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief add scalar s to vector [v] and store result in [dest]
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @returns destination
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(adds)(ivec3s v, int s) {
+ ivec3s r;
+ glm_ivec3_adds(v.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief subtract vector [b] from vector [a] and store result in [dest]
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @returns destination
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(sub)(ivec3s a, ivec3s b) {
+ ivec3s r;
+ glm_ivec3_sub(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief subtract scalar s from vector [v] and store result in [dest]
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @returns destination
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(subs)(ivec3s v, int s) {
+ ivec3s r;
+ glm_ivec3_subs(v.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief multiply vector [a] with vector [b] and store result in [dest]
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @returns destination
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(mul)(ivec3s a, ivec3s b) {
+ ivec3s r;
+ glm_ivec3_mul(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief multiply vector [a] with scalar s and store result in [dest]
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @returns destination
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(scale)(ivec3s v, int s) {
+ ivec3s r;
+ glm_ivec3_scale(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
+ivec3s
+glms_ivec3_(div)(ivec3s a, ivec3s b) {
+ ivec3s r;
+ glm_ivec3_div(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief div vector with scalar: d = v / s
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @returns result = (a[0]/s, a[1]/s, a[2]/s)
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(divs)(ivec3s v, int s) {
+ ivec3s r;
+ glm_ivec3_divs(v.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief Element-wise modulo operation on ivec3 vectors: dest = a % b
+ *
+ * Performs element-wise modulo on each component of vectors `a` and `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
+ivec3s
+glms_ivec3_(mod)(ivec3s a, ivec3s b) {
+ ivec3s r;
+ glm_ivec3_mod(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief add vector [a] with vector [b] and add result to vector [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[in] dest dest += (a + b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(addadd)(ivec3s a, ivec3s b, ivec3s dest) {
+ glm_ivec3_addadd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief add scalar [s] onto vector [a] and add result to vector [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a vector
+ * @param[in] s scalar
+ * @param[in] dest dest += (a + s)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(addadds)(ivec3s a, int s, ivec3s dest) {
+ glm_ivec3_addadds(a.raw, s, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief subtract vector [a] from vector [b] and add result to [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[in] dest dest += (a - b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(subadd)(ivec3s a, ivec3s b, ivec3s dest) {
+ glm_ivec3_subadd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief subtract scalar [s] from vector [a] and add result to [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a first
+ * @param[in] s scalar
+ * @param[in] dest dest += (a - s)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(subadds)(ivec3s a, int s, ivec3s dest) {
+ glm_ivec3_subadds(a.raw, s, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief multiply vector [a] with vector [b] and add result to [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[in] dest dest += (a * b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(muladd)(ivec3s a, ivec3s b, ivec3s dest) {
+ glm_ivec3_muladd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief multiply vector [a] with scalar [s] and add result to [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a vector
+ * @param[in] s scalar
+ * @param[in] dest dest += (a * s)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(muladds)(ivec3s a, int s, ivec3s dest) {
+ glm_ivec3_muladds(a.raw, s, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief add maximum of vector [a] and vector [b] to vector [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[in] dest dest += max(a, b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(maxadd)(ivec3s a, ivec3s b, ivec3s dest) {
+ glm_ivec3_maxadd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief add minimum of vector [a] and vector [b] to vector [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[in] dest dest += min(a, b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(minadd)(ivec3s a, ivec3s b, ivec3s dest) {
+ glm_ivec3_minadd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief subtract vector [a] from vector [b] and subtract result from [dest]
+ *
+ * applies -= operator so dest must be initialized
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[in] dest dest -= (a - b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(subsub)(ivec3s a, ivec3s b, ivec3s dest) {
+ glm_ivec3_subsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief subtract scalar [s] from vector [a] and subtract result from [dest]
+ *
+ * applies -= operator so dest must be initialized
+ *
+ * @param[in] a vector
+ * @param[in] s scalar
+ * @param[in] dest dest -= (a - s)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(subsubs)(ivec3s a, int s, ivec3s dest) {
+ glm_ivec3_subsubs(a.raw, s, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief add vector [a] to vector [b] and subtract the result from [dest]
+ *
+ * applies -= operator so dest must be initialized
+ *
+ * @param[in] a vector
+ * @param[in] b scalar
+ * @param[in] dest dest -= (a + b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(addsub)(ivec3s a, ivec3s b, ivec3s dest) {
+ glm_ivec3_addsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief add scalar [s] to vector [a] and subtract the result from [dest]
+ *
+ * applies -= operator so dest must be initialized
+ *
+ * @param[in] a vector
+ * @param[in] s scalar
+ * @param[in] dest dest -= (a + b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(addsubs)(ivec3s a, int s, ivec3s dest) {
+ glm_ivec3_addsubs(a.raw, s, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief multiply vector [a] and vector [b] and subtract the result from [dest]
+ *
+ * applies -= operator so dest must be initialized
+ *
+ * @param[in] a vector
+ * @param[in] b scalar
+ * @param[in] dest dest -= (a * b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(mulsub)(ivec3s a, ivec3s b, ivec3s dest) {
+ glm_ivec3_mulsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief multiply vector [a] with scalar [s] and subtract the result from [dest]
+ *
+ * applies -= operator so dest must be initialized
+ *
+ * @param[in] a vector
+ * @param[in] s scalar
+ * @param[in] dest dest -= (a * s)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(mulsubs)(ivec3s a, int s, ivec3s dest) {
+ glm_ivec3_mulsubs(a.raw, s, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief subtract maximum of vector [a] and vector [b] from vector [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[in] dest dest -= max(a, b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(maxsub)(ivec3s a, ivec3s b, ivec3s dest) {
+ glm_ivec3_maxsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief subtract minimum of vector [a] and vector [b] from vector [dest]
+ *
+ * applies -= operator so dest must be initialized
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[in] dest dest -= min(a, b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(minsub)(ivec3s a, ivec3s b, ivec3s dest) {
+ glm_ivec3_minsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @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
+glms_ivec3_(distance2)(ivec3s a, ivec3s b) {
+ return glm_ivec3_distance2(a.raw, b.raw);
+}
+
+/*!
+ * @brief distance between two vectors
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @return returns distance
+ */
+CGLM_INLINE
+float
+glms_ivec3_(distance)(ivec3s a, ivec3s b) {
+ return glm_ivec3_distance(a.raw, b.raw);
+}
+
+/*!
+ * @brief fill a vector with specified value
+ *
+ * @param[in] val value
+ * @returns destination
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(fill)(int val) {
+ ivec3s r;
+ glm_ivec3_fill(r.raw, val);
+ return r;
+}
+
+/*!
+ * @brief check if vector is equal to value
+ *
+ * @param[in] v vector
+ * @param[in] val value
+ */
+CGLM_INLINE
+bool
+glms_ivec3_(eq)(ivec3s v, int val) {
+ return glm_ivec3_eq(v.raw, val);
+}
+
+/*!
+ * @brief check if vector is equal to another
+ *
+ * @param[in] a vector
+ * @param[in] b vector
+ */
+CGLM_INLINE
+bool
+glms_ivec3_(eqv)(ivec3s a, ivec3s b) {
+ return glm_ivec3_eqv(a.raw, b.raw);
+}
+
+/*!
+ * @brief set each member of dest to greater of vector a and b
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @returns destination
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(maxv)(ivec3s a, ivec3s b) {
+ ivec3s r;
+ glm_ivec3_maxv(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief set each member of dest to lesser of vector a and b
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @returns destination
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(minv)(ivec3s a, ivec3s b) {
+ ivec3s r;
+ glm_ivec3_minv(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief clamp each member of [v] between minVal and maxVal (inclusive)
+ *
+ * @param[in] v vector
+ * @param[in] minVal minimum value
+ * @param[in] maxVal maximum value
+ * @returns clamped vector
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(clamp)(ivec3s v, int minVal, int maxVal) {
+ glm_ivec3_clamp(v.raw, minVal, maxVal);
+ return v;
+}
+
+/*!
+ * @brief absolute value of v
+ *
+ * @param[in] v vector
+ * @returns destination
+ */
+CGLM_INLINE
+ivec3s
+glms_ivec3_(abs)(ivec3s v) {
+ ivec3s r;
+ glm_ivec3_abs(v.raw, r.raw);
+ return r;
+}
+
+#endif /* cglms_ivec3_h */
diff --git a/include/cglm/struct/ivec4.h b/include/cglm/struct/ivec4.h
new file mode 100644
index 0000000..103e887
--- /dev/null
+++ b/include/cglm/struct/ivec4.h
@@ -0,0 +1,588 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Macros:
+ GLMS_IVEC4_ONE_INIT
+ GLMS_IVEC4_ZERO_INIT
+ GLMS_IVEC4_ONE
+ GLMS_IVEC4_ZERO
+
+ Functions:
+ CGLM_INLINE ivec4s glms_ivec4(ivec3s v3, int last)
+ CGLM_INLINE void glms_ivec4_pack(ivec4s dst[], ivec4 src[], size_t len)
+ CGLM_INLINE void glms_ivec4_unpack(ivec4 dst[], ivec4s src[], size_t len)
+ CGLM_INLINE ivec4s glms_ivec4_zero(void)
+ CGLM_INLINE ivec4s glms_ivec4_one(void)
+ CGLM_INLINE ivec4s glms_ivec4_add(ivec4s a, ivec4s b)
+ CGLM_INLINE ivec4s glms_ivec4_adds(ivec4s v, int s)
+ CGLM_INLINE ivec4s glms_ivec4_sub(ivec4s a, ivec4s b)
+ CGLM_INLINE ivec4s glms_ivec4_subs(ivec4s v, int s)
+ CGLM_INLINE ivec4s glms_ivec4_mul(ivec4s a, ivec4s b)
+ CGLM_INLINE ivec4s glms_ivec4_scale(ivec4s v, int s)
+ CGLM_INLINE ivec4s glms_ivec4_addadd(ivec4s a, ivec4s b, ivec4s dest)
+ CGLM_INLINE ivec4s glms_ivec4_addadds(ivec4s a, int s, ivec4s dest)
+ CGLM_INLINE ivec4s glms_ivec4_subadd(ivec4s a, ivec4s b, ivec4s dest)
+ CGLM_INLINE ivec4s glms_ivec4_subadds(ivec4s a, int s, ivec4s dest)
+ CGLM_INLINE ivec4s glms_ivec4_muladd(ivec4s a, ivec4s b, ivec4s dest)
+ CGLM_INLINE ivec4s glms_ivec4_muladds(ivec4s a, int s, ivec4s dest)
+ CGLM_INLINE ivec4s glms_ivec4_maxadd(ivec4s a, ivec4s b, ivec4s dest)
+ CGLM_INLINE ivec4s glms_ivec4_minadd(ivec4s a, ivec4s b, ivec4s dest)
+ CGLM_INLINE ivec4s glms_ivec4_subsub(ivec4s a, ivec4s b, ivec4s dest)
+ CGLM_INLINE ivec4s glms_ivec4_subsubs(ivec4s a, int s, ivec4s dest)
+ CGLM_INLINE ivec4s glms_ivec4_addsub(ivec4s a, ivec4s b, ivec4s dest)
+ CGLM_INLINE ivec4s glms_ivec4_addsubs(ivec4s a, int s, ivec4s dest)
+ CGLM_INLINE ivec4s glms_ivec4_mulsub(ivec4s a, ivec4s b, ivec4s dest)
+ CGLM_INLINE ivec4s glms_ivec4_mulsubs(ivec4s a, int s, ivec4s dest)
+ CGLM_INLINE ivec4s glms_ivec4_maxsub(ivec4s a, ivec4s b, ivec4s dest)
+ CGLM_INLINE ivec4s glms_ivec4_minsub(ivec4s a, ivec4s b, ivec4s dest)
+ CGLM_INLINE int glms_ivec4_distance2(ivec4s a, ivec4s b)
+ CGLM_INLINE float glms_ivec4_distance(ivec4s a, ivec4s b)
+ CGLM_INLINE ivec4s glms_ivec4_maxv(ivec4s a, ivec4s b)
+ CGLM_INLINE ivec4s glms_ivec4_minv(ivec4s a, ivec4s b)
+ CGLM_INLINE ivec4s glms_ivec4_clamp(ivec4s v, int minVal, int maxVal)
+ CGLM_INLINE ivec4s glms_ivec4_abs(ivec4s v)
+ */
+
+#ifndef cglms_ivec4_h
+#define cglms_ivec4_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../ivec4.h"
+
+#define glms_ivec4_(NAME) CGLM_STRUCTAPI(ivec4, NAME)
+
+#define GLMS_IVEC4_ONE_INIT {GLM_IVEC4_ONE_INIT}
+#define GLMS_IVEC4_ZERO_INIT {GLM_IVEC4_ZERO_INIT}
+
+#define GLMS_IVEC4_ONE ((ivec4s)GLMS_IVEC4_ONE_INIT)
+#define GLMS_IVEC4_ZERO ((ivec4s)GLMS_IVEC4_ZERO_INIT)
+
+/*!
+ * @brief init ivec4 using ivec3
+ *
+ * @param[in] v3 vector3
+ * @param[in] last last item
+ * @returns destination
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4(ivec3s v3, int last) {
+ ivec4s r;
+ glm_ivec4(v3.raw, last, r.raw);
+ return r;
+}
+
+/*!
+ * @brief pack an array of ivec4 into an array of ivec4s
+ *
+ * @param[out] dst array of ivec4s
+ * @param[in] src array of ivec4
+ * @param[in] len number of elements
+ */
+CGLM_INLINE
+void
+glms_ivec4_(pack)(ivec4s dst[], ivec4 src[], size_t len) {
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ glm_ivec4_copy(src[i], dst[i].raw);
+ }
+}
+
+/*!
+ * @brief unpack an array of ivec4s into an array of ivec4
+ *
+ * @param[out] dst array of ivec4
+ * @param[in] src array of ivec4s
+ * @param[in] len number of elements
+ */
+CGLM_INLINE
+void
+glms_ivec4_(unpack)(ivec4 dst[], ivec4s src[], size_t len) {
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ glm_ivec4_copy(src[i].raw, dst[i]);
+ }
+}
+
+/*!
+ * @brief set all members of [v] to zero
+ *
+ * @returns vector
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(zero)(void) {
+ ivec4s r;
+ glm_ivec4_zero(r.raw);
+ return r;
+}
+
+/*!
+ * @brief set all members of [v] to one
+ *
+ * @returns vector
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(one)(void) {
+ ivec4s r;
+ glm_ivec4_one(r.raw);
+ return r;
+}
+
+/*!
+ * @brief add vector [a] to vector [b] and store result in [dest]
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @returns destination
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(add)(ivec4s a, ivec4s b) {
+ ivec4s r;
+ glm_ivec4_add(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief add scalar s to vector [v] and store result in [dest]
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @returns destination
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(adds)(ivec4s v, int s) {
+ ivec4s r;
+ glm_ivec4_adds(v.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief subtract vector [b] from vector [a] and store result in [dest]
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @returns destination
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(sub)(ivec4s a, ivec4s b) {
+ ivec4s r;
+ glm_ivec4_sub(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief subtract scalar s from vector [v] and store result in [dest]
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @returns destination
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(subs)(ivec4s v, int s) {
+ ivec4s r;
+ glm_ivec4_subs(v.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief multiply vector [a] with vector [b] and store result in [dest]
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @returns destination
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(mul)(ivec4s a, ivec4s b) {
+ ivec4s r;
+ glm_ivec4_mul(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief multiply vector [a] with scalar s and store result in [dest]
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @returns destination
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(scale)(ivec4s v, int s) {
+ ivec4s r;
+ glm_ivec4_scale(v.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief add vector [a] with vector [b] and add result to vector [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[in] dest dest += (a + b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(addadd)(ivec4s a, ivec4s b, ivec4s dest) {
+ glm_ivec4_addadd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief add scalar [s] onto vector [a] and add result to vector [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a vector
+ * @param[in] s scalar
+ * @param[in] dest dest += (a + s)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(addadds)(ivec4s a, int s, ivec4s dest) {
+ glm_ivec4_addadds(a.raw, s, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief subtract vector [a] from vector [b] and add result to [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[in] dest dest += (a - b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(subadd)(ivec4s a, ivec4s b, ivec4s dest) {
+ glm_ivec4_subadd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief subtract scalar [s] from vector [a] and add result to [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a first
+ * @param[in] s scalar
+ * @param[in] dest dest += (a - s)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(subadds)(ivec4s a, int s, ivec4s dest) {
+ glm_ivec4_subadds(a.raw, s, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief multiply vector [a] with vector [b] and add result to [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[in] dest dest += (a * b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(muladd)(ivec4s a, ivec4s b, ivec4s dest) {
+ glm_ivec4_muladd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief multiply vector [a] with scalar [s] and add result to [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a vector
+ * @param[in] s scalar
+ * @param[in] dest dest += (a * s)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(muladds)(ivec4s a, int s, ivec4s dest) {
+ glm_ivec4_muladds(a.raw, s, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief add maximum of vector [a] and vector [b] to vector [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[in] dest dest += max(a, b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(maxadd)(ivec4s a, ivec4s b, ivec4s dest) {
+ glm_ivec4_maxadd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief add minimum of vector [a] and vector [b] to vector [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[in] dest dest += min(a, b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(minadd)(ivec4s a, ivec4s b, ivec4s dest) {
+ glm_ivec4_minadd(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief subtract vector [a] from vector [b] and subtract result from [dest]
+ *
+ * applies -= operator so dest must be initialized
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[in] dest dest -= (a - b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(subsub)(ivec4s a, ivec4s b, ivec4s dest) {
+ glm_ivec4_subsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief subtract scalar [s] from vector [a] and subtract result from [dest]
+ *
+ * applies -= operator so dest must be initialized
+ *
+ * @param[in] a vector
+ * @param[in] s scalar
+ * @param[in] dest dest -= (a - s)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(subsubs)(ivec4s a, int s, ivec4s dest) {
+ glm_ivec4_subsubs(a.raw, s, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief add vector [a] to vector [b] and subtract the result from [dest]
+ *
+ * applies -= operator so dest must be initialized
+ *
+ * @param[in] a vector
+ * @param[in] b scalar
+ * @param[in] dest dest -= (a + b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(addsub)(ivec4s a, ivec4s b, ivec4s dest) {
+ glm_ivec4_addsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief add scalar [s] to vector [a] and subtract the result from [dest]
+ *
+ * applies -= operator so dest must be initialized
+ *
+ * @param[in] a vector
+ * @param[in] s scalar
+ * @param[in] dest dest -= (a + b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(addsubs)(ivec4s a, int s, ivec4s dest) {
+ glm_ivec4_addsubs(a.raw, s, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief multiply vector [a] and vector [b] and subtract the result from [dest]
+ *
+ * applies -= operator so dest must be initialized
+ *
+ * @param[in] a vector
+ * @param[in] b scalar
+ * @param[in] dest dest -= (a * b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(mulsub)(ivec4s a, ivec4s b, ivec4s dest) {
+ glm_ivec4_mulsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief multiply vector [a] with scalar [s] and subtract the result from [dest]
+ *
+ * applies -= operator so dest must be initialized
+ *
+ * @param[in] a vector
+ * @param[in] s scalar
+ * @param[in] dest dest -= (a * s)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(mulsubs)(ivec4s a, int s, ivec4s dest) {
+ glm_ivec4_mulsubs(a.raw, s, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief subtract maximum of vector [a] and vector [b] from vector [dest]
+ *
+ * applies += operator so dest must be initialized
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[in] dest dest -= max(a, b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(maxsub)(ivec4s a, ivec4s b, ivec4s dest) {
+ glm_ivec4_maxsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief subtract minimum of vector [a] and vector [b] from vector [dest]
+ *
+ * applies -= operator so dest must be initialized
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @param[in] dest dest -= min(a, b)
+ * @returns dest
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(minsub)(ivec4s a, ivec4s b, ivec4s dest) {
+ glm_ivec4_minsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @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
+glms_ivec4_(distance2)(ivec4s a, ivec4s b) {
+ return glm_ivec4_distance2(a.raw, b.raw);
+}
+
+/*!
+ * @brief distance between two vectors
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @return returns distance
+ */
+CGLM_INLINE
+float
+glms_ivec4_(distance)(ivec4s a, ivec4s b) {
+ return glm_ivec4_distance(a.raw, b.raw);
+}
+
+/*!
+ * @brief set each member of dest to greater of vector a and b
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @returns destination
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(maxv)(ivec4s a, ivec4s b) {
+ ivec4s r;
+ glm_ivec4_maxv(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief set each member of dest to lesser of vector a and b
+ *
+ * @param[in] a first vector
+ * @param[in] b second vector
+ * @returns destination
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(minv)(ivec4s a, ivec4s b) {
+ ivec4s r;
+ glm_ivec4_minv(a.raw, b.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief clamp each member of [v] between minVal and maxVal (inclusive)
+ *
+ * @param[in] v vector
+ * @param[in] minVal minimum value
+ * @param[in] maxVal maximum value
+ * @returns clamped vector
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(clamp)(ivec4s v, int minVal, int maxVal) {
+ glm_ivec4_clamp(v.raw, minVal, maxVal);
+ return v;
+}
+
+/*!
+ * @brief absolute value of v
+ *
+ * @param[in] v vector
+ * @returns destination
+ */
+CGLM_INLINE
+ivec4s
+glms_ivec4_(abs)(ivec4s v) {
+ ivec4s r;
+ glm_ivec4_abs(v.raw, r.raw);
+ return r;
+}
+
+#endif /* cglms_ivec4_h */
diff --git a/include/cglm/struct/mat2.h b/include/cglm/struct/mat2.h
new file mode 100644
index 0000000..915c1be
--- /dev/null
+++ b/include/cglm/struct/mat2.h
@@ -0,0 +1,274 @@
+/*
+ * 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 mat2s glms_mat2_make(const float * __restrict src);
+ CGLM_INLINE mat2s glms_mat2_identity(void)
+ CGLM_INLINE void glms_mat2_identity_array(mat2 * restrict mats, size_t count)
+ CGLM_INLINE mat2s glms_mat2_zero(void)
+ CGLM_INLINE mat2s glms_mat2_mul(mat2 m1, mat2 m2)
+ CGLM_INLINE vec2s glms_mat2_mulv(mat2 m, vec2 v)
+ CGLM_INLINE mat2s glms_mat2_transpose(mat2 m)
+ CGLM_INLINE mat2s glms_mat2_scale(mat2 m, float s)
+ CGLM_INLINE mat2s glms_mat2_inv(mat2 m)
+ CGLM_INLINE mat2s glms_mat2_swap_col(mat2 mat, int col1, int col2)
+ CGLM_INLINE mat2s glms_mat2_swap_row(mat2 mat, int row1, int row2)
+ CGLM_INLINE float glms_mat2_det(mat2 m)
+ CGLM_INLINE float glms_mat2_trace(mat2 m)
+ 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"
+
+/* api definition */
+#define glms_mat2_(NAME) CGLM_STRUCTAPI(mat2, NAME)
+
+#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 ((mat2s)GLMS_MAT2_IDENTITY_INIT)
+#define GLMS_MAT2_ZERO ((mat2s)GLMS_MAT2_ZERO_INIT)
+
+/*!
+ * @brief Returns mat2s (r) from pointer (src).
+ *
+ * @param[in] src pointer to an array of floats
+ * @return[out] r constructed mat2s from raw pointer
+ */
+CGLM_INLINE
+mat2s
+glms_mat2_(make)(const float * __restrict src) {
+ mat2s r;
+ glm_mat2_make(src, r.raw);
+ return r;
+}
+
+/*!
+ * @brief Return a identity mat2s (r).
+ *
+ * The same thing may be achieved with either of bellow methods,
+ * 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
+ *
+ * @return[out] r constructed mat2s from raw pointer
+ */
+CGLM_INLINE
+mat2s
+glms_mat2_(identity)(void) {
+ mat2s r;
+ glm_mat2_identity(r.raw);
+ return r;
+}
+
+/*!
+ * @brief Given an array of mat2s’s (mats) make each matrix an identity matrix.
+ *
+ * @param[in, out] mats Array of mat2s’s (must be aligned (16/32) if alignment is not disabled)
+ * @param[in] count Array size of mats or number of matrices
+ */
+CGLM_INLINE
+void
+glms_mat2_(identity_array)(mat2s * __restrict mats, 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, mats[i].raw);
+ }
+}
+
+/*!
+ * @brief Return zero'd out mat2 (r).
+ *
+ * @return[out] r constructed mat2s from raw pointer
+ */
+CGLM_INLINE
+mat2s
+glms_mat2_(zero)(void) {
+ mat2s r;
+ glm_mat2_zero(r.raw);
+ return r;
+}
+
+/*!
+ * @brief Multiply mat2 (m1) by mat2 (m2) and return in mat2s (r)
+ *
+ * m1 and m2 matrices can be the same matrix, it is possible to write this:
+ *
+ * @code
+ * mat2 m = GLM_MAT2_IDENTITY_INIT;
+ * mat2s r = glms_mat2_mul(m, m);
+ * @endcode
+ *
+ * @param[in] m1 mat2s (left)
+ * @param[in] m2 mat2s (right)
+ * @return[out] r constructed mat2s from raw pointers
+ */
+CGLM_INLINE
+mat2s
+glms_mat2_(mul)(mat2s m1, mat2s m2) {
+ mat2s r;
+ glm_mat2_mul(m1.raw, m2.raw, r.raw);
+ return r;
+}
+
+/*
+ * @brief Multiply mat2s (m) by vec2s (v) and return in vec2s (r).
+ *
+ * @param[in] m mat2s (left)
+ * @param[in] v vec2s (right, column vector)
+ * @return[out] r constructed vec2s from raw pointers
+ */
+CGLM_INLINE
+vec2s
+glms_mat2_(mulv)(mat2s m, vec2s v) {
+ vec2s r;
+ glm_mat2_mulv(m.raw, v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief Transpose mat2s (m) and store result in the same matrix.
+ *
+ * @param[in] m mat2s (src)
+ * @return[out] m constructed mat2s from raw pointers
+ */
+CGLM_INLINE
+mat2s
+glms_mat2_(transpose)(mat2s m) {
+ glm_mat2_transpose(m.raw);
+ return m;
+}
+
+/*!
+ * @brief Multiply mat2s (m) by scalar constant (s)
+ *
+ * @param[in] m mat2s (src)
+ * @param[in] s scalar value
+ * @return[out] m constructed mat2s from raw pointers
+ */
+CGLM_INLINE
+mat2s
+glms_mat2_(scale)(mat2s m, float s) {
+ glm_mat2_scale(m.raw, s);
+ return m;
+}
+
+/*!
+ * @brief Inverse mat2s (m) and return in mat2s (r).
+ *
+ * @param[in] m mat2s (left, src)
+ * @return[out] r constructed mat2s from raw pointers
+ */
+CGLM_INLINE
+mat2s
+glms_mat2_(inv)(mat2s m) {
+ mat2s r;
+ glm_mat2_inv(m.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief Swap two columns in mat2s (mat) and store in same matrix.
+ *
+ * @param[in] mat mat2s
+ * @param[in] col1 column 1 array index
+ * @param[in] col2 column 2 array index
+ * @return[out] mat constructed mat2s from raw pointers columns swapped
+ */
+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 rows in mat2s (mat) and store in same matrix.
+ *
+ * @param[in] mat mat2s
+ * @param[in] row1 row 1 array index
+ * @param[in] row2 row 2 array index
+ * @return[out] mat constructed mat2s from raw pointers rows swapped
+ */
+CGLM_INLINE
+mat2s
+glms_mat2_(swap_row)(mat2s mat, int row1, int row2) {
+ glm_mat2_swap_row(mat.raw, row1, row2);
+ return mat;
+}
+
+/*!
+ * @brief Returns mat2 determinant.
+ *
+ * @param[in] m mat2 (src)
+ *
+ * @return[out] mat2s raw pointers determinant (float)
+ */
+CGLM_INLINE
+float
+glms_mat2_(det)(mat2s m) {
+ return glm_mat2_det(m.raw);
+}
+
+/*!
+ * @brief Returns trace of matrix. Which is:
+ *
+ * The sum of the elements on the main diagonal from
+ * upper left corner to the bottom right corner.
+ *
+ * @param[in] m mat2 (m)
+ *
+ * @return[out] mat2s raw pointers trace (float)
+ */
+CGLM_INLINE
+float
+glms_mat2_(trace)(mat2s m) {
+ return glm_mat2_trace(m.raw);
+}
+
+/*!
+ * @brief Helper for R (row vector) * M (matrix) * C (column vector)
+ *
+ * rmc stands for Row * Matrix * Column
+ *
+ * the result is scalar because M * C = ResC (1x2, column vector),
+ * then if you take the dot_product(R (2x1), ResC (1x2)) = scalar value.
+ *
+ * @param[in] r vec2s (2x1, row vector)
+ * @param[in] m mat2s (2x2, matrix)
+ * @param[in] c vec2s (1x2, column vector)
+ *
+ * @return[out] Scalar value (float, 1x1)
+ */
+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/include/cglm/struct/mat2x3.h b/include/cglm/struct/mat2x3.h
new file mode 100644
index 0000000..5b061ba
--- /dev/null
+++ b/include/cglm/struct/mat2x3.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Macros:
+ GLMS_MAT2X3_ZERO_INIT
+ GLMS_MAT2X3_ZERO
+
+ Functions:
+ CGLM_INLINE mat2x3s glms_mat2x3_zero(void);
+ CGLM_INLINE mat2x3s glms_mat2x3_make(const float * __restrict src);
+ CGLM_INLINE mat2s glms_mat2x3_mul(mat2x3s m1, mat3x2s m2);
+ CGLM_INLINE vec3s glms_mat2x3_mulv(mat2x3s m, vec2s v);
+ CGLM_INLINE mat3x2s glms_mat2x3_transpose(mat2x3s m);
+ CGLM_INLINE mat2x3s glms_mat2x3_scale(mat2x3s m, float s);
+ */
+
+#ifndef cglms_mat2x3_h
+#define cglms_mat2x3_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../mat2x3.h"
+
+/* api definition */
+#define glms_mat2x3_(NAME) CGLM_STRUCTAPI(mat2x3, NAME)
+
+#define GLMS_MAT2X3_ZERO_INIT {GLM_MAT2X3_ZERO_INIT}
+
+/* for C only */
+#define GLMS_MAT2X3_ZERO ((mat2x3s)GLMS_MAT2X3_ZERO_INIT)
+
+/*!
+ * @brief Zero out the mat2x3s (dest).
+ *
+ * @return[out] dest constructed mat2x3s from raw pointer
+ */
+CGLM_INLINE
+mat2x3s
+glms_mat2x3_(zero)(void) {
+ mat2x3s dest;
+ glm_mat2x3_zero(dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Create mat2x3s (dest) from pointer (src).
+ *
+ * @param[in] src pointer to an array of floats
+ * @return[out] dest constructed mat2x3s from raw pointer
+ */
+CGLM_INLINE
+mat2x3s
+glms_mat2x3_(make)(const float * __restrict src) {
+ mat2x3s dest;
+ glm_mat2x3_make(src, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Multiply mat2x3s (m1) by mat3x2s (m2) and store in mat3s (dest).
+ *
+ * @code
+ * r = glms_mat2x3_mul(mat2x3s, mat3x2s);
+ * @endcode
+ *
+ * @param[in] m1 mat2x3s (left)
+ * @param[in] m2 mat3x2s (right)
+ * @return[out] dest constructed mat3s from raw pointers
+ */
+CGLM_INLINE
+mat3s
+glms_mat2x3_(mul)(mat2x3s m1, mat3x2s m2) {
+ mat3s dest;
+ glm_mat2x3_mul(m1.raw, m2.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Multiply mat2x3s (m) by vec2s (v) and store in vec3s (dest).
+ *
+ * @param[in] m mat2x3s (left)
+ * @param[in] v vec2s (right, column vector)
+ * @return[out] dest constructed vec3s from raw pointers
+ */
+CGLM_INLINE
+vec3s
+glms_mat2x3_(mulv)(mat2x3s m, vec2s v) {
+ vec3s dest;
+ glm_mat2x3_mulv(m.raw, v.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Transpose mat2x3s (m) and store in mat3x2s (dest).
+ *
+ * @param[in] m mat2x3s (left)
+ * @return[out] dest constructed mat3x2s from raw pointers
+ */
+CGLM_INLINE
+mat3x2s
+glms_mat2x3_(transpose)(mat2x3s m) {
+ mat3x2s dest;
+ glm_mat2x3_transpose(m.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Multiply mat2x3s (m) by scalar constant (s).
+ *
+ * @param[in, out] m mat2x3 (src, dest)
+ * @param[in] s float (scalar)
+ */
+CGLM_INLINE
+mat2x3s
+glms_mat2x3_(scale)(mat2x3s m, float s) {
+ glm_mat2x3_scale(m.raw, s);
+ return m;
+}
+
+#endif /* cglms_mat2x3_h */
diff --git a/include/cglm/struct/mat2x4.h b/include/cglm/struct/mat2x4.h
new file mode 100644
index 0000000..7e3e75a
--- /dev/null
+++ b/include/cglm/struct/mat2x4.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Macros:
+ GLMS_MAT2X4_ZERO_INIT
+ GLMS_MAT2X4_ZERO
+
+ Functions:
+ CGLM_INLINE mat2x4s glms_mat2x4_zero(void);
+ CGLM_INLINE mat2x4s glms_mat2x4_make(const float * __restrict src);
+ CGLM_INLINE mat2s glms_mat2x4_mul(mat2x4s m1, mat4x2s m2);
+ CGLM_INLINE vec4s glms_mat2x4_mulv(mat2x4s m, vec2s v);
+ CGLM_INLINE mat4x2s glms_mat2x4_transpose(mat2x4s m);
+ CGLM_INLINE mat2x4s glms_mat2x4_scale(mat2x4s m, float s);
+ */
+
+#ifndef cglms_mat2x4_h
+#define cglms_mat2x4_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../mat2x4.h"
+
+/* api definition */
+#define glms_mat2x4_(NAME) CGLM_STRUCTAPI(mat2x4, NAME)
+
+#define GLMS_MAT2X4_ZERO_INIT {GLM_MAT2X4_ZERO_INIT}
+
+/* for C only */
+#define GLMS_MAT2X4_ZERO ((mat2x4s)GLMS_MAT2X4_ZERO_INIT)
+
+/*!
+ * @brief Zero out the mat2x4s (dest).
+ *
+ * @return[out] dest constructed mat2x4s from raw pointer
+ */
+CGLM_INLINE
+mat2x4s
+glms_mat2x4_(zero)(void) {
+ mat2x4s dest;
+ glm_mat2x4_zero(dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Create mat2x4s (dest) from pointer (src).
+ *
+ * @param[in] src pointer to an array of floats
+ * @return[out] dest constructed mat2x4s from raw pointer
+ */
+CGLM_INLINE
+mat2x4s
+glms_mat2x4_(make)(const float * __restrict src) {
+ mat2x4s dest;
+ glm_mat2x4_make(src, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Multiply mat2x4s (m1) by mat4x2s (m2) and store in mat4s (dest).
+ *
+ * @code
+ * r = glms_mat2x4_mul(mat2x4s, mat4x2s);
+ * @endcode
+ *
+ * @param[in] m1 mat2x4s (left)
+ * @param[in] m2 mat4x2s (right)
+ * @return[out] dest constructed mat4s from raw pointers
+ */
+CGLM_INLINE
+mat4s
+glms_mat2x4_(mul)(mat2x4s m1, mat4x2s m2) {
+ mat4s dest;
+ glm_mat2x4_mul(m1.raw, m2.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Multiply mat2x4s (m) by vec2s (v) and store in vec4s (dest).
+ *
+ * @param[in] m mat2x4s (left)
+ * @param[in] v vec2s (right, column vector)
+ * @return[out] dest constructed vec4s from raw pointers
+ */
+CGLM_INLINE
+vec4s
+glms_mat2x4_(mulv)(mat2x4s m, vec2s v) {
+ vec4s dest;
+ glm_mat2x4_mulv(m.raw, v.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Transpose mat2x4s (m) and store in mat4x2s (dest).
+ *
+ * @param[in] m mat2x4s (left)
+ * @return[out] dest constructed mat4x2s from raw pointers
+ */
+CGLM_INLINE
+mat4x2s
+glms_mat2x4_(transpose)(mat2x4s m) {
+ mat4x2s dest;
+ glm_mat2x4_transpose(m.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Multiply mat2x4s (m) by scalar constant (s).
+ *
+ * @param[in, out] m mat2x4s (src, dest)
+ * @param[in] s float (scalar)
+ */
+CGLM_INLINE
+mat2x4s
+glms_mat2x4_(scale)(mat2x4s m, float s) {
+ glm_mat2x4_scale(m.raw, s);
+ return m;
+}
+
+#endif /* cglms_mat2x4_h */
diff --git a/include/cglm/struct/mat3.h b/include/cglm/struct/mat3.h
new file mode 100644
index 0000000..2fae073
--- /dev/null
+++ b/include/cglm/struct/mat3.h
@@ -0,0 +1,322 @@
+/*
+ * 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);
+ CGLM_INLINE mat3s glms_mat3_make(const float * __restrict src);
+ CGLM_INLINE mat3s glms_mat3_textrans(float sx, float sy, float rot, float tx, float ty);
+ */
+
+#ifndef cglms_mat3s_h
+#define cglms_mat3s_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../mat3.h"
+#include "vec3.h"
+
+/* api definition */
+#define glms_mat3_(NAME) CGLM_STRUCTAPI(mat3, NAME)
+
+#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;
+ * r = glms_mat3_mul(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 transpose 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);
+}
+
+/*!
+ * @brief Create mat3 matrix from pointer
+ *
+ * @param[in] src pointer to an array of floats
+ * @return constructed matrix from raw pointer
+ */
+CGLM_INLINE
+mat3s
+glms_mat3_(make)(const float * __restrict src) {
+ mat3s r;
+ glm_mat3_make(src, r.raw);
+ return r;
+}
+
+/*!
+ * @brief Create mat3 matrix from texture transform parameters
+ *
+ * @param[in] sx scale x
+ * @param[in] sy scale y
+ * @param[in] rot rotation in radians CCW/RH
+ * @param[in] tx translate x
+ * @param[in] ty translate y
+ * @return texture transform matrix
+ */
+CGLM_INLINE
+mat3s
+glms_mat3_(textrans)(float sx, float sy, float rot, float tx, float ty) {
+ mat3s r;
+ glm_mat3_textrans(sx, sy, rot, tx, ty, r.raw);
+ return r;
+}
+
+#endif /* cglms_mat3s_h */
diff --git a/include/cglm/struct/mat3x2.h b/include/cglm/struct/mat3x2.h
new file mode 100644
index 0000000..ab2d388
--- /dev/null
+++ b/include/cglm/struct/mat3x2.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Macros:
+ GLMS_MAT3X2_ZERO_INIT
+ GLMS_MAT3X2_ZERO
+
+ Functions:
+ CGLM_INLINE mat3x2s glms_mat3x2_zero(void);
+ CGLM_INLINE mat3x2s glms_mat3x2_make(const float * __restrict src);
+ CGLM_INLINE mat2s glms_mat3x2_mul(mat3x2s m1, mat2x3s m2);
+ CGLM_INLINE vec2s glms_mat3x2_mulv(mat3x2s m, vec3s v);
+ CGLM_INLINE mat2x3s glms_mat3x2_transpose(mat3x2s m);
+ CGLM_INLINE mat3x2s glms_mat3x2_scale(mat3x2s m, float s);
+ */
+
+#ifndef cglms_mat3x2_h
+#define cglms_mat3x2_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../mat3x2.h"
+
+/* api definition */
+#define glms_mat3x2_(NAME) CGLM_STRUCTAPI(mat3x2, NAME)
+
+#define GLMS_MAT3X2_ZERO_INIT {GLM_MAT3X2_ZERO_INIT}
+
+/* for C only */
+#define GLMS_MAT3X2_ZERO ((mat3x2s)GLMS_MAT3X2_ZERO_INIT)
+
+/*!
+ * @brief Zero out the mat3x2s (dest).
+ *
+ * @return[out] dest constructed mat3x2s from raw pointer
+ */
+CGLM_INLINE
+mat3x2s
+glms_mat3x2_(zero)(void) {
+ mat3x2s dest;
+ glm_mat3x2_zero(dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Create mat3x2s (dest) from pointer (src).
+ *
+ * @param[in] src pointer to an array of floats
+ * @return[out] dest constructed mat3x2s from raw pointer
+ */
+CGLM_INLINE
+mat3x2s
+glms_mat3x2_(make)(const float * __restrict src) {
+ mat3x2s dest;
+ glm_mat3x2_make(src, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Multiply mat3x2s (m1) by mat2x3s (m2) and store in mat2s (dest).
+ *
+ * @code
+ * r = glms_mat3x2_mul(mat3x2s, mat2x3s);
+ * @endcode
+ *
+ * @param[in] m1 mat3x2s (left)
+ * @param[in] m2 mat2x3s (right)
+ * @return[out] dest constructed mat2s from raw pointers
+ */
+CGLM_INLINE
+mat2s
+glms_mat3x2_(mul)(mat3x2s m1, mat2x3s m2) {
+ mat2s dest;
+ glm_mat3x2_mul(m1.raw, m2.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Multiply mat3x2s (m) by vec3s (v) and store in vec2s (dest).
+ *
+ * @param[in] m mat3x2s (left)
+ * @param[in] v vec3s (right, column vector)
+ * @return[out] dest constructed vec2s from raw pointers
+ */
+CGLM_INLINE
+vec2s
+glms_mat3x2_(mulv)(mat3x2s m, vec3s v) {
+ vec2s dest;
+ glm_mat3x2_mulv(m.raw, v.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Transpose mat3x2s (m) and store in mat2x3s (dest).
+ *
+ * @param[in] m mat3x2s (left)
+ * @return[out] dest constructed mat2x3s from raw pointers
+ */
+CGLM_INLINE
+mat2x3s
+glms_mat3x2_(transpose)(mat3x2s m) {
+ mat2x3s dest;
+ glm_mat3x2_transpose(m.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Multiply mat3x2s (m) by scalar constant (s).
+ *
+ * @param[in, out] m mat3x2s (src, dest)
+ * @param[in] s float (scalar)
+ */
+CGLM_INLINE
+mat3x2s
+glms_mat3x2_(scale)(mat3x2s m, float s) {
+ glm_mat3x2_scale(m.raw, s);
+ return m;
+}
+
+#endif /* cglms_mat3x2_h */
diff --git a/include/cglm/struct/mat3x4.h b/include/cglm/struct/mat3x4.h
new file mode 100644
index 0000000..436b36c
--- /dev/null
+++ b/include/cglm/struct/mat3x4.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Macros:
+ GLMS_MAT3X4_ZERO_INIT
+ GLMS_MAT3X4_ZERO
+
+ Functions:
+ CGLM_INLINE mat3x4s glms_mat3x4_zero(void);
+ CGLM_INLINE mat3x4s glms_mat3x4_make(const float * __restrict src);
+ CGLM_INLINE mat4s glms_mat3x4_mul(mat3x4s m1, mat4x3s m2);
+ CGLM_INLINE vec4s glms_mat3x4_mulv(mat3x4s m, vec3s v);
+ CGLM_INLINE mat4x3s glms_mat3x4_transpose(mat3x4s m);
+ CGLM_INLINE mat3x4s glms_mat3x4_scale(mat3x4s m, float s);
+ */
+
+#ifndef cglms_mat3x4_h
+#define cglms_mat3x4_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../mat3x4.h"
+
+/* api definition */
+#define glms_mat3x4_(NAME) CGLM_STRUCTAPI(mat3x4, NAME)
+
+#define GLMS_MAT3X4_ZERO_INIT {GLM_MAT3X4_ZERO_INIT}
+
+/* for C only */
+#define GLMS_MAT3X4_ZERO ((mat3x4s)GLMS_MAT3X4_ZERO_INIT)
+
+/*!
+ * @brief Zero out the mat3x4s (dest).
+ *
+ * @return[out] dest constructed mat3x4s from raw pointer
+ */
+CGLM_INLINE
+mat3x4s
+glms_mat3x4_(zero)(void) {
+ mat3x4s dest;
+ glm_mat3x4_zero(dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Create mat3x4s (dest) from pointer (src).
+ *
+ * @param[in] src pointer to an array of floats
+ * @return[out] dest constructed mat3x4s from raw pointer
+ */
+CGLM_INLINE
+mat3x4s
+glms_mat3x4_(make)(const float * __restrict src) {
+ mat3x4s dest;
+ glm_mat3x4_make(src, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Multiply mat3x4s (m1) by mat4x3s (m2) and store in mat4s (dest).
+ *
+ * @code
+ * r = glms_mat3x4_mul(mat3x4s, mat4x3s);
+ * @endcode
+ *
+ * @param[in] m1 mat3x4s (left)
+ * @param[in] m2 mat4x3s (right)
+ * @return[out] dest constructed mat4s from raw pointers
+ */
+CGLM_INLINE
+mat4s
+glms_mat3x4_(mul)(mat3x4s m1, mat4x3s m2) {
+ mat4s dest;
+ glm_mat3x4_mul(m1.raw, m2.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Multiply mat3x4s (m) by vec3s (v) and store in vec4s (dest).
+ *
+ * @param[in] m mat3x4s (left)
+ * @param[in] v vec3s (right, column vector)
+ * @return[out] dest constructed vec4s from raw pointers
+ */
+CGLM_INLINE
+vec4s
+glms_mat3x4_(mulv)(mat3x4s m, vec3s v) {
+ vec4s dest;
+ glm_mat3x4_mulv(m.raw, v.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Transpose mat3x4s (m) and store in mat4x3s (dest).
+ *
+ * @param[in] m mat3x4s (left)
+ * @return[out] dest constructed mat4x3s from raw pointers
+ */
+CGLM_INLINE
+mat4x3s
+glms_mat3x4_(transpose)(mat3x4s m) {
+ mat4x3s dest;
+ glm_mat3x4_transpose(m.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Multiply mat3x4s (m) by scalar constant (s).
+ *
+ * @param[in, out] m mat3x4s (src, dest)
+ * @param[in] s float (scalar)
+ */
+CGLM_INLINE
+mat3x4s
+glms_mat3x4_(scale)(mat3x4s m, float s) {
+ glm_mat3x4_scale(m.raw, s);
+ return m;
+}
+
+#endif /* cglms_mat3x4_h */
diff --git a/include/cglm/struct/mat4.h b/include/cglm/struct/mat4.h
new file mode 100644
index 0000000..663a5fd
--- /dev/null
+++ b/include/cglm/struct/mat4.h
@@ -0,0 +1,496 @@
+/*
+ * 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, mat4s dest);
+ 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);
+ CGLM_INLINE mat4s glms_mat4_make(const float * __restrict src);
+ CGLM_INLINE mat4s glms_mat4_textrans(float sx, float sy, float rot, float tx, float ty);
+ */
+
+#ifndef cglms_mat4s_h
+#define cglms_mat4s_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../mat4.h"
+#include "vec4.h"
+#include "vec3.h"
+
+/* api definition */
+#define glms_mat4_(NAME) CGLM_STRUCTAPI(mat4, NAME)
+
+#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
+ *
+ * @returns 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
+ * @param[in] dest destination
+ * @returns destination
+ */
+CGLM_INLINE
+mat4s
+glms_mat4_(ins3)(mat3s mat, mat4s dest) {
+ glm_mat4_ins3(mat.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @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;
+ * r = glms_mat4_mul(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
+ * mat4 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 transpose 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);
+}
+
+/*!
+ * @brief Create mat4 matrix from pointer
+ *
+ * @param[in] src pointer to an array of floats
+ * @return constructed matrix from raw pointer
+ */
+CGLM_INLINE
+mat4s
+glms_mat4_(make)(const float * __restrict src) {
+ mat4s r;
+ glm_mat4_make(src, r.raw);
+ return r;
+}
+
+/*!
+ * @brief Create mat4 matrix from texture transform parameters
+ *
+ * @param[in] sx scale x
+ * @param[in] sy scale y
+ * @param[in] rot rotation in radians CCW/RH
+ * @param[in] tx translate x
+ * @param[in] ty translate y
+ * @return texture transform matrix
+ */
+CGLM_INLINE
+mat4s
+glms_mat4_(textrans)(float sx, float sy, float rot, float tx, float ty) {
+ mat4s r;
+ glm_mat4_textrans(sx, sy, rot, tx, ty, r.raw);
+ return r;
+}
+
+#endif /* cglms_mat4s_h */
diff --git a/include/cglm/struct/mat4x2.h b/include/cglm/struct/mat4x2.h
new file mode 100644
index 0000000..6c68abe
--- /dev/null
+++ b/include/cglm/struct/mat4x2.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Macros:
+ GLMS_MAT4X2_ZERO_INIT
+ GLMS_MAT4X2_ZERO
+
+ Functions:
+ CGLM_INLINE mat4x2s glms_mat4x2_zero(void);
+ CGLM_INLINE mat4x2s glms_mat4x2_make(const float * __restrict src);
+ CGLM_INLINE mat2s glms_mat4x2_mul(mat4x2s m1, mat2x4s m2);
+ CGLM_INLINE vec2s glms_mat4x2_mulv(mat4x2s m, vec4s v);
+ CGLM_INLINE mat2x4s glms_mat4x2_transpose(mat4x2s m);
+ CGLM_INLINE mat4x2s glms_mat4x2_scale(mat4x2s m, float s);
+ */
+
+#ifndef cglms_mat4x2_h
+#define cglms_mat4x2_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../mat4x2.h"
+
+/* api definition */
+#define glms_mat4x2_(NAME) CGLM_STRUCTAPI(mat4x2, NAME)
+
+#define GLMS_MAT4X2_ZERO_INIT {GLM_MAT4X2_ZERO_INIT}
+
+/* for C only */
+#define GLMS_MAT4X2_ZERO ((mat4x2s)GLMS_MAT4X2_ZERO_INIT)
+
+
+/*!
+ * @brief Zero out the mat4x2s (dest).
+ *
+ * @return[out] dest constructed mat4x2s from raw pointer
+ */
+CGLM_INLINE
+mat4x2s
+glms_mat4x2_(zero)(void) {
+ mat4x2s dest;
+ glm_mat4x2_zero(dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Create mat4x2s (dest) from pointer (src).
+ *
+ * @param[in] src pointer to an array of floats
+ * @return[out] dest constructed mat4x2s from raw pointer
+ */
+CGLM_INLINE
+mat4x2s
+glms_mat4x2_(make)(const float * __restrict src) {
+ mat4x2s dest;
+ glm_mat4x2_make(src, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Multiply mat4x2s (m1) by mat2x4s (m2) and store in mat2s (dest).
+ *
+ * @code
+ * r = glms_mat4x2_mul(mat4x2s, mat2x4s);
+ * @endcode
+ *
+ * @param[in] m1 mat4x2s (left)
+ * @param[in] m2 mat2x4s (right)
+ * @return[out] dest constructed mat2s from raw pointers
+ */
+CGLM_INLINE
+mat2s
+glms_mat4x2_(mul)(mat4x2s m1, mat2x4s m2) {
+ mat2s dest;
+ glm_mat4x2_mul(m1.raw, m2.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Multiply mat4x2s (m) by vec4s (v) and store in vec2s (dest).
+ *
+ * @param[in] m mat4x2s (left)
+ * @param[in] v vec4s (right, column vector)
+ * @return[out] dest constructed vec2s from raw pointers
+ */
+CGLM_INLINE
+vec2s
+glms_mat4x2_(mulv)(mat4x2s m, vec4s v) {
+ vec2s dest;
+ glm_mat4x2_mulv(m.raw, v.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Transpose mat4x2s (m) and store in mat2x4s (dest).
+ *
+ * @param[in] m mat4x2s (left)
+ * @return[out] dest constructed mat2x4s from raw pointers
+ */
+CGLM_INLINE
+mat2x4s
+glms_mat4x2_(transpose)(mat4x2s m) {
+ mat2x4s dest;
+ glm_mat4x2_transpose(m.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Multiply mat4x2s (m) by scalar constant (s).
+ *
+ * @param[in, out] m mat4x2s (src, dest)
+ * @param[in] s float (scalar)
+ */
+CGLM_INLINE
+mat4x2s
+glms_mat4x2_(scale)(mat4x2s m, float s) {
+ glm_mat4x2_scale(m.raw, s);
+ return m;
+}
+
+#endif /* cglms_mat4x2_h */
diff --git a/include/cglm/struct/mat4x3.h b/include/cglm/struct/mat4x3.h
new file mode 100644
index 0000000..b398f98
--- /dev/null
+++ b/include/cglm/struct/mat4x3.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Macros:
+ GLMS_MAT4X3_ZERO_INIT
+ GLMS_MAT4X3_ZERO
+
+ Functions:
+ CGLM_INLINE mat4x3s glms_mat4x3_zero(void);
+ CGLM_INLINE mat4x3s glms_mat4x3_make(const float * __restrict src);
+ CGLM_INLINE mat3s glms_mat4x3_mul(mat4x3s m1, mat3x4s m2);
+ CGLM_INLINE vec3s glms_mat4x3_mulv(mat4x3s m, vec4s v);
+ CGLM_INLINE mat3x4s glms_mat4x3_transpose(mat4x3s m);
+ CGLM_INLINE mat4x3s glms_mat4x3_scale(mat4x3s m, float s);
+ */
+
+#ifndef cglms_mat4x3_h
+#define cglms_mat4x3_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../mat4x3.h"
+
+/* api definition */
+#define glms_mat4x3_(NAME) CGLM_STRUCTAPI(mat4x3, NAME)
+
+#define GLMS_MAT4X3_ZERO_INIT {GLM_MAT4X3_ZERO_INIT}
+
+/* for C only */
+#define GLMS_MAT4X3_ZERO ((mat4x3s)GLMS_MAT4X3_ZERO_INIT)
+
+/*!
+ * @brief Zero out the mat4x3s (dest).
+ *
+ * @return[out] dest constructed mat4x3s from raw pointer
+ */
+CGLM_INLINE
+mat4x3s
+glms_mat4x3_(zero)(void) {
+ mat4x3s dest;
+ glm_mat4x3_zero(dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Create mat4x3s (dest) from pointer (src).
+ *
+ * @param[in] src pointer to an array of floats
+ * @return[out] dest constructed mat4x3s from raw pointer
+ */
+CGLM_INLINE
+mat4x3s
+glms_mat4x3_(make)(const float * __restrict src) {
+ mat4x3s dest;
+ glm_mat4x3_make(src, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Multiply mat4x3s (m1) by mat3x4s (m2) and store in mat3s (dest).
+ *
+ * @code
+ * r = glms_mat4x3_mul(mat4x3s, mat3x4s);
+ * @endcode
+ *
+ * @param[in] m1 mat4x3s (left)
+ * @param[in] m2 mat3x4s (right)
+ * @return[out] dest constructed mat3s from raw pointers
+ */
+CGLM_INLINE
+mat3s
+glms_mat4x3_(mul)(mat4x3s m1, mat3x4s m2) {
+ mat3s dest;
+ glm_mat4x3_mul(m1.raw, m2.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Multiply mat4x3s (m) by vec4s (v) and store in vec3s (dest).
+ *
+ * @param[in] m mat4x3s (left)
+ * @param[in] v vec4s (right, column vector)
+ * @return[out] dest constructed vec3s from raw pointers
+ */
+CGLM_INLINE
+vec3s
+glms_mat4x3_(mulv)(mat4x3s m, vec4s v) {
+ vec3s dest;
+ glm_mat4x3_mulv(m.raw, v.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Transpose mat4x3s (m) and store in mat3x4s (dest).
+ *
+ * @param[in] m mat4x3s (left)
+ * @return[out] dest constructed mat3x4s from raw pointers
+ */
+CGLM_INLINE
+mat3x4s
+glms_mat4x3_(transpose)(mat4x3s m) {
+ mat3x4s dest;
+ glm_mat4x3_transpose(m.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief Multiply mat4x3s (m) by scalar constant (s).
+ *
+ * @param[in, out] m mat4x3s (src, dest)
+ * @param[in] s float (scalar)
+ */
+CGLM_INLINE
+mat4x3s
+glms_mat4x3_(scale)(mat4x3s m, float s) {
+ glm_mat4x3_scale(m.raw, s);
+ return m;
+}
+
+#endif /* cglms_mat4x3_h */
diff --git a/include/cglm/struct/noise.h b/include/cglm/struct/noise.h
new file mode 100644
index 0000000..3fd7d2e
--- /dev/null
+++ b/include/cglm/struct/noise.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglms_noises_h
+#define cglms_noises_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../noise.h"
+#include "vec4.h"
+
+/*
+ Functions:
+ CGLM_INLINE float glms_perlin_vec4(vec4s point);
+ */
+
+/*!
+ * @brief Classic perlin noise
+ *
+ * @param[in] point 4D vector
+ * @returns perlin noise value
+ */
+CGLM_INLINE
+float
+glms_perlin_vec4(vec4s point) {
+ return glm_perlin_vec4(point.raw);
+}
+
+/*!
+ * @brief Classic perlin noise
+ *
+ * @param[in] point 3D vector
+ * @returns perlin noise value
+ */
+CGLM_INLINE
+float
+glms_perlin_vec3(vec3s point) {
+ return glm_perlin_vec3(point.raw);
+}
+
+/*!
+ * @brief Classic perlin noise
+ *
+ * @param[in] point 2D vector
+ * @returns perlin noise value
+ */
+CGLM_INLINE
+float
+glms_perlin_vec2(vec2s point) {
+ return glm_perlin_vec2(point.raw);
+}
+
+#endif /* cglms_noises_h */
diff --git a/include/cglm/struct/plane.h b/include/cglm/struct/plane.h
new file mode 100644
index 0000000..6a84ac7
--- /dev/null
+++ b/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/include/cglm/struct/project.h b/include/cglm/struct/project.h
new file mode 100644
index 0000000..8383c77
--- /dev/null
+++ b/include/cglm/struct/project.h
@@ -0,0 +1,162 @@
+/*
+ * 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"
+
+#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]
+ * @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);
+ *
+ * or in struct api:
+ * MVP = mat4_mul(mat4_mul(proj, view), model)
+ *
+ * @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);
+ *
+ * or in struct api:
+ * MVP = mat4_mul(mat4_mul(proj, view), model)
+ *
+ * @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 map object's z coordinate to window coordinates
+ *
+ * Computing MVP:
+ * glm_mat4_mul(proj, view, viewProj);
+ * glm_mat4_mul(viewProj, model, MVP);
+ *
+ * or in struct api:
+ * MVP = mat4_mul(mat4_mul(proj, view), model)
+ *
+ * @param[in] v object coordinates
+ * @param[in] m MVP matrix
+ *
+ * @returns projected z coordinate
+ */
+CGLM_INLINE
+float
+glms_project_z(vec3s v, mat4s m) {
+#if CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_ZO_BIT
+ return glms_project_z_zo(v, m);
+#elif CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_NO_BIT
+ return glms_project_z_no(v, m);
+#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]
+ * @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/include/cglm/struct/quat.h b/include/cglm/struct/quat.h
new file mode 100644
index 0000000..d6789e4
--- /dev/null
+++ b/include/cglm/struct/quat.h
@@ -0,0 +1,601 @@
+/*
+ * 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 versors glms_quat_slerp_longest(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)
+ CGLM_INLINE versors glms_quat_make(float * restrict src)
+ */
+
+#ifndef cglms_quat_h
+#define cglms_quat_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../plane.h"
+#include "../quat.h"
+
+/* api definition */
+#define glms_quat_(NAME) CGLM_STRUCTAPI(quat, NAME)
+
+/*
+ * 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 quaternion 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 amount
+ * @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 interpolates between two quaternions
+ * using spherical linear interpolation (SLERP) and always takes the longest path
+ *
+ * @param[in] from from
+ * @param[in] to to
+ * @param[in] t amount
+ * @returns result quaternion
+ */
+CGLM_INLINE
+versors
+glms_quat_(slerp_longest)(versors from, versors to, float t) {
+ versors dest;
+ glm_quat_slerp_longest(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;
+}
+
+/*!
+ * @brief Create CGLM quaternion from pointer
+ *
+ * @param[in] src pointer to an array of floats
+ * @returns constructed quaternion from raw pointer
+ */
+CGLM_INLINE
+versors
+glms_quat_(make)(const float * __restrict src) {
+ versors dest;
+ glm_quat_make(src, dest.raw);
+ return dest;
+}
+
+#endif /* cglms_quat_h */
diff --git a/include/cglm/struct/ray.h b/include/cglm/struct/ray.h
new file mode 100644
index 0000000..10609b9
--- /dev/null
+++ b/include/cglm/struct/ray.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 cglms_ray_h
+#define cglms_ray_h
+
+#include "../common.h"
+#include "../types-struct.h"
+#include "../ray.h"
+
+/* api definition */
+#define glms_ray_(NAME) CGLM_STRUCTAPI(ray, NAME)
+
+/*!
+ * @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
+glms_ray_(triangle)(vec3s origin,
+ vec3s direction,
+ vec3s v0,
+ vec3s v1,
+ vec3s v2,
+ float *d) {
+ return glm_ray_triangle(origin.raw, direction.raw, v0.raw, v1.raw, v2.raw, d);
+}
+
+/*!
+ * @brief ray sphere intersection
+ *
+ * returns false if there is no intersection if true:
+ *
+ * - t1 > 0, t2 > 0: ray intersects the sphere at t1 and t2 both ahead of the origin
+ * - t1 < 0, t2 > 0: ray starts inside the sphere, exits at t2
+ * - t1 < 0, t2 < 0: no intersection ahead of the ray ( returns false )
+ * - the caller can check if the intersection points (t1 and t2) fall within a
+ * specific range (for example, tmin < t1, t2 < tmax) to determine if the
+ * intersections are within a desired segment of the ray
+ *
+ * @param[in] origin ray origin
+ * @param[out] dir normalized ray direction
+ * @param[in] s sphere [center.x, center.y, center.z, radii]
+ * @param[in] t1 near point1 (closer to origin)
+ * @param[in] t2 far point2 (farther from origin)
+ *
+ * @returns whether there is intersection
+ */
+CGLM_INLINE
+bool
+glms_ray_(sphere)(vec3s origin,
+ vec3s dir,
+ vec4s s,
+ float * __restrict t1,
+ float * __restrict t2) {
+ return glm_ray_sphere(origin.raw, dir.raw, s.raw, t1, t2);
+}
+
+/*!
+ * @brief point using t by 𝐏(𝑡)=𝐀+𝑡𝐛
+ *
+ * @param[in] orig origin of ray
+ * @param[in] dir direction of ray
+ * @param[in] t parameter
+ * @returns point point at t
+ */
+CGLM_INLINE
+vec3s
+glms_ray_(at)(vec3s orig, vec3s dir, float t) {
+ vec3s r;
+ glm_ray_at(orig.raw, dir.raw, t, r.raw);
+ return r;
+}
+
+#endif /* cglms_ray_h */
diff --git a/include/cglm/struct/sphere.h b/include/cglm/struct/sphere.h
new file mode 100644
index 0000000..9859c72
--- /dev/null
+++ b/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/include/cglm/struct/vec2-ext.h b/include/cglm/struct/vec2-ext.h
new file mode 100644
index 0000000..246132f
--- /dev/null
+++ b/include/cglm/struct/vec2-ext.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
+ */
+
+/*!
+ * @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_abs(vec2s v)
+ CGLM_INLINE vec2s glms_vec2_fract(vec2s v)
+ CGLM_INLINE vec2s glms_vec2_floor(vec2s v)
+ CGLM_INLINE vec2s glms_vec2_mods(vec2s v, float s)
+ CGLM_INLINE vec2s glms_vec2_steps(float edge, vec2s v)
+ CGLM_INLINE vec2s glms_vec2_stepr(vec2s edge, float 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"
+
+/* api definition */
+#define glms_vec2_(NAME) CGLM_STRUCTAPI(vec2, NAME)
+
+/*!
+ * @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 vector 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 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_vec2_(isnan)(vec2s v) {
+ return glm_vec2_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_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 fractional part of each vector item
+ *
+ * @param v vector
+ * @returns abs vector
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_(abs)(vec2s v) {
+ vec2s r;
+ glm_vec2_abs(v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief fractional part of each vector item
+ *
+ * @param[in] v vector
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_(fract)(vec2s v) {
+ vec2s r;
+ glm_vec2_fract(v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief floor of each vector item
+ *
+ * @param[in] v vector
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_(floor)(vec2s v) {
+ vec2s r;
+ glm_vec2_floor(v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief mod of each vector item by scalar
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_(mods)(vec2s v, float s) {
+ vec2s r;
+ glm_vec2_mods(v.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief threshold each vector item with scalar
+ * condition is: (x[i] < edge) ? 0.0 : 1.0
+ *
+ * @param[in] edge threshold
+ * @param[in] x vector to test against threshold
+ * @returns destination
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_(steps)(float edge, vec2s x) {
+ vec2s r;
+ glm_vec2_steps(edge, x.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief threshold a value with *vector* as the threshold
+ * condition is: (x < edge[i]) ? 0.0 : 1.0
+ *
+ * @param[in] edge threshold vector
+ * @param[in] x value to test against threshold
+ * @returns destination
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_(stepr)(vec2s edge, float x) {
+ vec2s r;
+ glm_vec2_stepr(edge.raw, x, 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/include/cglm/struct/vec2.h b/include/cglm/struct/vec2.h
new file mode 100644
index 0000000..40ed659
--- /dev/null
+++ b/include/cglm/struct/vec2.h
@@ -0,0 +1,747 @@
+/*
+ * 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_subsub(vec2s a, vec2s b, vec2s dest)
+ CGLM_INLINE vec2s glms_vec2_addsub(vec2s a, vec2s b, vec2s dest)
+ CGLM_INLINE vec2s glms_vec2_mulsub(vec2s a, vec2s b, vec2s dest)
+ CGLM_INLINE vec2s glms_vec2_mulsubs(vec2s a, float s, vec2s dest)
+ CGLM_INLINE vec2s glms_vec2_maxsub(vec2s a, vec2s b, vec2s dest)
+ CGLM_INLINE vec2s glms_vec2_minsub(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 vec2s glms_vec2_center(vec2s a, vec2s b)
+ 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)
+ CGLM_INLINE vec2s glms_vec2_step(vec2s edge, vec2s x)
+ CGLM_INLINE vec2s glms_vec2_make(float * restrict src)
+ CGLM_INLINE vec2s glms_vec2_reflect(vec2s v, vec2s n)
+ CGLM_INLINE bool glms_vec2_refract(vec2s v, vec2s n, float eta, vec2s *dest)
+ */
+
+#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 function 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 vectors (component-wise multiplication)
+ *
+ * @param a vector1
+ * @param b vector2
+ * @returns result = (a[0] * b[0], a[1] * b[1])
+ */
+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])
+ */
+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)
+ */
+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 vectors 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 vectors 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 sub two vectors and sub 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_(subsub)(vec2s a, vec2s b, vec2s dest) {
+ glm_vec2_subsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief add two vectors and sub 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_(addsub)(vec2s a, vec2s b, vec2s dest) {
+ glm_vec2_addsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief mul two vectors and sub 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_(mulsub)(vec2s a, vec2s b, vec2s dest) {
+ glm_vec2_mulsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief mul vector with scalar and sub result to dest
+ *
+ * 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_(mulsubs)(vec2s a, float s, vec2s dest) {
+ glm_vec2_mulsubs(a.raw, s, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief sub max of two vectors to 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_(maxsub)(vec2s a, vec2s b, vec2s dest) {
+ glm_vec2_maxsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief sub min of two vectors to 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_(minsub)(vec2s a, vec2s b, vec2s dest) {
+ glm_vec2_minsub(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 find center point of two vector
+ *
+ * @param[in] a vector1
+ * @param[in] b vector2
+ * @returns center point
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_(center)(vec2s a, vec2s b) {
+ vec2s r;
+ glm_vec2_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_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;
+}
+
+/*!
+ * @brief threshold function
+ *
+ * @param[in] edge threshold
+ * @param[in] x value to test against threshold
+ * @returns destination
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_(step)(vec2s edge, vec2s x) {
+ vec2s r;
+ glm_vec2_step(edge.raw, x.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief Create two dimensional vector from pointer
+ *
+ * @param[in] src pointer to an array of floats
+ * @returns constructed 2D vector from raw pointer
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_(make)(const float * __restrict src) {
+ vec2s dest;
+ glm_vec2_make(src, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief reflection vector using an incident ray and a surface normal
+ *
+ * @param[in] I incident vector
+ * @param[in] N normalized normal vector
+ * @returns reflection result
+ */
+CGLM_INLINE
+vec2s
+glms_vec2_(reflect)(vec2s v, vec2s n) {
+ vec2s dest;
+ glm_vec2_reflect(v.raw, n.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief computes refraction vector for an incident vector and a surface normal.
+ *
+ * calculates the refraction vector based on Snell's law. If total internal reflection
+ * occurs (angle too great given eta), dest is set to zero and returns false.
+ * Otherwise, computes refraction vector, stores it in dest, and returns true.
+ *
+ * @param[in] v normalized incident vector
+ * @param[in] n normalized normal vector
+ * @param[in] eta ratio of indices of refraction (incident/transmitted)
+ * @param[out] dest refraction vector if refraction occurs; zero vector otherwise
+ *
+ * @returns true if refraction occurs; false if total internal reflection occurs.
+ */
+CGLM_INLINE
+bool
+glms_vec2_(refract)(vec2s v, vec2s n, float eta, vec2s * __restrict dest) {
+ return glm_vec2_refract(v.raw, n.raw, eta, dest->raw);
+}
+
+#endif /* cglms_vec2s_h */
diff --git a/include/cglm/struct/vec3-ext.h b/include/cglm/struct/vec3-ext.h
new file mode 100644
index 0000000..6cd8ca0
--- /dev/null
+++ b/include/cglm/struct/vec3-ext.h
@@ -0,0 +1,325 @@
+/*
+ * 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 vec3s glms_vec3_floor(vec3s v);
+ CGLM_INLINE vec3s glms_vec3_mods(vec3s v, float s);
+ CGLM_INLINE vec3s glms_vec3_steps(float edge, vec3s v);
+ CGLM_INLINE vec3s glms_vec3_stepr(vec3s edge, float 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"
+
+/* api definition */
+#define glms_vec3_(NAME) CGLM_STRUCTAPI(vec3, NAME)
+
+/*!
+ * @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 vector 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 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_vec3_(isnan)(vec3s v) {
+ return glm_vec3_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_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 floor of each vector item
+ *
+ * @param[in] v vector
+ * @return dest destination vector
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_(floor)(vec3s v) {
+ vec3s r;
+ glm_vec3_floor(v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief mod of each vector item by scalar
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_(mods)(vec3s v, float s) {
+ vec3s r;
+ glm_vec3_mods(v.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief threshold each vector item with scalar
+ * condition is: (x[i] < edge) ? 0.0 : 1.0
+ *
+ * @param[in] edge threshold
+ * @param[in] x vector to test against threshold
+ * @returns destination
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_(steps)(float edge, vec3s x) {
+ vec3s r;
+ glm_vec3_steps(edge, x.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief threshold a value with *vector* as the threshold
+ * condition is: (x < edge[i]) ? 0.0 : 1.0
+ *
+ * @param[in] edge threshold vector
+ * @param[in] x value to test against threshold
+ * @returns destination
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_(stepr)(vec3s edge, float x) {
+ vec3s r;
+ glm_vec3_stepr(edge.raw, x, 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/include/cglm/struct/vec3.h b/include/cglm/struct/vec3.h
new file mode 100644
index 0000000..a1d901e
--- /dev/null
+++ b/include/cglm/struct/vec3.h
@@ -0,0 +1,1132 @@
+/*
+ * 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_subsub(vec3s a, vec3s b, vec3s dest);
+ CGLM_INLINE vec3s glms_vec3_addsub(vec3s a, vec3s b, vec3s dest);
+ CGLM_INLINE vec3s glms_vec3_mulsub(vec3s a, vec3s b, vec3s dest);
+ CGLM_INLINE vec3s glms_vec3_mulsubs(vec3s a, float s, vec3s dest);
+ CGLM_INLINE vec3s glms_vec3_maxsub(vec3s a, vec3s b, vec3s dest);
+ CGLM_INLINE vec3s glms_vec3_minsub(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_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(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);
+ CGLM_INLINE vec3s glms_vec3_make(float * restrict src);
+ CGLM_INLINE vec3s glms_vec3_faceforward(vec3s n, vec3s v, vec3s nref);
+ CGLM_INLINE vec3s glms_vec3_reflect(vec3s v, vec3s n);
+ CGLM_INLINE bool glms_vec3_refract(vec3s v, vec3s n, float eta, vec3s *dest)
+
+ 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);
+
+ Deprecated:
+ glms_vec3_step_uni --> use glms_vec3_steps
+ */
+
+#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"
+
+/* DEPRECATED! */
+#define glms_vec3_step_uni(edge, x) glms_vec3_steps(edge, x)
+
+#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 function 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 vectors (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 vectors 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 vectors 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 sub two vectors and sub 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_(subsub)(vec3s a, vec3s b, vec3s dest) {
+ glm_vec3_subsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief add two vectors and sub 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_(addsub)(vec3s a, vec3s b, vec3s dest) {
+ glm_vec3_addsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief mul two vectors and sub 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_(mulsub)(vec3s a, vec3s b, vec3s dest) {
+ glm_vec3_mulsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief mul vector with scalar and sub result to dest
+ *
+ * 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_(mulsubs)(vec3s a, float s, vec3s dest) {
+ glm_vec3_mulsubs(a.raw, s, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief sub max of two vectors to 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_(maxsub)(vec3s a, vec3s b, vec3s dest) {
+ glm_vec3_maxsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief sub min of two vectors to 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_(minsub)(vec3s a, vec3s b, vec3s dest) {
+ glm_vec3_minsub(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 between 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
+ *
+ * @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 existing 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;
+}
+
+/*!
+ * @brief Create three dimensional vector from pointer
+ *
+ * @param[in] src pointer to an array of floats
+ * @returns constructed 3D vector from raw pointer
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_(make)(const float * __restrict src) {
+ vec3s dest;
+ glm_vec3_make(src, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief a vector pointing in the same direction as another
+ *
+ * orients a vector to point away from a surface as defined by its normal
+ *
+ * @param[in] n vector to orient.
+ * @param[in] v incident vector
+ * @param[in] nref reference vector
+ * @returns oriented vector, pointing away from the surface.
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_(faceforward)(vec3s n, vec3s v, vec3s nref) {
+ vec3s dest;
+ glm_vec3_faceforward(n.raw, v.raw, nref.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief reflection vector using an incident ray and a surface normal
+ *
+ * @param[in] I incident vector
+ * @param[in] N normalized normal vector
+ * @returns reflection result
+ */
+CGLM_INLINE
+vec3s
+glms_vec3_(reflect)(vec3s v, vec3s n) {
+ vec3s dest;
+ glm_vec3_reflect(v.raw, n.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief computes refraction vector for an incident vector and a surface normal.
+ *
+ * calculates the refraction vector based on Snell's law. If total internal reflection
+ * occurs (angle too great given eta), dest is set to zero and returns false.
+ * Otherwise, computes refraction vector, stores it in dest, and returns true.
+ *
+ * @param[in] v normalized incident vector
+ * @param[in] n normalized normal vector
+ * @param[in] eta ratio of indices of refraction (incident/transmitted)
+ * @param[out] dest refraction vector if refraction occurs; zero vector otherwise
+ *
+ * @returns true if refraction occurs; false if total internal reflection occurs.
+ */
+CGLM_INLINE
+bool
+glms_vec3_(refract)(vec3s v, vec3s n, float eta, vec3s * __restrict dest) {
+ return glm_vec3_refract(v.raw, n.raw, eta, dest->raw);
+}
+
+#endif /* cglms_vec3s_h */
diff --git a/include/cglm/struct/vec4-ext.h b/include/cglm/struct/vec4-ext.h
new file mode 100644
index 0000000..f57348e
--- /dev/null
+++ b/include/cglm/struct/vec4-ext.h
@@ -0,0 +1,325 @@
+/*
+ * 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_floor(vec4s v);
+ CGLM_INLINE float glms_vec4_mods(vec4s v, float s);
+ CGLM_INLINE float glms_vec4_steps(float edge, vec4s v);
+ CGLM_INLINE void glms_vec4_stepr(vec4s edge, float 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"
+
+/* api definition */
+#define glms_vec4_(NAME) CGLM_STRUCTAPI(vec4, NAME)
+
+/*!
+ * @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 vector 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 floor of each vector item
+ *
+ * @param[in] v vector
+ * @returns dest destination vector
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_(floor)(vec4s v) {
+ vec4s r;
+ glm_vec4_floor(v.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief mod of each vector item by scalar
+ *
+ * @param[in] v vector
+ * @param[in] s scalar
+ * @returns destination vector
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_(mods)(vec4s v, float s) {
+ vec4s r;
+ glm_vec4_mods(v.raw, s, r.raw);
+ return r;
+}
+
+/*!
+ * @brief threshold each vector item with scalar
+ * condition is: (x[i] < edge) ? 0.0 : 1.0
+ *
+ * @param[in] edge threshold
+ * @param[in] x vector to test against threshold
+ * @returns destination
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_(steps)(float edge, vec4s x) {
+ vec4s r;
+ glm_vec4_steps(edge, x.raw, r.raw);
+ return r;
+}
+
+/*!
+ * @brief threshold a value with *vector* as the threshold
+ * condition is: (x < edge[i]) ? 0.0 : 1.0
+ *
+ * @param[in] edge threshold vector
+ * @param[in] x value to test against threshold
+ * @returns destination
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_(stepr)(vec4s edge, float x) {
+ vec4s r;
+ glm_vec4_stepr(edge.raw, x, 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/include/cglm/struct/vec4.h b/include/cglm/struct/vec4.h
new file mode 100644
index 0000000..a64c1a3
--- /dev/null
+++ b/include/cglm/struct/vec4.h
@@ -0,0 +1,961 @@
+/*
+ * 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_subsub(vec4s a, vec4s b, vec4s dest);
+ CGLM_INLINE vec4s glms_vec4_addsub(vec4s a, vec4s b, vec4s dest);
+ CGLM_INLINE vec4s glms_vec4_mulsub(vec4s a, vec4s b, vec4s dest);
+ CGLM_INLINE vec4s glms_vec4_mulsubs(vec4s a, float s, vec4s dest);
+ CGLM_INLINE vec4s glms_vec4_maxsub(vec4s a, vec4s b, vec4s dest);
+ CGLM_INLINE vec4s glms_vec4_minsub(vec4s a, vec4s b, vec4s dest);
+ CGLM_INLINE vec4s glms_vec4_negate(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(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);
+ CGLM_INLINE vec4s glms_vec4_make(float * restrict src);
+ CGLM_INLINE vec4s glms_vec4_reflect(vec4s v, vec4s n);
+ CGLM_INLINE bool glms_vec4_refract(vec4s v, vec4s n, float eta, vec4s *dest)
+
+ Deprecated:
+ glms_vec4_step_uni --> use glms_vec4_steps
+ */
+
+#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"
+
+/* DEPRECATED! */
+#define glms_vec4_step_uni(edge, x) glms_vec4_steps(edge, x)
+
+#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 function 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 vectors (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 vectors 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 vectors 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 sub two vectors and sub 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_(subsub)(vec4s a, vec4s b, vec4s dest) {
+ glm_vec4_subsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief add two vectors and sub 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_(addsub)(vec4s a, vec4s b, vec4s dest) {
+ glm_vec4_addsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief mul two vectors and sub 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_(mulsub)(vec4s a, vec4s b, vec4s dest) {
+ glm_vec4_mulsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief mul vector with scalar and sub result to dest
+ *
+ * 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_(mulsubs)(vec4s a, float s, vec4s dest) {
+ glm_vec4_mulsubs(a.raw, s, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief sub max of two vectors to 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_(maxsub)(vec4s a, vec4s b, vec4s dest) {
+ glm_vec4_maxsub(a.raw, b.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief sub min of two vectors to 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_(minsub)(vec4s a, vec4s b, vec4s dest) {
+ glm_vec4_minsub(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
+ *
+ * @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 existing 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;
+}
+
+/*!
+ * @brief Create four dimensional vector from pointer
+ *
+ * @param[in] src pointer to an array of floats
+ * @returns constructed 4D vector from raw pointer
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_(make)(const float * __restrict src) {
+ vec4s dest;
+ glm_vec4_make(src, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief reflection vector using an incident ray and a surface normal
+ *
+ * @param[in] v incident vector
+ * @param[in] n normalized normal vector
+ * @returns reflection result
+ */
+CGLM_INLINE
+vec4s
+glms_vec4_(reflect)(vec4s v, vec4s n) {
+ vec4s dest;
+ glm_vec4_reflect(v.raw, n.raw, dest.raw);
+ return dest;
+}
+
+/*!
+ * @brief computes refraction vector for an incident vector and a surface normal.
+ *
+ * calculates the refraction vector based on Snell's law. If total internal reflection
+ * occurs (angle too great given eta), dest is set to zero and returns false.
+ * Otherwise, computes refraction vector, stores it in dest, and returns true.
+ *
+ * this implementation does not explicitly preserve the 'w' component of the
+ * incident vector 'I' in the output 'dest', users requiring the preservation of
+ * the 'w' component should manually adjust 'dest' after calling this function.
+ *
+ * @param[in] v normalized incident vector
+ * @param[in] n normalized normal vector
+ * @param[in] eta ratio of indices of refraction (incident/transmitted)
+ * @param[out] dest refraction vector if refraction occurs; zero vector otherwise
+ *
+ * @returns true if refraction occurs; false if total internal reflection occurs.
+ */
+CGLM_INLINE
+bool
+glms_vec4_(refract)(vec4s v, vec4s n, float eta, vec4s * __restrict dest) {
+ return glm_vec4_refract(v.raw, n.raw, eta, dest->raw);
+}
+
+#endif /* cglms_vec4s_h */