use super::clers_symbol::{Symbol, SymbolReader};
use super::roblox_bit_reader::BitCounterError;
#[derive(Debug, Clone)]
pub struct Hull<'f> {
pub positions: &'f [[f32; 3]],
pub faces: &'f [[u32; 3]],
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
struct EdgeId(u32);
impl EdgeId {
const fn idx(self) -> usize {
let EdgeId(id) = self;
id as usize
}
const fn next(self) -> Self {
let EdgeId(id) = self;
Self(id / 3 * 3 + (id + 1) % 3)
}
const fn prev(self) -> Self {
let EdgeId(id) = self;
Self(id / 3 * 3 + (id + 2) % 3)
}
}
#[test]
fn test_edge_id() {
assert_eq!(EdgeId(3).next(), EdgeId(4));
assert_eq!(EdgeId(4).next(), EdgeId(5));
assert_eq!(EdgeId(5).next(), EdgeId(3));
assert_eq!(EdgeId(5).prev(), EdgeId(4));
assert_eq!(EdgeId(4).prev(), EdgeId(3));
assert_eq!(EdgeId(3).prev(), EdgeId(5));
}
#[derive(Eq, PartialEq)]
enum EdgeType {
Adjacency(EdgeId),
Uninit,
Boundary,
Processing,
Invalid,
}
#[derive(Clone, Copy)]
struct Edge(i32);
impl Edge {
const UNINIT: Self = Edge(-3);
const BOUNDARY: Self = Edge(-1);
const PROCESSING: Self = Edge(-2);
fn ty(self) -> EdgeType {
match self {
Edge(id) if 0 <= id => EdgeType::Adjacency(EdgeId(id as u32)),
Edge(-3) => EdgeType::Uninit,
Edge(-1) => EdgeType::Boundary,
Edge(-2) => EdgeType::Processing,
_ => EdgeType::Invalid,
}
}
}
impl From<EdgeId> for Edge {
fn from(EdgeId(id): EdgeId) -> Self {
Self(id as i32)
}
}
pub struct HullDecoder<'a> {
symbol_reader: SymbolReader<'a>,
adjacency: Box<[Edge]>,
indices: Box<[u32]>,
current_face: u32,
vertex_offset: u32,
}
impl<'a> HullDecoder<'a> {
pub fn new(symbol_reader: SymbolReader<'a>, capacity: usize) -> Self {
Self {
symbol_reader,
adjacency: vec![Edge::UNINIT; capacity].into_boxed_slice(),
indices: vec![0; capacity].into_boxed_slice(),
current_face: 0,
vertex_offset: 0,
}
}
pub const fn remaining_bits(&self) -> u32 {
self.symbol_reader.remaining_bits()
}
pub const fn current_face(&self) -> u32 {
self.current_face
}
pub const fn vertex_offset(&self) -> u32 {
self.vertex_offset
}
pub fn into_indices(self) -> Box<[u32]> {
self.indices
}
fn zip_boundary(&mut self, mut current_edge: EdgeId) -> EdgeId {
while self.adjacency[current_edge.idx()].ty() == EdgeType::Processing {
let mut candidate_edge = current_edge.next();
while let EdgeType::Adjacency(opposite_edge) = self.adjacency[candidate_edge.idx()].ty()
{
candidate_edge = opposite_edge.next();
}
if self.adjacency[candidate_edge.idx()].ty() != EdgeType::Boundary {
break;
}
self.adjacency[current_edge.idx()] = candidate_edge.into();
self.adjacency[candidate_edge.idx()] = current_edge.into();
current_edge = current_edge.prev();
let mut prev_edge = current_edge;
let candidate_prev_edge = candidate_edge.prev();
self.indices[current_edge.prev().idx()] = self.indices[candidate_prev_edge.idx()];
let mut connected_edge = self.adjacency[current_edge.idx()];
while let EdgeType::Adjacency(connected_edge_id) = connected_edge.ty()
&& candidate_edge != prev_edge
{
prev_edge = connected_edge_id.prev();
self.indices[prev_edge.prev().idx()] = self.indices[candidate_prev_edge.idx()];
connected_edge = self.adjacency[prev_edge.idx()];
}
while let EdgeType::Adjacency(linked_edge) = self.adjacency[current_edge.idx()].ty()
&& current_edge != candidate_edge
{
current_edge = linked_edge.prev();
}
}
current_edge
}
fn decode_recursive(
&mut self,
vertex_count: &mut u32,
mut cursor: EdgeId,
) -> Result<(), BitCounterError> {
loop {
let current_face = self.current_face;
let current_edge_0 = EdgeId(3 * current_face);
let current_edge_1 = EdgeId(3 * current_face + 1);
let current_edge_2 = EdgeId(3 * current_face + 2);
self.adjacency[current_edge_0.idx()] = cursor.into();
self.adjacency[current_edge_1.idx()] = Edge::UNINIT;
self.adjacency[current_edge_2.idx()] = Edge::UNINIT;
self.current_face += 1;
self.adjacency[cursor.idx()] = current_edge_0.into();
self.indices[current_edge_1.idx()] = self.indices[cursor.prev().idx()];
self.indices[current_edge_2.idx()] = self.indices[cursor.next().idx()];
cursor = current_edge_1;
let symbol = self.symbol_reader.read()?;
match symbol {
Symbol::Continue => {
self.indices[current_edge_0.idx()] = *vertex_count;
self.adjacency[cursor.next().idx()] = Edge::BOUNDARY;
*vertex_count += 1;
}
Symbol::Split => {
self.decode_recursive(vertex_count, cursor)?;
cursor = cursor.next();
}
Symbol::Left => {
self.adjacency[cursor.idx()] = Edge::PROCESSING;
cursor = cursor.next();
}
Symbol::Right => {
let next_edge = cursor.next();
self.adjacency[next_edge.idx()] = Edge::PROCESSING;
self.zip_boundary(next_edge);
}
Symbol::End => {
self.adjacency[cursor.idx()] = Edge::PROCESSING;
let next_edge = cursor.next();
self.adjacency[next_edge.idx()] = Edge::PROCESSING;
self.zip_boundary(next_edge);
return Ok(());
}
}
}
}
pub fn decode_hull(&mut self) -> Result<(), BitCounterError> {
let edge = 3 * self.current_face as usize;
self.adjacency[edge..edge + 3].copy_from_slice(&[
Edge::BOUNDARY,
Edge::UNINIT,
Edge::BOUNDARY,
]);
self.current_face += 1;
self.indices[edge..edge + 3].copy_from_slice(&[0, 1, 2]);
let mut vertex_count = 3;
self.decode_recursive(&mut vertex_count, EdgeId(edge as u32 + 1))?;
self.vertex_offset += vertex_count;
Ok(())
}
}