math: add Mat2x2 (#1130)
This commit is contained in:
parent
9cf37cdc39
commit
e9489ee560
2 changed files with 179 additions and 7 deletions
|
|
@ -51,6 +51,7 @@ pub const Vec2 = vec.Vec(2, f32);
|
|||
pub const Vec3 = vec.Vec(3, f32);
|
||||
pub const Vec4 = vec.Vec(4, f32);
|
||||
pub const Quat = q.Quat(f32);
|
||||
pub const Mat2x2 = mat.Mat(2, 2, Vec2);
|
||||
pub const Mat3x3 = mat.Mat(3, 3, Vec3);
|
||||
pub const Mat4x4 = mat.Mat(4, 4, Vec4);
|
||||
pub const Ray = ray.Ray(Vec3);
|
||||
|
|
@ -60,6 +61,7 @@ pub const Vec2h = vec.Vec(2, f16);
|
|||
pub const Vec3h = vec.Vec(3, f16);
|
||||
pub const Vec4h = vec.Vec(4, f16);
|
||||
pub const Quath = q.Quat(f16);
|
||||
pub const Mat2x2h = mat.Mat(2, 2, Vec2h);
|
||||
pub const Mat3x3h = mat.Mat(3, 3, Vec3h);
|
||||
pub const Mat4x4h = mat.Mat(4, 4, Vec4h);
|
||||
pub const Rayh = ray.Ray(Vec3h);
|
||||
|
|
@ -69,6 +71,7 @@ pub const Vec2d = vec.Vec(2, f64);
|
|||
pub const Vec3d = vec.Vec(3, f64);
|
||||
pub const Vec4d = vec.Vec(4, f64);
|
||||
pub const Quatd = q.Quat(f64);
|
||||
pub const Mat2x2d = mat.Mat(2, 2, Vec2d);
|
||||
pub const Mat3x3d = mat.Mat(3, 3, Vec3d);
|
||||
pub const Mat4x4d = mat.Mat(4, 4, Vec4d);
|
||||
pub const Rayd = ray.Ray(Vec3d);
|
||||
|
|
@ -81,6 +84,7 @@ pub const vec2FromInt = Vec2.fromInt;
|
|||
pub const vec3FromInt = Vec3.fromInt;
|
||||
pub const vec4FromInt = Vec4.fromInt;
|
||||
pub const quat = Quat.init;
|
||||
pub const mat2x2 = Mat2x2.init;
|
||||
pub const mat3x3 = Mat3x3.init;
|
||||
pub const mat4x4 = Mat4x4.init;
|
||||
|
||||
|
|
@ -92,6 +96,7 @@ pub const vec2hFromInt = Vec2h.fromInt;
|
|||
pub const vec3hFromInt = Vec3h.fromInt;
|
||||
pub const vec4hFromInt = Vec4h.fromInt;
|
||||
pub const quath = Quath.init;
|
||||
pub const mat2x2h = Mat2x2h.init;
|
||||
pub const mat3x3h = Mat3x3h.init;
|
||||
pub const mat4x4h = Mat4x4h.init;
|
||||
|
||||
|
|
@ -103,6 +108,7 @@ pub const vec2dFromInt = Vec2d.fromInt;
|
|||
pub const vec3dFromInt = Vec3d.fromInt;
|
||||
pub const vec4dFromInt = Vec4d.fromInt;
|
||||
pub const quatd = Quatd.init;
|
||||
pub const mat2x2d = Mat2x2d.init;
|
||||
pub const mat3x3d = Mat3x3d.init;
|
||||
pub const mat4x4d = Mat4x4d.init;
|
||||
|
||||
|
|
|
|||
180
src/math/mat.zig
180
src/math/mat.zig
|
|
@ -51,6 +51,10 @@ pub fn Mat(
|
|||
|
||||
/// Identity matrix
|
||||
pub const ident = switch (Matrix) {
|
||||
inline math.Mat2x2, math.Mat2x2h, math.Mat2x2d => Matrix.init(
|
||||
&RowVec.init(1, 0),
|
||||
&RowVec.init(0, 1),
|
||||
),
|
||||
inline math.Mat3x3, math.Mat3x3h, math.Mat3x3d => Matrix.init(
|
||||
&RowVec.init(1, 0, 0),
|
||||
&RowVec.init(0, 1, 0),
|
||||
|
|
@ -66,6 +70,70 @@ pub fn Mat(
|
|||
};
|
||||
|
||||
pub usingnamespace switch (Matrix) {
|
||||
inline math.Mat2x2, math.Mat2x2h, math.Mat2x2d => struct {
|
||||
/// Constructs a 2x2 matrix with the given rows. For example to write a translation
|
||||
/// matrix like in the left part of this equation:
|
||||
///
|
||||
/// ```
|
||||
/// |1 tx| |x | |x+y*tx|
|
||||
/// |0 ty| |y=1| = |ty |
|
||||
/// ```
|
||||
///
|
||||
/// You would write it with the same visual layout:
|
||||
///
|
||||
/// ```
|
||||
/// const m = Mat2x2.init(
|
||||
/// vec3(1, tx),
|
||||
/// vec3(0, ty),
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// Note that Mach matrices use [column-major storage and column-vectors](https://machengine.org/engine/math/matrix-storage/).
|
||||
pub inline fn init(r0: *const RowVec, r1: *const RowVec) Matrix {
|
||||
return .{ .v = [_]Vec{
|
||||
Vec.init(r0.x(), r1.x()),
|
||||
Vec.init(r0.y(), r1.y()),
|
||||
} };
|
||||
}
|
||||
|
||||
/// Returns the row `i` of the matrix.
|
||||
pub inline fn row(m: *const Matrix, i: usize) RowVec {
|
||||
// Note: we inline RowVec.init manually here as it is faster in debug builds.
|
||||
// return RowVec.init(m.v[0].v[i], m.v[1].v[i]);
|
||||
return .{ .v = .{ m.v[0].v[i], m.v[1].v[i] } };
|
||||
}
|
||||
|
||||
/// Returns the column `i` of the matrix.
|
||||
pub inline fn col(m: *const Matrix, i: usize) RowVec {
|
||||
// Note: we inline RowVec.init manually here as it is faster in debug builds.
|
||||
// return RowVec.init(m.v[i].v[0], m.v[i].v[1]);
|
||||
return .{ .v = .{ m.v[i].v[0], m.v[i].v[1] } };
|
||||
}
|
||||
|
||||
/// Transposes the matrix.
|
||||
pub inline fn transpose(m: *const Matrix) Matrix {
|
||||
return .{ .v = [_]Vec{
|
||||
Vec.init(m.v[0].v[0], m.v[1].v[0]),
|
||||
Vec.init(m.v[0].v[1], m.v[1].v[1]),
|
||||
} };
|
||||
}
|
||||
|
||||
/// Constructs a 1D matrix which scales each dimension by the given scalar.
|
||||
pub inline fn scaleScalar(t: Vec.T) Matrix {
|
||||
return init(
|
||||
&RowVec.init(t, 0),
|
||||
&RowVec.init(0, 1),
|
||||
);
|
||||
}
|
||||
|
||||
/// Constructs a 1D matrix which translates coordinates by the given scalar.
|
||||
pub inline fn translateScalar(t: Vec.T) Matrix {
|
||||
return init(
|
||||
&RowVec.init(1, t),
|
||||
&RowVec.init(0, 1),
|
||||
);
|
||||
}
|
||||
},
|
||||
inline math.Mat3x3, math.Mat3x3h, math.Mat3x3d => struct {
|
||||
/// Constructs a 3x3 matrix with the given rows. For example to write a translation
|
||||
/// matrix like in the left part of this equation:
|
||||
|
|
@ -390,21 +458,26 @@ pub fn Mat(
|
|||
|
||||
test "gpu_compatibility" {
|
||||
// https://www.w3.org/TR/WGSL/#alignment-and-size
|
||||
try testing.expect(usize, 16).eql(@sizeOf(math.Mat2x2));
|
||||
try testing.expect(usize, 48).eql(@sizeOf(math.Mat3x3));
|
||||
try testing.expect(usize, 64).eql(@sizeOf(math.Mat4x4));
|
||||
|
||||
try testing.expect(usize, 8).eql(@sizeOf(math.Mat2x2h));
|
||||
try testing.expect(usize, 24).eql(@sizeOf(math.Mat3x3h));
|
||||
try testing.expect(usize, 32).eql(@sizeOf(math.Mat4x4h));
|
||||
|
||||
try testing.expect(usize, 48 * 2).eql(@sizeOf(math.Mat3x3d)); // speculative
|
||||
try testing.expect(usize, 64 * 2).eql(@sizeOf(math.Mat4x4d)); // speculative
|
||||
try testing.expect(usize, 32).eql(@sizeOf(math.Mat2x2d)); // speculative
|
||||
try testing.expect(usize, 96).eql(@sizeOf(math.Mat3x3d)); // speculative
|
||||
try testing.expect(usize, 128).eql(@sizeOf(math.Mat4x4d)); // speculative
|
||||
}
|
||||
|
||||
test "zero_struct_overhead" {
|
||||
// Proof that using e.g. [3]Vec4 is equal to [3]@Vector(4, f32)
|
||||
try testing.expect(usize, @alignOf([3]@Vector(4, f32))).eql(@alignOf(math.Mat3x3));
|
||||
// Proof that using e.g. [3]Vec3 is equal to [3]@Vector(3, f32)
|
||||
try testing.expect(usize, @alignOf([2]@Vector(2, f32))).eql(@alignOf(math.Mat2x2));
|
||||
try testing.expect(usize, @alignOf([3]@Vector(3, f32))).eql(@alignOf(math.Mat3x3));
|
||||
try testing.expect(usize, @alignOf([4]@Vector(4, f32))).eql(@alignOf(math.Mat4x4));
|
||||
try testing.expect(usize, @sizeOf([3]@Vector(4, f32))).eql(@sizeOf(math.Mat3x3));
|
||||
try testing.expect(usize, @sizeOf([2]@Vector(2, f32))).eql(@sizeOf(math.Mat2x2));
|
||||
try testing.expect(usize, @sizeOf([3]@Vector(3, f32))).eql(@sizeOf(math.Mat3x3));
|
||||
try testing.expect(usize, @sizeOf([4]@Vector(4, f32))).eql(@sizeOf(math.Mat4x4));
|
||||
}
|
||||
|
||||
|
|
@ -429,7 +502,16 @@ test "init" {
|
|||
});
|
||||
}
|
||||
|
||||
test "mat3x3_ident" {
|
||||
test "Mat2x2_ident" {
|
||||
try testing.expect(math.Mat2x2, math.Mat2x2.ident).eql(math.Mat2x2{
|
||||
.v = [_]math.Vec2{
|
||||
math.Vec2.init(1, 0),
|
||||
math.Vec2.init(0, 1),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
test "Mat3x3_ident" {
|
||||
try testing.expect(math.Mat3x3, math.Mat3x3.ident).eql(math.Mat3x3{
|
||||
.v = [_]math.Vec3{
|
||||
math.Vec3.init(1, 0, 0),
|
||||
|
|
@ -439,7 +521,7 @@ test "mat3x3_ident" {
|
|||
});
|
||||
}
|
||||
|
||||
test "mat4x4_ident" {
|
||||
test "Mat4x4_ident" {
|
||||
try testing.expect(math.Mat4x4, math.Mat4x4.ident).eql(math.Mat4x4{
|
||||
.v = [_]math.Vec4{
|
||||
math.Vec4.init(1, 0, 0, 0),
|
||||
|
|
@ -450,6 +532,24 @@ test "mat4x4_ident" {
|
|||
});
|
||||
}
|
||||
|
||||
test "Mat2x2_row" {
|
||||
const m = math.Mat2x2.init(
|
||||
&math.vec2(0, 1),
|
||||
&math.vec2(2, 3),
|
||||
);
|
||||
try testing.expect(math.Vec2, math.vec2(0, 1)).eql(m.row(0));
|
||||
try testing.expect(math.Vec2, math.vec2(2, 3)).eql(m.row(@TypeOf(m).rows - 1));
|
||||
}
|
||||
|
||||
test "Mat2x2_col" {
|
||||
const m = math.Mat2x2.init(
|
||||
&math.vec2(0, 1),
|
||||
&math.vec2(2, 3),
|
||||
);
|
||||
try testing.expect(math.Vec2, math.vec2(0, 2)).eql(m.col(0));
|
||||
try testing.expect(math.Vec2, math.vec2(1, 3)).eql(m.col(@TypeOf(m).cols - 1));
|
||||
}
|
||||
|
||||
test "Mat3x3_row" {
|
||||
const m = math.Mat3x3.init(
|
||||
&math.vec3(0, 1, 2),
|
||||
|
|
@ -498,6 +598,17 @@ test "Mat4x4_col" {
|
|||
try testing.expect(math.Vec4, math.vec4(3, 7, 11, 15)).eql(m.col(@TypeOf(m).cols - 1));
|
||||
}
|
||||
|
||||
test "Mat2x2_transpose" {
|
||||
const m = math.Mat2x2.init(
|
||||
&math.vec2(0, 1),
|
||||
&math.vec2(2, 3),
|
||||
);
|
||||
try testing.expect(math.Mat2x2, math.Mat2x2.init(
|
||||
&math.vec2(0, 2),
|
||||
&math.vec2(1, 3),
|
||||
)).eql(m.transpose());
|
||||
}
|
||||
|
||||
test "Mat3x3_transpose" {
|
||||
const m = math.Mat3x3.init(
|
||||
&math.vec3(0, 1, 2),
|
||||
|
|
@ -526,6 +637,14 @@ test "Mat4x4_transpose" {
|
|||
)).eql(m.transpose());
|
||||
}
|
||||
|
||||
test "Mat2x2_scaleScalar" {
|
||||
const m = math.Mat2x2.scaleScalar(2);
|
||||
try testing.expect(math.Mat2x2, math.Mat2x2.init(
|
||||
&math.vec2(2, 0),
|
||||
&math.vec2(0, 1),
|
||||
)).eql(m);
|
||||
}
|
||||
|
||||
test "Mat3x3_scale" {
|
||||
const m = math.Mat3x3.scale(math.vec2(2, 3));
|
||||
try testing.expect(math.Mat3x3, math.Mat3x3.init(
|
||||
|
|
@ -592,6 +711,14 @@ test "Mat3x3_translateScalar" {
|
|||
)).eql(m);
|
||||
}
|
||||
|
||||
test "Mat2x2_translateScalar" {
|
||||
const m = math.Mat2x2.translateScalar(2);
|
||||
try testing.expect(math.Mat2x2, math.Mat2x2.init(
|
||||
&math.vec2(1, 2),
|
||||
&math.vec2(0, 1),
|
||||
)).eql(m);
|
||||
}
|
||||
|
||||
test "Mat4x4_translateScalar" {
|
||||
const m = math.Mat4x4.translateScalar(2);
|
||||
try testing.expect(math.Mat4x4, math.Mat4x4.init(
|
||||
|
|
@ -612,6 +739,27 @@ test "Mat4x4_translation" {
|
|||
try testing.expect(math.Vec3, math.vec3(2, 3, 4)).eql(m.translation());
|
||||
}
|
||||
|
||||
test "Mat2x2_mulVec_vec2_ident" {
|
||||
const v = math.Vec2.splat(1);
|
||||
const ident = math.Mat2x2.ident;
|
||||
const expected = v;
|
||||
var m = math.Mat2x2.mulVec(&ident, &v);
|
||||
|
||||
try testing.expect(math.Vec2, expected).eql(m);
|
||||
}
|
||||
|
||||
test "Mat2x2_mulVec_vec2" {
|
||||
const v = math.Vec2.splat(1);
|
||||
const mat = math.Mat2x2.init(
|
||||
&math.vec2(2, 0),
|
||||
&math.vec2(0, 2),
|
||||
);
|
||||
|
||||
const m = math.Mat2x2.mulVec(&mat, &v);
|
||||
const expected = math.vec2(2, 2);
|
||||
try testing.expect(math.Vec2, expected).eql(m);
|
||||
}
|
||||
|
||||
test "Mat3x3_mulVec_vec3_ident" {
|
||||
const v = math.Vec3.splat(1);
|
||||
const ident = math.Mat3x3.ident;
|
||||
|
|
@ -648,6 +796,24 @@ test "Mat4x4_mulVec_vec4" {
|
|||
try testing.expect(math.Vec4, expected).eql(m);
|
||||
}
|
||||
|
||||
test "Mat2x2_mul" {
|
||||
const a = math.Mat2x2.init(
|
||||
&math.vec2(4, 2),
|
||||
&math.vec2(7, 9),
|
||||
);
|
||||
const b = math.Mat2x2.init(
|
||||
&math.vec2(5, -7),
|
||||
&math.vec2(6, -3),
|
||||
);
|
||||
const c = math.Mat2x2.mul(&a, &b);
|
||||
|
||||
const expected = math.Mat2x2.init(
|
||||
&math.vec2(32, -34),
|
||||
&math.vec2(89, -76),
|
||||
);
|
||||
try testing.expect(math.Mat2x2, expected).eql(c);
|
||||
}
|
||||
|
||||
test "Mat3x3_mul" {
|
||||
const a = math.Mat3x3.init(
|
||||
&math.vec3(4, 2, -3),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue