use crate::config::PlacementConfig;
pub type Matrix = [f64; 12];
pub const 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];
pub fn placement(placement: &PlacementConfig) -> Matrix {
let [x, y, z] = placement.rotate.unwrap_or_default().map(f64::to_radians);
let [tx, ty, tz] = placement.at.unwrap_or_default();
let (sx, cx) = x.sin_cos();
let (sy, cy) = y.sin_cos();
let (sz, cz) = z.sin_cos();
[
cz * cy,
cz * sy * sx - sz * cx,
cz * sy * cx + sz * sx,
tx,
sz * cy,
sz * sy * sx + cz * cx,
sz * sy * cx - cz * sx,
ty,
-sy,
cy * sx,
cy * cx,
tz,
]
}
pub fn translation([dx, dy, dz]: [f64; 3]) -> Matrix {
let mut m = IDENTITY;
m[3] = dx;
m[7] = dy;
m[11] = dz;
m
}
pub fn compose(outer: &Matrix, inner: &Matrix) -> Matrix {
let mut m = [0.0; 12];
for row in 0..3 {
for col in 0..4 {
let carried = (0..3)
.map(|k| outer[row * 4 + k] * inner[k * 4 + col])
.sum::<f64>();
m[row * 4 + col] = carried + if col == 3 { outer[row * 4 + 3] } else { 0.0 };
}
}
m
}
pub fn apply(m: &Matrix, p: [f64; 3]) -> [f64; 3] {
[0, 1, 2].map(|row| (0..3).map(|k| m[row * 4 + k] * p[k]).sum::<f64>() + m[row * 4 + 3])
}