tiny.linear.Mat4
Defined in tiny.linear.
API (14)
Actions
Public operations.
determinantfromColsfromLinearTranslation: The homogeneous matrix of a linear part and a translation.inverse: The inverse, or null when the determinant is zero, NaN, or too small for its reciprocal to be a finite nonzero f32.lookAt: The view matrix of a camera ateyelooking attarget, or null when the two coincide or the view direction is parallel toup.mul:a b: applyingb, thena.mulVec:m v, summed asc0 v.x + c1 v.y + c2 v.z + c3 v.w.orthographic: An orthographic projection of the view-space box between the given planes, mapping view depth-nearto clip depth 0 and-farto 1.perspective: A perspective projection with vertical field of viewfov_yradians andaspectwidth over height, mapping view depth-nearto clip depth 0 and-farto 1.rowscaletranspose
Types and contracts
Public types and contracts.
Fields and members
Public fields and members.
Source
Source: lib/linear/src/matrix.zig:97
zig
pub const Mat4 = extern struct { cols: [4]Vec4 = .{ .{ .x = 1 }, .{ .y = 1 }, .{ .z = 1 }, .{ .w = 1 }, }, pub const identity: Mat4 = .{}; pub fn fromCols(c0: Vec4, c1: Vec4, c2: Vec4, c3: Vec4) Mat4 { return .{ .cols = .{ c0, c1, c2, c3 } }; } /// The homogeneous matrix of a linear part and a translation. pub fn fromLinearTranslation(linear: Mat3, translation: Vec3) Mat4 { return fromCols( Vec4.fromVec3(linear.cols[0], 0), Vec4.fromVec3(linear.cols[1], 0), Vec4.fromVec3(linear.cols[2], 0), Vec4.fromVec3(translation, 1), ); } pub fn row(m: Mat4, index: usize) Vec4 { assert(index < 4); const lanes = [4][4]f32{ m.cols[0].toArray(), m.cols[1].toArray(), m.cols[2].toArray(), m.cols[3].toArray(), }; return .{ .x = lanes[0][index], .y = lanes[1][index], .z = lanes[2][index], .w = lanes[3][index] }; } pub fn transpose(m: Mat4) Mat4 { return fromCols(m.row(0), m.row(1), m.row(2), m.row(3)); } /// `m v`, summed as `c0 v.x + c1 v.y + c2 v.z + c3 v.w`. pub fn mulVec(m: Mat4, v: Vec4) Vec4 { return m.cols[0].scale(v.x) .add(m.cols[1].scale(v.y)) .add(m.cols[2].scale(v.z)) .add(m.cols[3].scale(v.w)); } /// `a b`: applying `b`, then `a`. pub fn mul(a: Mat4, b: Mat4) Mat4 { return fromCols( a.mulVec(b.cols[0]), a.mulVec(b.cols[1]), a.mulVec(b.cols[2]), a.mulVec(b.cols[3]), ); } pub fn scale(m: Mat4, s: f32) Mat4 { return fromCols(m.cols[0].scale(s), m.cols[1].scale(s), m.cols[2].scale(s), m.cols[3].scale(s)); } pub fn determinant(m: Mat4) f32 { const minors = Minors.of(m); return minors.determinant(); } /// The inverse, or null when the determinant is zero, NaN, or too small /// for its reciprocal to be a finite nonzero f32. pub fn inverse(m: Mat4) ?Mat4 { const minors = Minors.of(m); const inverse_determinant = reciprocal(minors.determinant()) orelse return null; const a = m.cols; const adjugate = fromCols( .{ .x = a[1].y * minors.c5 - a[1].z * minors.c4 + a[1].w * minors.c3, .y = -a[0].y * minors.c5 + a[0].z * minors.c4 - a[0].w * minors.c3, .z = a[3].y * minors.s5 - a[3].z * minors.s4 + a[3].w * minors.s3, .w = -a[2].y * minors.s5 + a[2].z * minors.s4 - a[2].w * minors.s3, }, .{ .x = -a[1].x * minors.c5 + a[1].z * minors.c2 - a[1].w * minors.c1, .y = a[0].x * minors.c5 - a[0].z * minors.c2 + a[0].w * minors.c1, .z = -a[3].x * minors.s5 + a[3].z * minors.s2 - a[3].w * minors.s1, .w = a[2].x * minors.s5 - a[2].z * minors.s2 + a[2].w * minors.s1, }, .{ .x = a[1].x * minors.c4 - a[1].y * minors.c2 + a[1].w * minors.c0, .y = -a[0].x * minors.c4 + a[0].y * minors.c2 - a[0].w * minors.c0, .z = a[3].x * minors.s4 - a[3].y * minors.s2 + a[3].w * minors.s0, .w = -a[2].x * minors.s4 + a[2].y * minors.s2 - a[2].w * minors.s0, }, .{ .x = -a[1].x * minors.c3 + a[1].y * minors.c1 - a[1].z * minors.c0, .y = a[0].x * minors.c3 - a[0].y * minors.c1 + a[0].z * minors.c0, .z = -a[3].x * minors.s3 + a[3].y * minors.s1 - a[3].z * minors.s0, .w = a[2].x * minors.s3 - a[2].y * minors.s1 + a[2].z * minors.s0, }, ); return adjugate.scale(inverse_determinant); } /// The view matrix of a camera at `eye` looking at `target`, or null when /// the two coincide or the view direction is parallel to `up`. pub fn lookAt(eye: Vec3, target: Vec3, up: Vec3) ?Mat4 { const forward = target.sub(eye).normalized(0) orelse return null; const side = forward.cross(up).normalized(0) orelse return null; const camera_up = side.cross(forward); return fromCols( .{ .x = side.x, .y = camera_up.x, .z = -forward.x }, .{ .x = side.y, .y = camera_up.y, .z = -forward.y }, .{ .x = side.z, .y = camera_up.z, .z = -forward.z }, .{ .x = -side.dot(eye), .y = -camera_up.dot(eye), .z = forward.dot(eye), .w = 1 }, ); } /// A perspective projection with vertical field of view `fov_y` radians /// and `aspect` width over height, mapping view depth `-near` to clip /// depth 0 and `-far` to 1. pub fn perspective(fov_y: f32, aspect: f32, near: f32, far: f32) Mat4 { assert(fov_y > 0); assert(fov_y < std.math.pi); assert(aspect > 0); assert(near > 0); assert(far > near); const focal = 1 / @tan(fov_y * 0.5); const depth = 1 / (near - far); return fromCols( .{ .x = focal / aspect }, .{ .y = focal }, .{ .z = far * depth, .w = -1 }, .{ .z = near * far * depth }, ); } /// An orthographic projection of the view-space box between the given /// planes, mapping view depth `-near` to clip depth 0 and `-far` to 1. pub fn orthographic(left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32) Mat4 { assert(right != left); assert(top != bottom); assert(far != near); const width = 1 / (right - left); const height = 1 / (top - bottom); const depth = 1 / (near - far); return fromCols( .{ .x = 2 * width }, .{ .y = 2 * height }, .{ .z = depth }, .{ .x = -(right + left) * width, .y = -(top + bottom) * height, .z = near * depth, .w = 1 }, ); }};Source: lib/linear/src/root.zig:13
zig
pub const Mat4 = matrix.Mat4;Audit
| Definitions | 14 |
|---|---|
| Public names | 14 |
| Members | 1 |
| Version | 26.7.0 |
| Revision | daab053ee433 |