Module truster::matrix[][src]

Expand description

A 2D transformation matrix for points and vectors. For now, only floating point matrices are supported. Generics may come in the future.

Examples

Initialize a new Matrix with new:

let m = Matrix::new(&[
     1.0,  2.0,  3.0,  4.0,
     5.5,  6.5,  7.5,  8.5,
     9.0, 10.0, 11.0, 12.0,
    13.5, 14.5, 15.5, 16.5,
]);

let output = format!("{}", m);
assert_eq!(output,
"/1 2 3 4\\
|5.5 6.5 7.5 8.5|
|9 10 11 12|
\\13.5 14.5 15.5 16.5/")

Individual values can be accessed and mutated by index:

let m = Matrix::new(&[
     1.0,  2.0,  3.0,  4.0,
     5.5,  6.5,  7.5,  8.5,
     9.0, 10.0, 11.0, 12.0,
    13.5, 14.5, 15.5, 16.5,
]);

assert_eq!(m[[0, 0]], 1.0);
assert_eq!(m[[0, 3]], 4.0);
assert_eq!(m[[1, 0]], 5.5);
assert_eq!(m[[1, 2]], 7.5);
assert_eq!(m[[2, 2]], 11.0);
assert_eq!(m[[3, 0]], 13.5);
assert_eq!(m[[3, 2]], 15.5);

Matrices can be multiplied together:

let m1 = Matrix::new(&[
    1.0, 2.0, 3.0, 4.0,
    5.0, 6.0, 7.0, 8.0,
    9.0, 8.0, 7.0, 6.0,
    5.0, 4.0, 3.0, 2.0,
]);

let m2 = Matrix::new(&[
    -2.0, 1.0, 2.0,  3.0,
     3.0, 2.0, 1.0, -1.0,
     4.0, 3.0, 6.0,  5.0,
     1.0, 2.0, 7.0,  8.0,
]);

assert_eq!(m1 * &m2, Matrix::new(&[
    20.0, 22.0,  50.0,  48.0,
    44.0, 54.0, 114.0, 108.0,
    40.0, 58.0, 110.0, 102.0,
    16.0, 26.0,  46.0,  42.0,
]));

You can also multiply matrices with tuples to get their transform:

use truster::tuple::Tuple;

let m = Matrix::new(&[
    1.0, 2.0, 3.0, 4.0,
    2.0, 4.0, 4.0, 2.0,
    8.0, 6.0, 4.0, 1.0,
    0.0, 0.0, 0.0, 1.0,
]);

let p = Tuple::point(1.0, 2.0, 3.0);
assert_eq!(&m * p, Tuple::point(18.0, 24.0, 33.0));

Take the transpose of a matrix with Matrix::transpose:

let m = Matrix::new(&[
     1.0,  2.0,  3.0,  4.0,
    12.0, 42.0, 69.0, 37.0,
    21.0, 24.0, 96.0, 73.0,
    -1.0, -2.0, -3.0, -4.0,
]);

assert_eq!(m.transpose(), Matrix::new(&[
	1.0, 12.0, 21.0, -1.0,
	2.0, 42.0, 24.0, -2.0,
	3.0, 69.0, 96.0, -3.0,
	4.0, 37.0, 73.0, -4.0,
]));

Take the inverse of a matrix with Matrix::inverse:

let m1 = Matrix::new(&[
     3.0, -9.0,  7.0,  3.0,
     3.0, -8.0,  2.0, -9.0,
    -4.0,  4.0,  4.0,  1.0,
    -6.0,  5.0, -1.0,  1.0,
]);

let m2 = Matrix::new(&[
    8.0,  2.0, 2.0, 2.0,
    3.0, -1.0, 7.0, 0.0,
    7.0,  0.0, 5.0, 4.0,
    6.0, -2.0, 0.0, 5.0,
]);

let m3 = m1.clone() * &m2;
// m3 * &m2.inverse() == m1 // approximately (floating points)

Transformations

This library is meant for using matrices as transformations, so all common transformations can be used directly.

The supported transformations are:

  • Translation
use truster::tuple::Tuple;

let t = Matrix::translation(5.0, -3.0, 2.0);
let p = Tuple::point(-3.0, 4.0, 5.0);
assert_eq!(&t * p, Tuple::point(2.0, 1.0, 7.0));

// vectors stay unchanged.
let t = Matrix::translation(5.0, -3.0, 2.0);
let v = Tuple::vector(-3.0, 4.0, 5.0);
assert_eq!(&t * v, v);
  • Scaling
use truster::tuple::Tuple;

let t = Matrix::scaling(2.0, 3.0, 4.0);
let p = Tuple::point(-4.0, 6.0, 8.0);
assert_eq!(&t * p, Tuple::point(-8.0, 18.0, 32.0));
  • Rotation around X axis.
use truster::tuple::Tuple;

use std::f64::consts::PI;

let t = Matrix::rotation_x(PI / 2.0);
let p = Tuple::point(0.0, 1.0, 0.0);
// &t * p == Tuple::point(0.0, 0.0, 1.0)  // approximately
  • Rotation around Y axis.
use truster::tuple::Tuple;

use std::f64::consts::PI;

let t = Matrix::rotation_y(PI / 2.0);
let p = Tuple::point(0.0, 0.0, 1.0);
// &t * p == Tuple::point(1.0, 0.0, 0.0)  // approximately
  • Rotation around Z axis.
use truster::tuple::Tuple;

use std::f64::consts::PI;

let t = Matrix::rotation_z(PI / 2.0);
let p = Tuple::point(0.0, 1.0, 0.0);
// &t * p == Tuple::point(-1.0, 0.0, 0.0)  // approximately
  • Shearing
use truster::tuple::Tuple;

let t = Matrix::shearing(0.0, 1.0, 0.0, 0.0, 0.0, 0.0);
let p = Tuple::point(2.0, 3.0, 4.0);
assert_eq!(&t * p, Tuple::point(6.0, 3.0, 4.0));

Transformations can be chained together by multiplying:

use truster::tuple::Tuple;

use std::f64::consts::PI;

let p = Tuple::point(1.0, 0.0, 1.0);

let a = Matrix::rotation_x(PI / 2.0);
let b = Matrix::scaling(5.0, 5.0, 5.0);
let c = Matrix::translation(10.0, 5.0, 7.0);

let p2 = &a*p;
let p3 = &b*p2;
let p4 = &c*p3;

let t = c * &b * &a;

assert_eq!(&t*p, p4);

Structs