Browse the docs

silk.geometry.matrix.

Square 3x3 and 4x4 matrices for projective and three-dimensional transforms.

When to use#

Use Matrix3 for a projective transform of a plane, such as a perspective-correct image warp: a homography that silk.geometry.affine.Affine2 cannot express. Use Matrix4 for transforms in space, such as a CSS matrix3d, a perspective, or a 3D rotation, and to project those transforms back onto a plane. Use Affine2 for every transform of a plane that keeps parallel lines parallel; it is smaller and cheaper.

Details#

A matrix is a Copy struct that holds its entries in the public array values in column-major order: entry (row, column) is values[column * size + row]. That is the order of WGSL, GLSL, and CSS matrix3d, so a matrix copies to a GPU uniform or from CSS as written. A matrix multiplies a column vector: left * right applies right first, then left.

Matrix3.project and Matrix4.project divide by the homogeneous w coordinate and return None where w is zero. Matrix3.transformHomogeneous and Matrix4.transformHomogeneous return the coordinates before that division, for renderers that must clip against w.

Examples#

Round-trip a point through a perspective#

silk
import silk.geometry.matrix { Matrix4 }
import silk.geometry.point { Point3 }
import silk.core.option { Option }

pub fn main() -> i32 {
  let camera = Matrix4<f64>.perspective(100.0) * Matrix4<f64>.rotationY(0.5)
  let inverse = match camera.inverse() {
    Option<Matrix4<f64>>.Some { value } => value
    Option<Matrix4<f64>>.None => {
      return 1
    }
  }
  let point = Point3<f64>.new(10.0, 20.0, 5.0)
  let back = match (inverse * camera).project(point) {
    Option<Point3<f64>>.Some { value } => value
    Option<Point3<f64>>.None => {
      return 2
    }
  }
  if back.x < 9.999999 || back.x > 10.000001 || back.z < 4.999999 || back.z > 5.000001 {
    return 3
  }
  return 0
}

Import as Matrix3 with import silk.geometry.matrix { Matrix3 }.

Public declarations: 2.

Matrix3#

silk
pub struct Matrix3<T>

A 3x3 matrix of number type T, stored in column-major order.

When to use#

Use Matrix3 for a projective transform of a plane (a homography). Use silk.geometry.affine.Affine2 when the transform keeps parallel lines parallel.

Details#

Entry (row, column) is values[column * 3 + row]. The matrix maps (x, y) through the homogeneous vector (x, y, 1): project divides the first two results by the third. left * right applies right first. &a == &b compares all nine entries when T: Equal.

Field values#

silk
pub values: [T; 9]

The nine entries in column-major order: entry (row, column) is values[column * 3 + row].

Implementation Copy for Matrix3<T>#

silk
impl<T: Copy> Copy for Matrix3<T>

Implementation Matrix3<T>#

silk
impl<T> Matrix3<T>

Associated function new#

silk
pub fn new(values: [T; 9]) -> Matrix3<T>

Returns the matrix with values in column-major order.

Implementation Matrix3<T>#

silk
impl<T: Copy> Matrix3<T>

Method at#

silk
pub fn at(self: &Self, row: usize, column: usize) -> T

Returns entry (row, column), where both count from zero.

Gotchas#

The program traps if row or column is greater than 2.

Method transpose#

silk
pub fn transpose(self: Self) -> Matrix3<T>

Returns the matrix with rows and columns exchanged.

Implementation Matrix3<T>#

silk
impl<T: Copy + Zero + One> Matrix3<T>

Associated function identity#

silk
pub fn identity() -> Matrix3<T>

Returns the matrix that maps every point to itself.

Associated function fromAffine#

silk
pub fn fromAffine(transform: Affine2<T>) -> Matrix3<T>

Returns the matrix of the same transform as transform: [xx xy dx; yx yy dy; 0 0 1].

Implementation Matrix3<T>#

silk
impl<T: Copy + Equal + Zero + One> Matrix3<T>

Method toAffine#

silk
pub fn toAffine(self: Self) -> Option<Affine2<T>>

Returns the affine transform of the matrix, or None when its last row is not [0 0 1].

Details#

A matrix whose last row is [0 0 1] keeps parallel lines parallel. Any other last row describes a perspective, which Affine2 cannot hold.

Implementation Matrix3<T>#

silk
impl<T: Copy + Add<T, T> + Subtract<T, T> + Multiply<T, T>> Matrix3<T>

Method determinant#

silk
pub fn determinant(self: Self) -> T

