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_face_id = self.insert_face(new_halfedge_id);
147
148 let face = self.faces[face_id];
150 let new_face = self.faces[new_face_id];
152 self.bvh
153 .insert_or_update_partially(face.aabb(self), face.index, 0.0);
154 self.bvh
155 .insert_or_update_partially(new_face.aabb(self), new_face.index, 0.0);
156
157 let new_twin = self.insert_halfedge(center_v);
158
159 self.halfedges[new_twin].next = Some(new_halfedge_id);
160 self.halfedges[new_twin].face = Some(new_face_id);
161 self.halfedges[new_twin].twin = Some(new_he);
162 self.halfedges[new_he].twin = Some(new_twin);
163
164 self.halfedges[new_halfedge_id].next = Some(next_he);
166 self.halfedges[new_halfedge_id].face = Some(new_face_id);
167
168 self.halfedges[next_he].next = Some(new_twin);
170 self.halfedges[next_he].face = Some(new_face_id);
171
172 self.halfedges[existing_halfedge_id].end_vertex = center_v;
173
174 #[cfg(feature = "rerun")]
175 {
176 self.log_he_rerun("subdivide/new_he", new_he);
177 self.log_he_rerun("subdivide/new_twin", new_twin);
178 }
179
180 Some(new_he)
181 }
182
183 #[instrument(skip(self))]
190 pub fn subdivide_until_edges_below_max_length(
191 &mut self,
192 max_length_squared: f32,
193 selection: &mut Selection,
194 ) {
195 let mut dedup_halfedges = HashSet::new();
196
197 for he_id in selection.resolve_to_halfedges(self) {
198 let he = unwrap_or_return!(self.halfedges.get(he_id), "Halfedge not found");
199 let twin_already_in = he
200 .twin
201 .map(|twin| dedup_halfedges.contains(&twin))
202 .unwrap_or_else(|| {
203 error!("Twin missing");
204 false
205 });
206
207 if !twin_already_in {
208 dedup_halfedges.insert(he_id);
209 }
210 }
211
212 let mut halfedges_to_subdivide = dedup_halfedges
213 .into_iter()
214 .filter_map(|he| {
215 let len = self.halfedges[he].length_squared(self);
217 (len > max_length_squared).then_some((he, len))
218 })
219 .collect::<HashMap<_, _>>();
220
221 while !halfedges_to_subdivide.is_empty() {
222 let mut max_len = 0.0;
223 let mut max_he_id = HalfedgeId::default();
224
225 #[cfg(feature = "rerun")]
226 self.log_hes_rerun(
227 "subdivide/selection",
228 &halfedges_to_subdivide
229 .iter()
230 .map(|(he, _)| *he)
231 .collect::<Vec<_>>(),
232 );
233
234 for (&he, &len) in &halfedges_to_subdivide {
235 if len > max_len {
236 max_len = len;
237 max_he_id = he;
238 }
239 }
240
241 halfedges_to_subdivide.remove(&max_he_id);
242
243 let mut affected_faces = Selection::default();
244
245 let max_he = self.halfedges[max_he_id];
247 if let Some(face_id) = max_he.face {
248 selection.insert(face_id);
249 affected_faces.insert(face_id);
250
251 #[cfg(feature = "rerun")]
252 self.log_face_rerun("subdivide/selected_new", face_id);
253 }
254
255 if let Some(twin_id) = max_he.twin.or_else(error_none!("Twin missing"))
256 && let Some(twin_he) = self
257 .halfedges
258 .get(twin_id)
259 .or_else(error_none!("Halfedge not found"))
260 && let Some(twin_face_id) = twin_he.face
261 {
262 selection.insert(twin_face_id);
263 affected_faces.insert(twin_face_id);
264
265 #[cfg(feature = "rerun")]
266 self.log_face_rerun("subdivide/selected_new", twin_face_id);
267 }
268
269 let new_edges = self.subdivide_edge(max_he_id);
270
271 #[cfg(feature = "rerun")]
272 {
273 crate::RR
274 .log("meshgraph/subdivide", &rerun::Clear::recursive())
275 .unwrap();
276 crate::RR
277 .log("meshgraph/halfedge/subdivide", &rerun::Clear::recursive())
278 .unwrap();
279 crate::RR
280 .log("meshgraph/face/subdivide", &rerun::Clear::recursive())
281 .unwrap();
282 self.log_rerun();
283 }
284
285 for new_he_id in new_edges {
286 let new_he = self.halfedges[new_he_id];
288
289 if let Some(face_id) = new_he.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 let new_twin_id = unwrap_or_return!(new_he.twin, "New twin missing");
297 let new_twin =
298 unwrap_or_return!(self.halfedges.get(new_twin_id), "New twin not found");
299 if let Some(face_id) = new_twin.face {
300 selection.insert(face_id);
301 affected_faces.insert(face_id);
302 #[cfg(feature = "rerun")]
303 self.log_face_rerun("subdivide/selected_new", face_id);
304 }
305 }
306
307 for he_id in affected_faces.resolve_to_halfedges(self) {
308 let he = unwrap_or_return!(self.halfedges.get(he_id), "Halfedge not found");
309 let twin = unwrap_or_return!(he.twin, "Twin missing");
310
311 if halfedges_to_subdivide.contains_key(&twin) {
312 continue;
313 }
314
315 let len_sqr = he.length_squared(self);
316
317 if len_sqr > max_length_squared {
318 #[cfg(feature = "rerun")]
319 self.log_he_rerun("/subdivide/new_edge", he_id);
320 halfedges_to_subdivide.insert(he_id, len_sqr);
321 }
322 }
323 }
324 }
325}
326
327#[cfg(test)]
328mod tests {}