From 3ff902de9ccaff2a6d8660ff2a5a8254bf9bb3c3 Mon Sep 17 00:00:00 2001 From: acoto87 Date: Fri, 3 May 2019 22:48:13 -0500 Subject: [PATCH] add mat3 and mat4 implementation --- include/cglm/structs/mat3.h | 263 +++++++++++++++++++++- include/cglm/structs/mat4.h | 427 ++++++++++++++++++++++++++++++++++-- include/cglm/types-struct.h | 60 ++++- 3 files changed, 728 insertions(+), 22 deletions(-) diff --git a/include/cglm/structs/mat3.h b/include/cglm/structs/mat3.h index c1d8e48..63fe7c6 100644 --- a/include/cglm/structs/mat3.h +++ b/include/cglm/structs/mat3.h @@ -6,9 +6,29 @@ */ /* + Macros: + GLMS_MAT3_IDENTITY_INIT + GLMS_MAT3_ZERO_INIT + GLMS_MAT3_IDENTITY + GLMS_MAT3_ZERO + Functions: - CGLM_INLINE vec3s glm_mat3_mulv(mat3 m, vec3s v); - CGLM_INLINE float glm_mat3_rmc(vec3s r, mat3 m, vec3s c); + 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 mat3s glms_mat3_transpose_to(mat3s m); + 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 @@ -19,21 +39,250 @@ #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 transpose mat3 and store in dest + * + * source matrix will not be transposed unless dest is m + * + * @param[in] m matrix + * @param[out] dest result + */ +CGLM_INLINE +mat3s +glms_mat3_transpose_to(mat3s m) { + mat3s r; + glm_mat3_transpose_to(m.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) + * @returns vec3 (result, column vector) */ CGLM_INLINE vec3s -glms_mat3_mulv(mat3 m, vec3s v) { +glms_mat3_mulv(mat3s m, vec3s v) { vec3s r; - glm_mat3_mulv(m, v.raw, r.raw); + 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) * @@ -50,8 +299,8 @@ glms_mat3_mulv(mat3 m, vec3s v) { */ CGLM_INLINE float -glms_mat3_rmc(vec3s r, mat3 m, vec3s c) { - return glm_mat3_rmc(r.raw, m, c.raw); +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/structs/mat4.h b/include/cglm/structs/mat4.h index fc785d7..a61f18d 100644 --- a/include/cglm/structs/mat4.h +++ b/include/cglm/structs/mat4.h @@ -11,14 +11,42 @@ */ /* + Macros: + GLMS_MAT4_IDENTITY_INIT + GLMS_MAT4_ZERO_INIT + GLMS_MAT4_IDENTITY + GLMS_MAT4_ZERO + Functions: - CGLM_INLINE void glm_mat4_mulv(mat4 m, vec4 v, vec4 dest); - CGLM_INLINE void glm_mat4_mulv3(mat4 m, vec3 v, vec3 dest); - CGLM_INLINE float glm_mat4_rmc(vec4 r, mat4 m, vec4 c); + 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_to(mat4s m); + 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_mats_h -#define cglm_mats_h +#ifndef cglm_mat4s_h +#define cglm_mat4s_h #include "../common.h" #include "../types-struct.h" @@ -26,18 +54,250 @@ #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 ((mat4)GLMS_MAT4_IDENTITY_INIT) +#define GLMS_MAT4_ZERO ((mat4)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 mat4 t = GLM_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; + * + * glm_mat4_mulN((mat4 *[]){&m1, &m2, &m3, &m4}, 4, res); + * @endcode + * + * @warning matrices parameter is pointer array not mat4 array! + * + * @param[in] matrices mat4 * array + * @param[in] len matrices count + * @returns result + */ +CGLM_INLINE +mat4s +glms_mat4_mulN(mat4s * __restrict matrices[], uint32_t len) { + mat4s r; + glm_mat4_mulN(matrices, len, r.raw); + 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) + * @returns vec4 (result, column vector) */ CGLM_INLINE vec4s -glms_mat4_mulv(mat4 m, vec4s v) { +glms_mat4_mulv(mat4s m, vec4s v) { vec4s r; - glm_mat4_mulv(m, v.raw, r.raw); + 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; } @@ -47,16 +307,154 @@ glms_mat4_mulv(mat4 m, vec4s v) { * @param[in] m mat4(affine transform) * @param[in] v vec3 * @param[in] last 4th item to make it vec4 - * returns result vector (vec3) + * @returns result vector (vec3) */ CGLM_INLINE vec3s -glms_mat4_mulv3(mat4 m, vec3s v, float last) { +glms_mat4_mulv3(mat4s m, vec3s v, float last) { vec3s r; - glm_mat4_mulv3(m, v.raw, last, r.raw); + glm_mat4_mulv3(m.raw, v.raw, last, r.raw); return r; } +/*! + * @brief transpose mat4 and store in dest + * + * source matrix will not be transposed unless dest is m + * + * @param[in] m matrix + * @returns result + */ +CGLM_INLINE +mat4s +glms_mat4_transpose_to(mat4s m) { + mat4s r; + glm_mat4_transpose_to(m.raw, 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) * @@ -73,8 +471,9 @@ glms_mat4_mulv3(mat4 m, vec3s v, float last) { */ CGLM_INLINE float -glms_mat4_rmc(vec4s r, mat4 m, vec4s c) { - return glm_mat4_rmc(r.raw, m, c.raw); +glms_mat4_rmc(vec4s r, mat4s m, vec4s c) { + return glm_mat4_rmc(r.raw, m.raw, c.raw); } -#endif /* cglm_mats_h */ +#endif /* cglm_mat4s_h */ + \ No newline at end of file diff --git a/include/cglm/types-struct.h b/include/cglm/types-struct.h index 27e04fe..13431aa 100644 --- a/include/cglm/types-struct.h +++ b/include/cglm/types-struct.h @@ -10,7 +10,7 @@ #include "types.h" -typedef union CGLM_ALIGN_IF(16) vec3s { +typedef union vec3s { #ifndef CGLM_NO_ANONYMOUS_STRUCT struct { float x; @@ -33,4 +33,62 @@ typedef union CGLM_ALIGN_IF(16) vec4s { vec4 raw; } vec4s; +typedef vec4s versors; + +typedef union mat3s { +#ifndef CGLM_NO_ANONYMOUS_STRUCT + struct { + float m00; + float m01; + float m02; + float m10; + float m11; + float m12; + float m20; + float m21; + float m22; + }; + struct { + vec3s col0; + vec3s col1; + vec3s col2; + }; +#endif + mat3 raw; +} mat3s; + +#ifdef __AVX__ +typedef union CGLM_ALIGN_IF(32) mat4s { +#else +typedef union CGLM_ALIGN_IF(16) mat4s { +#endif +#ifndef CGLM_NO_ANONYMOUS_STRUCT + struct { + float m00; + float m01; + float m02; + float m03; + float m10; + float m11; + float m12; + float m13; + float m20; + float m21; + float m22; + float m23; + float m30; + float m31; + float m32; + float m33; + }; + struct { + vec4s col0; + vec4s col1; + vec4s col2; + vec4s col3; + }; +#endif + mat4 raw; +} mat4s; + #endif /* cglm_types_struct_h */