revolver

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 2aed9170f846b7c8036b4ea0c50634024803ed44
parent 1e57b726b635a7df096307ec28f381cf6af0ead3
Author: Samdal <samdal@protonmail.com>
Date:   Sat, 22 Mar 2025 23:00:31 +0100

a lot more math functions

Diffstat:
Mexamples/framebuffer.c | 2+-
Mexamples/test.c | 3---
Msrc/platform/platform_math.c | 543+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Msrc/platform/platform_math.h | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
4 files changed, 600 insertions(+), 37 deletions(-)

diff --git a/examples/framebuffer.c b/examples/framebuffer.c @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////// -// simple_texture.c +// framebuffer.c #include "revolver_inc.h" #include "revolver_inc.c" diff --git a/examples/test.c b/examples/test.c @@ -1,7 +1,4 @@ -////////////////////////////////////////////////////////////////// -// simple_texture.c - #include "revolver_inc.h" #include "revolver_inc.c" diff --git a/src/platform/platform_math.c b/src/platform/platform_math.c @@ -12,45 +12,255 @@ RV_GLOBAL s64 rv_range_diff(rv_range range) // vector math -RV_GLOBAL f32 rv_vec3_dot(const rv_vec3 a, const rv_vec3 b) +// vec2 +RV_GLOBAL rv_vec2 rv_vec2_neg(rv_vec2 v) { + return rv_vec2_scale(v, -1); +} +RV_GLOBAL rv_vec2 rv_vec2_norm(rv_vec2 v) { + f32 len = rv_vec2_len(v); + return rv_vec2_scale(v, len != 0.f ? 1.0f / rv_vec2_len(v) : 1.f); +} +RV_GLOBAL rv_vec2 rv_vec2_scale(rv_vec2 v, f32 s) +{ + return rv_v2(v.x * s, v.y * s); +} +RV_GLOBAL rv_vec2 rv_vec2_add(rv_vec2 a, rv_vec2 b) +{ + return rv_v2(a.x + b.x, a.y + b.y); +} +RV_GLOBAL rv_vec2 rv_vec2_sub(rv_vec2 a, rv_vec2 b) { - return (a.x * b.x) + (a.y * b.y) + (a.z * b.z); + return rv_v2(a.x - b.x, a.y - b.y); } +RV_GLOBAL rv_vec2 rv_vec2_mul(rv_vec2 a, rv_vec2 b) +{ + return rv_v2(a.x * b.x, a.y * b.y); +} +RV_GLOBAL rv_vec2 rv_vec2_div(rv_vec2 a, rv_vec2 b) +{ + return rv_v2(a.x / b.x, a.y / b.y); +} +RV_GLOBAL rv_vec2 rv_vec2_project_onto(rv_vec2 a, rv_vec2 b) +{ + f32 dot = rv_vec2_dot(a, b); + f32 len = rv_vec2_dot(b, b); + + // Orthogonal, so return b + if (len == 0.f) return b; -RV_GLOBAL f32 rv_vec3_len(const rv_vec3 v) + return rv_vec2_scale(b, dot / len); +} + +RV_GLOBAL f32 rv_vec2_len(rv_vec2 v) +{ + return (f32)sqrtf(rv_vec2_dot(v, v)); +} +RV_GLOBAL f32 rv_vec2_dist(rv_vec2 a, rv_vec2 b) +{ + f32 dx = (a.x - b.x); + f32 dy = (a.y - b.y); + return (float)(sqrtf(dx * dx + dy * dy)); +} +RV_GLOBAL f32 rv_vec2_cross(rv_vec2 a, rv_vec2 b) { - return sqrtf(rv_vec3_dot(v, v)); + return a.x * b.y - a.y * b.x; +} +RV_GLOBAL f32 rv_vec2_angle(rv_vec2 a, rv_vec2 b) +{ + return (float)acos(rv_vec2_dot(a, b) / (rv_vec2_len(a) * rv_vec2_len(b))); +} +RV_GLOBAL f32 rv_vec2_dot(rv_vec2 a, rv_vec2 b) +{ + return (f32)(a.x * b.x + a.y * b.y); } -RV_GLOBAL rv_vec3 rv_vec3_scale(const rv_vec3 v, const f32 s) +RV_GLOBAL bool32 rv_vec2_nan(rv_vec2 v) { - return rv_v3(v.x * s, v.y * s, v.z * s); + if (v.x != v.x || v.y != v.y) return true; + return false; } +RV_GLOBAL bool32 rv_vec2_eq(rv_vec2 a, rv_vec2 b) +{ + return (a.x == b.x && a.y == b.y); +} + -RV_GLOBAL rv_vec3 rv_vec3_norm(const rv_vec3 v) +// vec3 +RV_GLOBAL rv_vec3 rv_vec3_neg(rv_vec3 v) +{ + return rv_vec3_scale(v, -1.f); +} +RV_GLOBAL rv_vec3 rv_vec3_scale(rv_vec3 v, f32 s) +{ + return rv_v3(v.x * s, v.y * s, v.z * s); +} +RV_GLOBAL rv_vec3 rv_vec3_norm(rv_vec3 v) { f32 len = rv_vec3_len(v); return len == 0.f ? v : rv_vec3_scale(v, 1.f / len); } +RV_GLOBAL rv_vec3 rv_vec3_add(rv_vec3 a, rv_vec3 b) +{ + return rv_v3(a.x + b.x, a.y + b.y, a.z + b.z); +} +RV_GLOBAL rv_vec3 rv_vec3_sub(rv_vec3 a, rv_vec3 b) +{ + return rv_v3(a.x - b.x, a.y - b.y, a.z - b.z); +} +RV_GLOBAL rv_vec3 rv_vec3_mul(rv_vec3 a, rv_vec3 b) +{ + return rv_v3(a.x * b.x, a.y * b.y, a.z * b.z); +} +RV_GLOBAL rv_vec3 rv_vec3_div(rv_vec3 a, rv_vec3 b) +{ + return rv_v3(a.x / b.x, a.y / b.y, a.z / b.z); +} +RV_GLOBAL rv_vec3 rv_vec3_project_onto(rv_vec3 a, rv_vec3 b) +{ + f32 dot = rv_vec3_dot(a, b); + f32 len = rv_vec3_dot(b, b); + + // Orthogonal, so return b + if (len == 0.f) return b; + + return rv_vec3_scale(b, dot / len); +} +RV_GLOBAL rv_vec3 rv_vec3_cross(rv_vec3 a, rv_vec3 b) +{ + return rv_v3 + ( + a.y * b.z - a.z * b.y, + a.z * b.x - a.x * b.z, + a.x * b.y - a.y * b.x + ); +} + +RV_GLOBAL f32 rv_vec3_len(rv_vec3 v) +{ + return (f32)sqrt(rv_vec3_dot(v, v)); +} +RV_GLOBAL f32 rv_vec3_dist(rv_vec3 a, rv_vec3 b) +{ + f32 dx = (a.x - b.x); + f32 dy = (a.y - b.y); + f32 dz = (a.z - b.z); + return sqrtf(dx * dx + dy * dy + dz * dz); +} +RV_GLOBAL f32 rv_vec3_dot(rv_vec3 a, rv_vec3 b) +{ + return (f32)((a.x * b.x) + (a.y * b.y) + a.z * b.z); +} + +RV_GLOBAL bool32 rv_vec3_nan(rv_vec3 v) +{ + if (v.x != v.x || v.y != v.y || v.z != v.z) return true; + return false; +} +RV_GLOBAL bool32 rv_vec3_eq(rv_vec3 a, rv_vec3 b) +{ + return (a.x == b.x && a.y == b.y && a.z == b.z); +} +RV_GLOBAL bool32 rv_vec3_same_dir(rv_vec3 a, rv_vec3 b) +{ + return (rv_vec3_dot(a, b) > 0.f); +} + +// vec4 +RV_GLOBAL rv_vec4 rv_vec4_neg(rv_vec4 v) +{ + return rv_vec4_scale(v, -1); +} +RV_GLOBAL rv_vec4 rv_vec4_scale(rv_vec4 v, f32 s) +{ + return rv_v4(v.x * s, v.y * s, v.z * s, v.w * s); +} +RV_GLOBAL rv_vec4 rv_vec4_norm(rv_vec4 v) +{ + return rv_vec4_scale(v, 1.0f / rv_vec4_len(v)); +} +RV_GLOBAL rv_vec4 rv_vec4_add(rv_vec4 a, rv_vec4 b) +{ + return rv_v4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w); +} +RV_GLOBAL rv_vec4 rv_vec4_sub(rv_vec4 a, rv_vec4 b) +{ + return rv_v4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w); +} +RV_GLOBAL rv_vec4 rv_vec4_mul(rv_vec4 a, rv_vec4 b) +{ + return rv_v4(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w); +} +RV_GLOBAL rv_vec4 rv_vec4_div(rv_vec4 a, rv_vec4 b) +{ + return rv_v4(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w); +} +RV_GLOBAL rv_vec4 rv_vec4_project_onto(rv_vec4 a, rv_vec4 b) +{ + f32 dot = rv_vec4_dot(a, b); + f32 len = rv_vec4_dot(b, b); + + // Orthogonal, so return b + if (len == 0.f) return b; + + return rv_vec4_scale(b, dot / len); +} + +RV_GLOBAL f32 rv_vec4_len(rv_vec4 v) +{ + return (f32)sqrtf(rv_vec4_dot(v, v)); +} +RV_GLOBAL f32 rv_vec4_dist(rv_vec4 a, rv_vec4 b) +{ + f32 dx = (a.x - b.x); + f32 dy = (a.y - b.y); + f32 dz = (a.z - b.z); + f32 dw = (a.w - b.w); + return (float)(sqrtf(dx * dx + dy * dy + dz * dz + dw * dw)); +} +RV_GLOBAL f32 rv_vec4_dot(rv_vec4 a, rv_vec4 b) +{ + return (f32)(a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w); +} + +RV_GLOBAL bool32 rv_vec4_nan(rv_vec4 v) +{ + if (v.x != v.x || v.y != v.y || v.z != v.z || v.w != v.w) return true; + return false; +} +RV_GLOBAL bool32 rv_vec4_eq(rv_vec4 a, rv_vec4 b) +{ + return (a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w); +} ////////////////////////////////////////////////////////////////// // matrix math -RV_GLOBAL rv_mat4 rv_mat4_rotatev(const f32 angle, const rv_vec3 axis) + +RV_GLOBAL rv_mat4 rv_mat4_translatev(rv_vec3 v) +{ + rv_mat4 m_res = rv_mat4_identity(); + + m_res.elements[0 + 4 * 3] = v.x; + m_res.elements[1 + 4 * 3] = v.y; + m_res.elements[2 + 4 * 3] = v.z; + + return m_res; +} +RV_GLOBAL rv_mat4 rv_mat4_rotatev(f32 angle, rv_vec3 axis) { rv_mat4 m_res = rv_mat4_identity(); - f32 a = angle; - f32 c = cosf(a); - f32 s = sinf(a); + float a = angle; + float c = (float)cos(a); + float s = (float)sin(a); rv_vec3 naxis = rv_vec3_norm(axis); - f32 x = naxis.x; - f32 y = naxis.y; - f32 z = naxis.z; + float x = naxis.x; + float y = naxis.y; + float z = naxis.z; - // first column + //First column m_res.elements[0 + 0 * 4] = x * x * (1 - c) + c; m_res.elements[1 + 0 * 4] = x * y * (1 - c) + z * s; m_res.elements[2 + 0 * 4] = x * z * (1 - c) - y * s; @@ -67,8 +277,7 @@ RV_GLOBAL rv_mat4 rv_mat4_rotatev(const f32 angle, const rv_vec3 axis) return m_res; } - -RV_GLOBAL rv_mat4 rv_mat4_scalev(const rv_vec3 v) +RV_GLOBAL rv_mat4 rv_mat4_scalev(rv_vec3 v) { rv_mat4 m_res = rv_mat4_identity(); m_res.elements[0 + 0 * 4] = v.x; @@ -76,26 +285,205 @@ RV_GLOBAL rv_mat4 rv_mat4_scalev(const rv_vec3 v) m_res.elements[2 + 2 * 4] = v.z; return m_res; } +RV_GLOBAL rv_mat4 rv_mat4_transpose(rv_mat4 m) +{ + rv_mat4 t = rv_mat4_identity(); + + // First row + t.elements[0 * 4 + 0] = m.elements[0 * 4 + 0]; + t.elements[1 * 4 + 0] = m.elements[0 * 4 + 1]; + t.elements[2 * 4 + 0] = m.elements[0 * 4 + 2]; + t.elements[3 * 4 + 0] = m.elements[0 * 4 + 3]; + + // Second row + t.elements[0 * 4 + 1] = m.elements[1 * 4 + 0]; + t.elements[1 * 4 + 1] = m.elements[1 * 4 + 1]; + t.elements[2 * 4 + 1] = m.elements[1 * 4 + 2]; + t.elements[3 * 4 + 1] = m.elements[1 * 4 + 3]; -RV_GLOBAL rv_mat4 -rv_mat4_mul(const rv_mat4 m0, const rv_mat4 m1) + // Third row + t.elements[0 * 4 + 2] = m.elements[2 * 4 + 0]; + t.elements[1 * 4 + 2] = m.elements[2 * 4 + 1]; + t.elements[2 * 4 + 2] = m.elements[2 * 4 + 2]; + t.elements[3 * 4 + 2] = m.elements[2 * 4 + 3]; + + // Fourth row + t.elements[0 * 4 + 3] = m.elements[3 * 4 + 0]; + t.elements[1 * 4 + 3] = m.elements[3 * 4 + 1]; + t.elements[2 * 4 + 3] = m.elements[3 * 4 + 2]; + t.elements[3 * 4 + 3] = m.elements[3 * 4 + 3]; + + return t; +} +RV_GLOBAL rv_mat4 rv_mat4_inverse(rv_mat4 m) +{ + rv_mat4 res = rv_mat4_identity(); + + f32 temp[16]; + + temp[0] = m.elements[5] * m.elements[10] * m.elements[15] - + m.elements[5] * m.elements[11] * m.elements[14] - + m.elements[9] * m.elements[6] * m.elements[15] + + m.elements[9] * m.elements[7] * m.elements[14] + + m.elements[13] * m.elements[6] * m.elements[11] - + m.elements[13] * m.elements[7] * m.elements[10]; + + temp[4] = -m.elements[4] * m.elements[10] * m.elements[15] + + m.elements[4] * m.elements[11] * m.elements[14] + + m.elements[8] * m.elements[6] * m.elements[15] - + m.elements[8] * m.elements[7] * m.elements[14] - + m.elements[12] * m.elements[6] * m.elements[11] + + m.elements[12] * m.elements[7] * m.elements[10]; + + temp[8] = m.elements[4] * m.elements[9] * m.elements[15] - + m.elements[4] * m.elements[11] * m.elements[13] - + m.elements[8] * m.elements[5] * m.elements[15] + + m.elements[8] * m.elements[7] * m.elements[13] + + m.elements[12] * m.elements[5] * m.elements[11] - + m.elements[12] * m.elements[7] * m.elements[9]; + + temp[12] = -m.elements[4] * m.elements[9] * m.elements[14] + + m.elements[4] * m.elements[10] * m.elements[13] + + m.elements[8] * m.elements[5] * m.elements[14] - + m.elements[8] * m.elements[6] * m.elements[13] - + m.elements[12] * m.elements[5] * m.elements[10] + + m.elements[12] * m.elements[6] * m.elements[9]; + + temp[1] = -m.elements[1] * m.elements[10] * m.elements[15] + + m.elements[1] * m.elements[11] * m.elements[14] + + m.elements[9] * m.elements[2] * m.elements[15] - + m.elements[9] * m.elements[3] * m.elements[14] - + m.elements[13] * m.elements[2] * m.elements[11] + + m.elements[13] * m.elements[3] * m.elements[10]; + + temp[5] = m.elements[0] * m.elements[10] * m.elements[15] - + m.elements[0] * m.elements[11] * m.elements[14] - + m.elements[8] * m.elements[2] * m.elements[15] + + m.elements[8] * m.elements[3] * m.elements[14] + + m.elements[12] * m.elements[2] * m.elements[11] - + m.elements[12] * m.elements[3] * m.elements[10]; + + temp[9] = -m.elements[0] * m.elements[9] * m.elements[15] + + m.elements[0] * m.elements[11] * m.elements[13] + + m.elements[8] * m.elements[1] * m.elements[15] - + m.elements[8] * m.elements[3] * m.elements[13] - + m.elements[12] * m.elements[1] * m.elements[11] + + m.elements[12] * m.elements[3] * m.elements[9]; + + temp[13] = m.elements[0] * m.elements[9] * m.elements[14] - + m.elements[0] * m.elements[10] * m.elements[13] - + m.elements[8] * m.elements[1] * m.elements[14] + + m.elements[8] * m.elements[2] * m.elements[13] + + m.elements[12] * m.elements[1] * m.elements[10] - + m.elements[12] * m.elements[2] * m.elements[9]; + + temp[2] = m.elements[1] * m.elements[6] * m.elements[15] - + m.elements[1] * m.elements[7] * m.elements[14] - + m.elements[5] * m.elements[2] * m.elements[15] + + m.elements[5] * m.elements[3] * m.elements[14] + + m.elements[13] * m.elements[2] * m.elements[7] - + m.elements[13] * m.elements[3] * m.elements[6]; + + temp[6] = -m.elements[0] * m.elements[6] * m.elements[15] + + m.elements[0] * m.elements[7] * m.elements[14] + + m.elements[4] * m.elements[2] * m.elements[15] - + m.elements[4] * m.elements[3] * m.elements[14] - + m.elements[12] * m.elements[2] * m.elements[7] + + m.elements[12] * m.elements[3] * m.elements[6]; + + temp[10] = m.elements[0] * m.elements[5] * m.elements[15] - + m.elements[0] * m.elements[7] * m.elements[13] - + m.elements[4] * m.elements[1] * m.elements[15] + + m.elements[4] * m.elements[3] * m.elements[13] + + m.elements[12] * m.elements[1] * m.elements[7] - + m.elements[12] * m.elements[3] * m.elements[5]; + + temp[14] = -m.elements[0] * m.elements[5] * m.elements[14] + + m.elements[0] * m.elements[6] * m.elements[13] + + m.elements[4] * m.elements[1] * m.elements[14] - + m.elements[4] * m.elements[2] * m.elements[13] - + m.elements[12] * m.elements[1] * m.elements[6] + + m.elements[12] * m.elements[2] * m.elements[5]; + + temp[3] = -m.elements[1] * m.elements[6] * m.elements[11] + + m.elements[1] * m.elements[7] * m.elements[10] + + m.elements[5] * m.elements[2] * m.elements[11] - + m.elements[5] * m.elements[3] * m.elements[10] - + m.elements[9] * m.elements[2] * m.elements[7] + + m.elements[9] * m.elements[3] * m.elements[6]; + + temp[7] = m.elements[0] * m.elements[6] * m.elements[11] - + m.elements[0] * m.elements[7] * m.elements[10] - + m.elements[4] * m.elements[2] * m.elements[11] + + m.elements[4] * m.elements[3] * m.elements[10] + + m.elements[8] * m.elements[2] * m.elements[7] - + m.elements[8] * m.elements[3] * m.elements[6]; + + temp[11] = -m.elements[0] * m.elements[5] * m.elements[11] + + m.elements[0] * m.elements[7] * m.elements[9] + + m.elements[4] * m.elements[1] * m.elements[11] - + m.elements[4] * m.elements[3] * m.elements[9] - + m.elements[8] * m.elements[1] * m.elements[7] + + m.elements[8] * m.elements[3] * m.elements[5]; + + temp[15] = m.elements[0] * m.elements[5] * m.elements[10] - + m.elements[0] * m.elements[6] * m.elements[9] - + m.elements[4] * m.elements[1] * m.elements[10] + + m.elements[4] * m.elements[2] * m.elements[9] + + m.elements[8] * m.elements[1] * m.elements[6] - + m.elements[8] * m.elements[2] * m.elements[5]; + + float determinant = m.elements[0] * temp[0] + m.elements[1] * temp[4] + m.elements[2] * temp[8] + m.elements[3] * temp[12]; + determinant = 1.0f / determinant; + + for (int i = 0; i < 4 * 4; i++) + res.elements[i] = (float)(temp[i] * (float)determinant); + + return res; +} +RV_GLOBAL rv_mat4 rv_mat4_look_at(rv_vec3 position, rv_vec3 target, rv_vec3 up) +{ + rv_vec3 f = rv_vec3_norm(rv_vec3_sub(target, position)); + rv_vec3 s = rv_vec3_norm(rv_vec3_cross(f, up)); + rv_vec3 u = rv_vec3_cross(s, f); + + rv_mat4 m_res = rv_mat4_identity(); + m_res.elements[0 * 4 + 0] = s.x; + m_res.elements[1 * 4 + 0] = s.y; + m_res.elements[2 * 4 + 0] = s.z; + + m_res.elements[0 * 4 + 1] = u.x; + m_res.elements[1 * 4 + 1] = u.y; + m_res.elements[2 * 4 + 1] = u.z; + + m_res.elements[0 * 4 + 2] = -f.x; + m_res.elements[1 * 4 + 2] = -f.y; + m_res.elements[2 * 4 + 2] = -f.z; + + m_res.elements[3 * 4 + 0] = -rv_vec3_dot(s, position);; + m_res.elements[3 * 4 + 1] = -rv_vec3_dot(u, position); + m_res.elements[3 * 4 + 2] = rv_vec3_dot(f, position); + + return m_res; +} + +RV_GLOBAL rv_mat4 rv_mat4_mul(rv_mat4 m0, rv_mat4 m1) { rv_mat4 m_res = {0}; - for (s32 y = 0; y < 4; ++y) { - for (s32 x = 0; x < 4; ++x) { + for (u32 y = 0; y < 4; ++y) { + for (u32 x = 0; x < 4; ++x) { f32 sum = 0.0f; - for (s32 e = 0; e < 4; ++e) { + for (u32 e = 0; e < 4; ++e) { sum += m0.elements[x + e * 4] * m1.elements[e + y * 4]; } m_res.elements[x + y * 4] = sum; } } + return m_res; } - -RV_GLOBAL rv_mat4 rv_mat4_mul_list(const s32 count, ...) +RV_GLOBAL rv_mat4 rv_mat4_mul_list(s32 count, ...) { - va_list ap; rv_mat4 m = rv_mat4_identity(); va_start(ap, count); @@ -105,3 +493,108 @@ RV_GLOBAL rv_mat4 rv_mat4_mul_list(const s32 count, ...) va_end(ap); return m; } +RV_GLOBAL rv_vec4 rv_mat4_mul_vec4(rv_mat4 m, rv_vec4 v) +{ + return rv_v4 + ( + m.elements[0 + 4 * 0] * v.x + m.elements[0 + 4 * 1] * v.y + m.elements[0 + 4 * 2] * v.z + m.elements[0 + 4 * 3] * v.w, + m.elements[1 + 4 * 0] * v.x + m.elements[1 + 4 * 1] * v.y + m.elements[1 + 4 * 2] * v.z + m.elements[1 + 4 * 3] * v.w, + m.elements[2 + 4 * 0] * v.x + m.elements[2 + 4 * 1] * v.y + m.elements[2 + 4 * 2] * v.z + m.elements[2 + 4 * 3] * v.w, + m.elements[3 + 4 * 0] * v.x + m.elements[3 + 4 * 1] * v.y + m.elements[3 + 4 * 2] * v.z + m.elements[3 + 4 * 3] * v.w + ); +} +RV_GLOBAL rv_vec3 rv_mat4_mul_vec3(rv_mat4 m, rv_vec3 v) +{ + return rv_mat4_mul_vec4(m, rv_v4(.xyz = v, .w = 1.f)).xyz; +} + +RV_GLOBAL rv_mat4 rv_mat4_ortho_norm(rv_mat4 m) +{ + m.v.right = rv_vec4_norm(m.v.right); + m.v.up = rv_vec4_norm(m.v.up); + m.v.dir = rv_vec4_norm(m.v.dir); + return m; +} +RV_GLOBAL rv_mat4 rv_mat4_ortho(f32 l, f32 r, f32 b, f32 t, f32 n, f32 f) +{ + rv_mat4 m_res = rv_mat4_identity(); + + // Main diagonal + m_res.elements[0 + 0 * 4] = 2.0f / (r - l); + m_res.elements[1 + 1 * 4] = 2.0f / (t - b); + m_res.elements[2 + 2 * 4] = -2.0f / (f - n); + + // Last column + m_res.elements[0 + 3 * 4] = -(r + l) / (r - l); + m_res.elements[1 + 3 * 4] = -(t + b) / (t - b); + m_res.elements[2 + 3 * 4] = -(f + n) / (f - n); + + return m_res; +} +RV_GLOBAL rv_mat4 rv_mat4_perspective(f32 fov, f32 asp_ratio, f32 n, f32 f) +{ + // Zero matrix + rv_mat4 m_res = {0}; + + f32 q = 1.0f / (float)tan(rv_deg2rad(0.5f * fov)); + f32 a = q / asp_ratio; + f32 b = (n + f) / (n - f); + f32 c = (2.0f * n * f) / (n - f); + + m_res.elements[0 + 0 * 4] = a; + m_res.elements[1 + 1 * 4] = q; + m_res.elements[2 + 2 * 4] = b; + m_res.elements[2 + 3 * 4] = c; + m_res.elements[3 + 2 * 4] = -1.0f; + + return m_res; +} + +RV_GLOBAL void rv_mat4_decompose(const rv_mat4* m, rv_vec3* translation, rv_vec3* rotation, rv_vec3* scale) +{ + rv_mat4 mat = *m; + + scale->xyz[0] = rv_vec4_len(mat.v.right); + scale->xyz[1] = rv_vec4_len(mat.v.up); + scale->xyz[2] = rv_vec4_len(mat.v.dir); + + mat = rv_mat4_ortho_norm(mat); + + rotation->xyz[0] = rv_rad2deg(atan2f(mat.m[1][2], mat.m[2][2])); + rotation->xyz[1] = rv_rad2deg(atan2f(-mat.m[0][2], sqrtf(mat.m[1][2] * mat.m[1][2] + + mat.m[2][2] * mat.m[2][2]))); + rotation->xyz[2] = rv_rad2deg(atan2f(mat.m[0][1], mat.m[0][0])); + + translation->xyz[0] = mat.v.position.x; + translation->xyz[1] = mat.v.position.y; + translation->xyz[2] = mat.v.position.z; +} +RV_GLOBAL rv_mat4 rv_mat4_recompose(rv_vec3 translation, rv_vec3 rotation, rv_vec3 scale) +{ + rv_mat4 mat = rv_mat4_identity(); + + rv_vec3 direction_unary[3] = { + RV_XAXIS, + RV_YAXIS, + RV_ZAXIS + }; + + rv_mat4 rot[3] = {rv_mat4_identity(), rv_mat4_identity(), rv_mat4_identity()}; + for (uint32_t i = 0; i < 3; ++i) { + rot[i] = rv_mat4_rotatev(rv_deg2rad(rotation.xyz[i]), direction_unary[i]); + } + + mat = rv_mat4_mul_list(3, rot[2], rot[1], rot[0]); + + float valid_scale[3] = {0}; + for (uint32_t i = 0; i < 3; ++i) { + valid_scale[i] = fabsf(scale.xyz[i]) < RV_EPSILON ? 0.001f : scale.xyz[i]; + } + + mat.v.right = rv_vec4_scale(mat.v.right, valid_scale[0]); + mat.v.up = rv_vec4_scale(mat.v.up, valid_scale[1]); + mat.v.dir = rv_vec4_scale(mat.v.dir, valid_scale[2]); + mat.v.position = rv_v4(translation.xyz[0], translation.xyz[1], translation.xyz[2], 1.f); + + return mat; +} diff --git a/src/platform/platform_math.h b/src/platform/platform_math.h @@ -17,10 +17,19 @@ #define rv_array_count(arr) sizeof(arr) / sizeof(arr[0]) +#define RV_EPSILON 1e-6 +#define RV_PI 3.1415926535897932 + #define RV_XAXIS rv_v3(1, 0, 0) #define RV_YAXIS rv_v3(0, 1, 0) #define RV_ZAXIS rv_v3(0, 0, 1) +#define rv_rad2deg(radians)\ + (float)((radians * 180.0f) / RV_PI) + +#define rv_deg2rad(degrees)\ + (float)((degrees * RV_PI) / 180.0f) + // range RV_GLOBAL s64 rv_range_diff(rv_range range); @@ -28,15 +37,79 @@ RV_GLOBAL s64 rv_range_diff(rv_range range); ////////////////////////////////////////////////////////////////// // vector math -RV_GLOBAL f32 rv_vec3_dot(const rv_vec3 a, const rv_vec3 b); -RV_GLOBAL f32 rv_vec3_len(const rv_vec3 v); -RV_GLOBAL rv_vec3 rv_vec3_scale(const rv_vec3 v, const f32 s); -RV_GLOBAL rv_vec3 rv_vec3_norm(const rv_vec3 v); +// vec2 +RV_GLOBAL rv_vec2 rv_vec2_neg(rv_vec2 v); +RV_GLOBAL rv_vec2 rv_vec2_norm(rv_vec2 v); +RV_GLOBAL rv_vec2 rv_vec2_scale(rv_vec2 v, f32 s); +RV_GLOBAL rv_vec2 rv_vec2_add(rv_vec2 a, rv_vec2 b); +RV_GLOBAL rv_vec2 rv_vec2_sub(rv_vec2 a, rv_vec2 b); +RV_GLOBAL rv_vec2 rv_vec2_mul(rv_vec2 a, rv_vec2 b); +RV_GLOBAL rv_vec2 rv_vec2_div(rv_vec2 a, rv_vec2 b); +RV_GLOBAL rv_vec2 rv_vec2_project_onto(rv_vec2 a, rv_vec2 b); + +RV_GLOBAL f32 rv_vec2_len(rv_vec2 v); +RV_GLOBAL f32 rv_vec2_dist(rv_vec2 a, rv_vec2 b); +RV_GLOBAL f32 rv_vec2_cross(rv_vec2 a, rv_vec2 b); +RV_GLOBAL f32 rv_vec2_angle(rv_vec2 a, rv_vec2 b); +RV_GLOBAL f32 rv_vec2_dot(rv_vec2 a, rv_vec2 b); + +RV_GLOBAL bool32 rv_vec2_nan(rv_vec2 v); +RV_GLOBAL bool32 rv_vec2_eq(rv_vec2 a, rv_vec2 b); + +// vec3 +RV_GLOBAL rv_vec3 rv_vec3_neg(rv_vec3 v); +RV_GLOBAL rv_vec3 rv_vec3_scale(rv_vec3 v, f32 s); +RV_GLOBAL rv_vec3 rv_vec3_norm(rv_vec3 v); +RV_GLOBAL rv_vec3 rv_vec3_add(rv_vec3 a, rv_vec3 b); +RV_GLOBAL rv_vec3 rv_vec3_sub(rv_vec3 a, rv_vec3 b); +RV_GLOBAL rv_vec3 rv_vec3_mul(rv_vec3 a, rv_vec3 b); +RV_GLOBAL rv_vec3 rv_vec3_div(rv_vec3 a, rv_vec3 b); +RV_GLOBAL rv_vec3 rv_vec3_project_onto(rv_vec3 a, rv_vec3 b); +RV_GLOBAL rv_vec3 rv_vec3_cross(rv_vec3 a, rv_vec3 b); + +RV_GLOBAL f32 rv_vec3_len(rv_vec3 v); +RV_GLOBAL f32 rv_vec3_dist(rv_vec3 a, rv_vec3 b); +RV_GLOBAL f32 rv_vec3_dot(rv_vec3 a, rv_vec3 b); + +RV_GLOBAL bool32 rv_vec3_nan(rv_vec3 v); +RV_GLOBAL bool32 rv_vec3_eq(rv_vec3 a, rv_vec3 b); +RV_GLOBAL bool32 rv_vec3_same_dir(rv_vec3 a, rv_vec3 b); + +// vec4 +RV_GLOBAL rv_vec4 rv_vec4_neg(rv_vec4 v); +RV_GLOBAL rv_vec4 rv_vec4_scale(rv_vec4 v, f32 s); +RV_GLOBAL rv_vec4 rv_vec4_norm(rv_vec4 v); +RV_GLOBAL rv_vec4 rv_vec4_add(rv_vec4 a, rv_vec4 b); +RV_GLOBAL rv_vec4 rv_vec4_sub(rv_vec4 a, rv_vec4 b); +RV_GLOBAL rv_vec4 rv_vec4_mul(rv_vec4 a, rv_vec4 b); +RV_GLOBAL rv_vec4 rv_vec4_div(rv_vec4 a, rv_vec4 b); +RV_GLOBAL rv_vec4 rv_vec4_project_onto(rv_vec4 a, rv_vec4 b); + +RV_GLOBAL f32 rv_vec4_len(rv_vec4 v); +RV_GLOBAL f32 rv_vec4_dist(rv_vec4 a, rv_vec4 b); +RV_GLOBAL f32 rv_vec4_dot(rv_vec4 a, rv_vec4 b); + +RV_GLOBAL bool32 rv_vec4_nan(rv_vec4 v); +RV_GLOBAL bool32 rv_vec4_eq(rv_vec4 a, rv_vec4 b); ////////////////////////////////////////////////////////////////// // matrix math -RV_GLOBAL rv_mat4 rv_mat4_rotatev(const f32 angle, const rv_vec3 axis); -RV_GLOBAL rv_mat4 rv_mat4_scalev(const rv_vec3 v); -RV_GLOBAL rv_mat4 rv_mat4_mul(const rv_mat4 m0, const rv_mat4 m1); -RV_GLOBAL rv_mat4 rv_mat4_mul_list(const s32 count, ...); +RV_GLOBAL rv_mat4 rv_mat4_translatev(rv_vec3 v); +RV_GLOBAL rv_mat4 rv_mat4_rotatev(f32 angle, rv_vec3 axis); +RV_GLOBAL rv_mat4 rv_mat4_scalev(rv_vec3 v); +RV_GLOBAL rv_mat4 rv_mat4_transpose(rv_mat4 m); +RV_GLOBAL rv_mat4 rv_mat4_inverse(rv_mat4 m); +RV_GLOBAL rv_mat4 rv_mat4_look_at(rv_vec3 position, rv_vec3 target, rv_vec3 up); + +RV_GLOBAL rv_mat4 rv_mat4_mul(rv_mat4 m0, rv_mat4 m1); +RV_GLOBAL rv_mat4 rv_mat4_mul_list(s32 count, ...); +RV_GLOBAL rv_vec4 rv_mat4_mul_vec4(rv_mat4 m, rv_vec4 v); +RV_GLOBAL rv_vec3 rv_mat4_mul_vec3(rv_mat4 m, rv_vec3 v); + +RV_GLOBAL rv_mat4 rv_mat4_ortho_norm(rv_mat4 m); +RV_GLOBAL rv_mat4 rv_mat4_ortho(f32 l, f32 r, f32 b, f32 t, f32 n, f32 f); +RV_GLOBAL rv_mat4 rv_mat4_perspective(f32 fov, f32 asp_ratio, f32 n, f32 f); + +RV_GLOBAL void rv_mat4_decompose(const rv_mat4* m, rv_vec3* translation, rv_vec3* rotation, rv_vec3* scale); +RV_GLOBAL rv_mat4 rv_mat4_recompose(rv_vec3 translation, rv_vec3 rotation, rv_vec3 scale);