mesh_graph/ops/
subdivide.rs1use hashbrown::{HashMap, HashSet};
2
3use crate::{HalfedgeId, MeshGraph, Selection, SelectionOps, VertexId};
4
5#[cfg(feature = "rerun")]
6use crate::utils::vec3_array;
7
8impl MeshGraph {
9 pub fn subdivide_edge(&mut self, halfedge_id: HalfedgeId) -> Vec<HalfedgeId> {
17 let he = &self.halfedges[halfedge_id];
18 let twin_id = he.twin();
19
20 let start_v = he.start_vertex(self);
21 let end_v = he.end_vertex;
22
23 let start_pos = self.positions[start_v];
24 let end_pos = self.positions[end_v];
25
26 let center_pos = (start_pos + end_pos) * 0.5;
27
28 #[cfg(feature = "rerun")]
29 {
30 crate::RR
31 .log(
32 "meshgraph/subdivide/edge",
33 &rerun::Arrows3D::from_vectors([vec3_array(end_pos - start_pos)])
34 .with_origins([vec3_array(start_pos)]),
35 )
36 .unwrap();
37
38 crate::RR
39 .log(
40 "meshgraph/subdivide/center",
41 &rerun::Points3D::new([vec3_array(center_pos)]),
42 )
43 .unwrap();
44 }
45
46 let center_v = self.insert_vertex(center_pos);
47 if let Some(normals) = &mut self.vertex_normals {
48 normals[center_v] = (normals[start_v] + normals[end_v]).normalize();
49 }
50
51 let new_he = self.insert_halfedge(end_v);
52 self.vertices[center_v].outgoing_halfedge = Some(new_he);
53
54 let mut new_halfedges = Vec::with_capacity(3);
55 new_halfedges.push(new_he);
56
57 if let Some(new_face_he) = self.subdivide_face(halfedge_id, new_he, center_v) {
58 new_halfedges.push(new_face_he);
59 }
60
61 let new_twin = self.insert_halfedge(start_v);
62
63 if let Some(new_face_he) = self.subdivide_face(twin_id, new_twin, center_v) {
64 new_halfedges.push(new_face_he);
65 }
66
67 self.halfedges[new_he].twin = Some(twin_id);
68 self.halfedges[twin_id].twin = Some(new_he);
69
70 self.halfedges[halfedge_id].twin = Some(new_twin);
71 self.halfedges[new_twin].twin = Some(halfedge_id);
72
73 new_halfedges
77 }
78
79 fn subdivide_face(
81 &mut self,
82 existing_halfedge_id: HalfedgeId,
83 new_halfedge_id: HalfedgeId,
84 center_v: VertexId,
85 ) -> Option<HalfedgeId> {
86 let he = &self.halfedges[existing_halfedge_id];
87
88 let face_id = he.face?;
89 self.faces[face_id].halfedge = existing_halfedge_id;
90
91 let next_he = self.halfedges[existing_halfedge_id].next.unwrap();
92 let last_he = self.halfedges[next_he].next.unwrap();
93
94 let new_he = self.insert_halfedge(self.halfedges[next_he].end_vertex);
96
97 self.halfedges[existing_halfedge_id].next = Some(new_he);
98 self.halfedges[new_he].next = Some(last_he);
99 self.halfedges[new_he].face = Some(face_id);
100
101 let new_face_id = self.insert_face(new_halfedge_id);
103
104 self.qbvh.pre_update_or_insert(self.faces[face_id]);
105 self.qbvh.pre_update_or_insert(self.faces[new_face_id]);
106
107 let new_twin = self.insert_halfedge(center_v);
108
109 self.halfedges[new_twin].next = Some(new_halfedge_id);
110 self.halfedges[new_twin].face = Some(new_face_id);
111 self.halfedges[new_twin].twin = Some(new_he);
112 self.halfedges[new_he].twin = Some(new_twin);
113
114 self.halfedges[new_halfedge_id].next = Some(next_he);
115 self.halfedges[new_halfedge_id].face = Some(new_face_id);
116
117 self.halfedges[next_he].next = Some(new_twin);
118 self.halfedges[next_he].face = Some(new_face_id);
119
120 self.halfedges[existing_halfedge_id].end_vertex = center_v;
121
122 #[cfg(feature = "rerun")]
123 {
124 self.log_he_rerun("subdivide/new_he", new_he);
125 self.log_he_rerun("subdivide/new_twin", new_twin);
126 }
127
128 Some(new_he)
129 }
130
131 pub fn subdivide_until_edges_below_max_length(
138 &mut self,
139 max_length_squared: f32,
140 selection: &mut Selection,
141 ) {
142 let mut dedup_halfedges = HashSet::new();
143
144 for he in selection.resolve_to_halfedges(self) {
145 let twin = self.halfedges[he].twin;
146 let twin_already_in = twin
147 .map(|twin| dedup_halfedges.contains(&twin))
148 .unwrap_or_default();
149
150 if !twin_already_in {
151 dedup_halfedges.insert(he);
152 }
153 }
154
155 let mut halfedges_to_subdivide = dedup_halfedges
156 .into_iter()
157 .filter_map(|he| {
158 let len = self.halfedges[he].length_squared(self);
159 (len > max_length_squared).then_some((he, len))
160 })
161 .collect::<HashMap<_, _>>();
162
163 while !halfedges_to_subdivide.is_empty() {
164 let mut max_len = 0.0;
165 let mut max_he_id = HalfedgeId::default();
166
167 #[cfg(feature = "rerun")]
168 self.log_hes_rerun(
169 "subdivide/selection",
170 &halfedges_to_subdivide
171 .iter()
172 .map(|(he, _)| *he)
173 .collect::<Vec<_>>(),
174 );
175
176 for (&he, &len) in &halfedges_to_subdivide {
177 if len > max_len {
178 max_len = len;
179 max_he_id = he;
180 }
181 }
182
183 halfedges_to_subdivide.remove(&max_he_id);
184
185 let mut affected_faces = Selection::default();
186
187 let max_he = self.halfedges[max_he_id];
188 if let Some(face_id) = max_he.face {
189 selection.insert(face_id);
190 affected_faces.insert(face_id);
191
192 #[cfg(feature = "rerun")]
193 self.log_face_rerun("subdivide/selected_new", face_id);
194 }
195
196 if let Some(twin_face_id) = self.halfedges[max_he.twin()].face {
197 selection.insert(twin_face_id);
198 affected_faces.insert(twin_face_id);
199
200 #[cfg(feature = "rerun")]
201 self.log_face_rerun("subdivide/selected_new", twin_face_id);
202 }
203
204 let new_edges = self.subdivide_edge(max_he_id);
205
206 #[cfg(feature = "rerun")]
207 {
208 crate::RR
209 .log("meshgraph/subdivide", &rerun::Clear::recursive())
210 .unwrap();
211 crate::RR
212 .log("meshgraph/halfedge/subdivide", &rerun::Clear::recursive())
213 .unwrap();
214 crate::RR
215 .log("meshgraph/face/subdivide", &rerun::Clear::recursive())
216 .unwrap();
217 self.log_rerun();
218 }
219
220 for new_he_id in new_edges {
221 let new_he = self.halfedges[new_he_id];
222
223 if let Some(face_id) = new_he.face {
224 selection.insert(face_id);
225 affected_faces.insert(face_id);
226 #[cfg(feature = "rerun")]
227 self.log_face_rerun("subdivide/selected_new", face_id);
228 }
229
230 if let Some(face_id) = self.halfedges[new_he.twin()].face {
231 selection.insert(face_id);
232 affected_faces.insert(face_id);
233 #[cfg(feature = "rerun")]
234 self.log_face_rerun("subdivide/selected_new", face_id);
235 }
236 }
237
238 for he_id in affected_faces.resolve_to_halfedges(self) {
239 let he = self.halfedges[he_id];
240
241 if halfedges_to_subdivide.contains_key(&he.twin()) {
242 continue;
243 }
244
245 let len_sqr = he.length_squared(self);
246
247 if len_sqr > max_length_squared {
248 #[cfg(feature = "rerun")]
249 self.log_he_rerun("/subdivide/new_edge", he_id);
250 halfedges_to_subdivide.insert(he_id, len_sqr);
251 }
252 }
253 }
254 }
255}
256
257#[cfg(test)]
258mod tests {}