1433 lines
19 KiB
C
1433 lines
19 KiB
C
|
|
#ifndef _PIUMA_LIB_MATH_H_
|
||
|
|
#define _PIUMA_LIB_MATH_H_
|
||
|
|
|
||
|
|
#include "types.h"
|
||
|
|
#include <math.h>
|
||
|
|
|
||
|
|
// Vector types
|
||
|
|
union v2
|
||
|
|
{
|
||
|
|
struct { f32 x, y; };
|
||
|
|
struct { f32 r, g; };
|
||
|
|
struct { f32 u, v; };
|
||
|
|
struct { f32 E[2]; };
|
||
|
|
};
|
||
|
|
|
||
|
|
union v2s
|
||
|
|
{
|
||
|
|
struct { s32 x, y; };
|
||
|
|
struct { s32 r, g; };
|
||
|
|
struct { s32 u, v; };
|
||
|
|
struct { s32 E[2]; };
|
||
|
|
};
|
||
|
|
|
||
|
|
union v2u
|
||
|
|
{
|
||
|
|
struct { u32 x, y; };
|
||
|
|
struct { u32 r, g; };
|
||
|
|
struct { u32 u, v; };
|
||
|
|
struct { u32 E[2]; };
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
union v3
|
||
|
|
{
|
||
|
|
struct { f32 x, y, z; };
|
||
|
|
struct { f32 r, g, b; };
|
||
|
|
struct { f32 u, v, w_; };
|
||
|
|
struct { f32 E[3]; };
|
||
|
|
|
||
|
|
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
v2 xy;
|
||
|
|
f32 ignored0;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
f32 ignored1;
|
||
|
|
v2 yz;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
v2 uv;
|
||
|
|
f32 ignored2;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
f32 ignored3;
|
||
|
|
v2 vw_;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
f32 pitch;
|
||
|
|
f32 yaw;
|
||
|
|
f32 roll;
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
union v3s
|
||
|
|
{
|
||
|
|
struct { s32 x, y, z; };
|
||
|
|
struct { s32 r, g, b; };
|
||
|
|
struct { s32 u, v, w_; };
|
||
|
|
struct { s32 E[3]; };
|
||
|
|
|
||
|
|
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
v2s xy;
|
||
|
|
s32 ignored0;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
s32 ignored1;
|
||
|
|
v2s yz;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
v2s uv;
|
||
|
|
s32 ignored2;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
s32 ignored3;
|
||
|
|
v2s vw_;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
s32 pitch;
|
||
|
|
s32 yaw;
|
||
|
|
s32 roll;
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
union v3u
|
||
|
|
{
|
||
|
|
struct { u32 x, y, z; };
|
||
|
|
struct { u32 r, g, b; };
|
||
|
|
struct { u32 u, v, w_; };
|
||
|
|
struct { u32 E[3]; };
|
||
|
|
|
||
|
|
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
v2u xy;
|
||
|
|
u32 ignored0;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
u32 ignored1;
|
||
|
|
v2u yz;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
v2u uv;
|
||
|
|
u32 ignored2;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
u32 ignored3;
|
||
|
|
v2u vw_;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
u32 pitch;
|
||
|
|
u32 yaw;
|
||
|
|
u32 roll;
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
union v4
|
||
|
|
{
|
||
|
|
struct { f32 x, y, z, w; };
|
||
|
|
struct { f32 r, g, b, a; };
|
||
|
|
struct { f32 E[4]; };
|
||
|
|
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
v2 xy;
|
||
|
|
f32 ignored0;
|
||
|
|
f32 ignored1;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
f32 ignored2;
|
||
|
|
v2 yz;
|
||
|
|
f32 ignored3;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
f32 ignored4;
|
||
|
|
f32 ignored5;
|
||
|
|
v2 zw;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
v2 uv;
|
||
|
|
f32 ignored6;
|
||
|
|
f32 ignored7;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
v3 xyz;
|
||
|
|
f32 ignored8;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
v3 rgb;
|
||
|
|
f32 ignored9;
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
union v4s
|
||
|
|
{
|
||
|
|
struct { s32 x, y, z, w; };
|
||
|
|
struct { s32 r, g, b, a; };
|
||
|
|
struct { s32 E[4]; };
|
||
|
|
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
v2s xy;
|
||
|
|
s32 ignored0;
|
||
|
|
s32 ignored1;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
s32 ignored2;
|
||
|
|
v2s yz;
|
||
|
|
s32 ignored3;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
s32 ignored4;
|
||
|
|
s32 ignored5;
|
||
|
|
v2s zw;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
v2s uv;
|
||
|
|
s32 ignored6;
|
||
|
|
s32 ignored7;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
v3s xyz;
|
||
|
|
s32 ignored8;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
v3s rgb;
|
||
|
|
s32 ignored9;
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
union v4u
|
||
|
|
{
|
||
|
|
struct { u32 x, y, z, w; };
|
||
|
|
struct { u32 r, g, b, a; };
|
||
|
|
struct { u32 E[4]; };
|
||
|
|
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
v2u xy;
|
||
|
|
u32 ignored0;
|
||
|
|
u32 ignored1;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
u32 ignored2;
|
||
|
|
v2u yz;
|
||
|
|
u32 ignored3;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
u32 ignored4;
|
||
|
|
u32 ignored5;
|
||
|
|
v2u zw;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
v2u uv;
|
||
|
|
u32 ignored6;
|
||
|
|
u32 ignored7;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
v3u xyz;
|
||
|
|
u32 ignored8;
|
||
|
|
};
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
v3u rgb;
|
||
|
|
u32 ignored9;
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
// Matrix types
|
||
|
|
union m3x3
|
||
|
|
{
|
||
|
|
struct { v3 row[3]; };
|
||
|
|
struct { f32 E[3][3]; };
|
||
|
|
};
|
||
|
|
typedef m3x3 m3;
|
||
|
|
|
||
|
|
union m4x4
|
||
|
|
{
|
||
|
|
struct { v4 row[4]; };
|
||
|
|
struct { f32 E[4][4]; };
|
||
|
|
};
|
||
|
|
typedef m4x4 m4;
|
||
|
|
|
||
|
|
|
||
|
|
static const m3 m3_zero =
|
||
|
|
{
|
||
|
|
0, 0, 0,
|
||
|
|
0, 0, 0,
|
||
|
|
0, 0, 0
|
||
|
|
};
|
||
|
|
static const m3 m3_identity =
|
||
|
|
{
|
||
|
|
1, 0, 0,
|
||
|
|
0, 1, 0,
|
||
|
|
0, 0, 1
|
||
|
|
};
|
||
|
|
static const m4 m4_zero =
|
||
|
|
{
|
||
|
|
0, 0, 0, 0,
|
||
|
|
0, 0, 0, 0,
|
||
|
|
0, 0, 0, 0,
|
||
|
|
0, 0, 0, 0
|
||
|
|
};
|
||
|
|
static const m4 m4_identity =
|
||
|
|
{
|
||
|
|
1, 0, 0, 0,
|
||
|
|
0, 1, 0, 0,
|
||
|
|
0, 0, 1, 0,
|
||
|
|
0, 0, 0, 1
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
// Angles
|
||
|
|
static const f32 PI = 3.141592653589793238462643383;
|
||
|
|
static const f32 TAU = 6.283185307179586476925286766;
|
||
|
|
|
||
|
|
#define radians(x) (x*TAU/360)
|
||
|
|
#define degrees(x) (x*360/TAU)
|
||
|
|
|
||
|
|
|
||
|
|
// Utilities
|
||
|
|
#define square(x) ((x)*(x))
|
||
|
|
#define minimum(a, b) ((a) < (b) ? (a) : (b))
|
||
|
|
#define maximum(a, b) ((a) > (b) ? (a) : (b))
|
||
|
|
|
||
|
|
|
||
|
|
inline f32 clamp(f32 min, f32 max, f32 value)
|
||
|
|
{
|
||
|
|
if(value < min)
|
||
|
|
return min;
|
||
|
|
if(value > max)
|
||
|
|
return max;
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline f32 lerp(f32 start, f32 end, f32 u)
|
||
|
|
{
|
||
|
|
//return (1 - u) * start + u * end;
|
||
|
|
return start + (end - start) * u;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v3 lerp(v3 start, v3 end, f32 u)
|
||
|
|
{
|
||
|
|
f32 x = lerp(start.x, end.x, u);
|
||
|
|
f32 y = lerp(start.y, end.y, u);
|
||
|
|
f32 z = lerp(start.z, end.z, u);
|
||
|
|
return v3{x, y, z};
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v4 lerp(v4 start, v4 end, f32 u)
|
||
|
|
{
|
||
|
|
f32 x = lerp(start.x, end.x, u);
|
||
|
|
f32 y = lerp(start.y, end.y, u);
|
||
|
|
f32 z = lerp(start.z, end.z, u);
|
||
|
|
f32 w = lerp(start.w, end.w, u);
|
||
|
|
return v4{x, y, z, w};
|
||
|
|
}
|
||
|
|
|
||
|
|
inline f32 map(f32 new_start, f32 new_end, f32 old_start, f32 old_end, f32 u)
|
||
|
|
{
|
||
|
|
f32 old_range = old_end - old_start;
|
||
|
|
f32 new_range = new_end - new_start;
|
||
|
|
return (u - old_start) / old_range * new_range + new_start;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
// Conversions
|
||
|
|
inline v2 V2(v2s a)
|
||
|
|
{
|
||
|
|
return {(f32)a.x, (f32)a.y};
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v2 V2(v2u a)
|
||
|
|
{
|
||
|
|
return {(f32)a.x, (f32)a.y};
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v2s V2S(v2 a)
|
||
|
|
{
|
||
|
|
return {(s32)a.x, (s32)a.y};
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v2s V2S(v2u a)
|
||
|
|
{
|
||
|
|
return {(s32)a.x, (s32)a.y};
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v2u V2U(v2 a)
|
||
|
|
{
|
||
|
|
return {(u32)a.x, (u32)a.y};
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v2u V2U(v2s a)
|
||
|
|
{
|
||
|
|
return {(u32)a.x, (u32)a.y};
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v3 V3(v2 a, f32 z)
|
||
|
|
{
|
||
|
|
return {a.x, a.y, z};
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v3 V3(v3s a)
|
||
|
|
{
|
||
|
|
return {(f32)a.x, (f32)a.y, (f32)a.z};
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v3 V3(v3u a)
|
||
|
|
{
|
||
|
|
return {(f32)a.x, (f32)a.y, (f32)a.z};
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v3 V3(f32 e[3])
|
||
|
|
{
|
||
|
|
return v3{e[0], e[1], e[2]};
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v3s V3S(v2s a, s32 z)
|
||
|
|
{
|
||
|
|
return {a.x, a.y, z};
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v3s V3S(v3 a)
|
||
|
|
{
|
||
|
|
return {(s32)a.x, (s32)a.y, (s32)a.z};
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v3s V3S(v3u a)
|
||
|
|
{
|
||
|
|
return {(s32)a.x, (s32)a.y, (s32)a.z};
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v3u V3U(v2u a, u32 z)
|
||
|
|
{
|
||
|
|
return {a.x, a.y, z};
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v3u V3U(v3 a)
|
||
|
|
{
|
||
|
|
return {(u32)a.x, (u32)a.y, (u32)a.z};
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v3u V3U(v3s a)
|
||
|
|
{
|
||
|
|
return {(u32)a.x, (u32)a.y, (u32)a.z};
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v4 V4(v2 a, f32 z, f32 w)
|
||
|
|
{
|
||
|
|
v4 result;
|
||
|
|
|
||
|
|
result.xy = a;
|
||
|
|
result.z = z;
|
||
|
|
result.w = w;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v4 V4(v3 a, f32 w)
|
||
|
|
{
|
||
|
|
v4 result;
|
||
|
|
|
||
|
|
result.xyz = a;
|
||
|
|
result.w = w;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v4 V4(f32 e[4])
|
||
|
|
{
|
||
|
|
return v4{e[0], e[1], e[2], e[3]};
|
||
|
|
}
|
||
|
|
|
||
|
|
inline m3 M3(m4 m)
|
||
|
|
{
|
||
|
|
return m3{ m.row[0].xyz, m.row[1].xyz, m.row[2].xyz };
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
// Operators
|
||
|
|
inline v2 operator+(v2 a)
|
||
|
|
{
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v2 operator-(v2 a)
|
||
|
|
{
|
||
|
|
v2 result = { -a.x, -a.y };
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline bool operator==(v2 a, v2 b)
|
||
|
|
{
|
||
|
|
return a.x == b.x && a.y == b.y;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline bool operator!=(v2 a, v2 b)
|
||
|
|
{
|
||
|
|
return !(a == b);
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v2 operator+(v2 a, v2 b)
|
||
|
|
{
|
||
|
|
v2 result;
|
||
|
|
|
||
|
|
result.x = a.x + b.x;
|
||
|
|
result.y = a.y + b.y;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v2 operator-(v2 a, v2 b)
|
||
|
|
{
|
||
|
|
v2 result;
|
||
|
|
|
||
|
|
result.x = a.x - b.x;
|
||
|
|
result.y = a.y - b.y;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v2 operator*(v2 a, v2 b)
|
||
|
|
{
|
||
|
|
v2 result;
|
||
|
|
|
||
|
|
result.x = a.x * b.x;
|
||
|
|
result.y = a.y * b.y;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v2 operator/(v2 a, v2 b)
|
||
|
|
{
|
||
|
|
v2 result;
|
||
|
|
|
||
|
|
result.x = a.x / b.x;
|
||
|
|
result.y = a.y / b.y;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v2 operator*(v2 a, f32 b)
|
||
|
|
{
|
||
|
|
v2 result;
|
||
|
|
|
||
|
|
result.x = a.x * b;
|
||
|
|
result.y = a.y * b;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v2 operator/(v2 a, f32 b)
|
||
|
|
{
|
||
|
|
v2 result;
|
||
|
|
|
||
|
|
result.x = a.x / b;
|
||
|
|
result.y = a.y / b;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v2 operator*(f32 a, v2 b)
|
||
|
|
{
|
||
|
|
v2 result;
|
||
|
|
|
||
|
|
result.x = a * b.x;
|
||
|
|
result.y = a * b.y;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v2 & operator+=(v2 &a, v2 b)
|
||
|
|
{
|
||
|
|
a = a + b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v2 & operator-=(v2 &a, v2 b)
|
||
|
|
{
|
||
|
|
a = a - b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v2 & operator*=(v2 &a, v2 b)
|
||
|
|
{
|
||
|
|
a = a * b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v2 & operator/=(v2 &a, v2 b)
|
||
|
|
{
|
||
|
|
a = a / b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v2 & operator*=(v2 &a, f32 b)
|
||
|
|
{
|
||
|
|
a = a * b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v2 & operator/=(v2 &a, f32 b)
|
||
|
|
{
|
||
|
|
a = a / b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v2s operator+(v2s a)
|
||
|
|
{
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v2s operator-(v2s a)
|
||
|
|
{
|
||
|
|
v2s result = { -a.x, -a.y };
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline bool operator==(v2s a, v2s b)
|
||
|
|
{
|
||
|
|
return a.x == b.x && a.y == b.y;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline bool operator!=(v2s a, v2s b)
|
||
|
|
{
|
||
|
|
return !(a == b);
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v2s operator+(v2s a, v2s b)
|
||
|
|
{
|
||
|
|
v2s result;
|
||
|
|
|
||
|
|
result.x = a.x + b.x;
|
||
|
|
result.y = a.y + b.y;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v2s operator-(v2s a, v2s b)
|
||
|
|
{
|
||
|
|
v2s result;
|
||
|
|
|
||
|
|
result.x = a.x - b.x;
|
||
|
|
result.y = a.y - b.y;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v2s operator*(v2s a, v2s b)
|
||
|
|
{
|
||
|
|
v2s result;
|
||
|
|
|
||
|
|
result.x = a.x * b.x;
|
||
|
|
result.y = a.y * b.y;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v2s operator/(v2s a, v2s b)
|
||
|
|
{
|
||
|
|
v2s result;
|
||
|
|
|
||
|
|
result.x = a.x / b.x;
|
||
|
|
result.y = a.y / b.y;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v2s operator*(v2s a, f32 b)
|
||
|
|
{
|
||
|
|
v2s result;
|
||
|
|
|
||
|
|
result.x = a.x * b;
|
||
|
|
result.y = a.y * b;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v2s operator/(v2s a, f32 b)
|
||
|
|
{
|
||
|
|
v2s result;
|
||
|
|
|
||
|
|
result.x = a.x / b;
|
||
|
|
result.y = a.y / b;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v2s operator*(f32 a, v2s b)
|
||
|
|
{
|
||
|
|
v2s result;
|
||
|
|
|
||
|
|
result.x = a * b.x;
|
||
|
|
result.y = a * b.y;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v2s & operator+=(v2s &a, v2s b)
|
||
|
|
{
|
||
|
|
a = a + b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v2s & operator-=(v2s &a, v2s b)
|
||
|
|
{
|
||
|
|
a = a - b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v2s & operator*=(v2s &a, v2s b)
|
||
|
|
{
|
||
|
|
a = a * b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v2s & operator/=(v2s &a, v2s b)
|
||
|
|
{
|
||
|
|
a = a / b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v2s & operator*=(v2s &a, f32 b)
|
||
|
|
{
|
||
|
|
a = a * b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v2s & operator/=(v2s &a, f32 b)
|
||
|
|
{
|
||
|
|
a = a / b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v2u operator+(v2u a)
|
||
|
|
{
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v2u operator-(v2u a)
|
||
|
|
{
|
||
|
|
v2u result = { -a.x, -a.y };
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline bool operator==(v2u a, v2u b)
|
||
|
|
{
|
||
|
|
return a.x == b.x && a.y == b.y;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline bool operator!=(v2u a, v2u b)
|
||
|
|
{
|
||
|
|
return !(a == b);
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v2u operator+(v2u a, v2u b)
|
||
|
|
{
|
||
|
|
v2u result;
|
||
|
|
|
||
|
|
result.x = a.x + b.x;
|
||
|
|
result.y = a.y + b.y;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v2u operator-(v2u a, v2u b)
|
||
|
|
{
|
||
|
|
v2u result;
|
||
|
|
|
||
|
|
result.x = a.x - b.x;
|
||
|
|
result.y = a.y - b.y;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v2u operator*(v2u a, v2u b)
|
||
|
|
{
|
||
|
|
v2u result;
|
||
|
|
|
||
|
|
result.x = a.x * b.x;
|
||
|
|
result.y = a.y * b.y;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v2u operator/(v2u a, v2u b)
|
||
|
|
{
|
||
|
|
v2u result;
|
||
|
|
|
||
|
|
result.x = a.x / b.x;
|
||
|
|
result.y = a.y / b.y;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v2u operator*(v2u a, f32 b)
|
||
|
|
{
|
||
|
|
v2u result;
|
||
|
|
|
||
|
|
result.x = a.x * b;
|
||
|
|
result.y = a.y * b;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v2u operator/(v2u a, f32 b)
|
||
|
|
{
|
||
|
|
v2u result;
|
||
|
|
|
||
|
|
result.x = a.x / b;
|
||
|
|
result.y = a.y / b;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v2u operator*(f32 a, v2u b)
|
||
|
|
{
|
||
|
|
v2u result;
|
||
|
|
|
||
|
|
result.x = a * b.x;
|
||
|
|
result.y = a * b.y;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v2u & operator+=(v2u &a, v2u b)
|
||
|
|
{
|
||
|
|
a = a + b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v2u & operator-=(v2u &a, v2u b)
|
||
|
|
{
|
||
|
|
a = a - b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v2u & operator*=(v2u &a, v2u b)
|
||
|
|
{
|
||
|
|
a = a * b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v2u & operator/=(v2u &a, v2u b)
|
||
|
|
{
|
||
|
|
a = a / b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v2u & operator*=(v2u &a, f32 b)
|
||
|
|
{
|
||
|
|
a = a * b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v2u & operator/=(v2u &a, f32 b)
|
||
|
|
{
|
||
|
|
a = a / b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
inline v3 operator+(v3 a)
|
||
|
|
{
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v3 operator-(v3 a)
|
||
|
|
{
|
||
|
|
v3 result = { -a.x, -a.y, -a.z };
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline bool operator==(v3 a, v3 b)
|
||
|
|
{
|
||
|
|
return a.x == b.x && a.y == b.y && a.z == b.z;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline bool operator!=(v3 a, v3 b)
|
||
|
|
{
|
||
|
|
return !(a == b);
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v3 operator+(v3 a, v3 b)
|
||
|
|
{
|
||
|
|
v3 result;
|
||
|
|
|
||
|
|
result.x = a.x + b.x;
|
||
|
|
result.y = a.y + b.y;
|
||
|
|
result.z = a.z + b.z;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v3 operator-(v3 a, v3 b)
|
||
|
|
{
|
||
|
|
v3 result;
|
||
|
|
|
||
|
|
result.x = a.x - b.x;
|
||
|
|
result.y = a.y - b.y;
|
||
|
|
result.z = a.z - b.z;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v3 operator*(v3 a, v3 b)
|
||
|
|
{
|
||
|
|
v3 result;
|
||
|
|
|
||
|
|
result.x = a.x * b.x;
|
||
|
|
result.y = a.y * b.y;
|
||
|
|
result.z = a.z * b.z;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v3 operator/(v3 a, v3 b)
|
||
|
|
{
|
||
|
|
v3 result;
|
||
|
|
|
||
|
|
result.x = a.x / b.x;
|
||
|
|
result.y = a.y / b.y;
|
||
|
|
result.z = a.z / b.z;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v3 operator*(v3 a, f32 b)
|
||
|
|
{
|
||
|
|
v3 result;
|
||
|
|
|
||
|
|
result.x = a.x * b;
|
||
|
|
result.y = a.y * b;
|
||
|
|
result.z = a.z * b;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v3 operator/(v3 a, f32 b)
|
||
|
|
{
|
||
|
|
v3 result;
|
||
|
|
|
||
|
|
result.x = a.x / b;
|
||
|
|
result.y = a.y / b;
|
||
|
|
result.z = a.z / b;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v3 operator*(f32 a, v3 b)
|
||
|
|
{
|
||
|
|
v3 result;
|
||
|
|
|
||
|
|
result.x = a * b.x;
|
||
|
|
result.y = a * b.y;
|
||
|
|
result.z = a * b.z;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v3 & operator+=(v3 &a, v3 b)
|
||
|
|
{
|
||
|
|
a = a + b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v3 & operator-=(v3 &a, v3 b)
|
||
|
|
{
|
||
|
|
a = a - b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v3 & operator*=(v3 &a, v3 b)
|
||
|
|
{
|
||
|
|
a = a * b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v3 & operator/=(v3 &a, v3 b)
|
||
|
|
{
|
||
|
|
a = a / b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v3 & operator*=(v3 &a, f32 b)
|
||
|
|
{
|
||
|
|
a = a * b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v3 & operator/=(v3 &a, f32 b)
|
||
|
|
{
|
||
|
|
a = a / b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
inline v4 operator+(v4 a)
|
||
|
|
{
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v4 operator-(v4 a)
|
||
|
|
{
|
||
|
|
v4 result = { -a.x, -a.y, -a.z, -a.w };
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline bool operator==(v4 a, v4 b)
|
||
|
|
{
|
||
|
|
return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline bool operator!=(v4 a, v4 b)
|
||
|
|
{
|
||
|
|
return !(a == b);
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v4 operator+(v4 a, v4 b)
|
||
|
|
{
|
||
|
|
v4 result;
|
||
|
|
|
||
|
|
result.x = a.x + b.x;
|
||
|
|
result.y = a.y + b.y;
|
||
|
|
result.z = a.z + b.z;
|
||
|
|
result.w = a.w + b.w;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v4 operator-(v4 a, v4 b)
|
||
|
|
{
|
||
|
|
v4 result;
|
||
|
|
|
||
|
|
result.x = a.x - b.x;
|
||
|
|
result.y = a.y - b.y;
|
||
|
|
result.z = a.z - b.z;
|
||
|
|
result.w = a.w - b.w;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v4 operator*(v4 a, v4 b)
|
||
|
|
{
|
||
|
|
v4 result;
|
||
|
|
|
||
|
|
result.x = a.x * b.x;
|
||
|
|
result.y = a.y * b.y;
|
||
|
|
result.z = a.z * b.z;
|
||
|
|
result.w = a.w * b.w;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v4 operator/(v4 a, v4 b)
|
||
|
|
{
|
||
|
|
v4 result;
|
||
|
|
|
||
|
|
result.x = a.x / b.x;
|
||
|
|
result.y = a.y / b.y;
|
||
|
|
result.z = a.z / b.z;
|
||
|
|
result.w = a.w / b.w;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v4 operator*(v4 a, f32 b)
|
||
|
|
{
|
||
|
|
v4 result;
|
||
|
|
|
||
|
|
result.x = a.x * b;
|
||
|
|
result.y = a.y * b;
|
||
|
|
result.z = a.z * b;
|
||
|
|
result.w = a.w * b;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v4 operator/(v4 a, f32 b)
|
||
|
|
{
|
||
|
|
v4 result;
|
||
|
|
|
||
|
|
result.x = a.x / b;
|
||
|
|
result.y = a.y / b;
|
||
|
|
result.z = a.z / b;
|
||
|
|
result.w = a.w / b;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
inline v4 operator*(f32 a, v4 b)
|
||
|
|
{
|
||
|
|
v4 result;
|
||
|
|
|
||
|
|
result.x = a * b.x;
|
||
|
|
result.y = a * b.y;
|
||
|
|
result.z = a * b.z;
|
||
|
|
result.w = a * b.w;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v4 & operator+=(v4 &a, v4 b)
|
||
|
|
{
|
||
|
|
a = a + b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v4 & operator-=(v4 &a, v4 b)
|
||
|
|
{
|
||
|
|
a = a - b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v4 & operator*=(v4 &a, v4 b)
|
||
|
|
{
|
||
|
|
a = a * b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v4 & operator/=(v4 &a, v4 b)
|
||
|
|
{
|
||
|
|
a = a / b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v4 & operator*=(v4 &a, f32 b)
|
||
|
|
{
|
||
|
|
a = a * b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
inline v4 & operator/=(v4 &a, f32 b)
|
||
|
|
{
|
||
|
|
a = a / b;
|
||
|
|
return a;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
// Vector functions
|
||
|
|
inline f32 length(v2 a)
|
||
|
|
{
|
||
|
|
return sqrt(square(a.x) + square(a.y));
|
||
|
|
}
|
||
|
|
|
||
|
|
inline f32 length(v3 a)
|
||
|
|
{
|
||
|
|
return sqrt(square(a.x) + square(a.y) + square(a.z));
|
||
|
|
}
|
||
|
|
|
||
|
|
inline f32 length(v4 a)
|
||
|
|
{
|
||
|
|
return sqrt(square(a.x) + square(a.y) + square(a.z) + square(a.w));
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
inline f32 distance(v2 a, v2 b)
|
||
|
|
{
|
||
|
|
return length(a - b);
|
||
|
|
}
|
||
|
|
|
||
|
|
inline f32 distance(v3 a, v3 b)
|
||
|
|
{
|
||
|
|
return length(a - b);
|
||
|
|
}
|
||
|
|
|
||
|
|
inline f32 distance(v4 a, v4 b)
|
||
|
|
{
|
||
|
|
return length(a - b);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
inline f32 dot(v2 a, v2 b)
|
||
|
|
{
|
||
|
|
return a.x*b.x + a.y*b.y;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline f32 dot(v3 a, v3 b)
|
||
|
|
{
|
||
|
|
return a.x*b.x + a.y*b.y + a.z*b.z;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline f32 dot(v4 a, v4 b)
|
||
|
|
{
|
||
|
|
return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v3 cross(v3 a, v3 b)
|
||
|
|
{
|
||
|
|
v3 result;
|
||
|
|
|
||
|
|
result.x = a.y*b.z - a.z*b.y;
|
||
|
|
result.y = a.z*b.x - a.x*b.z;
|
||
|
|
result.z = a.x*b.y - a.y*b.x;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
inline v2 normalize(v2 a)
|
||
|
|
{
|
||
|
|
return a / length(a);
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v3 normalize(v3 a)
|
||
|
|
{
|
||
|
|
return a / length(a);
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v4 normalize(v4 a)
|
||
|
|
{
|
||
|
|
return a / length(a);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
// Matrix operators
|
||
|
|
inline v3 extract_column(m3 m, u8 column_index)
|
||
|
|
{
|
||
|
|
v3 result;
|
||
|
|
|
||
|
|
result.x = m.E[0][column_index];
|
||
|
|
result.y = m.E[1][column_index];
|
||
|
|
result.z = m.E[2][column_index];
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v4 extract_column(m4 m, u8 column_index)
|
||
|
|
{
|
||
|
|
v4 result;
|
||
|
|
|
||
|
|
result.x = m.E[0][column_index];
|
||
|
|
result.y = m.E[1][column_index];
|
||
|
|
result.z = m.E[2][column_index];
|
||
|
|
result.w = m.E[3][column_index];
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v3 operator*(m3 m, v3 v)
|
||
|
|
{
|
||
|
|
v3 result;
|
||
|
|
|
||
|
|
result.x = dot(m.row[0], v);
|
||
|
|
result.y = dot(m.row[1], v);
|
||
|
|
result.z = dot(m.row[2], v);
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline m3 operator*(m3 a, m3 b)
|
||
|
|
{
|
||
|
|
m3 result;
|
||
|
|
|
||
|
|
v3 c0 = extract_column(b, 0);
|
||
|
|
v3 c1 = extract_column(b, 1);
|
||
|
|
v3 c2 = extract_column(b, 2);
|
||
|
|
|
||
|
|
result.E[0][0] = dot(a.row[0], c0);
|
||
|
|
result.E[0][1] = dot(a.row[0], c1);
|
||
|
|
result.E[0][2] = dot(a.row[0], c2);
|
||
|
|
|
||
|
|
result.E[1][0] = dot(a.row[1], c0);
|
||
|
|
result.E[1][1] = dot(a.row[1], c1);
|
||
|
|
result.E[1][2] = dot(a.row[1], c2);
|
||
|
|
|
||
|
|
result.E[2][0] = dot(a.row[2], c0);
|
||
|
|
result.E[2][1] = dot(a.row[2], c1);
|
||
|
|
result.E[2][2] = dot(a.row[2], c2);
|
||
|
|
|
||
|
|
result.E[3][0] = dot(a.row[3], c0);
|
||
|
|
result.E[3][1] = dot(a.row[3], c1);
|
||
|
|
result.E[3][2] = dot(a.row[3], c2);
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline v4 operator*(m4 m, v4 v)
|
||
|
|
{
|
||
|
|
v4 result;
|
||
|
|
|
||
|
|
result.x = dot(m.row[0], v);
|
||
|
|
result.y = dot(m.row[1], v);
|
||
|
|
result.z = dot(m.row[2], v);
|
||
|
|
result.w = dot(m.row[3], v);
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline m4 operator*(m4 a, m4 b)
|
||
|
|
{
|
||
|
|
m4 result;
|
||
|
|
|
||
|
|
v4 c0 = extract_column(b, 0);
|
||
|
|
v4 c1 = extract_column(b, 1);
|
||
|
|
v4 c2 = extract_column(b, 2);
|
||
|
|
v4 c3 = extract_column(b, 3);
|
||
|
|
|
||
|
|
result.E[0][0] = dot(a.row[0], c0);
|
||
|
|
result.E[0][1] = dot(a.row[0], c1);
|
||
|
|
result.E[0][2] = dot(a.row[0], c2);
|
||
|
|
result.E[0][3] = dot(a.row[0], c3);
|
||
|
|
|
||
|
|
result.E[1][0] = dot(a.row[1], c0);
|
||
|
|
result.E[1][1] = dot(a.row[1], c1);
|
||
|
|
result.E[1][2] = dot(a.row[1], c2);
|
||
|
|
result.E[1][3] = dot(a.row[1], c3);
|
||
|
|
|
||
|
|
result.E[2][0] = dot(a.row[2], c0);
|
||
|
|
result.E[2][1] = dot(a.row[2], c1);
|
||
|
|
result.E[2][2] = dot(a.row[2], c2);
|
||
|
|
result.E[2][3] = dot(a.row[2], c3);
|
||
|
|
|
||
|
|
result.E[3][0] = dot(a.row[3], c0);
|
||
|
|
result.E[3][1] = dot(a.row[3], c1);
|
||
|
|
result.E[3][2] = dot(a.row[3], c2);
|
||
|
|
result.E[3][3] = dot(a.row[3], c3);
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
// Matrix functions
|
||
|
|
inline m3 m3_make_diagonal_matrix(f32 value)
|
||
|
|
{
|
||
|
|
m3 result = m3_zero;
|
||
|
|
result.E[0][0] = value;
|
||
|
|
result.E[1][1] = value;
|
||
|
|
result.E[2][2] = value;
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline m4 m4_make_diagonal_matrix(f32 value)
|
||
|
|
{
|
||
|
|
m4 result = m4_zero;
|
||
|
|
result.E[0][0] = value;
|
||
|
|
result.E[1][1] = value;
|
||
|
|
result.E[2][2] = value;
|
||
|
|
result.E[3][3] = value;
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline f32 determinant_of_minor(m3 m, int skip_r, int skip_c)
|
||
|
|
{
|
||
|
|
f32 minor[2][2];
|
||
|
|
for(int r = 0, source_r = 0; r < 2; r++, source_r++)
|
||
|
|
{
|
||
|
|
if(source_r == skip_r)
|
||
|
|
source_r++;
|
||
|
|
for(int c = 0, source_c = 0; c < 2; c++, source_c++)
|
||
|
|
{
|
||
|
|
if(source_c == skip_c)
|
||
|
|
source_c++;
|
||
|
|
minor[r][c] = m.E[source_r][source_c];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return minor[0][0] * minor[1][1] - minor[0][1] * minor[1][0];
|
||
|
|
}
|
||
|
|
|
||
|
|
inline f32 determinant(m3 m)
|
||
|
|
{
|
||
|
|
return
|
||
|
|
+ m.E[0][0] * m.E[1][1] * m.E[2][2]
|
||
|
|
+ m.E[0][1] * m.E[1][2] * m.E[2][0]
|
||
|
|
+ m.E[0][2] * m.E[1][0] * m.E[2][1]
|
||
|
|
- m.E[0][2] * m.E[1][1] * m.E[2][0]
|
||
|
|
- m.E[0][1] * m.E[1][0] * m.E[2][2]
|
||
|
|
- m.E[0][0] * m.E[1][2] * m.E[2][1];
|
||
|
|
}
|
||
|
|
|
||
|
|
inline m3 transpose(m3 m)
|
||
|
|
{
|
||
|
|
m3 result;
|
||
|
|
|
||
|
|
result.E[0][0] = m.E[0][0];
|
||
|
|
result.E[0][1] = m.E[1][0];
|
||
|
|
result.E[0][2] = m.E[2][0];
|
||
|
|
|
||
|
|
result.E[1][0] = m.E[0][1];
|
||
|
|
result.E[1][1] = m.E[1][1];
|
||
|
|
result.E[1][2] = m.E[2][1];
|
||
|
|
|
||
|
|
result.E[2][0] = m.E[0][2];
|
||
|
|
result.E[2][1] = m.E[1][2];
|
||
|
|
result.E[2][2] = m.E[2][2];
|
||
|
|
|
||
|
|
result.E[3][0] = m.E[0][3];
|
||
|
|
result.E[3][1] = m.E[1][3];
|
||
|
|
result.E[3][2] = m.E[2][3];
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline m3 inverse(m3 m)
|
||
|
|
{
|
||
|
|
m3 result;
|
||
|
|
|
||
|
|
f32 one_over_det = 1.0 / determinant(m);
|
||
|
|
f32 sign = 1;
|
||
|
|
for(int r = 0; r < 3; r++)
|
||
|
|
{
|
||
|
|
for(int c = 0; c < 3; c++)
|
||
|
|
{
|
||
|
|
result.E[c][r] = sign * determinant_of_minor(m, r, c) * one_over_det;
|
||
|
|
sign = -sign;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline f32 determinant_of_minor(m4 m, int skip_r, int skip_c)
|
||
|
|
{
|
||
|
|
m3 minor;
|
||
|
|
for(int r = 0, source_r = 0; r < 3; r++, source_r++)
|
||
|
|
{
|
||
|
|
if(source_r == skip_r)
|
||
|
|
source_r++;
|
||
|
|
for(int c = 0, source_c = 0; c < 3; c++, source_c++)
|
||
|
|
{
|
||
|
|
if(source_c == skip_c)
|
||
|
|
source_c++;
|
||
|
|
minor.E[r][c] = m.E[source_r][source_c];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return determinant(minor);
|
||
|
|
}
|
||
|
|
|
||
|
|
inline f32 determinant(m4 m)
|
||
|
|
{
|
||
|
|
f32 result = 0;
|
||
|
|
f32 sign = 1;
|
||
|
|
int r = 0;
|
||
|
|
// Laplace theorem
|
||
|
|
for(int c = 0; c < 4; c++)
|
||
|
|
{
|
||
|
|
result += m.E[r][c] * sign * determinant_of_minor(m, r, c);
|
||
|
|
sign = -sign;
|
||
|
|
}
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline m4 transpose(m4 m)
|
||
|
|
{
|
||
|
|
m4 result;
|
||
|
|
|
||
|
|
result.E[0][0] = m.E[0][0];
|
||
|
|
result.E[0][1] = m.E[1][0];
|
||
|
|
result.E[0][2] = m.E[2][0];
|
||
|
|
result.E[0][3] = m.E[3][0];
|
||
|
|
|
||
|
|
result.E[1][0] = m.E[0][1];
|
||
|
|
result.E[1][1] = m.E[1][1];
|
||
|
|
result.E[1][2] = m.E[2][1];
|
||
|
|
result.E[1][3] = m.E[3][1];
|
||
|
|
|
||
|
|
result.E[2][0] = m.E[0][2];
|
||
|
|
result.E[2][1] = m.E[1][2];
|
||
|
|
result.E[2][2] = m.E[2][2];
|
||
|
|
result.E[2][3] = m.E[3][2];
|
||
|
|
|
||
|
|
result.E[3][0] = m.E[0][3];
|
||
|
|
result.E[3][1] = m.E[1][3];
|
||
|
|
result.E[3][2] = m.E[2][3];
|
||
|
|
result.E[3][3] = m.E[3][3];
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline m4 inverse(m4 m)
|
||
|
|
{
|
||
|
|
m4 result;
|
||
|
|
|
||
|
|
f32 one_over_det = 1.0 / determinant(m);
|
||
|
|
f32 sign_a = 1;
|
||
|
|
for(int r = 0; r < 4; r++)
|
||
|
|
{
|
||
|
|
f32 sign_b = sign_a;
|
||
|
|
for(int c = 0; c < 4; c++)
|
||
|
|
{
|
||
|
|
result.E[c][r] = sign_b * determinant_of_minor(m, r, c) * one_over_det;
|
||
|
|
sign_b = -sign_b;
|
||
|
|
}
|
||
|
|
sign_a = -sign_a;
|
||
|
|
}
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif
|