const std = @import("std"); const vm = @import("root"); pub const Matrix4x4 = extern struct { ix: f32, iy: f32, iz: f32, iw: f32, jx: f32, jy: f32, jz: f32, jw: f32, kx: f32, ky: f32, kz: f32, kw: f32, tx: f32, ty: f32, tz: f32, tw: f32, pub const Array = [16]f32; pub const identity = init(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); // --- INIT --- pub inline fn init(ix: f32, iy: f32, iz: f32, iw: f32, jx: f32, jy: f32, jz: f32, jw: f32, kx: f32, ky: f32, kz: f32, kw: f32, tx: f32, ty: f32, tz: f32, tw: f32) Matrix4x4 { return .{ .ix = ix, .iy = iy, .iz = iz, .iw = iw, .jx = jx, .jy = jy, .jz = jz, .jw = jw, .kx = kx, .ky = ky, .kz = kz, .kw = kw, .tx = tx, .ty = ty, .tz = tz, .tw = tw }; } pub inline fn initTranslation(t: Vector3) Matrix4x4 { return .{ .ix = 1, .iy = 0, .iz = 0, .iw = 0, .jx = 0, .jy = 1, .jz = 0, .jw = 0, .kx = 0, .ky = 0, .kz = 1, .kw = 0, .tx = t.x, .ty = t.y, .tz = t.z, .tw = 1 }; } pub inline fn initRotation(q: Quaternion) Matrix4x4 { const xx = q.x * q.x; const xy = q.x * q.y; const xz = q.x * q.z; const xw = q.x * q.w; const yy = q.y * q.y; const yz = q.y * q.z; const yw = q.y * q.w; const zz = q.z * q.z; const zw = q.z * q.w; return .{ .ix = 1 - 2 * (yy + zz), .jx = 2 * (xy + zw), .kx = 2 * (xz - yw), .tx = 0, .iy = 2 * (xy - zw), .jy = 1 - 2 * (xx + zz), .ky = 2 * (yz + xw), .ty = 0, .iz = 2 * (xz + yw), .jz = 2 * (yz - xw), .kz = 1 - 2 * (xx + yy), .tz = 0, .iw = 0, .jw = 0, .kw = 0, .tw = 1 }; } pub inline fn initScale(s: Vector3) Matrix4x4 { return .{ .ix = s.x, .iy = 0, .iz = 0, .iw = 0, .jx = 0, .jy = s.y, .jz = 0, .jw = 0, .kx = 0, .ky = 0, .kz = s.z, .kw = 0, .tx = 0, .ty = 0, .tz = 0, .tw = 1 }; } pub inline fn initArray(array: Array) Matrix4x4 { return @bitCast(array); } // --- CONVERSION --- pub inline fn asArray(self: Matrix4x4) Array { return @bitCast(self); } pub inline fn asArrayPtr(self: *Matrix4x4) *Array { return @ptrCast(self); } pub inline fn asArrayConstPtr(self: *const Matrix4x4) *const Array { return @ptrCast(self); } // --- TRANSFORM --- pub inline fn transformPoint(self: Matrix4x4, p: Vector3) Vector3 { return .{ .x = p.x * self.ix + p.y * self.jx + p.z * self.kx + self.tx, .y = p.x * self.iy + p.y * self.jy + p.z * self.ky + self.ty, .z = p.x * self.iz + p.y * self.jz + p.z * self.kz + self.tz, }; } pub inline fn transformPoint_x8(self: Matrix4x4, p: Vector3x8) Vector3x8 { return .{ .x = p.x * ps(self.ix) + p.y * ps(self.jx) + p.z * ps(self.kx) + ps(self.tx), .y = p.x * ps(self.iy) + p.y * ps(self.jy) + p.z * ps(self.ky) + ps(self.ty), .z = p.x * ps(self.iz) + p.y * ps(self.jz) + p.z * ps(self.kz) + ps(self.tz), }; } pub inline fn transformVector(self: Matrix4x4, v: Vector3) Vector3 { return .{ .x = v.x * self.ix + v.y * self.jx + v.z * self.kx, .y = v.x * self.iy + v.y * self.jy + v.z * self.ky, .z = v.x * self.iz + v.y * self.jz + v.z * self.kz, }; } pub inline fn transformVector_x8(self: Matrix4x4, v: Vector3x8) Vector3x8 { return .{ .x = v.x * ps(self.ix) + v.y * ps(self.jx) + v.z * ps(self.kx), .y = v.x * ps(self.iy) + v.y * ps(self.jy) + v.z * ps(self.ky), .z = v.x * ps(self.iz) + v.y * ps(self.jz) + v.z * ps(self.kz), }; } pub inline fn transformHomogeneous(self: Matrix4x4, h: Vector4) Vector4 { return .{ .x = h.x * self.ix + h.y * self.jx + h.z * self.kx + h.w * self.tx, .y = h.x * self.iy + h.y * self.jy + h.z * self.ky + h.w * self.ty, .z = h.x * self.iz + h.y * self.jz + h.z * self.kz + h.w * self.tz, .w = h.x * self.iw + h.y * self.jw + h.z * self.kw + h.w * self.tw, }; } pub inline fn transformHomogeneous_x8(self: Matrix4x4, h: Vector4x8) Vector4x8 { return .{ .x = h.x * ps(self.ix) + h.y * ps(self.jx) + h.z * ps(self.kx) + h.w * ps(self.tx), .y = h.x * ps(self.iy) + h.y * ps(self.jy) + h.z * ps(self.ky) + h.w * ps(self.ty), .z = h.x * ps(self.iz) + h.y * ps(self.jz) + h.z * ps(self.kz) + h.w * ps(self.tz), .w = h.x * ps(self.iw) + h.y * ps(self.jw) + h.z * ps(self.kw) + h.w * ps(self.tw), }; } };