mesh_graph/ops/
subdivide.rs1use hashbrown::{HashMap, HashSet};
2use tracing::{error, instrument};
3
4use crate::{
5 HalfedgeId, MeshGraph, Selection, SelectionOps, VertexId, error_none, utils::unwrap_or_return,
6};
7
8#[cfg(feature = "rerun")]
9use crate::utils::vec3_array;
10
11impl MeshGraph {
12 #[instrument(skip(self))]
20 pub fn subdivide_edge(&mut self, halfedge_id: HalfedgeId) -> Vec<HalfedgeId> {
21 let mut new_halfedges = Vec::with_capacity(3);
22
23 let he = unwrap_or_return!(
24 self.halfedges.get(halfedge_id),
25 "Halfedge not found",
26 new_halfedges
27 );
28 let twin_id = unwrap_or_return!(he.twin, "Twin halfedge not found", new_halfedges);
29
30 let start_v = unwrap_or_return!(
31 he.start_vertex(self),
32 "Start vertex not found",
33 new_halfedges
34 );
35 let end_v = he.end_vertex;
36
37 let start_pos = self.positions[start_v];
38 let end_pos = self.positions[end_v];
39
40 let center_pos = (start_pos + end_pos) * 0.5;
41
42 #[cfg(feature = "rerun")]
43 {
44 crate::RR
45 .log(
46 "meshgraph/subdivide/edge",
47 &rerun::Arrows3D::from_vectors([vec3_array(end_pos - start_pos)])
48 .with_origins([vec3_array(start_pos)]),
49 )
50 .unwrap();
51
52 crate::RR
53 .log(
54 "meshgraph/subdivide/center",
55 &rerun::Points3D::new([vec3_array(center_pos)]),
56 )
57 .unwrap();
58 }
59
60 let center_v = self.insert_vertex(center_pos);
61 if let Some(normals) = &mut self.vertex_normals {
62 let start_normal = unwrap_or_return!(
63 normals.get(start_v),
64 "Start normal not found",
65 new_halfedges
66 );
67 let end_normal =
68 unwrap_or_return!(normals.get(end_v), "End normal not found", new_halfedges);
69 normals[center_v] = (start_normal + end_normal).normalize();
70 }
71
72 let new_he = self.insert_halfedge(end_v);
73 self.vertices[center_v].outgoing_halfedge = Some(new_he);
75
76 new_halfedges.push(new_he);
77
78 if let Some(new_face_he) = self.subdivide_face(halfedge_id, new_he, center_v) {
79 new_halfedges.push(new_face_he);
80 }
81
82 let new_twin = self.insert_halfedge(start_v);
83
84 if let Some(new_face_he) = self.subdivide_face(twin_id, new_twin, center_v) {
85 new_halfedges.push(new_face_he);
86 }
87
88 self.halfedges[new_he].twin = Some(twin_id);
90 unwrap_or_return!(
91 self.halfedges.get_mut(twin_id),
92 "Twin halfedge not found",
93 new_halfedges
94 )
95 .twin = Some(new_he);
96
97 self.halfedges[halfedge_id].twin = Some(new_twin);
99 self.halfedges[new_twin].twin = Some(halfedge_id);
101
102 new_halfedges
106 }
107
108 #[instrument(skip(self))]
110 fn subdivide_face(
111 &mut self,
112 existing_halfedge_id: HalfedgeId,
113 new_halfedge_id: HalfedgeId,
114 center_v: VertexId,
115 ) -> Option<HalfedgeId> {
116 let he = self
117 .halfedges
118 .get(existing_halfedge_id)
119 .or_else(error_none!("Halfedge not found"))?;
120
121 let face_id = he.face?;
122 self.faces
123 .get_mut(face_id)
124 .or_else(error_none!("Facee not found"))?
125 .halfedge = existing_halfedge_id;
126
127 let next_he = self.halfedges[existing_halfedge_id]
129 .next
130 .or_else(error_none!("Next halfedge missing"))?;
131 let last_he = self
132 .halfedges
133 .get(next_he)
134 .or_else(error_none!("Next halfedge not found"))?
135 .next
136 .or_else(error_none!("Last halfedge not found"))?;
137
138 let new_he = self.insert_halfedge(self.halfedges[next_he].end_vertex);
140
141 self.halfedges[existing_halfedge_id].next = Some(new_he);
142 self.halfedges[new_he].next = Some(last_he);
143 self.halfedges[new_he].face = Some(face_id);
144
145 let new_twin = self.insert_halfedge(center_v);
146
147 let new_face_id = self.insert_face(new_halfedge_id, next_he, new_twin);
149
150 self.halfedges[new_twin].twin = Some(new_he);
151 self.halfedges[new_he].twin = Some(new_twin);
152
153 self.halfedges[existing_halfedge_id].end_vertex = center_v;
154
155 let face = self.faces[face_id];
157 let new_face = self.faces[new_face_id];
159 self.bvh
160 .insert_or_update_partially(face.aabb(self), face.index, 0.0);
161 self.bvh
162 .insert_or_update_partially(new_face.aabb(self), new_face.index, 0.0);
163
164 #[cfg(feature = "rerun")]
165 {
166 self.log_he_rerun("subdivide/new_he", new_he);
167 self.log_he_rerun("subdivide/new_twin", new_twin);
168 }
169
170 Some(new_he)
171 }
172
173 #[instrument(skip(self))]
180 pub fn subdivide_until_edges_below_max_length(
181 &mut self,
182 max_length_squared: f32,
183 selection: &mut Selection,
184 ) {
185 let mut dedup_halfedges = HashSet::new();
186
187 for he_id in selection.resolve_to_halfedges(self) {
188 let he = unwrap_or_return!(self.halfedges.get(he_id), "Halfedge not found");
189 let twin_already_in = he
190 .twin
191 .map(|twin| dedup_halfedges.contains(&twin))
192 .unwrap_or_else(|| {
193 error!("Twin missing");
194 false
195 });
196
197 if !twin_already_in {
198 dedup_halfedges.insert(he_id);
199 }
200 }
201
202 let mut halfedges_to_subdivide = dedup_halfedges
203 .into_iter()
204 .filter_map(|he| {
205 let len = self.halfedges[he].length_squared(self);
207 (len > max_length_squared).then_some((he, len))
208 })
209 .collect::<HashMap<_, _>>();
210
211 while !halfedges_to_subdivide.is_empty() {
212 let mut max_len = 0.0;
213 let mut max_he_id = HalfedgeId::default();
214
215 #[cfg(feature = "rerun")]
216 self.log_hes_rerun(
217 "subdivide/selection",
218 &halfedges_to_subdivide
219 .iter()
220 .map(|(he, _)| *he)
221 .collect::<Vec<_>>(),
222 );
223
224 for (&he, &len) in &halfedges_to_subdivide {
225 if len > max_len {
226 max_len = len;
227 max_he_id = he;
228 }
229 }
230
231 halfedges_to_subdivide.remove(&max_he_id);
232
233 let mut affected_faces = Selection::default();
234
235 let max_he = self.halfedges[max_he_id];
237 if let Some(face_id) = max_he.face {
238 selection.insert(face_id);
239 affected_faces.insert(face_id);
240
241 #[cfg(feature = "rerun")]
242 self.log_face_rerun("subdivide/selected_new", face_id);
243 }
244
245 if let Some(twin_id) = max_he.twin.or_else(error_none!("Twin missing"))
246 && let Some(twin_he) = self
247 .halfedges
248 .get(twin_id)
249 .or_else(error_none!("Halfedge not found"))
250 && let Some(twin_face_id) = twin_he.face
251 {
252 selection.insert(twin_face_id);
253 affected_faces.insert(twin_face_id);
254
255 #[cfg(feature = "rerun")]
256 self.log_face_rerun("subdivide/selected_new", twin_face_id);
257 }
258
259 let new_edges = self.subdivide_edge(max_he_id);
260
261 #[cfg(feature = "rerun")]
262 {
263 crate::RR
264 .log("meshgraph/subdivide", &rerun::Clear::recursive())
265 .unwrap();
266 crate::RR
267 .log("meshgraph/halfedge/subdivide", &rerun::Clear::recursive())
268 .unwrap();
269 crate::RR
270 .log("meshgraph/face/subdivide", &rerun::Clear::recursive())
271 .unwrap();
272 self.log_rerun();
273 }
274
275 for new_he_id in new_edges {
276 let new_he = self.halfedges[new_he_id];
278
279 if let Some(face_id) = new_he.face {
280 selection.insert(face_id);
281 affected_faces.insert(face_id);
282 #[cfg(feature = "rerun")]
283 self.log_face_rerun("subdivide/selected_new", face_id);
284 }
285
286 let new_twin_id = unwrap_or_return!(new_he.twin, "New twin missing");
287 let new_twin =
288 unwrap_or_return!(self.halfedges.get(new_twin_id), "New twin not found");
289 if let Some(face_id) = new_twin.face {
290 selection.insert(face_id);
291 affected_faces.insert(face_id);
292 #[cfg(feature = "rerun")]
293 self.log_face_rerun("subdivide/selected_new", face_id);
294 }
295 }
296
297 for he_id in affected_faces.resolve_to_halfedges(self) {
298 let he = unwrap_or_return!(self.halfedges.get(he_id), "Halfedge not found");
299 let twin = unwrap_or_return!(he.twin, "Twin missing");
300
301 if halfedges_to_subdivide.contains_key(&twin) {
302 continue;
303 }
304
305 let len_sqr = he.length_squared(self);
306
307 if len_sqr > max_length_squared {
308 #[cfg(feature = "rerun")]
309 self.log_he_rerun("/subdivide/new_edge", he_id);
310 halfedges_to_subdivide.insert(he_id, len_sqr);
311 }
312 }
313 }
314 }
315}
316
317#[cfg(test)]
318mod tests {}