use super::{Image, Rgba, gltf};
use crate::Result;
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Mesh {
pub name: String,
pub primitives: Vec<Primitive>,
pub materials: Vec<Material>,
pub textures: Vec<Texture>,
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Primitive {
pub material: Option<usize>,
pub vertices: Vec<Vertex>,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Vertex {
pub position: [f32; 3],
pub normal: [f32; 3],
pub uv: [f32; 2],
pub color: Rgba,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Material {
pub name: String,
pub color: Rgba,
pub texture: Option<usize>,
pub alpha: AlphaMode,
pub double_sided: bool,
pub unlit: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AlphaMode {
Opaque,
Mask,
Blend,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Texture {
pub image: Image,
pub wrap: [Wrap; 2],
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Wrap {
Clamp,
Repeat,
Mirror,
}
impl Mesh {
pub fn to_glb(&self) -> Result<Vec<u8>> {
gltf::glb(self)
}
pub fn bounds(&self) -> Option<([f32; 3], [f32; 3])> {
let mut vertices = self.primitives.iter().flat_map(|p| &p.vertices);
let first = vertices.next()?.position;
Some(vertices.fold((first, first), |(min, max), vertex| {
let p = vertex.position;
(
[0, 1, 2].map(|i| min[i].min(p[i])),
[0, 1, 2].map(|i| max[i].max(p[i])),
)
}))
}
}