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