JUMBO vecmath completion update

This commit is contained in:
2026-01-04 15:43:10 +01:00
parent b09200b7ab
commit ed6391e97a
24 changed files with 3141 additions and 878 deletions

View File

@@ -1,82 +1,290 @@
const std = @import("std");
const vm = @import("root");
const vm = @import("../root.zig");
pub const Matrix3x2 = extern struct {
ix: f32,
iy: f32,
jx: f32,
jy: f32,
tx: f32,
ty: f32,
// zig fmt: off
ix: f32, iy: f32,
jx: f32, jy: f32,
tx: f32, ty: f32,
// zig fmt: on
pub const Array = [6]f32;
pub const identity = init(1, 0, 0, 1, 0, 0);
pub const identity = init(
// zig fmt: off
1, 0,
0, 1,
0, 0,
// zig fmt: on
);
// --- INIT ---
// --- INIT ----------------------------------------------------------------
pub inline fn init(ix: f32, iy: f32, jx: f32, jy: f32, tx: f32, ty: f32) Matrix3x2 {
return .{ .ix = ix, .iy = iy, .jx = jx, .jy = jy, .tx = tx, .ty = ty };
pub inline fn init(
// zig fmt: off
ix: f32, iy: f32,
jx: f32, jy: f32,
tx: f32, ty: f32,
// zig fmt: on
) Matrix3x2 {
return .{
// zig fmt: off
.ix = ix, .iy = iy,
.jx = jx, .jy = jy,
.tx = tx, .ty = ty,
// zig fmt: on
};
}
pub inline fn initTranslation(t: Vector2) Matrix3x2 {
return .{ .ix = 1, .iy = 0, .jx = 0, .jy = 1, .tx = t.x, .ty = t.y };
pub inline fn initVersors(i: vm.Vector2, j: vm.Vector2, t: vm.Vector2) Matrix3x2 {
return .{
// zig fmt: off
.ix = i.x, .iy = i.y,
.jx = j.x, .jy = j.y,
.tx = t.x, .ty = t.y,
// zig fmt: on
};
}
pub inline fn initRotation(angle_turns: f32) Matrix3x2 {
const c, const s = cossin(angle_turns).asArray();
return .{ .ix = c, .iy = s, .jx = -s, .jy = c, .tx = 0, .ty = 0 };
pub inline fn initTranslation(t: vm.Vector2) Matrix3x2 {
return .{
// zig fmt: off
.ix = 1, .iy = 0,
.jx = 0, .jy = 1,
.tx = t.x, .ty = t.y,
// zig fmt: on
};
}
pub inline fn initScale(s: Vector2) Matrix3x2 {
return .{ .ix = s.x, .iy = 0, .jx = 0, .jy = s.y, .tx = 0, .ty = 0 };
pub inline fn initRotation(c: vm.Complex) Matrix3x2 {
return .{
// zig fmt: off
.ix = c.re, .iy = c.im,
.jx = -c.im, .jy = c.re,
.tx = 0, .ty = 0,
// zig fmt: on
};
}
pub inline fn initScale(s: vm.Vector2) Matrix3x2 {
return .{
// zig fmt: off
.ix = s.x, .iy = 0,
.jx = 0, .jy = s.y,
.tx = 0, .ty = 0,
// zig fmt: on
};
}
pub inline fn initTranslationRotation(t: vm.Vector2, c: vm.Complex) Matrix3x2 {
return .{
// zig fmt: off
.ix = c.re, .iy = c.im,
.jx = -c.im, .jy = c.re,
.tx = t.x, .ty = t.y,
// zig fmt: on
};
}
pub inline fn initTranslationScale(t: vm.Vector2, s: vm.Vector2) Matrix3x2 {
return .{
// zig fmt: off
.ix = s.x, .iy = 0,
.jx = 0, .jy = s.y,
.tx = t.x, .ty = t.y,
// zig fmt: on
};
}
pub inline fn initTranslationRotationScale(t: vm.Vector2, c: vm.Complex, s: vm.Vector2) Matrix3x2 {
return .{
// zig fmt: off
.ix = s.x * c.re, .iy = s.x * c.im,
.jx = s.y * -c.im, .jy = s.y * c.re,
.tx = t.x, .ty = t.y,
// zig fmt: on
};
}
pub inline fn initArray(array: Array) Matrix3x2 {
return @bitCast(array);
}
// --- CONVERSION ---
// --- CONVERSION ----------------------------------------------------------
pub inline fn asArray(self: Matrix3x2) Array {
return @bitCast(self);
}
pub inline fn asArrayPtr(self: *Matrix3x2) *Array {
return @ptrCast(self);
// --- ACCESSORS -----------------------------------------------------------
pub inline fn getIVersor(self: Matrix3x2) vm.Vector2 {
return .{ .x = self.ix, .y = self.iy };
}
pub inline fn asArrayConstPtr(self: *const Matrix3x2) *const Array {
return @ptrCast(self);
pub inline fn getJVersor(self: Matrix3x2) vm.Vector2 {
return .{ .x = self.jx, .y = self.jy };
}
// --- TRANSFORM ---
pub inline fn getTranslationVector(self: Matrix3x2) vm.Vector2 {
return .{ .x = self.tx, .y = self.ty };
}
pub inline fn transformPoint(self: Matrix3x2, p: Vector2) Vector2 {
// --- COMPONENT-WISE ------------------------------------------------------
pub inline fn add(self: Matrix3x2, other: Matrix3x2) Matrix3x2 {
return .{
.ix = self.ix + other.ix,
.iy = self.iy + other.iy,
.jx = self.jx + other.jx,
.jy = self.jy + other.jy,
.tx = self.tx + other.tx,
.ty = self.ty + other.ty,
};
}
pub inline fn sub(self: Matrix3x2, other: Matrix3x2) Matrix3x2 {
return .{
.ix = self.ix - other.ix,
.iy = self.iy - other.iy,
.jx = self.jx - other.jx,
.jy = self.jy - other.jy,
.tx = self.tx - other.tx,
.ty = self.ty - other.ty,
};
}
pub inline fn mulScalar(self: Matrix3x2, scalar: f32) Matrix3x2 {
return .{
.ix = self.ix * scalar,
.iy = self.iy * scalar,
.jx = self.jx * scalar,
.jy = self.jy * scalar,
.tx = self.tx * scalar,
.ty = self.ty * scalar,
};
}
pub inline fn divScalar(self: Matrix3x2, scalar: f32) Matrix3x2 {
return .{
.ix = self.ix / scalar,
.iy = self.iy / scalar,
.jx = self.jx / scalar,
.jy = self.jy / scalar,
.tx = self.tx / scalar,
.ty = self.ty / scalar,
};
}
// --- TRANSFORM -----------------------------------------------------------
// TODO Move to vm.Vector2
pub inline fn transformPoint(self: Matrix3x2, p: vm.Vector2) vm.Vector2 {
return .{
.x = p.x * self.ix + p.y * self.jx + self.tx,
.y = p.x * self.iy + p.y * self.jy + self.ty,
};
}
pub inline fn transformPoint_x8(self: Matrix3x2, p: Vector2x8) Vector2x8 {
// TODO Move to vm.Vector2x8
pub inline fn transformPoint_x8(self: Matrix3x2, p: vm.Vector2x8) vm.Vector2x8 {
return .{
.x = p.x * ps(self.ix) + p.y * ps(self.jx) + ps(self.tx),
.y = p.x * ps(self.iy) + p.y * ps(self.jy) + ps(self.ty),
.x = p.x * vm.ps(self.ix) + p.y * vm.ps(self.jx) + vm.ps(self.tx),
.y = p.x * vm.ps(self.iy) + p.y * vm.ps(self.jy) + vm.ps(self.ty),
};
}
pub inline fn transformVector(self: Matrix3x2, v: Vector2) Vector2 {
// TODO Move to vm.Vector2
pub inline fn transformVector(self: Matrix3x2, v: vm.Vector2) vm.Vector2 {
return .{
.x = v.x * self.ix + v.y * self.jx,
.y = v.x * self.iy + v.y * self.jy,
};
}
pub inline fn transformVector_x8(self: Matrix3x2, v: Vector2x8) Vector2x8 {
// TODO Move to vm.Vector2x8
pub inline fn transformVector_x8(self: Matrix3x2, v: vm.Vector2x8) vm.Vector2x8 {
return .{
.x = v.x * ps(self.ix) + v.y * ps(self.jx),
.y = v.x * ps(self.iy) + v.y * ps(self.jy),
.x = v.x * vm.ps(self.ix) + v.y * vm.ps(self.jx),
.y = v.x * vm.ps(self.iy) + v.y * vm.ps(self.jy),
};
}
// --- COMPOSE -------------------------------------------------------------
pub inline fn mulMatrix(self: Matrix3x2, other: Matrix3x2) Matrix3x2 {
return .{
.ix = other.ix * self.ix + other.iy * self.jx,
.iy = other.ix * self.iy + other.iy * self.jy,
.jx = other.jx * self.ix + other.jy * self.jx,
.jy = other.jx * self.iy + other.jy * self.jy,
.tx = other.tx * self.ix + other.ty * self.jx + self.tx,
.ty = other.tx * self.iy + other.ty * self.jy + self.ty,
};
}
pub inline fn mulMatrix_x8(self: Matrix3x2, other: vm.Matrix3x2x8) vm.Matrix3x2 {
return .{
.ix = other.ix * vm.ps(self.ix) + other.iy * vm.ps(self.jx),
.iy = other.ix * vm.ps(self.iy) + other.iy * vm.ps(self.jy),
.jx = other.jx * vm.ps(self.ix) + other.jy * vm.ps(self.jx),
.jy = other.jx * vm.ps(self.iy) + other.jy * vm.ps(self.jy),
.tx = other.tx * vm.ps(self.ix) + other.ty * vm.ps(self.jx) + vm.ps(self.tx),
.ty = other.tx * vm.ps(self.iy) + other.ty * vm.ps(self.jy) + vm.ps(self.ty),
};
}
// INVERSION DERIVATION
//
// Imagine matrix extended to 3×3 like so:
//
// ⎡ix jx tx⎤
// A = ⎢iy jy ty⎥
// ⎣ 0 0 1⎦
//
// Then:
//
// det A = ix · jy jx · iy
//
// ⎡ ⎡jy ty⎤ ⎡iy ty⎤ ⎡iy jy⎤⎤T
// ⎢ det ⎣ 0 1⎦ det ⎣ 0 1⎦ det ⎣ 0 0⎦⎥
// 1 ⎢ ⎡jx tx⎤ ⎡ix tx⎤ ⎡ix jx⎤⎥ 1 ⎡ jy jx j×t⎤
// inv A = ⎯⎯⎯⎯⎯ ⎢det ⎣ 0 1⎦ det ⎣ 0 1⎦ det ⎣ 0 0⎦⎥ = ⎯⎯⎯⎯⎯ ⎢iy ix i×t⎥
// det A ⎢ ⎡jx tx⎤ ⎡ix tx⎤ ⎡ix jx⎤⎥ det A ⎣ 0 0 det A⎦
// ⎣ det ⎣jy ty⎦ det ⎣iy ty⎦ det ⎣iy jy⎦⎦
//
// After multiplying by 1 / (det A), the third row becomes [0 0 1].
// When A is orthonormal, we can assume det A = 1.
pub inline fn inverseOrthonormal(self: Matrix3x2) Matrix3x2 {
std.debug.assert(self.ix == self.jy and self.iy == -self.jx);
const ix = self.ix;
const iy = self.jx;
const jx = self.iy;
const jy = self.jy;
return .{
.ix = ix,
.iy = iy,
.jx = jx,
.jy = jy,
.tx = -(self.tx * ix + self.ty * jx),
.ty = -(self.tx * iy + self.ty * jy),
};
}
pub inline fn inverseAffine(self: Matrix3x2) Matrix3x2 {
const inv_det = 1.0 / (self.ix * self.jy - self.jx * self.iy);
const ix = self.jy;
const iy = -self.iy;
const jx = -self.jx;
const jy = self.ix;
return .{
.ix = inv_det * ix,
.iy = inv_det * iy,
.jx = inv_det * jx,
.jy = inv_det * jy,
.tx = -inv_det * (self.tx * ix + self.ty * jx),
.ty = -inv_det * (self.tx * iy + self.ty * jy),
};
}
};

View File

@@ -1,2 +1,443 @@
const std = @import("std");
const vm = @import("root");
const vm = @import("../root.zig");
pub const Matrix3x2x8 = struct {
// zig fmt: off
ix: vm.f32x8, iy: vm.f32x8,
jx: vm.f32x8, jy: vm.f32x8,
tx: vm.f32x8, ty: vm.f32x8,
// zig fmt: on
pub const identity = initSingle(
// zig fmt: off
1, 0,
0, 1,
0, 0,
// zig fmt: on
);
// --- INIT ----------------------------------------------------------------
pub inline fn init(
// zig fmt: off
ix: vm.f32x8, iy: vm.f32x8,
jx: vm.f32x8, jy: vm.f32x8,
tx: vm.f32x8, ty: vm.f32x8,
// zig fmt: on
) Matrix3x2x8 {
return .{
// zig fmt: off
.ix = ix, .iy = iy,
.jx = jx, .jy = jy,
.tx = tx, .ty = ty,
// zig fmt: on
};
}
pub inline fn initSingle(
// zig fmt: off
ix: f32, iy: f32,
jx: f32, jy: f32,
tx: f32, ty: f32,
// zig fmt: on
) Matrix3x2x8 {
return .{
// zig fmt: off
.ix = vm.ps(ix), .iy = vm.ps(iy),
.jx = vm.ps(jx), .jy = vm.ps(jy),
.tx = vm.ps(tx), .ty = vm.ps(ty),
// zig fmt: on
};
}
pub inline fn initVersors(i: vm.Vector2x8, j: vm.Vector2x8, t: vm.Vector2x8) Matrix3x2x8 {
return .{
// zig fmt: off
.ix = i.x, .iy = i.y,
.jx = j.x, .jy = j.y,
.tx = t.x, .ty = t.y,
// zig fmt: on
};
}
pub inline fn initVersorsSingle(i: vm.Vector2, j: vm.Vector2, t: vm.Vector2) Matrix3x2x8 {
return .{
// zig fmt: off
.ix = vm.ps(i.x), .iy = vm.ps(i.y),
.jx = vm.ps(j.x), .jy = vm.ps(j.y),
.tx = vm.ps(t.x), .ty = vm.ps(t.y),
// zig fmt: on
};
}
pub inline fn initTranslation(t: vm.Vector2x8) Matrix3x2x8 {
return .{
// zig fmt: off
.ix = vm.ps(1), .iy = vm.ps(0),
.jx = vm.ps(0), .jy = vm.ps(1),
.tx = t.x, .ty = t.y,
// zig fmt: on
};
}
pub inline fn initTranslationSingle(t: vm.Vector2) Matrix3x2x8 {
return .{
// zig fmt: off
.ix = vm.ps(1), .iy = vm.ps(0),
.jx = vm.ps(0), .jy = vm.ps(1),
.tx = vm.ps(t.x), .ty = vm.ps(t.y),
// zig fmt: on
};
}
pub inline fn initRotation(c: vm.Complex_x8) Matrix3x2x8 {
return .{
// zig fmt: off
.ix = c.re, .iy = c.im,
.jx = -c.im, .jy = c.re,
.tx = vm.ps(0), .ty = vm.ps(0),
// zig fmt: on
};
}
pub inline fn initRotationSingle(c: vm.Complex) Matrix3x2x8 {
return .{
// zig fmt: off
.ix = vm.ps( c.re), .iy = vm.ps(c.im),
.jx = vm.ps(-c.im), .jy = vm.ps(c.re),
.tx = vm.ps(0), .ty = vm.ps(0),
// zig fmt: on
};
}
pub inline fn initScale(s: vm.Vector2x8) Matrix3x2x8 {
return .{
// zig fmt: off
.ix = s.x, .iy = vm.ps(0),
.jx = vm.ps(0), .jy = s.y,
.tx = vm.ps(0), .ty = vm.ps(0),
// zig fmt: on
};
}
pub inline fn initScaleSingle(s: vm.Vector2) Matrix3x2x8 {
return .{
// zig fmt: off
.ix = vm.ps(s.x), .iy = vm.ps(0),
.jx = vm.ps(0), .jy = vm.ps(s.y),
.tx = vm.ps(0), .ty = vm.ps(0),
// zig fmt: on
};
}
pub inline fn initTranslationRotation(t: vm.Vector2x8, c: vm.Complex_x8) Matrix3x2x8 {
return .{
// zig fmt: off
.ix = c.re, .iy = c.im,
.jx = -c.im, .jy = c.re,
.tx = t.x, .ty = t.y,
// zig fmt: on
};
}
pub inline fn initTranslationRotationSingle(t: vm.Vector2, c: vm.Complex) Matrix3x2x8 {
return .{
// zig fmt: off
.ix = vm.ps( c.re), .iy = vm.ps(c.im),
.jx = vm.ps(-c.im), .jy = vm.ps(c.re),
.tx = vm.ps( t.x), .ty = vm.ps(t.y),
// zig fmt: on
};
}
pub inline fn initTranslationScale(t: vm.Vector2x8, s: vm.Vector2x8) Matrix3x2x8 {
return .{
// zig fmt: off
.ix = s.x, .iy = vm.ps(0),
.jx = vm.ps(0), .jy = s.y,
.tx = t.x, .ty = t.y,
// zig fmt: on
};
}
pub inline fn initTranslationScaleSingle(t: vm.Vector2, s: vm.Vector2) Matrix3x2x8 {
return .{
// zig fmt: off
.ix = vm.ps(s.x), .iy = vm.ps(0),
.jx = vm.ps(0), .jy = vm.ps(s.y),
.tx = vm.ps(t.x), .ty = vm.ps(t.y),
// zig fmt: on
};
}
pub inline fn initTranslationRotationScale(t: vm.Vector2x8, c: vm.Complex_x8, s: vm.Vector2x8) Matrix3x2x8 {
return .{
// zig fmt: off
.ix = s.x * c.re, .iy = s.x * c.im,
.jx = s.y * -c.im, .jy = s.y * c.re,
.tx = t.x, .ty = t.y,
// zig fmt: on
};
}
pub inline fn initTranslationRotationScaleSingle(t: vm.Vector2, c: vm.Complex, s: vm.Vector2) Matrix3x2x8 {
return .{
// zig fmt: off
.ix = vm.ps(s.x * c.re), .iy = vm.ps(s.x * c.im),
.jx = vm.ps(s.y * -c.im), .jy = vm.ps(s.y * c.re),
.tx = vm.ps(t.x), .ty = vm.ps(t.y),
// zig fmt: on
};
}
pub inline fn initArrayOfMatrices(matrices: [8]vm.Matrix3x2) Matrix3x2x8 {
const vector: @Vector(48, f32) = @as([48]f32, @bitCast(matrices));
return .{
.ix = @shuffle(f32, vector, undefined, [_]i32{ 0, 6, 12, 18, 24, 30, 36, 42 }),
.iy = @shuffle(f32, vector, undefined, [_]i32{ 1, 7, 13, 19, 25, 31, 37, 43 }),
.jx = @shuffle(f32, vector, undefined, [_]i32{ 2, 8, 14, 20, 26, 32, 38, 44 }),
.jy = @shuffle(f32, vector, undefined, [_]i32{ 3, 9, 15, 21, 27, 33, 39, 45 }),
.tx = @shuffle(f32, vector, undefined, [_]i32{ 4, 10, 16, 22, 28, 34, 40, 46 }),
.ty = @shuffle(f32, vector, undefined, [_]i32{ 5, 11, 17, 23, 29, 35, 41, 47 }),
};
}
pub inline fn splat(matrix: vm.Matrix3x2) Matrix3x2x8 {
return .{
// zig fmt: off
.ix = vm.ps(matrix.ix), .iy = vm.ps(matrix.iy),
.jx = vm.ps(matrix.jx), .jy = vm.ps(matrix.jy),
.tx = vm.ps(matrix.tx), .ty = vm.ps(matrix.ty),
// zig fmt: on
};
}
// --- CONVERSION ----------------------------------------------------------
pub inline fn asArrayOfMatrices(self: Matrix3x2x8) [8]vm.Matrix3x2 {
const vector: @Vector(48, f32) = self.ix ++ self.iy ++ self.jx ++ self.jy ++ self.tx ++ self.ty;
return @bitCast(@as([48]f32, @shuffle(f32, vector, undefined, [_]i32{
0, 8, 16, 24, 32, 40,
1, 9, 17, 25, 33, 41,
2, 10, 18, 26, 34, 42,
3, 11, 19, 27, 35, 43,
4, 12, 20, 28, 36, 44,
5, 13, 21, 29, 37, 45,
6, 14, 22, 30, 38, 46,
7, 15, 23, 31, 39, 47,
})));
}
pub inline fn unpack(self: Matrix3x2x8) [6]vm.f32x8 {
return .{ self.ix, self.iy, self.jx, self.jy, self.tx, self.ty };
}
// --- LOAD AND STORE ------------------------------------------------------
pub inline fn loadArrayOfMatrices(self: *Matrix3x2x8, array: *const [8]vm.Matrix3x2) void {
const vector: @Vector(48, f32) = @as(*const [48]f32, @ptrCast(array)).*;
self.ix = @shuffle(f32, vector, undefined, [_]i32{ 0, 6, 12, 18, 24, 30, 36, 42 });
self.iy = @shuffle(f32, vector, undefined, [_]i32{ 1, 7, 13, 19, 25, 31, 37, 43 });
self.jx = @shuffle(f32, vector, undefined, [_]i32{ 2, 8, 14, 20, 26, 32, 38, 44 });
self.jy = @shuffle(f32, vector, undefined, [_]i32{ 3, 9, 15, 21, 27, 33, 39, 45 });
self.tx = @shuffle(f32, vector, undefined, [_]i32{ 4, 10, 16, 22, 28, 34, 40, 46 });
self.ty = @shuffle(f32, vector, undefined, [_]i32{ 5, 11, 17, 23, 29, 35, 41, 47 });
}
pub inline fn storeArrayOfMatrices(self: *const Matrix3x2x8, array: *[8]vm.Matrix3x2) void {
const vector: @Vector(48, f32) = self.ix ++ self.iy ++ self.jx ++ self.jy ++ self.tx ++ self.ty;
@as(*[48]f32, @ptrCast(array)).* = @shuffle(f32, vector, undefined, [_]i32{
0, 8, 16, 24, 32, 40,
1, 9, 17, 25, 33, 41,
2, 10, 18, 26, 34, 42,
3, 11, 19, 27, 35, 43,
4, 12, 20, 28, 36, 44,
5, 13, 21, 29, 37, 45,
6, 14, 22, 30, 38, 46,
7, 15, 23, 31, 39, 47,
});
}
// --- ACCESSORS -----------------------------------------------------------
pub inline fn getIVersor(self: Matrix3x2x8) vm.Vector2x8 {
return .{ .x = self.ix, .y = self.iy };
}
pub inline fn getJVersor(self: Matrix3x2x8) vm.Vector2x8 {
return .{ .x = self.jx, .y = self.jy };
}
pub inline fn getTranslationVector(self: Matrix3x2x8) vm.Vector2x8 {
return .{ .x = self.tx, .y = self.ty };
}
// --- COMPONENT-WISE ------------------------------------------------------
pub inline fn add(self: Matrix3x2x8, other: Matrix3x2x8) Matrix3x2x8 {
return .{
.ix = self.ix + other.ix,
.iy = self.iy + other.iy,
.jx = self.jx + other.jx,
.jy = self.jy + other.jy,
.tx = self.tx + other.tx,
.ty = self.ty + other.ty,
};
}
pub inline fn sub(self: Matrix3x2x8, other: Matrix3x2x8) Matrix3x2x8 {
return .{
.ix = self.ix - other.ix,
.iy = self.iy - other.iy,
.jx = self.jx - other.jx,
.jy = self.jy - other.jy,
.tx = self.tx - other.tx,
.ty = self.ty - other.ty,
};
}
pub inline fn mulScalar(self: Matrix3x2x8, scalar: vm.f32x8) Matrix3x2x8 {
return .{
.ix = self.ix * scalar,
.iy = self.iy * scalar,
.jx = self.jx * scalar,
.jy = self.jy * scalar,
.tx = self.tx * scalar,
.ty = self.ty * scalar,
};
}
pub inline fn mulScalarSingle(self: Matrix3x2x8, scalar: f32) Matrix3x2x8 {
return .{
.ix = self.ix * vm.ps(scalar),
.iy = self.iy * vm.ps(scalar),
.jx = self.jx * vm.ps(scalar),
.jy = self.jy * vm.ps(scalar),
.tx = self.tx * vm.ps(scalar),
.ty = self.ty * vm.ps(scalar),
};
}
pub inline fn divScalar(self: Matrix3x2x8, scalar: f32) Matrix3x2x8 {
return .{
.ix = self.ix / scalar,
.iy = self.iy / scalar,
.jx = self.jx / scalar,
.jy = self.jy / scalar,
.tx = self.tx / scalar,
.ty = self.ty / scalar,
};
}
pub inline fn divScalarSingle(self: Matrix3x2x8, scalar: f32) Matrix3x2x8 {
return .{
.ix = self.ix / vm.ps(scalar),
.iy = self.iy / vm.ps(scalar),
.jx = self.jx / vm.ps(scalar),
.jy = self.jy / vm.ps(scalar),
.tx = self.tx / vm.ps(scalar),
.ty = self.ty / vm.ps(scalar),
};
}
// --- TRANSFORM -----------------------------------------------------------
// TODO Move to vm.Vector2x8
pub inline fn transformPoint(self: Matrix3x2x8, p: vm.Vector2x8) vm.Vector2x8 {
return .{
.x = p.x * self.ix + p.y * self.jx + self.tx,
.y = p.x * self.iy + p.y * self.jy + self.ty,
};
}
// TODO Move to vm.Vector2x8
pub inline fn transformPointSingle(self: Matrix3x2x8, p: vm.Vector2) vm.Vector2x8 {
return .{
.x = vm.ps(p.x) * self.ix + vm.ps(p.y) * self.jx + self.tx,
.y = vm.ps(p.x) * self.iy + vm.ps(p.y) * self.jy + self.ty,
};
}
// TODO Move to vm.Vector2x8
pub inline fn transformVector(self: Matrix3x2x8, v: vm.Vector2x8) vm.Vector2x8 {
return .{
.x = v.x * self.ix + v.y * self.jx,
.y = v.x * self.iy + v.y * self.jy,
};
}
// TODO Move to vm.Vector2x8
pub inline fn transformVectorSingle(self: Matrix3x2x8, v: vm.Vector2) vm.Vector2x8 {
return .{
.x = vm.ps(v.x) * self.ix + vm.ps(v.y) * self.jx,
.y = vm.ps(v.x) * self.iy + vm.ps(v.y) * self.jy,
};
}
// --- COMPOSE -------------------------------------------------------------
pub inline fn mulMatrix(self: Matrix3x2x8, other: Matrix3x2x8) Matrix3x2x8 {
return .{
.ix = other.ix * self.ix + other.iy * self.jx,
.iy = other.ix * self.iy + other.iy * self.jy,
.jx = other.jx * self.ix + other.jy * self.jx,
.jy = other.jx * self.iy + other.jy * self.jy,
.tx = other.tx * self.ix + other.ty * self.jx + self.tx,
.ty = other.tx * self.iy + other.ty * self.jy + self.ty,
};
}
pub inline fn mulMatrixSingle(self: Matrix3x2x8, other: vm.Matrix3x2) Matrix3x2x8 {
return .{
.ix = vm.ps(other.ix) * self.ix + vm.ps(other.iy) * self.jx,
.iy = vm.ps(other.ix) * self.iy + vm.ps(other.iy) * self.jy,
.jx = vm.ps(other.jx) * self.ix + vm.ps(other.jy) * self.jx,
.jy = vm.ps(other.jx) * self.iy + vm.ps(other.jy) * self.jy,
.tx = vm.ps(other.tx) * self.ix + vm.ps(other.ty) * self.jx + self.tx,
.ty = vm.ps(other.tx) * self.iy + vm.ps(other.ty) * self.jy + self.ty,
};
}
pub inline fn premulMatrixSingle(self: Matrix3x2x8, other: vm.Matrix3x2) Matrix3x2x8 {
return .{
.ix = self.ix * vm.ps(other.ix) + self.iy * vm.ps(other.jx),
.iy = self.ix * vm.ps(other.iy) + self.iy * vm.ps(other.jy),
.jx = self.jx * vm.ps(other.ix) + self.jy * vm.ps(other.jx),
.jy = self.jx * vm.ps(other.iy) + self.jy * vm.ps(other.jy),
.tx = self.tx * vm.ps(other.ix) + self.ty * vm.ps(other.jx) + vm.ps(other.tx),
.ty = self.tx * vm.ps(other.iy) + self.ty * vm.ps(other.jy) + vm.ps(other.ty),
};
}
pub inline fn inverseOrthonormal(self: Matrix3x2x8) Matrix3x2x8 {
std.debug.assert(@reduce(.And, self.ix == self.jy and self.iy == -self.jx));
const ix = self.ix;
const iy = self.jx;
const jx = self.iy;
const jy = self.jy;
return .{
.ix = ix,
.iy = iy,
.jx = jx,
.jy = jy,
.tx = -(self.tx * ix + self.ty * jx),
.ty = -(self.tx * iy + self.ty * jy),
};
}
pub inline fn inverseAffine(self: Matrix3x2x8) Matrix3x2x8 {
const inv_det = vm.ps(1.0) / (self.ix * self.jy - self.jx * self.iy);
const ix = self.jy;
const iy = -self.iy;
const jx = -self.jx;
const jy = self.ix;
return .{
.ix = inv_det * ix,
.iy = inv_det * iy,
.jx = inv_det * jx,
.jy = inv_det * jy,
.tx = -inv_det * (self.tx * ix + self.ty * jx),
.ty = -inv_det * (self.tx * iy + self.ty * jy),
};
}
};

View File

@@ -1,39 +1,68 @@
const std = @import("std");
const vm = @import("root");
const vm = @import("../root.zig");
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,
// zig fmt: off
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,
// zig fmt: on
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);
pub const identity = init(
// zig fmt: off
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
// zig fmt: on
);
// --- INIT ---
// --- 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 init(
// zig fmt: off
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,
// zig fmt: on
) Matrix4x4 {
return .{
// zig fmt: off
.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,
// zig fmt: on
};
}
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 initVersors(i: vm.Vector4, j: vm.Vector4, k: vm.Vector4, t: vm.Vector4) Matrix4x4 {
return .{
// zig fmt: off
.ix = i.x, .iy = i.y, .iz = i.z, .iw = i.w,
.jx = j.x, .jy = j.y, .jz = j.z, .jw = j.w,
.kx = k.x, .ky = k.y, .kz = k.z, .kw = k.w,
.tx = t.x, .ty = t.y, .tz = t.z, .tw = t.w,
// zig fmt: on
};
}
pub inline fn initRotation(q: Quaternion) Matrix4x4 {
pub inline fn initTranslation(t: vm.Vector3) Matrix4x4 {
return .{
// zig fmt: off
.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,
// zig fmt: on
};
}
pub inline fn initRotation(q: vm.Quaternion) Matrix4x4 {
const xx = q.x * q.x;
const xy = q.x * q.y;
const xz = q.x * q.z;
@@ -44,34 +73,198 @@ pub const Matrix4x4 = extern struct {
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 };
return .{
// zig fmt: off
.ix = 1 - 2 * (yy + zz), .iy = 2 * (xy - zw), .iz = 2 * (xz + yw), .iw = 0,
.jx = 2 * (xy + zw), .jy = 1 - 2 * (xx + zz), .jz = 2 * (yz - xw), .jw = 0,
.kx = 2 * (xz - yw), .ky = 2 * (yz + xw), .kz = 1 - 2 * (xx + yy), .kw = 0,
.tx = 0, .ty = 0, .tz = 0, .tw = 1,
// zig fmt: on
};
}
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 initScale(s: vm.Vector3) Matrix4x4 {
return .{
// zig fmt: off
.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,
// zig fmt: on
};
}
pub inline fn initTranslationRotation(t: vm.Vector3, q: vm.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 .{
// zig fmt: off
.ix = 1 - 2 * (yy + zz), .iy = 2 * (xy - zw), .iz = 2 * (xz + yw), .iw = 0,
.jx = 2 * (xy + zw), .jy = 1 - 2 * (xx + zz), .jz = 2 * (yz - xw), .jw = 0,
.kx = 2 * (xz - yw), .ky = 2 * (yz + xw), .kz = 1 - 2 * (xx + yy), .kw = 0,
.tx = t.x, .ty = t.y, .tz = t.z, .tw = 1,
// zig fmt: on
};
}
pub inline fn initTranslationScale(t: vm.Vector3, s: vm.Vector3) Matrix4x4 {
return .{
// zig fmt: off
.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 = t.x, .ty = t.y, .tz = t.z, .tw = 1,
// zig fmt: on
};
}
pub inline fn initTranslationRotationScale(t: vm.Vector3, q: vm.Quaternion, s: vm.Vector3) 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 .{
// zig fmt: off
.ix = s.x * (1 - 2 * (yy + zz)), .iy = s.x * 2 * (xy - zw), .iz = s.x * 2 * (xz + yw), .iw = 0,
.jx = s.y * 2 * (xy + zw), .jy = s.y * (1 - 2 * (xx + zz)), .jz = s.y * 2 * (yz - xw), .jw = 0,
.kx = s.z * 2 * (xz - yw), .ky = s.z * 2 * (yz + xw), .kz = s.z * (1 - 2 * (xx + yy)), .kw = 0,
.tx = t.x, .ty = t.y, .tz = t.z, .tw = 1,
// zig fmt: on
};
}
pub inline fn initArray(array: Array) Matrix4x4 {
return @bitCast(array);
}
// --- CONVERSION ---
// --- CONVERSION ----------------------------------------------------------
pub inline fn asArray(self: Matrix4x4) Array {
return @bitCast(self);
}
pub inline fn asArrayPtr(self: *Matrix4x4) *Array {
return @ptrCast(self);
// --- ACCESSORS -----------------------------------------------------------
pub inline fn getIVersor(self: Matrix4x4) vm.Vector4 {
return .{ .x = self.ix, .y = self.iy, .z = self.iz, .w = self.iw };
}
pub inline fn asArrayConstPtr(self: *const Matrix4x4) *const Array {
return @ptrCast(self);
pub inline fn getJVersor(self: Matrix4x4) vm.Vector4 {
return .{ .x = self.jx, .y = self.jy, .z = self.jz, .w = self.jw };
}
// --- TRANSFORM ---
pub inline fn getKVersor(self: Matrix4x4) vm.Vector4 {
return .{ .x = self.kx, .y = self.ky, .z = self.kz, .w = self.kw };
}
pub inline fn transformPoint(self: Matrix4x4, p: Vector3) Vector3 {
pub inline fn getTranslationVector(self: Matrix4x4) vm.Vector4 {
return .{ .x = self.tx, .y = self.ty, .z = self.tz, .w = self.tw };
}
// --- COMPONENT-WISE ------------------------------------------------------
pub inline fn add(self: Matrix4x4, other: Matrix4x4) Matrix4x4 {
return .{
.ix = self.ix + other.ix,
.iy = self.iy + other.iy,
.iz = self.iz + other.iz,
.iw = self.iw + other.iw,
.jx = self.jx + other.jx,
.jy = self.jy + other.jy,
.jz = self.jz + other.jz,
.jw = self.jw + other.jw,
.kx = self.kx + other.kx,
.ky = self.ky + other.ky,
.kz = self.kz + other.kz,
.kw = self.kw + other.kw,
.tx = self.tx + other.tx,
.ty = self.ty + other.ty,
.tz = self.tz + other.tz,
.tw = self.tw + other.tw,
};
}
pub inline fn sub(self: Matrix4x4, other: Matrix4x4) Matrix4x4 {
return .{
.ix = self.ix - other.ix,
.iy = self.iy - other.iy,
.iz = self.iz - other.iz,
.iw = self.iw - other.iw,
.jx = self.jx - other.jx,
.jy = self.jy - other.jy,
.jz = self.jz - other.jz,
.jw = self.jw - other.jw,
.kx = self.kx - other.kx,
.ky = self.ky - other.ky,
.kz = self.kz - other.kz,
.kw = self.kw - other.kw,
.tx = self.tx - other.tx,
.ty = self.ty - other.ty,
.tz = self.tz - other.tz,
.tw = self.tw - other.tw,
};
}
pub inline fn mulScalar(self: Matrix4x4, scalar: f32) Matrix4x4 {
return .{
.ix = self.ix * scalar,
.iy = self.iy * scalar,
.iz = self.iz * scalar,
.iw = self.iw * scalar,
.jx = self.jx * scalar,
.jy = self.jy * scalar,
.jz = self.jz * scalar,
.jw = self.jw * scalar,
.kx = self.kx * scalar,
.ky = self.ky * scalar,
.kz = self.kz * scalar,
.kw = self.kw * scalar,
.tx = self.tx * scalar,
.ty = self.ty * scalar,
.tz = self.tz * scalar,
.tw = self.tw * scalar,
};
}
pub inline fn divScalar(self: Matrix4x4, scalar: f32) Matrix4x4 {
return .{
.ix = self.ix / scalar,
.iy = self.iy / scalar,
.iz = self.iz / scalar,
.iw = self.iw / scalar,
.jx = self.jx / scalar,
.jy = self.jy / scalar,
.jz = self.jz / scalar,
.jw = self.jw / scalar,
.kx = self.kx / scalar,
.ky = self.ky / scalar,
.kz = self.kz / scalar,
.kw = self.kw / scalar,
.tx = self.tx / scalar,
.ty = self.ty / scalar,
.tz = self.tz / scalar,
.tw = self.tw / scalar,
};
}
// --- TRANSFORM -----------------------------------------------------------
// TODO Move to vm.Vector3
pub inline fn transformPoint(self: Matrix4x4, p: vm.Vector3) vm.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,
@@ -79,15 +272,17 @@ pub const Matrix4x4 = extern struct {
};
}
pub inline fn transformPoint_x8(self: Matrix4x4, p: Vector3x8) Vector3x8 {
// TODO Move to vm.Vector3x8
pub inline fn transformPoint_x8(self: Matrix4x4, p: vm.Vector3x8) vm.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),
.x = p.x * vm.ps(self.ix) + p.y * vm.ps(self.jx) + p.z * vm.ps(self.kx) + vm.ps(self.tx),
.y = p.x * vm.ps(self.iy) + p.y * vm.ps(self.jy) + p.z * vm.ps(self.ky) + vm.ps(self.ty),
.z = p.x * vm.ps(self.iz) + p.y * vm.ps(self.jz) + p.z * vm.ps(self.kz) + vm.ps(self.tz),
};
}
pub inline fn transformVector(self: Matrix4x4, v: Vector3) Vector3 {
// TODO Move to vm.Vector3
pub inline fn transformVector(self: Matrix4x4, v: vm.Vector3) vm.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,
@@ -95,15 +290,17 @@ pub const Matrix4x4 = extern struct {
};
}
pub inline fn transformVector_x8(self: Matrix4x4, v: Vector3x8) Vector3x8 {
// TODO Move to vm.Vector3x8
pub inline fn transformVector_x8(self: Matrix4x4, v: vm.Vector3x8) vm.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),
.x = v.x * vm.ps(self.ix) + v.y * vm.ps(self.jx) + v.z * vm.ps(self.kx),
.y = v.x * vm.ps(self.iy) + v.y * vm.ps(self.jy) + v.z * vm.ps(self.ky),
.z = v.x * vm.ps(self.iz) + v.y * vm.ps(self.jz) + v.z * vm.ps(self.kz),
};
}
pub inline fn transformHomogeneous(self: Matrix4x4, h: Vector4) Vector4 {
// TODO Move to vm.Vector4
pub inline fn transformHomogeneous(self: Matrix4x4, h: vm.Vector4) vm.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,
@@ -112,12 +309,293 @@ pub const Matrix4x4 = extern struct {
};
}
pub inline fn transformHomogeneous_x8(self: Matrix4x4, h: Vector4x8) Vector4x8 {
// TODO Move to vm.Vector4x8
pub inline fn transformHomogeneous_x8(self: Matrix4x4, h: vm.Vector4x8) vm.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),
.x = h.x * vm.ps(self.ix) + h.y * vm.ps(self.jx) + h.z * vm.ps(self.kx) + h.w * vm.ps(self.tx),
.y = h.x * vm.ps(self.iy) + h.y * vm.ps(self.jy) + h.z * vm.ps(self.ky) + h.w * vm.ps(self.ty),
.z = h.x * vm.ps(self.iz) + h.y * vm.ps(self.jz) + h.z * vm.ps(self.kz) + h.w * vm.ps(self.tz),
.w = h.x * vm.ps(self.iw) + h.y * vm.ps(self.jw) + h.z * vm.ps(self.kw) + h.w * vm.ps(self.tw),
};
}
// --- COMPOSE -------------------------------------------------------------
/// The caller asserts that W rows of all matrices are equal to [0 0 0 1].
pub fn mulMatrixAffine(self: Matrix4x4, other: Matrix4x4) Matrix4x4 {
std.debug.assert(self.iw == 0 and self.jw == 0 and self.kw == 0 and self.tw == 1);
std.debug.assert(other.iw == 0 and other.jw == 0 and other.kw == 0 and other.tw == 1);
return .{
.ix = other.ix * self.ix + other.iy * self.jx + other.iz * self.kx,
.iy = other.ix * self.iy + other.iy * self.jy + other.iz * self.ky,
.iz = other.ix * self.iz + other.iy * self.jz + other.iz * self.kz,
.iw = 0,
.jx = other.jx * self.ix + other.jy * self.jx + other.jz * self.kx,
.jy = other.jx * self.iy + other.jy * self.jy + other.jz * self.ky,
.jz = other.jx * self.iz + other.jy * self.jz + other.jz * self.kz,
.jw = 0,
.kx = other.kx * self.ix + other.ky * self.jx + other.kz * self.kx,
.ky = other.kx * self.iy + other.ky * self.jy + other.kz * self.ky,
.kz = other.kx * self.iz + other.ky * self.jz + other.kz * self.kz,
.kw = 0,
.tx = other.tx * self.tx + other.ty * self.jx + other.tz * self.kx + self.tx,
.ty = other.tx * self.ty + other.ty * self.jy + other.tz * self.ky + self.ty,
.tz = other.tx * self.tz + other.ty * self.jz + other.tz * self.kz + self.tz,
.tw = 1,
};
}
// TODO Move to vm.Matrix4x4x8
/// The caller asserts that W rows of all matrices are equal to [0 0 0 1].
pub fn mulMatrixAffine_x8(self: Matrix4x4, other: vm.Matrix4x4x8) vm.Matrix4x4x8 {
std.debug.assert(self.iw == 0 and self.jw == 0 and self.kw == 0 and self.tw == 1);
std.debug.assert(@reduce(.And, (other.iw == vm.ps(0)) & (other.jw == vm.ps(0)) & (other.kw == vm.ps(0)) & (other.tw == vm.ps(1))));
return .{
.ix = other.ix * vm.ps(self.ix) + other.iy * vm.ps(self.jx) + other.iz * vm.ps(self.kx),
.iy = other.ix * vm.ps(self.iy) + other.iy * vm.ps(self.jy) + other.iz * vm.ps(self.ky),
.iz = other.ix * vm.ps(self.iz) + other.iy * vm.ps(self.jz) + other.iz * vm.ps(self.kz),
.iw = vm.ps(0),
.jx = other.jx * vm.ps(self.ix) + other.jy * vm.ps(self.jx) + other.jz * vm.ps(self.kx),
.jy = other.jx * vm.ps(self.iy) + other.jy * vm.ps(self.jy) + other.jz * vm.ps(self.ky),
.jz = other.jx * vm.ps(self.iz) + other.jy * vm.ps(self.jz) + other.jz * vm.ps(self.kz),
.jw = vm.ps(0),
.kx = other.kx * vm.ps(self.ix) + other.ky * vm.ps(self.jx) + other.kz * vm.ps(self.kx),
.ky = other.kx * vm.ps(self.iy) + other.ky * vm.ps(self.jy) + other.kz * vm.ps(self.ky),
.kz = other.kx * vm.ps(self.iz) + other.ky * vm.ps(self.jz) + other.kz * vm.ps(self.kz),
.kw = vm.ps(0),
.tx = other.tx * vm.ps(self.tx) + other.ty * vm.ps(self.jx) + other.tz * vm.ps(self.kx) + vm.ps(self.tx),
.ty = other.tx * vm.ps(self.ty) + other.ty * vm.ps(self.jy) + other.tz * vm.ps(self.ky) + vm.ps(self.ty),
.tz = other.tx * vm.ps(self.tz) + other.ty * vm.ps(self.jz) + other.tz * vm.ps(self.kz) + vm.ps(self.tz),
.tw = vm.ps(1),
};
}
pub fn mulMatrixFull(self: Matrix4x4, other: Matrix4x4) Matrix4x4 {
return .{
.ix = other.ix * self.ix + other.iy * self.jx + other.iz * self.kx + other.iw * self.tx,
.iy = other.ix * self.iy + other.iy * self.jy + other.iz * self.ky + other.iw * self.ty,
.iz = other.ix * self.iz + other.iy * self.jz + other.iz * self.kz + other.iw * self.tz,
.iw = other.ix * self.iw + other.iy * self.jw + other.iz * self.kw + other.iw * self.tw,
.jx = other.jx * self.ix + other.jy * self.jx + other.jz * self.kx + other.jw * self.tx,
.jy = other.jx * self.iy + other.jy * self.jy + other.jz * self.ky + other.jw * self.ty,
.jz = other.jx * self.iz + other.jy * self.jz + other.jz * self.kz + other.jw * self.tz,
.jw = other.jx * self.iw + other.jy * self.jw + other.jz * self.kw + other.jw * self.tw,
.kx = other.kx * self.ix + other.ky * self.jx + other.kz * self.kx + other.kw * self.tx,
.ky = other.kx * self.iy + other.ky * self.jy + other.kz * self.ky + other.kw * self.ty,
.kz = other.kx * self.iz + other.ky * self.jz + other.kz * self.kz + other.kw * self.tz,
.kw = other.kx * self.iw + other.ky * self.jw + other.kz * self.kw + other.kw * self.tw,
.tx = other.tx * self.ix + other.ty * self.jx + other.tz * self.kx + other.tw * self.tx,
.ty = other.tx * self.iy + other.ty * self.jy + other.tz * self.ky + other.tw * self.ty,
.tz = other.tx * self.iz + other.ty * self.jz + other.tz * self.kz + other.tw * self.tz,
.tw = other.tx * self.iw + other.ty * self.jw + other.tz * self.kw + other.tw * self.tw,
};
}
// TODO Move to vm.Matrix4x4x8
pub fn mulMatrixFull_x8(self: Matrix4x4, other: vm.Matrix4x4x8) vm.Matrix4x4x8 {
return .{
.ix = other.ix * vm.ps(self.ix) + other.iy * vm.ps(self.jx) + other.iz * vm.ps(self.kx) + other.iw * vm.ps(self.tx),
.iy = other.ix * vm.ps(self.iy) + other.iy * vm.ps(self.jy) + other.iz * vm.ps(self.ky) + other.iw * vm.ps(self.ty),
.iz = other.ix * vm.ps(self.iz) + other.iy * vm.ps(self.jz) + other.iz * vm.ps(self.kz) + other.iw * vm.ps(self.tz),
.iw = other.ix * vm.ps(self.iw) + other.iy * vm.ps(self.jw) + other.iz * vm.ps(self.kw) + other.iw * vm.ps(self.tw),
.jx = other.jx * vm.ps(self.ix) + other.jy * vm.ps(self.jx) + other.jz * vm.ps(self.kx) + other.jw * vm.ps(self.tx),
.jy = other.jx * vm.ps(self.iy) + other.jy * vm.ps(self.jy) + other.jz * vm.ps(self.ky) + other.jw * vm.ps(self.ty),
.jz = other.jx * vm.ps(self.iz) + other.jy * vm.ps(self.jz) + other.jz * vm.ps(self.kz) + other.jw * vm.ps(self.tz),
.jw = other.jx * vm.ps(self.iw) + other.jy * vm.ps(self.jw) + other.jz * vm.ps(self.kw) + other.jw * vm.ps(self.tw),
.kx = other.kx * vm.ps(self.ix) + other.ky * vm.ps(self.jx) + other.kz * vm.ps(self.kx) + other.kw * vm.ps(self.tx),
.ky = other.kx * vm.ps(self.iy) + other.ky * vm.ps(self.jy) + other.kz * vm.ps(self.ky) + other.kw * vm.ps(self.ty),
.kz = other.kx * vm.ps(self.iz) + other.ky * vm.ps(self.jz) + other.kz * vm.ps(self.kz) + other.kw * vm.ps(self.tz),
.kw = other.kx * vm.ps(self.iw) + other.ky * vm.ps(self.jw) + other.kz * vm.ps(self.kw) + other.kw * vm.ps(self.tw),
.tx = other.tx * vm.ps(self.ix) + other.ty * vm.ps(self.jx) + other.tz * vm.ps(self.kx) + other.tw * vm.ps(self.tx),
.ty = other.tx * vm.ps(self.iy) + other.ty * vm.ps(self.jy) + other.tz * vm.ps(self.ky) + other.tw * vm.ps(self.ty),
.tz = other.tx * vm.ps(self.iz) + other.ty * vm.ps(self.jz) + other.tz * vm.ps(self.kz) + other.tw * vm.ps(self.tz),
.tw = other.tx * vm.ps(self.iw) + other.ty * vm.ps(self.jw) + other.tz * vm.ps(self.kw) + other.tw * vm.ps(self.tw),
};
}
// INVERSION DERIVATION (affine and orthonormal case)
//
// We assume the matrix looks like so:
//
// ⎡ix jx kx tx⎤
// ⎢iy jy ky ty⎥
// A = ⎢iz jz kz tz⎥
// ⎣ 0 0 0 1⎦
//
// Then:
// ⎡ix jx kx⎤
// det A = det ⎢iy jy ky⎥
// ⎣iz jz kz⎦
//
// ⎡ ⎡jy ky ty⎤ ⎡iy ky ty⎤ ⎡iy jy ty⎤ ⎡iy jy ky⎤⎤T
// ⎢ det ⎢jz kz tz⎥ det ⎢iz kz tz⎥ det ⎢iz jz tz⎥ det ⎢iz jz kz⎥⎥
// ⎢ ⎣ 0 0 1⎦ ⎣ 0 0 1⎦ ⎣ 0 0 1⎦ ⎣ 0 0 0⎦⎥
// ⎢ ⎡jx kx tx⎤ ⎡ix kx tx⎤ ⎡ix jx tx⎤ ⎡ix jx kx⎤⎥
// ⎢det ⎢jz kz tz⎥ det ⎢iz kz tz⎥ det ⎢iz jz tz⎥ det ⎢iz jz kz⎥⎥
// 1 ⎢ ⎣ 0 0 1⎦ ⎣ 0 0 1⎦ ⎣ 0 0 1⎦ ⎣ 0 0 0⎦⎥
// inv A = ⎯⎯⎯⎯⎯ ⎢ ⎡jx kx tx⎤ ⎡ix kx tx⎤ ⎡ix jx tx⎤ ⎡ix jx kx⎤⎥
// det A ⎢ det ⎢jy ky ty⎥ det ⎢iy ky ty⎥ det ⎢iy jy ty⎥ det ⎢iy jy ky⎥⎥
// ⎢ ⎣ 0 0 1⎦ ⎣ 0 0 1⎦ ⎣ 0 0 1⎦ ⎣ 0 0 0⎦⎥
// ⎢ ⎡jx kx tx⎤ ⎡ix kx tx⎤ ⎡ix jx tx⎤ ⎡ix jx kx⎤⎥
// ⎢det ⎢jy ky ty⎥ det ⎢iy ky ty⎥ det ⎢iy jy ty⎥ det ⎢iy jy ky⎥⎥
// ⎣ ⎣jz kz tz⎦ ⎣iz kz tz⎦ ⎣iz jz tz⎦ ⎣iz jz kz⎦⎦
//
// ⎡ ⎡kx jx tx⎤⎤
// ⎢jy · kz ky · jz kx · jz jx · kz jx · ky kx · jy det ⎢ky jy ty⎥⎥
// ⎢ ⎣kz jz tz⎦⎥
// ⎢ ⎡ix kx tx⎤⎥
// 1 ⎢ky · iz iy · kz ix · kz kx · iz kx · iy ix · ky det ⎢iy ky ty⎥⎥
// inv A = ⎯⎯⎯⎯⎯ ⎢ ⎣iz kz tz⎦⎥
// det A ⎢ ⎡jx ix tx⎤⎥
// ⎢iy · jz jy · iz jx · iz ix · jz ix · jy jx · iy det ⎢jy iy ty⎥⎥
// ⎢ ⎣jz iz tz⎦⎥
// ⎣ 0 0 0 det A ⎦
//
// After multiplying by 1 / (det A), the fourth row becomes [0 0 0 1].
// When A is orthonormal, we can assume det A = 1.
pub fn inverseOrthonormal(self: Matrix4x4) Matrix4x4 {
std.debug.assert(self.iw == 0 and self.jw == 0 and self.kw == 0 and self.tw == 1);
const ix = self.ix;
const iy = self.jx;
const iz = self.kx;
const jx = self.iy;
const jy = self.jy;
const jz = self.ky;
const kx = self.iz;
const ky = self.jz;
const kz = self.kz;
return .{
.ix = ix,
.iy = iy,
.iz = iz,
.iw = 0,
.jx = jx,
.jy = jy,
.jz = jz,
.jw = 0,
.kx = kx,
.ky = ky,
.kz = kz,
.kw = 0,
.tx = -(self.tx * ix + self.ty * jx + self.tz * kx),
.ty = -(self.tx * iy + self.ty * jy + self.tz * ky),
.tz = -(self.tx * iz + self.ty * jz + self.tz * kz),
.tw = 1,
};
}
pub fn inverseAffine(self: Matrix4x4) Matrix4x4 {
std.debug.assert(self.iw == 0 and self.jw == 0 and self.kw == 0 and self.tw == 1);
const inv_det = 1.0 / (
// zig fmt: off
self.ix * (self.jy * self.kz - self.ky * self.jz) +
self.jx * (self.ky * self.iz - self.iy * self.kz) +
self.kx * (self.iy * self.jz - self.iy * self.jz)
// zig fmt: on
);
const ix = self.jy * self.kz - self.ky * self.jz;
const iy = self.ky * self.iz - self.iy * self.kz;
const iz = self.iy * self.jz - self.jy * self.iz;
const jx = self.kx * self.jz - self.jx * self.kz;
const jy = self.ix * self.kz - self.kx * self.iz;
const jz = self.jx * self.iz - self.ix * self.jz;
const kx = self.jx * self.ky - self.kx * self.jy;
const ky = self.kx * self.iy - self.ix * self.ky;
const kz = self.ix * self.jy - self.jx * self.iy;
return .{
.ix = inv_det * ix,
.iy = inv_det * iy,
.iz = inv_det * iz,
.iw = 0,
.jx = inv_det * jx,
.jy = inv_det * jy,
.jz = inv_det * jz,
.jw = 0,
.kx = inv_det * kx,
.ky = inv_det * ky,
.kz = inv_det * kz,
.kw = 0,
.tx = -inv_det * (self.tx * ix + self.ty * jx + self.tz * kx),
.ty = -inv_det * (self.tx * iy + self.ty * jy + self.tz * ky),
.tz = -inv_det * (self.tx * iz + self.ty * jz + self.tz * kz),
.tw = 1,
};
}
// DETERMINANT DERIVATION (full case)
//
// ⎡ix jx kx tx⎤
// ⎢iy jy ky ty⎥
// det A = det ⎢iz jz kz tz⎥
// ⎣iw jw kw tw⎦
//
// ⎡jy ky ty⎤ ⎡iy ky ty⎤ ⎡iy jy ty⎤ ⎡iy jy ky⎤
// det A = ix · det ⎢jz kz tz⎥ jx · det ⎢iz kz tz⎥ + kx · det ⎢iz jz tz⎥ tx · det ⎢iz jz kz⎥
// ⎣jw kw tw⎦ ⎣iw kw tw⎦ ⎣iw jw tw⎦ ⎣iw jw kw⎦
//
// ⎛ ⎡kz tz⎤ ⎡jz tz⎤ ⎡jz kz⎤⎞
// det A = ix · ⎝jy · det ⎣kw tw⎦ ky · det ⎣jw tw⎦ + ty · det ⎣jw kw⎦⎠ +
//
// ⎛ ⎡kz tz⎤ ⎡iz tz⎤ ⎡iz kz⎤⎞
// jx · ⎝iy · det ⎣kw tw⎦ ky · det ⎣iw tw⎦ + ty · det ⎣iw kw⎦⎠ +
//
// ⎛ ⎡jz tz⎤ ⎡iz tz⎤ ⎡iz jz⎤⎞
// + kx · ⎝iy · det ⎣jw tw⎦ jy · det ⎣iw tw⎦ + ty · det ⎣iw jw⎦⎠ +
//
// ⎛ ⎡jz kz⎤ ⎡iz kz⎤ ⎡iz jz⎤⎞
// tx · ⎝iy · det ⎣jw kw⎦ jy · det ⎣iw kw⎦ + ky · det ⎣iw jw⎦⎠
pub fn inverseFull(self: Matrix4x4) Matrix4x4 {
const iy_jw = self.iy * self.jw - self.jy * self.iw;
const iy_jz = self.iy * self.jz - self.jy * self.iz;
const iy_kz = self.iy * self.kz - self.ky * self.iz;
const iy_kw = self.iy * self.kw - self.ky * self.iw;
const iy_tz = self.iy * self.tz - self.ty * self.iz;
const iy_tw = self.iy * self.tw - self.ty * self.iw;
const iz_jw = self.iz * self.jw - self.jz * self.iw;
const iz_kw = self.iz * self.kw - self.kz * self.iw;
const iz_tw = self.iz * self.tw - self.tz * self.iw;
const jy_kz = self.jy * self.kz - self.ky * self.jz;
const jy_kw = self.jy * self.kw - self.ky * self.jw;
const jy_tw = self.jy * self.tw - self.ty * self.jw;
const jy_tz = self.jy * self.tz - self.ty * self.jz;
const jz_kw = self.jz * self.kw - self.kz * self.jw;
const jz_tw = self.jz * self.tw - self.tz * self.jw;
const ky_tz = self.ky * self.tz - self.ty * self.kz;
const ky_tw = self.ky * self.tw - self.ty * self.kw;
const kz_tw = self.kz * self.tw - self.tz * self.kw;
const det_ix = self.jy * kz_tw - self.ky * jz_tw + self.ty * jz_kw;
const det_jx = self.iy * kz_tw - self.ky * iz_tw + self.ty * iz_kw;
const det_kx = self.iy * jz_tw - self.jy * iz_tw + self.ty * iz_jw;
const det_tx = self.iy * jz_kw - self.jy * iz_kw + self.ky * iz_jw;
const det_iy = self.jx * kz_tw - self.kx * jz_tw + self.tx * jz_kw;
const det_jy = self.ix * kz_tw - self.kx * iz_tw + self.tx * iz_kw;
const det_ky = self.ix * jz_tw - self.jz * iz_tw + self.tx * iz_jw;
const det_ty = self.ix * jz_kw - self.jx * iz_kw + self.kx * iz_jw;
const det_iz = self.jx * ky_tw - self.kx * jy_tw + self.tx * jy_kw;
const det_jz = self.ix * ky_tw - self.kx * iy_tw + self.tx * iy_kw;
const det_kz = self.ix * jy_tw - self.jx * iy_tw + self.tx * iy_jw;
const det_tz = self.ix * jy_kw - self.jx * iy_kw + self.kx * iy_jw;
const det_iw = self.jx * ky_tz - self.kx * jy_tz + self.tx * jy_kz;
const det_jw = self.ix * ky_tz - self.kx * iy_tz + self.tx * iy_kz;
const det_kw = self.ix * jy_tz - self.jx * iy_tz + self.tx * iy_jz;
const det_tw = self.ix * jy_kz - self.jx * iy_kz + self.kx * iy_jz;
const det = self.ix * det_ix - self.jx * det_jx + self.kx * det_kx - self.tx * det_tx;
const inv_det = 1.0 / det;
return .{
// zig fmt: off
.ix = inv_det * det_ix, .iy = -inv_det * det_jx, .iz = inv_det * det_kx, .iw = -inv_det * det_tx,
.jx = -inv_det * det_iy, .jy = inv_det * det_jy, .jz = -inv_det * det_ky, .jw = inv_det * det_ty,
.kx = inv_det * det_iz, .ky = -inv_det * det_jz, .kz = inv_det * det_kz, .kw = -inv_det * det_tz,
.tx = -inv_det * det_iw, .ty = inv_det * det_jw, .tz = -inv_det * det_kw, .tw = inv_det * det_tw,
// zig fmt: on
};
}
};

View File

@@ -1,2 +1,779 @@
const std = @import("std");
const vm = @import("root");
const vm = @import("../root.zig");
pub const Matrix4x4x8 = extern struct {
// zig fmt: off
ix: vm.f32x8, iy: vm.f32x8, iz: vm.f32x8, iw: vm.f32x8,
jx: vm.f32x8, jy: vm.f32x8, jz: vm.f32x8, jw: vm.f32x8,
kx: vm.f32x8, ky: vm.f32x8, kz: vm.f32x8, kw: vm.f32x8,
tx: vm.f32x8, ty: vm.f32x8, tz: vm.f32x8, tw: vm.f32x8,
// zig fmt: on
pub const identity = initSingle(
// zig fmt: off
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
// zig fmt: on
);
// --- INIT ----------------------------------------------------------------
pub inline fn init(
// zig fmt: off
ix: vm.f32x8, iy: vm.f32x8, iz: vm.f32x8, iw: vm.f32x8,
jx: vm.f32x8, jy: vm.f32x8, jz: vm.f32x8, jw: vm.f32x8,
kx: vm.f32x8, ky: vm.f32x8, kz: vm.f32x8, kw: vm.f32x8,
tx: vm.f32x8, ty: vm.f32x8, tz: vm.f32x8, tw: vm.f32x8,
// zig fmt: on
) Matrix4x4x8 {
return .{
// zig fmt: off
.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,
// zig fmt: on
};
}
pub inline fn initSingle(
// zig fmt: off
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,
// zig fmt: on
) Matrix4x4x8 {
return .{
// zig fmt: off
.ix = vm.ps(ix), .iy = vm.ps(iy), .iz = vm.ps(iz), .iw = vm.ps(iw),
.jx = vm.ps(jx), .jy = vm.ps(jy), .jz = vm.ps(jz), .jw = vm.ps(jw),
.kx = vm.ps(kx), .ky = vm.ps(ky), .kz = vm.ps(kz), .kw = vm.ps(kw),
.tx = vm.ps(tx), .ty = vm.ps(ty), .tz = vm.ps(tz), .tw = vm.ps(tw),
// zig fmt: on
};
}
pub inline fn initVersors(i: vm.Vector4x8, j: vm.Vector4x8, k: vm.Vector4x8, t: vm.Vector4x8) Matrix4x4x8 {
return .{
// zig fmt: off
.ix = i.x, .iy = i.y, .iz = i.z, .iw = i.w,
.jx = j.x, .jy = j.y, .jz = j.z, .jw = j.w,
.kx = k.x, .ky = k.y, .kz = k.z, .kw = k.w,
.tx = t.x, .ty = t.y, .tz = t.z, .tw = t.w,
// zig fmt: on
};
}
pub inline fn initVersorsSingle(i: vm.Vector4, j: vm.Vector4, k: vm.Vector4, t: vm.Vector4) Matrix4x4x8 {
return .{
// zig fmt: off
.ix = vm.ps(i.x), .iy = vm.ps(i.y), .iz = vm.ps(i.z), .iw = vm.ps(i.w),
.jx = vm.ps(j.x), .jy = vm.ps(j.y), .jz = vm.ps(j.z), .jw = vm.ps(j.w),
.kx = vm.ps(k.x), .ky = vm.ps(k.y), .kz = vm.ps(k.z), .kw = vm.ps(k.w),
.tx = vm.ps(t.x), .ty = vm.ps(t.y), .tz = vm.ps(t.z), .tw = vm.ps(t.w),
// zig fmt: on
};
}
pub inline fn initTranslation(t: vm.Vector3x8) Matrix4x4x8 {
return .{
// zig fmt: off
.ix = vm.ps(1), .iy = vm.ps(0), .iz = vm.ps(0), .iw = vm.ps(0),
.jx = vm.ps(0), .jy = vm.ps(1), .jz = vm.ps(0), .jw = vm.ps(0),
.kx = vm.ps(0), .ky = vm.ps(0), .kz = vm.ps(1), .kw = vm.ps(0),
.tx = t.x, .ty = t.y, .tz = t.z, .tw = vm.ps(1),
// zig fmt: on
};
}
pub inline fn initTranslationSingle(t: vm.Vector3) Matrix4x4x8 {
return .{
// zig fmt: off
.ix = vm.ps(1), .iy = vm.ps(0), .iz = vm.ps(0), .iw = vm.ps(0),
.jx = vm.ps(0), .jy = vm.ps(1), .jz = vm.ps(0), .jw = vm.ps(0),
.kx = vm.ps(0), .ky = vm.ps(0), .kz = vm.ps(1), .kw = vm.ps(0),
.tx = vm.ps(t.x), .ty = vm.ps(t.y), .tz = vm.ps(t.z), .tw = vm.ps(1),
// zig fmt: on
};
}
pub inline fn initRotation(q: vm.Quaternion_x8) Matrix4x4x8 {
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 .{
// zig fmt: off
.ix = vm.ps(1) - vm.ps(2) * (yy + zz), .iy = vm.ps(2) * (xy - zw), .iz = vm.ps(2) * (xz + yw), .iw = vm.ps(0),
.jx = vm.ps(2) * (xy + zw), .jy = vm.ps(1) - vm.ps(2) * (xx + zz), .jz = vm.ps(2) * (yz - xw), .jw = vm.ps(0),
.kx = vm.ps(2) * (xz - yw), .ky = vm.ps(2) * (yz + xw), .kz = vm.ps(1) - vm.ps(2) * (xx + yy), .kw = vm.ps(0),
.tx = vm.ps(0), .ty = vm.ps(0), .tz = vm.ps(0), .tw = vm.ps(1),
// zig fmt: on
};
}
pub inline fn initRotationSingle(q: vm.Quaternion) Matrix4x4x8 {
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 .{
// zig fmt: off
.ix = vm.ps(1 - 2 * (yy + zz)), .iy = vm.ps(2 * (xy - zw)), .iz = vm.ps(2 * (xz + yw)), .iw = vm.ps(0),
.jx = vm.ps(2 * (xy + zw)), .jy = vm.ps(1 - 2 * (xx + zz)), .jz = vm.ps(2 * (yz - xw)), .jw = vm.ps(0),
.kx = vm.ps(2 * (xz - yw)), .ky = vm.ps(2 * (yz + xw)), .kz = vm.ps(1 - 2 * (xx + yy)), .kw = vm.ps(0),
.tx = vm.ps(0), .ty = vm.ps(0), .tz = vm.ps(0), .tw = vm.ps(1),
// zig fmt: on
};
}
pub inline fn initScale(s: vm.Vector3x8) Matrix4x4x8 {
return .{
// zig fmt: off
.ix = s.x, .iy = vm.ps(0), .iz = vm.ps(0), .iw = vm.ps(0),
.jx = vm.ps(0), .jy = s.y, .jz = vm.ps(0), .jw = vm.ps(0),
.kx = vm.ps(0), .ky = vm.ps(0), .kz = s.z, .kw = vm.ps(0),
.tx = vm.ps(0), .ty = vm.ps(0), .tz = vm.ps(0), .tw = vm.ps(1),
// zig fmt: on
};
}
pub inline fn initScaleSingle(s: vm.Vector3) Matrix4x4x8 {
return .{
// zig fmt: off
.ix = vm.ps(s.x), .iy = vm.ps(0), .iz = vm.ps(0), .iw = vm.ps(0),
.jx = vm.ps(0), .jy = vm.ps(s.y), .jz = vm.ps(0), .jw = vm.ps(0),
.kx = vm.ps(0), .ky = vm.ps(0), .kz = vm.ps(s.z), .kw = vm.ps(0),
.tx = vm.ps(0), .ty = vm.ps(0), .tz = vm.ps(0), .tw = vm.ps(1),
// zig fmt: on
};
}
pub inline fn initTranslationRotation(t: vm.Vector3x8, q: vm.Quaternion_x8) Matrix4x4x8 {
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 .{
// zig fmt: off
.ix = vm.ps(1) - vm.ps(2) * (yy + zz), .iy = vm.ps(2) * (xy - zw), .iz = vm.ps(2) * (xz + yw), .iw = vm.ps(0),
.jx = vm.ps(2) * (xy + zw), .jy = vm.ps(1) - vm.ps(2) * (xx + zz), .jz = vm.ps(2) * (yz - xw), .jw = vm.ps(0),
.kx = vm.ps(2) * (xz - yw), .ky = vm.ps(2) * (yz + xw), .kz = vm.ps(1) - vm.ps(2) * (xx + yy), .kw = vm.ps(0),
.tx = t.x, .ty = t.y, .tz = t.z, .tw = vm.ps(1),
// zig fmt: on
};
}
pub inline fn initTranslationRotationSingle(t: vm.Vector3, q: vm.Quaternion) Matrix4x4x8 {
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 .{
// zig fmt: off
.ix = vm.ps(1 - 2 * (yy + zz)), .iy = vm.ps(2 * (xy - zw)), .iz = vm.ps(2 * (xz + yw)), .iw = vm.ps(0),
.jx = vm.ps(2 * (xy + zw)), .jy = vm.ps(1 - 2 * (xx + zz)), .jz = vm.ps(2 * (yz - xw)), .jw = vm.ps(0),
.kx = vm.ps(2 * (xz - yw)), .ky = vm.ps(2 * (yz + xw)), .kz = vm.ps(1 - 2 * (xx + yy)), .kw = vm.ps(0),
.tx = vm.ps(t.x), .ty = vm.ps(t.y), .tz = vm.ps(t.z), .tw = vm.ps(1),
// zig fmt: on
};
}
pub inline fn initTranslationScale(t: vm.Vector3x8, s: vm.Vector3x8) Matrix4x4x8 {
return .{
// zig fmt: off
.ix = s.x, .iy = vm.ps(0), .iz = vm.ps(0), .iw = vm.ps(0),
.jx = vm.ps(0), .jy = s.y, .jz = vm.ps(0), .jw = vm.ps(0),
.kx = vm.ps(0), .ky = vm.ps(0), .kz = s.z, .kw = vm.ps(0),
.tx = t.x, .ty = t.y, .tz = t.z, .tw = vm.ps(1),
// zig fmt: on
};
}
pub inline fn initTranslationScaleSingle(t: vm.Vector3, s: vm.Vector3) Matrix4x4x8 {
return .{
// zig fmt: off
.ix = vm.ps(s.x), .iy = vm.ps(0), .iz = vm.ps(0), .iw = vm.ps(0),
.jx = vm.ps(0), .jy = vm.ps(s.y), .jz = vm.ps(0), .jw = vm.ps(0),
.kx = vm.ps(0), .ky = vm.ps(0), .kz = vm.ps(s.z), .kw = vm.ps(0),
.tx = vm.ps(t.x), .ty = vm.ps(t.y), .tz = vm.ps(t.z), .tw = vm.ps(1),
// zig fmt: on
};
}
pub inline fn initTranslationRotationScale(t: vm.Vector3x8, q: vm.Quaternion_x8, s: vm.Vector3x8) Matrix4x4x8 {
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 .{
// zig fmt: off
.ix = s.x * (vm.ps(1) - vm.ps(2) * (yy + zz)), .iy = s.x * vm.ps(2) * (xy - zw), .iz = s.x * vm.ps(2) * (xz + yw), .iw = vm.ps(0),
.jx = s.y * vm.ps(2) * (xy + zw), .jy = s.y * (vm.ps(1) - vm.ps(2) * (xx + zz)), .jz = s.y * vm.ps(2) * (yz - xw), .jw = vm.ps(0),
.kx = s.z * vm.ps(2) * (xz - yw), .ky = s.z * vm.ps(2) * (yz + xw), .kz = s.z * (vm.ps(1) - vm.ps(2) * (xx + yy)), .kw = vm.ps(0),
.tx = t.x, .ty = t.y, .tz = t.z, .tw = vm.ps(1),
// zig fmt: on
};
}
pub inline fn initTranslationRotationScaleSingle(t: vm.Vector3, q: vm.Quaternion, s: vm.Vector3) Matrix4x4x8 {
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 .{
// zig fmt: off
.ix = vm.ps(s.x * (1 - 2 * (yy + zz))), .iy = vm.ps(s.x * 2 * (xy - zw)), .iz = vm.ps(s.x * 2 * (xz + yw)), .iw = vm.ps(0),
.jx = vm.ps(s.y * 2 * (xy + zw)), .jy = vm.ps(s.y * (1 - 2 * (xx + zz))), .jz = vm.ps(s.y * 2 * (yz - xw)), .jw = vm.ps(0),
.kx = vm.ps(s.z * 2 * (xz - yw)), .ky = vm.ps(s.z * 2 * (yz + xw)), .kz = vm.ps(s.z * (1 - 2 * (xx + yy))), .kw = vm.ps(0),
.tx = vm.ps(t.x), .ty = vm.ps(t.y), .tz = vm.ps(t.z), .tw = vm.ps(1),
// zig fmt: on
};
}
pub inline fn initArrayOfMatrices(matrices: [8]vm.Matrix4x4) Matrix4x4x8 {
const vector: @Vector(128, f32) = @as([128]f32, @bitCast(matrices));
return .{
.ix = @shuffle(f32, vector, undefined, [_]i32{ 0, 16, 32, 48, 64, 80, 96, 112 }),
.iy = @shuffle(f32, vector, undefined, [_]i32{ 1, 17, 33, 49, 65, 81, 97, 113 }),
.iz = @shuffle(f32, vector, undefined, [_]i32{ 2, 18, 34, 50, 66, 82, 98, 114 }),
.iw = @shuffle(f32, vector, undefined, [_]i32{ 3, 19, 35, 51, 67, 83, 99, 115 }),
.jx = @shuffle(f32, vector, undefined, [_]i32{ 4, 20, 36, 52, 68, 84, 100, 116 }),
.jy = @shuffle(f32, vector, undefined, [_]i32{ 5, 21, 37, 53, 69, 85, 101, 117 }),
.jz = @shuffle(f32, vector, undefined, [_]i32{ 6, 22, 38, 54, 70, 86, 102, 118 }),
.jw = @shuffle(f32, vector, undefined, [_]i32{ 7, 23, 39, 55, 71, 87, 103, 119 }),
.kx = @shuffle(f32, vector, undefined, [_]i32{ 8, 24, 40, 56, 72, 88, 104, 120 }),
.ky = @shuffle(f32, vector, undefined, [_]i32{ 9, 25, 41, 57, 73, 89, 105, 121 }),
.kz = @shuffle(f32, vector, undefined, [_]i32{ 10, 26, 42, 58, 74, 90, 106, 122 }),
.kw = @shuffle(f32, vector, undefined, [_]i32{ 11, 27, 43, 59, 75, 91, 107, 123 }),
.tx = @shuffle(f32, vector, undefined, [_]i32{ 12, 28, 44, 60, 76, 92, 108, 124 }),
.ty = @shuffle(f32, vector, undefined, [_]i32{ 13, 29, 45, 61, 77, 93, 109, 125 }),
.tz = @shuffle(f32, vector, undefined, [_]i32{ 14, 30, 46, 62, 78, 94, 110, 126 }),
.tw = @shuffle(f32, vector, undefined, [_]i32{ 15, 31, 47, 63, 79, 95, 111, 127 }),
};
}
pub inline fn splat(matrix: vm.Matrix4x4) Matrix4x4x8 {
return .{
// zig fmt: off
.ix = vm.ps(matrix.ix), .iy = vm.ps(matrix.iy), .iz = vm.ps(matrix.iz), .iw = vm.ps(matrix.iw),
.jx = vm.ps(matrix.jx), .jy = vm.ps(matrix.jy), .jz = vm.ps(matrix.jz), .jw = vm.ps(matrix.jw),
.kx = vm.ps(matrix.kx), .ky = vm.ps(matrix.ky), .kz = vm.ps(matrix.kz), .kw = vm.ps(matrix.kw),
.tx = vm.ps(matrix.tx), .ty = vm.ps(matrix.ty), .tz = vm.ps(matrix.tz), .tw = vm.ps(matrix.tw),
// zig fmt: on
};
}
// --- CONVERSION ----------------------------------------------------------
pub inline fn asArrayOfMatrices(self: Matrix4x4x8) [8]vm.Matrix4x4 {
const vector: @Vector(128, f32) = self.ix ++ self.iy ++ self.iz ++ self.iw ++ self.jx ++ self.jy ++ self.jz ++ self.jw ++ self.kx ++ self.ky ++ self.kz ++ self.kw ++ self.tx ++ self.ty ++ self.tz ++ self.tw;
return @bitCast(@as([128]f32, @shuffle(f32, vector, undefined, [_]i32{
0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120,
1, 9, 17, 25, 33, 41, 49, 57, 65, 73, 81, 89, 97, 105, 113, 121,
2, 10, 18, 26, 34, 42, 50, 58, 66, 74, 82, 90, 98, 106, 114, 122,
3, 11, 19, 27, 35, 43, 51, 59, 67, 75, 83, 91, 99, 107, 115, 123,
4, 12, 20, 28, 36, 44, 52, 60, 68, 76, 84, 92, 100, 108, 116, 124,
5, 13, 21, 29, 37, 45, 53, 61, 69, 77, 85, 93, 101, 109, 117, 125,
6, 14, 22, 30, 38, 46, 54, 62, 70, 78, 86, 94, 102, 110, 118, 126,
7, 15, 23, 31, 39, 47, 55, 63, 71, 79, 87, 95, 103, 111, 119, 127,
})));
}
pub inline fn unpack(self: Matrix4x4x8) [16]vm.f32x8 {
return .{ self.ix, self.iy, self.iz, self.iw, self.jx, self.jy, self.jz, self.jw, self.kx, self.ky, self.kz, self.kw, self.tx, self.ty, self.tz, self.tw };
}
// --- LOAD AND STORE ------------------------------------------------------
pub inline fn loadArrayOfMatrices(self: *Matrix4x4x8, array: *const [8]vm.Matrix4x4) void {
const vector: @Vector(128, f32) = @as(*const [128]f32, @ptrCast(array)).*;
self.ix = @shuffle(f32, vector, undefined, [_]i32{ 0, 16, 32, 48, 64, 80, 96, 112 });
self.iy = @shuffle(f32, vector, undefined, [_]i32{ 1, 17, 33, 49, 65, 81, 97, 113 });
self.iz = @shuffle(f32, vector, undefined, [_]i32{ 2, 18, 34, 50, 66, 82, 98, 114 });
self.iw = @shuffle(f32, vector, undefined, [_]i32{ 3, 19, 35, 51, 67, 83, 99, 115 });
self.jx = @shuffle(f32, vector, undefined, [_]i32{ 4, 20, 36, 52, 68, 84, 100, 116 });
self.jy = @shuffle(f32, vector, undefined, [_]i32{ 5, 21, 37, 53, 69, 85, 101, 117 });
self.jz = @shuffle(f32, vector, undefined, [_]i32{ 6, 22, 38, 54, 70, 86, 102, 118 });
self.jw = @shuffle(f32, vector, undefined, [_]i32{ 7, 23, 39, 55, 71, 87, 103, 119 });
self.kx = @shuffle(f32, vector, undefined, [_]i32{ 8, 24, 40, 56, 72, 88, 104, 120 });
self.ky = @shuffle(f32, vector, undefined, [_]i32{ 9, 25, 41, 57, 73, 89, 105, 121 });
self.kz = @shuffle(f32, vector, undefined, [_]i32{ 10, 26, 42, 58, 74, 90, 106, 122 });
self.kw = @shuffle(f32, vector, undefined, [_]i32{ 11, 27, 43, 59, 75, 91, 107, 123 });
self.tx = @shuffle(f32, vector, undefined, [_]i32{ 12, 28, 44, 60, 76, 92, 108, 124 });
self.ty = @shuffle(f32, vector, undefined, [_]i32{ 13, 29, 45, 61, 77, 93, 109, 125 });
self.tz = @shuffle(f32, vector, undefined, [_]i32{ 14, 30, 46, 62, 78, 94, 110, 126 });
self.tw = @shuffle(f32, vector, undefined, [_]i32{ 15, 31, 47, 63, 79, 95, 111, 127 });
}
pub inline fn storeArrayOfMatrices(self: *const Matrix4x4x8, array: *[8]vm.Matrix4x4) void {
const vector: @Vector(128, f32) = self.ix ++ self.iy ++ self.iz ++ self.iw ++ self.jx ++ self.jy ++ self.jz ++ self.jw ++ self.kx ++ self.ky ++ self.kz ++ self.kw ++ self.tx ++ self.ty ++ self.tz ++ self.tw;
@as(*[128]f32, @ptrCast(array)).* = @shuffle(f32, vector, undefined, [_]i32{
0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120,
1, 9, 17, 25, 33, 41, 49, 57, 65, 73, 81, 89, 97, 105, 113, 121,
2, 10, 18, 26, 34, 42, 50, 58, 66, 74, 82, 90, 98, 106, 114, 122,
3, 11, 19, 27, 35, 43, 51, 59, 67, 75, 83, 91, 99, 107, 115, 123,
4, 12, 20, 28, 36, 44, 52, 60, 68, 76, 84, 92, 100, 108, 116, 124,
5, 13, 21, 29, 37, 45, 53, 61, 69, 77, 85, 93, 101, 109, 117, 125,
6, 14, 22, 30, 38, 46, 54, 62, 70, 78, 86, 94, 102, 110, 118, 126,
7, 15, 23, 31, 39, 47, 55, 63, 71, 79, 87, 95, 103, 111, 119, 127,
});
}
// --- ACCESSORS -----------------------------------------------------------
pub inline fn getIVersor(self: Matrix4x4x8) vm.Vector4 {
return .{ .x = self.ix, .y = self.iy, .z = self.iz, .w = self.iw };
}
pub inline fn getJVersor(self: Matrix4x4x8) vm.Vector4 {
return .{ .x = self.jx, .y = self.jy, .z = self.jz, .w = self.jw };
}
pub inline fn getKVersor(self: Matrix4x4x8) vm.Vector4 {
return .{ .x = self.kx, .y = self.ky, .z = self.kz, .w = self.kw };
}
pub inline fn getTranslationVector(self: Matrix4x4x8) vm.Vector4 {
return .{ .x = self.tx, .y = self.ty, .z = self.tz, .w = self.tw };
}
// --- COMPONENT-WISE ------------------------------------------------------
pub inline fn add(self: Matrix4x4x8, other: Matrix4x4x8) Matrix4x4x8 {
return .{
.ix = self.ix + other.ix,
.iy = self.iy + other.iy,
.iz = self.iz + other.iz,
.iw = self.iw + other.iw,
.jx = self.jx + other.jx,
.jy = self.jy + other.jy,
.jz = self.jz + other.jz,
.jw = self.jw + other.jw,
.kx = self.kx + other.kx,
.ky = self.ky + other.ky,
.kz = self.kz + other.kz,
.kw = self.kw + other.kw,
.tx = self.tx + other.tx,
.ty = self.ty + other.ty,
.tz = self.tz + other.tz,
.tw = self.tw + other.tw,
};
}
pub inline fn sub(self: Matrix4x4x8, other: Matrix4x4x8) Matrix4x4x8 {
return .{
.ix = self.ix - other.ix,
.iy = self.iy - other.iy,
.iz = self.iz - other.iz,
.iw = self.iw - other.iw,
.jx = self.jx - other.jx,
.jy = self.jy - other.jy,
.jz = self.jz - other.jz,
.jw = self.jw - other.jw,
.kx = self.kx - other.kx,
.ky = self.ky - other.ky,
.kz = self.kz - other.kz,
.kw = self.kw - other.kw,
.tx = self.tx - other.tx,
.ty = self.ty - other.ty,
.tz = self.tz - other.tz,
.tw = self.tw - other.tw,
};
}
pub inline fn mulScalar(self: Matrix4x4x8, scalar: vm.f32x8) Matrix4x4x8 {
return .{
.ix = self.ix * scalar,
.iy = self.iy * scalar,
.iz = self.iz * scalar,
.iw = self.iw * scalar,
.jx = self.jx * scalar,
.jy = self.jy * scalar,
.jz = self.jz * scalar,
.jw = self.jw * scalar,
.kx = self.kx * scalar,
.ky = self.ky * scalar,
.kz = self.kz * scalar,
.kw = self.kw * scalar,
.tx = self.tx * scalar,
.ty = self.ty * scalar,
.tz = self.tz * scalar,
.tw = self.tw * scalar,
};
}
pub inline fn mulScalarSingle(self: Matrix4x4x8, scalar: f32) Matrix4x4x8 {
return .{
.ix = self.ix * vm.ps(scalar),
.iy = self.iy * vm.ps(scalar),
.iz = self.iz * vm.ps(scalar),
.iw = self.iw * vm.ps(scalar),
.jx = self.jx * vm.ps(scalar),
.jy = self.jy * vm.ps(scalar),
.jz = self.jz * vm.ps(scalar),
.jw = self.jw * vm.ps(scalar),
.kx = self.kx * vm.ps(scalar),
.ky = self.ky * vm.ps(scalar),
.kz = self.kz * vm.ps(scalar),
.kw = self.kw * vm.ps(scalar),
.tx = self.tx * vm.ps(scalar),
.ty = self.ty * vm.ps(scalar),
.tz = self.tz * vm.ps(scalar),
.tw = self.tw * vm.ps(scalar),
};
}
pub inline fn divScalar(self: Matrix4x4x8, scalar: vm.f32x8) Matrix4x4x8 {
return .{
.ix = self.ix / scalar,
.iy = self.iy / scalar,
.iz = self.iz / scalar,
.iw = self.iw / scalar,
.jx = self.jx / scalar,
.jy = self.jy / scalar,
.jz = self.jz / scalar,
.jw = self.jw / scalar,
.kx = self.kx / scalar,
.ky = self.ky / scalar,
.kz = self.kz / scalar,
.kw = self.kw / scalar,
.tx = self.tx / scalar,
.ty = self.ty / scalar,
.tz = self.tz / scalar,
.tw = self.tw / scalar,
};
}
pub inline fn divScalarSingle(self: Matrix4x4x8, scalar: f32) Matrix4x4x8 {
return .{
.ix = self.ix / vm.ps(scalar),
.iy = self.iy / vm.ps(scalar),
.iz = self.iz / vm.ps(scalar),
.iw = self.iw / vm.ps(scalar),
.jx = self.jx / vm.ps(scalar),
.jy = self.jy / vm.ps(scalar),
.jz = self.jz / vm.ps(scalar),
.jw = self.jw / vm.ps(scalar),
.kx = self.kx / vm.ps(scalar),
.ky = self.ky / vm.ps(scalar),
.kz = self.kz / vm.ps(scalar),
.kw = self.kw / vm.ps(scalar),
.tx = self.tx / vm.ps(scalar),
.ty = self.ty / vm.ps(scalar),
.tz = self.tz / vm.ps(scalar),
.tw = self.tw / vm.ps(scalar),
};
}
// --- TRANSFORM -----------------------------------------------------------
// TODO Move to vm.Vector3x8
pub inline fn transformPoint(self: Matrix4x4x8, p: vm.Vector3x8) vm.Vector3x8 {
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,
};
}
// TODO Move to vm.Vector3x8
pub inline fn transformPointSingle(self: Matrix4x4x8, p: vm.Vector3) vm.Vector3x8 {
return .{
.x = vm.ps(p.x) * self.ix + vm.ps(p.y) * self.jx + vm.ps(p.z) * self.kx + self.tx,
.y = vm.ps(p.x) * self.iy + vm.ps(p.y) * self.jy + vm.ps(p.z) * self.ky + self.ty,
.z = vm.ps(p.x) * self.iz + vm.ps(p.y) * self.jz + vm.ps(p.z) * self.kz + self.tz,
};
}
// TODO Move to vm.Vector3x8
pub inline fn transformVector(self: Matrix4x4x8, v: vm.Vector3x8) vm.Vector3x8 {
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,
};
}
// TODO Move to vm.Vector3x8
pub inline fn transformVectorSingle(self: Matrix4x4x8, v: vm.Vector3) vm.Vector3x8 {
return .{
.x = vm.ps(v.x) * self.ix + vm.ps(v.y) * self.jx + vm.ps(v.z) * self.kx,
.y = vm.ps(v.x) * self.iy + vm.ps(v.y) * self.jy + vm.ps(v.z) * self.ky,
.z = vm.ps(v.x) * self.iz + vm.ps(v.y) * self.jz + vm.ps(v.z) * self.kz,
};
}
// TODO Move to vm.Vector4x8
pub inline fn transformHomogeneous(self: Matrix4x4x8, h: vm.Vector4x8) vm.Vector4x8 {
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,
};
}
// TODO Move to vm.Vector4x8
pub inline fn transformHomogeneousSingle(self: Matrix4x4x8, h: vm.Vector4) vm.Vector4x8 {
return .{
.x = vm.ps(h.x) * self.ix + vm.ps(h.y) * self.jx + vm.ps(h.z) * self.kx + vm.ps(h.w) * self.tx,
.y = vm.ps(h.x) * self.iy + vm.ps(h.y) * self.jy + vm.ps(h.z) * self.ky + vm.ps(h.w) * self.ty,
.z = vm.ps(h.x) * self.iz + vm.ps(h.y) * self.jz + vm.ps(h.z) * self.kz + vm.ps(h.w) * self.tz,
.w = vm.ps(h.x) * self.iw + vm.ps(h.y) * self.jw + vm.ps(h.z) * self.kw + vm.ps(h.w) * self.tw,
};
}
// --- COMPOSE -------------------------------------------------------------
/// The caller asserts that W rows of all matrices are equal to [0 0 0 1].
pub fn mulMatrixAffine(self: Matrix4x4x8, other: Matrix4x4x8) Matrix4x4x8 {
std.debug.assert(@reduce(.And, (self.iw == vm.ps(0)) & (self.jw == vm.ps(0)) & (self.kw == vm.ps(0)) & (self.tw == vm.ps(1))));
std.debug.assert(@reduce(.And, (other.iw == vm.ps(0)) & (other.jw == vm.ps(0)) & (other.kw == vm.ps(0)) & (other.tw == vm.ps(1))));
return .{
.ix = other.ix * self.ix + other.iy * self.jx + other.iz * self.kx,
.iy = other.ix * self.iy + other.iy * self.jy + other.iz * self.ky,
.iz = other.ix * self.iz + other.iy * self.jz + other.iz * self.kz,
.iw = vm.ps(0),
.jx = other.jx * self.ix + other.jy * self.jx + other.jz * self.kx,
.jy = other.jx * self.iy + other.jy * self.jy + other.jz * self.ky,
.jz = other.jx * self.iz + other.jy * self.jz + other.jz * self.kz,
.jw = vm.ps(0),
.kx = other.kx * self.ix + other.ky * self.jx + other.kz * self.kx,
.ky = other.kx * self.iy + other.ky * self.jy + other.kz * self.ky,
.kz = other.kx * self.iz + other.ky * self.jz + other.kz * self.kz,
.kw = vm.ps(0),
.tx = other.tx * self.tx + other.ty * self.jx + other.tz * self.kx + self.tx,
.ty = other.tx * self.ty + other.ty * self.jy + other.tz * self.ky + self.ty,
.tz = other.tx * self.tz + other.ty * self.jz + other.tz * self.kz + self.tz,
.tw = vm.ps(1),
};
}
/// The caller asserts that W rows of all matrices are equal to [0 0 0 1].
pub fn mulMatrixAffineSingle(self: Matrix4x4x8, other: vm.Matrix4x4) vm.Matrix4x4x8 {
std.debug.assert(@reduce(.And, (self.iw == vm.ps(0)) & (self.jw == vm.ps(0)) & (self.kw == vm.ps(0)) & (self.tw == vm.ps(1))));
std.debug.assert(other.iw == 0 and other.jw == 0 and other.kw == 0 and other.tw == 1);
return .{
.ix = vm.ps(other.ix) * self.ix + vm.ps(other.iy) * self.jx + vm.ps(other.iz) * self.kx,
.iy = vm.ps(other.ix) * self.iy + vm.ps(other.iy) * self.jy + vm.ps(other.iz) * self.ky,
.iz = vm.ps(other.ix) * self.iz + vm.ps(other.iy) * self.jz + vm.ps(other.iz) * self.kz,
.iw = vm.ps(0),
.jx = vm.ps(other.jx) * self.ix + vm.ps(other.jy) * self.jx + vm.ps(other.jz) * self.kx,
.jy = vm.ps(other.jx) * self.iy + vm.ps(other.jy) * self.jy + vm.ps(other.jz) * self.ky,
.jz = vm.ps(other.jx) * self.iz + vm.ps(other.jy) * self.jz + vm.ps(other.jz) * self.kz,
.jw = vm.ps(0),
.kx = vm.ps(other.kx) * self.ix + vm.ps(other.ky) * self.jx + vm.ps(other.kz) * self.kx,
.ky = vm.ps(other.kx) * self.iy + vm.ps(other.ky) * self.jy + vm.ps(other.kz) * self.ky,
.kz = vm.ps(other.kx) * self.iz + vm.ps(other.ky) * self.jz + vm.ps(other.kz) * self.kz,
.kw = vm.ps(0),
.tx = vm.ps(other.tx) * self.tx + vm.ps(other.ty) * self.jx + vm.ps(other.tz) * self.kx + self.tx,
.ty = vm.ps(other.tx) * self.ty + vm.ps(other.ty) * self.jy + vm.ps(other.tz) * self.ky + self.ty,
.tz = vm.ps(other.tx) * self.tz + vm.ps(other.ty) * self.jz + vm.ps(other.tz) * self.kz + self.tz,
.tw = vm.ps(1),
};
}
pub fn mulMatrixFull(self: Matrix4x4x8, other: Matrix4x4x8) Matrix4x4x8 {
return .{
.ix = other.ix * self.ix + other.iy * self.jx + other.iz * self.kx + other.iw * self.tx,
.iy = other.ix * self.iy + other.iy * self.jy + other.iz * self.ky + other.iw * self.ty,
.iz = other.ix * self.iz + other.iy * self.jz + other.iz * self.kz + other.iw * self.tz,
.iw = other.ix * self.iw + other.iy * self.jw + other.iz * self.kw + other.iw * self.tw,
.jx = other.jx * self.ix + other.jy * self.jx + other.jz * self.kx + other.jw * self.tx,
.jy = other.jx * self.iy + other.jy * self.jy + other.jz * self.ky + other.jw * self.ty,
.jz = other.jx * self.iz + other.jy * self.jz + other.jz * self.kz + other.jw * self.tz,
.jw = other.jx * self.iw + other.jy * self.jw + other.jz * self.kw + other.jw * self.tw,
.kx = other.kx * self.ix + other.ky * self.jx + other.kz * self.kx + other.kw * self.tx,
.ky = other.kx * self.iy + other.ky * self.jy + other.kz * self.ky + other.kw * self.ty,
.kz = other.kx * self.iz + other.ky * self.jz + other.kz * self.kz + other.kw * self.tz,
.kw = other.kx * self.iw + other.ky * self.jw + other.kz * self.kw + other.kw * self.tw,
.tx = other.tx * self.ix + other.ty * self.jx + other.tz * self.kx + other.tw * self.tx,
.ty = other.tx * self.iy + other.ty * self.jy + other.tz * self.ky + other.tw * self.ty,
.tz = other.tx * self.iz + other.ty * self.jz + other.tz * self.kz + other.tw * self.tz,
.tw = other.tx * self.iw + other.ty * self.jw + other.tz * self.kw + other.tw * self.tw,
};
}
pub fn mulMatrixFullSingle(self: Matrix4x4x8, other: vm.Matrix4x4) vm.Matrix4x4x8 {
return .{
.ix = vm.ps(other.ix) * self.ix + vm.ps(other.iy) * self.jx + vm.ps(other.iz) * self.kx + vm.ps(other.iw) * self.tx,
.iy = vm.ps(other.ix) * self.iy + vm.ps(other.iy) * self.jy + vm.ps(other.iz) * self.ky + vm.ps(other.iw) * self.ty,
.iz = vm.ps(other.ix) * self.iz + vm.ps(other.iy) * self.jz + vm.ps(other.iz) * self.kz + vm.ps(other.iw) * self.tz,
.iw = vm.ps(other.ix) * self.iw + vm.ps(other.iy) * self.jw + vm.ps(other.iz) * self.kw + vm.ps(other.iw) * self.tw,
.jx = vm.ps(other.jx) * self.ix + vm.ps(other.jy) * self.jx + vm.ps(other.jz) * self.kx + vm.ps(other.jw) * self.tx,
.jy = vm.ps(other.jx) * self.iy + vm.ps(other.jy) * self.jy + vm.ps(other.jz) * self.ky + vm.ps(other.jw) * self.ty,
.jz = vm.ps(other.jx) * self.iz + vm.ps(other.jy) * self.jz + vm.ps(other.jz) * self.kz + vm.ps(other.jw) * self.tz,
.jw = vm.ps(other.jx) * self.iw + vm.ps(other.jy) * self.jw + vm.ps(other.jz) * self.kw + vm.ps(other.jw) * self.tw,
.kx = vm.ps(other.kx) * self.ix + vm.ps(other.ky) * self.jx + vm.ps(other.kz) * self.kx + vm.ps(other.kw) * self.tx,
.ky = vm.ps(other.kx) * self.iy + vm.ps(other.ky) * self.jy + vm.ps(other.kz) * self.ky + vm.ps(other.kw) * self.ty,
.kz = vm.ps(other.kx) * self.iz + vm.ps(other.ky) * self.jz + vm.ps(other.kz) * self.kz + vm.ps(other.kw) * self.tz,
.kw = vm.ps(other.kx) * self.iw + vm.ps(other.ky) * self.jw + vm.ps(other.kz) * self.kw + vm.ps(other.kw) * self.tw,
.tx = vm.ps(other.tx) * self.ix + vm.ps(other.ty) * self.jx + vm.ps(other.tz) * self.kx + vm.ps(other.tw) * self.tx,
.ty = vm.ps(other.tx) * self.iy + vm.ps(other.ty) * self.jy + vm.ps(other.tz) * self.ky + vm.ps(other.tw) * self.ty,
.tz = vm.ps(other.tx) * self.iz + vm.ps(other.ty) * self.jz + vm.ps(other.tz) * self.kz + vm.ps(other.tw) * self.tz,
.tw = vm.ps(other.tx) * self.iw + vm.ps(other.ty) * self.jw + vm.ps(other.tz) * self.kw + vm.ps(other.tw) * self.tw,
};
}
pub fn inverseOrthonormal(self: Matrix4x4x8) Matrix4x4x8 {
std.debug.assert(@reduce(.And, (self.iw == vm.ps(0)) & (self.jw == vm.ps(0)) & (self.kw == vm.ps(0)) & (self.tw == vm.ps(1))));
const ix = self.ix;
const iy = self.jx;
const iz = self.kx;
const jx = self.iy;
const jy = self.jy;
const jz = self.ky;
const kx = self.iz;
const ky = self.jz;
const kz = self.kz;
return .{
.ix = ix,
.iy = iy,
.iz = iz,
.iw = vm.ps(0),
.jx = jx,
.jy = jy,
.jz = jz,
.jw = vm.ps(0),
.kx = kx,
.ky = ky,
.kz = kz,
.kw = vm.ps(0),
.tx = -(self.tx * ix + self.ty * jx + self.tz * kx),
.ty = -(self.tx * iy + self.ty * jy + self.tz * ky),
.tz = -(self.tx * iz + self.ty * jz + self.tz * kz),
.tw = vm.ps(1),
};
}
pub fn inverseAffine(self: Matrix4x4x8) Matrix4x4x8 {
std.debug.assert(@reduce(.And, (self.iw == vm.ps(0)) & (self.jw == vm.ps(0)) & (self.kw == vm.ps(0)) & (self.tw == vm.ps(1))));
const inv_det = vm.ps(1.0) / (
// zig fmt: off
self.ix * (self.jy * self.kz - self.ky * self.jz) +
self.jx * (self.ky * self.iz - self.iy * self.kz) +
self.kx * (self.iy * self.jz - self.iy * self.jz)
// zig fmt: on
);
const ix = self.jy * self.kz - self.ky * self.jz;
const iy = self.ky * self.iz - self.iy * self.kz;
const iz = self.iy * self.jz - self.jy * self.iz;
const jx = self.kx * self.jz - self.jx * self.kz;
const jy = self.ix * self.kz - self.kx * self.iz;
const jz = self.jx * self.iz - self.ix * self.jz;
const kx = self.jx * self.ky - self.kx * self.jy;
const ky = self.kx * self.iy - self.ix * self.ky;
const kz = self.ix * self.jy - self.jx * self.iy;
return .{
.ix = inv_det * ix,
.iy = inv_det * iy,
.iz = inv_det * iz,
.iw = vm.ps(0),
.jx = inv_det * jx,
.jy = inv_det * jy,
.jz = inv_det * jz,
.jw = vm.ps(0),
.kx = inv_det * kx,
.ky = inv_det * ky,
.kz = inv_det * kz,
.kw = vm.ps(0),
.tx = -inv_det * (self.tx * ix + self.ty * jx + self.tz * kx),
.ty = -inv_det * (self.tx * iy + self.ty * jy + self.tz * ky),
.tz = -inv_det * (self.tx * iz + self.ty * jz + self.tz * kz),
.tw = vm.ps(1),
};
}
pub fn inverseFull(self: Matrix4x4x8) Matrix4x4x8 {
const iy_jz = self.iy * self.jz - self.jy * self.iz;
const iy_jw = self.iy * self.jw - self.jy * self.iw;
const iy_kz = self.iy * self.kz - self.ky * self.iz;
const iy_kw = self.iy * self.kw - self.ky * self.iw;
const iy_tz = self.iy * self.tz - self.ty * self.iz;
const iy_tw = self.iy * self.tw - self.ty * self.iw;
const iz_jw = self.iz * self.jw - self.jz * self.iw;
const iz_kw = self.iz * self.kw - self.kz * self.iw;
const iz_tw = self.iz * self.tw - self.tz * self.iw;
const jy_kz = self.jy * self.kz - self.ky * self.jz;
const jy_kw = self.jy * self.kw - self.ky * self.jw;
const jy_tz = self.jy * self.tz - self.ty * self.jz;
const jy_tw = self.jy * self.tw - self.ty * self.jw;
const jz_kw = self.jz * self.kw - self.kz * self.jw;
const jz_tw = self.jz * self.tw - self.tz * self.jw;
const ky_tz = self.ky * self.tz - self.ty * self.kz;
const ky_tw = self.ky * self.tw - self.ty * self.kw;
const kz_tw = self.kz * self.tw - self.tz * self.kw;
const det_ix = self.jy * kz_tw - self.ky * jz_tw + self.ty * jz_kw;
const det_jx = self.iy * kz_tw - self.ky * iz_tw + self.ty * iz_kw;
const det_kx = self.iy * jz_tw - self.jy * iz_tw + self.ty * iz_jw;
const det_tx = self.iy * jz_kw - self.jy * iz_kw + self.ky * iz_jw;
const det_iy = self.jx * kz_tw - self.kx * jz_tw + self.tx * jz_kw;
const det_jy = self.ix * kz_tw - self.kx * iz_tw + self.tx * iz_kw;
const det_ky = self.ix * jz_tw - self.jz * iz_tw + self.tx * iz_jw;
const det_ty = self.ix * jz_kw - self.jx * iz_kw + self.kx * iz_jw;
const det_iz = self.jx * ky_tw - self.kx * jy_tw + self.tx * jy_kw;
const det_jz = self.ix * ky_tw - self.kx * iy_tw + self.tx * iy_kw;
const det_kz = self.ix * jy_tw - self.jx * iy_tw + self.tx * iy_jw;
const det_tz = self.ix * jy_kw - self.jx * iy_kw + self.kx * iy_jw;
const det_iw = self.jx * ky_tz - self.kx * jy_tz + self.tx * jy_kz;
const det_jw = self.ix * ky_tz - self.kx * iy_tz + self.tx * iy_kz;
const det_kw = self.ix * jy_tz - self.jx * iy_tz + self.tx * iy_jz;
const det_tw = self.ix * jy_kz - self.jx * iy_kz + self.kx * iy_jz;
const det = self.ix * det_ix - self.jx * det_jx + self.kx * det_kx - self.tx * det_tx;
const inv_det = vm.ps(1.0) / det;
return .{
// zig fmt: off
.ix = inv_det * det_ix, .iy = -inv_det * det_jx, .iz = inv_det * det_kx, .iw = -inv_det * det_tx,
.jx = -inv_det * det_iy, .jy = inv_det * det_jy, .jz = -inv_det * det_ky, .jw = inv_det * det_ty,
.kx = inv_det * det_iz, .ky = -inv_det * det_jz, .kz = inv_det * det_kz, .kw = -inv_det * det_tz,
.tx = -inv_det * det_iw, .ty = inv_det * det_jw, .tz = -inv_det * det_kw, .tw = inv_det * det_tw,
// zig fmt: on
};
}
};