pub type Matrix = [[f32; 4]; 4];
pub fn identity() -> Matrix {
[
[1.0, 0.0, 0.0, 0.0],
[0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[0.0, 0.0, 0.0, 1.0],
]
}
pub fn translate(x: f32, y: f32, z: f32) -> Matrix {
[
[1.0, 0.0, 0.0, 0.0],
[0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[x, y, z, 1.0],
]
}
pub fn scale(x: f32, y: f32, z: f32) -> Matrix {
[
[x, 0.0, 0.0, 0.0],
[0.0, y, 0.0, 0.0],
[0.0, 0.0, z, 0.0],
[0.0, 0.0, 0.0, 1.0],
]
}
pub fn rotate_x(angle: f32) -> Matrix {
let radians = angle.to_radians();
let sin = radians.sin();
let cos = radians.cos();
[
[1.0, 0.0, 0.0, 0.0],
[0.0, cos, sin, 0.0],
[0.0, -sin, cos, 0.0],
[0.0, 0.0, 0.0, 1.0],
]
}
pub fn rotate_y(angle: f32) -> Matrix {
let radians = angle.to_radians();
let sin = radians.sin();
let cos = radians.cos();
[
[cos, 0.0, -sin, 0.0],
[0.0, 1.0, 0.0, 0.0],
[sin, 0.0, cos, 0.0],
[0.0, 0.0, 0.0, 1.0],
]
}
pub fn rotate_z(angle: f32) -> Matrix {
let radians = angle.to_radians();
let sin = radians.sin();
let cos = radians.cos();
[
[cos, -sin, 0.0, 0.0],
[sin, cos, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[0.0, 0.0, 0.0, 1.0],
]
}
pub fn orthographic(width: f32, height: f32, depth: f32) -> Matrix {
let x = 2.0 / width;
let y = -2.0 / height;
let z = -2.0 / depth;
[
[x, 0.0, 0.0, 0.0],
[0.0, y, 0.0, 0.0],
[0.0, 0.0, z, 0.0],
[-1.0, 1.0, -1.0, 1.0],
]
}
#[allow(clippy::needless_range_loop)]
pub fn multiply(m1: Matrix, m2: Matrix) -> Matrix {
let mut result = [[0.0; 4]; 4];
for i in 0..4 {
for j in 0..4 {
for k in 0..4 {
result[i][j] += m1[i][k] * m2[k][j];
}
}
}
result
}
#[test]
fn is_identity() {
assert_eq!(
identity(),
[
[1.0, 0.0, 0.0, 0.0],
[0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[0.0, 0.0, 0.0, 1.0]
]
);
}
#[test]
fn is_translate() {
assert_eq!(
translate(15.5, 7.8, 9.0),
[
[1.0, 0.0, 0.0, 0.0],
[0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[15.5, 7.8, 9.0, 1.0]
]
);
}
#[test]
fn is_scale() {
assert_eq!(
scale(4.0, 7.1, 8.2),
[
[4.0, 0.0, 0.0, 0.0],
[0.0, 7.1, 0.0, 0.0],
[0.0, 0.0, 8.2, 0.0],
[0.0, 0.0, 0.0, 1.0]
]
);
}
#[test]
fn is_rotate_x() {
let zero = 0.000_000_043_711_39;
assert_eq!(
rotate_x(90.0),
[
[1.0, 0.0, 0.0, 0.0],
[0.0, -zero, 1.0, 0.0],
[0.0, -1.0, -zero, 0.0],
[0.0, 0.0, 0.0, 1.0]
]
);
}
#[test]
fn is_rotate_y() {
let zero = 0.000_000_043_711_39;
assert_eq!(
rotate_y(90.0),
[
[-zero, 0.0, -1.0, 0.0],
[0.0, 1.0, 0.0, 0.0],
[1.0, 0.0, -zero, 0.0],
[0.0, 0.0, 0.0, 1.0]
]
);
}
#[test]
fn is_rotate_z() {
let zero = 0.000_000_043_711_39;
assert_eq!(
rotate_z(90.0),
[
[-zero, -1.0, 0.0, 0.0],
[1.0, -zero, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[0.0, 0.0, 0.0, 1.0]
]
);
}
#[test]
fn is_orthographic() {
assert_eq!(
orthographic(10.0, 5.0, 1.0),
[
[0.2, 0.0, 0.0, 0.0],
[0.0, -0.4, 0.0, 0.0],
[0.0, 0.0, -2.0, 0.0],
[-1.0, 1.0, -1.0, 1.0]
]
);
}
#[test]
fn is_multiplied() {
let a = translate(3.0, 4.0, 5.0);
let b = scale(6.0, 7.0, 8.0);
assert_eq!(
multiply(a, b),
[
[6.0, 0.0, 0.0, 0.0],
[0.0, 7.0, 0.0, 0.0],
[0.0, 0.0, 8.0, 0.0],
[18.0, 28.0, 40.0, 1.0]
]
);
}