use crate::corner_table::CornerTable;
use crate::encoder_buffer::EncoderBuffer;
use crate::geometry_indices::{CornerIndex, VertexIndex, INVALID_CORNER_INDEX};
use crate::mesh_edgebreaker_shared::EdgebreakerSymbol;
pub struct MeshEdgebreakerTraversalValenceEncoder {
vertex_valences: Vec<i32>,
corner_to_vertex_map: Vec<VertexIndex>,
prev_symbol: i32,
last_corner: CornerIndex,
num_symbols: usize,
min_valence: i32,
max_valence: i32,
context_symbols: Vec<Vec<u32>>,
}
impl Default for MeshEdgebreakerTraversalValenceEncoder {
fn default() -> Self {
Self::new()
}
}
impl MeshEdgebreakerTraversalValenceEncoder {
pub fn new() -> Self {
Self {
vertex_valences: Vec::new(),
corner_to_vertex_map: Vec::new(),
prev_symbol: -1,
last_corner: INVALID_CORNER_INDEX,
num_symbols: 0,
min_valence: 2,
max_valence: 7,
context_symbols: Vec::new(),
}
}
pub fn init(&mut self, corner_table: &CornerTable) {
self.min_valence = 2;
self.max_valence = 7;
self.vertex_valences.resize(corner_table.num_vertices(), 0);
for i in 0..corner_table.num_vertices() {
self.vertex_valences[i] = corner_table.valence(VertexIndex(i as u32));
}
self.corner_to_vertex_map
.resize(corner_table.num_corners(), VertexIndex(0));
for i in 0..corner_table.num_corners() {
self.corner_to_vertex_map[i] = corner_table.vertex(CornerIndex(i as u32));
}
let num_unique_valences = (self.max_valence - self.min_valence + 1) as usize;
self.context_symbols = vec![Vec::new(); num_unique_valences];
}
pub fn new_corner_reached(&mut self, corner: CornerIndex) {
self.last_corner = corner;
}
pub fn encode_symbol(
&mut self,
symbol: EdgebreakerSymbol,
corner_table: &CornerTable,
visited_faces: &[bool],
) {
self.num_symbols += 1;
let next = corner_table.next(self.last_corner);
let prev = corner_table.previous(self.last_corner);
let active_vertex_idx = self.corner_to_vertex_map[next.0 as usize].0 as usize;
let active_valence = self.vertex_valences[active_vertex_idx];
match symbol {
EdgebreakerSymbol::Center | EdgebreakerSymbol::Split => {
self.vertex_valences[self.corner_to_vertex_map[next.0 as usize].0 as usize] -= 1;
self.vertex_valences[self.corner_to_vertex_map[prev.0 as usize].0 as usize] -= 1;
if symbol == EdgebreakerSymbol::Split {
let mut num_left_faces = 0;
let mut act_c = corner_table.opposite(prev);
while act_c != INVALID_CORNER_INDEX {
if visited_faces[corner_table.face(act_c).0 as usize] {
break;
}
num_left_faces += 1;
act_c = corner_table.opposite(corner_table.next(act_c));
}
let last_corner_v_idx =
self.corner_to_vertex_map[self.last_corner.0 as usize].0 as usize;
self.vertex_valences[last_corner_v_idx] = num_left_faces + 1;
let new_vert_id = VertexIndex(self.vertex_valences.len() as u32);
let mut num_right_faces = 0;
act_c = corner_table.opposite(next);
while act_c != INVALID_CORNER_INDEX {
if visited_faces[corner_table.face(act_c).0 as usize] {
break;
}
num_right_faces += 1;
let next_act_c = corner_table.next(act_c);
self.corner_to_vertex_map[next_act_c.0 as usize] = new_vert_id;
act_c = corner_table.opposite(corner_table.previous(act_c));
}
self.vertex_valences.push(num_right_faces + 1);
}
}
EdgebreakerSymbol::Right => {
self.vertex_valences
[self.corner_to_vertex_map[self.last_corner.0 as usize].0 as usize] -= 1;
self.vertex_valences[self.corner_to_vertex_map[next.0 as usize].0 as usize] -= 1;
self.vertex_valences[self.corner_to_vertex_map[prev.0 as usize].0 as usize] -= 2;
}
EdgebreakerSymbol::Left => {
self.vertex_valences
[self.corner_to_vertex_map[self.last_corner.0 as usize].0 as usize] -= 1;
self.vertex_valences[self.corner_to_vertex_map[next.0 as usize].0 as usize] -= 2;
self.vertex_valences[self.corner_to_vertex_map[prev.0 as usize].0 as usize] -= 1;
}
EdgebreakerSymbol::End => {
self.vertex_valences
[self.corner_to_vertex_map[self.last_corner.0 as usize].0 as usize] -= 2;
self.vertex_valences[self.corner_to_vertex_map[next.0 as usize].0 as usize] -= 2;
self.vertex_valences[self.corner_to_vertex_map[prev.0 as usize].0 as usize] -= 2;
}
_ => {} }
if self.prev_symbol != -1 {
let clamped_valence = if active_valence < self.min_valence {
self.min_valence
} else if active_valence > self.max_valence {
self.max_valence
} else {
active_valence
};
let context = (clamped_valence - self.min_valence) as usize;
let sym_id = self.prev_symbol as u32;
self.context_symbols[context].push(sym_id);
}
self.prev_symbol = symbol as i32;
}
pub fn num_encoded_symbols(&self) -> usize {
self.num_symbols
}
pub fn done(&self, out_buffer: &mut EncoderBuffer, compression_level: i32) {
for symbols in &self.context_symbols {
out_buffer.encode_varint(symbols.len() as u64);
if !symbols.is_empty() {
let options = crate::symbol_encoding::SymbolEncodingOptions { compression_level };
if !crate::symbol_encoding::encode_symbols(symbols, 1, &options, out_buffer) {
debug_log!("Error encoding valence symbols");
}
}
}
}
}