use crate::math::{ Vec3 }; #[repr(C)] #[derive(Clone, Copy, Debug)] pub struct Mat4 { pub data: [f32; 16], } impl Mat4 { pub fn identity() -> Self { Self { data: [ 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 translation(x: f32, y: f32, z: f32) -> Self { Self { data: [ 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) -> Self { Self { data: [ 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 rotation_x(angle: f32) -> Self { let c = angle.cos(); let s = angle.sin(); Self { data: [ 1.0, 0.0, 0.0, 0.0, 0.0, c, s, 0.0, 0.0, -s, c, 0.0, 0.0, 0.0, 0.0, 1.0, ], } } pub fn rotation_y(angle: f32) -> Self { let c = angle.cos(); let s = angle.sin(); Self { data: [ c, 0.0, -s, 0.0, 0.0, 1.0, 0.0, 0.0, s, 0.0, c, 0.0, 0.0, 0.0, 0.0, 1.0, ], } } pub fn rotation_z(angle: f32) -> Self { let c = angle.cos(); let s = angle.sin(); Self { data: [ c, s, 0.0, 0.0, -s, c, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, ], } } pub fn perspective(fov: f32, aspect: f32, near: f32, far: f32) -> Self { let f = 1.0 / (fov / 2.0).tan(); let nf = 1.0 / (near - far); Self { data: [ f / aspect, 0.0, 0.0, 0.0, 0.0, f, 0.0, 0.0, 0.0, 0.0, (far + near) * nf, -1.0, 0.0, 0.0, 2.0 * far * near * nf, 0.0, ], } } pub fn look_at(eye: Vec3, target: Vec3, up: Vec3) -> Self { let f = (target - eye).normalize(); let r = f.cross(&up).normalize(); let u = r.cross(&f); Self { data: [ r.x(), u.x(), -f.x(), 0.0, r.y(), u.y(), -f.y(), 0.0, r.z(), u.z(), -f.z(), 0.0, -r.dot(&eye), -u.dot(&eye), f.dot(&eye), 1.0, ], } } pub fn as_ptr(&self) -> *const f32 { self.data.as_ptr() } } impl std::ops::Mul for Mat4 { type Output = Self; fn mul(self, rhs: Self) -> Self { let mut result = [0.0f32; 16]; for row in 0..4 { for col in 0..4 { for k in 0..4 { result[col * 4 + row] += self.data[k * 4 + row] * rhs.data[col * 4 + k]; } } } Self { data: result } } }