1a1089c427b17a954a37ce32578aee1389f498d8
[blender.git] / source / blender / bmesh / operators / bmesh_dupeops.c
1 #include "MEM_guardedalloc.h"
2
3 #include "BKE_utildefines.h"
4
5 #include "BLI_ghash.h"
6 #include "BLI_memarena.h"
7 #include "BLI_blenlib.h"
8 #include "BLI_arithb.h"
9
10 #include "bmesh.h"
11 #include "bmesh_operators_private.h"
12
13 /*local flag defines*/
14 #define DUPE_INPUT              1 /*input from operator*/
15 #define DUPE_NEW                2
16 #define DUPE_DONE               4
17 #define DUPE_MAPPED             8
18
19 /*
20  *  COPY VERTEX
21  *
22  *   Copy an existing vertex from one bmesh to another.
23  *
24 */
25 static BMVert *copy_vertex(BMesh *source_mesh, BMVert *source_vertex, BMesh *target_mesh, GHash *vhash)
26 {
27         BMVert *target_vertex = NULL;
28
29         /*Create a new vertex*/
30         target_vertex = BM_Make_Vert(target_mesh, source_vertex->co,  NULL);
31         
32         /*Insert new vertex into the vert hash*/
33         BLI_ghash_insert(vhash, source_vertex, target_vertex);  
34         
35         /*Copy attributes*/
36         BM_Copy_Attributes(source_mesh, target_mesh, source_vertex, target_vertex);
37         
38         /*Set internal op flags*/
39         BMO_SetFlag(target_mesh, (BMHeader*)target_vertex, DUPE_NEW);
40         
41         return target_vertex;
42 }
43
44 /*
45  * COPY EDGE
46  *
47  * Copy an existing edge from one bmesh to another.
48  *
49 */
50 static BMEdge *copy_edge(BMOperator *op, BMesh *source_mesh,
51                          BMEdge *source_edge, BMesh *target_mesh,
52                          GHash *vhash, GHash *ehash)
53 {
54         BMEdge *target_edge = NULL;
55         BMVert *target_vert1, *target_vert2;
56         BMFace *face;
57         BMIter fiter;
58         int rlen;
59
60         /*see if any of the neighboring faces are
61           not being duplicated.  in that case,
62           add it to the new/old map.*/
63         rlen = 0;
64         for (face=BMIter_New(&fiter,source_mesh, BM_FACES_OF_EDGE,source_edge);
65                 face; face=BMIter_Step(&fiter)) {
66                 if (BMO_TestFlag(source_mesh, face, DUPE_INPUT)) {
67                         rlen++;
68                 }
69         }
70
71         /*Lookup v1 and v2*/
72         target_vert1 = BLI_ghash_lookup(vhash, source_edge->v1);
73         target_vert2 = BLI_ghash_lookup(vhash, source_edge->v2);
74         
75         /*Create a new edge*/
76         target_edge = BM_Make_Edge(target_mesh, target_vert1, target_vert2, NULL, 0);
77         
78         /*add to new/old edge map if necassary*/
79         if (rlen < 2) {
80                 /*not sure what non-manifold cases of greater then three
81                   radial should do.*/
82                 BMO_Insert_MapPointer(source_mesh,op, "boundarymap",
83                         source_edge, target_edge);
84         }
85
86         /*Insert new edge into the edge hash*/
87         BLI_ghash_insert(ehash, source_edge, target_edge);      
88         
89         /*Copy attributes*/
90         BM_Copy_Attributes(source_mesh, target_mesh, source_edge, target_edge);
91         
92         /*Set internal op flags*/
93         BMO_SetFlag(target_mesh, (BMHeader*)target_edge, DUPE_NEW);
94         
95         return target_edge;
96 }
97
98 /*
99  * COPY FACE
100  *
101  *  Copy an existing face from one bmesh to another.
102  *
103 */
104 static BMFace *copy_face(BMOperator *op, BMesh *source_mesh,
105                          BMFace *source_face, BMesh *target_mesh, 
106                          BMEdge **edar, GHash *vhash, GHash *ehash)
107 {
108         BMVert *target_vert1, *target_vert2;
109         BMLoop *source_loop, *target_loop;
110         BMFace *target_face = NULL;
111         BMIter iter, iter2;
112         int i;
113         
114         /*lookup the first and second verts*/
115         target_vert1 = BLI_ghash_lookup(vhash, BMIter_New(&iter, source_mesh, BM_VERTS_OF_FACE, source_face));
116         target_vert2 = BLI_ghash_lookup(vhash, BMIter_Step(&iter));
117         
118         /*lookup edges*/
119         for (i=0,source_loop=BMIter_New(&iter, source_mesh, BM_LOOPS_OF_FACE, source_face); 
120                      source_loop; source_loop=BMIter_Step(&iter), i++) {
121                 edar[i] = BLI_ghash_lookup(ehash, source_loop->e);
122         }
123         
124         /*create new face*/
125         target_face = BM_Make_Ngon(target_mesh, target_vert1, target_vert2, edar, source_face->len, 0); 
126         BMO_Insert_MapPointer(source_mesh, op, 
127                  "facemap", source_face, target_face);
128         BMO_Insert_MapPointer(source_mesh, op, 
129                  "facemap", target_face, source_face);
130
131         BM_Copy_Attributes(source_mesh, target_mesh, source_face, target_face);
132
133         /*mark the face for output*/
134         BMO_SetFlag(target_mesh, (BMHeader*)target_face, DUPE_NEW);
135         
136         /*copy per-loop custom data*/
137         for (i=0,source_loop=BMIter_New(&iter, source_mesh, BM_LOOPS_OF_FACE, source_face),
138           target_loop=BMIter_New(&iter2, target_mesh, BM_LOOPS_OF_FACE, target_face);
139           source_loop && target_loop; source_loop=BMIter_Step(&iter), target_loop=BMIter_Step(&iter2),
140           i++) {
141                 BM_Copy_Attributes(source_mesh, target_mesh, source_loop, target_loop);         
142         }
143
144
145         return target_face;
146 }
147         /*
148  * COPY MESH
149  *
150  * Internal Copy function.
151 */
152
153 static void copy_mesh(BMOperator *op, BMesh *source, BMesh *target)
154 {
155
156         BMVert *v = NULL, *v2;
157         BMEdge *e = NULL, **edar = NULL;
158         BMLoop *l = NULL;
159         BMFace *f = NULL;
160         
161         BMIter verts;
162         BMIter edges;
163         BMIter faces;
164         
165         GHash *vhash;
166         GHash *ehash;
167         
168         int maxlength = 0;
169
170         /*initialize pointer hashes*/
171         vhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); 
172         ehash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
173         
174         /*initialize edge pointer array*/
175         for(f = BMIter_New(&faces, source, BM_FACES_OF_MESH, source); f; f = BMIter_Step(&faces)){
176                 if(f->len > maxlength) maxlength = f->len;
177         }
178         edar = MEM_callocN(sizeof(BMEdge*) * maxlength, "BM copy mesh edge pointer array");
179         
180         /*first we dupe all flagged faces and their elements from source*/
181         for(f = BMIter_New(&faces, source, BM_FACES_OF_MESH, source); f; f= BMIter_Step(&faces)){
182                 if(BMO_TestFlag(source, (BMHeader*)f, DUPE_INPUT)){
183                         /*vertex pass*/
184                         for(v = BMIter_New(&verts, source, BM_VERTS_OF_FACE, f); v; v = BMIter_Step(&verts)){
185                                 if(!BMO_TestFlag(source, (BMHeader*)v, DUPE_DONE)){ 
186                                         copy_vertex(source,v, target, vhash);
187                                         BMO_SetFlag(source, (BMHeader*)v, DUPE_DONE);
188                                 }
189                         }
190
191                         /*edge pass*/
192                         for(e = BMIter_New(&edges, source, BM_EDGES_OF_FACE, f); e; e = BMIter_Step(&edges)){
193                                 if(!BMO_TestFlag(source, (BMHeader*)e, DUPE_DONE)){
194                                         copy_edge(op, source, e, target,  vhash,  ehash);
195                                         BMO_SetFlag(source, (BMHeader*)e, DUPE_DONE);
196                                 }
197                         }
198                         copy_face(op, source, f, target, edar, vhash, ehash);
199                         BMO_SetFlag(source, (BMHeader*)f, DUPE_DONE);
200                 }
201         }
202         
203         /*now we dupe all the edges*/
204         for(e = BMIter_New(&edges, source, BM_EDGES_OF_MESH, source); e; e = BMIter_Step(&edges)){
205                 if(BMO_TestFlag(source, (BMHeader*)e, DUPE_INPUT) && (!BMO_TestFlag(source, (BMHeader*)e, DUPE_DONE))){
206                         /*make sure that verts are copied*/
207                         if(!BMO_TestFlag(source, (BMHeader*)e->v1, DUPE_DONE)) {
208                                 copy_vertex(source, e->v1, target, vhash);
209                                 BMO_SetFlag(source, (BMHeader*)e->v1, DUPE_DONE);
210                         }
211                         if(!BMO_TestFlag(source, (BMHeader*)e->v2, DUPE_DONE)) {
212                                 copy_vertex(source, e->v2, target, vhash);
213                                 BMO_SetFlag(source, (BMHeader*)e->v2, DUPE_DONE);
214                         }
215                         /*now copy the actual edge*/
216                         copy_edge(op, source, e, target,  vhash,  ehash);                       
217                         BMO_SetFlag(source, (BMHeader*)e, DUPE_DONE); 
218                 }
219         }
220         
221         /*finally dupe all loose vertices*/
222         for(v = BMIter_New(&verts, source, BM_VERTS_OF_MESH, source); v; v = BMIter_Step(&verts)){
223                 if(BMO_TestFlag(source, (BMHeader*)v, DUPE_INPUT) && (!BMO_TestFlag(source, (BMHeader*)v, DUPE_DONE))){
224                         v2 = copy_vertex(source, v, target, vhash);
225                         BMO_Insert_MapPointer(source, op, 
226                                          "isovertmap", v, v2);
227                         BMO_SetFlag(source, (BMHeader*)v, DUPE_DONE);
228                 }
229         }
230
231         /*free pointer hashes*/
232         BLI_ghash_free(vhash, NULL, NULL);
233         BLI_ghash_free(ehash, NULL, NULL);      
234
235         /*free edge pointer array*/
236         if(edar)
237                 MEM_freeN(edar);
238 }
239
240 /*
241 BMesh *bmesh_make_mesh_from_mesh(BMesh *bm, int allocsize[4])
242 {
243         BMesh *target = NULL;
244         target = bmesh_make_mesh(allocsize);
245         
246
247         CustomData_copy(&bm->vdata, &target->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
248         CustomData_copy(&bm->edata, &target->edata, CD_MASK_BMESH, CD_CALLOC, 0);
249         CustomData_copy(&bm->ldata, &target->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
250         CustomData_copy(&bm->pdata, &target->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
251         
252
253         CustomData_bmesh_init_pool(&target->vdata, allocsize[0]);
254         CustomData_bmesh_init_pool(&target->edata, allocsize[1]);
255         CustomData_bmesh_init_pool(&target->ldata, allocsize[2]);
256         CustomData_bmesh_init_pool(&target->pdata, allocsize[3]);
257         
258         bmesh_begin_edit(bm);
259         bmesh_begin_edit(target);
260         
261         bmesh_copy_mesh(bm, target, 0);
262
263         bmesh_end_edit(bm);
264         bmesh_end_edit(target);
265         
266         return target;
267
268 }
269 */
270
271 /*
272  * Duplicate Operator
273  *
274  * Duplicates verts, edges and faces of a mesh.
275  *
276  * INPUT SLOTS:
277  *
278  * BMOP_DUPE_VINPUT: Buffer containing pointers to mesh vertices to be duplicated
279  * BMOP_DUPE_EINPUT: Buffer containing pointers to mesh edges to be duplicated
280  * BMOP_DUPE_FINPUT: Buffer containing pointers to mesh faces to be duplicated
281  *
282  * OUTPUT SLOTS:
283  * 
284  * BMOP_DUPE_VORIGINAL: Buffer containing pointers to the original mesh vertices
285  * BMOP_DUPE_EORIGINAL: Buffer containing pointers to the original mesh edges
286  * BMOP_DUPE_FORIGINAL: Buffer containing pointers to the original mesh faces
287  * BMOP_DUPE_VNEW: Buffer containing pointers to the new mesh vertices
288  * BMOP_DUPE_ENEW: Buffer containing pointers to the new mesh edges
289  * BMOP_DUPE_FNEW: Buffer containing pointers to the new mesh faces
290  *
291 */
292
293 void dupeop_exec(BMesh *bm, BMOperator *op)
294 {
295         BMOperator *dupeop = op;
296         
297         /*flag input*/
298         BMO_Flag_Buffer(bm, dupeop, "geom", DUPE_INPUT);
299         /*use the internal copy function*/
300         copy_mesh(dupeop, bm, bm);
301         
302         /*Output*/
303         /*First copy the input buffers to output buffers - original data*/
304         BMO_CopySlot(dupeop, dupeop, "geom", "origout");
305
306         /*Now alloc the new output buffers*/
307         BMO_Flag_To_Slot(bm, dupeop, "newout", DUPE_NEW, BM_ALL);
308 }
309
310 /*executes the duplicate operation, feeding elements of 
311   type flag etypeflag and header flag flag to it.  note,
312   to get more useful information (such as the mapping from
313   original to new elements) you should run the dupe op manually.*/
314 void BMOP_DupeFromFlag(BMesh *bm, int etypeflag, int flag)
315 {
316         BMOperator dupeop;
317
318         BMO_Init_Op(&dupeop, "dupe");
319         BMO_HeaderFlag_To_Slot(bm, &dupeop, "geom", flag, etypeflag);
320
321         BMO_Exec_Op(bm, &dupeop);
322         BMO_Finish_Op(bm, &dupeop);
323 }
324
325 /*
326  * Split Operator
327  *
328  * Duplicates verts, edges and faces of a mesh but also deletes the originals.
329  *
330  * INPUT SLOTS:
331  *
332  * BMOP_DUPE_VINPUT: Buffer containing pointers to mesh vertices to be split
333  * BMOP_DUPE_EINPUT: Buffer containing pointers to mesh edges to be split
334  * BMOP_DUPE_FINPUT: Buffer containing pointers to mesh faces to be split
335  *
336  * OUTPUT SLOTS:
337  * 
338  * BMOP_DUPE_VOUTPUT: Buffer containing pointers to the split mesh vertices
339  * BMOP_DUPE_EOUTPUT: Buffer containing pointers to the split mesh edges
340  * BMOP_DUPE_FOUTPUT: Buffer containing pointers to the split mesh faces
341  *
342 */
343
344 #define SPLIT_INPUT     1
345 void splitop_exec(BMesh *bm, BMOperator *op)
346 {
347         BMOperator *splitop = op;
348         BMOperator dupeop;
349         BMOperator delop;
350         BMVert *v;
351         BMEdge *e;
352         BMFace *f;
353         BMIter iter, iter2;
354         int found;
355
356         /*initialize our sub-operators*/
357         BMO_Init_Op(&dupeop, "dupe");
358         BMO_Init_Op(&delop, "del");
359         
360         BMO_CopySlot(splitop, &dupeop, "geom", "geom");
361         BMO_Exec_Op(bm, &dupeop);
362         
363         BMO_Flag_Buffer(bm, splitop, "geom", SPLIT_INPUT);
364
365         /*make sure to remove edges and verts we don't need.*/
366         for (e= BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);e;e=BMIter_Step(&iter)) {
367                 found = 0;
368                 f = BMIter_New(&iter2, bm, BM_FACES_OF_EDGE, e);
369                 for (; f; f=BMIter_Step(&iter2)) {
370                         if (!BMO_TestFlag(bm, f, SPLIT_INPUT)) {
371                                 found = 1;
372                                 break;
373                         }
374                 }
375                 if (!found) BMO_SetFlag(bm, e, SPLIT_INPUT);
376         }
377         
378         for (v= BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);v;v=BMIter_Step(&iter)) {
379                 found = 0;
380                 e = BMIter_New(&iter2, bm, BM_EDGES_OF_VERT, v);
381                 for (; e; e=BMIter_Step(&iter2)) {
382                         if (!BMO_TestFlag(bm, e, SPLIT_INPUT)) {
383                                 found = 1;
384                                 break;
385                         }
386                 }
387                 if (!found) BMO_SetFlag(bm, v, SPLIT_INPUT);
388
389         }
390
391         /*connect outputs of dupe to delete, exluding keep geometry*/
392         BMO_Set_Int(&delop, "context", DEL_FACES);
393         BMO_Flag_To_Slot(bm, &delop, "geom", SPLIT_INPUT, BM_ALL);
394         
395         BMO_Exec_Op(bm, &delop);
396
397         /*now we make our outputs by copying the dupe outputs*/
398         BMO_CopySlot(&dupeop, splitop, "newout", "geom");
399         BMO_CopySlot(&dupeop, splitop, "boundarymap",
400                      "boundarymap");
401         BMO_CopySlot(&dupeop, splitop, "isovertmap",
402                      "isovertmap");
403         
404         /*cleanup*/
405         BMO_Finish_Op(bm, &delop);
406         BMO_Finish_Op(bm, &dupeop);
407 }
408
409 #define DEL_INPUT               1
410 #define DEL_WIREVERT    2
411
412 static void delete_verts(BMesh *bm);
413 static void delete_context(BMesh *bm, int type);
414
415 void delop_exec(BMesh *bm, BMOperator *op)
416 {
417         BMOperator *delop = op;
418
419         /*Mark Buffers*/
420         BMO_Flag_Buffer(bm, delop, "geom", DEL_INPUT);
421
422         delete_context(bm, BMO_Get_Int(op, "context"));
423 }
424
425 static void delete_verts(BMesh *bm)
426 {
427         BMVert *v;
428         BMEdge *e;
429         BMLoop *f;
430         
431         BMIter verts;
432         BMIter edges;
433         BMIter faces;
434         
435         for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts)){
436                 if(BMO_TestFlag(bm, (BMHeader*)v, DEL_INPUT)) {
437                         /*Visit edges*/
438                         for(e = BMIter_New(&edges, bm, BM_EDGES_OF_VERT, v); e; e = BMIter_Step(&edges))
439                                 BMO_SetFlag(bm, (BMHeader*)e, DEL_INPUT);
440                         /*Visit faces*/
441                         for(f = BMIter_New(&faces, bm, BM_FACES_OF_VERT, v); f; f = BMIter_Step(&faces))
442                                 BMO_SetFlag(bm, (BMHeader*)f, DEL_INPUT);
443                 }
444         }
445
446         BM_remove_tagged_faces(bm, DEL_INPUT);
447         BM_remove_tagged_edges(bm, DEL_INPUT);
448         BM_remove_tagged_verts(bm, DEL_INPUT);
449 }
450
451 static void delete_edges(BMesh *bm){
452         BMEdge *e;
453         BMFace *f;
454         
455         BMIter edges;
456         BMIter faces;
457
458         for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges)){
459                 if(BMO_TestFlag(bm, (BMHeader*)e, DEL_INPUT)) {
460                         for(f = BMIter_New(&faces, bm, BM_FACES_OF_EDGE, e); f; f = BMIter_Step(&faces)){
461                                         BMO_SetFlag(bm, (BMHeader*)f, DEL_INPUT);
462                         }
463                 }
464         }
465         BM_remove_tagged_faces(bm, DEL_INPUT);
466         BM_remove_tagged_edges(bm, DEL_INPUT);
467 }
468
469 /*you need to make remove tagged verts/edges/faces
470         api functions that take a filter callback.....
471         and this new filter type will be for opstack flags.
472         This is because the BM_remove_taggedXXX functions bypass iterator API.
473                  -Ops dont care about 'UI' considerations like selection state, hide state, ect. If you want to work on unhidden selections for instance,
474                  copy output from a 'select context' operator to another operator....
475 */
476
477 /*Break this into smaller functions*/
478
479 static void delete_context(BMesh *bm, int type){
480         BMVert *v;
481         BMEdge *e;
482         BMFace *f;
483
484         BMIter verts;
485         BMIter edges;
486         BMIter faces;
487         
488         if(type == DEL_VERTS) delete_verts(bm);
489         else if(type == DEL_EDGES){
490                 /*flush down to verts*/
491                 for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges)){
492                         if(BMO_TestFlag(bm, (BMHeader*)e, DEL_INPUT)){
493                                 BMO_SetFlag(bm, (BMHeader*)(e->v1), DEL_INPUT);
494                                 BMO_SetFlag(bm, (BMHeader*)(e->v2), DEL_INPUT);
495                         }
496                 }
497                 delete_edges(bm);
498                 /*remove loose vertices*/
499                 for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts)){
500                         if(BMO_TestFlag(bm, (BMHeader*)v, DEL_INPUT) && (!(v->edge)))
501                                 BMO_SetFlag(bm, (BMHeader*)v, DEL_WIREVERT);
502                 }
503                 BM_remove_tagged_verts(bm, DEL_WIREVERT);
504         }
505         else if(type == DEL_EDGESFACES) delete_edges(bm);
506         else if(type == DEL_ONLYFACES) BM_remove_tagged_faces(bm, DEL_INPUT);
507         else if (type == DEL_ONLYTAGGED) {
508                 BM_remove_tagged_faces(bm, DEL_INPUT);
509                 BM_remove_tagged_edges(bm, DEL_INPUT);
510                 BM_remove_tagged_verts(bm, DEL_INPUT);
511         } else if(type == DEL_FACES){
512                 /*go through and mark all edges and all verts of all faces for delete*/
513                 for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces)){
514                         if(BMO_TestFlag(bm, (BMHeader*)f, DEL_INPUT)){
515                                 for(e = BMIter_New(&edges, bm, BM_EDGES_OF_FACE, f); e; e = BMIter_Step(&edges))
516                                         BMO_SetFlag(bm, (BMHeader*)e, DEL_INPUT);
517                                 for(v = BMIter_New(&verts, bm, BM_VERTS_OF_FACE, f); v; v = BMIter_Step(&verts))
518                                         BMO_SetFlag(bm, (BMHeader*)v, DEL_INPUT);
519                         }
520                 }
521                 /*now go through and mark all remaining faces all edges for keeping.*/
522                 for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces)){
523                         if(!BMO_TestFlag(bm, (BMHeader*)f, DEL_INPUT)){
524                                 for(e = BMIter_New(&edges, bm, BM_EDGES_OF_FACE, f); e; e= BMIter_Step(&edges))
525                                         BMO_ClearFlag(bm, (BMHeader*)e, DEL_INPUT);
526                                 for(v = BMIter_New(&verts, bm, BM_VERTS_OF_FACE, f); v; v= BMIter_Step(&verts))
527                                         BMO_ClearFlag(bm, (BMHeader*)v, DEL_INPUT);
528                         }
529                 }
530                 /*now delete marked faces*/
531                 BM_remove_tagged_faces(bm, DEL_INPUT);
532                 /*delete marked edges*/
533                 BM_remove_tagged_edges(bm, DEL_INPUT);
534                 /*remove loose vertices*/
535                 BM_remove_tagged_verts(bm, DEL_INPUT);
536         }
537         /*does this option even belong in here?*/
538         else if(type == DEL_ALL){
539                 for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces))
540                         BMO_SetFlag(bm, (BMHeader*)f, DEL_INPUT);
541                 for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges))
542                         BMO_SetFlag(bm, (BMHeader*)e, DEL_INPUT);
543                 for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts))
544                         BMO_SetFlag(bm, (BMHeader*)v, DEL_INPUT);
545                 
546                 BM_remove_tagged_faces(bm, DEL_INPUT);
547                 BM_remove_tagged_edges(bm, DEL_INPUT);
548                 BM_remove_tagged_verts(bm, DEL_INPUT);
549         }
550 }