use ecs::Component; use crate::vector::Vec3; use crate::vertex::Vertex; pub mod cube; #[derive(Debug, Clone, Component)] pub struct Mesh { vertices: Vec, indices: Option>, } impl Mesh { #[must_use] pub fn new(vertices: Vec, indices: Option>) -> Self { Self { vertices, indices } } #[must_use] pub fn vertices(&self) -> &[Vertex] { &self.vertices } #[must_use] pub fn indices(&self) -> Option<&[u32]> { self.indices.as_deref() } /// Finds the vertex positions that are furthest in every 3D direction. Keep in mind /// that this can be quite time-expensive if the mesh has many vertices. pub fn find_furthest_vertex_positions(&self) -> DirectionPositions<'_> { let mut point_iter = self.vertices().iter().map(|vertex| &vertex.pos).into_iter(); let first_point = point_iter.next().unwrap(); point_iter .fold( FurthestPosAcc { up: FurthestPos::new(&first_point, &Vec3::UP), down: FurthestPos::new(&first_point, &Vec3::DOWN), left: FurthestPos::new(&first_point, &Vec3::LEFT), right: FurthestPos::new(&first_point, &Vec3::RIGHT), back: FurthestPos::new(&first_point, &Vec3::BACK), front: FurthestPos::new(&first_point, &Vec3::FRONT), }, |mut furthest_pos_acc, pos| { furthest_pos_acc.up.update_if_further(pos); furthest_pos_acc.down.update_if_further(pos); furthest_pos_acc.left.update_if_further(pos); furthest_pos_acc.right.update_if_further(pos); furthest_pos_acc.back.update_if_further(pos); furthest_pos_acc.front.update_if_further(pos); furthest_pos_acc }, ) .into() } } #[derive(Debug, Clone)] pub struct DirectionPositions<'mesh> { pub up: &'mesh Vec3, pub down: &'mesh Vec3, pub left: &'mesh Vec3, pub right: &'mesh Vec3, pub back: &'mesh Vec3, pub front: &'mesh Vec3, } impl<'mesh> From> for DirectionPositions<'mesh> { fn from(acc: FurthestPosAcc<'mesh>) -> Self { Self { up: acc.up.pos, down: acc.down.pos, left: acc.left.pos, right: acc.right.pos, back: acc.back.pos, front: acc.front.pos, } } } #[derive(Debug)] struct FurthestPosAcc<'mesh> { up: FurthestPos<'mesh>, down: FurthestPos<'mesh>, left: FurthestPos<'mesh>, right: FurthestPos<'mesh>, back: FurthestPos<'mesh>, front: FurthestPos<'mesh>, } #[derive(Debug)] struct FurthestPos<'mesh> { pos: &'mesh Vec3, dot_prod: f32, direction: &'mesh Vec3, } impl<'mesh> FurthestPos<'mesh> { fn new(pos: &'mesh Vec3, direction: &'mesh Vec3) -> Self { Self { pos, dot_prod: direction.dot(&pos), direction, } } fn update_if_further(&mut self, point: &'mesh Vec3) { let point_dot_prod = self.direction.dot(point); if point_dot_prod > self.dot_prod { self.pos = point; self.dot_prod = point_dot_prod; } } }