mesh_graph/ops/
subdivide.rs

1use 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    /// Subdivides an edge by computing it's center vertex. This also subdivides any adjacent triangles and
13    /// makes sure everything is properly reconnected. Works only on triangle meshes.
14    ///
15    /// Returns the id of the new halfedge which goes from the center vertex to the original edge's end vertex.
16    /// And also return the halfedges that are created by subdividing the adjacent faces. Only one of the two twin
17    /// halfedges per face subdivision is returned. In total the number `n` of halfedges returned is `1 <= n <= 3`.
18    /// (The one from dividing the halfedge and at most 2 from dividing the two adjacent faces).
19    #[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        // inserted just above
74        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        // inserted above
89        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        // checked in the beginning of the function
98        self.halfedges[halfedge_id].twin = Some(new_twin);
99        // inserted above
100        self.halfedges[new_twin].twin = Some(halfedge_id);
101
102        // self.vertices[end_v].outgoing_halfedge = Some(new_twin);
103        // self.vertices[start_v].outgoing_halfedge = Some(new_he);
104
105        new_halfedges
106    }
107
108    /// Subdivides a triangle into two halves. Used in [Self::subdivide_edge].
109    #[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        // checked above
128        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        // rewire existing face
139        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        // insert new face
148        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        // checked above
156        let face = self.faces[face_id];
157        // freshly inserted
158        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    /// Subdivide all edges in the selection until all of them are <= max_length.
174    /// Please note that you have to provide the squared value of max_length.
175    /// All new edges created during this process are added to the selection.
176    ///
177    /// This will schedule necessary updates to the QBVH but you have to call
178    /// `refit()` and maybe `rebalance()` after the operation.
179    #[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                // already checked above
206                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            // already checked
236            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                // newly inserted in `self.subdivide_edge`
277                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 {}