From 10dc4168998536b4063a336e92b570297a40e1de Mon Sep 17 00:00:00 2001 From: Caleb Gingles Date: Fri, 12 Jan 2024 13:01:02 -0500 Subject: [PATCH 1/4] Expose mat4 determinant and add test. Consolidate common calculations. --- src/mat4.zig | 114 +++++++++++++++++++++++++++------------------------ 1 file changed, 60 insertions(+), 54 deletions(-) diff --git a/src/mat4.zig b/src/mat4.zig index c08f8fe..4daa3f9 100644 --- a/src/mat4.zig +++ b/src/mat4.zig @@ -340,66 +340,59 @@ pub fn Mat4x4(comptime T: type) type { return result; } + fn detsubs(self: Self) [12]T { + return .{ + self.data[0][0] * self.data[1][1] - self.data[1][0] * self.data[0][1], + self.data[0][0] * self.data[1][2] - self.data[1][0] * self.data[0][2], + self.data[0][0] * self.data[1][3] - self.data[1][0] * self.data[0][3], + self.data[0][1] * self.data[1][2] - self.data[1][1] * self.data[0][2], + self.data[0][1] * self.data[1][3] - self.data[1][1] * self.data[0][3], + self.data[0][2] * self.data[1][3] - self.data[1][2] * self.data[0][3], + + self.data[2][0] * self.data[3][1] - self.data[3][0] * self.data[2][1], + self.data[2][0] * self.data[3][2] - self.data[3][0] * self.data[2][2], + self.data[2][0] * self.data[3][3] - self.data[3][0] * self.data[2][3], + self.data[2][1] * self.data[3][2] - self.data[3][1] * self.data[2][2], + self.data[2][1] * self.data[3][3] - self.data[3][1] * self.data[2][3], + self.data[2][2] * self.data[3][3] - self.data[3][2] * self.data[2][3], + }; + } + + /// Calculate determinant of the given 4x4 matrix. + pub fn det(self: Self) T { + var s = detsubs(self); + return s[0] * s[11] - s[1] * s[10] + s[2] * s[9] + s[3] * s[8] - s[4] * s[7] + s[5] * s[6]; + } + /// Construct inverse 4x4 from given matrix. /// Note: This is not the most efficient way to do this. /// TODO: Make it more efficient. pub fn inv(self: Self) Self { var inv_mat: Self = undefined; - var s: [6]T = undefined; - var c: [6]T = undefined; - - s[0] = self.data[0][0] * self.data[1][1] - self.data[1][0] * self.data[0][1]; - s[1] = self.data[0][0] * self.data[1][2] - self.data[1][0] * self.data[0][2]; - s[2] = self.data[0][0] * self.data[1][3] - self.data[1][0] * self.data[0][3]; - s[3] = self.data[0][1] * self.data[1][2] - self.data[1][1] * self.data[0][2]; - s[4] = self.data[0][1] * self.data[1][3] - self.data[1][1] * self.data[0][3]; - s[5] = self.data[0][2] * self.data[1][3] - self.data[1][2] * self.data[0][3]; - - c[0] = self.data[2][0] * self.data[3][1] - self.data[3][0] * self.data[2][1]; - c[1] = self.data[2][0] * self.data[3][2] - self.data[3][0] * self.data[2][2]; - c[2] = self.data[2][0] * self.data[3][3] - self.data[3][0] * self.data[2][3]; - c[3] = self.data[2][1] * self.data[3][2] - self.data[3][1] * self.data[2][2]; - c[4] = self.data[2][1] * self.data[3][3] - self.data[3][1] * self.data[2][3]; - c[5] = self.data[2][2] * self.data[3][3] - self.data[3][2] * self.data[2][3]; - - const determ = 1 / (s[0] * c[5] - s[1] * c[4] + s[2] * c[3] + s[3] * c[2] - s[4] * c[1] + s[5] * c[0]); - - inv_mat.data[0][0] = - (self.data[1][1] * c[5] - self.data[1][2] * c[4] + self.data[1][3] * c[3]) * determ; - inv_mat.data[0][1] = - (-self.data[0][1] * c[5] + self.data[0][2] * c[4] - self.data[0][3] * c[3]) * determ; - inv_mat.data[0][2] = - (self.data[3][1] * s[5] - self.data[3][2] * s[4] + self.data[3][3] * s[3]) * determ; - inv_mat.data[0][3] = - (-self.data[2][1] * s[5] + self.data[2][2] * s[4] - self.data[2][3] * s[3]) * determ; - - inv_mat.data[1][0] = - (-self.data[1][0] * c[5] + self.data[1][2] * c[2] - self.data[1][3] * c[1]) * determ; - inv_mat.data[1][1] = - (self.data[0][0] * c[5] - self.data[0][2] * c[2] + self.data[0][3] * c[1]) * determ; - inv_mat.data[1][2] = - (-self.data[3][0] * s[5] + self.data[3][2] * s[2] - self.data[3][3] * s[1]) * determ; - inv_mat.data[1][3] = - (self.data[2][0] * s[5] - self.data[2][2] * s[2] + self.data[2][3] * s[1]) * determ; - - inv_mat.data[2][0] = - (self.data[1][0] * c[4] - self.data[1][1] * c[2] + self.data[1][3] * c[0]) * determ; - inv_mat.data[2][1] = - (-self.data[0][0] * c[4] + self.data[0][1] * c[2] - self.data[0][3] * c[0]) * determ; - inv_mat.data[2][2] = - (self.data[3][0] * s[4] - self.data[3][1] * s[2] + self.data[3][3] * s[0]) * determ; - inv_mat.data[2][3] = - (-self.data[2][0] * s[4] + self.data[2][1] * s[2] - self.data[2][3] * s[0]) * determ; - - inv_mat.data[3][0] = - (-self.data[1][0] * c[3] + self.data[1][1] * c[1] - self.data[1][2] * c[0]) * determ; - inv_mat.data[3][1] = - (self.data[0][0] * c[3] - self.data[0][1] * c[1] + self.data[0][2] * c[0]) * determ; - inv_mat.data[3][2] = - (-self.data[3][0] * s[3] + self.data[3][1] * s[1] - self.data[3][2] * s[0]) * determ; - inv_mat.data[3][3] = - (self.data[2][0] * s[3] - self.data[2][1] * s[1] + self.data[2][2] * s[0]) * determ; + var s = detsubs(self); + + const determ = 1 / (s[0] * s[11] - s[1] * s[10] + s[2] * s[9] + s[3] * s[8] - s[4] * s[7] + s[5] * s[6]); + + inv_mat.data[0][0] = (self.data[1][1] * s[11] - self.data[1][2] * s[10] + self.data[1][3] * s[9]) * determ; + inv_mat.data[0][1] = (-self.data[0][1] * s[11] + self.data[0][2] * s[10] - self.data[0][3] * s[9]) * determ; + inv_mat.data[0][2] = (self.data[3][1] * s[5] - self.data[3][2] * s[4] + self.data[3][3] * s[3]) * determ; + inv_mat.data[0][3] = (-self.data[2][1] * s[5] + self.data[2][2] * s[4] - self.data[2][3] * s[3]) * determ; + + inv_mat.data[1][0] = (-self.data[1][0] * s[11] + self.data[1][2] * s[8] - self.data[1][3] * s[7]) * determ; + inv_mat.data[1][1] = (self.data[0][0] * s[11] - self.data[0][2] * s[8] + self.data[0][3] * s[7]) * determ; + inv_mat.data[1][2] = (-self.data[3][0] * s[5] + self.data[3][2] * s[2] - self.data[3][3] * s[1]) * determ; + inv_mat.data[1][3] = (self.data[2][0] * s[5] - self.data[2][2] * s[2] + self.data[2][3] * s[1]) * determ; + + inv_mat.data[2][0] = (self.data[1][0] * s[10] - self.data[1][1] * s[8] + self.data[1][3] * s[6]) * determ; + inv_mat.data[2][1] = (-self.data[0][0] * s[10] + self.data[0][1] * s[8] - self.data[0][3] * s[6]) * determ; + inv_mat.data[2][2] = (self.data[3][0] * s[4] - self.data[3][1] * s[2] + self.data[3][3] * s[0]) * determ; + inv_mat.data[2][3] = (-self.data[2][0] * s[4] + self.data[2][1] * s[2] - self.data[2][3] * s[0]) * determ; + + inv_mat.data[3][0] = (-self.data[1][0] * s[9] + self.data[1][1] * s[7] - self.data[1][2] * s[6]) * determ; + inv_mat.data[3][1] = (self.data[0][0] * s[9] - self.data[0][1] * s[7] + self.data[0][2] * s[6]) * determ; + inv_mat.data[3][2] = (-self.data[3][0] * s[3] + self.data[3][1] * s[1] - self.data[3][2] * s[0]) * determ; + inv_mat.data[3][3] = (self.data[2][0] * s[3] - self.data[2][1] * s[1] + self.data[2][2] * s[0]) * determ; return inv_mat; } @@ -615,6 +608,19 @@ test "zalgebra.Mat4.scale" { }); } +test "zalgebra.Mat4.det" { + const a: Mat4 = .{ + .data = .{ + .{ 2, 0, 0, 4 }, + .{ 0, 2, 0, 0 }, + .{ 0, 0, 2, 0 }, + .{ 4, 0, 0, 2 }, + }, + }; + + try expectEqual(a.det(), -48); +} + test "zalgebra.Mat4.inv" { const a: Mat4 = .{ .data = .{ From c21c3b8228ef5617fe5067af5b9a89c29bfd9d9e Mon Sep 17 00:00:00 2001 From: Caleb Gingles Date: Fri, 12 Jan 2024 13:08:43 -0500 Subject: [PATCH 2/4] const fixes for newer compiler --- src/mat4.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mat4.zig b/src/mat4.zig index 4daa3f9..eee1c46 100644 --- a/src/mat4.zig +++ b/src/mat4.zig @@ -360,7 +360,7 @@ pub fn Mat4x4(comptime T: type) type { /// Calculate determinant of the given 4x4 matrix. pub fn det(self: Self) T { - var s = detsubs(self); + const s = detsubs(self); return s[0] * s[11] - s[1] * s[10] + s[2] * s[9] + s[3] * s[8] - s[4] * s[7] + s[5] * s[6]; } @@ -370,7 +370,7 @@ pub fn Mat4x4(comptime T: type) type { pub fn inv(self: Self) Self { var inv_mat: Self = undefined; - var s = detsubs(self); + const s = detsubs(self); const determ = 1 / (s[0] * s[11] - s[1] * s[10] + s[2] * s[9] + s[3] * s[8] - s[4] * s[7] + s[5] * s[6]); From 8c3f39244dfc46edff6f77d8a1607f2bbd426e31 Mon Sep 17 00:00:00 2001 From: Caleb Gingles Date: Fri, 12 Jan 2024 14:09:53 -0500 Subject: [PATCH 3/4] Clean up signs for readability --- src/mat4.zig | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/mat4.zig b/src/mat4.zig index eee1c46..c5df2c6 100644 --- a/src/mat4.zig +++ b/src/mat4.zig @@ -374,25 +374,25 @@ pub fn Mat4x4(comptime T: type) type { const determ = 1 / (s[0] * s[11] - s[1] * s[10] + s[2] * s[9] + s[3] * s[8] - s[4] * s[7] + s[5] * s[6]); - inv_mat.data[0][0] = (self.data[1][1] * s[11] - self.data[1][2] * s[10] + self.data[1][3] * s[9]) * determ; - inv_mat.data[0][1] = (-self.data[0][1] * s[11] + self.data[0][2] * s[10] - self.data[0][3] * s[9]) * determ; - inv_mat.data[0][2] = (self.data[3][1] * s[5] - self.data[3][2] * s[4] + self.data[3][3] * s[3]) * determ; - inv_mat.data[0][3] = (-self.data[2][1] * s[5] + self.data[2][2] * s[4] - self.data[2][3] * s[3]) * determ; - - inv_mat.data[1][0] = (-self.data[1][0] * s[11] + self.data[1][2] * s[8] - self.data[1][3] * s[7]) * determ; - inv_mat.data[1][1] = (self.data[0][0] * s[11] - self.data[0][2] * s[8] + self.data[0][3] * s[7]) * determ; - inv_mat.data[1][2] = (-self.data[3][0] * s[5] + self.data[3][2] * s[2] - self.data[3][3] * s[1]) * determ; - inv_mat.data[1][3] = (self.data[2][0] * s[5] - self.data[2][2] * s[2] + self.data[2][3] * s[1]) * determ; - - inv_mat.data[2][0] = (self.data[1][0] * s[10] - self.data[1][1] * s[8] + self.data[1][3] * s[6]) * determ; - inv_mat.data[2][1] = (-self.data[0][0] * s[10] + self.data[0][1] * s[8] - self.data[0][3] * s[6]) * determ; - inv_mat.data[2][2] = (self.data[3][0] * s[4] - self.data[3][1] * s[2] + self.data[3][3] * s[0]) * determ; - inv_mat.data[2][3] = (-self.data[2][0] * s[4] + self.data[2][1] * s[2] - self.data[2][3] * s[0]) * determ; - - inv_mat.data[3][0] = (-self.data[1][0] * s[9] + self.data[1][1] * s[7] - self.data[1][2] * s[6]) * determ; - inv_mat.data[3][1] = (self.data[0][0] * s[9] - self.data[0][1] * s[7] + self.data[0][2] * s[6]) * determ; - inv_mat.data[3][2] = (-self.data[3][0] * s[3] + self.data[3][1] * s[1] - self.data[3][2] * s[0]) * determ; - inv_mat.data[3][3] = (self.data[2][0] * s[3] - self.data[2][1] * s[1] + self.data[2][2] * s[0]) * determ; + inv_mat.data[0][0] = determ * (self.data[1][1] * s[11] - self.data[1][2] * s[10] + self.data[1][3] * s[9]); + inv_mat.data[0][1] = determ * -(self.data[0][1] * s[11] - self.data[0][2] * s[10] + self.data[0][3] * s[9]); + inv_mat.data[0][2] = determ * (self.data[3][1] * s[5] - self.data[3][2] * s[4] + self.data[3][3] * s[3]); + inv_mat.data[0][3] = determ * -(self.data[2][1] * s[5] - self.data[2][2] * s[4] + self.data[2][3] * s[3]); + + inv_mat.data[1][0] = determ * -(self.data[1][0] * s[11] - self.data[1][2] * s[8] + self.data[1][3] * s[7]); + inv_mat.data[1][1] = determ * (self.data[0][0] * s[11] - self.data[0][2] * s[8] + self.data[0][3] * s[7]); + inv_mat.data[1][2] = determ * -(self.data[3][0] * s[5] - self.data[3][2] * s[2] + self.data[3][3] * s[1]); + inv_mat.data[1][3] = determ * (self.data[2][0] * s[5] - self.data[2][2] * s[2] + self.data[2][3] * s[1]); + + inv_mat.data[2][0] = determ * (self.data[1][0] * s[10] - self.data[1][1] * s[8] + self.data[1][3] * s[6]); + inv_mat.data[2][1] = determ * -(self.data[0][0] * s[10] - self.data[0][1] * s[8] + self.data[0][3] * s[6]); + inv_mat.data[2][2] = determ * (self.data[3][0] * s[4] - self.data[3][1] * s[2] + self.data[3][3] * s[0]); + inv_mat.data[2][3] = determ * -(self.data[2][0] * s[4] - self.data[2][1] * s[2] + self.data[2][3] * s[0]); + + inv_mat.data[3][0] = determ * -(self.data[1][0] * s[9] - self.data[1][1] * s[7] + self.data[1][2] * s[6]); + inv_mat.data[3][1] = determ * (self.data[0][0] * s[9] - self.data[0][1] * s[7] + self.data[0][2] * s[6]); + inv_mat.data[3][2] = determ * -(self.data[3][0] * s[3] - self.data[3][1] * s[1] + self.data[3][2] * s[0]); + inv_mat.data[3][3] = determ * (self.data[2][0] * s[3] - self.data[2][1] * s[1] + self.data[2][2] * s[0]); return inv_mat; } From f6385d5e47fe8d52bd71a841ecca644297afae8e Mon Sep 17 00:00:00 2001 From: Caleb Gingles Date: Fri, 12 Jan 2024 20:38:03 -0500 Subject: [PATCH 4/4] Zig fmt didn't like the extra spaces --- src/mat4.zig | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/mat4.zig b/src/mat4.zig index c5df2c6..e8ec3b3 100644 --- a/src/mat4.zig +++ b/src/mat4.zig @@ -374,25 +374,25 @@ pub fn Mat4x4(comptime T: type) type { const determ = 1 / (s[0] * s[11] - s[1] * s[10] + s[2] * s[9] + s[3] * s[8] - s[4] * s[7] + s[5] * s[6]); - inv_mat.data[0][0] = determ * (self.data[1][1] * s[11] - self.data[1][2] * s[10] + self.data[1][3] * s[9]); + inv_mat.data[0][0] = determ * (self.data[1][1] * s[11] - self.data[1][2] * s[10] + self.data[1][3] * s[9]); inv_mat.data[0][1] = determ * -(self.data[0][1] * s[11] - self.data[0][2] * s[10] + self.data[0][3] * s[9]); - inv_mat.data[0][2] = determ * (self.data[3][1] * s[5] - self.data[3][2] * s[4] + self.data[3][3] * s[3]); + inv_mat.data[0][2] = determ * (self.data[3][1] * s[5] - self.data[3][2] * s[4] + self.data[3][3] * s[3]); inv_mat.data[0][3] = determ * -(self.data[2][1] * s[5] - self.data[2][2] * s[4] + self.data[2][3] * s[3]); inv_mat.data[1][0] = determ * -(self.data[1][0] * s[11] - self.data[1][2] * s[8] + self.data[1][3] * s[7]); - inv_mat.data[1][1] = determ * (self.data[0][0] * s[11] - self.data[0][2] * s[8] + self.data[0][3] * s[7]); + inv_mat.data[1][1] = determ * (self.data[0][0] * s[11] - self.data[0][2] * s[8] + self.data[0][3] * s[7]); inv_mat.data[1][2] = determ * -(self.data[3][0] * s[5] - self.data[3][2] * s[2] + self.data[3][3] * s[1]); - inv_mat.data[1][3] = determ * (self.data[2][0] * s[5] - self.data[2][2] * s[2] + self.data[2][3] * s[1]); + inv_mat.data[1][3] = determ * (self.data[2][0] * s[5] - self.data[2][2] * s[2] + self.data[2][3] * s[1]); - inv_mat.data[2][0] = determ * (self.data[1][0] * s[10] - self.data[1][1] * s[8] + self.data[1][3] * s[6]); + inv_mat.data[2][0] = determ * (self.data[1][0] * s[10] - self.data[1][1] * s[8] + self.data[1][3] * s[6]); inv_mat.data[2][1] = determ * -(self.data[0][0] * s[10] - self.data[0][1] * s[8] + self.data[0][3] * s[6]); - inv_mat.data[2][2] = determ * (self.data[3][0] * s[4] - self.data[3][1] * s[2] + self.data[3][3] * s[0]); + inv_mat.data[2][2] = determ * (self.data[3][0] * s[4] - self.data[3][1] * s[2] + self.data[3][3] * s[0]); inv_mat.data[2][3] = determ * -(self.data[2][0] * s[4] - self.data[2][1] * s[2] + self.data[2][3] * s[0]); inv_mat.data[3][0] = determ * -(self.data[1][0] * s[9] - self.data[1][1] * s[7] + self.data[1][2] * s[6]); - inv_mat.data[3][1] = determ * (self.data[0][0] * s[9] - self.data[0][1] * s[7] + self.data[0][2] * s[6]); + inv_mat.data[3][1] = determ * (self.data[0][0] * s[9] - self.data[0][1] * s[7] + self.data[0][2] * s[6]); inv_mat.data[3][2] = determ * -(self.data[3][0] * s[3] - self.data[3][1] * s[1] + self.data[3][2] * s[0]); - inv_mat.data[3][3] = determ * (self.data[2][0] * s[3] - self.data[2][1] * s[1] + self.data[2][2] * s[0]); + inv_mat.data[3][3] = determ * (self.data[2][0] * s[3] - self.data[2][1] * s[1] + self.data[2][2] * s[0]); return inv_mat; }