1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * The Original Code is Copyright (C) 2007 Blender Foundation.
17 * All rights reserved.
18 */
19
20 /** \file
21 * \ingroup bmesh
22 *
23 * BM remove functions.
24 */
25
26 #include "BLI_utildefines.h"
27
28 #include "bmesh.h"
29 #include "intern/bmesh_private.h"
30
31 /* -------------------------------------------------------------------- */
32 /* BMO functions */
33
34 /** \name BMesh Operator Delete Functions
35 * \{ */
36
37 /**
38 * Called by operators to remove elements that they have marked for
39 * removal.
40 */
bmo_remove_tagged_faces(BMesh * bm,const short oflag)41 static void bmo_remove_tagged_faces(BMesh *bm, const short oflag)
42 {
43 BMFace *f, *f_next;
44 BMIter iter;
45
46 BM_ITER_MESH_MUTABLE (f, f_next, &iter, bm, BM_FACES_OF_MESH) {
47 if (BMO_face_flag_test(bm, f, oflag)) {
48 BM_face_kill(bm, f);
49 }
50 }
51 }
52
bmo_remove_tagged_edges(BMesh * bm,const short oflag)53 static void bmo_remove_tagged_edges(BMesh *bm, const short oflag)
54 {
55 BMEdge *e, *e_next;
56 BMIter iter;
57
58 BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
59 if (BMO_edge_flag_test(bm, e, oflag)) {
60 BM_edge_kill(bm, e);
61 }
62 }
63 }
64
bmo_remove_tagged_verts(BMesh * bm,const short oflag)65 static void bmo_remove_tagged_verts(BMesh *bm, const short oflag)
66 {
67 BMVert *v, *v_next;
68 BMIter iter;
69
70 BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
71 if (BMO_vert_flag_test(bm, v, oflag)) {
72 BM_vert_kill(bm, v);
73 }
74 }
75 }
76
bmo_remove_tagged_verts_loose(BMesh * bm,const short oflag)77 static void bmo_remove_tagged_verts_loose(BMesh *bm, const short oflag)
78 {
79 BMVert *v, *v_next;
80 BMIter iter;
81
82 BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
83 if (BMO_vert_flag_test(bm, v, oflag) && (v->e == NULL)) {
84 BM_vert_kill(bm, v);
85 }
86 }
87 }
88
BMO_mesh_delete_oflag_tagged(BMesh * bm,const short oflag,const char htype)89 void BMO_mesh_delete_oflag_tagged(BMesh *bm, const short oflag, const char htype)
90 {
91 if (htype & BM_FACE) {
92 bmo_remove_tagged_faces(bm, oflag);
93 }
94 if (htype & BM_EDGE) {
95 bmo_remove_tagged_edges(bm, oflag);
96 }
97 if (htype & BM_VERT) {
98 bmo_remove_tagged_verts(bm, oflag);
99 }
100 }
101
102 /**
103 * \warning oflag applies to different types in some contexts,
104 * not just the type being removed.
105 */
BMO_mesh_delete_oflag_context(BMesh * bm,const short oflag,const int type)106 void BMO_mesh_delete_oflag_context(BMesh *bm, const short oflag, const int type)
107 {
108 BMEdge *e;
109 BMFace *f;
110
111 BMIter eiter;
112 BMIter fiter;
113
114 switch (type) {
115 case DEL_VERTS: {
116 bmo_remove_tagged_verts(bm, oflag);
117
118 break;
119 }
120 case DEL_EDGES: {
121 /* flush down to vert */
122 BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
123 if (BMO_edge_flag_test(bm, e, oflag)) {
124 BMO_vert_flag_enable(bm, e->v1, oflag);
125 BMO_vert_flag_enable(bm, e->v2, oflag);
126 }
127 }
128 bmo_remove_tagged_edges(bm, oflag);
129 bmo_remove_tagged_verts_loose(bm, oflag);
130
131 break;
132 }
133 case DEL_EDGESFACES: {
134 bmo_remove_tagged_edges(bm, oflag);
135
136 break;
137 }
138 case DEL_ONLYFACES: {
139 bmo_remove_tagged_faces(bm, oflag);
140
141 break;
142 }
143 case DEL_ONLYTAGGED: {
144 BMO_mesh_delete_oflag_tagged(bm, oflag, BM_ALL_NOLOOP);
145
146 break;
147 }
148 case DEL_FACES:
149 case DEL_FACES_KEEP_BOUNDARY: {
150 /* go through and mark all edges and all verts of all faces for delete */
151 BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
152 if (BMO_face_flag_test(bm, f, oflag)) {
153 BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
154 BMLoop *l_iter;
155
156 l_iter = l_first;
157 do {
158 BMO_vert_flag_enable(bm, l_iter->v, oflag);
159 BMO_edge_flag_enable(bm, l_iter->e, oflag);
160 } while ((l_iter = l_iter->next) != l_first);
161 }
162 }
163 /* now go through and mark all remaining faces all edges for keeping */
164 BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
165 if (!BMO_face_flag_test(bm, f, oflag)) {
166 BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
167 BMLoop *l_iter;
168
169 l_iter = l_first;
170 do {
171 BMO_vert_flag_disable(bm, l_iter->v, oflag);
172 BMO_edge_flag_disable(bm, l_iter->e, oflag);
173 } while ((l_iter = l_iter->next) != l_first);
174 }
175 }
176 /* also mark all the vertices of remaining edges for keeping */
177 BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
178
179 /* Only exception to normal 'DEL_FACES' logic. */
180 if (type == DEL_FACES_KEEP_BOUNDARY) {
181 if (BM_edge_is_boundary(e)) {
182 BMO_edge_flag_disable(bm, e, oflag);
183 }
184 }
185
186 if (!BMO_edge_flag_test(bm, e, oflag)) {
187 BMO_vert_flag_disable(bm, e->v1, oflag);
188 BMO_vert_flag_disable(bm, e->v2, oflag);
189 }
190 }
191
192 /* now delete marked face */
193 bmo_remove_tagged_faces(bm, oflag);
194 /* delete marked edge */
195 bmo_remove_tagged_edges(bm, oflag);
196 /* remove loose vertice */
197 bmo_remove_tagged_verts(bm, oflag);
198
199 break;
200 }
201 }
202 }
203
204 /** \} */
205
206 /* -------------------------------------------------------------------- */
207 /* BM functions
208 *
209 * note! this is just a duplicate of the code above (bad!)
210 * but for now keep in sync, its less hassle than having to create bmesh operator flags,
211 * each time we need to remove some geometry.
212 */
213
214 /** \name BMesh Delete Functions (no oflags)
215 * \{ */
216
bm_remove_tagged_faces(BMesh * bm,const char hflag)217 static void bm_remove_tagged_faces(BMesh *bm, const char hflag)
218 {
219 BMFace *f, *f_next;
220 BMIter iter;
221
222 BM_ITER_MESH_MUTABLE (f, f_next, &iter, bm, BM_FACES_OF_MESH) {
223 if (BM_elem_flag_test(f, hflag)) {
224 BM_face_kill(bm, f);
225 }
226 }
227 }
228
bm_remove_tagged_edges(BMesh * bm,const char hflag)229 static void bm_remove_tagged_edges(BMesh *bm, const char hflag)
230 {
231 BMEdge *e, *e_next;
232 BMIter iter;
233
234 BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
235 if (BM_elem_flag_test(e, hflag)) {
236 BM_edge_kill(bm, e);
237 }
238 }
239 }
240
bm_remove_tagged_verts(BMesh * bm,const char hflag)241 static void bm_remove_tagged_verts(BMesh *bm, const char hflag)
242 {
243 BMVert *v, *v_next;
244 BMIter iter;
245
246 BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
247 if (BM_elem_flag_test(v, hflag)) {
248 BM_vert_kill(bm, v);
249 }
250 }
251 }
252
bm_remove_tagged_verts_loose(BMesh * bm,const char hflag)253 static void bm_remove_tagged_verts_loose(BMesh *bm, const char hflag)
254 {
255 BMVert *v, *v_next;
256 BMIter iter;
257
258 BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
259 if (BM_elem_flag_test(v, hflag) && (v->e == NULL)) {
260 BM_vert_kill(bm, v);
261 }
262 }
263 }
264
BM_mesh_delete_hflag_tagged(BMesh * bm,const char hflag,const char htype)265 void BM_mesh_delete_hflag_tagged(BMesh *bm, const char hflag, const char htype)
266 {
267 if (htype & BM_FACE) {
268 bm_remove_tagged_faces(bm, hflag);
269 }
270 if (htype & BM_EDGE) {
271 bm_remove_tagged_edges(bm, hflag);
272 }
273 if (htype & BM_VERT) {
274 bm_remove_tagged_verts(bm, hflag);
275 }
276 }
277
278 /**
279 * \warning oflag applies to different types in some contexts,
280 * not just the type being removed.
281 */
BM_mesh_delete_hflag_context(BMesh * bm,const char hflag,const int type)282 void BM_mesh_delete_hflag_context(BMesh *bm, const char hflag, const int type)
283 {
284 BMEdge *e;
285 BMFace *f;
286
287 BMIter eiter;
288 BMIter fiter;
289
290 switch (type) {
291 case DEL_VERTS: {
292 bm_remove_tagged_verts(bm, hflag);
293
294 break;
295 }
296 case DEL_EDGES: {
297 /* flush down to vert */
298 BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
299 if (BM_elem_flag_test(e, hflag)) {
300 BM_elem_flag_enable(e->v1, hflag);
301 BM_elem_flag_enable(e->v2, hflag);
302 }
303 }
304 bm_remove_tagged_edges(bm, hflag);
305 bm_remove_tagged_verts_loose(bm, hflag);
306
307 break;
308 }
309 case DEL_EDGESFACES: {
310 bm_remove_tagged_edges(bm, hflag);
311
312 break;
313 }
314 case DEL_ONLYFACES: {
315 bm_remove_tagged_faces(bm, hflag);
316
317 break;
318 }
319 case DEL_ONLYTAGGED: {
320 BM_mesh_delete_hflag_tagged(bm, hflag, BM_ALL_NOLOOP);
321
322 break;
323 }
324 case DEL_FACES: {
325 /* go through and mark all edges and all verts of all faces for delete */
326 BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
327 if (BM_elem_flag_test(f, hflag)) {
328 BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
329 BMLoop *l_iter;
330
331 l_iter = l_first;
332 do {
333 BM_elem_flag_enable(l_iter->v, hflag);
334 BM_elem_flag_enable(l_iter->e, hflag);
335 } while ((l_iter = l_iter->next) != l_first);
336 }
337 }
338 /* now go through and mark all remaining faces all edges for keeping */
339 BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
340 if (!BM_elem_flag_test(f, hflag)) {
341 BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
342 BMLoop *l_iter;
343
344 l_iter = l_first;
345 do {
346 BM_elem_flag_disable(l_iter->v, hflag);
347 BM_elem_flag_disable(l_iter->e, hflag);
348 } while ((l_iter = l_iter->next) != l_first);
349 }
350 }
351 /* also mark all the vertices of remaining edges for keeping */
352 BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
353 if (!BM_elem_flag_test(e, hflag)) {
354 BM_elem_flag_disable(e->v1, hflag);
355 BM_elem_flag_disable(e->v2, hflag);
356 }
357 }
358 /* now delete marked face */
359 bm_remove_tagged_faces(bm, hflag);
360 /* delete marked edge */
361 bm_remove_tagged_edges(bm, hflag);
362 /* remove loose vertice */
363 bm_remove_tagged_verts(bm, hflag);
364
365 break;
366 }
367 }
368 }
369
370 /** \} */
371