b046972987acae85f58b4aa0e1280ac9d3403d90
[blender.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  * about this.  
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2007 Blender Foundation.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): Geoffrey Bantle.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /** \file blender/bmesh/intern/bmesh_construct.c
30  *  \ingroup bmesh
31  *
32  * BM construction functions.
33  */
34
35 #include "MEM_guardedalloc.h"
36
37 #include "BKE_customdata.h" 
38 #include "BKE_utildefines.h"
39
40 #include "BLI_array.h"
41 #include "BLI_utildefines.h"
42
43 #include "DNA_meshdata_types.h"
44 #include "DNA_mesh_types.h"
45
46 #include "BLI_math.h"
47 #include "BLI_utildefines.h"
48
49 #include "bmesh.h"
50 #include "bmesh_private.h"
51
52 #include <math.h>
53 #include <stdio.h>
54 #include <string.h>
55
56 #define SELECT 1
57
58 /*prototypes*/
59 static void bm_copy_loop_attributes(BMesh *source_mesh, BMesh *target_mesh,
60                                     const BMLoop *source_loop, BMLoop *target_loop);
61 #if 0
62
63 /*
64  * BM_CONSTRUCT.C
65  *
66  * This file contains functions for making and destroying
67  * individual elements like verts, edges and faces.
68  *
69 */
70
71 /*
72  * BMESH MAKE VERT
73  *
74  * Creates a new vertex and returns a pointer
75  * to it. If a pointer to an example vertex is
76  * passed in, it's custom data and properties
77  * will be copied to the new vertex.
78  *
79 */
80
81 BMVert *BM_Make_Vert(BMesh *bm, float co[3], BMVert *example)
82 {
83         BMVert *v = NULL;
84         v = bmesh_mv(bm, co);
85         if(example)
86                 CustomData_bmesh_copy_data(&bm->vdata, &bm->vdata, example->head.data, &v->head.data);
87         return v;
88 }
89
90 /*
91  * BMESH MAKE EDGE
92  *
93  * Creates a new edge betweeen two vertices and returns a
94  * pointer to it. If 'nodouble' equals 1, then a check is
95  * is done to make sure that an edge between those two vertices
96  * does not already exist. If it does, that edge is returned instead
97  * of creating a new one.
98  *
99  * If a new edge is created, and a pointer to an example edge is
100  * provided, it's custom data and properties will be copied to the
101  * new edge.
102  *
103 */
104
105 BMEdge *BM_Make_Edge(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge *example, int nodouble)
106 {
107         BMEdge *e = NULL;
108         
109         if(nodouble) /*test if edge already exists.*/
110                 e = BM_Edge_Exist(v1, v2);
111
112         if(!e){
113                 e = bmesh_me(bm, v1, v2);
114
115                 if(example)
116                         CustomData_bmesh_copy_data(&bm->edata, &bm->edata, example->head.data, &e->head.data);
117         }
118         
119         return e;
120         
121 }
122 #endif
123
124 /*
125  * BMESH MAKE QUADTRIANGLE
126  *
127  * Creates a new quad or triangle from
128  * a list of 3 or 4 vertices. If nodouble
129  * equals 1, then a check is done to see
130  * if a face with these vertices already
131  * exists and returns it instead. If a pointer
132  * to an example face is provided, it's custom
133  * data and properties will be copied to the new
134  * face.
135  *
136  * Note that the winding of the face is determined
137  * by the order of the vertices in the vertex array
138  *
139 */
140
141 BMFace *BM_Make_QuadTri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, 
142                         BMVert *v4, const BMFace *example, int nodouble)
143 {
144         BMEdge *edar[4];
145         BMVert *vtar[4];
146
147         edar[0] = BM_Edge_Exist(v1, v2);
148         edar[1] = BM_Edge_Exist(v2, v3);
149         edar[2] = BM_Edge_Exist(v3, v4? v4 : v1);
150         if (v4) edar[3] = BM_Edge_Exist(v4, v1);
151         else edar[3] = NULL;
152
153         if (!edar[0]) edar[0] = BM_Make_Edge(bm, v1, v2, NULL, 0);
154         if (!edar[1]) edar[1] = BM_Make_Edge(bm, v2, v3, NULL, 0);
155         if (!edar[2]) edar[2] = BM_Make_Edge(bm, v3, v4?v4:v1, NULL, 0);
156         if (!edar[0] && v4) edar[0] = BM_Make_Edge(bm, v4, v1, NULL, 0);
157
158         vtar[0] = v1;
159         vtar[1] = v2;
160         vtar[2] = v3;
161         vtar[3] = v4;
162
163         return BM_Make_Quadtriangle(bm, vtar, edar, v4?4:3, example, nodouble);
164 }
165
166 /*remove the edge array bits from this. Its not really needed?*/
167 BMFace *BM_Make_Quadtriangle(BMesh *bm, BMVert **verts, BMEdge **edges, int len, const BMFace *example, int nodouble)
168 {
169         BMEdge *edar[4];
170         BMFace *f = NULL;
171         int overlap = 0;
172
173         edar[0] = edar[1] = edar[2] = edar[3] = NULL;
174         
175         if(edges){
176                 edar[0] = edges[0];
177                 edar[1] = edges[1];
178                 edar[2] = edges[2];
179                 if(len == 4) edar[3] = edges[3];
180         }else{
181                 edar[0] = BM_Edge_Exist(verts[0],verts[1]);
182                 edar[1] = BM_Edge_Exist(verts[1],verts[2]);
183                 if(len == 4){
184                         edar[2] = BM_Edge_Exist(verts[2],verts[3]);
185                         edar[3] = BM_Edge_Exist(verts[3],verts[0]);
186
187                 }else{
188                         edar[2] = BM_Edge_Exist(verts[2],verts[0]);
189                 }
190         }
191         
192         if(nodouble){
193                 /*check if face exists or overlaps*/
194                 if(len == 4){
195                         overlap = BM_Exist_Face_Overlaps(bm, verts, len, &f);
196                 }else{
197                         overlap = BM_Exist_Face_Overlaps(bm, verts, len, &f);
198                 }
199         }
200
201         /*make new face*/
202         if((!f) && (!overlap)){
203                 if(!edar[0]) edar[0] = BM_Make_Edge(bm, verts[0], verts[1], NULL, 0);
204                 if(!edar[1]) edar[1] = BM_Make_Edge(bm, verts[1], verts[2], NULL, 0);
205                 if(len == 4){
206                         if(!edar[2]) edar[2] = BM_Make_Edge(bm, verts[2], verts[3], NULL, 0);
207                         if(!edar[3]) edar[3] = BM_Make_Edge(bm, verts[3], verts[0], NULL, 0);
208                 } else {
209                         if(!edar[2]) edar[2] = BM_Make_Edge(bm, verts[2], verts[0], NULL, 0);
210                 }
211         
212                 f = BM_Make_Face(bm, verts, edar, len, 0);
213         
214                 if(example && f)
215                         BM_Copy_Attributes(bm, bm, example, f);
216
217         }
218
219         return f;
220 }
221
222
223 /*copies face data from shared adjacent faces*/
224 void BM_Face_CopyShared(BMesh *bm, BMFace *f)
225 {
226         BMIter iter;
227         BMLoop *l, *l2;
228
229         if (!f) return;
230
231         l=BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, f);
232         for (; l; l=BMIter_Step(&iter)) {
233                 l2 = l->radial_next;
234                 
235                 if (l2 && l2 != l) {
236                         if (l2->v == l->v) {
237                                 bm_copy_loop_attributes(bm, bm, l2, l);
238                         } else {
239                                 l2 = l2->next;
240                                 bm_copy_loop_attributes(bm, bm, l2, l);
241                         }
242                 }
243         }
244 }
245
246 /*
247  * BMESH MAKE NGON
248  *
249  * Attempts to make a new Ngon from a list of edges.
250  * If nodouble equals one, a check for overlaps or existing
251  *
252  * The edges are not required to be ordered, simply to to form
253  * a single closed loop as a whole
254  *
255  * Note that while this function will work fine when the edges
256  * are already sorted, if the edges are always going to be sorted,
257  * BM_Make_Face should be considered over this function as it
258  * avoids some unnecessary work.
259 */
260 #define VERT_BUF_SIZE 100
261 BMFace *BM_Make_Ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, int nodouble)
262 {
263         BMEdge **edges2 = NULL;
264         BLI_array_staticdeclare(edges2, VERT_BUF_SIZE);
265         BMVert **verts = NULL, *v;
266         BLI_array_staticdeclare(verts, VERT_BUF_SIZE);
267         BMFace *f = NULL;
268         BMEdge *e;
269         BMVert *ev1, *ev2;
270         int i, /* j,*/ v1found, reverse;
271
272         /*this code is hideous, yeek.  I'll have to think about ways of
273           cleaning it up.  basically, it now combines the old BM_Make_Ngon
274           *and* the old bmesh_mf functions, so its kindof smashed together
275                 - joeedh*/
276
277         if (!len || !v1 || !v2 || !edges || !bm)
278                 return NULL;
279
280         /*put edges in correct order*/
281         for (i=0; i<len; i++) {
282                 bmesh_api_setflag(edges[i], _FLAG_MF);
283         }
284
285         ev1 = edges[0]->v1;
286         ev2 = edges[0]->v2;
287
288         if (v1 == ev2) {
289                 /* Swapping here improves performance and consistency of face
290                    structure in the special case that the edges are already in
291                    the correct order and winding */
292                 SWAP(BMVert *, ev1, ev2);
293         }
294
295         BLI_array_append(verts, ev1);
296         v = ev2;
297         e = edges[0];
298         do {
299                 BMEdge *e2 = e;
300
301                 BLI_array_append(verts, v);
302                 BLI_array_append(edges2, e);
303
304                 do {
305                         e2 = bmesh_disk_nextedge(e2, v);
306                         if (e2 != e && bmesh_api_getflag(e2, _FLAG_MF)) {
307                                 v = BM_OtherEdgeVert(e2, v);
308                                 break;
309                         }
310                 } while (e2 != e);
311
312                 if (e2 == e)
313                         goto err; /*the edges do not form a closed loop*/
314
315                 e = e2;
316         } while (e != edges[0]);
317
318         if (BLI_array_count(edges2) != len)
319                 goto err; /*we didn't use all edges in forming the boundary loop*/
320
321         /*ok, edges are in correct order, now ensure they are going
322           in the correct direction*/
323         v1found = reverse = 0;
324         for (i=0; i<len; i++) {
325                 if (BM_Vert_In_Edge(edges2[i], v1)) {
326                         /*see if v1 and v2 are in the same edge*/
327                         if (BM_Vert_In_Edge(edges2[i], v2)) {
328                                 /*if v1 is shared by the *next* edge, then the winding
329                                   is incorrect*/
330                                 if (BM_Vert_In_Edge(edges2[(i+1)%len], v1)) {
331                                         reverse = 1;
332                                         break;
333                                 }
334                         }
335
336                         v1found = 1;
337                 }
338
339                 if (!v1found && BM_Vert_In_Edge(edges2[i], v2)) {
340                         reverse = 1;
341                         break;
342                 }
343         }
344
345         if (reverse) {
346                 for (i=0; i<len/2; i++) {
347                         v = verts[i];
348                         verts[i] = verts[len-i-1];
349                         verts[len-i-1] = v;
350                 }
351         }
352
353         for (i=0; i<len; i++) {
354                 edges2[i] = BM_Edge_Exist(verts[i], verts[(i+1)%len]);
355                 if (!edges2[i])
356                         goto err;
357         }
358
359         f = BM_Make_Face(bm, verts, edges2, len, nodouble);
360
361         /*clean up flags*/
362         for (i=0; i<len; i++) {
363                 bmesh_api_clearflag(edges2[i], _FLAG_MF);
364         }
365
366         BLI_array_free(verts);
367         BLI_array_free(edges2);
368
369         return f;
370
371 err:
372         for (i=0; i<len; i++) {
373                 bmesh_api_clearflag(edges[i], _FLAG_MF);
374         }
375
376         BLI_array_free(verts);
377         BLI_array_free(edges2);
378
379         return NULL;
380 }
381
382
383 /*bmesh_make_face_from_face(BMesh *bm, BMFace *source, BMFace *target) */
384
385
386 /*
387  * REMOVE TAGGED XXX
388  *
389  * Called by operators to remove elements that they have marked for
390  * removal.
391  *
392 */
393
394 void BM_remove_tagged_faces(BMesh *bm, int flag)
395 {
396         BMFace *f;
397         BMIter iter;
398
399         BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
400                 if(BMO_TestFlag(bm, f, flag)) BM_Kill_Face(bm, f);
401         }
402 }
403
404 void BM_remove_tagged_edges(BMesh *bm, int flag)
405 {
406         BMEdge *e;
407         BMIter iter;
408
409         BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
410                 if(BMO_TestFlag(bm, e, flag)) BM_Kill_Edge(bm, e);
411         }
412 }
413
414 void BM_remove_tagged_verts(BMesh *bm, int flag)
415 {
416         BMVert *v;
417         BMIter iter;
418
419         BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
420                 if(BMO_TestFlag(bm, v, flag)) BM_Kill_Vert(bm, v);
421         }
422 }
423
424 static void bm_copy_vert_attributes(BMesh *source_mesh, BMesh *target_mesh, const BMVert *source_vertex, BMVert *target_vertex)
425 {
426         if ((source_mesh == target_mesh) && (source_vertex == target_vertex)) {
427                 return;
428         }
429         copy_v3_v3(target_vertex->no, source_vertex->no);
430         CustomData_bmesh_free_block(&target_mesh->vdata, &target_vertex->head.data);
431         CustomData_bmesh_copy_data(&source_mesh->vdata, &target_mesh->vdata, source_vertex->head.data, &target_vertex->head.data);      
432 }
433
434 static void bm_copy_edge_attributes(BMesh *source_mesh, BMesh *target_mesh, const BMEdge *source_edge, BMEdge *target_edge)
435 {
436         if ((source_mesh == target_mesh) && (source_edge == target_edge)) {
437                 return;
438         }
439         CustomData_bmesh_free_block(&target_mesh->edata, &target_edge->head.data);
440         CustomData_bmesh_copy_data(&source_mesh->edata, &target_mesh->edata, source_edge->head.data, &target_edge->head.data);
441 }
442
443 static void bm_copy_loop_attributes(BMesh *source_mesh, BMesh *target_mesh, const BMLoop *source_loop, BMLoop *target_loop)
444 {
445         if ((source_mesh == target_mesh) && (source_loop == target_loop)) {
446                 return;
447         }
448         CustomData_bmesh_free_block(&target_mesh->ldata, &target_loop->head.data);
449         CustomData_bmesh_copy_data(&source_mesh->ldata, &target_mesh->ldata, source_loop->head.data, &target_loop->head.data);
450 }
451
452 static void bm_copy_face_attributes(BMesh *source_mesh, BMesh *target_mesh, const BMFace *source_face, BMFace *target_face)
453 {
454         if ((source_mesh == target_mesh) && (source_face == target_face)) {
455                 return;
456         }
457         copy_v3_v3(target_face->no, source_face->no);
458         CustomData_bmesh_free_block(&target_mesh->pdata, &target_face->head.data);
459         CustomData_bmesh_copy_data(&source_mesh->pdata, &target_mesh->pdata, source_face->head.data, &target_face->head.data);  
460         target_face->mat_nr = source_face->mat_nr;
461 }
462
463 /*BMESH_TODO: Special handling for hide flags?*/
464
465 void BM_Copy_Attributes(BMesh *source_mesh, BMesh *target_mesh, const void *source, void *target)
466 {
467         const BMHeader *sheader = source;
468         BMHeader *theader = target;
469         
470         if(sheader->htype != theader->htype)
471                 return;
472
473         /*First we copy select*/
474         if(BM_Selected(source_mesh, source)) BM_Select(target_mesh, target, 1);
475         
476         /*Now we copy flags*/
477         theader->hflag = sheader->hflag;
478         
479         /*Copy specific attributes*/
480         if(theader->htype == BM_VERT)
481                 bm_copy_vert_attributes(source_mesh, target_mesh, (const BMVert*)source, (BMVert*)target);
482         else if(theader->htype == BM_EDGE)
483                 bm_copy_edge_attributes(source_mesh, target_mesh, (const BMEdge*)source, (BMEdge*)target);
484         else if(theader->htype == BM_LOOP)
485                 bm_copy_loop_attributes(source_mesh, target_mesh, (const BMLoop*)source, (BMLoop*)target);
486         else if(theader->htype == BM_FACE)
487                 bm_copy_face_attributes(source_mesh, target_mesh, (const BMFace*)source, (BMFace*)target);
488 }
489
490 BMesh *BM_Copy_Mesh(BMesh *bmold)
491 {
492         BMesh *bm;
493         BMVert *v, *v2, **vtable = NULL;
494         BMEdge *e, *e2, **edges = NULL, **etable = NULL;
495         BLI_array_declare(edges);
496         BMLoop *l, /* *l2,*/ **loops = NULL;
497         BLI_array_declare(loops);
498         BMFace *f, *f2, **ftable = NULL;
499         BMEditSelection *ese;
500         BMIter iter, liter;
501         int allocsize[4] = {512,512,2048,512}, numTex, numCol;
502         int i, j;
503
504         /*allocate a bmesh*/
505         bm = BM_Make_Mesh(bmold->ob, allocsize);
506
507         CustomData_copy(&bmold->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
508         CustomData_copy(&bmold->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
509         CustomData_copy(&bmold->ldata, &bm->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
510         CustomData_copy(&bmold->pdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
511
512         CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
513         CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
514         CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]);
515         CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]);
516
517         /*needed later*/
518         numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
519         numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
520
521         vtable= MEM_mallocN(sizeof(BMVert *) * bmold->totvert, "BM_Copy_Mesh vtable");
522         etable= MEM_mallocN(sizeof(BMEdge *) * bmold->totedge, "BM_Copy_Mesh etable");
523         ftable= MEM_mallocN(sizeof(BMFace *) * bmold->totface, "BM_Copy_Mesh ftable");
524
525         v = BMIter_New(&iter, bmold, BM_VERTS_OF_MESH, NULL);
526         for (i=0; v; v=BMIter_Step(&iter), i++) {
527                 v2 = BM_Make_Vert(bm, v->co, NULL); /* copy between meshes so cant use 'example' argument */
528                 BM_Copy_Attributes(bmold, bm, v, v2);
529                 vtable[i] = v2;
530                 BM_SetIndex(v, i); /* set_inline */
531                 BM_SetIndex(v2, i); /* set_inline */
532         }
533         bmold->elem_index_dirty &= ~BM_VERT;
534         bm->elem_index_dirty &= ~BM_VERT;
535
536         /* safety check */
537         BLI_assert(i == bmold->totvert);
538         
539         e = BMIter_New(&iter, bmold, BM_EDGES_OF_MESH, NULL);
540         for (i=0; e; e=BMIter_Step(&iter), i++) {
541                 e2 = BM_Make_Edge(bm, vtable[BM_GetIndex(e->v1)],
542                                   vtable[BM_GetIndex(e->v2)], e, 0);
543
544                 BM_Copy_Attributes(bmold, bm, e, e2);
545                 etable[i] = e2;
546                 BM_SetIndex(e, i); /* set_inline */
547                 BM_SetIndex(e2, i); /* set_inline */
548         }
549         bmold->elem_index_dirty &= ~BM_EDGE;
550         bm->elem_index_dirty &= ~BM_EDGE;
551
552         /* safety check */
553         BLI_assert(i == bmold->totedge);
554         
555         f = BMIter_New(&iter, bmold, BM_FACES_OF_MESH, NULL);
556         for (i=0; f; f=BMIter_Step(&iter), i++) {
557                 BM_SetIndex(f, i); /* set_inline */
558
559                 BLI_array_empty(loops);
560                 BLI_array_empty(edges);
561                 l = BMIter_New(&liter, bmold, BM_LOOPS_OF_FACE, f);
562                 for (j=0; j<f->len; j++, l = BMIter_Step(&liter)) {
563                         BLI_array_growone(loops);
564                         BLI_array_growone(edges);
565                         loops[j] = l;
566                         edges[j] = etable[BM_GetIndex(l->e)];
567                 }
568
569                 v = vtable[BM_GetIndex(loops[0]->v)];
570                 v2 = vtable[BM_GetIndex(loops[1]->v)];
571
572                 if (!bmesh_verts_in_edge(v, v2, edges[0])) {
573                         v = vtable[BM_GetIndex(loops[BLI_array_count(loops)-1]->v)];
574                         v2 = vtable[BM_GetIndex(loops[0]->v)];
575                 }
576
577                 f2 = BM_Make_Ngon(bm, v, v2, edges, f->len, 0);
578                 if (!f2)
579                         continue;
580                 /* use totface incase adding some faces fails */
581                 BM_SetIndex(f2, (bm->totface-1)); /* set_inline */
582
583                 ftable[i] = f2;
584
585                 BM_Copy_Attributes(bmold, bm, f, f2);
586                 copy_v3_v3(f2->no, f->no);
587
588                 l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f2);
589                 for (j=0; j<f->len; j++, l = BMIter_Step(&liter)) {
590                         BM_Copy_Attributes(bmold, bm, loops[j], l);
591                 }
592
593                 if (f == bmold->act_face) bm->act_face = f2;
594         }
595         bmold->elem_index_dirty &= ~BM_FACE;
596         bm->elem_index_dirty &= ~BM_FACE;
597
598         /* safety check */
599         BLI_assert(i == bmold->totface);
600
601         /*copy over edit selection history*/
602         for (ese=bmold->selected.first; ese; ese=ese->next) {
603                 void *ele = NULL;
604
605                 if (ese->htype == BM_VERT)
606                         ele= vtable[BM_GetIndex(ese->data)];
607                 else if (ese->htype == BM_EDGE)
608                         ele= etable[BM_GetIndex(ese->data)];
609                 else if (ese->htype == BM_FACE) {
610                         ele= ftable[BM_GetIndex(ese->data)];
611                 }
612                 else {
613                         BLI_assert(0);
614                 }
615                 
616                 if (ele)
617                         BM_store_selection(bm, ele);
618         }
619
620         MEM_freeN(etable);
621         MEM_freeN(vtable);
622         MEM_freeN(ftable);
623
624         BLI_array_free(loops);
625         BLI_array_free(edges);
626
627         return bm;
628 }
629
630 /*
631   BM FLAGS TO ME FLAGS
632
633   Returns the flags stored in element,
634   which much be either a BMVert, BMEdge,
635   or BMFace, converted to mesh flags.
636 */
637
638 short BMFlags_To_MEFlags(void *element)
639 {
640         const char src_htype= ((BMHeader *)element)->htype;
641         const char src_hflag= ((BMHeader *)element)->hflag;
642
643         short dst_flag= 0;
644
645         if (src_hflag & BM_HIDDEN)            dst_flag |= ME_HIDE;
646
647         if (src_htype == BM_FACE) {
648                 if (src_hflag & BM_SELECT)        dst_flag |= ME_FACE_SEL;
649                 if (src_hflag & BM_SMOOTH)        dst_flag |= ME_SMOOTH;
650         } else if (src_htype == BM_EDGE) {
651                 if (src_hflag & BM_SELECT)        dst_flag |= SELECT;
652                 if (src_hflag & BM_SEAM)          dst_flag |= ME_SEAM;
653                 if (src_hflag & BM_SHARP)         dst_flag |= ME_SHARP;
654                 if (BM_Wire_Edge(NULL, element))  dst_flag |= ME_LOOSEEDGE;
655                 dst_flag |= ME_EDGEDRAW | ME_EDGERENDER;
656         } else if (src_htype == BM_VERT) {
657                 if (src_hflag & BM_SELECT)        dst_flag |= SELECT;
658         }
659
660         return dst_flag;
661 }
662
663 /*
664   BM FLAGS TO ME FLAGS
665
666   Returns the flags stored in element,
667   which much be either a MVert, MEdge,
668   or MPoly, converted to mesh flags.
669   type must be either BM_VERT, BM_EDGE,
670   or BM_FACE.
671 */
672 char MEFlags_To_BMFlags(const short hflag, const char htype)
673 {
674         char f= 0;
675
676         if (htype == BM_FACE) {
677                 if (hflag & ME_FACE_SEL)  f |= BM_SELECT;
678                 if (hflag & ME_SMOOTH)    f |= BM_SMOOTH;
679                 if (hflag & ME_HIDE)      f |= BM_HIDDEN;
680         } else if (htype == BM_EDGE) {
681                 if (hflag & SELECT)       f |= BM_SELECT;
682                 if (hflag & ME_SEAM)      f |= BM_SEAM;
683                 if (hflag & ME_SHARP)     f |= BM_SHARP;
684                 if (hflag & ME_HIDE)      f |= BM_HIDDEN;
685         } else if (htype == BM_VERT) {
686                 if (hflag & SELECT)       f |= BM_SELECT;
687                 if (hflag & ME_HIDE)      f |= BM_HIDDEN;
688         }
689
690         return f;
691 }