draco_oxide_core/mesh/
mod.rs1pub mod builder;
2pub mod ds;
3
4use crate::attribute::{Attribute, AttributeType, ComponentDataType};
5use crate::types::{Float, Vector};
6use crate::types::{NdVector, PointIdx};
7use crate::utils::geom::point_to_face_distance_3d;
8
9#[derive(Clone, Debug)]
13pub struct Mesh {
14 pub faces: Vec<[PointIdx; 3]>,
16 pub attributes: Vec<Attribute>,
18
19 name: String,
20}
21
22impl Default for Mesh {
23 fn default() -> Self {
24 Self::new()
25 }
26}
27
28impl Mesh {
29 pub fn get_attributes(&self) -> &[Attribute] {
31 &self.attributes
32 }
33
34 pub fn get_faces(&self) -> &[[PointIdx; 3]] {
36 &self.faces
37 }
38
39 pub fn get_attributes_mut(&mut self) -> &mut [Attribute] {
41 &mut self.attributes
42 }
43
44 pub fn get_attributes_mut_by_indices<'a>(
50 &'a mut self,
51 indices: &[usize],
52 ) -> Vec<&'a mut Attribute> {
53 let out = indices
54 .iter()
55 .map(|i| &mut self.attributes[*i] as *mut Attribute)
56 .collect::<Vec<_>>();
57
58 unsafe {
61 let out = out.to_vec();
62 std::mem::transmute::<Vec<*mut Attribute>, Vec<&mut Attribute>>(out)
63 }
64 }
65
66 pub fn get_name(&self) -> &str {
68 &self.name
69 }
70
71 pub fn set_name(&mut self, name: &str) {
73 self.name = name.to_owned();
74 }
75
76 pub fn new() -> Self {
78 Self {
79 faces: Vec::new(),
80 attributes: Vec::new(),
81
82 name: String::new(),
83 }
84 }
85
86 pub fn diff_l2_norm(&self, other: &Self) -> f64 {
91 let pos_att_iter = self
92 .attributes
93 .iter()
94 .enumerate()
95 .filter(|(_, att)| att.get_attribute_type() == AttributeType::Position);
96 let other_pos_att_iter = other
97 .attributes
98 .iter()
99 .enumerate()
100 .filter(|(_, att)| att.get_attribute_type() == AttributeType::Position);
101
102 let mut num_points = 0;
103 let mut sum_of_squared_dist = 0.0;
104 for ((_, pos_att), (_, other_pos_att)) in pos_att_iter.zip(other_pos_att_iter) {
105 if pos_att.get_num_components() != 3 {
106 panic!("Position attribute must have 3 components, but the first mesh has {} components", pos_att.get_num_components());
107 }
108
109 let faces = &self.faces;
111 let other_faces = &other.faces;
112
113 num_points += pos_att.len();
114 num_points += other_pos_att.len();
115 sum_of_squared_dist +=
116 sum_of_squared_dist_unpack_datatype(pos_att, faces, other_pos_att, other_faces);
117 }
118
119 sum_of_squared_dist.sqrt() / num_points as f64
120 }
121}
122
123fn sum_of_squared_dist_unpack_datatype(
124 position_att: &Attribute,
125 faces: &[[PointIdx; 3]],
126 other_position_att: &Attribute,
127 other_faces: &[[PointIdx; 3]],
128) -> f64 {
129 unsafe {
133 match position_att.get_component_type() {
134 ComponentDataType::F32 => sum_of_squared_dist_impl::<f32>(
135 position_att,
136 faces,
137 other_position_att,
138 other_faces,
139 ) as f64,
140 ComponentDataType::F64 => sum_of_squared_dist_impl::<f64>(
141 position_att,
142 faces,
143 other_position_att,
144 other_faces,
145 ),
146 _ => panic!("Position Attribute is not of type f32 or f64"),
147 }
148 }
149}
150
151unsafe fn sum_of_squared_dist_impl<F>(
153 self_pos_att: &Attribute,
154 self_faces: &[[PointIdx; 3]],
155 other_pos_att: &Attribute,
156 other_faces: &[[PointIdx; 3]],
157) -> F
158where
159 F: Float,
160 NdVector<3, F>: Vector<3, Component = F>,
161{
162 assert!(
163 other_pos_att.get_component_type() == self_pos_att.get_component_type(),
164 "Component types must match, but the first mesh has {:?} and the second mesh has {:?}",
165 self_pos_att.get_component_type(),
166 other_pos_att.get_component_type()
167 );
168
169 if other_pos_att.get_num_components() != 3 {
170 panic!(
171 "Position attribute must have 3 components, but the second mesh has {} components",
172 other_pos_att.get_num_components()
173 );
174 }
175
176 let resolve = |att: &Attribute, faces: &[[PointIdx; 3]]| -> Vec<[usize; 3]> {
180 faces
181 .iter()
182 .map(|f| {
183 [
184 usize::from(att.get_unique_val_idx(f[0])),
185 usize::from(att.get_unique_val_idx(f[1])),
186 usize::from(att.get_unique_val_idx(f[2])),
187 ]
188 })
189 .collect()
190 };
191 let self_face_vals = resolve(self_pos_att, self_faces);
192 let other_face_vals = resolve(other_pos_att, other_faces);
193
194 let self_pos_att = self_pos_att.unique_vals_as_slice_unchecked::<NdVector<3, F>>();
196 let other_pos_att = unsafe { other_pos_att.unique_vals_as_slice_unchecked::<NdVector<3, F>>() };
198
199 let mut sum_of_squared_dist = F::zero();
200 for pos in self_pos_att.iter() {
201 let min_dist = min_dist_point_to_faces(*pos, &other_face_vals, other_pos_att);
202 sum_of_squared_dist += min_dist * min_dist;
203 }
204 for pos in other_pos_att.iter() {
205 let min_dist = min_dist_point_to_faces(*pos, &self_face_vals, self_pos_att);
206 sum_of_squared_dist += min_dist * min_dist;
207 }
208
209 sum_of_squared_dist.sqrt()
210}
211
212fn min_dist_point_to_faces<F>(
213 p: NdVector<3, F>,
214 face_vals: &[[usize; 3]],
215 pos_att: &[NdVector<3, F>],
216) -> F
217where
218 F: Float,
219{
220 let mut min_dist = F::MAX_VALUE;
221 for face in face_vals {
222 let v0 = pos_att[face[0]];
223 let v1 = pos_att[face[1]];
224 let v2 = pos_att[face[2]];
225 let dist = point_to_face_distance_3d(p, [v0, v1, v2]);
226 if dist < min_dist {
227 min_dist = dist;
228 }
229 }
230 min_dist
231}