Skip to content

Commit

Permalink
Merge pull request #40 from Nairou/det
Browse files Browse the repository at this point in the history
Expose mat4 determinant and add test. Consolidate common calculations.
  • Loading branch information
kooparse authored Jan 14, 2024
2 parents f69c796 + f6385d5 commit e135bef
Showing 1 changed file with 60 additions and 54 deletions.
114 changes: 60 additions & 54 deletions src/mat4.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
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];
}

/// 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;
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]);

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;
}
Expand Down Expand Up @@ -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 = .{
Expand Down

0 comments on commit e135bef

Please sign in to comment.