A 4×4 matrix: everything a 3×3 matrix does, plus the translation a transformation of space needs.
Column-major, so c3 is the translation column and to_array is exactly the sixteen floats a mat4x4<f32> occupies in a storage or uniform buffer. A point is a Vec4 with w = 1, a direction one with w = 0, and the fourth row of a projection matrix puts the perspective divide into w.
Values are immutable.
approx
pub fn Mat4::approx(Self, Self, eps? : Float) -> Bool
Whether the two matrices agree to within eps element by element.
col
pub fn Mat4::col(Self, Int32) -> Vec4
Column index, counted from zero.
determinant
pub fn Mat4::determinant(Self) -> Float
The signed hypervolume the matrix scales by: zero exactly when it is singular.
from_array
pub fn Mat4::from_array(FixedArray[Float]) -> Self
The matrix from sixteen values in column-major order — the order a mat4x4<f32> sits in a buffer in.
Aborts if the array does not hold sixteen values.
from_axis_angle
pub fn Mat4::from_axis_angle(Vec3, Float) -> Self
The rotation of radians about axis, by the right-hand rule.
from_cols
pub fn Mat4::from_cols(Vec4, Vec4, Vec4, Vec4) -> Self
The matrix with the four vecs as its columns.
from_euler
pub fn Mat4::from_euler(EulerOrder, Vec3) -> Self
The rotation the three angles describe, taken in order, in radians, read by axis. See Quat::from_euler for how the components are read and which orders that reading cannot express.
from_euler_turns
pub fn Mat4::from_euler_turns(EulerOrder, Turns) -> Self
The rotation the three turns describe, in the order the order names them.
from_mat3
pub fn Mat4::from_mat3(Mat3) -> Self
The matrix that does what the 3×3 matrix does to x, y and z, and leaves w alone.
from_quat
pub fn Mat4::from_quat(Quat) -> Self
The rotation the quaternion holds.
from_rows
pub fn Mat4::from_rows(Vec4, Vec4, Vec4, Vec4) -> Self
The matrix with the four vecs as its rows.
from_scale
pub fn Mat4::from_scale(Vec3) -> Self
The matrix that scales each axis by the matching component of s.
from_translation
pub fn Mat4::from_translation(Vec3) -> Self
The matrix that moves every point by t.
from_trs
pub fn Mat4::from_trs(Trs) -> Self
The matrix that scales by scale, then rotates by rotation, then moves by translation.
mbt check
test {
let scale : @moonmath.Vec3 = @moonmath.Vec3::splat(2.0)
let offset = @moonmath.Vec3::new(1.0, 0.0, 0.0)
let m = @moonmath.Mat4::from_trs(
@moonmath.Trs::new(offset, @moonmath.Quat::identity(), scale),
)
// One, scaled by two, then moved one along x.
assert_true(
m
.transform_point(@moonmath.Vec3::one())
.approx(@moonmath.Vec3::new(3.0, 2.0, 2.0)),
)
}
frustum
pub fn Mat4::frustum(Float, Float, Float, Float, Float, Float) -> Self
A perspective projection from an explicit frustum with the depth range 0..1.
The rectangle on the near plane becomes the full clip volume, so the six numbers are all a camera needs: left and bottom are negative, right and top positive for a centred view, and offsetting them is what a lens shift does.
frustum_gl
pub fn Mat4::frustum_gl(Float, Float, Float, Float, Float, Float) -> Self
A perspective projection from an explicit frustum with the depth range -1..1.
get
pub fn Mat4::get(Self, Int32, Int32) -> Float
The element at row and column, both counted from zero.
identity
pub fn Mat4::identity() -> Self
The identity: the matrix that changes nothing.
inverse
pub fn Mat4::inverse(Self) -> Self?
The matrix that undoes this one, or None when there is none.
The usual use is the inverse of a camera's view-projection matrix, and the usual singular case is a projection built with far equal to near.
is_finite
pub fn Mat4::is_finite(Self) -> Bool
Whether every element is finite.
look_at
pub fn Mat4::look_at(Vec3, Vec3, Vec3) -> Self
The view matrix of a camera at eye looking at target, with up telling it which way is up.
Right-handed: the camera looks down its own -z, so the third column of the result is eye - target, normalized. up need not be perpendicular to the view direction, only not parallel to it; when it is parallel there is no answer and the identity comes back rather than a matrix full of NaNs.
mul_vec4
pub fn Mat4::mul_vec4(Self, Vec4) -> Vec4
The vector the matrix takes v to, without any division by w.
This is what a shader's matrix * vector does: the projection divide happens after clipping, not here. One expression per component, for the reason given at Mat2::mul_vec2.
orthographic
pub fn Mat4::orthographic(Float, Float, Float, Float, Float, Float) -> Self
An orthographic projection with the depth range 0..1: the box the six planes bound becomes the unit cube in clip space.
Right-handed, so the camera looks down -z and near and far are distances in front of it, both positive. A box with left == right, bottom == top or near == far has no volume to map and gives the identity.
orthographic_gl
pub fn Mat4::orthographic_gl(Float, Float, Float, Float, Float, Float) -> Self
An orthographic projection with the depth range -1..1.
perspective
pub fn Mat4::perspective(Float, Float, Float, Float) -> Self
A perspective projection with the depth range 0..1: the near plane maps to zero and the far plane to one, which is what WebGPU clips against.
fov_y is the vertical field of view in radians and aspect the width divided by the height. Right-handed: the camera looks down -z, so near and far are distances in front of it, both positive.
mbt check
test {
let m = @moonmath.Mat4::perspective(@moonmath.half_pi, 1.0, 0.1, 100.0)
// The near plane lands on depth 0 and the far plane on depth 1.
let near = m.mul_vec4(@moonmath.Vec4::new(0.0, 0.0, -0.1, 1.0))
assert_true(@moonmath.approx(near.z / near.w, 0.0))
let far = m.mul_vec4(@moonmath.Vec4::new(0.0, 0.0, -100.0, 1.0))
assert_true(@moonmath.approx(far.z / far.w, 1.0))
}
perspective_gl
pub fn Mat4::perspective_gl(Float, Float, Float, Float) -> Self
A perspective projection with the depth range -1..1, for a pipeline that clips like OpenGL.
The same as perspective in every other respect; only the third row differs.
perspective_infinite
pub fn Mat4::perspective_infinite(Float, Float, Float) -> Self
A perspective projection with the depth range 0..1 and no far plane.
Precision is better spent near the eye: with no far plane to reach, the depth values crowd into the region where a depth buffer can still tell them apart, instead of being spread over a range whose far end nothing occupies.
perspective_infinite_gl
pub fn Mat4::perspective_infinite_gl(Float, Float, Float) -> Self
A perspective projection with the depth range -1..1 and no far plane.
row
pub fn Mat4::row(Self, Int32) -> Vec4
Row index, counted from zero.
to_array
pub fn Mat4::to_array(Self) -> FixedArray[Float]
The elements in column-major order, the sixteen a buffer holds.
to_trs
pub fn Mat4::to_trs(Self) -> Trs?
The translation, rotation and scale the matrix was built from, or None when it cannot be read that way.
A matrix with shear in it — the common case being a non-uniform scale applied after a rotation — is not a Trs and has no decomposition here; neither has one whose linear part is singular, whose rotation would be unrecoverable. When the determinant is negative the first component of scale carries the sign, because a mirrored basis is a rotation with one flipped axis.
transform_point
pub fn Mat4::transform_point(Self, Vec3) -> Vec3
The point the matrix takes p to, dividing by w when there is one.
A projection matrix leaves the result in homogeneous coordinates; the point only exists after that division, so it happens here. A w of zero — a point on the horizon of a perspective projection — leaves the numerator as it is.
transform_vector
pub fn Mat4::transform_vector(Self, Vec3) -> Vec3
The direction the matrix takes v to, ignoring the translation column.
Directions have no position, so the fourth row must not touch them: a translation leaves a direction alone, as it should.
transpose
pub fn Mat4::transpose(Self) -> Self
The matrix with rows and columns exchanged.
zero
pub fn Mat4::zero() -> Self
The zero matrix: the one that sends everything to the origin and loses w.