use bunny_geom::FixedAabb3;
use bunny_mesh::{QuantizedVertex, Triangle16, Triangle32};
use super::error::CompressedMeshError;
use super::read::{read_triangle, read_vertex, take_record};
use super::{TRIANGLE16_STRIDE, TRIANGLE32_STRIDE, VERTEX_STRIDE};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum CompressedIndexWidth {
Width16,
Width32,
}
impl CompressedIndexWidth {
pub(super) const fn stride(self) -> usize {
match self {
Self::Width16 => TRIANGLE16_STRIDE,
Self::Width32 => TRIANGLE32_STRIDE,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum CompressedTriangle {
Width16(Triangle16),
Width32(Triangle32),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct CompressedMesh<'a> {
bounds: FixedAabb3,
vertex_bytes: &'a [u8],
triangle_bytes: &'a [u8],
vertex_count: usize,
triangle_count: usize,
index_width: CompressedIndexWidth,
}
#[derive(Clone, Copy)]
pub(super) struct CompressedMeshParts<'a> {
pub(super) bounds: FixedAabb3,
pub(super) vertex_bytes: &'a [u8],
pub(super) triangle_bytes: &'a [u8],
pub(super) vertex_count: usize,
pub(super) triangle_count: usize,
pub(super) index_width: CompressedIndexWidth,
}
impl<'a> CompressedMesh<'a> {
pub(super) const fn new(parts: CompressedMeshParts<'a>) -> Self {
Self {
bounds: parts.bounds,
vertex_bytes: parts.vertex_bytes,
triangle_bytes: parts.triangle_bytes,
vertex_count: parts.vertex_count,
triangle_count: parts.triangle_count,
index_width: parts.index_width,
}
}
#[must_use]
pub const fn bounds(self) -> FixedAabb3 {
self.bounds
}
#[must_use]
pub const fn vertex_count(self) -> usize {
self.vertex_count
}
#[must_use]
pub const fn triangle_count(self) -> usize {
self.triangle_count
}
#[must_use]
pub const fn index_width(self) -> CompressedIndexWidth {
self.index_width
}
#[must_use]
pub const fn vertex_bytes(self) -> &'a [u8] {
self.vertex_bytes
}
#[must_use]
pub const fn triangle_bytes(self) -> &'a [u8] {
self.triangle_bytes
}
pub fn vertex(self, index: usize) -> Result<QuantizedVertex, CompressedMeshError> {
if index >= self.vertex_count {
return Err(CompressedMeshError::IndexOutOfBounds);
}
read_vertex(take_record(self.vertex_bytes, index, VERTEX_STRIDE)?)
}
pub fn triangle(self, index: usize) -> Result<CompressedTriangle, CompressedMeshError> {
if index >= self.triangle_count {
return Err(CompressedMeshError::IndexOutOfBounds);
}
let bytes = take_record(self.triangle_bytes, index, self.index_width.stride())?;
read_triangle(bytes, self.index_width)
}
}