82 lines
3.1 KiB
Zig
82 lines
3.1 KiB
Zig
const std = @import("std");
|
|
const vec = @import("vec.zig");
|
|
const Vec3f = vec.Vec3f;
|
|
const Vec4f = vec.Vec4f;
|
|
|
|
// Intentionally use Vec4f to hopefully improve vectorization.
|
|
pub const Mat3f = Mat(3, Vec4f);
|
|
pub const Mat4f = Mat(4, Vec4f);
|
|
|
|
pub fn Mat(comptime nelem: comptime_int, comptime Vec: type) type {
|
|
return packed struct {
|
|
const Self = @This();
|
|
pub const nelem = nelem;
|
|
|
|
pub const zero = Self{};
|
|
pub const id = Self{
|
|
.c0 = .{ .x = 1 },
|
|
.c1 = .{ .y = 1 },
|
|
.c2 = if (nelem > 2 and Vec.nelem > 2) .{ .z = 1 } else {},
|
|
.c3 = if (nelem > 3 and Vec.nelem > 3) .{ .w = 1 } else {},
|
|
};
|
|
|
|
c0: Vec = .{},
|
|
c1: Vec = .{},
|
|
c2: if (nelem > 2) Vec else void = if (nelem > 2) .{} else {},
|
|
c3: if (nelem > 3) Vec else void = if (nelem > 3) .{} else {},
|
|
|
|
pub inline fn mulCol(self: Self, col: Vec) Vec {
|
|
const a = self.c0.mulvs(col.x);
|
|
const b = self.c1.mulvs(col.y);
|
|
const c = if (nelem > 2 and Vec.nelem > 2) self.c2.mulvs(col.z) else {};
|
|
const d = if (nelem > 3 and Vec.nelem > 2) self.c0.mulvs(col.w) else {};
|
|
return a.add(b).add(if (nelem > 2) if (nelem > 3) c.add(d) else c else Vec.zero);
|
|
}
|
|
|
|
pub inline fn mul(a: Self, b: Self) Self {
|
|
return Self{
|
|
.c0 = a.mulCol(b.c0),
|
|
.c1 = a.mulCol(b.c1),
|
|
.c2 = if (nelem > 2) a.mulCol(b.c2) else {},
|
|
.c3 = if (nelem > 3) a.mulCol(b.c3) else {},
|
|
};
|
|
}
|
|
|
|
// Special methods specifically for Mat4f.
|
|
pub usingnamespace if (nelem == 4 and Vec == Vec4f) struct {
|
|
pub inline fn lookAt(eye: Vec4f, at: Vec4f, up: Vec4f) Self {
|
|
// right-handed (ew)
|
|
const f = at.sub(eye).normalize3();
|
|
const s = f.cross3(up).normalize3();
|
|
const u = s.cross3(f).normalize3();
|
|
|
|
const tx = -s.dot3(eye);
|
|
const ty = -u.dot3(eye);
|
|
const tz = f.dot3(eye);
|
|
return Self{
|
|
.c0 = .{ .x = s.x, .y = u.x, .z = -f.x, .w = 0 },
|
|
.c1 = .{ .x = s.y, .y = u.y, .z = -f.y, .w = 0 },
|
|
.c2 = .{ .x = s.z, .y = u.z, .z = -f.z, .w = 0 },
|
|
.c3 = .{ .x = tx, .y = ty, .z = tz, .w = 1 },
|
|
};
|
|
}
|
|
|
|
pub inline fn glPerspective(fov_y: f32, aspect: f32, z_near: f32, z_far: f32) Self {
|
|
const t = std.math.tan(fov_y * 0.5);
|
|
var m = Mat(4, Vec4f).zero;
|
|
m.c0.x = 1.0 / (aspect * t);
|
|
m.c1.y = 1.0 / t;
|
|
m.c2.z = -1.0 * (z_far * z_near) / (z_far - z_near);
|
|
m.c3.z = -2.0 * (z_far * z_near) / (z_far - z_near);
|
|
return m;
|
|
}
|
|
|
|
pub inline fn vkPerspective(fov_y: f32, aspect: f32, z_near: f32, z_far: f32) Self {
|
|
var m = glPerspective(fov_y, aspect, z_near, z_far);
|
|
m.c1.y *= -1.0;
|
|
return m;
|
|
}
|
|
} else struct {};
|
|
};
|
|
}
|