diff --git a/include/cglm/cglms.h b/include/cglm/cglms.h new file mode 100644 index 0000000..0ecc8de --- /dev/null +++ b/include/cglm/cglms.h @@ -0,0 +1,33 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_structs_h +#define cglm_structs_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "cglm.h" +#include "types-struct.h" +#include "struct/vec3.h" +#include "struct/vec4.h" +#include "struct/mat3.h" +#include "struct/mat4.h" +#include "struct/affine.h" +#include "struct/frustum.h" +#include "struct/plane.h" +#include "struct/box.h" +#include "struct/color.h" +#include "struct/io.h" +#include "struct/project.h" +#include "struct/sphere.h" +#include "struct/curve.h" + +#ifdef __cplusplus +} +#endif +#endif /* cglm_structs_h */ diff --git a/include/cglm/frustum.h b/include/cglm/frustum.h index 78b39d2..5aa3c17 100644 --- a/include/cglm/frustum.h +++ b/include/cglm/frustum.h @@ -65,7 +65,7 @@ * Exracted planes order: [left, right, bottom, top, near, far] * * @param[in] m matrix (see brief) - * @param[out] dest exracted view frustum planes (see brief) + * @param[out] dest extracted view frustum planes (see brief) */ CGLM_INLINE void diff --git a/include/cglm/plane.h b/include/cglm/plane.h index 48fe879..7a5291d 100644 --- a/include/cglm/plane.h +++ b/include/cglm/plane.h @@ -25,7 +25,7 @@ /*! * @brief normalizes a plane * - * @param[in, out] plane pnale to normalize + * @param[in, out] plane plane to normalize */ CGLM_INLINE void diff --git a/include/cglm/struct/affine.h b/include/cglm/struct/affine.h new file mode 100644 index 0000000..0f753c5 --- /dev/null +++ b/include/cglm/struct/affine.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 + */ + +/* + Functions: + CGLM_INLINE mat4s glms_translate(mat4s m, vec3s v); + CGLM_INLINE mat4s glms_translate_x(mat4s m, float x); + CGLM_INLINE mat4s glms_translate_y(mat4s m, float y); + CGLM_INLINE mat4s glms_translate_z(mat4s m, float z); + CGLM_INLINE mat4s glms_translate_make(vec3s v); + CGLM_INLINE mat4s glms_scale_to(mat4s m, vec3s v); + CGLM_INLINE mat4s glms_scale_make(vec3s v); + CGLM_INLINE mat4s glms_scale(mat4s m, vec3s v); + CGLM_INLINE mat4s glms_scale_uni(mat4s m, float s); + CGLM_INLINE mat4s glmx_rotate_x(mat4s m, float angle); + CGLM_INLINE mat4s glms_rotate_y(mat4s m, float angle); + CGLM_INLINE mat4s glms_rotate_z(mat4s m, float angle); + CGLM_INLINE mat4s glms_rotate_make(float angle, vec3s axis); + CGLM_INLINE mat4s glms_rotate(mat4s m, float angle, vec3s axis); + CGLM_INLINE mat4s glms_rotate_at(mat4s m, vec3s pivot, float angle, vec3s axis); + CGLM_INLINE mat4s glms_rotate_atm(mat4s m, vec3s pivot, float angle, vec3s axis); + CGLM_INLINE vec3s glms_decompose_scalev(mat4s m); + CGLM_INLINE bool glms_uniscaled(mat4s m); + CGLM_INLINE void glms_decompose_rs(mat4s m, mat4s * r, vec3s * s); + CGLM_INLINE void glms_decompose(mat4s m, vec4s t, mat4s * r, vec3s * s); + */ + +#ifndef cglm_affines_h +#define cglm_affines_h + +#include "../common.h" +#include "../types-struct.h" +#include "../affine.h" +#include "vec3.h" +#include "vec4.h" +#include "mat4.h" + +CGLM_INLINE +mat4s +glms_mat4_mul(mat4s m1, mat4s m2); + +/*! + * @brief translate existing transform matrix by v vector + * and stores result in same matrix + * + * @param[in] m affine transfrom + * @param[in] v translate vector [x, y, z] + * @returns affine transfrom + */ +CGLM_INLINE +mat4s +glms_translate(mat4s m, vec3s v) { + glm_translate(m.raw, v.raw); + return m; +} + +/*! + * @brief translate existing transform matrix by x factor + * + * @param[in] m affine transfrom + * @param[in] x x factor + * @returns affine transfrom + */ +CGLM_INLINE +mat4s +glms_translate_x(mat4s m, float x) { + glm_translate_x(m.raw, x); + return m; +} + +/*! + * @brief translate existing transform matrix by y factor + * + * @param[in] m affine transfrom + * @param[in] y y factor + * @returns affine transfrom + */ +CGLM_INLINE +mat4s +glms_translate_y(mat4s m, float y) { + glm_translate_y(m.raw, y); + return m; +} + +/*! + * @brief translate existing transform matrix by z factor + * + * @param[in] m affine transfrom + * @param[in] z z factor + * @returns affine transfrom + */ +CGLM_INLINE +mat4s +glms_translate_z(mat4s m, float z) { + glm_translate_z(m.raw, z); + return m; +} + +/*! + * @brief creates NEW translate transform matrix by v vector + * + * @param[in] v translate vector [x, y, z] + * @returns affine transfrom + */ +CGLM_INLINE +mat4s +glms_translate_make(vec3s v) { + mat4s m; + glm_translate_make(m.raw, v.raw); + return m; +} + +/*! + * @brief creates NEW scale matrix by v vector + * + * @param[out] m affine transfrom + * @param[in] v scale vector [x, y, z] + */ +CGLM_INLINE +mat4s +glms_scale_make(vec3s v) { + mat4s m; + glm_scale_make(m.raw, v.raw); + return m; +} + +/*! + * @brief scales existing transform matrix by v vector + * and stores result in same matrix + * + * @param[in] m affine transfrom + * @param[in] v scale vector [x, y, z] + * @returns affine transfrom + */ +CGLM_INLINE +mat4s +glms_scale(mat4s m, vec3s v) { + mat4s r; + glm_scale_to(m.raw, v.raw, r.raw); + return r; +} + +/*! + * @brief applies uniform scale to existing transform matrix v = [s, s, s] + * and stores result in same matrix + * + * @param[in] m affine transfrom + * @param[in] s scale factor + * @returns affine transfrom + */ +CGLM_INLINE +mat4s +glms_scale_uni(mat4s m, float s) { + glm_scale_uni(m.raw, s); + return m; +} + +/*! + * @brief rotate existing transform matrix around X axis by angle + * and store result in dest + * + * @param[in] m affine transfrom + * @param[in] angle angle (radians) + * @returns rotated matrix + */ +CGLM_INLINE +mat4s +glmx_rotate_x(mat4s m, float angle) { + mat4s r; + glm_rotate_x(m.raw, angle, r.raw); + return r; +} + +/*! + * @brief rotate existing transform matrix around Y axis by angle + * and store result in dest + * + * @param[in] m affine transfrom + * @param[in] angle angle (radians) + * @returns rotated matrix + */ +CGLM_INLINE +mat4s +glms_rotate_y(mat4s m, float angle) { + mat4s r; + glm_rotate_y(m.raw, angle, r.raw); + return r; +} + +/*! + * @brief rotate existing transform matrix around Z axis by angle + * and store result in dest + * + * @param[in] m affine transfrom + * @param[in] angle angle (radians) + * @returns rotated matrix + */ +CGLM_INLINE +mat4s +glms_rotate_z(mat4s m, float angle) { + mat4s r; + glm_rotate_z(m.raw, angle, r.raw); + return r; +} + +/*! + * @brief creates NEW rotation matrix by angle and axis + * + * axis will be normalized so you don't need to normalize it + * + * @param[in] angle angle (radians) + * @param[in] axis axis + * @returns affine transfrom + */ +CGLM_INLINE +mat4s +glms_rotate_make(float angle, vec3s axis) { + mat4s m; + glm_rotate_make(m.raw, angle, axis.raw); + return m; +} + +/*! + * @brief rotate existing transform matrix around given axis by angle + * + * @param[in] m affine transfrom + * @param[in] angle angle (radians) + * @param[in] axis axis + * @returns affine transfrom + */ +CGLM_INLINE +mat4s +glms_rotate(mat4s m, float angle, vec3s axis) { + glm_rotate(m.raw, angle, axis.raw); + return m; +} + +/*! + * @brief rotate existing transform + * around given axis by angle at given pivot point (rotation center) + * + * @param[in] m affine transfrom + * @param[in] pivot rotation center + * @param[in] angle angle (radians) + * @param[in] axis axis + * @returns affine transfrom + */ +CGLM_INLINE +mat4s +glms_rotate_at(mat4s m, vec3s pivot, float angle, vec3s axis) { + glm_rotate_at(m.raw, pivot.raw, angle, axis.raw); + return m; +} + +/*! + * @brief creates NEW rotation matrix by angle and axis at given point + * + * this creates rotation matrix, it assumes you don't have a matrix + * + * this should work faster than glm_rotate_at because it reduces + * one glm_translate. + * + * @param[in] m affine transfrom + * @param[in] pivot rotation center + * @param[in] angle angle (radians) + * @param[in] axis axis + * @returns affine transfrom + */ +CGLM_INLINE +mat4s +glms_rotate_atm(mat4s m, vec3s pivot, float angle, vec3s axis) { + glm_rotate_atm(m.raw, pivot.raw, angle, axis.raw); + return m; +} + +/*! + * @brief decompose scale vector + * + * @param[in] m affine transform + * @returns scale vector (Sx, Sy, Sz) + */ +CGLM_INLINE +vec3s +glms_decompose_scalev(mat4s m) { + vec3s r; + glm_decompose_scalev(m.raw, r.raw); + return r; +} + +/*! + * @brief returns true if matrix is uniform scaled. This is helpful for + * creating normal matrix. + * + * @param[in] m m + * + * @return boolean + */ +CGLM_INLINE +bool +glms_uniscaled(mat4s m) { + return glm_uniscaled(m.raw); +} + +/*! + * @brief decompose rotation matrix (mat4) and scale vector [Sx, Sy, Sz] + * DON'T pass projected matrix here + * + * @param[in] m affine transform + * @param[out] r rotation matrix + * @param[out] s scale matrix + */ +CGLM_INLINE +void +glms_decompose_rs(mat4s m, mat4s * __restrict r, vec3s * __restrict s) { + glm_decompose_rs(m.raw, r->raw, s->raw); +} + +/*! + * @brief decompose affine transform, TODO: extract shear factors. + * DON'T pass projected matrix here + * + * @param[in] m affine transfrom + * @param[out] t translation vector + * @param[out] r rotation matrix (mat4) + * @param[out] s scaling vector [X, Y, Z] + */ +CGLM_INLINE +void +glms_decompose(mat4s m, vec4s * __restrict t, mat4s * __restrict r, vec3s * __restrict s) { + glm_decompose(m.raw, t->raw, r->raw, s->raw); +} + +#endif /* cglm_affines_h */ diff --git a/include/cglm/struct/box.h b/include/cglm/struct/box.h new file mode 100644 index 0000000..9dc915e --- /dev/null +++ b/include/cglm/struct/box.h @@ -0,0 +1,256 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_boxs_h +#define cglm_boxs_h + +#include "../common.h" +#include "../types-struct.h" +#include "../box.h" +#include "vec3.h" +#include "vec4.h" +#include "mat4.h" + +/*! + * @brief apply transform to Axis-Aligned Bounding Box + * + * @param[in] box bounding box + * @param[in] m transform matrix + * @param[out] dest transformed bounding box + */ +CGLM_INLINE +void +glms_aabb_transform(vec3s box[2], mat4s m, vec3s dest[2]) { + vec3 rawBox[2]; + vec3 rawDest[2]; + + glms_vec3_unpack(rawBox, box, 2); + glm_aabb_transform(rawBox, m.raw, rawDest); + glms_vec3_pack(dest, rawDest, 2); +} + +/*! + * @brief merges two AABB bounding box and creates new one + * + * two box must be in same space, if one of box is in different space then + * you should consider to convert it's space by glm_box_space + * + * @param[in] box1 bounding box 1 + * @param[in] box2 bounding box 2 + * @param[out] dest merged bounding box + */ +CGLM_INLINE +void +glms_aabb_merge(vec3s box1[2], vec3s box2[2], vec3s dest[2]) { + vec3 rawBox1[2]; + vec3 rawBox2[2]; + vec3 rawDest[2]; + + glms_vec3_unpack(rawBox1, box1, 2); + glms_vec3_unpack(rawBox2, box2, 2); + glm_aabb_merge(rawBox1, rawBox2, rawDest); + glms_vec3_pack(dest, rawDest, 2); +} + +/*! + * @brief crops a bounding box with another one. + * + * this could be useful for gettng a bbox which fits with view frustum and + * object bounding boxes. In this case you crop view frustum box with objects + * box + * + * @param[in] box bounding box 1 + * @param[in] cropBox crop box + * @param[out] dest cropped bounding box + */ +CGLM_INLINE +void +glms_aabb_crop(vec3s box[2], vec3s cropBox[2], vec3s dest[2]) { + vec3 rawBox[2]; + vec3 rawCropBox[2]; + vec3 rawDest[2]; + + glms_vec3_unpack(rawBox, box, 2); + glms_vec3_unpack(rawCropBox, cropBox, 2); + glm_aabb_crop(rawBox, rawCropBox, rawDest); + glms_vec3_pack(dest, rawDest, 2); +} + +/*! + * @brief crops a bounding box with another one. + * + * this could be useful for gettng a bbox which fits with view frustum and + * object bounding boxes. In this case you crop view frustum box with objects + * box + * + * @param[in] box bounding box + * @param[in] cropBox crop box + * @param[in] clampBox miniumum box + * @param[out] dest cropped bounding box + */ +CGLM_INLINE +void +glms_aabb_crop_until(vec3s box[2], + vec3s cropBox[2], + vec3s clampBox[2], + vec3s dest[2]) { + glms_aabb_crop(box, cropBox, dest); + glms_aabb_merge(clampBox, dest, dest); +} + +/*! + * @brief check if AABB intersects with frustum planes + * + * this could be useful for frustum culling using AABB. + * + * OPTIMIZATION HINT: + * if planes order is similar to LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR + * then this method should run even faster because it would only use two + * planes if object is not inside the two planes + * fortunately cglm extracts planes as this order! just pass what you got! + * + * @param[in] box bounding box + * @param[in] planes frustum planes + */ +CGLM_INLINE +bool +glms_aabb_frustum(vec3s box[2], vec4s planes[6]) { + vec3 rawBox[2]; + vec4 rawPlanes[6]; + + glms_vec3_unpack(rawBox, box, 2); + glms_vec4_unpack(rawPlanes, planes, 6); + return glm_aabb_frustum(rawBox, rawPlanes); +} + +/*! + * @brief invalidate AABB min and max values + * + * @param[in, out] box bounding box + */ +CGLM_INLINE +void +glms_aabb_invalidate(vec3s box[2]) { + box[0] = glms_vec3_broadcast(FLT_MAX); + box[1] = glms_vec3_broadcast(-FLT_MAX); +} + +/*! + * @brief check if AABB is valid or not + * + * @param[in] box bounding box + */ +CGLM_INLINE +bool +glms_aabb_isvalid(vec3s box[2]) { + vec3 rawBox[2]; + glms_vec3_unpack(rawBox, box, 2); + return glm_aabb_isvalid(rawBox); +} + +/*! + * @brief distance between of min and max + * + * @param[in] box bounding box + */ +CGLM_INLINE +float +glms_aabb_size(vec3s box[2]) { + return glm_vec3_distance(box[0].raw, box[1].raw); +} + +/*! + * @brief radius of sphere which surrounds AABB + * + * @param[in] box bounding box + */ +CGLM_INLINE +float +glms_aabb_radius(vec3s box[2]) { + return glms_aabb_size(box) * 0.5f; +} + +/*! + * @brief computes center point of AABB + * + * @param[in] box bounding box + * @param[out] dest 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 /* cglm_boxs_h */ diff --git a/include/cglm/struct/color.h b/include/cglm/struct/color.h new file mode 100644 index 0000000..e9ddc0c --- /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 cglm_colors_h +#define cglm_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 /* cglm_colors_h */ diff --git a/include/cglm/struct/curve.h b/include/cglm/struct/curve.h new file mode 100644 index 0000000..0972f0f --- /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 cglm_curves_h +#define cglm_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 /* cglm_curves_h */ diff --git a/include/cglm/struct/frustum.h b/include/cglm/struct/frustum.h new file mode 100644 index 0000000..98931f4 --- /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 cglm_frustums_h +#define cglm_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 /* cglm_frustums_h */ diff --git a/include/cglm/struct/io.h b/include/cglm/struct/io.h new file mode 100644 index 0000000..0a084e4 --- /dev/null +++ b/include/cglm/struct/io.h @@ -0,0 +1,82 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_mat4_print(mat4 matrix, FILE *ostream); + CGLM_INLINE void glm_mat3_print(mat3 matrix, FILE *ostream); + CGLM_INLINE void glm_vec4_print(vec4 vec, FILE *ostream); + CGLM_INLINE void glm_vec3_print(vec3 vec, FILE *ostream); + CGLM_INLINE void glm_ivec3_print(ivec3 vec, FILE *ostream); + CGLM_INLINE void glm_versor_print(versor vec, FILE *ostream); + */ + +#ifndef cglm_ios_h +#define cglm_ios_h + +#include "../common.h" +#include "../io.h" +#include "mat4.h" + +#include +#include + +CGLM_INLINE +void +glms_mat4_print(mat4s matrix, + FILE * __restrict ostream) { + + glm_mat4_print(matrix.raw, ostream); +} + +CGLM_INLINE +void +glms_mat3_print(mat3s matrix, + FILE * __restrict ostream) { + glm_mat3_print(matrix.raw, ostream); +} + +CGLM_INLINE +void +glms_vec4_print(vec4s vec, + FILE * __restrict ostream) { + glm_vec4_print(vec.raw, ostream); +} + +CGLM_INLINE +void +glms_vec3_print(vec3s vec, + FILE * __restrict ostream) { + glm_vec3_print(vec.raw, ostream); +} + +CGLM_INLINE +void +glms_ivec3_print(ivec3s vec, + FILE * __restrict ostream) { + glm_ivec3_print(vec.raw, ostream); +} + +CGLM_INLINE +void +glms_versor_print(versors vec, + FILE * __restrict ostream) { + glm_versor_print(vec.raw, ostream); +} + +CGLM_INLINE +void +glms_aabb_print(vec3s bbox[2], + const char * __restrict tag, + FILE * __restrict ostream) { + vec3 rawBbox[2]; + + glms_vec3_unpack(rawBbox, bbox, 2); + glm_aabb_print(rawBbox, tag, ostream); +} + +#endif /* cglm_ios_h */ diff --git a/include/cglm/struct/mat3.h b/include/cglm/struct/mat3.h new file mode 100644 index 0000000..8072746 --- /dev/null +++ b/include/cglm/struct/mat3.h @@ -0,0 +1,289 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLMS_MAT3_IDENTITY_INIT + GLMS_MAT3_ZERO_INIT + GLMS_MAT3_IDENTITY + GLMS_MAT3_ZERO + + Functions: + CGLM_INLINE mat3s glms_mat3_copy(mat3s mat); + CGLM_INLINE mat3s glms_mat3_identity(); + CGLM_INLINE void glms_mat3_identity_array(mat3s * __restrict mat, size_t count); + CGLM_INLINE mat3s glms_mat3_zero(); + CGLM_INLINE mat3s glms_mat3_mul(mat3s m1, mat3s m2); + CGLM_INLINE ma3s glms_mat3_transpose(mat3s m); + CGLM_INLINE vec3s glms_mat3_mulv(mat3s m, vec3s v); + CGLM_INLINE float glms_mat3_trace(mat3s m); + CGLM_INLINE versor glms_mat3_quat(mat3s m); + CGLM_INLINE mat3s glms_mat3_scale(mat3s m, float s); + CGLM_INLINE float glms_mat3_det(mat3s mat); + CGLM_INLINE mat3s glms_mat3_inv(mat3s mat); + CGLM_INLINE mat3s glms_mat3_swap_col(mat3s mat, int col1, int col2); + CGLM_INLINE mat3s glms_mat3_swap_row(mat3s mat, int row1, int row2); + CGLM_INLINE float glms_mat3_rmc(vec3s r, mat3s m, vec3s c); + */ + +#ifndef cglm_mat3s_h +#define cglm_mat3s_h + +#include "../common.h" +#include "../types-struct.h" +#include "../mat3.h" +#include "vec3.h" + +#define GLMS_MAT3_IDENTITY_INIT {1.0f, 0.0f, 0.0f, \ + 0.0f, 1.0f, 0.0f, \ + 0.0f, 0.0f, 1.0f} +#define GLMS_MAT3_ZERO_INIT {0.0f, 0.0f, 0.0f, \ + 0.0f, 0.0f, 0.0f, \ + 0.0f, 0.0f, 0.0f} + +/* for C only */ +#define GLMS_MAT3_IDENTITY ((mat3s)GLMS_MAT3_IDENTITY_INIT) +#define GLMS_MAT3_ZERO ((mat3s)GLMS_MAT3_ZERO_INIT) + +/*! + * @brief copy all members of [mat] to [dest] + * + * @param[in] mat source + * @returns destination + */ +CGLM_INLINE +mat3s +glms_mat3_copy(mat3s mat) { + mat3s r; + glm_mat3_copy(mat.raw, r.raw); + return r; +} + +/*! + * @brief make given matrix identity. It is identical with below, + * but it is more easy to do that with this func especially for members + * e.g. glm_mat3_identity(aStruct->aMatrix); + * + * @code + * glm_mat3_copy(GLM_MAT3_IDENTITY, mat); // C only + * + * // or + * mat3 mat = GLM_MAT3_IDENTITY_INIT; + * @endcode + * + * @returns destination + */ +CGLM_INLINE +mat3s +glms_mat3_identity() { + mat3s r; + glm_mat3_identity(r.raw); + return r; +} + +/*! + * @brief make given matrix array's each element identity matrix + * + * @param[in, out] mat matrix array (must be aligned (16/32) + * if alignment is not disabled) + * + * @param[in] count count of matrices + */ +CGLM_INLINE +void +glms_mat3_identity_array(mat3s * __restrict mat, size_t count) { + CGLM_ALIGN_MAT mat3s t = GLMS_MAT3_IDENTITY_INIT; + size_t i; + + for (i = 0; i < count; i++) { + glm_mat3_copy(t.raw, mat[i].raw); + } +} + +/*! + * @brief make given matrix zero. + * + * @returns matrix + */ +CGLM_INLINE +mat3s +glms_mat3_zero() { + mat3s r; + glm_mat3_zero(r.raw); + return r; +} + +/*! + * @brief multiply m1 and m2 to dest + * + * m1, m2 and dest matrices can be same matrix, it is possible to write this: + * + * @code + * mat3 m = GLM_MAT3_IDENTITY_INIT; + * glm_mat3_mul(m, m, m); + * @endcode + * + * @param[in] m1 left matrix + * @param[in] m2 right matrix + * @returns destination matrix + */ +CGLM_INLINE +mat3s +glms_mat3_mul(mat3s m1, mat3s m2) { + mat3s r; + glm_mat3_mul(m1.raw, m2.raw, r.raw); + return r; +} + +/*! + * @brief tranpose mat3 and store result in same matrix + * + * @param[in, out] m source and dest + */ +CGLM_INLINE +mat3s +glms_mat3_transpose(mat3s m) { + glm_mat3_transpose(m.raw); + return m; +} + +/*! + * @brief multiply mat3 with vec3 (column vector) and store in dest vector + * + * @param[in] m mat3 (left) + * @param[in] v vec3 (right, column vector) + * @returns vec3 (result, column vector) + */ +CGLM_INLINE +vec3s +glms_mat3_mulv(mat3s m, vec3s v) { + vec3s r; + glm_mat3_mulv(m.raw, v.raw, r.raw); + return r; +} + +/*! + * @brief trace of matrix + * + * sum of the elements on the main diagonal from upper left to the lower right + * + * @param[in] m matrix + */ +CGLM_INLINE +float +glms_mat3_trace(mat3s m) { + return glm_mat3_trace(m.raw); +} + +/*! + * @brief convert mat3 to quaternion + * + * @param[in] m rotation matrix + * @returns destination quaternion + */ +CGLM_INLINE +versors +glms_mat3_quat(mat3s m) { + versors r; + glm_mat3_quat(m.raw, r.raw); + return r; +} + +/*! + * @brief scale (multiply with scalar) matrix + * + * multiply matrix with scalar + * + * @param[in] m matrix + * @param[in] s scalar + * @returns scaled matrix + */ +CGLM_INLINE +mat3s +glms_mat3_scale(mat3s m, float s) { + glm_mat3_scale(m.raw, s); + return m; +} + +/*! + * @brief mat3 determinant + * + * @param[in] mat matrix + * + * @return determinant + */ +CGLM_INLINE +float +glms_mat3_det(mat3s mat) { + return glm_mat3_det(mat.raw); +} + +/*! + * @brief inverse mat3 and store in dest + * + * @param[in] mat matrix + * @returns inverse matrix + */ +CGLM_INLINE +mat3s +glms_mat3_inv(mat3s mat) { + mat3s r; + glm_mat3_inv(mat.raw, r.raw); + return r; +} + +/*! + * @brief swap two matrix columns + * + * @param[in] mat matrix + * @param[in] col1 col1 + * @param[in] col2 col2 + * @returns matrix + */ +CGLM_INLINE +mat3s +glms_mat3_swap_col(mat3s mat, int col1, int col2) { + glm_mat3_swap_col(mat.raw, col1, col2); + return mat; +} + +/*! + * @brief swap two matrix rows + * + * @param[in] mat matrix + * @param[in] row1 row1 + * @param[in] row2 row2 + * @returns matrix + */ +CGLM_INLINE +mat3s +glms_mat3_swap_row(mat3s mat, int row1, int row2) { + glm_mat3_swap_row(mat.raw, row1, row2); + return mat; +} + +/*! + * @brief helper for R (row vector) * M (matrix) * C (column vector) + * + * rmc stands for Row * Matrix * Column + * + * the result is scalar because R * M = Matrix1x3 (row vector), + * then Matrix1x3 * Vec3 (column vector) = Matrix1x1 (Scalar) + * + * @param[in] r row vector or matrix1x3 + * @param[in] m matrix3x3 + * @param[in] c column vector or matrix3x1 + * + * @return scalar value e.g. Matrix1x1 + */ +CGLM_INLINE +float +glms_mat3_rmc(vec3s r, mat3s m, vec3s c) { + return glm_mat3_rmc(r.raw, m.raw, c.raw); +} + +#endif /* cglm_mat3s_h */ diff --git a/include/cglm/struct/mat4.h b/include/cglm/struct/mat4.h new file mode 100644 index 0000000..5947dc0 --- /dev/null +++ b/include/cglm/struct/mat4.h @@ -0,0 +1,467 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/*! + * Most of functions in this header are optimized manually with SIMD + * if available. You dont need to call/incude SIMD headers manually + */ + +/* + Macros: + GLMS_MAT4_IDENTITY_INIT + GLMS_MAT4_ZERO_INIT + GLMS_MAT4_IDENTITY + GLMS_MAT4_ZERO + + Functions: + CGLM_INLINE mat4s glms_mat4_ucopy(mat4s mat); + CGLM_INLINE mat4s glms_mat4_copy(mat4s mat); + CGLM_INLINE mat4s glms_mat4_identity(); + CGLM_INLINE void glms_mat4_identity_array(mat4s * __restrict mat, size_t count); + CGLM_INLINE mat4s glms_mat4_zero(); + CGLM_INLINE mat3s glms_mat4_pick3(mat4s mat); + CGLM_INLINE mat3s glms_mat4_pick3t(mat4s mat); + CGLM_INLINE mat4s glms_mat4_ins3(mat3s mat); + CGLM_INLINE mat4s glms_mat4_mul(mat4s m1, mat4s m2); + CGLM_INLINE mat4s glms_mat4_mulN(mat4s * __restrict matrices[], uint32_t len); + CGLM_INLINE vec4s glms_mat4_mulv(mat4s m, vec4s v); + CGLM_INLINE float glms_mat4_trace(mat4s m); + CGLM_INLINE float glms_mat4_trace3(mat4s m); + CGLM_INLINE versors glms_mat4_quat(mat4s m); + CGLM_INLINE vec3s glms_mat4_mulv3(mat4s m, vec3s v, float last); + CGLM_INLINE mat4s glms_mat4_transpose(mat4s m); + CGLM_INLINE mat4s glms_mat4_scale_p(mat4s m, float s); + CGLM_INLINE mat4s glms_mat4_scale(mat4s m, float s); + CGLM_INLINE float glms_mat4_det(mat4s mat); + CGLM_INLINE mat4s glms_mat4_inv(mat4s mat); + CGLM_INLINE mat4s glms_mat4_inv_fast(mat4s mat); + CGLM_INLINE mat4s glms_mat4_swap_col(mat4s mat, int col1, int col2); + CGLM_INLINE mat4s glms_mat4_swap_row(mat4s mat, int row1, int row2); + CGLM_INLINE float glms_mat4_rmc(vec4s r, mat4s m, vec4s c); + */ + +#ifndef cglm_mat4s_h +#define cglm_mat4s_h + +#include "../common.h" +#include "../types-struct.h" +#include "../mat4.h" +#include "vec4.h" +#include "vec3.h" + +#define GLMS_MAT4_IDENTITY_INIT {1.0f, 0.0f, 0.0f, 0.0f, \ + 0.0f, 1.0f, 0.0f, 0.0f, \ + 0.0f, 0.0f, 1.0f, 0.0f, \ + 0.0f, 0.0f, 0.0f, 1.0f} + +#define GLMS_MAT4_ZERO_INIT {0.0f, 0.0f, 0.0f, 0.0f, \ + 0.0f, 0.0f, 0.0f, 0.0f, \ + 0.0f, 0.0f, 0.0f, 0.0f, \ + 0.0f, 0.0f, 0.0f, 0.0f} + +/* for C only */ +#define GLMS_MAT4_IDENTITY ((mat4s)GLMS_MAT4_IDENTITY_INIT) +#define GLMS_MAT4_ZERO ((mat4s)GLMS_MAT4_ZERO_INIT) + +/*! + * @brief copy all members of [mat] to [dest] + * + * matrix may not be aligned, u stands for unaligned, this may be useful when + * copying a matrix from external source e.g. asset importer... + * + * @param[in] mat source + * @returns destination + */ +CGLM_INLINE +mat4s +glms_mat4_ucopy(mat4s mat) { + mat4s r; + glm_mat4_ucopy(mat.raw, r.raw); + return r; +} + +/*! + * @brief copy all members of [mat] to [dest] + * + * @param[in] mat source + * @returns destination + */ +CGLM_INLINE +mat4s +glms_mat4_copy(mat4s mat) { + mat4s r; + glm_mat4_copy(mat.raw, r.raw); + return r; +} + +/*! + * @brief make given matrix identity. It is identical with below, + * but it is more easy to do that with this func especially for members + * e.g. glm_mat4_identity(aStruct->aMatrix); + * + * @code + * glm_mat4_copy(GLM_MAT4_IDENTITY, mat); // C only + * + * // or + * mat4 mat = GLM_MAT4_IDENTITY_INIT; + * @endcode + * + * @retuns destination + */ +CGLM_INLINE +mat4s +glms_mat4_identity() { + mat4s r; + glm_mat4_identity(r.raw); + return r; +} + +/*! + * @brief make given matrix array's each element identity matrix + * + * @param[in, out] mat matrix array (must be aligned (16/32) + * if alignment is not disabled) + * + * @param[in] count count of matrices + */ +CGLM_INLINE +void +glms_mat4_identity_array(mat4s * __restrict mat, size_t count) { + CGLM_ALIGN_MAT mat4s t = GLMS_MAT4_IDENTITY_INIT; + size_t i; + + for (i = 0; i < count; i++) { + glm_mat4_copy(t.raw, mat[i].raw); + } +} + +/*! + * @brief make given matrix zero. + * + * @returns matrix + */ +CGLM_INLINE +mat4s +glms_mat4_zero() { + mat4s r; + glm_mat4_zero(r.raw); + return r; +} + +/*! + * @brief copy upper-left of mat4 to mat3 + * + * @param[in] mat source + * @returns destination + */ +CGLM_INLINE +mat3s +glms_mat4_pick3(mat4s mat) { + mat3s r; + glm_mat4_pick3(mat.raw, r.raw); + return r; +} + +/*! + * @brief copy upper-left of mat4 to mat3 (transposed) + * + * the postfix t stands for transpose + * + * @param[in] mat source + * @returns destination + */ +CGLM_INLINE +mat3s +glms_mat4_pick3t(mat4s mat) { + mat3s r; + glm_mat4_pick3t(mat.raw, r.raw); + return r; +} + +/*! + * @brief copy mat3 to mat4's upper-left + * + * @param[in] mat source + * @returns destination + */ +CGLM_INLINE +mat4s +glms_mat4_ins3(mat3s mat) { + mat4s r; + glm_mat4_ins3(mat.raw, r.raw); + return r; +} + +/*! + * @brief multiply m1 and m2 to dest + * + * m1, m2 and dest matrices can be same matrix, it is possible to write this: + * + * @code + * mat4 m = GLM_MAT4_IDENTITY_INIT; + * glm_mat4_mul(m, m, m); + * @endcode + * + * @param[in] m1 left matrix + * @param[in] m2 right matrix + * @returns destination matrix + */ +CGLM_INLINE +mat4s +glms_mat4_mul(mat4s m1, mat4s m2) { + mat4s r; + glm_mat4_mul(m1.raw, m2.raw, r.raw); + return r; +} + +/*! + * @brief mupliply N mat4 matrices and store result in dest + * + * this function lets you multiply multiple (more than two or more...) matrices + *

