1use std::{cmp, fmt};
2
3use crate::encode::entropy::rans::{self, RabsCoder};
4use crate::encode::entropy::symbol_coding::encode_symbols;
5use draco_oxide_core::attribute::AttributeType;
6use draco_oxide_core::bit_coder::{BitWriter, ByteWriter};
7use draco_oxide_core::buffer::LsbFirst;
8use draco_oxide_core::codec::connectivity::edgebreaker::symbol_encoder::{
9 CrLight, Symbol, SymbolEncoder,
10};
11use draco_oxide_core::debug_write;
12use draco_oxide_core::mesh::ds::CornerTable;
13use draco_oxide_core::mesh::ds::GenericCornerTable;
14use draco_oxide_core::mesh::ds::{AttributeDS, DS};
15
16use draco_oxide_core::types::{
17 ConfigType, CornerIdx, FaceIdx, VecCornerIdx, VecFaceIdx, VecVertexIdx, VertexIdx,
18};
19
20use draco_oxide_core::codec::connectivity::edgebreaker::{
21 self, EdgebreakerKind, Orientation, TopologySplit, MAX_VALENCE, MIN_VALENCE,
22};
23use draco_oxide_core::codec::entropy::SymbolEncodingMethod;
24use draco_oxide_core::utils::bit_coder::leb128_write;
25use std::vec;
26
27use crate::encode::connectivity::ConnectivityEncoder;
28
29pub(crate) struct Edgebreaker<'ads, 'faces, T>
30where
31 T: Traversal,
32{
33 visited_vertices: VecVertexIdx<bool>,
36
37 visited_faces: VecFaceIdx<bool>,
40
41 visited_holes: Vec<bool>,
43
44 vertex_hole_id: VecVertexIdx<Option<usize>>,
46
47 corner_traversal_stack: Vec<CornerIdx>,
48
49 last_encoded_symbol_idx: usize,
50
51 processed_connectivity_corners: Vec<CornerIdx>,
52
53 face_to_split_symbol_map: VecFaceIdx<u32>,
57
58 num_split_symbols: usize,
59
60 vertex_traversal_length: Vec<usize>,
61
62 init_face_connectivity_corners: Vec<CornerIdx>,
63
64 traversal: T,
65
66 topology_splits: Vec<TopologySplit>,
68
69 adss: &'ads [AttributeDS<'faces>],
70
71 pos_corner_table: &'ads CornerTable,
72
73 posds: &'ads AttributeDS<'faces>,
74
75 gds: &'ads DS,
76
77 config: Config,
79}
80
81#[derive(Clone, fmt::Debug, cmp::PartialEq)]
84pub struct Config {
85 pub traversal: EdgebreakerKind,
88}
89
90impl ConfigType for Config {
91 fn default() -> Self {
92 Self {
93 traversal: EdgebreakerKind::Valence,
94 }
95 }
96}
97
98#[derive(Debug, PartialEq)]
99#[remain::sorted]
100#[derive(thiserror::Error)]
101pub enum Err {
102 #[error("Edgebreaker error: {0}")]
103 EdgebreakerError(#[from] edgebreaker::Err),
104 #[error("The input mesh has an empty AttributeDS array.")]
105 EmptyAttributeDSArray,
106 #[error("Entropy encoding error: {0}")]
107 EntropyEncodingError(#[from] crate::encode::entropy::symbol_coding::Err),
108 #[error("Too many handles.")]
109 HandleSizeTooLarge,
110 #[error("Too many holes.")]
111 HoleSizeTooLarge,
112 #[error("The input mesh is non-orientable.")]
113 NonOrientable,
114 #[error("Rabs coder error: {0}")]
115 RabsCoderError(#[from] rans::Err),
116 #[error("The input mesh has too many connected components: {0}")]
117 TooManyConnectedComponents(usize),
118}
119
120impl<'ads, 'faces, T> Edgebreaker<'ads, 'faces, T>
121where
122 T: Traversal,
123{
124 pub fn new(
126 config: Config,
127 adss: &'ads [AttributeDS<'faces>],
128 make_traversal: impl FnOnce(&'ads AttributeDS<'faces>) -> T,
129 ) -> Result<Self, Err> {
130 let pos_ads = adss
131 .iter()
132 .find(|ads| ads.att_data().get_attribute_type() == AttributeType::Position)
133 .ok_or(Err::EmptyAttributeDSArray)?;
134 let gds = pos_ads.global_ds();
135 let traversal = make_traversal(pos_ads);
136
137 let out = Self {
138 visited_vertices: VecVertexIdx::from(vec![false; pos_ads.num_vertices()]),
139 visited_faces: VecFaceIdx::from(vec![false; gds.num_faces()]),
140 visited_holes: Vec::new(),
141 pos_corner_table: pos_ads.corner_table().pos_corner_table(),
142 posds: pos_ads,
143 vertex_hole_id: VecVertexIdx::new(),
144 corner_traversal_stack: Vec::new(),
145 last_encoded_symbol_idx: usize::MAX,
146 processed_connectivity_corners: Vec::new(),
147 face_to_split_symbol_map: VecFaceIdx::from(vec![u32::MAX; gds.num_faces()]),
148 num_split_symbols: 0,
149 vertex_traversal_length: Vec::new(),
150 init_face_connectivity_corners: Vec::new(),
151 traversal,
152 topology_splits: Vec::new(),
153 gds,
154 adss,
155 config,
156 };
157 Ok(out)
158 }
159
160 fn compute_boundaries(&mut self) -> Result<(), Err> {
161 self.vertex_hole_id = VecVertexIdx::from(vec![None; self.posds.num_vertices()]);
162 for c in 0..self.gds.num_corners() {
163 let c = CornerIdx::from(c);
164 if self.pos_corner_table.opposite(c).is_none() {
165 let mut v = self.posds.vertex_idx(c.next());
167 if self.vertex_hole_id[v].is_some() {
168 continue;
170 }
171 let boundary_idx = self.visited_holes.len();
173 self.visited_holes.push(false);
174
175 let mut c = c;
176 while self.vertex_hole_id[v].is_none() {
177 self.vertex_hole_id[v] = Some(boundary_idx);
178 c = c.next();
179
180 while self.pos_corner_table.opposite(c).is_some() {
181 c = c.next();
182 }
183 v = self.posds.vertex_idx(c.next());
185 }
186 }
187 }
188 Ok(())
189 }
190
191 fn process_boundary(&mut self, start_corner: CornerIdx, encode_first_vertex: bool) -> usize {
192 let mut corner = start_corner.previous();
193 while let Some(opp) = self.pos_corner_table.opposite(corner) {
194 corner = opp.next();
195 } let start_v = self.posds.vertex_idx(start_corner);
198
199 let mut num_encoded_hole_verts = 0;
200 if encode_first_vertex {
201 self.visited_vertices[start_v] = true;
202 num_encoded_hole_verts += 1;
203 }
204
205 self.visited_holes[self.vertex_hole_id[start_v].unwrap()] = true; let mut curr_v = self.posds.vertex_idx(corner.previous());
207 while curr_v != start_v {
208 self.visited_vertices[curr_v] = true;
209 num_encoded_hole_verts += 1;
210 corner = corner.next();
211 while let Some(opp) = self.pos_corner_table.opposite(corner) {
212 corner = opp.next();
213 }
214 curr_v = self.posds.vertex_idx(corner.previous());
215 }
216 num_encoded_hole_verts
217 }
218
219 fn edgebreaker_from(&mut self, mut c: CornerIdx) -> Result<(), Err> {
221 self.corner_traversal_stack.clear();
222 self.corner_traversal_stack.push(c);
223 let num_faces = self.gds.num_faces();
224 while let Some(&start) = self.corner_traversal_stack.last() {
225 c = start;
226 if self.visited_faces[c.face_idx()] {
228 self.corner_traversal_stack.pop();
229 continue;
230 }
231
232 let mut num_visited_faces = 0;
233 while num_visited_faces < num_faces {
234 num_visited_faces += 1;
235 self.last_encoded_symbol_idx = self.last_encoded_symbol_idx.wrapping_add(1); let face_idx = c.face_idx();
238 self.visited_faces[face_idx] = true;
239 self.processed_connectivity_corners.push(c);
240 self.traversal.new_corner_reached(c);
241 let v = self.posds.vertex_idx(c);
242 if !self.visited_vertices[v] {
243 self.visited_vertices[v] = true;
244 if self.vertex_hole_id[v].is_none() {
245 self.traversal.record_symbol(
246 Symbol::C,
247 &self.visited_faces,
248 self.pos_corner_table,
249 );
250 c = self.posds.corner_table().get_right_corner(c).unwrap(); continue;
252 }
253 }
254 let maybe_right_c = self.posds.corner_table().get_right_corner(c);
255 let maybe_left_c = self.posds.corner_table().get_left_corner(c);
256 let maybe_right_face = maybe_right_c.map(|c| c.face_idx());
257 let maybe_left_face = maybe_left_c.map(|c| c.face_idx());
258 if self.is_right_face_visited(c) {
259 if let Some(right_face) = maybe_right_face {
260 self.check_and_store_topology_split_event(
261 self.last_encoded_symbol_idx,
262 Orientation::Right,
263 right_face,
264 );
265 }
266 if self.is_left_face_visited(c) {
267 if let Some(left_face) = maybe_left_face {
269 self.check_and_store_topology_split_event(
270 self.last_encoded_symbol_idx,
271 Orientation::Left,
272 left_face,
273 );
274 }
275 self.traversal.record_symbol(
276 Symbol::E,
277 &self.visited_faces,
278 self.pos_corner_table,
279 );
280 self.corner_traversal_stack.pop();
281 break;
283 } else {
284 self.traversal.record_symbol(
286 Symbol::R,
287 &self.visited_faces,
288 self.pos_corner_table,
289 );
290 c = maybe_left_c.unwrap(); }
292 } else if self.is_left_face_visited(c) {
293 if let Some(left_face) = maybe_left_face {
295 self.check_and_store_topology_split_event(
296 self.last_encoded_symbol_idx,
297 Orientation::Left,
298 left_face,
299 );
300 }
301 self.traversal.record_symbol(
302 Symbol::L,
303 &self.visited_faces,
304 self.pos_corner_table,
305 );
306 c = maybe_right_c.unwrap(); } else {
308 self.traversal.record_symbol(
309 Symbol::S,
310 &self.visited_faces,
311 self.pos_corner_table,
312 );
313 self.num_split_symbols += 1;
314 if let Some(hole_idx) = self.vertex_hole_id[v] {
315 if !self.visited_holes[hole_idx] {
316 self.process_boundary(c, false);
317 }
318 }
319 self.face_to_split_symbol_map[face_idx] = self.last_encoded_symbol_idx as u32;
320 *self.corner_traversal_stack.last_mut().unwrap() = maybe_left_c.unwrap();
321 self.corner_traversal_stack.push(maybe_right_c.unwrap());
322 break;
323 }
324 }
325 }
326 Ok(())
327 }
328
329 fn is_right_face_visited(&self, c: CornerIdx) -> bool {
333 if let Some(c_r) = self.posds.corner_table().get_right_corner(c) {
334 self.visited_faces[c_r.face_idx()]
335 } else {
336 true
337 }
338 }
339
340 fn is_left_face_visited(&self, c: CornerIdx) -> bool {
344 if let Some(c_l) = self.pos_corner_table.get_left_corner(c) {
345 self.visited_faces[c_l.face_idx()]
346 } else {
347 true
348 }
349 }
350
351 fn encode_topology_splits<W>(&mut self, writer: &mut W) -> Result<(), Err>
352 where
353 W: ByteWriter,
354 {
355 let mut last_idx = 0;
356 leb128_write(self.topology_splits.len() as u64, writer);
358 for split in self.topology_splits.iter() {
359 leb128_write((split.merging_symbol_idx - last_idx) as u64, writer);
360 leb128_write(
361 (split.merging_symbol_idx - split.split_symbol_idx) as u64,
362 writer,
363 );
364 last_idx = split.merging_symbol_idx;
365 }
366 let mut bit_coder: BitWriter<'_, W, LsbFirst> = BitWriter::spown_from(writer);
367 for split in self.topology_splits.iter() {
368 let orientation = match split.merging_edge_orientation {
369 Orientation::Left => (1, 0),
370 Orientation::Right => (1, 1),
371 };
372 bit_coder.write_bits(orientation);
373 }
374 Ok(())
375 }
376
377 fn begin_from(&mut self, face_idx: FaceIdx) -> (bool, CornerIdx) {
384 let mut corner_index = CornerIdx::from(3 * usize::from(face_idx));
385 for _ in 0..3 {
386 if self.pos_corner_table.opposite(corner_index).is_none() {
387 return (false, corner_index);
389 }
390 if self.vertex_hole_id[self.posds.vertex_idx(corner_index)].is_some() {
391 while let Some(right_corner) = self.posds.corner_table().swing_right(corner_index) {
393 corner_index = right_corner;
394 }
395 let start_corner = corner_index.previous();
396 return (false, start_corner);
397 }
398 corner_index = corner_index.next();
399 }
400 (true, corner_index)
401 }
402
403 fn check_and_store_topology_split_event(
404 &mut self,
405 merging_symbol_idx: usize,
406 merging_edge_orientation: Orientation,
407 split_face_idx: FaceIdx,
408 ) {
409 let split_symbol_idx = self.face_to_split_symbol_map[split_face_idx];
410 if split_symbol_idx == u32::MAX {
411 return;
412 }
413 let split = TopologySplit {
414 merging_symbol_idx,
415 split_symbol_idx: split_symbol_idx as usize,
416 merging_edge_orientation,
417 };
418
419 self.topology_splits.push(split);
420 }
421}
422
423impl<'ads, 'faces, T> ConnectivityEncoder for Edgebreaker<'ads, 'faces, T>
424where
425 T: Traversal,
426{
427 type Config = Config;
428 type Err = Err;
429 fn encode_connectivity<W>(mut self, writer: &mut W) -> Result<Vec<CornerIdx>, Self::Err>
436 where
437 W: ByteWriter,
438 {
439 debug_write!("Init Decoder", writer);
440 self.config.traversal.write_to(writer);
442 debug_write!("Init Decoder Done", writer);
443
444 self.compute_boundaries()?;
445
446 leb128_write(self.posds.num_vertices() as u64, writer);
447 leb128_write(self.gds.num_faces() as u64, writer);
448
449 writer.write_u8((self.adss.len() - 1) as u8);
450
451 for c in 0..self.gds.num_corners() {
453 let c = CornerIdx::from(c);
454 let face_idx = c.face_idx();
455 if self.visited_faces[face_idx] {
456 continue;
458 }
459
460 let (is_start_face_interior, start_corner) = self.begin_from(face_idx);
461
462 self.traversal
463 .record_start_face_config(is_start_face_interior);
464
465 if is_start_face_interior {
466 let corner_index = start_corner;
467 let v = self.posds.vertex_idx(corner_index);
468 let n = self.posds.vertex_idx(corner_index.next());
469 let p = self.posds.vertex_idx(corner_index.previous());
470 self.visited_vertices[v] = true;
471 self.visited_vertices[n] = true;
472 self.visited_vertices[p] = true;
473
474 self.vertex_traversal_length.push(1);
475
476 self.visited_faces[face_idx] = true;
477
478 self.init_face_connectivity_corners
479 .push(corner_index.next());
480 let corner_opp = self.pos_corner_table.opposite(corner_index.next()).unwrap(); self.edgebreaker_from(corner_opp)?;
482 } else {
483 self.process_boundary(start_corner.next(), true);
485 self.edgebreaker_from(start_corner)?;
486 }
487 }
488
489 leb128_write(self.traversal.num_symbols() as u64, writer);
491
492 leb128_write(self.num_split_symbols as u64, writer);
494
495 self.encode_topology_splits(writer)?;
496 self.traversal
498 .encode(writer, self.adss, self.pos_corner_table, self.gds)?;
499
500 self.init_face_connectivity_corners.reverse();
501 self.init_face_connectivity_corners
502 .append(&mut self.processed_connectivity_corners);
503
504 Ok(self.init_face_connectivity_corners)
505 }
506}
507
508pub(crate) trait Traversal {
509 fn record_symbol(
510 &mut self,
511 symbol: Symbol,
512 visited_faces: &VecFaceIdx<bool>,
513 corner_table: &CornerTable,
514 );
515 fn record_start_face_config(&mut self, interior_cfg: bool);
516 fn new_corner_reached(&mut self, corner: CornerIdx);
517 fn num_symbols(&self) -> usize;
518 fn encode<W>(
519 self,
520 writer: &mut W,
521 att_data: &[AttributeDS<'_>],
522 corner_table: &CornerTable,
523 gds: &DS,
524 ) -> Result<(), Err>
525 where
526 W: ByteWriter;
527}
528
529pub(crate) struct DefaultTraversal {
530 symbols: Vec<Symbol>,
531 interior_cfg: Vec<bool>,
532 processed_connectivity_corners: Vec<CornerIdx>,
533}
534
535impl DefaultTraversal {
536 pub(crate) fn new() -> Self {
537 Self {
538 symbols: Vec::new(),
539 interior_cfg: Vec::new(),
540 processed_connectivity_corners: Vec::new(),
541 }
542 }
543}
544
545impl Traversal for DefaultTraversal {
546 fn record_symbol(
547 &mut self,
548 symbol: Symbol,
549 _visited_faces: &VecFaceIdx<bool>,
550 _corner_table: &CornerTable,
551 ) {
552 self.symbols.push(symbol);
553 }
554
555 fn new_corner_reached(&mut self, corner: CornerIdx) {
556 self.processed_connectivity_corners.push(corner);
557 }
558
559 fn record_start_face_config(&mut self, interior_cfg: bool) {
560 self.interior_cfg.push(interior_cfg);
561 }
562
563 fn num_symbols(&self) -> usize {
564 self.symbols.len()
565 }
566
567 fn encode<W>(
568 self,
569 final_writer: &mut W,
570 att_data: &[AttributeDS<'_>],
571 pos_corner_table: &CornerTable,
572 gds: &DS,
573 ) -> Result<(), Err>
574 where
575 W: ByteWriter,
576 {
577 let mut writer = Vec::new();
578 {
579 let mut writer: BitWriter<'_, Vec<u8>, LsbFirst> = BitWriter::spown_from(&mut writer);
580 for s in self.symbols.into_iter().rev() {
581 writer.write_bits(CrLight::encode_symbol(s));
582 }
583 }
584
585 leb128_write(writer.len() as u64, final_writer);
587 for byte in writer {
589 final_writer.write_u8(byte);
590 }
591
592 encode_start_faces(&self.interior_cfg, final_writer)?;
593 encode_attribute_seams(
594 self.processed_connectivity_corners,
595 att_data,
596 pos_corner_table,
597 gds,
598 final_writer,
599 )
600 }
601}
602
603fn encode_start_faces<W>(interior_cfg: &[bool], final_writer: &mut W) -> Result<(), Err>
606where
607 W: ByteWriter,
608{
609 let freq_count_0 = interior_cfg.iter().filter(|&&cfg| !cfg).count();
610 let zero_prob = (((freq_count_0 as f32 / interior_cfg.len() as f32) * 256.0 + 0.5) as u16)
612 .clamp(1, 255) as u8;
613 final_writer.write_u8(zero_prob);
614 let mut writer: RabsCoder = RabsCoder::new(zero_prob as usize, None);
615 for &cfg in interior_cfg.iter().rev() {
616 writer.write(if cfg { 1 } else { 0 })?;
617 }
618 let buffer = writer.flush()?;
619 leb128_write(buffer.len() as u64, final_writer);
620 for byte in buffer {
621 final_writer.write_u8(byte);
622 }
623 Ok(())
624}
625
626fn encode_attribute_seams<W>(
642 processed_connectivity_corners: Vec<CornerIdx>,
643 att_data: &[AttributeDS<'_>],
644 pos_corner_table: &CornerTable,
645 gds: &DS,
646 final_writer: &mut W,
647) -> Result<(), Err>
648where
649 W: ByteWriter,
650{
651 let seam_atts = att_data
652 .iter()
653 .filter(|ads| ads.att_data().get_attribute_type() != AttributeType::Position)
654 .collect::<Vec<_>>();
655 for group in seam_atts.chunks(8) {
659 let mut visited_faces = vec![false; gds.num_faces()];
660 let mut packed: Vec<u8> = Vec::with_capacity(gds.num_corners() >> 1);
661 let mut zeros = vec![0usize; group.len()];
662 for c in processed_connectivity_corners.iter().rev().copied() {
663 let corners = [c, c.next(), c.previous()];
664 let f_idx = c.face_idx();
665 visited_faces[usize::from(f_idx)] = true;
666 for corner in &corners {
667 if let Some(opp_corner) = pos_corner_table.opposite(*corner) {
668 let opp_face = opp_corner.face_idx();
669 if visited_faces[usize::from(opp_face)] {
670 continue;
672 }
673 } else {
674 continue;
676 }
677
678 let mut bits = 0u8;
679 for (j, ads) in group.iter().enumerate() {
680 if ads.corner_table().opposite(*corner).is_none() {
681 bits |= 1 << j;
682 } else {
683 zeros[j] += 1;
684 }
685 }
686 packed.push(bits);
687 }
688 }
689 write_seam_streams(&packed, &zeros, final_writer)?;
690 }
691
692 Ok(())
693}
694
695fn seam_prob_zero(zeros: usize, total: usize) -> u8 {
698 (((zeros as f32 / total as f32) * 256.0 + 0.5) as u16).clamp(1, 255) as u8
699}
700
701fn write_seam_streams<W>(packed: &[u8], zeros: &[usize], final_writer: &mut W) -> Result<(), Err>
707where
708 W: ByteWriter,
709{
710 let probs: Vec<u8> = zeros
711 .iter()
712 .map(|&z| seam_prob_zero(z, packed.len()))
713 .collect();
714 let buffers = match probs.len() {
715 1 => encode_seams_fixed::<1>(packed, &probs),
716 2 => encode_seams_fixed::<2>(packed, &probs),
717 _ => encode_seams_general(packed, &probs),
718 }?;
719 for (prob, buffer) in probs.iter().zip(buffers) {
720 final_writer.write_u8(*prob);
721 leb128_write(buffer.len() as u64, final_writer);
722 for byte in buffer {
723 final_writer.write_u8(byte);
724 }
725 }
726 Ok(())
727}
728
729fn encode_seams_fixed<const N: usize>(packed: &[u8], probs: &[u8]) -> Result<Vec<Vec<u8>>, Err> {
732 let mut coders: [RabsCoder; N] =
733 std::array::from_fn(|j| RabsCoder::new(probs[j] as usize, None));
734 for &bits in packed.iter().rev() {
735 for (j, coder) in coders.iter_mut().enumerate() {
736 coder.write((bits >> j) & 1)?;
737 }
738 }
739 let mut buffers = Vec::with_capacity(coders.len());
740 for coder in coders {
741 buffers.push(coder.flush()?);
742 }
743 Ok(buffers)
744}
745
746fn encode_seams_general(packed: &[u8], probs: &[u8]) -> Result<Vec<Vec<u8>>, Err> {
748 let mut coders: Vec<RabsCoder> = probs
749 .iter()
750 .map(|&prob| RabsCoder::new(prob as usize, None))
751 .collect();
752 for &bits in packed.iter().rev() {
753 for (j, coder) in coders.iter_mut().enumerate() {
754 coder.write((bits >> j) & 1)?;
755 }
756 }
757 let mut buffers = Vec::with_capacity(coders.len());
758 for coder in coders {
759 buffers.push(coder.flush()?);
760 }
761 Ok(buffers)
762}
763
764pub(crate) struct ValenceTraversal {
765 vertex_valences: VecVertexIdx<isize>,
769 corner_to_vertex_map: VecCornerIdx<VertexIdx>,
772 context_symbols: Vec<Vec<Symbol>>,
773 last_corner: CornerIdx,
774 prev_symbol: Option<Symbol>,
775 interior_cfg: Vec<bool>,
776 num_symbols: usize,
777 processed_connectivity_corners: Vec<CornerIdx>,
778}
779impl ValenceTraversal {
780 #[inline]
781 fn vertex_idx(&self, corner: CornerIdx) -> VertexIdx {
782 self.corner_to_vertex_map[corner]
783 }
784
785 pub(crate) fn new(pos_ds: &AttributeDS) -> Self {
786 let mut vertex_valences: VecVertexIdx<isize> =
787 Vec::with_capacity(pos_ds.num_vertices()).into();
788 for i in 0..pos_ds.num_vertices() {
789 let v = VertexIdx::from(i);
790 vertex_valences.push(pos_ds.vertex_valence(v) as isize);
791 }
792
793 let num_corners = pos_ds.global_ds().num_corners();
794 let mut corner_to_vertex_map: VecCornerIdx<VertexIdx> =
795 Vec::with_capacity(num_corners).into();
796 for c in 0..num_corners {
797 corner_to_vertex_map.push(pos_ds.vertex_idx(CornerIdx::from(c)));
798 }
799
800 let num_unique_valences = MAX_VALENCE - MIN_VALENCE + 1;
801
802 let context_symbols = vec![Vec::new(); num_unique_valences];
803 Self {
804 vertex_valences,
805 corner_to_vertex_map,
806 context_symbols,
807 last_corner: CornerIdx::INVALID, prev_symbol: None,
809 interior_cfg: Vec::new(),
810 num_symbols: 0,
811 processed_connectivity_corners: Vec::new(),
812 }
813 }
814}
815
816impl Traversal for ValenceTraversal {
817 fn record_symbol(
818 &mut self,
819 symbol: Symbol,
820 visited_faces: &VecFaceIdx<bool>,
821 corner_table: &CornerTable,
822 ) {
823 self.num_symbols += 1;
824
825 let next = self.last_corner.next();
826 let prev = self.last_corner.previous();
827
828 let v_last = self.vertex_idx(self.last_corner);
829 let v_next = self.vertex_idx(next);
830 let v_prev = self.vertex_idx(prev);
831
832 let active_valence = self.vertex_valences[v_next];
833 match symbol {
834 Symbol::C | Symbol::S => {
835 self.vertex_valences[v_next] -= 1;
836 self.vertex_valences[v_prev] -= 1;
837 }
838 Symbol::R => {
839 self.vertex_valences[v_last] -= 1;
841 self.vertex_valences[v_next] -= 1;
842 self.vertex_valences[v_prev] -= 2;
843 }
844 Symbol::L => {
845 self.vertex_valences[v_last] -= 1;
846 self.vertex_valences[v_next] -= 2;
847 self.vertex_valences[v_prev] -= 1;
848 }
849 Symbol::E => {
850 self.vertex_valences[v_last] -= 2;
851 self.vertex_valences[v_next] -= 2;
852 self.vertex_valences[v_prev] -= 2;
853 }
854 }
855 if symbol == Symbol::S {
856 let mut num_left_faces = 0;
862 let mut maybe_act_c = corner_table.opposite(prev);
863 while let Some(act_c) = maybe_act_c {
864 if visited_faces[act_c.face_idx()] {
865 break;
866 }
867 num_left_faces += 1;
868 maybe_act_c = corner_table.opposite(act_c.next());
869 }
870 self.vertex_valences[v_last] = num_left_faces + 1;
871
872 let new_vertex = self.vertex_valences.len();
873 let mut num_right_faces = 0;
874
875 maybe_act_c = corner_table.opposite(next);
876 while let Some(act_c) = maybe_act_c {
877 if visited_faces[act_c.face_idx()] {
878 break;
879 }
880 num_right_faces += 1;
881 self.corner_to_vertex_map[act_c.next()] = new_vertex.into();
882 maybe_act_c = corner_table.opposite(act_c.previous());
883 }
884 self.vertex_valences.push(num_right_faces + 1);
885 }
886
887 if let Some(prev_symbol) = self.prev_symbol {
888 let clamped_valence = active_valence.clamp(MIN_VALENCE as isize, MAX_VALENCE as isize);
889
890 let context = (clamped_valence - MIN_VALENCE as isize) as usize;
891 self.context_symbols[context].push(prev_symbol);
892 }
893
894 self.prev_symbol = Some(symbol);
895 }
896
897 fn record_start_face_config(&mut self, interior_cfg: bool) {
898 self.interior_cfg.push(interior_cfg);
899 }
900
901 fn new_corner_reached(&mut self, c: CornerIdx) {
902 self.last_corner = c;
903 self.processed_connectivity_corners.push(c);
904 }
905
906 fn num_symbols(&self) -> usize {
907 self.num_symbols
908 }
909
910 fn encode<W>(
911 self,
912 writer: &mut W,
913 att_data: &[AttributeDS<'_>],
914 pos_corner_table: &CornerTable,
915 gds: &DS,
916 ) -> Result<(), Err>
917 where
918 W: ByteWriter,
919 {
920 encode_start_faces(&self.interior_cfg, writer)?;
921 encode_attribute_seams(
922 self.processed_connectivity_corners,
923 att_data,
924 pos_corner_table,
925 gds,
926 writer,
927 )?;
928
929 for context in self.context_symbols {
931 leb128_write(context.len() as u64, writer);
932 if context.is_empty() {
933 continue;
934 }
935 let context = context
936 .iter()
937 .map(|&s| s.get_id() as u64)
938 .collect::<Vec<_>>();
939
940 encode_symbols(context, 1, SymbolEncodingMethod::DirectCoded, writer)?;
941 }
942
943 Ok(())
944 }
945}