1 #include "MEM_guardedalloc.h"
3 #include "BLI_utildefines.h"
6 #include "BLI_memarena.h"
7 #include "BLI_blenlib.h"
12 #include "bmesh_operators_private.h"
14 /*local flag defines*/
15 #define DUPE_INPUT 1 /*input from operator*/
23 * Copy an existing vertex from one bmesh to another.
26 static BMVert *copy_vertex(BMesh *source_mesh, BMVert *source_vertex, BMesh *target_mesh, GHash *vhash)
28 BMVert *target_vertex = NULL;
30 /*Create a new vertex*/
31 target_vertex = BM_Make_Vert(target_mesh, source_vertex->co, NULL);
33 /*Insert new vertex into the vert hash*/
34 BLI_ghash_insert(vhash, source_vertex, target_vertex);
37 BM_Copy_Attributes(source_mesh, target_mesh, source_vertex, target_vertex);
39 /*Set internal op flags*/
40 BMO_SetFlag(target_mesh, (BMHeader*)target_vertex, DUPE_NEW);
48 * Copy an existing edge from one bmesh to another.
51 static BMEdge *copy_edge(BMOperator *op, BMesh *source_mesh,
52 BMEdge *source_edge, BMesh *target_mesh,
53 GHash *vhash, GHash *ehash)
55 BMEdge *target_edge = NULL;
56 BMVert *target_vert1, *target_vert2;
61 /*see if any of the neighboring faces are
62 not being duplicated. in that case,
63 add it to the new/old map.*/
65 for (face=BMIter_New(&fiter,source_mesh, BM_FACES_OF_EDGE,source_edge);
66 face; face=BMIter_Step(&fiter)) {
67 if (BMO_TestFlag(source_mesh, face, DUPE_INPUT)) {
73 target_vert1 = BLI_ghash_lookup(vhash, source_edge->v1);
74 target_vert2 = BLI_ghash_lookup(vhash, source_edge->v2);
77 target_edge = BM_Make_Edge(target_mesh, target_vert1, target_vert2, NULL, 0);
79 /*add to new/old edge map if necassary*/
81 /*not sure what non-manifold cases of greater then three
83 BMO_Insert_MapPointer(source_mesh,op, "boundarymap",
84 source_edge, target_edge);
87 /*Insert new edge into the edge hash*/
88 BLI_ghash_insert(ehash, source_edge, target_edge);
91 BM_Copy_Attributes(source_mesh, target_mesh, source_edge, target_edge);
93 /*Set internal op flags*/
94 BMO_SetFlag(target_mesh, (BMHeader*)target_edge, DUPE_NEW);
102 * Copy an existing face from one bmesh to another.
105 static BMFace *copy_face(BMOperator *op, BMesh *source_mesh,
106 BMFace *source_face, BMesh *target_mesh,
107 BMEdge **edar, GHash *vhash, GHash *ehash)
109 BMVert *target_vert1, *target_vert2;
110 BMLoop *source_loop, *target_loop;
111 BMFace *target_face = NULL;
115 /*lookup the first and second verts*/
116 target_vert1 = BLI_ghash_lookup(vhash, BMIter_New(&iter, source_mesh, BM_VERTS_OF_FACE, source_face));
117 target_vert2 = BLI_ghash_lookup(vhash, BMIter_Step(&iter));
120 for (i=0,source_loop=BMIter_New(&iter, source_mesh, BM_LOOPS_OF_FACE, source_face);
121 source_loop; source_loop=BMIter_Step(&iter), i++) {
122 edar[i] = BLI_ghash_lookup(ehash, source_loop->e);
126 target_face = BM_Make_Ngon(target_mesh, target_vert1, target_vert2, edar, source_face->len, 0);
127 BMO_Insert_MapPointer(source_mesh, op,
128 "facemap", source_face, target_face);
129 BMO_Insert_MapPointer(source_mesh, op,
130 "facemap", target_face, source_face);
132 BM_Copy_Attributes(source_mesh, target_mesh, source_face, target_face);
134 /*mark the face for output*/
135 BMO_SetFlag(target_mesh, (BMHeader*)target_face, DUPE_NEW);
137 /*copy per-loop custom data*/
138 BM_ITER(source_loop, &iter, source_mesh, BM_LOOPS_OF_FACE, source_face) {
139 BM_ITER(target_loop, &iter2, target_mesh, BM_LOOPS_OF_FACE, target_face) {
140 if (BLI_ghash_lookup(vhash, source_loop->v) == target_loop->v) {
141 BM_Copy_Attributes(source_mesh, target_mesh, source_loop, target_loop);
152 * Internal Copy function.
155 static void copy_mesh(BMOperator *op, BMesh *source, BMesh *target)
158 BMVert *v = NULL, *v2;
159 BMEdge *e = NULL, **edar = NULL;
171 /*initialize pointer hashes*/
172 vhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh dupeops v");
173 ehash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh dupeops e");
175 /*initialize edge pointer array*/
176 for(f = BMIter_New(&faces, source, BM_FACES_OF_MESH, source); f; f = BMIter_Step(&faces)){
177 if(f->len > maxlength) maxlength = f->len;
179 edar = MEM_callocN(sizeof(BMEdge*) * maxlength, "BM copy mesh edge pointer array");
181 for(v = BMIter_New(&verts, source, BM_VERTS_OF_MESH, source); v; v = BMIter_Step(&verts)){
182 if(BMO_TestFlag(source, (BMHeader*)v, DUPE_INPUT) && (!BMO_TestFlag(source, (BMHeader*)v, DUPE_DONE))){
186 v2 = copy_vertex(source, v, target, vhash);
188 BM_ITER(f, &iter, source, BM_FACES_OF_VERT, v) {
189 if (BMO_TestFlag(source, f, DUPE_INPUT)) {
196 BM_ITER(e, &iter, source, BM_EDGES_OF_VERT, v) {
197 if (BMO_TestFlag(source, e, DUPE_INPUT)) {
205 BMO_Insert_MapPointer(source, op, "isovertmap", v, v2);
207 BMO_SetFlag(source, (BMHeader*)v, DUPE_DONE);
211 /*now we dupe all the edges*/
212 for(e = BMIter_New(&edges, source, BM_EDGES_OF_MESH, source); e; e = BMIter_Step(&edges)){
213 if(BMO_TestFlag(source, (BMHeader*)e, DUPE_INPUT) && (!BMO_TestFlag(source, (BMHeader*)e, DUPE_DONE))){
214 /*make sure that verts are copied*/
215 if(!BMO_TestFlag(source, (BMHeader*)e->v1, DUPE_DONE)) {
216 copy_vertex(source, e->v1, target, vhash);
217 BMO_SetFlag(source, (BMHeader*)e->v1, DUPE_DONE);
219 if(!BMO_TestFlag(source, (BMHeader*)e->v2, DUPE_DONE)) {
220 copy_vertex(source, e->v2, target, vhash);
221 BMO_SetFlag(source, (BMHeader*)e->v2, DUPE_DONE);
223 /*now copy the actual edge*/
224 copy_edge(op, source, e, target, vhash, ehash);
225 BMO_SetFlag(source, (BMHeader*)e, DUPE_DONE);
229 /*first we dupe all flagged faces and their elements from source*/
230 for(f = BMIter_New(&faces, source, BM_FACES_OF_MESH, source); f; f= BMIter_Step(&faces)){
231 if(BMO_TestFlag(source, (BMHeader*)f, DUPE_INPUT)){
233 for(v = BMIter_New(&verts, source, BM_VERTS_OF_FACE, f); v; v = BMIter_Step(&verts)){
234 if(!BMO_TestFlag(source, (BMHeader*)v, DUPE_DONE)){
235 copy_vertex(source,v, target, vhash);
236 BMO_SetFlag(source, (BMHeader*)v, DUPE_DONE);
241 for(e = BMIter_New(&edges, source, BM_EDGES_OF_FACE, f); e; e = BMIter_Step(&edges)){
242 if(!BMO_TestFlag(source, (BMHeader*)e, DUPE_DONE)){
243 copy_edge(op, source, e, target, vhash, ehash);
244 BMO_SetFlag(source, (BMHeader*)e, DUPE_DONE);
247 copy_face(op, source, f, target, edar, vhash, ehash);
248 BMO_SetFlag(source, (BMHeader*)f, DUPE_DONE);
252 /*free pointer hashes*/
253 BLI_ghash_free(vhash, NULL, NULL);
254 BLI_ghash_free(ehash, NULL, NULL);
256 /*free edge pointer array*/
264 * Duplicates verts, edges and faces of a mesh.
268 * BMOP_DUPE_VINPUT: Buffer containing pointers to mesh vertices to be duplicated
269 * BMOP_DUPE_EINPUT: Buffer containing pointers to mesh edges to be duplicated
270 * BMOP_DUPE_FINPUT: Buffer containing pointers to mesh faces to be duplicated
274 * BMOP_DUPE_VORIGINAL: Buffer containing pointers to the original mesh vertices
275 * BMOP_DUPE_EORIGINAL: Buffer containing pointers to the original mesh edges
276 * BMOP_DUPE_FORIGINAL: Buffer containing pointers to the original mesh faces
277 * BMOP_DUPE_VNEW: Buffer containing pointers to the new mesh vertices
278 * BMOP_DUPE_ENEW: Buffer containing pointers to the new mesh edges
279 * BMOP_DUPE_FNEW: Buffer containing pointers to the new mesh faces
283 void dupeop_exec(BMesh *bm, BMOperator *op)
285 BMOperator *dupeop = op;
286 BMesh *bm2 = BMO_Get_Pnt(op, "dest");
292 BMO_Flag_Buffer(bm, dupeop, "geom", DUPE_INPUT, BM_ALL);
294 /*use the internal copy function*/
295 copy_mesh(dupeop, bm, bm2);
298 /*First copy the input buffers to output buffers - original data*/
299 BMO_CopySlot(dupeop, dupeop, "geom", "origout");
301 /*Now alloc the new output buffers*/
302 BMO_Flag_To_Slot(bm, dupeop, "newout", DUPE_NEW, BM_ALL);
305 /*executes the duplicate operation, feeding elements of
306 type flag etypeflag and header flag flag to it. note,
307 to get more useful information (such as the mapping from
308 original to new elements) you should run the dupe op manually.*/
309 void BMOP_DupeFromFlag(BMesh *bm, int etypeflag, int flag)
313 BMO_Init_Op(&dupeop, "dupe");
314 BMO_HeaderFlag_To_Slot(bm, &dupeop, "geom", flag, etypeflag);
316 BMO_Exec_Op(bm, &dupeop);
317 BMO_Finish_Op(bm, &dupeop);
323 * Duplicates verts, edges and faces of a mesh but also deletes the originals.
327 * BMOP_DUPE_VINPUT: Buffer containing pointers to mesh vertices to be split
328 * BMOP_DUPE_EINPUT: Buffer containing pointers to mesh edges to be split
329 * BMOP_DUPE_FINPUT: Buffer containing pointers to mesh faces to be split
333 * BMOP_DUPE_VOUTPUT: Buffer containing pointers to the split mesh vertices
334 * BMOP_DUPE_EOUTPUT: Buffer containing pointers to the split mesh edges
335 * BMOP_DUPE_FOUTPUT: Buffer containing pointers to the split mesh faces
339 #define SPLIT_INPUT 1
340 void splitop_exec(BMesh *bm, BMOperator *op)
342 BMOperator *splitop = op;
351 /*initialize our sub-operators*/
352 BMO_Init_Op(&dupeop, "dupe");
353 BMO_Init_Op(&delop, "del");
355 BMO_CopySlot(splitop, &dupeop, "geom", "geom");
356 BMO_Exec_Op(bm, &dupeop);
358 BMO_Flag_Buffer(bm, splitop, "geom", SPLIT_INPUT, BM_ALL);
360 /*make sure to remove edges and verts we don't need.*/
361 for (e= BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);e;e=BMIter_Step(&iter)) {
363 f = BMIter_New(&iter2, bm, BM_FACES_OF_EDGE, e);
364 for (; f; f=BMIter_Step(&iter2)) {
365 if (!BMO_TestFlag(bm, f, SPLIT_INPUT)) {
370 if (!found) BMO_SetFlag(bm, e, SPLIT_INPUT);
373 for (v= BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);v;v=BMIter_Step(&iter)) {
375 e = BMIter_New(&iter2, bm, BM_EDGES_OF_VERT, v);
376 for (; e; e=BMIter_Step(&iter2)) {
377 if (!BMO_TestFlag(bm, e, SPLIT_INPUT)) {
382 if (!found) BMO_SetFlag(bm, v, SPLIT_INPUT);
386 /*connect outputs of dupe to delete, exluding keep geometry*/
387 BMO_Set_Int(&delop, "context", DEL_FACES);
388 BMO_Flag_To_Slot(bm, &delop, "geom", SPLIT_INPUT, BM_ALL);
390 BMO_Exec_Op(bm, &delop);
392 /*now we make our outputs by copying the dupe outputs*/
393 BMO_CopySlot(&dupeop, splitop, "newout", "geom");
394 BMO_CopySlot(&dupeop, splitop, "boundarymap",
396 BMO_CopySlot(&dupeop, splitop, "isovertmap",
400 BMO_Finish_Op(bm, &delop);
401 BMO_Finish_Op(bm, &dupeop);
405 #define DEL_WIREVERT 2
407 static void delete_verts(BMesh *bm);
408 static void delete_context(BMesh *bm, int type);
410 void delop_exec(BMesh *bm, BMOperator *op)
412 BMOperator *delop = op;
415 BMO_Flag_Buffer(bm, delop, "geom", DEL_INPUT, BM_ALL);
417 delete_context(bm, BMO_Get_Int(op, "context"));
420 static void delete_verts(BMesh *bm)
430 for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts)){
431 if(BMO_TestFlag(bm, (BMHeader*)v, DEL_INPUT)) {
433 for(e = BMIter_New(&edges, bm, BM_EDGES_OF_VERT, v); e; e = BMIter_Step(&edges))
434 BMO_SetFlag(bm, (BMHeader*)e, DEL_INPUT);
436 for(f = BMIter_New(&faces, bm, BM_FACES_OF_VERT, v); f; f = BMIter_Step(&faces))
437 BMO_SetFlag(bm, (BMHeader*)f, DEL_INPUT);
441 BM_remove_tagged_faces(bm, DEL_INPUT);
442 BM_remove_tagged_edges(bm, DEL_INPUT);
443 BM_remove_tagged_verts(bm, DEL_INPUT);
446 static void delete_edges(BMesh *bm){
453 for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges)){
454 if(BMO_TestFlag(bm, (BMHeader*)e, DEL_INPUT)) {
455 for(f = BMIter_New(&faces, bm, BM_FACES_OF_EDGE, e); f; f = BMIter_Step(&faces)){
456 BMO_SetFlag(bm, (BMHeader*)f, DEL_INPUT);
460 BM_remove_tagged_faces(bm, DEL_INPUT);
461 BM_remove_tagged_edges(bm, DEL_INPUT);
464 /*you need to make remove tagged verts/edges/faces
465 api functions that take a filter callback.....
466 and this new filter type will be for opstack flags.
467 This is because the BM_remove_taggedXXX functions bypass iterator API.
468 -Ops dont care about 'UI' considerations like selection state, hide state, ect. If you want to work on unhidden selections for instance,
469 copy output from a 'select context' operator to another operator....
472 /*Break this into smaller functions*/
474 static void delete_context(BMesh *bm, int type){
483 if(type == DEL_VERTS) delete_verts(bm);
484 else if(type == DEL_EDGES){
485 /*flush down to verts*/
486 for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges)){
487 if(BMO_TestFlag(bm, (BMHeader*)e, DEL_INPUT)){
488 BMO_SetFlag(bm, (BMHeader*)(e->v1), DEL_INPUT);
489 BMO_SetFlag(bm, (BMHeader*)(e->v2), DEL_INPUT);
493 /*remove loose vertices*/
494 for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts)){
495 if(BMO_TestFlag(bm, (BMHeader*)v, DEL_INPUT) && (!(v->e)))
496 BMO_SetFlag(bm, (BMHeader*)v, DEL_WIREVERT);
498 BM_remove_tagged_verts(bm, DEL_WIREVERT);
500 else if(type == DEL_EDGESFACES) delete_edges(bm);
501 else if(type == DEL_ONLYFACES) BM_remove_tagged_faces(bm, DEL_INPUT);
502 else if (type == DEL_ONLYTAGGED) {
503 BM_remove_tagged_faces(bm, DEL_INPUT);
504 BM_remove_tagged_edges(bm, DEL_INPUT);
505 BM_remove_tagged_verts(bm, DEL_INPUT);
506 } else if(type == DEL_FACES){
507 /*go through and mark all edges and all verts of all faces for delete*/
508 for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces)){
509 if(BMO_TestFlag(bm, (BMHeader*)f, DEL_INPUT)){
510 for(e = BMIter_New(&edges, bm, BM_EDGES_OF_FACE, f); e; e = BMIter_Step(&edges))
511 BMO_SetFlag(bm, (BMHeader*)e, DEL_INPUT);
512 for(v = BMIter_New(&verts, bm, BM_VERTS_OF_FACE, f); v; v = BMIter_Step(&verts))
513 BMO_SetFlag(bm, (BMHeader*)v, DEL_INPUT);
516 /*now go through and mark all remaining faces all edges for keeping.*/
517 for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces)){
518 if(!BMO_TestFlag(bm, (BMHeader*)f, DEL_INPUT)){
519 for(e = BMIter_New(&edges, bm, BM_EDGES_OF_FACE, f); e; e= BMIter_Step(&edges))
520 BMO_ClearFlag(bm, (BMHeader*)e, DEL_INPUT);
521 for(v = BMIter_New(&verts, bm, BM_VERTS_OF_FACE, f); v; v= BMIter_Step(&verts))
522 BMO_ClearFlag(bm, (BMHeader*)v, DEL_INPUT);
525 /*now delete marked faces*/
526 BM_remove_tagged_faces(bm, DEL_INPUT);
527 /*delete marked edges*/
528 BM_remove_tagged_edges(bm, DEL_INPUT);
529 /*remove loose vertices*/
530 BM_remove_tagged_verts(bm, DEL_INPUT);
532 /*does this option even belong in here?*/
533 else if(type == DEL_ALL){
534 for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces))
535 BMO_SetFlag(bm, (BMHeader*)f, DEL_INPUT);
536 for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges))
537 BMO_SetFlag(bm, (BMHeader*)e, DEL_INPUT);
538 for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts))
539 BMO_SetFlag(bm, (BMHeader*)v, DEL_INPUT);
541 BM_remove_tagged_faces(bm, DEL_INPUT);
542 BM_remove_tagged_edges(bm, DEL_INPUT);
543 BM_remove_tagged_verts(bm, DEL_INPUT);