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]>,
15 pub attributes: Vec<Attribute>,
16
17 name: String,
19}
20
21impl Default for Mesh {
22 fn default() -> Self {
23 Self::new()
24 }
25}
26
27impl Mesh {
28 pub fn get_attributes(&self) -> &[Attribute] {
29 &self.attributes
30 }
31
32 pub fn get_faces(&self) -> &[[PointIdx; 3]] {
33 &self.faces
34 }
35
36 pub fn get_attributes_mut(&mut self) -> &mut [Attribute] {
37 &mut self.attributes
38 }
39
40 pub fn get_attributes_mut_by_indices<'a>(
41 &'a mut self,
42 indices: &[usize],
43 ) -> Vec<&'a mut Attribute> {
44 let out = indices
45 .iter()
46 .map(|i| &mut self.attributes[*i] as *mut Attribute)
47 .collect::<Vec<_>>();
48
49 unsafe {
50 let out = out.to_vec();
51 std::mem::transmute::<Vec<*mut Attribute>, Vec<&mut Attribute>>(out)
52 }
53 }
54
55 pub fn get_name(&self) -> &str {
56 &self.name
57 }
58
59 pub fn set_name(&mut self, name: &str) {
60 self.name = name.to_owned();
61 }
62
63 pub fn new() -> Self {
64 Self {
65 faces: Vec::new(),
66 attributes: Vec::new(),
67
68 name: String::new(),
69 }
70 }
71
72 pub fn diff_l2_norm(&self, other: &Self) -> f64 {
73 let pos_att_iter = self
74 .attributes
75 .iter()
76 .enumerate()
77 .filter(|(_, att)| att.get_attribute_type() == AttributeType::Position);
78 let other_pos_att_iter = other
79 .attributes
80 .iter()
81 .enumerate()
82 .filter(|(_, att)| att.get_attribute_type() == AttributeType::Position);
83
84 let mut num_points = 0;
85 let mut sum_of_squared_dist = 0.0;
86 for ((_, pos_att), (_, other_pos_att)) in pos_att_iter.zip(other_pos_att_iter) {
87 if pos_att.get_num_components() != 3 {
88 panic!("Position attribute must have 3 components, but the first mesh has {} components", pos_att.get_num_components());
89 }
90
91 let faces = &self.faces;
93 let other_faces = &other.faces;
94
95 num_points += pos_att.len();
96 num_points += other_pos_att.len();
97 sum_of_squared_dist +=
98 sum_of_squared_dist_unpack_datatype(pos_att, faces, other_pos_att, other_faces);
99 }
100
101 sum_of_squared_dist.sqrt() / num_points as f64
102 }
103}
104
105fn sum_of_squared_dist_unpack_datatype(
106 position_att: &Attribute,
107 faces: &[[PointIdx; 3]],
108 other_position_att: &Attribute,
109 other_faces: &[[PointIdx; 3]],
110) -> f64 {
111 unsafe {
115 match position_att.get_component_type() {
116 ComponentDataType::F32 => sum_of_squared_dist_impl::<f32>(
117 position_att,
118 faces,
119 other_position_att,
120 other_faces,
121 ) as f64,
122 ComponentDataType::F64 => sum_of_squared_dist_impl::<f64>(
123 position_att,
124 faces,
125 other_position_att,
126 other_faces,
127 ),
128 _ => panic!("Position Attribute is not of type f32 or f64"),
129 }
130 }
131}
132
133unsafe fn sum_of_squared_dist_impl<F>(
135 self_pos_att: &Attribute,
136 self_faces: &[[PointIdx; 3]],
137 other_pos_att: &Attribute,
138 other_faces: &[[PointIdx; 3]],
139) -> F
140where
141 F: Float,
142 NdVector<3, F>: Vector<3, Component = F>,
143{
144 assert!(
145 other_pos_att.get_component_type() == self_pos_att.get_component_type(),
146 "Component types must match, but the first mesh has {:?} and the second mesh has {:?}",
147 self_pos_att.get_component_type(),
148 other_pos_att.get_component_type()
149 );
150
151 if other_pos_att.get_num_components() != 3 {
152 panic!(
153 "Position attribute must have 3 components, but the second mesh has {} components",
154 other_pos_att.get_num_components()
155 );
156 }
157
158 let self_pos_att = self_pos_att.unique_vals_as_slice_unchecked::<NdVector<3, F>>();
160 let other_pos_att = unsafe { other_pos_att.unique_vals_as_slice_unchecked::<NdVector<3, F>>() };
162
163 let mut sum_of_squared_dist = F::zero();
164 for pos in self_pos_att.iter() {
165 let min_dist = min_dist_point_to_faces(*pos, other_faces, other_pos_att);
166 sum_of_squared_dist += min_dist * min_dist;
167 }
168 for pos in other_pos_att.iter() {
169 let min_dist = min_dist_point_to_faces(*pos, self_faces, self_pos_att);
170 sum_of_squared_dist += min_dist * min_dist;
171 }
172
173 sum_of_squared_dist.sqrt()
174}
175
176fn min_dist_point_to_faces<F>(
177 p: NdVector<3, F>,
178 faces: &[[PointIdx; 3]],
179 pos_att: &[NdVector<3, F>],
180) -> F
181where
182 F: Float,
183{
184 let mut min_dist = F::MAX_VALUE;
185 for face in faces {
186 let v0 = pos_att[usize::from(face[0])];
187 let v1 = pos_att[usize::from(face[1])];
188 let v2 = pos_att[usize::from(face[2])];
189 let dist = point_to_face_distance_3d(p, [v0, v1, v2]);
190 if dist < min_dist {
191 min_dist = dist;
192 }
193 }
194 min_dist
195}