math: make matrix init visually match scientific notation
Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
parent
8fd84a6bda
commit
de90bb6c12
1 changed files with 108 additions and 54 deletions
162
src/math/mat.zig
162
src/math/mat.zig
|
|
@ -11,6 +11,22 @@ pub fn Mat(
|
|||
comptime Vector: type,
|
||||
) type {
|
||||
return extern struct {
|
||||
/// The column vectors of the matrix.
|
||||
///
|
||||
/// Mach matrices use [column-major storage and column-vectors](https://machengine.org/engine/math/matrix-storage/).
|
||||
/// The translation vector is stored in contiguous memory elements 12, 13, 14:
|
||||
///
|
||||
/// ```
|
||||
/// [4]Vec4{
|
||||
/// vec4( 1, 0, 0, 0),
|
||||
/// vec4( 0, 1, 0, 0),
|
||||
/// vec4( 0, 0, 1, 0),
|
||||
/// vec4(tx, ty, tz, tw),
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Use the init() constructor to write code which visually matches the same layout as you'd
|
||||
/// see used in scientific / maths communities.
|
||||
v: [cols]Vec,
|
||||
|
||||
/// The number of columns, e.g. Mat3x4.cols == 3
|
||||
|
|
@ -48,104 +64,142 @@ pub fn Mat(
|
|||
|
||||
pub usingnamespace switch (Matrix) {
|
||||
inline math.Mat3x3, math.Mat3x3h, math.Mat3x3d => struct {
|
||||
pub inline fn init(
|
||||
col0: RowVec,
|
||||
col1: RowVec,
|
||||
col2: RowVec,
|
||||
) Matrix {
|
||||
/// Constructs a 3x3 matrix with the given rows. For example to write a translation
|
||||
/// matrix like in the left part of this equation:
|
||||
///
|
||||
/// ```
|
||||
/// |1 0 tx| |x | |x+z*tx|
|
||||
/// |0 1 ty| |y | = |y+z*ty|
|
||||
/// |0 0 tz| |z=1| |tz |
|
||||
/// ```
|
||||
///
|
||||
/// You would write it with the same visual layout:
|
||||
///
|
||||
/// ```
|
||||
/// const m = Mat3x3.init(
|
||||
/// vec4(1, 0, tx),
|
||||
/// vec4(0, 1, ty),
|
||||
/// vec4(0, 0, tz),
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// Note that Mach matrices use [column-major storage and column-vectors](https://machengine.org/engine/math/matrix-storage/).
|
||||
pub inline fn init(r0: RowVec, r1: RowVec, r2: RowVec) Matrix {
|
||||
return .{ .v = [_]Vec{
|
||||
Vec.init(col0.x(), col0.y(), col0.z(), 1),
|
||||
Vec.init(col1.x(), col1.y(), col1.z(), 1),
|
||||
Vec.init(col2.x(), col2.y(), col2.z(), 1),
|
||||
Vec.init(r0.x(), r1.x(), r2.x(), 1),
|
||||
Vec.init(r0.y(), r1.y(), r2.y(), 1),
|
||||
Vec.init(r0.z(), r1.z(), r2.z(), 1),
|
||||
} };
|
||||
}
|
||||
|
||||
/// Constructs a 2D matrix which scales each dimension by the given vector.
|
||||
// TODO: needs tests
|
||||
pub inline fn scale(v: math.Vec2) Matrix {
|
||||
pub inline fn scale(s: math.Vec2) Matrix {
|
||||
return init(
|
||||
RowVec.init(v.x(), 0, 0, 1),
|
||||
RowVec.init(0, v.y(), 0, 1),
|
||||
RowVec.init(0, 0, 1, 1),
|
||||
RowVec.init(s.x(), 0, 0),
|
||||
RowVec.init(0, s.y(), 0),
|
||||
RowVec.init(0, 0, 1),
|
||||
);
|
||||
}
|
||||
|
||||
/// Constructs a 2D matrix which scales each dimension by the given scalar.
|
||||
// TODO: needs tests
|
||||
pub inline fn scaleScalar(scalar: Vec.T) Matrix {
|
||||
return scale(Vec.splat(scalar));
|
||||
pub inline fn scaleScalar(t: Vec.T) Matrix {
|
||||
return scale(Vec.splat(t));
|
||||
}
|
||||
|
||||
/// Constructs a 2D matrix which translates coordinates by the given vector.
|
||||
// TODO: needs tests
|
||||
pub inline fn translate(v: math.Vec2) Matrix {
|
||||
pub inline fn translate(t: math.Vec2) Matrix {
|
||||
return init(
|
||||
RowVec.init(1, 0, 0),
|
||||
RowVec.init(0, 1, 0),
|
||||
RowVec.init(v.x(), v.y(), 1),
|
||||
RowVec.init(1, 0, t.x()),
|
||||
RowVec.init(0, 1, t.y()),
|
||||
RowVec.init(0, 0, 1),
|
||||
);
|
||||
}
|
||||
|
||||
/// Constructs a 2D matrix which translates coordinates by the given scalar.
|
||||
// TODO: needs tests
|
||||
pub inline fn translateScalar(scalar: Vec.T) Matrix {
|
||||
return translate(Vec.splat(scalar));
|
||||
pub inline fn translateScalar(t: Vec.T) Matrix {
|
||||
return translate(Vec.splat(t));
|
||||
}
|
||||
|
||||
/// Returns the translation component of the matrix.
|
||||
// TODO: needs tests
|
||||
pub inline fn translation(v: Matrix) math.Vec2 {
|
||||
return math.Vec2.init(v.v[2].x(), v.v[2].y());
|
||||
pub inline fn translation(t: Matrix) math.Vec2 {
|
||||
return math.Vec2.init(t.v[2].x(), t.v[2].y());
|
||||
}
|
||||
},
|
||||
inline math.Mat4x4, math.Mat4x4h, math.Mat4x4d => struct {
|
||||
pub inline fn init(col0: Vec, col1: Vec, col2: Vec, col3: Vec) Matrix {
|
||||
return .{ .v = [_]RowVec{
|
||||
col0,
|
||||
col1,
|
||||
col2,
|
||||
col3,
|
||||
/// Constructs a 4x4 matrix with the given rows. For example to write a translation
|
||||
/// matrix like in the left part of this equation:
|
||||
///
|
||||
/// ```
|
||||
/// |1 0 0 tx| |x | |x+w*tx|
|
||||
/// |0 1 0 ty| |y | = |y+w*ty|
|
||||
/// |0 0 1 tz| |z | |z+w*tz|
|
||||
/// |0 0 0 tw| |w=1| |tw |
|
||||
/// ```
|
||||
///
|
||||
/// You would write it with the same visual layout:
|
||||
///
|
||||
/// ```
|
||||
/// const m = Mat4x4.init(
|
||||
/// vec4(1, 0, 0, tx),
|
||||
/// vec4(0, 1, 0, ty),
|
||||
/// vec4(0, 0, 1, tz),
|
||||
/// vec4(0, 0, 0, tw),
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// Note that Mach matrices use [column-major storage and column-vectors](https://machengine.org/engine/math/matrix-storage/).
|
||||
pub inline fn init(r0: Vec, r1: RowVec, r2: RowVec, r3: RowVec) Matrix {
|
||||
return .{ .v = [_]Vec{
|
||||
Vec.init(r0.x(), r1.x(), r2.x(), r3.x()),
|
||||
Vec.init(r0.y(), r1.y(), r2.y(), r3.y()),
|
||||
Vec.init(r0.z(), r1.z(), r2.z(), r3.z()),
|
||||
Vec.init(r0.w(), r1.w(), r2.w(), r3.w()),
|
||||
} };
|
||||
}
|
||||
|
||||
/// Constructs a 3D matrix which scales each dimension by the given vector.
|
||||
// TODO: needs tests
|
||||
pub inline fn scale(v: math.Vec3) Matrix {
|
||||
pub inline fn scale(s: math.Vec3) Matrix {
|
||||
return init(
|
||||
RowVec.init(v.x(), 0, 0, 0),
|
||||
RowVec.init(0, v.y(), 0, 0),
|
||||
RowVec.init(0, 0, v.z(), 0),
|
||||
RowVec.init(0, 0, 0, 1),
|
||||
Vec.init(s.x(), 0, 0, 0),
|
||||
Vec.init(0, s.y(), 0, 0),
|
||||
Vec.init(0, 0, s.z(), 0),
|
||||
Vec.init(0, 0, 0, 1),
|
||||
);
|
||||
}
|
||||
|
||||
/// Constructs a 3D matrix which scales each dimension by the given scalar.
|
||||
// TODO: needs tests
|
||||
pub inline fn scaleScalar(scalar: Vec.T) Matrix {
|
||||
return scale(Vec.splat(scalar));
|
||||
pub inline fn scaleScalar(s: Vec.T) Matrix {
|
||||
return scale(Vec.splat(s));
|
||||
}
|
||||
|
||||
/// Constructs a 3D matrix which translates coordinates by the given vector.
|
||||
// TODO: needs tests
|
||||
pub inline fn translate(v: math.Vec3) Matrix {
|
||||
pub inline fn translate(t: math.Vec3) Matrix {
|
||||
return init(
|
||||
RowVec.init(1, 0, 0, 0),
|
||||
RowVec.init(0, 1, 0, 0),
|
||||
RowVec.init(0, 0, 1, 0),
|
||||
RowVec.init(v.x(), v.y(), v.z(), 1),
|
||||
RowVec.init(1, 0, 0, t.x()),
|
||||
RowVec.init(0, 1, 0, t.y()),
|
||||
RowVec.init(0, 0, 1, t.z()),
|
||||
RowVec.init(0, 0, 0, 1),
|
||||
);
|
||||
}
|
||||
|
||||
/// Constructs a 3D matrix which translates coordinates by the given scalar.
|
||||
// TODO: needs tests
|
||||
pub inline fn translateScalar(scalar: Vec.T) Matrix {
|
||||
return translate(Vec.splat(scalar));
|
||||
pub inline fn translateScalar(t: Vec.T) Matrix {
|
||||
return translate(Vec.splat(t));
|
||||
}
|
||||
|
||||
/// Returns the translation component of the matrix.
|
||||
// TODO: needs tests
|
||||
pub inline fn translation(v: Matrix) math.Vec3 {
|
||||
return math.Vec3.init(v.v[3].x(), v.v[3].y(), v.v[3].z());
|
||||
pub inline fn translation(t: Matrix) math.Vec3 {
|
||||
return math.Vec3.init(t.v[3].x(), t.v[3].y(), t.v[3].z());
|
||||
}
|
||||
|
||||
/// Constructs an orthographic projection matrix; an orthogonal transformation matrix
|
||||
|
|
@ -174,10 +228,10 @@ pub fn Mat(
|
|||
const ty = (top + bottom) / (bottom - top);
|
||||
const tz = near / (near - far);
|
||||
return init(
|
||||
RowVec.init(xx, 0, 0, 0),
|
||||
RowVec.init(0, yy, 0, 0),
|
||||
RowVec.init(0, 0, zz, 0),
|
||||
RowVec.init(tx, ty, tz, 1),
|
||||
RowVec.init(xx, 0, 0, tx),
|
||||
RowVec.init(0, yy, 0, ty),
|
||||
RowVec.init(0, 0, zz, tz),
|
||||
RowVec.init(0, 0, 0, 1),
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
@ -381,14 +435,14 @@ test "n" {
|
|||
|
||||
test "init" {
|
||||
try testing.expect(math.Mat3x3, math.mat3x3(
|
||||
math.vec3(1, 2, 3),
|
||||
math.vec3(4, 5, 6),
|
||||
math.vec3(7, 8, 9),
|
||||
math.vec3(1, 0, 1337),
|
||||
math.vec3(0, 1, 7331),
|
||||
math.vec3(0, 0, 1),
|
||||
)).eql(math.Mat3x3{
|
||||
.v = [_]math.Vec4{
|
||||
math.Vec4.init(1, 2, 3, 1),
|
||||
math.Vec4.init(4, 5, 6, 1),
|
||||
math.Vec4.init(7, 8, 9, 1),
|
||||
math.Vec4.init(1, 0, 0, 1),
|
||||
math.Vec4.init(0, 1, 0, 1),
|
||||
math.Vec4.init(1337, 7331, 1, 1),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue