commit 2aed9170f846b7c8036b4ea0c50634024803ed44
parent 1e57b726b635a7df096307ec28f381cf6af0ead3
Author: Samdal <samdal@protonmail.com>
Date: Sat, 22 Mar 2025 23:00:31 +0100
a lot more math functions
Diffstat:
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);