draco_oxide/encode/connectivity/
mod.rs1pub mod config;
2pub(crate) mod edgebreaker;
3pub(crate) mod sequential;
4
5use std::fmt::Debug;
6
7use crate::encode::connectivity::edgebreaker::{DefaultTraversal, ValenceTraversal};
8use draco_oxide_core::attribute::AttributeType;
9use draco_oxide_core::bit_coder::ByteWriter;
10use draco_oxide_core::codec::connectivity::edgebreaker::EdgebreakerKind;
11use draco_oxide_core::mesh::ds::AttributeDS;
12use draco_oxide_core::types::{ConfigType, CornerIdx};
13
14#[cfg(feature = "evaluation")]
15use crate::eval;
16
17pub fn encode_connectivity<'faces, W>(
19 adss: &mut [AttributeDS<'faces>],
20 writer: &mut W,
21 cfg: &super::Config,
22) -> Result<Vec<CornerIdx>, Err>
23where
24 W: ByteWriter,
25{
26 #[cfg(feature = "evaluation")]
27 eval::scope_begin("connectivity info", writer);
28
29 let result = encode_connectivity_datatype_unpacked(adss, writer, cfg.connectivity.clone());
30
31 #[cfg(feature = "evaluation")]
32 eval::scope_end(writer);
33 result
34}
35
36pub fn encode_connectivity_datatype_unpacked<'faces, W>(
37 adss: &mut [AttributeDS<'faces>],
38 writer: &mut W,
39 cfg: Config,
40) -> Result<Vec<CornerIdx>, Err>
41where
42 W: ByteWriter,
43{
44 let corners_of_edgebreaker = match cfg {
45 Config::Edgebreaker(cfg) => {
46 #[cfg(feature = "evaluation")]
47 eval::scope_begin("edgebreaker", writer);
48
49 let result = match cfg.traversal {
50 EdgebreakerKind::Standard => {
51 let encoder =
52 edgebreaker::Edgebreaker::new(cfg, adss, |_| DefaultTraversal::new())?;
53 encoder.encode_connectivity(writer)?
54 }
55 EdgebreakerKind::Predictive => {
56 unimplemented!("Predictive edgebreaker encoding is not implemented yet");
57 }
58 EdgebreakerKind::Valence => {
59 let encoder = edgebreaker::Edgebreaker::new(cfg, adss, ValenceTraversal::new)?;
60 encoder.encode_connectivity(writer)?
61 }
62 };
63
64 #[cfg(feature = "evaluation")]
65 eval::scope_end(writer);
66
67 result
68 }
69 Config::Sequential(cfg) => {
70 #[cfg(feature = "evaluation")]
71 eval::scope_begin("sequential", writer);
72
73 let num_points = adss
74 .iter()
75 .find(|ads| ads.att_data().get_attribute_type() == AttributeType::Position)
76 .unwrap()
77 .att_data()
78 .len();
79 let faces = (0..adss[0].global_ds().num_faces())
80 .map(|i| {
81 let c = CornerIdx::from(3 * i);
82 [
83 adss[0].global_ds().point_idx(c),
84 adss[0].global_ds().point_idx(c.next()),
85 adss[0].global_ds().point_idx(c.next().next()),
86 ]
87 })
88 .collect::<Vec<_>>();
89 let encoder = sequential::Sequential::new(&faces, cfg, num_points);
90 encoder.encode_connectivity(writer)?
92 }
93 };
94 Ok(corners_of_edgebreaker)
95}
96
97pub trait ConnectivityEncoder {
98 type Err;
99 type Config;
100 fn encode_connectivity<W>(self, writer: &mut W) -> Result<Vec<CornerIdx>, Self::Err>
101 where
102 W: ByteWriter;
103}
104
105#[remain::sorted]
106#[derive(thiserror::Error, Debug)]
107pub enum Err {
108 #[error("Edgebreaker encoding error: {0}")]
109 EdgebreakerError(#[from] edgebreaker::Err),
110 #[error("Position attribute must be of type f32 or f64")]
111 PositionAttributeTypeError,
112 #[error("Sequential encoding error: {0}")]
113 SequentialError(#[from] sequential::Err),
114 #[error("Too many connectivity attributes")]
115 TooManyConnectivityAttributes,
116}
117
118#[remain::sorted]
119#[derive(Clone, Debug)]
120pub enum Config {
121 Edgebreaker(edgebreaker::Config),
122 #[allow(unused)] Sequential(sequential::Config),
124}
125
126impl ConfigType for Config {
127 fn default() -> Self {
128 Self::Edgebreaker(edgebreaker::Config::default())
129 }
130}
131
132impl Config {
133 pub fn encoder_method(&self) -> draco_oxide_core::codec::header::EncoderMethod {
136 use draco_oxide_core::codec::header::EncoderMethod;
137 match self {
138 Config::Edgebreaker(_) => EncoderMethod::Edgebreaker,
139 Config::Sequential(_) => EncoderMethod::Sequential,
140 }
141 }
142}