fixed camera (using cglm for maths)

This commit is contained in:
matthew 2025-08-03 14:33:37 +10:00
parent 3d8e0b2840
commit 09b57ae114
3 changed files with 1430 additions and 325 deletions

View File

@ -161,7 +161,7 @@ Cycle(Game* g)
projection[1, 1] *= -1.0;
g.globals.projection_matrix = projection;
g.globals.view_matrix = Mat4Identity(); //g.camera.view;
g.globals.view_matrix = g.camera.view;
g.globals.res.x = ext.x;
g.globals.res.y = ext.y;
SetUniform(&g.rd, &g.globals);
@ -219,6 +219,7 @@ struct Camera
{
Mat4 view = Mat4Identity();
Vec3 pos = Vec3(0.0, 0.0, 2.0);
Vec3 velocity = Vec3(0.0);
Vec3 front = Vec3(0.0, 0.0, -1.0);
Vec3 up = Vec3(0.0, 1.0, 0.0);
Vec3 right = Vec3(0.0);
@ -231,50 +232,21 @@ struct Camera
pragma(inline): void
HandleInputs(Camera* cam, Inputs* inputs)
{
f32 velocity = cam.speed * g_DELTA;
Logf("pos %s pitch %s yaw %s", cam.pos.v, cam.pitch, cam.yaw);
foreach(i; 0 .. inputs.count)
{
InputEvent event = inputs.events[i];
switch(event.key)
{
case Input.W:
{
if (!event.pressed) continue;
cam.pos += cam.front * velocity;
} break;
case Input.S:
{
if (!event.pressed) continue;
cam.pos -= cam.front * velocity;
} break;
case Input.A:
{
if (!event.pressed) continue;
cam.pos -= cam.right * velocity;
} break;
case Input.D:
{
if (!event.pressed) continue;
cam.pos += cam.right * velocity;
} break;
case Input.Space:
{
if (!event.pressed) continue;
cam.pos += cam.up * velocity;
} break;
case Input.LeftCtrl:
{
if (!event.pressed) continue;
cam.pos -= cam.up * velocity;
} break;
case Input.W: cam.velocity.z = event.pressed ? -1.0 : 0.0; break;
case Input.S: cam.velocity.z = event.pressed ? 1.0 : 0.0; break;
case Input.A: cam.velocity.x = event.pressed ? -1.0 : 0.0; break;
case Input.D: cam.velocity.x = event.pressed ? 1.0 : 0.0; break;
case Input.Space: cam.velocity.y = event.pressed ? 1.0 : 0.0; break;
case Input.LeftCtrl: cam.velocity.y = event.pressed ? -1.0 : 0.0; break;
case Input.MouseMotion:
{
Logf("Mouse Motion");
// (0, 0) top left
cam.yaw += cast(f32)(event.rel_x) / 20.0;
cam.yaw -= cast(f32)(event.rel_x) / 20.0;
cam.pitch += cast(f32)(event.rel_y) / 20.0;
if (cam.pitch > 90.0)
@ -296,6 +268,8 @@ Update(Camera* cam)
{
Vec3 front = Vec3(0.0);
cam.pos += cam.velocity * g_DELTA;
front.x = cosf(Radians(cam.yaw)) * cosf(Radians(cam.pitch));
front.y = sinf(Radians(cam.pitch));
front.z = sinf(Radians(cam.yaw)) * cosf(Radians(cam.pitch));

View File

@ -1,4 +1,5 @@
import aliases;
import includes;
import util;
import std.math;
import std.math.algebraic;
@ -19,10 +20,6 @@ f32 Radians(f32 deg)
return deg * (PI / 180.0);
}
// TODO: Clean this mess up
enum IsVector(T) = is(T : Vector!U, U...);
struct Vector(T, int N)
{
static assert(N > 0 && N <= 4);
@ -58,8 +55,6 @@ struct Vector(T, int N)
}
}
nothrow @nogc:
this(Vec3, f32)(Vec3 v3, f32 f) if (N == 4 && is(T: f32))
{
x = v3.x;
@ -91,36 +86,18 @@ struct Vector(T, int N)
}
}
ref Vector opAssign(U)(U x) if (isAssignable!(T, U))
ref Vector opAssign(U)(U x) if (is(U: T))
{
mixin(GenerateLoop!("v[@] = x;", N)());
return this;
}
ref Vector opAssign(U)(U arr) if (isStaticArray!(U) && isAssignable!(T, typeof(arr[0])) && arr.length == N)
{
mixin(GenerateLoop!("v[@] = arr[@];", N)());
return this;
}
ref Vector opAssign(U)(U arr) if (isDynamicArray!(U) && isAssignable!(T, typeof(arr[0])))
{
mixin(GenerateLoop!("v[@] = arr[@];", N)());
return this;
}
ref Vector opAssign(U)(U u) if (is(U : Vector))
{
v[] = u.v[];
return this;
}
ref Vector opAssign(U)(U x) if (IsVector!(U) && isAssignable!(T, U._T) && (!is(U: Vector)) && (U._N == _N))
{
mixin(GenerateLoop!("v[@] = x.v[@];", N)());
return this;
}
inout(T)* ptr() inout @property
{
return v.ptr;
@ -201,7 +178,7 @@ struct Vector(T, int N)
f32* r = &operand.x;
f32* res = &result.x;
asm @nogc nothrow
asm
{
mov R8, l;
mov R9, r;
@ -209,11 +186,11 @@ struct Vector(T, int N)
movups XMM0, x.offsetof[R8];
movups XMM1, operand.x.offsetof[R9];
}
static if (op == "*") asm @nogc nothrow { mulps XMM0, XMM1; }
else static if (op == "-") asm @nogc nothrow { subps XMM0, XMM1; }
else static if (op == "+") asm @nogc nothrow { addps XMM0, XMM1; }
else static if (op == "/") asm @nogc nothrow { divps XMM0, XMM1; }
asm @nogc nothrow
static if (op == "*") asm { mulps XMM0, XMM1; }
else static if (op == "-") asm { subps XMM0, XMM1; }
else static if (op == "+") asm { addps XMM0, XMM1; }
else static if (op == "/") asm { divps XMM0, XMM1; }
asm
{
movups result.x.offsetof[R10], XMM0;
}
@ -229,7 +206,7 @@ struct Vector(T, int N)
f32* r = &other.x;
f32* res = &result.x;
asm @nogc nothrow
asm
{
mov R8, l;
mov R9, r;
@ -237,11 +214,11 @@ struct Vector(T, int N)
movups XMM0, x.offsetof[R8];
movups XMM1, other.x.offsetof[R9];
}
static if (op == "*") asm @nogc nothrow { mulps XMM0, XMM1; }
else static if (op == "-") asm @nogc nothrow { subps XMM0, XMM1; }
else static if (op == "+") asm @nogc nothrow { addps XMM0, XMM1; }
else static if (op == "/") asm @nogc nothrow { divps XMM0, XMM1; }
asm @nogc nothrow
static if (op == "*") asm { mulps XMM0, XMM1; }
else static if (op == "-") asm { subps XMM0, XMM1; }
else static if (op == "+") asm { addps XMM0, XMM1; }
else static if (op == "/") asm { divps XMM0, XMM1; }
asm
{
movups result.x.offsetof[R8], XMM0;
}
@ -378,7 +355,8 @@ struct Vector(T, int N)
}
}
struct Matrix(T, int D)
// TODO: fix alignment for non mat4s
align(16) struct Matrix(T, int D)
{
static assert(D > 0 && D <= 4);
@ -394,9 +372,12 @@ struct Matrix(T, int D)
T[N] v;
Row[D] rows;
MatrixVec[D] vec;
static if (D == 4) mat4 glm_mat;
static if (D == 3) mat3 glm_mat;
static if (D == 2) mat2 glm_mat;
}
// TODO: setup @nogc nothrow
// TODO: setup
this(U...)(U values)
{
@ -505,44 +486,8 @@ struct Matrix(T, int D)
{
Vec4 opBinary(string op, U)(U x) if (is(U: Vec4) && is(T: f32) && (op == "*"))
{
Vec4 result;
auto res = &result;
auto m = &this;
auto v = &x;
asm @trusted @nogc nothrow
{
mov R8, m;
mov R9, v;
mov R10, res;
movups XMM0, vec.offsetof[R8]+00;
movups XMM1, vec.offsetof[R8]+16;
movups XMM2, vec.offsetof[R8]+32;
movups XMM3, vec.offsetof[R8]+48;
movups XMM4, x.x.offsetof[R9];
movups XMM5, XMM4;
shufps XMM5, XMM5, 0;
movups XMM6, XMM4;
shufps XMM6, XMM6, 85;
movups XMM7, XMM4;
shufps XMM7, XMM7, 170;
movups XMM8, XMM4;
shufps XMM8, XMM8, 255;
mulps XMM3, XMM8;
mulps XMM2, XMM7;
addps XMM3, XMM2;
mulps XMM1, XMM6;
addps XMM3, XMM1;
mulps XMM0, XMM5;
addps XMM3, XMM0;
movups result.x.offsetof[R10], XMM3;
}
Vec4 result = 0.0;
glm_mat4_mulv(glm_mat.ptr, x.v.ptr, result.v.ptr);
return result;
}
@ -551,35 +496,7 @@ struct Matrix(T, int D)
Matrix result;
MatZero(&result);
Row[D] m1 = rows;
Row[D] m2 = x.rows;
f32 a00 = m1[0][0], a01 = m1[0][1], a02 = m1[0][2], a03 = m1[0][3],
a10 = m1[1][0], a11 = m1[1][1], a12 = m1[1][2], a13 = m1[1][3],
a20 = m1[2][0], a21 = m1[2][1], a22 = m1[2][2], a23 = m1[2][3],
a30 = m1[3][0], a31 = m1[3][1], a32 = m1[3][2], a33 = m1[3][3],
b00 = m2[0][0], b01 = m2[0][1], b02 = m2[0][2], b03 = m2[0][3],
b10 = m2[1][0], b11 = m2[1][1], b12 = m2[1][2], b13 = m2[1][3],
b20 = m2[2][0], b21 = m2[2][1], b22 = m2[2][2], b23 = m2[2][3],
b30 = m2[3][0], b31 = m2[3][1], b32 = m2[3][2], b33 = m2[3][3];
result[0, 0] = a00 * b00 + a10 * b01 + a20 * b02 + a30 * b03;
result[0, 1] = a01 * b00 + a11 * b01 + a21 * b02 + a31 * b03;
result[0, 2] = a02 * b00 + a12 * b01 + a22 * b02 + a32 * b03;
result[0, 3] = a03 * b00 + a13 * b01 + a23 * b02 + a33 * b03;
result[1, 0] = a00 * b10 + a10 * b11 + a20 * b12 + a30 * b13;
result[1, 1] = a01 * b10 + a11 * b11 + a21 * b12 + a31 * b13;
result[1, 2] = a02 * b10 + a12 * b11 + a22 * b12 + a32 * b13;
result[1, 3] = a03 * b10 + a13 * b11 + a23 * b12 + a33 * b13;
result[2, 0] = a00 * b20 + a10 * b21 + a20 * b22 + a30 * b23;
result[2, 1] = a01 * b20 + a11 * b21 + a21 * b22 + a31 * b23;
result[2, 2] = a02 * b20 + a12 * b21 + a22 * b22 + a32 * b23;
result[2, 3] = a03 * b20 + a13 * b21 + a23 * b22 + a33 * b23;
result[3, 0] = a00 * b30 + a10 * b31 + a20 * b32 + a30 * b33;
result[3, 1] = a01 * b30 + a11 * b31 + a21 * b32 + a31 * b33;
result[3, 2] = a02 * b30 + a12 * b31 + a22 * b32 + a32 * b33;
result[3, 3] = a03 * b30 + a13 * b31 + a23 * b32 + a33 * b33;
glm_mat4_mul(glm_mat.ptr, x.glm_mat.ptr, result.glm_mat.ptr);
return result;
}
@ -600,8 +517,6 @@ struct Matrix(T, int D)
struct Quat
{
@nogc nothrow:
union
{
f32[4] v;
@ -685,7 +600,7 @@ Mat4MulASM(Mat4 l, Mat4 r)
auto res = &result;
// TODO: fix this
asm @trusted @nogc nothrow
asm @trusted
{
mov R8, lp;
mov R9, rp;
@ -788,7 +703,7 @@ Mat4MulASM(Mat4 l, Mat4 r)
return result;
}
nothrow @nogc pragma(inline): Mat4
pragma(inline): Mat4
Mat4Identity()
{
return Mat4(
@ -810,7 +725,7 @@ Mat4Identity(Mat4* mat)
(*mat)[3, 3] = 1.0;
}
nothrow @nogc pragma(inline): Mat3
pragma(inline): Mat3
Mat3Identity()
{
return Mat3(
@ -820,7 +735,7 @@ Mat3Identity()
);
}
nothrow @nogc pragma(inline): Mat2
pragma(inline): Mat2
Mat2Identity()
{
return Mat2(
@ -918,19 +833,10 @@ Normalize(Quat q)
pragma(inline): Mat4
Perspective(f32 fov, f32 aspect, f32 near, f32 far)
{
Mat4 mat;
MatZero(&mat);
f32 f = 1.0 / tanf(fov * 0.5);
f32 fn = 1.0 / (near - far);
mat[0, 0] = f / aspect;
mat[1, 1] = f;
mat[2, 2] = far * fn;
mat[2, 3] = -1.0;
mat[3, 2] = near * far * fn;
return mat;
Mat4 res;
MatZero(&res);
glm_perspective(fov, aspect, near, far, res.glm_mat.ptr);
return res;
}
pragma(inline): Vec3
@ -954,18 +860,10 @@ Rotate(Quat q, Vec3 vec)
pragma(inline): Mat4
LookAt(Vec3 eye, Vec3 center, Vec3 up)
{
Vec3 f = Normalize(center - eye);
Vec3 s = CrossN(f, up);
Vec3 u = Cross(s, f);
Mat4 mat;
return Mat4(
+s.x, +s.y, +s.z, -Dot(&s, &eye),
+u.x, +u.y, +u.z, -Dot(&u, &eye),
-f.x, -f.y, -f.z, -Dot(&f, &eye),
0.0, 0.0, 0.0, 1.0,
);
Mat4 result;
MatZero(&result);
glm_lookat(eye.v.ptr, center.v.ptr, up.v.ptr, result.glm_mat.ptr);
return result;
}
pragma(inline): Mat4
@ -995,22 +893,20 @@ pragma(inline): void
CrossN(Vec3 a, Vec3 b, Vec3* dst)
{
Cross(a, b, dst);
Normalize(dst);
glm_vec3_normalize(dst.v.ptr);
}
pragma(inline): void
Cross(Vec3 a, Vec3 b, Vec3* dst)
{
dst.x = a.y * b.z - a.z * b.y;
dst.y = a.z * b.x - a.x * b.z;
dst.z = a.x * b.y - a.y * b.x;
glm_vec3_cross(a.v.ptr, b.v.ptr, dst.v.ptr);
}
pragma(inline): void
MatZero(Mat4* mat)
{
auto v = &mat.vec;
asm @nogc nothrow
asm
{
mov R8, v;
xorps XMM0, XMM0;
@ -1024,114 +920,15 @@ MatZero(Mat4* mat)
pragma(inline): void
Translate(Mat4* mat, Vec3 vec)
{
Mat4Identity(mat);
(*mat)[3, 0] = vec[0];
(*mat)[3, 1] = vec[1];
(*mat)[3, 2] = vec[2];
}
pragma(inline): void
Rotate(Mat4* mat, f32 angle, Vec3 axis)
{
Mat4 rot = Rotate(angle, axis);
MultiplyRotate(mat, &rot, mat);
}
pragma(inline): void
MultiplyRotate(Mat4* m1, Mat4* m2, Mat4* dst)
{
f32 a00 = (*m1)[0, 0], a01 = (*m1)[0, 1], a02 = (*m1)[0, 2], a03 = (*m1)[0, 3],
a10 = (*m1)[1, 0], a11 = (*m1)[1, 1], a12 = (*m1)[1, 2], a13 = (*m1)[1, 3],
a20 = (*m1)[2, 0], a21 = (*m1)[2, 1], a22 = (*m1)[2, 2], a23 = (*m1)[2, 3],
a30 = (*m1)[3, 0], a31 = (*m1)[3, 1], a32 = (*m1)[3, 2], a33 = (*m1)[3, 3],
b00 = (*m2)[0, 0], b01 = (*m2)[0, 1], b02 = (*m2)[0, 2],
b10 = (*m2)[1, 0], b11 = (*m2)[1, 1], b12 = (*m2)[1, 2],
b20 = (*m2)[2, 0], b21 = (*m2)[2, 1], b22 = (*m2)[2, 2];
(*dst)[0, 0] = a00 * b00 + a10 * b01 + a20 * b02;
(*dst)[0, 1] = a01 * b00 + a11 * b01 + a21 * b02;
(*dst)[0, 2] = a02 * b00 + a12 * b01 + a22 * b02;
(*dst)[0, 3] = a03 * b00 + a13 * b01 + a23 * b02;
(*dst)[1, 0] = a00 * b10 + a10 * b11 + a20 * b12;
(*dst)[1, 1] = a01 * b10 + a11 * b11 + a21 * b12;
(*dst)[1, 2] = a02 * b10 + a12 * b11 + a22 * b12;
(*dst)[1, 3] = a03 * b10 + a13 * b11 + a23 * b12;
(*dst)[2, 0] = a00 * b20 + a10 * b21 + a20 * b22;
(*dst)[2, 1] = a01 * b20 + a11 * b21 + a21 * b22;
(*dst)[2, 2] = a02 * b20 + a12 * b21 + a22 * b22;
(*dst)[2, 3] = a03 * b20 + a13 * b21 + a23 * b22;
(*dst)[3, 0] = a30;
(*dst)[3, 1] = a31;
(*dst)[3, 2] = a32;
(*dst)[3, 3] = a33;
}
pragma(inline): Mat4
Rotate(f32 angle, Vec3 axis)
{
f32 c = cosf(angle);
Vec3 axis_normal = Normalize(axis);
Vec3 v = axis_normal * (1.0 - c);
Vec3 vs = axis_normal * sinf(angle);
Mat4 mat;
mat.vec[0].xyz = axis_normal * v.x;
mat.vec[1].xyz = axis_normal * v.y;
mat.vec[2].xyz = axis_normal * v.z;
mat[0, 0] += c; mat[1, 0] -= vs.z; mat[2, 0] += vs.y;
mat[0, 1] += vs.z; mat[1, 1] += c; mat[2, 1] -= vs.x;
mat[0, 2] -= vs.y; mat[1, 2] += vs.x; mat[2, 2] += c;
mat[0, 3] = mat[1, 3] = mat[3, 0] = mat[3, 2] = 0.0;
mat[3, 3] = 1.0;
return mat;
glm_translate(mat.glm_mat.ptr, vec.v.ptr);
}
pragma(inline): Mat4
Inverse(Mat4 mat)
{
// TODO: SIMD this
f32 a = mat[0, 0], b = mat[0, 1], c = mat[0, 2], d = mat[0, 3],
e = mat[1, 0], f = mat[1, 1], g = mat[1, 2], h = mat[1, 3],
i = mat[2, 0], j = mat[2, 1], k = mat[2, 2], l = mat[2, 3],
m = mat[3, 0], n = mat[3, 1], o = mat[3, 2], p = mat[3, 3];
f32 c1 = k * p - l * o, c2 = c * h - d * g, c3 = i * p - l * m,
c4 = a * h - d * e, c5 = j * p - l * n, c6 = b * h - d * f,
c7 = i * n - j * m, c8 = a * f - b * e, c9 = j * o - k * n,
c10 = b * g - c * f, c11 = i * o - k * m, c12 = a * g - c * e;
f32 idt = 1.0/(c8*c1+c4*c9+c10*c3+c2*c7-c12*c5-c6*c11), ndt = -idt;
Mat4 res;
res[0, 0] = (f * c1 - g * c5 + h * c9) * idt;
res[0, 1] = (b * c1 - c * c5 + d * c9) * ndt;
res[0, 2] = (n * c2 - o * c6 + p * c10) * idt;
res[0, 3] = (j * c2 - k * c6 + l * c10) * ndt;
res[1, 0] = (e * c1 - g * c3 + h * c11) * ndt;
res[1, 1] = (a * c1 - c * c3 + d * c11) * idt;
res[1, 2] = (m * c2 - o * c4 + p * c12) * ndt;
res[1, 3] = (i * c2 - k * c4 + l * c12) * idt;
res[2, 0] = (e * c5 - f * c3 + h * c7) * idt;
res[2, 1] = (a * c5 - b * c3 + d * c7) * ndt;
res[2, 2] = (m * c6 - n * c4 + p * c8) * idt;
res[2, 3] = (i * c6 - j * c4 + l * c8) * ndt;
res[3, 0] = (e * c9 - f * c11 + g * c7) * ndt;
res[3, 1] = (a * c9 - b * c11 + c * c7) * idt;
res[3, 2] = (m * c10 - n * c12 + o * c8) * ndt;
res[3, 3] = (i * c10 - j * c12 + k * c8) * idt;
MatZero(&res);
glm_mat4_inv(mat.glm_mat.ptr, res.glm_mat.ptr);
return res;
}
@ -1154,20 +951,6 @@ Remap(f32 v, f32 in_min, f32 in_max, f32 out_min, f32 out_max)
return Mix(out_min, out_max, t);
}
pragma(inline): T
SquaredMagnitude(T)(T v) if (IsVector!(T))
{
T sum_squares = 0;
mixin(GenerateLoop!("sum_squares += v.v[@] * v.v[@];", v._N)());
return sum_squares;
}
pragma(inline): T
SquaredDistTo(T)(T l, T r) if (IsVector!(T))
{
return SquaredMagnitude(r - l);
}
unittest
{
enum FLOAT_MAX = f32.max;
@ -1199,19 +982,6 @@ unittest
return cast(f32)(rand())/cast(f32)(RAND_MAX + 1.0);
}
Mat4 RandomMat4()
{
Mat4 mat;
Mat4Identity(&mat);
mat[3, 0] = RandomFloat();
mat[3, 1] = RandomFloat();
mat[3, 2] = RandomFloat();
Rotate(&mat, RandomFloat(), Vec3(RandomFloat(), RandomFloat(), RandomFloat()));
return mat;
}
{ // Vec2 arithmetic
Vec2 v1 = Vec2(5.0, 10.0);
Vec2 v2 = Vec2(2.5, 5.0);
@ -1358,21 +1128,4 @@ unittest
assert(v3 == v4, "Vec3 CrossN failure");
}
{ // LookAt
Vec3 eye = Vec3(0.024, 14.6, 67.04);
Vec3 dir = Vec3(0.0, 0.0, -1.0);
Vec3 up = Vec3(0.0, 1.0, 0.0);
Vec3 center = eye + dir;
Mat4 view1 = LookAt(eye, center, up);
Mat4 view2 = Mat4(
1.0, -0.0, 0.0, -0.024,
0.0, 1.0, 0.0, -14.6,
-0.0, -0.0, 1.0, 67.04,
0.0, 0.0, 0.0, 1.0
);
assert(view1 == view2, "LookAt failure");
}
}

1378
src/to_rework/math.d Normal file

File diff suppressed because it is too large Load Diff