Returns the determinant. Zero means the matrix has no inverse.

Method transformHomogeneous#

silk
pub fn transformHomogeneous(self: Self, point: Point2<T>) -> Vector3<T>

Returns (x', y', w): point mapped through (x, y, 1) before the division by w.

When to use#

Use transformHomogeneous when the sign of w matters, such as to clip the part of a plane behind a projection. Use project for the divided point.

Implementation Matrix3<T>#

silk
impl<T: Copy + Equal + Zero + Add<T, T> + Subtract<T, T> + Multiply<T, T> + Divide<T, T>> Matrix3<
  T
>

Method project#

silk
pub fn project(self: Self, point: Point2<T>) -> Option<Point2<T>>

Returns point mapped through the matrix and divided by w, or None where w is zero.

Gotchas#

A negative w still gives a point, which is the mirror image of a point behind the projection. Use transformHomogeneous to test the sign of w first.

Implementation Matrix3<T>#

silk
impl<
  T: Copy + Equal + Zero + One + Float + Add<T, T> + Subtract<T, T> + Multiply<T, T> + Divide<T, T>
> Matrix3<T>

Method inverse#

silk
pub fn inverse(self: Self) -> Option<Matrix3<T>>

Returns the matrix that undoes self, or None when self has no finite inverse.

Details#

None means the determinant is zero, or that the inverse has an infinite or NaN entry, such as when an input entry is infinite or NaN.

Implementation Multiply<Matrix3<T>, Matrix3<T>> for Matrix3<T>#

silk
impl<T: Copy + Zero + Add<T, T> + Multiply<T, T>> Multiply<Matrix3<T>, Matrix3<T>> for Matrix3<T>

Operation multiply#

silk
fn multiply(left: Self, right: Self) -> Self

Implementation Equal for Matrix3<T>#

silk
impl<T: Equal> Equal for Matrix3<T>

Operation equals#

silk
fn equals(left: &Self, right: &Self) -> bool

Matrix4#

silk
pub struct Matrix4<T>

A 4x4 matrix of number type T, stored in column-major order.

When to use#

Use Matrix4 for transforms in space, such as CSS matrix3d, perspective, and 3D rotations. Use silk.geometry.affine.Affine2 for a transform of a plane.

Details#

Entry (row, column) is values[column * 4 + row], the order of CSS matrix3d(...) arguments and of WGSL mat4x4. The matrix maps (x, y, z) through the homogeneous vector (x, y, z, 1): project divides the first three results by the fourth. left * right applies right first. &a == &b compares all sixteen entries when T: Equal.

Field values#

silk
pub values: [T; 16]

The sixteen entries in column-major order: entry (row, column) is values[column * 4 + row].

Implementation Copy for Matrix4<T>#

silk
impl<T: Copy> Copy for Matrix4<T>

Implementation Matrix4<T>#

silk
impl<T> Matrix4<T>

Associated function new#

silk
pub fn new(values: [T; 16]) -> Matrix4<T>

Returns the matrix with values in column-major order, the order of CSS matrix3d.

Implementation Matrix4<T>#

silk
impl<T: Copy> Matrix4<T>

Method at#

silk
pub fn at(self: &Self, row: usize, column: usize) -> T

Returns entry (row, column), where both count from zero.

Gotchas#

The program traps if row or column is greater than 3.

Method transpose#

silk
pub fn transpose(self: Self) -> Matrix4<T>

Returns the matrix with rows and columns exchanged.

Implementation Matrix4<T>#

silk
impl<T: Copy + Zero + One> Matrix4<T>

Associated function identity#

silk
pub fn identity() -> Matrix4<T>

Returns the matrix that maps every point to itself.

Associated function fromAffine#

silk
pub fn fromAffine(transform: Affine2<T>) -> Matrix4<T>

Returns the matrix of transform acting on x and y, with z unchanged.

Details#

This is the CSS rule for a 2D transform in a 3D context: matrix(a, b, c, d, e, f) equals matrix3d(a, b, 0, 0, c, d, 0, 0, 0, 0, 1, 0, e, f, 0, 1).

Associated function translation#

silk
pub fn translation(offset: Vector3<T>) -> Matrix4<T>

Returns the matrix that moves every point by offset.

Associated function scale#

silk
pub fn scale(x: T, y: T, z: T) -> Matrix4<T>

Returns the matrix that multiplies x by x, y by y, and z by z around the origin.

Implementation Matrix4<T>#

silk
impl<T: Copy + Equal + Zero + One> Matrix4<T>

