diff options
Diffstat (limited to 'mons_math')
27 files changed, 1948 insertions, 0 deletions
diff --git a/mons_math/CMakeLists.txt b/mons_math/CMakeLists.txt new file mode 100644 index 0000000..e5d015e --- /dev/null +++ b/mons_math/CMakeLists.txt @@ -0,0 +1,43 @@ +cmake_minimum_required(VERSION 3.14) +project(mons_math LANGUAGES C) +set(CMAKE_C_STANDARD 99) +set(CMAKE_EXPORT_COMPILE_COMMANDS true) +set(CMAKE_BUILD_TYPE "Debug") + +add_library(mons_math + SHARED + ./src/mat2.c + ./src/mat3.c + ./src/mat4.c + ./src/vec2.c + ./src/vec3.c + ./src/vec4.c + ./src/util.c + ./src/quat.c +) + +target_include_directories(mons_math PUBLIC + "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>/include" + "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>" +) +target_compile_options(mons_math PRIVATE -coverage) +target_link_options(mons_math PRIVATE -coverage) +target_link_libraries(mons_math PUBLIC m) + +include(CTest) + +function(TESTCASE NAME) + add_executable(test_${NAME} ./tests/${NAME}.c) + target_link_libraries(test_${NAME} PUBLIC mons_math) + add_test( + NAME ${NAME} + COMMAND $<TARGET_FILE:test_${NAME}> + ) +endfunction() + +testcase(vec2_ops) +testcase(vec3_ops) +testcase(vec4_ops) +# testcase(mat2_ops) +# testcase(mat3_ops) +# testcase(mat4_ops) diff --git a/mons_math/include/mons_math/mat2.h b/mons_math/include/mons_math/mat2.h new file mode 100644 index 0000000..b1a8ca0 --- /dev/null +++ b/mons_math/include/mons_math/mat2.h @@ -0,0 +1,39 @@ +#ifndef MONS_MAT2_H +#define MONS_MAT2_H + +#include "mons_math/vec2.h" + +typedef struct mons_mat2 { + mons_vec2 m1; + mons_vec2 m2; +} mons_mat2; + +mons_mat2 mons_mat2_add(mons_mat2 a, mons_mat2 b); +void mons_mat2_add_inplace(mons_mat2 *a, mons_mat2 b); + +mons_mat2 mons_mat2_mul_f(mons_mat2 a, float b); +mons_mat2 mons_mat2_mul_i(mons_mat2 a, int b); +mons_mat2 mons_mat2_mul(mons_mat2 a, mons_mat2 b); + +void mons_mat2_mul_f_inplace(mons_mat2 *a, float b); +void mons_mat2_mul_i_inplace(mons_mat2 *a, int b); + +mons_mat2 mons_mat2_inverse(mons_mat2 a); +void mons_mat2_inverse_inplace(mons_mat2 *a); + +mons_mat2 mons_mat2_transpose(mons_mat2 a); +void mons_mat2_transpose_inplace(mons_mat2 *a); + +mons_vec2 mons_mat2_n1(mons_mat2 a); +mons_vec2 mons_mat2_n2(mons_mat2 a); + +float mons_mat2_determinant(mons_mat2 a); +mons_mat2 mons_mat2_adjoint(mons_mat2 a); +mons_mat2 mons_mat2_inverse(mons_mat2 a); + +extern const mons_mat2 MONS_MAT2_ZERO; +extern const mons_mat2 MONS_MAT2_IDENTITY; + +int mons_mat2_equal(mons_mat2 a, mons_mat2 b); + +#endif diff --git a/mons_math/include/mons_math/mat3.h b/mons_math/include/mons_math/mat3.h new file mode 100644 index 0000000..9ca4a64 --- /dev/null +++ b/mons_math/include/mons_math/mat3.h @@ -0,0 +1,41 @@ +#ifndef MONS_MAT3_H +#define MONS_MAT3_H + +#include "mons_math/vec3.h" + +typedef struct mons_mat3 { + mons_vec3 m1; + mons_vec3 m2; + mons_vec3 m3; +} mons_mat3; + +mons_mat3 mons_mat3_add(mons_mat3 a, mons_mat3 b); +void mons_mat3_add_inplace(mons_mat3 *a, mons_mat3 b); + +mons_mat3 mons_mat3_mul_f(mons_mat3 a, float b); +mons_mat3 mons_mat3_mul_i(mons_mat3 a, int b); +mons_mat3 mons_mat3_mul(mons_mat3 a, mons_mat3 b); + +void mons_mat3_mul_f_inplace(mons_mat3 *a, float b); +void mons_mat3_mul_i_inplace(mons_mat3 *a, int b); + +mons_mat3 mons_mat3_inverse(mons_mat3 a); + +mons_mat3 mons_mat3_transpose(mons_mat3 a); +void mons_mat3_transpose_inplace(mons_mat3 *a); + +mons_vec3 mons_mat3_n1(mons_mat3 a); +mons_vec3 mons_mat3_n2(mons_mat3 a); +mons_vec3 mons_mat3_n3(mons_mat3 a); + +float mons_mat3_determinant(mons_mat3 a); +mons_mat3 mons_mat3_minor(mons_mat3 a); +mons_mat3 mons_mat3_cofactor(mons_mat3 a); +mons_mat3 mons_mat3_adjoint(mons_mat3 a); + +extern const mons_mat3 MONS_MAT3_ZERO; +extern const mons_mat3 MONS_MAT3_IDENTITY; + +int mons_mat3_equal(mons_mat3 a, mons_mat3 b); + +#endif diff --git a/mons_math/include/mons_math/mat4.h b/mons_math/include/mons_math/mat4.h new file mode 100644 index 0000000..0b949fe --- /dev/null +++ b/mons_math/include/mons_math/mat4.h @@ -0,0 +1,57 @@ +#ifndef MONS_MATH_MATRIX_H +#define MONS_MATH_MATRIX_H + +#include "mons_math/vec4.h" + +typedef struct mons_mat4 { + mons_vec4 m1; + mons_vec4 m2; + mons_vec4 m3; + mons_vec4 m4; +} mons_mat4; + +mons_mat4 mons_mat4_add(mons_mat4 a, mons_mat4 b); +void mons_mat4_add_inplace(mons_mat4 *a, mons_mat4 b); + +mons_mat4 mons_mat4_mul_f(mons_mat4 a, float b); +mons_mat4 mons_mat4_mul_i(mons_mat4 a, int b); +mons_mat4 mons_mat4_mul(mons_mat4 a, mons_mat4 b); +void mons_mat4_mul_inplace(mons_mat4 *a, mons_mat4 b); + +void mons_mat4_mul_f_inplace(mons_mat4 *a, float b); +void mons_mat4_mul_i_inplace(mons_mat4 *a, int b); + +mons_mat4 mons_mat4_inverse(mons_mat4 a); + +mons_mat4 mons_mat4_transpose(mons_mat4 a); +void mons_mat4_transpose_inplace(mons_mat4 *a); + +mons_vec4 mons_mat4_n1(mons_mat4 a); +mons_vec4 mons_mat4_n2(mons_mat4 a); +mons_vec4 mons_mat4_n3(mons_mat4 a); +mons_vec4 mons_mat4_n4(mons_mat4 a); + +float mons_mat4_determinant(mons_mat4 a); + +extern const mons_mat4 MONS_MAT4_ZERO; +extern const mons_mat4 MONS_MAT4_IDENTITY; + +int mons_mat4_equal(mons_mat4 a, mons_mat4 b); + +void mons_mat4_print(mons_mat4 mat); + +#define MONS_MAT4_ZERO {\ + { 0, 0, 0, 0 },\ + { 0, 0, 0, 0 },\ + { 0, 0, 0, 0 },\ + { 0, 0, 0, 0 },\ +} + +#define MONS_MAT4_IDENTITY {\ + { 1, 0, 0, 0 },\ + { 0, 1, 0, 0 },\ + { 0, 0, 1, 0 },\ + { 0, 0, 0, 1 },\ +} + +#endif diff --git a/mons_math/include/mons_math/matrix.h b/mons_math/include/mons_math/matrix.h new file mode 100644 index 0000000..48fdec6 --- /dev/null +++ b/mons_math/include/mons_math/matrix.h @@ -0,0 +1,8 @@ +#ifndef MONS_MATRIX_H +#define MONS_MATRIX_H + +#include "mat2.h" +#include "mat3.h" +#include "mat4.h" + +#endif diff --git a/mons_math/include/mons_math/quat.h b/mons_math/include/mons_math/quat.h new file mode 100644 index 0000000..353d7bb --- /dev/null +++ b/mons_math/include/mons_math/quat.h @@ -0,0 +1,44 @@ +#ifndef MONS_QUAT_H +#define MONS_QUAT_H + +struct mons_vec3; + +typedef struct mons_quat { + float x; + float y; + float z; + float w; +} mons_quat; + +mons_quat mons_quat_from_axis_angle(struct mons_vec3 axis, float angle); + +mons_quat mons_quat_mul(mons_quat a, mons_quat b); + +void mons_quat_mul_inplace(mons_quat *a, mons_quat b); + +mons_quat mons_quat_mul_f(mons_quat a, float b); + +void mons_quat_mul_f_inplace(mons_quat *a, float b); + +mons_quat mons_quat_mul_i(mons_quat a, int b); + +void mons_quat_mul_i_inplace(mons_quat *a, int b); + +struct mons_mat4 mons_quat_to_mat4(mons_quat a); + +mons_quat mons_quat_normalize(mons_quat a); + +void mons_quat_normalize_inplace(mons_quat *a); + +struct mons_vec3 mons_quat_transform_vec3(mons_quat quat, struct mons_vec3 vec); + +mons_quat mons_quat_conjugate(mons_quat quat); + +mons_quat mons_quat_looking_at(struct mons_vec3 eye, struct mons_vec3 target, struct mons_vec3 up); + +void mons_quat_print(mons_quat quat); + +#define MONS_QUAT_IDENTITY (mons_quat) { 0, 0, 0, 1 } + +#endif + diff --git a/mons_math/include/mons_math/util.h b/mons_math/include/mons_math/util.h new file mode 100644 index 0000000..5218243 --- /dev/null +++ b/mons_math/include/mons_math/util.h @@ -0,0 +1,8 @@ +#ifndef MONS_MATH_UTIL_H +#define MONS_MATH_UTIL_H + +#define MONS_FLOAT_EQUAL_EPSILON 0.0001f; + +int mons_float_approx_equal(float a, float b); + +#endif diff --git a/mons_math/include/mons_math/vec2.h b/mons_math/include/mons_math/vec2.h new file mode 100644 index 0000000..3fb405d --- /dev/null +++ b/mons_math/include/mons_math/vec2.h @@ -0,0 +1,46 @@ +#ifndef MONS_VEC2_H +#define MONS_VEC2_H + +typedef struct mons_vec2 { + float x; + float y; +} mons_vec2; + +mons_vec2 mons_vec2_add(mons_vec2 a, mons_vec2 b); +void mons_vec2_add_inplace(mons_vec2 *a, mons_vec2 b); + +mons_vec2 mons_vec2_sub(mons_vec2 a, mons_vec2 b); +void mons_vec2_sub_inplace(mons_vec2 *a, mons_vec2 b); + +mons_vec2 mons_vec2_mul_f(mons_vec2 a, float b); +mons_vec2 mons_vec2_mul_i(mons_vec2 a, int b); +float mons_vec2_dot(mons_vec2 a, mons_vec2 b); + +void mons_vec2_mul_f_inplace(mons_vec2 *a, float b); +void mons_vec2_mul_i_inplace(mons_vec2 *a, int b); + +mons_vec2 mons_vec2_div_f(mons_vec2 a, float b); +mons_vec2 mons_vec2_div_i(mons_vec2 a, int b); +void mons_vec2_div_f_inplace(mons_vec2 *a, float b); +void mons_vec2_div_i_inplace(mons_vec2 *a, int b); + +float mons_vec2_len(mons_vec2 a); +float mons_vec2_len_squared(mons_vec2 a); + +struct mons_vec3 mons_vec2_extend(mons_vec2 a); + +int mons_vec2_equal(mons_vec2 a, mons_vec2 b); +mons_vec2 mons_vec2_negate(mons_vec2 a); +void mons_vec2_negate_inplace(mons_vec2 *a); + +mons_vec2 mons_vec2_normalize(mons_vec2 a); +void mons_vec2_normalize_inplace(mons_vec2 *a); + +#define MONS_VEC2_ZERO (mons_vec2) { 0, 0 } +#define MONS_VEC2_ONE (mons_vec2) { 1, 1 } +#define MONS_VEC2_X (mons_vec2) { 1, 0 } +#define MONS_VEC2_Y (mons_vec2) { 0, 1 } +#define MONS_VEC2_NEG_X (mons_vec2) {-1,0} +#define MONS_VEC2_NEG_Y (mons_vec2) {0,-1} + +#endif diff --git a/mons_math/include/mons_math/vec3.h b/mons_math/include/mons_math/vec3.h new file mode 100644 index 0000000..6b37410 --- /dev/null +++ b/mons_math/include/mons_math/vec3.h @@ -0,0 +1,56 @@ +#ifndef MONS_VEC3_H +#define MONS_VEC3_H + +typedef struct mons_vec3 { + float x; + float y; + float z; +} mons_vec3; + +mons_vec3 mons_vec3_add(mons_vec3 a, mons_vec3 b); +void mons_vec3_add_inplace(mons_vec3 *a, mons_vec3 b); + +mons_vec3 mons_vec3_sub(mons_vec3 a, mons_vec3 b); +void mons_vec3_sub_inplace(mons_vec3 *a, mons_vec3 b); + +mons_vec3 mons_vec3_mul_memberwise(mons_vec3 a, mons_vec3 b); +void mons_vec3_mul_memberwise_inplace(mons_vec3 *a, mons_vec3 b); +mons_vec3 mons_vec3_mul_f(mons_vec3 a, float b); +mons_vec3 mons_vec3_mul_i(mons_vec3 a, int b); +float mons_vec3_dot(mons_vec3 a, mons_vec3 b); + +void mons_vec3_mul_f_inplace(mons_vec3 *a, float b); +void mons_vec3_mul_i_inplace(mons_vec3 *a, int b); + +mons_vec3 mons_vec3_div_f(mons_vec3 a, float b); +mons_vec3 mons_vec3_div_i(mons_vec3 a, int b); +void mons_vec3_div_f_inplace(mons_vec3 *a, float b); +void mons_vec3_div_i_inplace(mons_vec3 *a, int b); + +mons_vec3 mons_vec3_cross(mons_vec3 a, mons_vec3 b); + +float mons_vec3_len(mons_vec3 a); +float mons_vec3_len_squared(mons_vec3 a); + +struct mons_vec2 mons_vec3_truncate(mons_vec3 a); +struct mons_vec4 mons_vec3_extend(mons_vec3 a); + +int mons_vec3_equal(mons_vec3 a, mons_vec3 b); +mons_vec3 mons_vec3_negate(mons_vec3 a); +void mons_vec3_negate_inplace(mons_vec3 *a); + +mons_vec3 mons_vec3_normalize(mons_vec3 a); +void mons_vec3_normalize_inplace(mons_vec3 *a); + +void mons_vec3_print(mons_vec3 vec); + +#define MONS_VEC3_ZERO (mons_vec3) { 0, 0, 0 } +#define MONS_VEC3_ONE (mons_vec3) { 1, 1, 1 } +#define MONS_VEC3_X (mons_vec3) { 1, 0, 0 } +#define MONS_VEC3_Y (mons_vec3) { 0, 1, 0 } +#define MONS_VEC3_Z (mons_vec3) { 0, 0, 1 } +#define MONS_VEC3_NEG_X (mons_vec3) {-1,0,0} +#define MONS_VEC3_NEG_Y (mons_vec3) {0,-1,0} +#define MONS_VEC3_NEG_Z (mons_vec3) {0,0,-1} + +#endif diff --git a/mons_math/include/mons_math/vec4.h b/mons_math/include/mons_math/vec4.h new file mode 100644 index 0000000..24a2d8f --- /dev/null +++ b/mons_math/include/mons_math/vec4.h @@ -0,0 +1,53 @@ +#ifndef MONS_MATH_VEC4_H +#define MONS_MATH_VEC4_H + +typedef struct mons_vec4 { + float x; + float y; + float z; + float w; +} mons_vec4; + +mons_vec4 mons_vec4_add(mons_vec4 a, mons_vec4 b); +void mons_vec4_add_inplace(mons_vec4 *a, mons_vec4 b); + +mons_vec4 mons_vec4_sub(mons_vec4 a, mons_vec4 b); +void mons_vec4_sub_inplace(mons_vec4 *a, mons_vec4 b); + +mons_vec4 mons_vec4_mul_f(mons_vec4 a, float b); +mons_vec4 mons_vec4_mul_i(mons_vec4 a, int b); +float mons_vec4_dot(mons_vec4 a, mons_vec4 b); + +void mons_vec4_mul_f_inplace(mons_vec4 *a, float b); +void mons_vec4_mul_i_inplace(mons_vec4 *a, int b); + +mons_vec4 mons_vec4_div_f(mons_vec4 a, float b); +mons_vec4 mons_vec4_div_i(mons_vec4 a, int b); +void mons_vec4_div_f_inplace(mons_vec4 *a, float b); +void mons_vec4_div_i_inplace(mons_vec4 *a, int b); + +float mons_vec4_len(mons_vec4 a); +float mons_vec4_len_squared(mons_vec4 a); + +struct mons_vec3 mons_vec4_truncate(mons_vec4 a); + +int mons_vec4_equal(mons_vec4 a, mons_vec4 b); +mons_vec4 mons_vec4_negate(mons_vec4 a); +void mons_vec4_negate_inplace(mons_vec4 *a); +mons_vec4 mons_vec4_normalize(mons_vec4 a); +void mons_vec4_normalize_inplace(mons_vec4 *a); + +void mons_vec4_print(mons_vec4 vec); + +#define MONS_VEC4_ZERO (mons_vec4) { 0, 0, 0, 0 } +#define MONS_VEC4_ONE (mons_vec4) { 1, 1, 1, 1 } +#define MONS_VEC4_X (mons_vec4) { 1, 0, 0, 0 } +#define MONS_VEC4_Y (mons_vec4) { 0, 1, 0, 0 } +#define MONS_VEC4_Z (mons_vec4) { 0, 0, 1, 0 } +#define MONS_VEC4_W (mons_vec4) { 0, 0, 0, 1 } +#define MONS_VEC4_NEG_X (mons_vec4) {-1,0,0,0} +#define MONS_VEC4_NEG_Y (mons_vec4) {0,-1,0,0} +#define MONS_VEC4_NEG_Z (mons_vec4) {0,0,-1,0} +#define MONS_VEC4_NEG_W (mons_vec4) {0,0,0,-1} + +#endif diff --git a/mons_math/include/mons_math/vector.h b/mons_math/include/mons_math/vector.h new file mode 100644 index 0000000..2576d26 --- /dev/null +++ b/mons_math/include/mons_math/vector.h @@ -0,0 +1,8 @@ +#ifndef MONS_VECTOR_H +#define MONS_VECTOR_H + +#include "vec2.h" +#include "vec3.h" +#include "vec4.h" + +#endif diff --git a/mons_math/run_tests b/mons_math/run_tests new file mode 100755 index 0000000..5a3b9ef --- /dev/null +++ b/mons_math/run_tests @@ -0,0 +1,6 @@ +#!/bin/bash + +cmake . -B build && +make -C build && +ctest --test-dir build --output-on-failure -T Test -T Coverage + diff --git a/mons_math/src/mat2.c b/mons_math/src/mat2.c new file mode 100644 index 0000000..026b165 --- /dev/null +++ b/mons_math/src/mat2.c @@ -0,0 +1,123 @@ +#include "mons_math/mat2.h" + +const mons_mat2 MONS_MAT2_ZERO = { + {0, 0}, + {0, 0}, +}; + +const mons_mat2 MONS_MAT2_IDENTITY = { + {1, 0}, + {0, 1}, +}; + +mons_mat2 mons_mat2_add(mons_mat2 a, mons_mat2 b) { + mons_mat2 result = { + mons_vec2_add(a.m1, b.m1), + mons_vec2_add(a.m2, b.m2), + }; + return result; +} + +void mons_mat2_add_inplace(mons_mat2 *a, mons_mat2 b) { + mons_vec2_add_inplace(&a->m1, b.m1); + mons_vec2_add_inplace(&a->m2, b.m2); +} + +mons_mat2 mons_mat2_mul_f(mons_mat2 a, float b) { + mons_mat2 result = { + mons_vec2_mul_f(a.m1, b), + mons_vec2_mul_f(a.m2, b), + }; + return result; +} + +mons_mat2 mons_mat2_mul_i(mons_mat2 a, int b) { + mons_mat2 result = { + mons_vec2_mul_i(a.m1, b), + mons_vec2_mul_i(a.m2, b), + }; + return result; +} + +mons_mat2 mons_mat2_mul(mons_mat2 a, mons_mat2 b) { + mons_vec2 b_n1 = mons_mat2_n1(b); + mons_vec2 b_n2 = mons_mat2_n2(b); + + mons_mat2 result = { + { + mons_vec2_dot(a.m1, b_n1), + mons_vec2_dot(a.m1, b_n2), + }, + { + mons_vec2_dot(a.m2, b_n1), + mons_vec2_dot(a.m2, b_n2), + }, + }; + return result; +} + +void mons_mat2_mul_f_inplace(mons_mat2 *a, float b) { + mons_vec2_mul_f_inplace(&a->m1, b); + mons_vec2_mul_f_inplace(&a->m2, b); +} + +void mons_mat2_mul_i_inplace(mons_mat2 *a, int b) { + mons_vec2_mul_i_inplace(&a->m1, b); + mons_vec2_mul_i_inplace(&a->m2, b); +} + +mons_mat2 mons_mat2_transpose(mons_mat2 a) { + mons_mat2 result = { + mons_mat2_n1(a), + mons_mat2_n2(a), + }; + return result; +} + +void mons_mat2_transpose_inplace(mons_mat2 *a) { *a = mons_mat2_transpose(*a); } + +mons_vec2 mons_mat2_n1(mons_mat2 a) { + mons_vec2 result = { + a.m1.x, + a.m2.x, + }; + return result; +} + +mons_vec2 mons_mat2_n2(mons_mat2 a) { + mons_vec2 result = { + a.m1.y, + a.m2.y, + }; + return result; +} + +float mons_mat2_determinant(mons_mat2 a) { + // ad - bc + return (a.m1.x * a.m2.y) - (a.m1.y * a.m2.x); +} + +mons_mat2 mons_mat2_adjoint(mons_mat2 a) { + /* + * d -b + * -c a + */ + mons_mat2 result = {{ + a.m2.y, + -a.m1.y, + }, + { + -a.m2.x, + a.m1.x, + }}; + return result; +} + +mons_mat2 mons_mat2_inverse(mons_mat2 a) { + return mons_mat2_mul_f(mons_mat2_adjoint(a), + 1.0 / mons_mat2_determinant(a)); +} + +int mons_mat2_equal(mons_mat2 a, mons_mat2 b) { + return mons_vec2_equal(a.m1, b.m1) && mons_vec2_equal(a.m2, b.m2); +} diff --git a/mons_math/src/mat3.c b/mons_math/src/mat3.c new file mode 100644 index 0000000..f806375 --- /dev/null +++ b/mons_math/src/mat3.c @@ -0,0 +1,237 @@ +#include "mons_math/mat3.h" +#include "mons_math/mat2.h" +#include "mons_math/vec3.h" + +const mons_mat3 MONS_MAT3_ZERO = { + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, +}; + +const mons_mat3 MONS_MAT3_IDENTITY = { + {1, 0, 0}, + {0, 1, 0}, + {0, 0, 1}, +}; + +mons_mat3 mons_mat3_add(mons_mat3 a, mons_mat3 b) { + mons_mat3 result = { + mons_vec3_add(a.m1, b.m1), + mons_vec3_add(a.m2, b.m2), + mons_vec3_add(a.m3, b.m3), + }; + return result; +} + +void mons_mat3_add_inplace(mons_mat3 *a, mons_mat3 b) { + mons_vec3_add_inplace(&a->m1, b.m1); + mons_vec3_add_inplace(&a->m2, b.m2); + mons_vec3_add_inplace(&a->m3, b.m3); +} + +mons_mat3 mons_mat3_mul_f(mons_mat3 a, float b) { + mons_mat3 result = { + mons_vec3_mul_f(a.m1, b), + mons_vec3_mul_f(a.m2, b), + mons_vec3_mul_f(a.m3, b), + }; + return result; +} + +mons_mat3 mons_mat3_mul_i(mons_mat3 a, int b) { + mons_mat3 result = { + mons_vec3_mul_i(a.m1, b), + mons_vec3_mul_i(a.m2, b), + mons_vec3_mul_i(a.m3, b), + }; + return result; +} + +mons_mat3 mons_mat3_mul(mons_mat3 a, mons_mat3 b) { + mons_vec3 b_n1 = mons_mat3_n1(b); + mons_vec3 b_n2 = mons_mat3_n2(b); + mons_vec3 b_n3 = mons_mat3_n3(b); + + mons_mat3 result = { + { + mons_vec3_dot(a.m1, b_n1), + mons_vec3_dot(a.m1, b_n2), + mons_vec3_dot(a.m1, b_n3), + }, + { + mons_vec3_dot(a.m2, b_n1), + mons_vec3_dot(a.m2, b_n2), + mons_vec3_dot(a.m2, b_n3), + }, + { + mons_vec3_dot(a.m3, b_n1), + mons_vec3_dot(a.m3, b_n2), + mons_vec3_dot(a.m3, b_n3), + }, + }; + return result; +} + +void mons_mat3_mul_f_inplace(mons_mat3 *a, float b) { + mons_vec3_mul_f_inplace(&a->m1, b); + mons_vec3_mul_f_inplace(&a->m2, b); + mons_vec3_mul_f_inplace(&a->m3, b); +} + +void mons_mat3_mul_i_inplace(mons_mat3 *a, int b) { + mons_vec3_mul_i_inplace(&a->m1, b); + mons_vec3_mul_i_inplace(&a->m2, b); + mons_vec3_mul_i_inplace(&a->m3, b); +} + +mons_mat3 mons_mat3_transpose(mons_mat3 a) { + mons_mat3 result = { + mons_mat3_n1(a), + mons_mat3_n2(a), + mons_mat3_n3(a), + }; +} + +void mons_mat3_transpose_inplace(mons_mat3 *a) { *a = mons_mat3_transpose(*a); } + +mons_vec3 mons_mat3_n1(mons_mat3 a) { + mons_vec3 result = { + a.m1.x, + a.m2.x, + a.m3.x, + }; + return result; +} + +mons_vec3 mons_mat3_n2(mons_mat3 a) { + mons_vec3 result = { + a.m1.y, + a.m2.y, + a.m3.y, + }; + return result; +} + +mons_vec3 mons_mat3_n3(mons_mat3 a) { + mons_vec3 result = { + a.m1.z, + a.m2.z, + a.m3.z, + }; + return result; +} + +float mons_mat3_determinant(mons_mat3 a) { + /* + * a * det( + * e f + * h i + * ) + * - b * det( + * d f + * g i + * ) + * + c * det( + * d e + * g h + * ) + */ + mons_mat2 efhi = { + {a.m2.y, a.m2.z}, + {a.m3.y, a.m3.z}, + }; + mons_mat2 dfgi = { + {a.m2.x, a.m2.z}, + {a.m3.x, a.m3.z}, + }; + mons_mat2 degh = { + {a.m2.x, a.m2.y}, + {a.m3.x, a.m3.y}, + }; + + return (a.m1.x * mons_mat2_determinant(efhi)) - + (a.m1.y * mons_mat2_determinant(dfgi)) + + (a.m1.z * mons_mat2_determinant(degh)); +} + +mons_mat3 mons_mat3_minor(mons_mat3 a) { + // Get determinants of minors + // First row elements + mons_mat2 minor_1_1 = { + {a.m2.y, a.m2.z}, + {a.m3.y, a.m3.z}, + }; + float det_1_1 = mons_mat2_determinant(minor_1_1); + mons_mat2 minor_1_2 = { + {a.m2.x, a.m2.z}, + {a.m3.x, a.m3.z}, + }; + float det_1_2 = mons_mat2_determinant(minor_1_2); + mons_mat2 minor_1_3 = { + {a.m2.x, a.m2.y}, + {a.m3.x, a.m3.y}, + }; + float det_1_3 = mons_mat2_determinant(minor_1_3); + // Second row elements + mons_mat2 minor_2_1 = { + {a.m1.y, a.m1.z}, + {a.m3.y, a.m3.z}, + }; + float det_2_1 = mons_mat2_determinant(minor_2_1); + mons_mat2 minor_2_2 = { + {a.m1.x, a.m1.z}, + {a.m3.x, a.m3.z}, + }; + float det_2_2 = mons_mat2_determinant(minor_2_2); + mons_mat2 minor_2_3 = { + {a.m1.x, a.m1.y}, + {a.m3.x, a.m3.y}, + }; + float det_2_3 = mons_mat2_determinant(minor_2_3); + // Third row elements + mons_mat2 minor_3_1 = { + {a.m1.y, a.m1.z}, + {a.m2.y, a.m2.z}, + }; + float det_3_1 = mons_mat2_determinant(minor_3_1); + mons_mat2 minor_3_2 = { + {a.m1.x, a.m1.z}, + {a.m2.x, a.m2.z}, + }; + float det_3_2 = mons_mat2_determinant(minor_3_2); + mons_mat2 minor_3_3 = { + {a.m1.x, a.m1.y}, + {a.m2.x, a.m2.y}, + }; + float det_3_3 = mons_mat2_determinant(minor_3_3); + + mons_mat3 result = { + {det_1_1, det_1_2, det_1_3}, + {det_2_1, det_2_2, det_2_3}, + {det_3_1, det_3_2, det_3_3}, + }; + return result; +} + +mons_mat3 mons_mat3_cofactor(mons_mat3 a) { + mons_mat3 result = mons_mat3_minor(a); + result.m1.y *= -1; + result.m2.x *= -1; + result.m2.z *= -1; + result.m3.y *= -1; + return result; +} + +mons_mat3 mons_mat3_adjoint(mons_mat3 a) { + return mons_mat3_transpose(mons_mat3_cofactor(a)); +} + +mons_mat3 mons_mat3_inverse(mons_mat3 a) { + return mons_mat3_mul_f(mons_mat3_adjoint(a), + 1.0 / mons_mat3_determinant(a)); +} + +int mons_mat3_equal(mons_mat3 a, mons_mat3 b) { + return mons_vec3_equal(a.m1, b.m1) && mons_vec3_equal(a.m2, b.m2) && + mons_vec3_equal(a.m3, b.m3); +} diff --git a/mons_math/src/mat4.c b/mons_math/src/mat4.c new file mode 100644 index 0000000..bb92ca8 --- /dev/null +++ b/mons_math/src/mat4.c @@ -0,0 +1,321 @@ +#include "mons_math/mat4.h" +#include "mons_math/mat3.h" +#include "mons_math/vec4.h" +#include <stdio.h> + +mons_mat4 mons_mat4_add(mons_mat4 a, mons_mat4 b) { + mons_mat4 result = { + mons_vec4_add(a.m1, b.m1), + mons_vec4_add(a.m2, b.m2), + mons_vec4_add(a.m3, b.m3), + mons_vec4_add(a.m4, b.m4), + }; + return result; +} + +void mons_mat4_add_inplace(mons_mat4 *a, mons_mat4 b) { + mons_vec4_add_inplace(&a->m1, b.m1); + mons_vec4_add_inplace(&a->m2, b.m2); + mons_vec4_add_inplace(&a->m3, b.m3); + mons_vec4_add_inplace(&a->m4, b.m4); +} + +mons_mat4 mons_mat4_mul_f(mons_mat4 a, float b) { + mons_mat4 result = { + mons_vec4_mul_f(a.m1, b), + mons_vec4_mul_f(a.m2, b), + mons_vec4_mul_f(a.m3, b), + mons_vec4_mul_f(a.m4, b), + }; + return result; +} + +mons_mat4 mons_mat4_mul_i(mons_mat4 a, int b) { + mons_mat4 result = { + mons_vec4_mul_i(a.m1, b), + mons_vec4_mul_i(a.m2, b), + mons_vec4_mul_i(a.m3, b), + mons_vec4_mul_i(a.m4, b), + }; + return result; +} + +void mons_mat4_mul_f_inplace(mons_mat4 *a, float b) { + mons_vec4_mul_f_inplace(&a->m1, b); + mons_vec4_mul_f_inplace(&a->m2, b); + mons_vec4_mul_f_inplace(&a->m3, b); + mons_vec4_mul_f_inplace(&a->m4, b); +} + +void mons_mat4_mul_i_inplace(mons_mat4 *a, int b) { + mons_vec4_mul_i_inplace(&a->m1, b); + mons_vec4_mul_i_inplace(&a->m2, b); + mons_vec4_mul_i_inplace(&a->m3, b); + mons_vec4_mul_i_inplace(&a->m4, b); +} + +mons_mat4 mons_mat4_mul(mons_mat4 a, mons_mat4 b) { + mons_vec4 b_n1 = mons_mat4_n1(b); + mons_vec4 b_n2 = mons_mat4_n2(b); + mons_vec4 b_n3 = mons_mat4_n3(b); + mons_vec4 b_n4 = mons_mat4_n4(b); + + mons_mat4 result = { + { + mons_vec4_dot(a.m1, b_n1), + mons_vec4_dot(a.m1, b_n2), + mons_vec4_dot(a.m1, b_n3), + mons_vec4_dot(a.m1, b_n4), + }, + { + mons_vec4_dot(a.m2, b_n1), + mons_vec4_dot(a.m2, b_n2), + mons_vec4_dot(a.m2, b_n3), + mons_vec4_dot(a.m2, b_n4), + }, + { + mons_vec4_dot(a.m3, b_n1), + mons_vec4_dot(a.m3, b_n2), + mons_vec4_dot(a.m3, b_n3), + mons_vec4_dot(a.m3, b_n4), + }, + { + mons_vec4_dot(a.m4, b_n1), + mons_vec4_dot(a.m4, b_n2), + mons_vec4_dot(a.m4, b_n3), + mons_vec4_dot(a.m4, b_n4), + }, + }; + return result; +} + +mons_mat4 mons_mat4_transpose(mons_mat4 a) { + mons_mat4 result = { + mons_mat4_n1(a), + mons_mat4_n2(a), + mons_mat4_n3(a), + mons_mat4_n4(a), + }; + return result; +} + +void mons_mat4_transpose_inplace(mons_mat4 *a) { *a = mons_mat4_transpose(*a); } + +mons_vec4 mons_mat4_n1(mons_mat4 a) { + mons_vec4 result = { + a.m1.x, + a.m2.x, + a.m3.x, + a.m4.x, + }; + return result; +} + +mons_vec4 mons_mat4_n2(mons_mat4 a) { + mons_vec4 result = { + a.m1.y, + a.m2.y, + a.m3.y, + a.m4.y, + }; + return result; +} + +mons_vec4 mons_mat4_n3(mons_mat4 a) { + mons_vec4 result = { + a.m1.z, + a.m2.z, + a.m3.z, + a.m4.z, + }; + return result; +} + +mons_vec4 mons_mat4_n4(mons_mat4 a) { + mons_vec4 result = { + a.m1.w, + a.m2.w, + a.m3.w, + a.m4.w, + }; + return result; +} + +float mons_mat4_determinant(mons_mat4 a) { + mons_mat3 minor_1_1 = { + {a.m2.y, a.m2.z, a.m2.w}, + {a.m3.y, a.m3.z, a.m3.w}, + {a.m4.y, a.m4.z, a.m4.w}, + }; + mons_mat3 minor_1_2 = { + {a.m2.x, a.m2.z, a.m2.w}, + {a.m3.x, a.m3.z, a.m3.w}, + {a.m4.x, a.m4.z, a.m4.w}, + }; + mons_mat3 minor_1_3 = { + {a.m2.x, a.m2.y, a.m2.w}, + {a.m3.x, a.m3.y, a.m3.w}, + {a.m4.x, a.m4.y, a.m4.w}, + }; + mons_mat3 minor_1_4 = { + {a.m2.x, a.m2.y, a.m2.z}, + {a.m3.x, a.m3.y, a.m3.z}, + {a.m4.x, a.m4.y, a.m4.z}, + }; + + return (a.m1.x * mons_mat3_determinant(minor_1_1)) - + (a.m1.y * mons_mat3_determinant(minor_1_2)) + + (a.m1.z * mons_mat3_determinant(minor_1_3)) - + (a.m1.w * mons_mat3_determinant(minor_1_4)); +} + +mons_mat4 mons_mat4_minor(mons_mat4 a) { + // First Row + mons_mat3 minor_1_1 = { + {a.m2.y, a.m2.z, a.m2.w}, + {a.m3.y, a.m3.z, a.m3.w}, + {a.m4.y, a.m4.z, a.m4.w}, + }; + float det_1_1 = mons_mat3_determinant(minor_1_1); + mons_mat3 minor_1_2 = { + {a.m2.x, a.m2.z, a.m2.w}, + {a.m3.x, a.m3.z, a.m3.w}, + {a.m4.x, a.m4.z, a.m4.w}, + }; + float det_1_2 = mons_mat3_determinant(minor_1_2); + mons_mat3 minor_1_3 = { + {a.m2.x, a.m2.y, a.m2.w}, + {a.m3.x, a.m3.y, a.m3.w}, + {a.m4.x, a.m4.y, a.m4.w}, + }; + float det_1_3 = mons_mat3_determinant(minor_1_3); + mons_mat3 minor_1_4 = { + {a.m2.x, a.m2.y, a.m2.z}, + {a.m3.x, a.m3.y, a.m3.z}, + {a.m4.x, a.m4.y, a.m4.z}, + }; + float det_1_4 = mons_mat3_determinant(minor_1_4); + // Second Row + mons_mat3 minor_2_1 = { + {a.m1.y, a.m1.z, a.m1.w}, + {a.m3.y, a.m3.z, a.m3.w}, + {a.m4.y, a.m4.z, a.m4.w}, + }; + float det_2_1 = mons_mat3_determinant(minor_2_1); + mons_mat3 minor_2_2 = { + {a.m1.x, a.m1.z, a.m1.w}, + {a.m3.x, a.m3.z, a.m3.w}, + {a.m4.x, a.m4.z, a.m4.w}, + }; + float det_2_2 = mons_mat3_determinant(minor_2_2); + mons_mat3 minor_2_3 = { + {a.m1.x, a.m1.y, a.m1.w}, + {a.m3.x, a.m3.y, a.m3.w}, + {a.m4.x, a.m4.y, a.m4.w}, + }; + float det_2_3 = mons_mat3_determinant(minor_2_3); + mons_mat3 minor_2_4 = { + {a.m1.x, a.m1.y, a.m1.z}, + {a.m3.x, a.m3.y, a.m3.z}, + {a.m4.x, a.m4.y, a.m4.z}, + }; + float det_2_4 = mons_mat3_determinant(minor_2_4); + // Third Row + mons_mat3 minor_3_1 = { + {a.m1.y, a.m1.z, a.m1.w}, + {a.m2.y, a.m2.z, a.m2.w}, + {a.m4.y, a.m4.z, a.m4.w}, + }; + float det_3_1 = mons_mat3_determinant(minor_3_1); + mons_mat3 minor_3_2 = { + {a.m1.x, a.m1.z, a.m1.w}, + {a.m2.x, a.m2.z, a.m2.w}, + {a.m4.x, a.m4.z, a.m4.w}, + }; + float det_3_2 = mons_mat3_determinant(minor_3_2); + mons_mat3 minor_3_3 = { + {a.m1.x, a.m1.y, a.m1.w}, + {a.m2.x, a.m2.y, a.m2.w}, + {a.m4.x, a.m4.y, a.m4.w}, + }; + float det_3_3 = mons_mat3_determinant(minor_3_3); + mons_mat3 minor_3_4 = { + {a.m1.x, a.m1.y, a.m1.z}, + {a.m2.x, a.m2.y, a.m2.z}, + {a.m4.x, a.m4.y, a.m4.z}, + }; + float det_3_4 = mons_mat3_determinant(minor_3_4); + // Fourth Row + mons_mat3 minor_4_1 = { + {a.m1.y, a.m1.z, a.m1.w}, + {a.m2.y, a.m2.z, a.m2.w}, + {a.m3.y, a.m3.z, a.m3.w}, + }; + float det_4_1 = mons_mat3_determinant(minor_4_1); + mons_mat3 minor_4_2 = { + {a.m1.x, a.m1.z, a.m1.w}, + {a.m2.x, a.m2.z, a.m2.w}, + {a.m3.x, a.m3.z, a.m3.w}, + }; + float det_4_2 = mons_mat3_determinant(minor_4_2); + mons_mat3 minor_4_3 = { + {a.m1.x, a.m1.y, a.m1.w}, + {a.m2.x, a.m2.y, a.m2.w}, + {a.m3.x, a.m3.y, a.m3.w}, + }; + float det_4_3 = mons_mat3_determinant(minor_4_3); + mons_mat3 minor_4_4 = { + {a.m1.x, a.m1.y, a.m1.z}, + {a.m2.x, a.m2.y, a.m2.z}, + {a.m3.x, a.m3.y, a.m3.z}, + }; + float det_4_4 = mons_mat3_determinant(minor_4_4); + + mons_mat4 result = { + {det_1_1, det_1_2, det_1_3, det_1_4}, + {det_2_1, det_2_2, det_2_3, det_2_4}, + {det_3_1, det_3_2, det_3_3, det_3_4}, + {det_4_1, det_4_2, det_4_3, det_4_4}, + }; + return result; +} + +mons_mat4 mons_mat4_cofactor(mons_mat4 a) { + mons_mat4 result = mons_mat4_minor(a); + result.m1.y *= -1; + result.m1.w *= -1; + result.m2.x *= -1; + result.m2.z *= -1; + result.m3.y *= -1; + result.m3.w *= -1; + result.m4.x *= -1; + result.m4.z *= -1; + return result; +} + +mons_mat4 mons_mat4_adjoint(mons_mat4 a) { + return mons_mat4_transpose(mons_mat4_cofactor(a)); +} + +mons_mat4 mons_mat4_inverse(mons_mat4 a) { + return mons_mat4_mul_f(mons_mat4_adjoint(a), + 1.0 / mons_mat4_determinant(a)); +} + +int mons_mat4_equal(mons_mat4 a, mons_mat4 b) { + return mons_vec4_equal(a.m1, b.m1) + && mons_vec4_equal(a.m2, b.m2) + && mons_vec4_equal(a.m3, b.m3) + && mons_vec4_equal(a.m4, b.m4); +} + +void mons_mat4_mul_inplace(mons_mat4 *a, mons_mat4 b) { + *a = mons_mat4_mul(*a, b); +} + +void mons_mat4_print(mons_mat4 mat) { + printf("[%.3f %.3f %.3f %.3f]\n", mat.m1.x, mat.m2.x, mat.m3.x, mat.m4.x); + printf("[%.3f %.3f %.3f %.3f]\n", mat.m1.y, mat.m2.y, mat.m3.y, mat.m4.y); + printf("[%.3f %.3f %.3f %.3f]\n", mat.m1.z, mat.m2.z, mat.m3.z, mat.m4.z); + printf("[%.3f %.3f %.3f %.3f]\n", mat.m1.w, mat.m2.w, mat.m3.w, mat.m4.w); +} diff --git a/mons_math/src/quat.c b/mons_math/src/quat.c new file mode 100644 index 0000000..7c6a1cd --- /dev/null +++ b/mons_math/src/quat.c @@ -0,0 +1,141 @@ +#include "mons_math/quat.h" +#include "mons_math/mat4.h" +#include "mons_math/vec3.h" +#include "mons_math/vec4.h" +#include <math.h> +#include <stdlib.h> +#include <stdio.h> + +mons_quat mons_quat_from_axis_angle(mons_vec3 axis, float angle) { + float half_angle = 0.5f * angle; + float s = sinf(half_angle); + return (mons_quat){ + axis.x * s, + axis.y * s, + axis.z * s, + cosf(half_angle), + }; +} + +mons_quat mons_quat_mul(mons_quat a, mons_quat b) { + return (mons_quat){ + (a.w * b.x) + (a.x * b.w) + (a.y * b.z) - (a.z * b.y), + (a.w * b.y) + (a.y * b.w) + (a.z * b.x) - (a.x * b.z), + (a.w * b.z) + (a.z * b.w) + (a.x * b.y) - (a.y * b.x), + (a.w * b.w) - (a.x * b.x) - (a.y * b.y) - (a.z * b.z), + }; +} + +void mons_quat_mul_inplace(mons_quat *a, mons_quat b) { + *a = mons_quat_mul(*a, b); +} + +mons_quat mons_quat_mul_f(mons_quat a, float b) { + return (mons_quat){ + a.x * b, + a.y * b, + a.z * b, + a.w * b, + }; +} + +void mons_quat_mul_f_inplace(mons_quat *a, float b) { + a->x *= b; + a->y *= b; + a->z *= b; + a->w *= b; +} + +mons_quat mons_quat_mul_i(mons_quat a, int b) { + return (mons_quat){ + a.x * b, + a.y * b, + a.z * b, + a.w * b, + }; +} + +void mons_quat_mul_i_inplace(mons_quat *a, int b) { + a->x *= b; + a->y *= b; + a->z *= b; + a->w *= b; +} + +mons_mat4 mons_quat_to_mat4(mons_quat a) { + return (mons_mat4){ + { + 1.0 - (2.0 * a.y * a.y) - (2.0 * a.z * a.z), + (2.0 * a.x * a.y) - (2.0 * a.w * a.z), + (2.0 * a.x * a.z) + (2.0 * a.w * a.y), + 0.0, + }, + { + (2.0 * a.x * a.y) + (2.0 * a.w * a.z), + 1.0 - (2.0 * a.x * a.x) - (2.0 * a.z * a.z), + (2.0 * a.y * a.z) - (2.0 * a.w * a.x), + 0.0, + }, + { + (2.0 * a.x * a.z) - (2.0 * a.w * a.y), + (2.0 * a.y * a.z) + (2.0 * a.w * a.x), + 1.0 - (2.0 * a.x * a.x) - (2.0 * a.y * a.y), + 0.0, + }, + { + 0.0, + 0.0, + 0.0, + 1.0, + }, + }; +} + +mons_quat mons_quat_normalize(mons_quat a) { + mons_vec4 normalized = mons_vec4_normalize(*((mons_vec4 *)&a)); + return *((mons_quat *)&normalized); +} + +void mons_quat_normalize_inplace(mons_quat *a) { + mons_vec4_normalize_inplace((mons_vec4 *)a); +} + +mons_vec3 mons_quat_transform_vec3(mons_quat quat, mons_vec3 vec) { + mons_vec3 quat_vec = (mons_vec3){quat.x, quat.y, quat.z}; + float s = quat.w; + + return mons_vec3_add( + mons_vec3_add( + mons_vec3_mul_f(quat_vec, mons_vec3_dot(quat_vec, vec) * 2.0f), + mons_vec3_mul_f(vec, s * s - mons_vec3_dot(quat_vec, quat_vec))), + mons_vec3_mul_f(mons_vec3_cross(quat_vec, vec), 2.0f * s)); +} + +mons_quat mons_quat_conjugate(mons_quat quat) { + return (mons_quat){ + .x = -quat.x, + .y = -quat.y, + .z = -quat.z, + .w = quat.w, + }; +} + +mons_quat mons_quat_looking_at(mons_vec3 eye, mons_vec3 target, mons_vec3 up) { + mons_vec3 f = mons_vec3_normalize(mons_vec3_sub(target, eye)); + mons_vec3 side = mons_vec3_normalize(mons_vec3_cross(up, f)); + mons_vec3 b = mons_vec3_normalize(mons_vec3_add(f, MONS_VEC3_NEG_Z)); + mons_quat p = mons_quat_from_axis_angle(mons_vec3_cross(b, f), mons_vec3_dot(b,f)); + mons_vec3 r = (mons_vec3) { + p.w*p.w + p.x*p.x - p.y*p.y - p.z*p.z, + (2.0f * p.x * p.y) - (2.0f * p.w * p.z), + (2.0f * p.x * p.z) + (2.0f * p.w * p.y), + }; + b = mons_vec3_normalize(mons_vec3_add(side, r)); + mons_quat q = mons_quat_from_axis_angle(mons_vec3_cross(b,side), mons_vec3_dot(b, side)); + + return mons_quat_mul(p, q); +} + +void mons_quat_print(mons_quat quat) { + mons_vec4_print(*(mons_vec4*)&quat); +} diff --git a/mons_math/src/util.c b/mons_math/src/util.c new file mode 100644 index 0000000..f0f3ec0 --- /dev/null +++ b/mons_math/src/util.c @@ -0,0 +1,7 @@ +#include "mons_math/util.h" +#include <math.h> + +int mons_float_approx_equal(float a, float b) { + return fabs(a - b) < MONS_FLOAT_EQUAL_EPSILON; +} + diff --git a/mons_math/src/vec2.c b/mons_math/src/vec2.c new file mode 100644 index 0000000..590397d --- /dev/null +++ b/mons_math/src/vec2.c @@ -0,0 +1,120 @@ +#include "mons_math/vec2.h" +#include "mons_math/util.h" +#include "mons_math/vec3.h" +#include <math.h> + +mons_vec2 mons_vec2_add(mons_vec2 a, mons_vec2 b) { + mons_vec2 result = { + a.x + b.x, + a.y + b.y, + }; + return result; +} + +void mons_vec2_add_inplace(mons_vec2 *a, mons_vec2 b) { + a->x += b.x; + a->y += b.y; +} + +mons_vec2 mons_vec2_sub(mons_vec2 a, mons_vec2 b) { + mons_vec2 result = { + a.x - b.x, + a.y - b.y, + }; + return result; +} + +void mons_vec2_sub_inplace(mons_vec2 *a, mons_vec2 b) { + a->x -= b.x; + a->y -= b.y; +} + +mons_vec2 mons_vec2_mul_f(mons_vec2 a, float b) { + mons_vec2 result = { + a.x * b, + a.y * b, + }; + return result; +} + +mons_vec2 mons_vec2_mul_i(mons_vec2 a, int b) { + mons_vec2 result = { + a.x * b, + a.y * b, + }; + return result; +} + +float mons_vec2_dot(mons_vec2 a, mons_vec2 b) { + return (a.x * b.x) + (a.y * b.y); +} + +void mons_vec2_mul_f_inplace(mons_vec2 *a, float b) { + a->x *= b; + a->y *= b; +} + +void mons_vec2_mul_i_inplace(mons_vec2 *a, int b) { + a->x *= b; + a->y *= b; +} + +float mons_vec2_len(mons_vec2 a) { return sqrtf(mons_vec2_len_squared(a)); } + +float mons_vec2_len_squared(mons_vec2 a) { return (a.x * a.x) + (a.y * a.y); } + +mons_vec3 mons_vec2_extend(mons_vec2 a) { + mons_vec3 result = { + a.x, + a.y, + 0.0, + }; + return result; +} + +int mons_vec2_equal(mons_vec2 a, mons_vec2 b) { + return mons_float_approx_equal(a.x, b.x) && + mons_float_approx_equal(a.y, b.y); +} + +mons_vec2 mons_vec2_div_f(mons_vec2 a, float b) { + return (mons_vec2) { + a.x / b, + a.y / b, + }; +} + +mons_vec2 mons_vec2_div_i(mons_vec2 a, int b) { + return (mons_vec2) { + a.x / b, + a.y / b, + }; +} + +void mons_vec2_div_f_inplace(mons_vec2 *a, float b) { + a->x /= b; + a->y /= b; +} + +void mons_vec2_div_i_inplace(mons_vec2 *a, int b) { + a->x /= b; + a->y /= b; +} + +mons_vec2 mons_vec2_negate(mons_vec2 a) { + return mons_vec2_mul_i(a, -1); +} + +void mons_vec2_negate_inplace(mons_vec2 *a) { + mons_vec2_mul_i_inplace(a, -1); +} + +mons_vec2 mons_vec2_normalize(mons_vec2 a) { + float len = mons_vec2_len(a); + return mons_vec2_div_f(a, len); +} + +void mons_vec2_normalize_inplace(mons_vec2 *a) { + float len = mons_vec2_len(*a); + mons_vec2_div_f_inplace(a, len); +} diff --git a/mons_math/src/vec3.c b/mons_math/src/vec3.c new file mode 100644 index 0000000..725f5b3 --- /dev/null +++ b/mons_math/src/vec3.c @@ -0,0 +1,175 @@ +#include "mons_math/vec3.h" +#include "mons_math/vec2.h" +#include "mons_math/vec4.h" +#include "mons_math/util.h" +#include <math.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +mons_vec3 mons_vec3_add(mons_vec3 a, mons_vec3 b) { + mons_vec3 result = { + a.x + b.x, + a.y + b.y, + a.z + b.z, + }; + return result; +} + +void mons_vec3_add_inplace(mons_vec3 *a, mons_vec3 b) { + a->x += b.x; + a->y += b.y; + a->z += b.z; +} + +mons_vec3 mons_vec3_sub(mons_vec3 a, mons_vec3 b) { + mons_vec3 result = { + a.x - b.x, + a.y - b.y, + a.z - b.z, + }; + return result; +} + +void mons_vec3_sub_inplace(mons_vec3 *a, mons_vec3 b) { + a->x -= b.x; + a->y -= b.y; + a->z -= b.z; +} + +mons_vec3 mons_vec3_mul_f(mons_vec3 a, float b) { + mons_vec3 result = { + a.x * b, + a.y * b, + a.z * b, + }; + return result; +} + +mons_vec3 mons_vec3_mul_i(mons_vec3 a, int b) { + mons_vec3 result = { + a.x * b, + a.y * b, + a.z * b, + }; + return result; +} + +float mons_vec3_dot(mons_vec3 a, mons_vec3 b) { + return (a.x * b.x) + (a.y * b.y) + (a.z * b.z); +} + +void mons_vec3_mul_f_inplace(mons_vec3 *a, float b) { + a->x *= b; + a->y *= b; + a->z *= b; +} + +void mons_vec3_mul_i_inplace(mons_vec3 *a, int b) { + a->x *= b; + a->y *= b; + a->z *= b; +} + +float mons_vec3_len(mons_vec3 a) { return sqrtf(mons_vec3_len_squared(a)); } + +float mons_vec3_len_squared(mons_vec3 a) { + return (a.x * a.x) + (a.y * a.y) + (a.z * a.z); +} + +mons_vec4 mons_vec3_extend(mons_vec3 a) { + mons_vec4 result = { + a.x, + a.y, + a.z, + 0.0, + }; + return result; +} + +mons_vec2 mons_vec3_truncate(mons_vec3 a) { + mons_vec2 result = { + a.x, + a.y, + }; + return result; +} + +int mons_vec3_equal(mons_vec3 a, mons_vec3 b) { + return mons_float_approx_equal(a.x, b.x) + && mons_float_approx_equal(a.y, b.y) + && mons_float_approx_equal(a.z, b.z); +} + +mons_vec3 mons_vec3_div_f(mons_vec3 a, float b) { + return (mons_vec3) { + a.x / b, + a.y / b, + a.z / b, + }; +} + +void mons_vec3_div_f_inplace(mons_vec3 *a, float b) { + a->x /= b; + a->y /= b; + a->z /= b; +} + +mons_vec3 mons_vec3_div_i(mons_vec3 a, int b) { + return (mons_vec3) { + a.x / b, + a.y / b, + a.z / b, + }; +} + +void mons_vec3_div_i_inplace(mons_vec3 *a, int b) { + a->x /= b; + a->y /= b; + a->z /= b; +} + +mons_vec3 mons_vec3_negate(mons_vec3 a) { + return mons_vec3_mul_i(a, -1); +} + +void mons_vec3_negate_inplace(mons_vec3 *a) { + return mons_vec3_mul_i_inplace(a, -1); +} + +mons_vec3 mons_vec3_normalize(mons_vec3 a) { + float length = mons_vec3_len(a); + return mons_vec3_div_f(a, length); +} + +void mons_vec3_normalize_inplace(mons_vec3 *a) { + float length = mons_vec3_len(*a); + mons_vec3_div_f_inplace(a, length); +} + +mons_vec3 mons_vec3_cross(mons_vec3 a, mons_vec3 b) { + return (mons_vec3) { + (a.y * b.z) - (a.z * b.y), + (a.z * b.x) - (a.x * b.z), + (a.x * b.y) - (a.y * b.x), + }; +} + +mons_vec3 mons_vec3_mul_memberwise(mons_vec3 a, mons_vec3 b) { + return (mons_vec3) { + a.x * b.x, + a.y * b.y, + a.z * b.z, + }; +} + +void mons_vec3_mul_memberwise_inplace(mons_vec3 *a, mons_vec3 b) { + a->x *= b.x; + a->y *= b.y; + a->z *= b.z; +} + +void mons_vec3_print(mons_vec3 vec) { + printf("[%f, %f, %f]", vec.x, vec.y, vec.z); +} + diff --git a/mons_math/src/vec4.c b/mons_math/src/vec4.c new file mode 100644 index 0000000..d4474ee --- /dev/null +++ b/mons_math/src/vec4.c @@ -0,0 +1,149 @@ +#include "mons_math/vec4.h" +#include "mons_math/vec3.h" +#include "mons_math/util.h" +#include <math.h> +#include <stdio.h> + +mons_vec4 mons_vec4_add(mons_vec4 a, mons_vec4 b) { + mons_vec4 result = { + a.x + b.x, + a.y + b.y, + a.z + b.z, + a.w + b.w, + }; + return result; +} + +void mons_vec4_add_inplace(mons_vec4 *a, mons_vec4 b) { + a->x += b.x; + a->y += b.y; + a->z += b.z; + a->w += b.w; +} + +mons_vec4 mons_vec4_sub(mons_vec4 a, mons_vec4 b) { + mons_vec4 result = { + a.x - b.x, + a.y - b.y, + a.z - b.z, + a.w - b.w, + }; + return result; +} + +void mons_vec4_sub_inplace(mons_vec4 *a, mons_vec4 b) { + a->x -= b.x; + a->y -= b.y; + a->z -= b.z; + a->w -= b.w; +} + +mons_vec4 mons_vec4_mul_f(mons_vec4 a, float b) { + mons_vec4 result = { + a.x * b, + a.y * b, + a.z * b, + a.w * b, + }; + return result; +} + +mons_vec4 mons_vec4_mul_i(mons_vec4 a, int b) { + mons_vec4 result = { + a.x * b, + a.y * b, + a.z * b, + a.w * b, + }; + return result; +} + +void mons_vec4_mul_f_inplace(mons_vec4 *a, float b) { + a->x *= b; + a->y *= b; + a->z *= b; + a->w *= b; +} + +void mons_vec4_mul_i_inplace(mons_vec4 *a, int b) { + a->x *= b; + a->y *= b; + a->z *= b; + a->w *= b; +} + +mons_vec4 mons_vec4_div_f(mons_vec4 a, float b) { + return (mons_vec4) { + a.x / b, + a.y / b, + a.z / b, + a.w / b, + }; +} + +mons_vec4 mons_vec4_div_i(mons_vec4 a, int b) { + return (mons_vec4) { + a.x / b, + a.y / b, + a.z / b, + a.w / b, + }; +} + +void mons_vec4_div_f_inplace(mons_vec4 *a, float b) { + a->x /= b; + a->y /= b; + a->z /= b; + a->w /= b; +} + +void mons_vec4_div_i_inplace(mons_vec4 *a, int b) { + a->x /= b; + a->y /= b; + a->z /= b; + a->w /= b; +} + +float mons_vec4_dot(mons_vec4 a, mons_vec4 b) { + return (a.x * b.x) + (a.y * b.y) + (a.z * b.z) + (a.w * b.w); +} + +float mons_vec4_len(mons_vec4 a) { return sqrt(mons_vec4_len_squared(a)); } + +float mons_vec4_len_squared(mons_vec4 a) { + return (a.x * a.x) + (a.y * a.y) + (a.z * a.z) + (a.w * a.w); +} + +mons_vec3 mons_vec4_truncate(mons_vec4 a) { + mons_vec3 result = {a.x, a.y, a.z}; + return result; +} + +int mons_vec4_equal(mons_vec4 a, mons_vec4 b) { + return mons_float_approx_equal(a.x, b.x) + && mons_float_approx_equal(a.y, b.y) + && mons_float_approx_equal(a.z, b.z) + && mons_float_approx_equal(a.w, b.w); +} + +mons_vec4 mons_vec4_negate(mons_vec4 a) { + return mons_vec4_mul_i(a, -1); +} + +void mons_vec4_negate_inplace(mons_vec4 *a) { + mons_vec4_mul_i_inplace(a, -1); +} + +mons_vec4 mons_vec4_normalize(mons_vec4 a) { + float len = mons_vec4_len(a); + return mons_vec4_div_f(a, len); +} + +void mons_vec4_normalize_inplace(mons_vec4 *a) { + float len = mons_vec4_len(*a); + mons_vec4_div_f_inplace(a, len); +} + +void mons_vec4_print(mons_vec4 vec) { + printf("[%f, %f, %f, %f]", vec.x, vec.y, vec.z, vec.w); +} diff --git a/mons_math/tests/mat2_ops.c b/mons_math/tests/mat2_ops.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/mons_math/tests/mat2_ops.c diff --git a/mons_math/tests/mat3_ops.c b/mons_math/tests/mat3_ops.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/mons_math/tests/mat3_ops.c diff --git a/mons_math/tests/mat4_ops.c b/mons_math/tests/mat4_ops.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/mons_math/tests/mat4_ops.c diff --git a/mons_math/tests/test.h b/mons_math/tests/test.h new file mode 100644 index 0000000..ce94b2e --- /dev/null +++ b/mons_math/tests/test.h @@ -0,0 +1,14 @@ +#ifndef TEST_H +#define TEST_H + +#include <stdio.h> +#include <stdlib.h> + +#define ASSERT(cond) {\ + if (!(cond)) {\ + fprintf(stderr, "Assertion Failed @ %s:%d (%s): %s", __func__, __LINE__, __FILE__, #cond);\ + exit(EXIT_FAILURE);\ + }\ +} + +#endif diff --git a/mons_math/tests/vec2_ops.c b/mons_math/tests/vec2_ops.c new file mode 100644 index 0000000..c7c6d7a --- /dev/null +++ b/mons_math/tests/vec2_ops.c @@ -0,0 +1,81 @@ +#include "mons_math/vec2.h" +#include "mons_math/vec3.h" +#include "mons_math/util.h" +#include "test.h" + +int main(void) { + mons_vec2 a = {2.0, 3.0}; + mons_vec2 b = {6.0, 5.0}; + + // Add + mons_vec2 sum = mons_vec2_add(a, b); + ASSERT(mons_vec2_equal(sum, (mons_vec2){8.0, 8.0})); + + // Add in Place + mons_vec2_add_inplace(&a, b); + ASSERT(mons_vec2_equal(a, sum)); + + // Subtract + mons_vec2 diff = mons_vec2_sub(sum, b); + ASSERT(mons_vec2_equal(diff, (mons_vec2){2.0, 3.0})); + + // Subtract in Place + mons_vec2_sub_inplace(&a, b); + ASSERT(mons_vec2_equal(diff, a)); + + // Multiply (float) + mons_vec2 product_f = mons_vec2_mul_f(a, -3.0); + ASSERT(mons_vec2_equal(product_f, (mons_vec2){-6.0, -9.0})) + + // Multiply in Place (float) + mons_vec2_mul_f_inplace(&a, 3.0); + ASSERT(mons_vec2_equal(mons_vec2_negate(product_f), a)) + + // Divide (float) + mons_vec2 quotient_f = mons_vec2_div_f(product_f, 3.0); + mons_vec2_negate_inplace("ient_f); + ASSERT(mons_vec2_equal(quotient_f, (mons_vec2){2.0, 3.0})); + + // Divide in Place (float) + mons_vec2_div_f_inplace(&a, 3.0); + ASSERT(mons_vec2_equal(quotient_f, a)); + + // Multiply (int) + mons_vec2 product_i = mons_vec2_mul_i(a, -3); + ASSERT(mons_vec2_equal(product_i, (mons_vec2){-6.0, -9.0})) + + // Multiply in Place (int) + mons_vec2_mul_i_inplace(&a, 3); + ASSERT(mons_vec2_equal(mons_vec2_negate(product_i), a)) + + // Divide (int) + mons_vec2 quotient_i = mons_vec2_div_i(product_i, 3); + mons_vec2_negate_inplace("ient_i); + ASSERT(mons_vec2_equal(quotient_i, (mons_vec2){2.0, 3.0})); + + // Divide in Place (int) + mons_vec2_div_i_inplace(&a, 3); + ASSERT(mons_vec2_equal(quotient_i, a)); + + // Get Length + float a_len = mons_vec2_len(a); + ASSERT(mons_float_approx_equal(a_len, 3.60555)); + + // Dot Product + float dot = mons_vec2_dot(a, b); + ASSERT(mons_float_approx_equal(dot, 27.0)); + + // Extend + mons_vec3 extended = mons_vec2_extend(a); + ASSERT(mons_vec3_equal(extended, (mons_vec3){a.x, a.y, 0.0})); + + // Normalize + mons_vec2 normalized = mons_vec2_normalize(a); + ASSERT(mons_float_approx_equal(mons_vec2_len(normalized), 1.0)); + + // Normalize in Place + mons_vec2_normalize_inplace(&a); + ASSERT(mons_float_approx_equal(mons_vec2_len(a), 1.0)); + + return EXIT_SUCCESS; +} diff --git a/mons_math/tests/vec3_ops.c b/mons_math/tests/vec3_ops.c new file mode 100644 index 0000000..e29b396 --- /dev/null +++ b/mons_math/tests/vec3_ops.c @@ -0,0 +1,90 @@ +#include "mons_math/vec2.h" +#include "mons_math/vec3.h" +#include "mons_math/vec4.h" +#include "mons_math/util.h" +#include "test.h" + +int main(void) { + mons_vec3 a = {2.0, 3.0, 4.0}; + mons_vec3 b = {6.0, 5.0, 4.0}; + + // Add + mons_vec3 sum = mons_vec3_add(a, b); + ASSERT(mons_vec3_equal(sum, (mons_vec3){8.0, 8.0, 8.0})); + + // Add in Place + mons_vec3_add_inplace(&a, b); + ASSERT(mons_vec3_equal(a, sum)); + + // Subtract + mons_vec3 diff = mons_vec3_sub(sum, b); + ASSERT(mons_vec3_equal(diff, (mons_vec3){2.0, 3.0, 4.0})); + + // Subtract in Place + mons_vec3_sub_inplace(&a, b); + ASSERT(mons_vec3_equal(diff, a)); + + // Multiply (float) + mons_vec3 product_f = mons_vec3_mul_f(a, -3.0); + ASSERT(mons_vec3_equal(product_f, (mons_vec3){-6.0, -9.0, -12.0})) + + // Multiply in Place (float) + mons_vec3_mul_f_inplace(&a, 3.0); + ASSERT(mons_vec3_equal(mons_vec3_negate(product_f), a)) + + // Divide (float) + mons_vec3 quotient_f = mons_vec3_div_f(product_f, 3.0); + mons_vec3_negate_inplace("ient_f); + ASSERT(mons_vec3_equal(quotient_f, (mons_vec3){2.0, 3.0, 4.0})); + + // Divide in Place (float) + mons_vec3_div_f_inplace(&a, 3.0); + ASSERT(mons_vec3_equal(quotient_f, a)); + + // Multiply (int) + mons_vec3 product_i = mons_vec3_mul_i(a, -3); + ASSERT(mons_vec3_equal(product_i, (mons_vec3){-6.0, -9.0, -12.0})) + + // Multiply in Place (int) + mons_vec3_mul_i_inplace(&a, 3); + ASSERT(mons_vec3_equal(mons_vec3_negate(product_i), a)) + + // Divide (int) + mons_vec3 quotient_i = mons_vec3_div_i(product_i, 3); + mons_vec3_negate_inplace("ient_i); + ASSERT(mons_vec3_equal(quotient_i, (mons_vec3){2.0, 3.0, 4.0})); + + // Divide in Place (int) + mons_vec3_div_i_inplace(&a, 3); + ASSERT(mons_vec3_equal(quotient_i, a)); + + // Get Length + float a_len = mons_vec3_len(a); + ASSERT(mons_float_approx_equal(a_len, 5.38516)); + + // Dot Product + float dot = mons_vec3_dot(a, b); + ASSERT(mons_float_approx_equal(dot, 43.0)); + + // Cross Product + mons_vec3 cross = mons_vec3_cross(a, b); + ASSERT(mons_vec3_equal(cross, (mons_vec3){-8.0, 16.0, -8.0})); + + // Extend + mons_vec4 extended = mons_vec3_extend(a); + ASSERT(mons_vec4_equal(extended, (mons_vec4){a.x, a.y, a.z, 0.0})); + + // Truncate + mons_vec2 truncated = mons_vec3_truncate(a); + ASSERT(mons_vec2_equal(truncated, (mons_vec2){a.x, a.y})); + + // Normalize + mons_vec3 normalized = mons_vec3_normalize(a); + ASSERT(mons_float_approx_equal(mons_vec3_len(normalized), 1.0)); + + // Normalize in Place + mons_vec3_normalize_inplace(&a); + ASSERT(mons_float_approx_equal(mons_vec3_len(a), 1.0)); + + return EXIT_SUCCESS; +} diff --git a/mons_math/tests/vec4_ops.c b/mons_math/tests/vec4_ops.c new file mode 100644 index 0000000..e7837c4 --- /dev/null +++ b/mons_math/tests/vec4_ops.c @@ -0,0 +1,81 @@ +#include "mons_math/vec3.h" +#include "mons_math/vec4.h" +#include "mons_math/util.h" +#include "test.h" + +int main(void) { + mons_vec4 a = {2.0, 3.0, 4.0, 5.0}; + mons_vec4 b = {6.0, 5.0, 4.0, 3.0}; + + // Add + mons_vec4 sum = mons_vec4_add(a, b); + ASSERT(mons_vec4_equal(sum, (mons_vec4){8.0, 8.0, 8.0, 8.0})); + + // Add in Place + mons_vec4_add_inplace(&a, b); + ASSERT(mons_vec4_equal(a, sum)); + + // Subtract + mons_vec4 diff = mons_vec4_sub(sum, b); + ASSERT(mons_vec4_equal(diff, (mons_vec4){2.0, 3.0, 4.0, 5.0})); + + // Subtract in Place + mons_vec4_sub_inplace(&a, b); + ASSERT(mons_vec4_equal(diff, a)); + + // Multiply (float) + mons_vec4 product_f = mons_vec4_mul_f(a, -3.0); + ASSERT(mons_vec4_equal(product_f, (mons_vec4){-6.0, -9.0, -12.0, -15.0})) + + // Multiply in Place (float) + mons_vec4_mul_f_inplace(&a, 3.0); + ASSERT(mons_vec4_equal(mons_vec4_negate(product_f), a)) + + // Divide (float) + mons_vec4 quotient_f = mons_vec4_div_f(product_f, 3.0); + mons_vec4_negate_inplace("ient_f); + ASSERT(mons_vec4_equal(quotient_f, (mons_vec4){2.0, 3.0, 4.0, 5.0})); + + // Divide in Place (float) + mons_vec4_div_f_inplace(&a, 3.0); + ASSERT(mons_vec4_equal(quotient_f, a)); + + // Multiply (int) + mons_vec4 product_i = mons_vec4_mul_i(a, -3); + ASSERT(mons_vec4_equal(product_i, (mons_vec4){-6.0, -9.0, -12.0, -15.0})) + + // Multiply in Place (int) + mons_vec4_mul_i_inplace(&a, 3); + ASSERT(mons_vec4_equal(mons_vec4_negate(product_i), a)) + + // Divide (int) + mons_vec4 quotient_i = mons_vec4_div_i(product_i, 3); + mons_vec4_negate_inplace("ient_i); + ASSERT(mons_vec4_equal(quotient_i, (mons_vec4){2.0, 3.0, 4.0, 5.0})); + + // Divide in Place (int) + mons_vec4_div_i_inplace(&a, 3); + ASSERT(mons_vec4_equal(quotient_i, a)); + + // Get Length + float a_len = mons_vec4_len(a); + ASSERT(mons_float_approx_equal(a_len, 7.34846)); + + // Dot Product + float dot = mons_vec4_dot(a, b); + ASSERT(mons_float_approx_equal(dot, 58.0)); + + // Truncate + mons_vec3 truncated = mons_vec4_truncate(a); + ASSERT(mons_vec3_equal(truncated, (mons_vec3){a.x, a.y, a.z})); + + // Normalize + mons_vec4 normalized = mons_vec4_normalize(a); + ASSERT(mons_float_approx_equal(mons_vec4_len(normalized), 1.0)); + + // Normalize in Place + mons_vec4_normalize_inplace(&a); + ASSERT(mons_float_approx_equal(mons_vec4_len(a), 1.0)); + + return EXIT_SUCCESS; +} |