multiplication will be done in loop, this may reduce instructions + * size but if len is too small then compiler may unroll whole loop, + * usage: + * @code + * mat m1, m2, m3, m4, res; + * + * res = glm_mat4_mulN((mat4 *[]){&m1, &m2, &m3, &m4}, 4); + * @endcode + * + * @warning matrices parameter is pointer array not mat4 array! + * + * @param[in] matrices mat4 * array + * @param[in] len matrices count + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_mat4_mulN(mat4s * __restrict matrices[], uint32_t len) { + CGLM_ALIGN_MAT mat4s r = GLMS_MAT4_IDENTITY_INIT; + size_t i; + + for (i = 0; i < len; i++) { + r = glms_mat4_mul(r, *matrices[i]); + } + + return r; +} + +/*! + * @brief multiply mat4 with vec4 (column vector) and store in dest vector + * + * @param[in] m mat4 (left) + * @param[in] v vec4 (right, column vector) + * @returns vec4 (result, column vector) + */ +CGLM_INLINE +vec4s +glms_mat4_mulv(mat4s m, vec4s v) { + vec4s r; + glm_mat4_mulv(m.raw, v.raw, r.raw); + return r; +} + +/*! + * @brief trace of matrix + * + * sum of the elements on the main diagonal from upper left to the lower right + * + * @param[in] m matrix + */ +CGLM_INLINE +float +glms_mat4_trace(mat4s m) { + return glm_mat4_trace(m.raw); +} + +/*! + * @brief trace of matrix (rotation part) + * + * sum of the elements on the main diagonal from upper left to the lower right + * + * @param[in] m matrix + */ +CGLM_INLINE +float +glms_mat4_trace3(mat4s m) { + return glm_mat4_trace3(m.raw); +} + +/*! + * @brief convert mat4's rotation part to quaternion + * + * @param[in] m affine matrix + * @returns destination quaternion + */ +CGLM_INLINE +versors +glms_mat4_quat(mat4s m) { + versors r; + glm_mat4_quat(m.raw, r.raw); + return r; +} + +/*! + * @brief multiply vector with mat4 + * + * @param[in] m mat4(affine transform) + * @param[in] v vec3 + * @param[in] last 4th item to make it vec4 + * @returns result vector (vec3) + */ +CGLM_INLINE +vec3s +glms_mat4_mulv3(mat4s m, vec3s v, float last) { + vec3s r; + glm_mat4_mulv3(m.raw, v.raw, last, r.raw); + return r; +} + +/*! + * @brief tranpose mat4 and store result in same matrix + * + * @param[in] m source + * @returns result + */ +CGLM_INLINE +mat4s +glms_mat4_transpose(mat4s m) { + glm_mat4_transpose(m.raw); + return m; +} + +/*! + * @brief scale (multiply with scalar) matrix without simd optimization + * + * multiply matrix with scalar + * + * @param[in] m matrix + * @param[in] s scalar + * @returns matrix + */ +CGLM_INLINE +mat4s +glms_mat4_scale_p(mat4s m, float s) { + glm_mat4_scale_p(m.raw, s); + return m; +} + +/*! + * @brief scale (multiply with scalar) matrix + * + * multiply matrix with scalar + * + * @param[in] m matrix + * @param[in] s scalar + * @returns matrix + */ +CGLM_INLINE +mat4s +glms_mat4_scale(mat4s m, float s) { + glm_mat4_scale(m.raw, s); + return m; +} + +/*! + * @brief mat4 determinant + * + * @param[in] mat matrix + * + * @return determinant + */ +CGLM_INLINE +float +glms_mat4_det(mat4s mat) { + return glm_mat4_det(mat.raw); +} + +/*! + * @brief inverse mat4 and store in dest + * + * @param[in] mat matrix + * @returns inverse matrix + */ +CGLM_INLINE +mat4s +glms_mat4_inv(mat4s mat) { + mat4s r; + glm_mat4_inv(mat.raw, r.raw); + return r; +} + +/*! + * @brief inverse mat4 and store in dest + * + * this func uses reciprocal approximation without extra corrections + * e.g Newton-Raphson. this should work faster than normal, + * to get more precise use glm_mat4_inv version. + * + * NOTE: You will lose precision, glm_mat4_inv is more accurate + * + * @param[in] mat matrix + * @returns inverse matrix + */ +CGLM_INLINE +mat4s +glms_mat4_inv_fast(mat4s mat) { + mat4s r; + glm_mat4_inv_fast(mat.raw, r.raw); + return r; +} + +/*! + * @brief swap two matrix columns + * + * @param[in] mat matrix + * @param[in] col1 col1 + * @param[in] col2 col2 + * @returns matrix + */ +CGLM_INLINE +mat4s +glms_mat4_swap_col(mat4s mat, int col1, int col2) { + glm_mat4_swap_col(mat.raw, col1, col2); + return mat; +} + +/*! + * @brief swap two matrix rows + * + * @param[in] mat matrix + * @param[in] row1 row1 + * @param[in] row2 row2 + * @returns matrix + */ +CGLM_INLINE +mat4s +glms_mat4_swap_row(mat4s mat, int row1, int row2) { + glm_mat4_swap_row(mat.raw, row1, row2); + return mat; +} + +/*! + * @brief helper for R (row vector) * M (matrix) * C (column vector) + * + * rmc stands for Row * Matrix * Column + * + * the result is scalar because R * M = Matrix1x4 (row vector), + * then Matrix1x4 * Vec4 (column vector) = Matrix1x1 (Scalar) + * + * @param[in] r row vector or matrix1x4 + * @param[in] m matrix4x4 + * @param[in] c column vector or matrix4x1 + * + * @return scalar value e.g. B(s) + */ +CGLM_INLINE +float +glms_mat4_rmc(vec4s r, mat4s m, vec4s c) { + return glm_mat4_rmc(r.raw, m.raw, c.raw); +} + +#endif /* cglm_mat4s_h */ + \ No newline at end of file diff --git a/include/cglm/struct/plane.h b/include/cglm/struct/plane.h new file mode 100644 index 0000000..cea7e8c --- /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 cglm_planes_h +#define cglm_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 /* cglm_planes_h */ diff --git a/include/cglm/struct/project.h b/include/cglm/struct/project.h new file mode 100644 index 0000000..d45ba3d --- /dev/null +++ b/include/cglm/struct/project.h @@ -0,0 +1,104 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_projects_h +#define cglm_projects_h + +#include "../common.h" +#include "../types-struct.h" +#include "../project.h" +#include "vec3.h" +#include "vec4.h" +#include "mat4.h" + +/*! + * @brief maps the specified viewport coordinates into specified space [1] + * the matrix should contain projection matrix. + * + * if you don't have ( and don't want to have ) an inverse matrix then use + * glm_unproject version. You may use existing inverse of matrix in somewhere + * else, this is why glm_unprojecti exists to save save inversion cost + * + * [1] space: + * 1- if m = invProj: View Space + * 2- if m = invViewProj: World Space + * 3- if m = invMVP: Object Space + * + * You probably want to map the coordinates into object space + * so use invMVP as m + * + * Computing viewProj: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * glm_mat4_inv(viewProj, invMVP); + * + * @param[in] pos point/position in viewport coordinates + * @param[in] invMat matrix (see brief) + * @param[in] vp viewport as [x, y, width, height] + * @returns unprojected coordinates + */ +CGLM_INLINE +vec3s +glms_unprojecti(vec3s pos, mat4s invMat, vec4s vp) { + vec3s r; + glm_unprojecti(pos.raw, invMat.raw, vp.raw, r.raw); + return r; +} + +/*! + * @brief maps the specified viewport coordinates into specified space [1] + * the matrix should contain projection matrix. + * + * this is same as glm_unprojecti except this function get inverse matrix for + * you. + * + * [1] space: + * 1- if m = proj: View Space + * 2- if m = viewProj: World Space + * 3- if m = MVP: Object Space + * + * You probably want to map the coordinates into object space + * so use MVP as m + * + * Computing viewProj and MVP: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * + * @param[in] pos point/position in viewport coordinates + * @param[in] m matrix (see brief) + * @param[in] vp viewport as [x, y, width, height] + * @returns unprojected coordinates + */ +CGLM_INLINE +vec3s +glms_unproject(vec3s pos, mat4s m, vec4s vp) { + vec3s r; + glm_unproject(pos.raw, m.raw, vp.raw, r.raw); + return r; +} + +/*! + * @brief map object coordinates to window coordinates + * + * Computing MVP: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * + * @param[in] pos object coordinates + * @param[in] m MVP matrix + * @param[in] vp viewport as [x, y, width, height] + * @param[out] dest projected coordinates + */ +CGLM_INLINE +vec3s +glms_project(vec3s pos, mat4s m, vec4s vp) { + vec3s r; + glm_project(pos.raw, m.raw, vp.raw, r.raw); + return r; +} + +#endif /* cglm_projects_h */ diff --git a/include/cglm/struct/sphere.h b/include/cglm/struct/sphere.h new file mode 100644 index 0000000..164e8bc --- /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 cglm_spheres_h +#define cglm_spheres_h + +#include "../common.h" +#include "../types-struct.h" +#include "../sphere.h" +#include "mat4.h" + +/* + Sphere Representation in cglm: [center.x, center.y, center.z, radii] + + You could use this representation or you can convert it to vec4 before call + any function + */ + +/*! + * @brief helper for getting sphere radius + * + * @param[in] s sphere + * + * @return returns radii + */ +CGLM_INLINE +float +glms_sphere_radii(vec4s s) { + return glm_sphere_radii(s.raw); +} + +/*! + * @brief apply transform to sphere, it is just wrapper for glm_mat4_mulv3 + * + * @param[in] s sphere + * @param[in] m transform matrix + * @returns transformed sphere + */ +CGLM_INLINE +vec4s +glms_sphere_transform(vec4s s, mat4 m) { + vec4s r; + glm_sphere_transform(s.raw, m, r.raw); + return r; +} + +/*! + * @brief merges two spheres and creates a new one + * + * two sphere must be in same space, for instance if one in world space then + * the other must be in world space too, not in local space. + * + * @param[in] s1 sphere 1 + * @param[in] s2 sphere 2 + * returns merged/extended sphere + */ +CGLM_INLINE +vec4s +glms_sphere_merge(vec4s s1, vec4s s2) { + vec4s r; + glm_sphere_merge(s1.raw, s2.raw, r.raw); + return r; +} + +/*! + * @brief check if two sphere intersects + * + * @param[in] s1 sphere + * @param[in] s2 other sphere + */ +CGLM_INLINE +bool +glms_sphere_sphere(vec4s s1, vec4s s2) { + return glm_sphere_sphere(s1.raw, s2.raw); +} + +/*! + * @brief check if sphere intersects with point + * + * @param[in] s sphere + * @param[in] point point + */ +CGLM_INLINE +bool +glms_sphere_point(vec4s s, vec3s point) { + return glm_sphere_point(s.raw, point.raw); +} + +#endif /* cglm_spheres_h */ diff --git a/include/cglm/struct/vec3-ext.h b/include/cglm/struct/vec3-ext.h new file mode 100644 index 0000000..53a1199 --- /dev/null +++ b/include/cglm/struct/vec3-ext.h @@ -0,0 +1,198 @@ +/* + * 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 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_sqrt(vec3s v); + */ + +#ifndef cglm_vec3s_ext_h +#define cglm_vec3s_ext_h + +#include "../common.h" +#include "../types-struct.h" +#include "../util.h" +#include "../vec3-ext.h" + +/*! + * @brief fill a vector with specified value + * + * @param[in] val value + * @returns dest + */ +CGLM_INLINE +vec3s +glms_vec3_broadcast(float val) { + vec3s r; + glm_vec3_broadcast(val, r.raw); + return r; +} + +/*! + * @brief check if vector is equal to value (without epsilon) + * + * @param[in] v vector + * @param[in] val value + */ +CGLM_INLINE +bool +glms_vec3_eq(vec3s v, float val) { + return glm_vec3_eq(v.raw, val); +} + +/*! + * @brief check if vector is equal to value (with epsilon) + * + * @param[in] v vector + * @param[in] val value + */ +CGLM_INLINE +bool +glms_vec3_eq_eps(vec3s v, float val) { + return glm_vec3_eq_eps(v.raw, val); +} + +/*! + * @brief check if vectors members are equal (without epsilon) + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glms_vec3_eq_all(vec3s v) { + return glm_vec3_eq_all(v.raw); +} + +/*! + * @brief check if vector is equal to another (without epsilon) + * + * @param[in] a vector + * @param[in] b vector + */ +CGLM_INLINE +bool +glms_vec3_eqv(vec3s a, vec3s b) { + return glm_vec3_eqv(a.raw, b.raw); +} + +/*! + * @brief check if vector is equal to another (with epsilon) + * + * @param[in] a vector + * @param[in] b vector + */ +CGLM_INLINE +bool +glms_vec3_eqv_eps(vec3s a, vec3s b) { + return glm_vec3_eqv_eps(a.raw, b.raw); +} + +/*! + * @brief max value of vector + * + * @param[in] v vector + */ +CGLM_INLINE +float +glms_vec3_max(vec3s v) { + return glm_vec3_max(v.raw); +} + +/*! + * @brief min value of vector + * + * @param[in] v vector + */ +CGLM_INLINE +float +glms_vec3_min(vec3s v) { + return glm_vec3_min(v.raw); +} + +/*! + * @brief check if all items are NaN (not a number) + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glms_vec3_isnan(vec3s v) { + return glm_vec3_isnan(v.raw); +} + +/*! + * @brief check if all items are INFINITY + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glms_vec3_isinf(vec3s v) { + return glm_vec3_isinf(v.raw); +} + +/*! + * @brief check if all items are valid number + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glms_vec3_isvalid(vec3s v) { + return glm_vec3_isvalid(v.raw); +} + +/*! + * @brief get sign of 32 bit float as +1, -1, 0 + * + * Important: It returns 0 for zero/NaN input + * + * @param v vector + * @returns sign vector + */ +CGLM_INLINE +vec3s +glms_vec3_sign(vec3s v) { + vec3s r; + glm_vec3_sign(v.raw, r.raw); + return r; +} + +/*! + * @brief 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 /* cglm_vec3s_ext_h */ diff --git a/include/cglm/struct/vec3.h b/include/cglm/struct/vec3.h new file mode 100644 index 0000000..91389a2 --- /dev/null +++ b/include/cglm/struct/vec3.h @@ -0,0 +1,767 @@ +/* + * 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 vec3s glms_vec3_copy(vec3s v); + 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(); + CGLM_INLINE vec3s glms_vec3_one(); + 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 vec3s glms_vec3_add(vec3s a, vec3s b); + CGLM_INLINE vec3s glms_vec3_adds(vec3s a, float s); + CGLM_INLINE vec3s glms_vec3_sub(vec3s a, vec3s b); + CGLM_INLINE vec3s glms_vec3_subs(vec3s a, float s); + CGLM_INLINE vec3s glms_vec3_mul(vec3s a, vec3s b); + CGLM_INLINE vec3s glms_vec3_scale(vec3s v, float s); + CGLM_INLINE vec3s glms_vec3_scale_as(vec3s v, float s); + CGLM_INLINE vec3s glms_vec3_div(vec3s a, vec3s b); + CGLM_INLINE vec3s glms_vec3_divs(vec3s a, float s); + CGLM_INLINE vec3s glms_vec3_addadd(vec3s a, vec3s b, vec3s dest); + CGLM_INLINE vec3s glms_vec3_subadd(vec3s a, vec3s b, vec3s dest); + CGLM_INLINE vec3s glms_vec3_muladd(vec3s a, vec3s b, vec3s dest); + CGLM_INLINE vec3s glms_vec3_muladds(vec3s a, float s, vec3s dest); + CGLM_INLINE vec3s glms_vec3_maxadd(vec3s a, vec3s b, vec3s dest); + CGLM_INLINE vec3s glms_vec3_minadd(vec3s a, vec3s b, vec3s dest); + CGLM_INLINE vec3s glms_vec3_flipsign(vec3s v); + CGLM_INLINE vec3s glms_vec3_negate(vec3s v); + CGLM_INLINE vec3s glms_vec3_inv(vec3s v); + CGLM_INLINE vec3s glms_vec3_normalize(vec3s v); + CGLM_INLINE vec3s glms_vec3_cross(vec3s a, vec3s b); + CGLM_INLINE vec3s glms_vec3_crossn(vec3s a, vec3s b); + CGLM_INLINE float glms_vec3_distance(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_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); + + Convenient: + CGLM_INLINE vec3s glms_cross(vec3s a, vec3s b); + CGLM_INLINE float glms_dot(vec3s a, vec3s b); + CGLM_INLINE vec3s glms_normalize(vec3s v); + */ + +#ifndef cglm_vec3s_h +#define cglm_vec3s_h + +#include "../common.h" +#include "../types-struct.h" +#include "../util.h" +#include "../vec3.h" +#include "vec3-ext.h" + +#define GLMS_VEC3_ONE_INIT {1.0f, 1.0f, 1.0f} +#define GLMS_VEC3_ZERO_INIT {0.0f, 0.0f, 0.0f} + +#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 copy all members of [a] to [dest] + * + * @param[in] a source + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_copy(vec3s v) { + vec3s r; + glm_vec3_copy(v.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 + * + * @param[in] v vector + * @returns zero vector + */ +CGLM_INLINE +vec3s +glms_vec3_zero() { + vec3s r; + glm_vec3_zero(r.raw); + return r; +} + +/*! + * @brief make vector one + * + * @param[in] v vector + * @returns one vector + */ +CGLM_INLINE +vec3s +glms_vec3_one() { + vec3s r; + glm_vec3_one(r.raw); + return r; +} + +/*! + * @brief vec3 dot product + * + * @param[in] a vector1 + * @param[in] b vector2 + * + * @return dot product + */ +CGLM_INLINE +float +glms_vec3_dot(vec3s a, vec3s b) { + return glm_vec3_dot(a.raw, b.raw); +} + +/*! + * @brief norm * norm (magnitude) of vec + * + * we can use this func instead of calling norm * norm, because it would call + * sqrtf fuction twice but with this func we can avoid func call, maybe this is + * not good name for this func + * + * @param[in] v vector + * + * @return norm * norm + */ +CGLM_INLINE +float +glms_vec3_norm2(vec3s v) { + return glm_vec3_norm2(v.raw); +} + +/*! + * @brief norm (magnitude) of vec3 + * + * @param[in] v vector + * + * @return norm + */ +CGLM_INLINE +float +glms_vec3_norm(vec3s v) { + return glm_vec3_norm(v.raw); +} + +/*! + * @brief 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] v 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] v vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec3s +glms_vec3_subs(vec3s a, float s) { + vec3s r; + glm_vec3_subs(a.raw, s, r.raw); + return r; +} + +/*! + * @brief multiply two vector (component-wise multiplication) + * + * @param a vector1 + * @param b vector2 + * @returns v3 = (a[0] * b[0], a[1] * b[1], a[2] * b[2]) + */ +CGLM_INLINE +vec3s +glms_vec3_mul(vec3s a, vec3s b) { + vec3s r; + glm_vec3_mul(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief multiply/scale vec3 vector with scalar: result = v * s + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec3s +glms_vec3_scale(vec3s v, float s) { + vec3s r; + glm_vec3_scale(v.raw, s, r.raw); + return r; +} + +/*! + * @brief make vec3 vector scale as specified: result = unit(v) * s + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec3s +glms_vec3_scale_as(vec3s v, float s) { + vec3s r; + glm_vec3_scale_as(v.raw, s, r.raw); + return r; +} + +/*! + * @brief div vector with another component-wise division: d = a / b + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns result = (a[0]/b[0], a[1]/b[1], a[2]/b[2]) + */ +CGLM_INLINE +vec3s +glms_vec3_div(vec3s a, vec3s b) { + vec3s r; + glm_vec3_div(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief div vector with scalar: d = v / s + * + * @param[in] v vector + * @param[in] s scalar + * @returns result = (a[0]/s, a[1]/s, a[2]/s) + */ +CGLM_INLINE +vec3s +glms_vec3_divs(vec3s a, float s) { + vec3s r; + glm_vec3_divs(a.raw, s, r.raw); + return r; +} + +/*! + * @brief add two vectors and add result to sum + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += (a + b) + */ +CGLM_INLINE +vec3s +glms_vec3_addadd(vec3s a, vec3s b, vec3s dest) { + glm_vec3_addadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief sub two vectors and add result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += (a + b) + */ +CGLM_INLINE +vec3s +glms_vec3_subadd(vec3s a, vec3s b, vec3s dest) { + glm_vec3_subadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief mul two vectors and add result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += (a * b) + */ +CGLM_INLINE +vec3s +glms_vec3_muladd(vec3s a, vec3s b, vec3s dest) { + glm_vec3_muladd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief mul vector with scalar and add result to sum + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @returns dest += (a * b) + */ +CGLM_INLINE +vec3s +glms_vec3_muladds(vec3s a, float s, vec3s dest) { + glm_vec3_muladds(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief add max of two vector to result/dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += max(a, b) + */ +CGLM_INLINE +vec3s +glms_vec3_maxadd(vec3s a, vec3s b, vec3s dest) { + glm_vec3_maxadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief add min of two vector to result/dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += min(a, b) + */ +CGLM_INLINE +vec3s +glms_vec3_minadd(vec3s a, vec3s b, vec3s dest) { + glm_vec3_minadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief negate vector components and store result in dest + * + * @param[in] v vector + * @returns result vector + */ +CGLM_INLINE +vec3s +glms_vec3_flipsign(vec3s v) { + glm_vec3_flipsign(v.raw); + return v; +} + +/*! + * @brief negate vector components + * + * @param[in] v vector + * @returns negated vector + */ +CGLM_INLINE +vec3s +glms_vec3_negate(vec3s v) { + glm_vec3_negate(v.raw); + return v; +} + +/*! + * @brief normalize vec3 and store result in same vec + * + * @param[in] v vector + * @returns normalized vector + */ +CGLM_INLINE +vec3s +glms_vec3_normalize(vec3s v) { + glm_vec3_normalize(v.raw); + return v; +} + +/*! + * @brief cross product of two vector (RH) + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_cross(vec3s a, vec3s b) { + vec3s r; + glm_vec3_cross(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief cross product of two vector (RH) and normalize the result + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_crossn(vec3s a, vec3s b) { + vec3s r; + glm_vec3_crossn(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief angle betwen two vector + * + * @param[in] a vector1 + * @param[in] b vector2 + * + * @return angle as radians + */ +CGLM_INLINE +float +glms_vec3_angle(vec3s a, vec3s b) { + return glm_vec3_angle(a.raw, b.raw); +} + +/*! + * @brief rotate vec3 around axis by angle using Rodrigues' rotation formula + * + * @param[in] v vector + * @param[in] axis axis vector (must be unit vector) + * @param[in] angle angle by radians + * @returns rotated vector + */ +CGLM_INLINE +vec3s +glms_vec3_rotate(vec3s v, float angle, vec3s axis) { + glm_vec3_rotate(v.raw, angle, axis.raw); + return v; +} + +/*! + * @brief apply rotation matrix to vector + * + * matrix format should be (no perspective): + * a b c x + * e f g y + * i j k z + * 0 0 0 w + * + * @param[in] m affine matrix or rot matrix + * @param[in] v vector + * @returns rotated vector + */ +CGLM_INLINE +vec3s +glms_vec3_rotate_m4(mat4s m, vec3s v) { + vec3s r; + glm_vec3_rotate_m4(m.raw, v.raw, r.raw); + return r; +} + +/*! + * @brief apply rotation matrix to vector + * + * @param[in] m affine matrix or rot matrix + * @param[in] v vector + * @returns rotated vector + */ +CGLM_INLINE +vec3s +glms_vec3_rotate_m3(mat3s m, vec3s v) { + vec3s r; + glm_vec3_rotate_m3(m.raw, v.raw, r.raw); + return r; +} + +/*! + * @brief project a vector onto b vector + * + * @param[in] a vector1 + * @param[in] b vector2 + * @returns projected vector + */ +CGLM_INLINE +vec3s +glms_vec3_proj(vec3s a, vec3s b) { + vec3s r; + glm_vec3_proj(a.raw, b.raw, r.raw); + return r; +} + +/** + * @brief find center point of two vector + * + * @param[in] a vector1 + * @param[in] b vector2 + * @returns center point + */ +CGLM_INLINE +vec3s +glms_vec3_center(vec3s a, vec3s b) { + vec3s r; + glm_vec3_center(a.raw, b.raw, r.raw); + return r; +} + +/** + * @brief 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 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 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 vector + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @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 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; +} + +#endif /* cglm_vec3s_h */ diff --git a/include/cglm/struct/vec4-ext.h b/include/cglm/struct/vec4-ext.h new file mode 100644 index 0000000..fdc5059 --- /dev/null +++ b/include/cglm/struct/vec4-ext.h @@ -0,0 +1,198 @@ +/* + * 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 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_sqrt(vec4s v); + */ + +#ifndef cglm_vec4s_ext_h +#define cglm_vec4s_ext_h + +#include "../common.h" +#include "../types-struct.h" +#include "../util.h" +#include "../vec4-ext.h" + +/*! + * @brief fill a vector with specified value + * + * @param val value + * @returns dest + */ +CGLM_INLINE +vec4s +glms_vec4_broadcast(float val) { + vec4s r; + glm_vec4_broadcast(val, r.raw); + return r; +} + +/*! + * @brief check if vector is equal to value (without epsilon) + * + * @param v vector + * @param val value + */ +CGLM_INLINE +bool +glms_vec4_eq(vec4s v, float val) { + return glm_vec4_eq(v.raw, val); +} + +/*! + * @brief check if vector is equal to value (with epsilon) + * + * @param v vector + * @param val value + */ +CGLM_INLINE +bool +glms_vec4_eq_eps(vec4s v, float val) { + return glm_vec4_eq_eps(v.raw, val); +} + +/*! + * @brief check if vectors members are equal (without epsilon) + * + * @param v vector + */ +CGLM_INLINE +bool +glms_vec4_eq_all(vec4s v) { + return glm_vec4_eq_all(v.raw); +} + +/*! + * @brief check if vector is equal to another (without epsilon) + * + * @param a vector + * @param b vector + */ +CGLM_INLINE +bool +glms_vec4_eqv(vec4s a, vec4s b) { + return glm_vec4_eqv(a.raw, b.raw); +} + +/*! + * @brief check if vector is equal to another (with epsilon) + * + * @param a vector + * @param b vector + */ +CGLM_INLINE +bool +glms_vec4_eqv_eps(vec4s a, vec4s b) { + return glm_vec4_eqv_eps(a.raw, b.raw); +} + +/*! + * @brief max value of vector + * + * @param v vector + */ +CGLM_INLINE +float +glms_vec4_max(vec4s v) { + return glm_vec4_max(v.raw); +} + +/*! + * @brief min value of vector + * + * @param v vector + */ +CGLM_INLINE +float +glms_vec4_min(vec4s v) { + return glm_vec4_min(v.raw); +} + +/*! + * @brief check if one of items is NaN (not a number) + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glms_vec4_isnan(vec4s v) { + return glm_vec4_isnan(v.raw); +} + +/*! + * @brief check if one of items is INFINITY + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glms_vec4_isinf(vec4s v) { + return glm_vec4_isinf(v.raw); +} + +/*! + * @brief check if all items are valid number + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glms_vec4_isvalid(vec4s v) { + return glm_vec4_isvalid(v.raw); +} + +/*! + * @brief get sign of 32 bit float as +1, -1, 0 + * + * Important: It returns 0 for zero/NaN input + * + * @param v vector + * @returns sign vector + */ +CGLM_INLINE +vec4s +glms_vec4_sign(vec4s v) { + vec4s r; + glm_vec4_sign(v.raw, r.raw); + return r; +} + +/*! + * @brief 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 /* cglm_vec4s_ext_h */ diff --git a/include/cglm/struct/vec4.h b/include/cglm/struct/vec4.h new file mode 100644 index 0000000..f96725f --- /dev/null +++ b/include/cglm/struct/vec4.h @@ -0,0 +1,582 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLM_VEC4_ONE_INIT + GLM_VEC4_BLACK_INIT + GLM_VEC4_ZERO_INIT + GLM_VEC4_ONE + GLM_VEC4_BLACK + GLM_VEC4_ZERO + + Functions: + CGLM_INLINE 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 vec4s glms_vec4_add(vec4s a, vec4s b); + CGLM_INLINE vec4s glms_vec4_adds(vec4s v, float s); + CGLM_INLINE vec4s glms_vec4_sub(vec4s a, vec4s b); + CGLM_INLINE vec4s glms_vec4_subs(vec4s v, float s); + CGLM_INLINE vec4s glms_vec4_mul(vec4s a, vec4s b); + CGLM_INLINE vec4s glms_vec4_scale(vec4s v, float s); + CGLM_INLINE vec4s glms_vec4_scale_as(vec4s v, float s); + CGLM_INLINE vec4s glms_vec4_div(vec4s a, vec4s b); + CGLM_INLINE vec4s glms_vec4_divs(vec4s v, float s); + CGLM_INLINE vec4s glms_vec4_addadd(vec4s a, vec4s b, vec4s dest); + CGLM_INLINE vec4s glms_vec4_subadd(vec4s a, vec4s b, vec4s dest); + CGLM_INLINE vec4s glms_vec4_muladd(vec4s a, vec4s b, vec4s dest); + CGLM_INLINE vec4s glms_vec4_muladds(vec4s a, float s, vec4s dest); + CGLM_INLINE vec4s glms_vec4_maxadd(vec4s a, vec4s b, vec4s dest); + CGLM_INLINE vec4s glms_vec4_minadd(vec4s a, vec4s b, vec4s dest); + CGLM_INLINE vec4s glms_vec4_negate(vec4s v); + CGLM_INLINE vec4s glms_vec4_inv(vec4s v); + CGLM_INLINE vec4s glms_vec4_normalize(vec4s v); + CGLM_INLINE float glms_vec4_distance(vec4s a, vec4s b); + CGLM_INLINE 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_cubic(float s); + */ + +#ifndef cglm_vec4s_h +#define cglm_vec4s_h + +#include "../common.h" +#include "../types-struct.h" +#include "../util.h" +#include "../vec4.h" +#include "vec4-ext.h" + +#define GLMS_VEC4_ONE_INIT {1.0f, 1.0f, 1.0f, 1.0f} +#define GLMS_VEC4_BLACK_INIT {0.0f, 0.0f, 0.0f, 1.0f} +#define GLMS_VEC4_ZERO_INIT {0.0f, 0.0f, 0.0f, 0.0f} + +#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] a source + * @returns destination + */ +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 + * + * @param[in] v vector + * @returns zero vector + */ +CGLM_INLINE +vec4s +glms_vec4_zero() { + vec4s r; + glm_vec4_zero(r.raw); + return r; +} + +/*! + * @brief make vector one + * + * @param[in] v vector + * @returns one vector + */ +CGLM_INLINE +vec4s +glms_vec4_one() { + vec4s r; + glm_vec4_one(r.raw); + return r; +} + +/*! + * @brief vec4 dot product + * + * @param[in] a vector1 + * @param[in] b vector2 + * + * @return dot product + */ +CGLM_INLINE +float +glms_vec4_dot(vec4s a, vec4s b) { + return glm_vec4_dot(a.raw, b.raw); +} + +/*! + * @brief norm * norm (magnitude) of vec + * + * we can use this func instead of calling norm * norm, because it would call + * sqrtf fuction twice but with this func we can avoid func call, maybe this is + * not good name for this func + * + * @param[in] v vec4 + * + * @return norm * norm + */ +CGLM_INLINE +float +glms_vec4_norm2(vec4s v) { + return glm_vec4_norm2(v.raw); +} + +/*! + * @brief norm (magnitude) of vec4 + * + * @param[in] v vector + * + * @return norm + */ +CGLM_INLINE +float +glms_vec4_norm(vec4s v) { + return glm_vec4_norm(v.raw); +} + +/*! + * @brief add b vector to a vector store result in dest + * + * @param[in] a vector1 + * @param[in] b vector2 + * @returns destination vector + */ +CGLM_INLINE +vec4s +glms_vec4_add(vec4s a, vec4s b) { + vec4s r; + glm_vec4_add(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief add scalar to v vector store result in dest (d = v + vec(s)) + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec4s +glms_vec4_adds(vec4s v, float s) { + vec4s r; + glm_vec4_adds(v.raw, s, r.raw); + return r; +} + +/*! + * @brief subtract b vector from a vector store result in dest (d = a - b) + * + * @param[in] a vector1 + * @param[in] b vector2 + * @returns destination vector + */ +CGLM_INLINE +vec4s +glms_vec4_sub(vec4s a, vec4s b) { + vec4s r; + glm_vec4_sub(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief subtract scalar from v vector store result in dest (d = v - vec(s)) + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec4s +glms_vec4_subs(vec4s v, float s) { + vec4s r; + glm_vec4_subs(v.raw, s, r.raw); + return r; +} + +/*! + * @brief multiply two vector (component-wise multiplication) + * + * @param a vector1 + * @param b vector2 + * @returns dest = (a[0] * b[0], a[1] * b[1], a[2] * b[2], a[3] * b[3]) + */ +CGLM_INLINE +vec4s +glms_vec4_mul(vec4s a, vec4s b) { + vec4s r; + glm_vec4_mul(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief multiply/scale vec4 vector with scalar: result = v * s + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec4s +glms_vec4_scale(vec4s v, float s) { + vec4s r; + glm_vec4_scale(v.raw, s, r.raw); + return r; +} + +/*! + * @brief make vec4 vector scale as specified: result = unit(v) * s + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec4s +glms_vec4_scale_as(vec4s v, float s) { + vec4s r; + glm_vec4_scale_as(v.raw, s, r.raw); + return r; +} + +/*! + * @brief div vector with another component-wise division: d = a / b + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns result = (a[0]/b[0], a[1]/b[1], a[2]/b[2], a[3]/b[3]) + */ +CGLM_INLINE +vec4s +glms_vec4_div(vec4s a, vec4s b) { + vec4s r; + glm_vec4_div(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief div vec4 vector with scalar: d = v / s + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec4s +glms_vec4_divs(vec4s v, float s) { + vec4s r; + glm_vec4_divs(v.raw, s, r.raw); + return r; +} + +/*! + * @brief add two vectors and add result to sum + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += (a + b) + */ +CGLM_INLINE +vec4s +glms_vec4_addadd(vec4s a, vec4s b, vec4s dest) { + glm_vec4_addadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief sub two vectors and add result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += (a - b) + */ +CGLM_INLINE +vec4s +glms_vec4_subadd(vec4s a, vec4s b, vec4s dest) { + glm_vec4_subadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief mul two vectors and add result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += (a * b) + */ +CGLM_INLINE +vec4s +glms_vec4_muladd(vec4s a, vec4s b, vec4s dest) { + glm_vec4_muladd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief mul vector with scalar and add result to sum + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @returns dest += (a * b) + */ +CGLM_INLINE +vec4s +glms_vec4_muladds(vec4s a, float s, vec4s dest) { + glm_vec4_muladds(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief add max of two vector to result/dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += max(a, b) + */ +CGLM_INLINE +vec4s +glms_vec4_maxadd(vec4s a, vec4s b, vec4s dest) { + glm_vec4_maxadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief add min of two vector to result/dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += min(a, b) + */ +CGLM_INLINE +vec4s +glms_vec4_minadd(vec4s a, vec4s b, vec4s dest) { + glm_vec4_minadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief negate vector components and store result in dest + * + * @param[in] v vector + * @returns result vector + */ +CGLM_INLINE +vec4s +glms_vec4_negate(vec4s v) { + glm_vec4_negate(v.raw); + return v; +} + +/*! + * @brief normalize vec4 and store result in same vec + * + * @param[in] v vector + * @returns normalized vector + */ +CGLM_INLINE +vec4s +glms_vec4_normalize(vec4s v) { + glm_vec4_normalize(v.raw); + return v; +} + +/** + * @brief distance between two vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @return returns distance + */ +CGLM_INLINE +float +glms_vec4_distance(vec4s a, vec4s b) { + return glm_vec4_distance(a.raw, b.raw); +} + +/*! + * @brief 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 vector + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @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 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; +} + +#endif /* cglm_vec4s_h */ diff --git a/include/cglm/types-struct.h b/include/cglm/types-struct.h new file mode 100644 index 0000000..f71c286 --- /dev/null +++ b/include/cglm/types-struct.h @@ -0,0 +1,74 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_types_struct_h +#define cglm_types_struct_h + +#include "types.h" + +typedef union vec3s { +#ifndef CGLM_NO_ANONYMOUS_STRUCT + struct { + float x; + float y; + float z; + }; +#endif + vec3 raw; +} vec3s; + +typedef union ivec3s { +#ifndef CGLM_NO_ANONYMOUS_STRUCT + struct { + int x; + int y; + int z; + }; +#endif + ivec3 raw; +} ivec3s; + +typedef union CGLM_ALIGN_IF(16) vec4s { +#ifndef CGLM_NO_ANONYMOUS_STRUCT + struct { + float x; + float y; + float z; + float w; + }; +#endif + vec4 raw; +} vec4s; + +typedef vec4s versors; + +typedef union mat3s { +#ifndef CGLM_NO_ANONYMOUS_STRUCT + struct { + float m00, m01, m02; + float m10, m11, m12; + float m20, m21, m22; + }; +#endif + vec3s col[3]; + mat3 raw; +} mat3s; + +typedef union CGLM_ALIGN_MAT mat4s { +#ifndef CGLM_NO_ANONYMOUS_STRUCT + struct { + float m00, m01, m02, m03; + float m10, m11, m12, m13; + float m20, m21, m22, m23; + float m30, m31, m32, m33; + }; +#endif + vec4s col[4]; + mat4 raw; +} mat4s; + +#endif /* cglm_types_struct_h */ diff --git a/test/src/test_common.c b/test/src/test_common.c index 0afc235..d734e72 100644 --- a/test/src/test_common.c +++ b/test/src/test_common.c @@ -48,6 +48,13 @@ test_rand_vec3(vec3 dest) { dest[2] = drand48(); } +vec3s +test_rand_vec3s() { + vec3s r; + test_rand_vec3(r.raw); + return r; +} + void test_rand_vec4(vec4 dest) { srand((unsigned int)time(NULL)); @@ -58,6 +65,13 @@ test_rand_vec4(vec4 dest) { dest[3] = drand48(); } +vec4s +test_rand_vec4s() { + vec4s r; + test_rand_vec4(r.raw); + return r; +} + float test_rand(void) { srand((unsigned int)time(NULL)); @@ -120,6 +134,11 @@ test_assert_vec3_eq(vec3 v1, vec3 v2) { assert_true(fabsf(v1[2] - v2[2]) <= 0.000009); } +void +test_assert_vec3s_eq(vec3s v1, vec3s v2) { + test_assert_vec3_eq(v1.raw, v2.raw); +} + void test_assert_vec4_eq(vec4 v1, vec4 v2) { assert_true(fabsf(v1[0] - v2[0]) <= 0.000009); /* rounding errors */ @@ -128,6 +147,11 @@ test_assert_vec4_eq(vec4 v1, vec4 v2) { assert_true(fabsf(v1[3] - v2[3]) <= 0.000009); } +void +test_assert_vec4s_eq(vec4s v1, vec4s v2) { + test_assert_vec4_eq(v1.raw, v2.raw); +} + void test_assert_quat_eq_abs(versor v1, versor v2) { assert_true(fabsf(fabsf(v1[0]) - fabsf(v2[0])) <= 0.0009); /* rounding errors */ diff --git a/test/src/test_common.h b/test/src/test_common.h index 8a16b0f..51d1826 100644 --- a/test/src/test_common.h +++ b/test/src/test_common.h @@ -20,6 +20,7 @@ #include #include +#include #include void @@ -43,9 +44,15 @@ test_assert_mat3_eq(mat3 m1, mat3 m2); void test_assert_vec3_eq(vec3 v1, vec3 v2); +void +test_assert_vec3s_eq(vec3s v1, vec3s v2); + void test_assert_vec4_eq(vec4 v1, vec4 v2); +void +test_assert_vec4s_eq(vec4s v1, vec4s v2); + void test_assert_quat_eq(versor v1, versor v2); @@ -55,8 +62,14 @@ test_assert_quat_eq_abs(versor v1, versor v2); void test_rand_vec3(vec3 dest); +vec3s +test_rand_vec3s(); + void -test_rand_vec4(vec4 dest) ; +test_rand_vec4(vec4 dest); + +vec4s +test_rand_vec4s(); float test_rand(void); diff --git a/test/src/test_quat.c b/test/src/test_quat.c index 0d64367..d0cc27c 100644 --- a/test/src/test_quat.c +++ b/test/src/test_quat.c @@ -44,9 +44,11 @@ test_quat(void **state) { test_assert_mat4_eq2(inRot, outRot, 0.000009); /* almost equal */ /* 4. test SSE mul and raw mul */ +#if defined( __SSE__ ) || defined( __SSE2__ ) test_quat_mul_raw(inQuat, outQuat, q3); glm_quat_mul_sse2(inQuat, outQuat, q4); test_assert_quat_eq(q3, q4); +#endif } /* 5. test lookat */ diff --git a/test/src/test_vec3.c b/test/src/test_vec3.c index 6cfc593..4f1f2d1 100644 --- a/test/src/test_vec3.c +++ b/test/src/test_vec3.c @@ -12,6 +12,7 @@ test_vec3(void **state) { mat3 rot1m3; mat4 rot1; vec3 v, v1, v2; + vec3s vs1, vs2, vs3, vs4; /* test zero */ glm_vec3_zero(v); @@ -75,4 +76,12 @@ test_vec3(void **state) { test_assert_vec3_eq(v1, v2); test_assert_vec3_eq(v1, GLM_ZUP); + + /* structs */ + vs1 = test_rand_vec3s(); + vs2 = test_rand_vec3s(); + + vs3 = glms_vec3_add(vs1, vs2); + vs4 = glms_vec3_maxv(vs1, vs3); + test_assert_vec3s_eq(vs3, vs4); } diff --git a/test/src/test_vec4.c b/test/src/test_vec4.c index daf4e00..02137b0 100644 --- a/test/src/test_vec4.c +++ b/test/src/test_vec4.c @@ -65,10 +65,10 @@ test_vec4_clamp(vec4 v, float minVal, float maxVal) { void test_vec4(void **state) { vec4 v, v1, v2, v3, v4; + vec4s vs1, vs2, vs3, vs4; int i; float d1, d2; - for (i = 0; i < 1000; i++) { /* 1. test SSE/SIMD dot product */ test_rand_vec4(v); @@ -182,4 +182,12 @@ test_vec4(void **state) { assert_true(v3[1] >= 0.0999 && v3[1] <= 0.80001); assert_true(v3[2] >= 0.0999 && v3[2] <= 0.80001); assert_true(v3[3] >= 0.0999 && v3[3] <= 0.80001); + + /* structs */ + vs1 = test_rand_vec4s(); + vs2 = test_rand_vec4s(); + + vs3 = glms_vec4_add(vs1, vs2); + vs4 = glms_vec4_maxv(vs1, vs3); + test_assert_vec4s_eq(vs3, vs4); }