use glam::Vec3; use super::Vertex; #[derive(Debug, Clone)] pub struct Mesh { pub faces: Vec<[T; 3]>, } #[derive(Debug, Clone)] pub struct MeshIndexed { pub vertices: Vec, pub faces: Vec<[u16; 3]>, } pub type CpuMesh = Mesh; pub type CpuMeshIndexed = MeshIndexed; impl Mesh { pub fn new() -> Self { Self { faces: Vec::new() } } pub fn concat(meshes: impl IntoIterator) -> Self { Self { faces: meshes .into_iter() .map(|mesh| mesh.faces) .flatten() .collect(), } } pub fn into_indexed(self) -> MeshIndexed { if self.faces.len() >= (1 << 16) / 3 { panic!("too many faces"); } let n_faces = self.faces.len() as u16; MeshIndexed { vertices: self.faces.into_iter().flatten().collect(), faces: (0..n_faces) .map(|face| [3 * face, 3 * face + 1, 3 * face + 2]) .collect(), } } } impl Mesh { pub fn to_standard_mesh(&self) -> CpuMesh { CpuMesh { faces: self .faces .iter() .map(|face| { let [a, b, c] = face; let normal = (b - a).cross(c - a).normalize(); face.map(|position| Vertex { position, normal }) }) .collect(), } } } impl MeshIndexed { pub fn new() -> Self { Self { vertices: Vec::new(), faces: Vec::new(), } } pub fn concat(meshes: impl IntoIterator) -> Self { let mut ret = Self::new(); for mesh in meshes { let base = ret.vertices.len() as u16; ret.vertices.extend(mesh.vertices); if ret.vertices.len() > 1 << 16 { panic!("too many vertices"); } ret.faces.extend( mesh.faces .into_iter() .map(|face| face.map(|index| base + index)), ); } ret } pub fn to_mesh(&self) -> Mesh { Mesh { faces: self .faces .iter() .map(|face| face.map(|index| self.vertices[index as usize])) .collect(), } } }