bmesh - changes to mempool allocations
[blender-staging.git] / source / blender / bmesh / intern / bmesh_construct.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2007 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Geoffrey Bantle.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/bmesh/intern/bmesh_construct.c
29  *  \ingroup bmesh
30  *
31  * BM construction functions.
32  */
33
34 #include "MEM_guardedalloc.h"
35
36 #include "BLI_array.h"
37 #include "BLI_math.h"
38
39 #include "BKE_customdata.h"
40
41 #include "DNA_meshdata_types.h"
42
43 #include "bmesh.h"
44 #include "bmesh_private.h"
45
46 #define SELECT 1
47
48 /* prototypes */
49 static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
50                                const BMLoop *source_loop, BMLoop *target_loop);
51
52 /**
53  * \brief Make Quad/Triangle
54  *
55  * Creates a new quad or triangle from a list of 3 or 4 vertices.
56  * If \a nodouble is TRUE, then a check is done to see if a face
57  * with these vertices already exists and returns it instead.
58  *
59  * If a pointer to an example face is provided, it's custom data
60  * and properties will be copied to the new face.
61  *
62  * \note The winding of the face is determined by the order
63  * of the vertices in the vertex array.
64  */
65
66 BMFace *BM_face_create_quad_tri(BMesh *bm,
67                                 BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
68                                 const BMFace *example, const int nodouble)
69 {
70         BMVert *vtar[4] = {v1, v2, v3, v4};
71         return BM_face_create_quad_tri_v(bm, vtar, v4 ? 4 : 3, example, nodouble);
72 }
73
74 BMFace *BM_face_create_quad_tri_v(BMesh *bm, BMVert **verts, int len, const BMFace *example, const int nodouble)
75 {
76         BMFace *f = NULL;
77         int is_overlap = FALSE;
78
79         if (nodouble) {
80                 /* check if face exists or overlaps */
81                 is_overlap = BM_face_exists(bm, verts, len, &f);
82         }
83
84         /* make new face */
85         if ((f == NULL) && (!is_overlap)) {
86                 BMEdge *edar[4] = {NULL};
87                 edar[0] = BM_edge_create(bm, verts[0], verts[1], NULL, TRUE);
88                 edar[1] = BM_edge_create(bm, verts[1], verts[2], NULL, TRUE);
89                 if (len == 4) {
90                         edar[2] = BM_edge_create(bm, verts[2], verts[3], NULL, TRUE);
91                         edar[3] = BM_edge_create(bm, verts[3], verts[0], NULL, TRUE);
92                 }
93                 else {
94                         edar[2] = BM_edge_create(bm, verts[2], verts[0], NULL, TRUE);
95                 }
96
97                 f = BM_face_create(bm, verts, edar, len, FALSE);
98
99                 if (example && f) {
100                         BM_elem_attrs_copy(bm, bm, example, f);
101                 }
102         }
103
104         return f;
105 }
106
107 /* copies face data from shared adjacent faces */
108 void BM_face_copy_shared(BMesh *bm, BMFace *f)
109 {
110         BMIter iter;
111         BMLoop *l, *l_other;
112
113         BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
114                 l_other = l->radial_next;
115                 
116                 if (l_other && l_other != l) {
117                         if (l_other->v == l->v) {
118                                 bm_loop_attrs_copy(bm, bm, l_other, l);
119                         }
120                         else {
121                                 l_other = l_other->next;
122                                 bm_loop_attrs_copy(bm, bm, l_other, l);
123                         }
124                 }
125         }
126 }
127
128 /**
129  * \brief Make NGon
130  *
131  * Makes an ngon from an unordered list of edges. \a v1 and \a v2
132  * must be the verts defining edges[0],
133  * and define the winding of the new face.
134  *
135  * \a edges are not required to be ordered, simply to to form
136  * a single closed loop as a whole.
137  *
138  * \note While this function will work fine when the edges
139  * are already sorted, if the edges are always going to be sorted,
140  * #BM_face_create should be considered over this function as it
141  * avoids some unnecessary work.
142  */
143 BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, int nodouble)
144 {
145         BMEdge **edges2 = NULL;
146         BLI_array_staticdeclare(edges2, BM_NGON_STACK_SIZE);
147         BMVert **verts = NULL;
148         BLI_array_staticdeclare(verts, BM_NGON_STACK_SIZE);
149         BMFace *f = NULL;
150         BMEdge *e;
151         BMVert *v, *ev1, *ev2;
152         int i, /* j, */ v1found, reverse;
153
154         /* this code is hideous, yeek.  I'll have to think about ways of
155          *  cleaning it up.  basically, it now combines the old BM_face_create_ngon
156          *  _and_ the old bmesh_mf functions, so its kindof smashed together
157          * - joeedh */
158
159         if (!len || !v1 || !v2 || !edges || !bm)
160                 return NULL;
161
162         /* put edges in correct order */
163         for (i = 0; i < len; i++) {
164                 BM_ELEM_API_FLAG_ENABLE(edges[i], _FLAG_MF);
165         }
166
167         ev1 = edges[0]->v1;
168         ev2 = edges[0]->v2;
169
170         if (v1 == ev2) {
171                 /* Swapping here improves performance and consistency of face
172                  * structure in the special case that the edges are already in
173                  * the correct order and winding */
174                 SWAP(BMVert *, ev1, ev2);
175         }
176
177         BLI_array_append(verts, ev1);
178         v = ev2;
179         e = edges[0];
180         do {
181                 BMEdge *e2 = e;
182
183                 BLI_array_append(verts, v);
184                 BLI_array_append(edges2, e);
185
186                 do {
187                         e2 = bmesh_disk_edge_next(e2, v);
188                         if (e2 != e && BM_ELEM_API_FLAG_TEST(e2, _FLAG_MF)) {
189                                 v = BM_edge_other_vert(e2, v);
190                                 break;
191                         }
192                 } while (e2 != e);
193
194                 if (e2 == e)
195                         goto err; /* the edges do not form a closed loop */
196
197                 e = e2;
198         } while (e != edges[0]);
199
200         if (BLI_array_count(edges2) != len) {
201                 goto err; /* we didn't use all edges in forming the boundary loop */
202         }
203
204         /* ok, edges are in correct order, now ensure they are going
205          * in the correct direction */
206         v1found = reverse = FALSE;
207         for (i = 0; i < len; i++) {
208                 if (BM_vert_in_edge(edges2[i], v1)) {
209                         /* see if v1 and v2 are in the same edge */
210                         if (BM_vert_in_edge(edges2[i], v2)) {
211                                 /* if v1 is shared by the *next* edge, then the winding
212                                  * is incorrect */
213                                 if (BM_vert_in_edge(edges2[(i + 1) % len], v1)) {
214                                         reverse = TRUE;
215                                         break;
216                                 }
217                         }
218
219                         v1found = TRUE;
220                 }
221
222                 if ((v1found == FALSE) && BM_vert_in_edge(edges2[i], v2)) {
223                         reverse = TRUE;
224                         break;
225                 }
226         }
227
228         if (reverse) {
229                 for (i = 0; i < len / 2; i++) {
230                         v = verts[i];
231                         verts[i] = verts[len - i - 1];
232                         verts[len - i - 1] = v;
233                 }
234         }
235
236         for (i = 0; i < len; i++) {
237                 edges2[i] = BM_edge_exists(verts[i], verts[(i + 1) % len]);
238                 if (!edges2[i]) {
239                         goto err;
240                 }
241         }
242
243         f = BM_face_create(bm, verts, edges2, len, nodouble);
244
245         /* clean up flags */
246         for (i = 0; i < len; i++) {
247                 BM_ELEM_API_FLAG_DISABLE(edges2[i], _FLAG_MF);
248         }
249
250         BLI_array_free(verts);
251         BLI_array_free(edges2);
252
253         return f;
254
255 err:
256         for (i = 0; i < len; i++) {
257                 BM_ELEM_API_FLAG_DISABLE(edges[i], _FLAG_MF);
258         }
259
260         BLI_array_free(verts);
261         BLI_array_free(edges2);
262
263         return NULL;
264 }
265
266
267 /* bmesh_make_face_from_face(BMesh *bm, BMFace *source, BMFace *target) */
268
269
270 /**
271  * Called by operators to remove elements that they have marked for
272  * removal.
273  */
274 void BMO_remove_tagged_faces(BMesh *bm, const short oflag)
275 {
276         BMFace *f;
277         BMIter iter;
278
279         BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
280                 if (BMO_elem_flag_test(bm, f, oflag)) {
281                         BM_face_kill(bm, f);
282                 }
283         }
284 }
285
286 void BMO_remove_tagged_edges(BMesh *bm, const short oflag)
287 {
288         BMEdge *e;
289         BMIter iter;
290
291         BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
292                 if (BMO_elem_flag_test(bm, e, oflag)) {
293                         BM_edge_kill(bm, e);
294                 }
295         }
296 }
297
298 void BMO_remove_tagged_verts(BMesh *bm, const short oflag)
299 {
300         BMVert *v;
301         BMIter iter;
302
303         BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
304                 if (BMO_elem_flag_test(bm, v, oflag)) {
305                         BM_vert_kill(bm, v);
306                 }
307         }
308 }
309
310 /*************************************************************/
311 /* you need to make remove tagged verts/edges/faces
312  * api functions that take a filter callback.....
313  * and this new filter type will be for opstack flags.
314  * This is because the BM_remove_taggedXXX functions bypass iterator API.
315  *  - Ops dont care about 'UI' considerations like selection state, hide state, ect.
316  *    If you want to work on unhidden selections for instance,
317  *    copy output from a 'select context' operator to another operator....
318  */
319
320 static void bmo_remove_tagged_context_verts(BMesh *bm, const short oflag)
321 {
322         BMVert *v;
323         BMEdge *e;
324         BMFace *f;
325
326         BMIter verts;
327         BMIter edges;
328         BMIter faces;
329
330         for (v = BM_iter_new(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BM_iter_step(&verts)) {
331                 if (BMO_elem_flag_test(bm, v, oflag)) {
332                         /* Visit edge */
333                         for (e = BM_iter_new(&edges, bm, BM_EDGES_OF_VERT, v); e; e = BM_iter_step(&edges))
334                                 BMO_elem_flag_enable(bm, e, oflag);
335                         /* Visit face */
336                         for (f = BM_iter_new(&faces, bm, BM_FACES_OF_VERT, v); f; f = BM_iter_step(&faces))
337                                 BMO_elem_flag_enable(bm, f, oflag);
338                 }
339         }
340
341         BMO_remove_tagged_faces(bm, oflag);
342         BMO_remove_tagged_edges(bm, oflag);
343         BMO_remove_tagged_verts(bm, oflag);
344 }
345
346 static void bmo_remove_tagged_context_edges(BMesh *bm, const short oflag)
347 {
348         BMEdge *e;
349         BMFace *f;
350
351         BMIter edges;
352         BMIter faces;
353
354         for (e = BM_iter_new(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BM_iter_step(&edges)) {
355                 if (BMO_elem_flag_test(bm, e, oflag)) {
356                         for (f = BM_iter_new(&faces, bm, BM_FACES_OF_EDGE, e); f; f = BM_iter_step(&faces)) {
357                                 BMO_elem_flag_enable(bm, f, oflag);
358                         }
359                 }
360         }
361         BMO_remove_tagged_faces(bm, oflag);
362         BMO_remove_tagged_edges(bm, oflag);
363 }
364
365 #define DEL_WIREVERT    (1 << 10)
366
367 /**
368  * \warning oflag applies to different types in some contexts,
369  * not just the type being removed.
370  *
371  * \warning take care, uses operator flag DEL_WIREVERT
372  */
373 void BMO_remove_tagged_context(BMesh *bm, const short oflag, const int type)
374 {
375         BMVert *v;
376         BMEdge *e;
377         BMFace *f;
378
379         BMIter verts;
380         BMIter edges;
381         BMIter faces;
382
383         switch (type) {
384                 case DEL_VERTS:
385                 {
386                         bmo_remove_tagged_context_verts(bm, oflag);
387
388                         break;
389                 }
390                 case DEL_EDGES:
391                 {
392                         /* flush down to vert */
393                         for (e = BM_iter_new(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BM_iter_step(&edges)) {
394                                 if (BMO_elem_flag_test(bm, e, oflag)) {
395                                         BMO_elem_flag_enable(bm, e->v1, oflag);
396                                         BMO_elem_flag_enable(bm, e->v2, oflag);
397                                 }
398                         }
399                         bmo_remove_tagged_context_edges(bm, oflag);
400                         /* remove loose vertice */
401                         for (v = BM_iter_new(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BM_iter_step(&verts)) {
402                                 if (BMO_elem_flag_test(bm, v, oflag) && (!(v->e)))
403                                         BMO_elem_flag_enable(bm, v, DEL_WIREVERT);
404                         }
405                         BMO_remove_tagged_verts(bm, DEL_WIREVERT);
406
407                         break;
408                 }
409                 case DEL_EDGESFACES:
410                 {
411                         bmo_remove_tagged_context_edges(bm, oflag);
412
413                         break;
414                 }
415                 case DEL_ONLYFACES:
416                 {
417                         BMO_remove_tagged_faces(bm, oflag);
418
419                         break;
420                 }
421                 case DEL_ONLYTAGGED:
422                 {
423                         BMO_remove_tagged_faces(bm, oflag);
424                         BMO_remove_tagged_edges(bm, oflag);
425                         BMO_remove_tagged_verts(bm, oflag);
426
427                         break;
428                 }
429                 case DEL_FACES:
430                 {
431                         /* go through and mark all edges and all verts of all faces for delet */
432                         for (f = BM_iter_new(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BM_iter_step(&faces)) {
433                                 if (BMO_elem_flag_test(bm, f, oflag)) {
434                                         for (e = BM_iter_new(&edges, bm, BM_EDGES_OF_FACE, f); e; e = BM_iter_step(&edges))
435                                                 BMO_elem_flag_enable(bm, e, oflag);
436                                         for (v = BM_iter_new(&verts, bm, BM_VERTS_OF_FACE, f); v; v = BM_iter_step(&verts))
437                                                 BMO_elem_flag_enable(bm, v, oflag);
438                                 }
439                         }
440                         /* now go through and mark all remaining faces all edges for keeping */
441                         for (f = BM_iter_new(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BM_iter_step(&faces)) {
442                                 if (!BMO_elem_flag_test(bm, f, oflag)) {
443                                         for (e = BM_iter_new(&edges, bm, BM_EDGES_OF_FACE, f); e; e = BM_iter_step(&edges)) {
444                                                 BMO_elem_flag_disable(bm, e, oflag);
445                                         }
446                                         for (v = BM_iter_new(&verts, bm, BM_VERTS_OF_FACE, f); v; v = BM_iter_step(&verts)) {
447                                                 BMO_elem_flag_disable(bm, v, oflag);
448                                         }
449                                 }
450                         }
451                         /* also mark all the vertices of remaining edges for keeping */
452                         for (e = BM_iter_new(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BM_iter_step(&edges)) {
453                                 if (!BMO_elem_flag_test(bm, e, oflag)) {
454                                         BMO_elem_flag_disable(bm, e->v1, oflag);
455                                         BMO_elem_flag_disable(bm, e->v2, oflag);
456                                 }
457                         }
458                         /* now delete marked face */
459                         BMO_remove_tagged_faces(bm, oflag);
460                         /* delete marked edge */
461                         BMO_remove_tagged_edges(bm, oflag);
462                         /* remove loose vertice */
463                         BMO_remove_tagged_verts(bm, oflag);
464
465                         break;
466                 }
467                 case DEL_ALL:
468                 {
469                         /* does this option even belong in here? */
470                         for (f = BM_iter_new(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BM_iter_step(&faces))
471                                 BMO_elem_flag_enable(bm, f, oflag);
472                         for (e = BM_iter_new(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BM_iter_step(&edges))
473                                 BMO_elem_flag_enable(bm, e, oflag);
474                         for (v = BM_iter_new(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BM_iter_step(&verts))
475                                 BMO_elem_flag_enable(bm, v, oflag);
476
477                         BMO_remove_tagged_faces(bm, oflag);
478                         BMO_remove_tagged_edges(bm, oflag);
479                         BMO_remove_tagged_verts(bm, oflag);
480
481                         break;
482                 }
483         }
484 }
485 /*************************************************************/
486
487
488 static void bm_vert_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
489                                const BMVert *source_vertex, BMVert *target_vertex)
490 {
491         if ((source_mesh == target_mesh) && (source_vertex == target_vertex)) {
492                 return;
493         }
494         copy_v3_v3(target_vertex->no, source_vertex->no);
495         CustomData_bmesh_free_block(&target_mesh->vdata, &target_vertex->head.data);
496         CustomData_bmesh_copy_data(&source_mesh->vdata, &target_mesh->vdata,
497                                    source_vertex->head.data, &target_vertex->head.data);
498 }
499
500 static void bm_edge_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
501                                const BMEdge *source_edge, BMEdge *target_edge)
502 {
503         if ((source_mesh == target_mesh) && (source_edge == target_edge)) {
504                 return;
505         }
506         CustomData_bmesh_free_block(&target_mesh->edata, &target_edge->head.data);
507         CustomData_bmesh_copy_data(&source_mesh->edata, &target_mesh->edata,
508                                    source_edge->head.data, &target_edge->head.data);
509 }
510
511 static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
512                                const BMLoop *source_loop, BMLoop *target_loop)
513 {
514         if ((source_mesh == target_mesh) && (source_loop == target_loop)) {
515                 return;
516         }
517         CustomData_bmesh_free_block(&target_mesh->ldata, &target_loop->head.data);
518         CustomData_bmesh_copy_data(&source_mesh->ldata, &target_mesh->ldata,
519                                    source_loop->head.data, &target_loop->head.data);
520 }
521
522 static void bm_face_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
523                                const BMFace *source_face, BMFace *target_face)
524 {
525         if ((source_mesh == target_mesh) && (source_face == target_face)) {
526                 return;
527         }
528         copy_v3_v3(target_face->no, source_face->no);
529         CustomData_bmesh_free_block(&target_mesh->pdata, &target_face->head.data);
530         CustomData_bmesh_copy_data(&source_mesh->pdata, &target_mesh->pdata,
531                                    source_face->head.data, &target_face->head.data);
532         target_face->mat_nr = source_face->mat_nr;
533 }
534
535 /* BMESH_TODO: Special handling for hide flags? */
536
537 /**
538  * Copies attributes, e.g. customdata, header flags, etc, from one element
539  * to another of the same type.
540  */
541 void BM_elem_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, const void *source, void *target)
542 {
543         const BMHeader *sheader = source;
544         BMHeader *theader = target;
545
546         BLI_assert(sheader->htype == theader->htype);
547
548         if (sheader->htype != theader->htype)
549                 return;
550
551         /* First we copy select */
552         if (BM_elem_flag_test((BMElem *)sheader, BM_ELEM_SELECT)) {
553                 BM_elem_select_set(target_mesh, (BMElem *)target, TRUE);
554         }
555         
556         /* Now we copy flags */
557         theader->hflag = sheader->hflag;
558         
559         /* Copy specific attributes */
560         switch (theader->htype) {
561                 case BM_VERT:
562                         bm_vert_attrs_copy(source_mesh, target_mesh, (const BMVert *)source, (BMVert *)target);
563                         break;
564                 case BM_EDGE:
565                         bm_edge_attrs_copy(source_mesh, target_mesh, (const BMEdge *)source, (BMEdge *)target);
566                         break;
567                 case BM_LOOP:
568                         bm_loop_attrs_copy(source_mesh, target_mesh, (const BMLoop *)source, (BMLoop *)target);
569                         break;
570                 case BM_FACE:
571                         bm_face_attrs_copy(source_mesh, target_mesh, (const BMFace *)source, (BMFace *)target);
572                         break;
573                 default:
574                         BLI_assert(0);
575         }
576 }
577
578 BMesh *BM_mesh_copy(BMesh *bm_old)
579 {
580         BMesh *bm_new;
581         BMVert *v, *v2, **vtable = NULL;
582         BMEdge *e, *e2, **edges = NULL, **etable = NULL;
583         BLI_array_declare(edges);
584         BMLoop *l, /* *l2, */ **loops = NULL;
585         BLI_array_declare(loops);
586         BMFace *f, *f2, **ftable = NULL;
587         BMEditSelection *ese;
588         BMIter iter, liter;
589         int i, j;
590         BMAllocTemplate allocsize = {bm_old->totvert,
591                                      bm_old->totedge,
592                                      bm_old->totloop,
593                                      bm_old->totface};
594
595         /* allocate a bmesh */
596         bm_new = BM_mesh_create(bm_old->ob, &allocsize);
597
598         CustomData_copy(&bm_old->vdata, &bm_new->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
599         CustomData_copy(&bm_old->edata, &bm_new->edata, CD_MASK_BMESH, CD_CALLOC, 0);
600         CustomData_copy(&bm_old->ldata, &bm_new->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
601         CustomData_copy(&bm_old->pdata, &bm_new->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
602
603         CustomData_bmesh_init_pool(&bm_new->vdata, allocsize.totvert, BM_VERT);
604         CustomData_bmesh_init_pool(&bm_new->edata, allocsize.totedge, BM_EDGE);
605         CustomData_bmesh_init_pool(&bm_new->ldata, allocsize.totloop, BM_LOOP);
606         CustomData_bmesh_init_pool(&bm_new->pdata, allocsize.totface, BM_FACE);
607
608         vtable = MEM_mallocN(sizeof(BMVert *) * bm_old->totvert, "BM_mesh_copy vtable");
609         etable = MEM_mallocN(sizeof(BMEdge *) * bm_old->totedge, "BM_mesh_copy etable");
610         ftable = MEM_mallocN(sizeof(BMFace *) * bm_old->totface, "BM_mesh_copy ftable");
611
612         v = BM_iter_new(&iter, bm_old, BM_VERTS_OF_MESH, NULL);
613         for (i = 0; v; v = BM_iter_step(&iter), i++) {
614                 v2 = BM_vert_create(bm_new, v->co, NULL); /* copy between meshes so cant use 'example' argument */
615                 BM_elem_attrs_copy(bm_old, bm_new, v, v2);
616                 vtable[i] = v2;
617                 BM_elem_index_set(v, i); /* set_inline */
618                 BM_elem_index_set(v2, i); /* set_inline */
619         }
620         bm_old->elem_index_dirty &= ~BM_VERT;
621         bm_new->elem_index_dirty &= ~BM_VERT;
622
623         /* safety check */
624         BLI_assert(i == bm_old->totvert);
625         
626         e = BM_iter_new(&iter, bm_old, BM_EDGES_OF_MESH, NULL);
627         for (i = 0; e; e = BM_iter_step(&iter), i++) {
628                 e2 = BM_edge_create(bm_new,
629                                     vtable[BM_elem_index_get(e->v1)],
630                                     vtable[BM_elem_index_get(e->v2)],
631                                     e, FALSE);
632
633                 BM_elem_attrs_copy(bm_old, bm_new, e, e2);
634                 etable[i] = e2;
635                 BM_elem_index_set(e, i); /* set_inline */
636                 BM_elem_index_set(e2, i); /* set_inline */
637         }
638         bm_old->elem_index_dirty &= ~BM_EDGE;
639         bm_new->elem_index_dirty &= ~BM_EDGE;
640
641         /* safety check */
642         BLI_assert(i == bm_old->totedge);
643         
644         f = BM_iter_new(&iter, bm_old, BM_FACES_OF_MESH, NULL);
645         for (i = 0; f; f = BM_iter_step(&iter), i++) {
646                 BM_elem_index_set(f, i); /* set_inline */
647
648                 BLI_array_empty(loops);
649                 BLI_array_empty(edges);
650                 BLI_array_growitems(loops, f->len);
651                 BLI_array_growitems(edges, f->len);
652
653                 l = BM_iter_new(&liter, bm_old, BM_LOOPS_OF_FACE, f);
654                 for (j = 0; j < f->len; j++, l = BM_iter_step(&liter)) {
655                         loops[j] = l;
656                         edges[j] = etable[BM_elem_index_get(l->e)];
657                 }
658
659                 v = vtable[BM_elem_index_get(loops[0]->v)];
660                 v2 = vtable[BM_elem_index_get(loops[1]->v)];
661
662                 if (!bmesh_verts_in_edge(v, v2, edges[0])) {
663                         v = vtable[BM_elem_index_get(loops[BLI_array_count(loops) - 1]->v)];
664                         v2 = vtable[BM_elem_index_get(loops[0]->v)];
665                 }
666
667                 f2 = BM_face_create_ngon(bm_new, v, v2, edges, f->len, FALSE);
668                 if (!f2)
669                         continue;
670                 /* use totface incase adding some faces fails */
671                 BM_elem_index_set(f2, (bm_new->totface - 1)); /* set_inline */
672
673                 ftable[i] = f2;
674
675                 BM_elem_attrs_copy(bm_old, bm_new, f, f2);
676                 copy_v3_v3(f2->no, f->no);
677
678                 l = BM_iter_new(&liter, bm_new, BM_LOOPS_OF_FACE, f2);
679                 for (j = 0; j < f->len; j++, l = BM_iter_step(&liter)) {
680                         BM_elem_attrs_copy(bm_old, bm_new, loops[j], l);
681                 }
682
683                 if (f == bm_old->act_face) bm_new->act_face = f2;
684         }
685         bm_old->elem_index_dirty &= ~BM_FACE;
686         bm_new->elem_index_dirty &= ~BM_FACE;
687
688         /* safety check */
689         BLI_assert(i == bm_old->totface);
690
691         /* copy over edit selection history */
692         for (ese = bm_old->selected.first; ese; ese = ese->next) {
693                 void *ele = NULL;
694
695                 if (ese->htype == BM_VERT)
696                         ele = vtable[BM_elem_index_get(ese->ele)];
697                 else if (ese->htype == BM_EDGE)
698                         ele = etable[BM_elem_index_get(ese->ele)];
699                 else if (ese->htype == BM_FACE) {
700                         ele = ftable[BM_elem_index_get(ese->ele)];
701                 }
702                 else {
703                         BLI_assert(0);
704                 }
705                 
706                 if (ele)
707                         BM_select_history_store(bm_new, ele);
708         }
709
710         MEM_freeN(etable);
711         MEM_freeN(vtable);
712         MEM_freeN(ftable);
713
714         BLI_array_free(loops);
715         BLI_array_free(edges);
716
717         return bm_new;
718 }
719
720 /* ME -> BM */
721 char BM_vert_flag_from_mflag(const char  meflag)
722 {
723         return ( ((meflag & SELECT)       ? BM_ELEM_SELECT : 0) |
724                  ((meflag & ME_HIDE)      ? BM_ELEM_HIDDEN : 0)
725                  );
726 }
727 char BM_edge_flag_from_mflag(const short meflag)
728 {
729         return ( ((meflag & SELECT)        ? BM_ELEM_SELECT : 0) |
730                  ((meflag & ME_SEAM)       ? BM_ELEM_SEAM   : 0) |
731                  ((meflag & ME_SHARP) == 0 ? BM_ELEM_SMOOTH : 0) | /* invert */
732                  ((meflag & ME_HIDE)       ? BM_ELEM_HIDDEN : 0)
733                  );
734 }
735 char BM_face_flag_from_mflag(const char  meflag)
736 {
737         return ( ((meflag & ME_FACE_SEL)  ? BM_ELEM_SELECT : 0) |
738                  ((meflag & ME_SMOOTH)    ? BM_ELEM_SMOOTH : 0) |
739                  ((meflag & ME_HIDE)      ? BM_ELEM_HIDDEN : 0)
740                  );
741 }
742
743 /* BM -> ME */
744 char  BM_vert_flag_to_mflag(BMVert *eve)
745 {
746         const char hflag = eve->head.hflag;
747
748         return ( ((hflag & BM_ELEM_SELECT)  ? SELECT  : 0) |
749                  ((hflag & BM_ELEM_HIDDEN)  ? ME_HIDE : 0)
750                  );
751 }
752 short BM_edge_flag_to_mflag(BMEdge *eed)
753 {
754         const char hflag = eed->head.hflag;
755
756         return ( ((hflag & BM_ELEM_SELECT)       ? SELECT    : 0) |
757                  ((hflag & BM_ELEM_SEAM)         ? ME_SEAM   : 0) |
758                  ((hflag & BM_ELEM_SMOOTH) == 0  ? ME_SHARP  : 0) |
759                  ((hflag & BM_ELEM_HIDDEN)       ? ME_HIDE   : 0) |
760                  ((BM_edge_is_wire(NULL, eed)) ? ME_LOOSEEDGE : 0) | /* not typical */
761                  (ME_EDGEDRAW | ME_EDGERENDER)
762                  );
763 }
764 char  BM_face_flag_to_mflag(BMFace *efa)
765 {
766         const char hflag = efa->head.hflag;
767
768         return ( ((hflag & BM_ELEM_SELECT) ? ME_FACE_SEL : 0) |
769                  ((hflag & BM_ELEM_SMOOTH) ? ME_SMOOTH   : 0) |
770                  ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE     : 0)
771                  );
772 }