use core::ops::{Add, Mul, Sub}; #[repr(C)] #[derive(Debug, Copy, Clone, Default)] pub struct Vec2 { pub x: f32, pub y: f32, } #[repr(C)] #[derive(Debug, Copy, Clone, Default)] pub struct Vec3 { pub x: f32, pub y: f32, pub z: f32, } #[repr(C)] #[derive(Debug, Copy, Clone, Default)] pub struct Vec4 { pub x: f32, pub y: f32, pub z: f32, pub w: f32, } #[repr(C)] #[derive(Debug, Copy, Clone, Default)] pub struct Mat4 { pub m: [f32; 16], } #[allow(non_camel_case_types)] pub type pxl8_vec2 = Vec2; #[allow(non_camel_case_types)] pub type pxl8_vec3 = Vec3; #[allow(non_camel_case_types)] pub type pxl8_vec4 = Vec4; #[allow(non_camel_case_types)] pub type pxl8_mat4 = Mat4; impl Vec3 { pub const ZERO: Vec3 = Vec3 { x: 0.0, y: 0.0, z: 0.0 }; pub const Y: Vec3 = Vec3 { x: 0.0, y: 1.0, z: 0.0 }; pub fn new(x: f32, y: f32, z: f32) -> Self { Self { x, y, z } } pub fn dot(self, rhs: Self) -> f32 { self.x * rhs.x + self.y * rhs.y + self.z * rhs.z } pub fn cross(self, rhs: Self) -> Self { Self { x: self.y * rhs.z - self.z * rhs.y, y: self.z * rhs.x - self.x * rhs.z, z: self.x * rhs.y - self.y * rhs.x, } } pub fn length(self) -> f32 { libm::sqrtf(self.dot(self)) } pub fn normalize(self) -> Self { let len_sq = self.dot(self); if len_sq < 1e-12 { return Self::ZERO; } self * (1.0 / libm::sqrtf(len_sq)) } } impl Add for Vec3 { type Output = Self; fn add(self, rhs: Self) -> Self { Self { x: self.x + rhs.x, y: self.y + rhs.y, z: self.z + rhs.z, } } } impl Sub for Vec3 { type Output = Self; fn sub(self, rhs: Self) -> Self { Self { x: self.x - rhs.x, y: self.y - rhs.y, z: self.z - rhs.z, } } } impl Mul for Vec3 { type Output = Self; fn mul(self, rhs: f32) -> Self { Self { x: self.x * rhs, y: self.y * rhs, z: self.z * rhs, } } }