Method toAffine#

silk
pub fn toAffine(self: Self) -> Option<Affine2<T>>

Returns the affine transform of the matrix, or None when it is not a 2D transform.

Details#

The result is Some exactly when the matrix leaves z and w alone, as CSS "is 2D" requires: entries (2, 0), (3, 0), (2, 1), (3, 1), (0, 2), (1, 2), (3, 2), and (2, 3) are zero and entries (2, 2) and (3, 3) are one.

Implementation Matrix4<T>#

silk
impl<T: Copy + Zero + One + Float + Subtract<T, T>> Matrix4<T>

Associated function rotationX#

silk
pub fn rotationX(radians: T) -> Matrix4<T>

Returns the matrix that rotates by radians around the x axis, turning positive y toward positive z.

Associated function rotationY#

silk
pub fn rotationY(radians: T) -> Matrix4<T>

Returns the matrix that rotates by radians around the y axis, turning positive z toward positive x.

Associated function rotationZ#

silk
pub fn rotationZ(radians: T) -> Matrix4<T>

Returns the matrix that rotates by radians around the z axis, turning positive x toward positive y.

Details#

On the x-y plane this is silk.geometry.affine.Affine2.rotation with the same angle, which is clockwise in a y-down space such as CSS.

Implementation Matrix4<T>#

silk
impl<T: Copy + Zero + One + Subtract<T, T> + Divide<T, T>> Matrix4<T>

Associated function perspective#

silk
pub fn perspective(distance: T) -> Matrix4<T>

Returns the CSS perspective(distance) matrix: a viewer at distance along positive z.

Details#

The matrix is the identity with entry (3, 2) set to -1 / distance, so a point at depth z scales by distance / (distance - z) after project.

Gotchas#

A zero distance divides by zero. CSS treats perspective(0) as no perspective; pass the identity in that case.

Implementation Matrix4<T>#

silk
impl<T: Copy + Add<T, T> + Subtract<T, T> + Multiply<T, T>> Matrix4<T>

Method determinant#

silk
pub fn determinant(self: Self) -> T

Returns the determinant. Zero means the matrix has no inverse.

Method transformHomogeneous#

silk
pub fn transformHomogeneous(self: Self, point: Point3<T>) -> [T; 4]

Returns (x', y', z', w): point mapped through (x, y, z, 1) before the division by w.

When to use#

Use transformHomogeneous when the sign of w matters, such as to clip geometry behind the viewer of a perspective. Use project for the divided point.

Implementation Matrix4<T>#

silk
impl<T: Copy + Equal + Zero + Add<T, T> + Subtract<T, T> + Multiply<T, T> + Divide<T, T>> Matrix4<
  T
>

Method project#

silk
pub fn project(self: Self, point: Point3<T>) -> Option<Point3<T>>

Returns point mapped through the matrix and divided by w, or None where w is zero.

Gotchas#

A negative w still gives a point, which is the mirror image of a point behind the viewer. Use transformHomogeneous to test the sign of w first.

Method projectPoint2#

silk
pub fn projectPoint2(self: Self, point: Point2<T>) -> Option<Point2<T>>

Returns the point of the plane z = 0 mapped through the matrix, flattened onto the x-y plane, or None where w is zero.

When to use#

Use projectPoint2 to draw a 2D element under a CSS 3D transform: the element lies in the plane z = 0, and the screen shows the x and y of each projected point.

Implementation Matrix4<T>#

silk
impl<
  T: Copy + Equal + Zero + One + Float + Add<T, T> + Subtract<T, T> + Multiply<T, T> + Divide<T, T>
> Matrix4<T>

Method inverse#

silk
pub fn inverse(self: Self) -> Option<Matrix4<T>>

Returns the matrix that undoes self, or None when self has no finite inverse.

Details#

The inverse is the adjugate divided by the determinant. None means the determinant is zero, or that the inverse has an infinite or NaN entry, such as when an input entry is infinite or NaN.

Implementation Multiply<Matrix4<T>, Matrix4<T>> for Matrix4<T>#

silk
impl<T: Copy + Zero + Add<T, T> + Multiply<T, T>> Multiply<Matrix4<T>, Matrix4<T>> for Matrix4<T>

Operation multiply#

silk
fn multiply(left: Self, right: Self) -> Self

Implementation Equal for Matrix4<T>#

silk
impl<T: Equal> Equal for Matrix4<T>

Operation equals#

silk
fn equals(left: &Self, right: &Self) -> bool

Category: Geometry.

Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2.

View the source of this page