use std::collections::HashMap;
use crate::scene::MaterialId;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Topology {
Triangles,
TriangleStrip,
TriangleFan,
Lines,
LineStrip,
LineLoop,
Points,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Indices {
U16(Vec<u16>),
U32(Vec<u32>),
}
impl Indices {
pub fn len(&self) -> usize {
match self {
Self::U16(v) => v.len(),
Self::U32(v) => v.len(),
}
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
#[derive(Clone, Debug)]
pub struct Primitive {
pub topology: Topology,
pub positions: Vec<[f32; 3]>,
pub normals: Option<Vec<[f32; 3]>>,
pub tangents: Option<Vec<[f32; 4]>>,
pub uvs: Vec<Vec<[f32; 2]>>,
pub colors: Vec<Vec<[f32; 4]>>,
pub joints: Option<Vec<[u16; 4]>>,
pub weights: Option<Vec<[f32; 4]>>,
pub indices: Option<Indices>,
pub material: Option<MaterialId>,
pub extras: HashMap<String, serde_json::Value>,
}
impl Primitive {
pub fn new(topology: Topology) -> Self {
Self {
topology,
positions: Vec::new(),
normals: None,
tangents: None,
uvs: Vec::new(),
colors: Vec::new(),
joints: None,
weights: None,
indices: None,
material: None,
extras: HashMap::new(),
}
}
pub fn triangle_count(&self) -> usize {
let n = self
.indices
.as_ref()
.map(|i| i.len())
.unwrap_or(self.positions.len());
match self.topology {
Topology::Triangles => n / 3,
Topology::TriangleStrip | Topology::TriangleFan => n.saturating_sub(2),
_ => 0,
}
}
}
#[derive(Clone, Debug, Default)]
pub struct Mesh {
pub name: Option<String>,
pub primitives: Vec<Primitive>,
}
impl Mesh {
pub fn new(name: impl Into<Option<String>>) -> Self {
Self {
name: name.into(),
primitives: Vec::new(),
}
}
pub fn with_primitive(mut self, primitive: Primitive) -> Self {
self.primitives.push(primitive);
self
}
}