use macaw::BoundingBox;
use macaw::ColorRgba8;
use macaw::Vec3;
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "with_serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "with_speedy", derive(speedy::Writable, speedy::Readable))]
pub struct MeshBounds {
pub bounding_box_min: Vec3,
pub bounding_box_max: Vec3,
pub bounding_sphere_radius: f32,
}
impl MeshBounds {
#[inline]
pub fn bounding_box(&self) -> BoundingBox {
BoundingBox::from_min_max(self.bounding_box_min, self.bounding_box_max)
}
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "with_serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "with_speedy", derive(speedy::Writable, speedy::Readable))]
pub struct MeshData {
pub name: String,
pub indices: Vec<u32>,
pub positions: Vec<[f32; 3]>,
pub normals: Option<Vec<[f32; 3]>>,
pub colors: Option<Vec<ColorRgba8>>,
}
impl MeshData {
pub fn validate(&self) -> Result<(), String> {
if self.indices.len() % 3 != 0 {
return Err(
"Index count not divisible by 3, which is required for triangle lists".to_owned(),
);
}
if !self.indices.is_empty() {
let max = *self.indices.iter().max().unwrap();
if max >= self.positions.len() as u32 {
return Err(format!(
"Index out of bounds: {}, vertex count: {}",
max,
self.positions.len()
));
}
}
if let Some(normals) = &self.normals {
if normals.len() != self.positions.len() {
return Err(format!(
"Mismatch in amount of normals vs positions: {} vs {}",
normals.len(),
self.positions.len()
));
}
}
if let Some(colors) = &self.colors {
if colors.len() != self.positions.len() {
return Err(format!(
"Mismatch in amount of colors vs positions: {} vs {}",
colors.len(),
self.positions.len()
));
}
}
Ok(())
}
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "with_serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "with_speedy", derive(speedy::Writable, speedy::Readable))]
pub struct Mesh {
pub bounding_box_min: Vec3,
pub bounding_box_max: Vec3,
pub bounding_sphere_radius: f32,
pub primitive_count: u64,
pub data: Option<MeshData>,
}
impl Mesh {
pub fn empty() -> Self {
Self {
bounding_box_min: Vec3::ZERO,
bounding_box_max: Vec3::ZERO,
bounding_sphere_radius: 0.0,
primitive_count: 0,
data: None,
}
}
pub fn validate(&self) -> Result<(), String> {
if let Some(data) = &self.data {
data.validate()
} else {
Ok(())
}
}
pub fn get_bounds(&self) -> MeshBounds {
MeshBounds {
bounding_box_min: self.bounding_box_min,
bounding_box_max: self.bounding_box_max,
bounding_sphere_radius: self.bounding_sphere_radius,
}
}
}
impl Default for Mesh {
fn default() -> Self {
Self::empty()
}
}