6f7fac9fa45337e3283d02c2ca7c53589fb607cc
[blender.git] / source / blender / bmesh / intern / editmesh_to_bmesh.c
1
2 #include "MEM_guardedalloc.h"
3 #include "BKE_customdata.h" 
4 #include "DNA_listBase.h"
5 #include "DNA_meshdata_types.h"
6 #include "DNA_object_types.h"
7 #include "DNA_scene_types.h"
8 #include <string.h>
9 #include "BKE_utildefines.h"
10 #include "BKE_mesh.h"
11 #include "BKE_global.h"
12 #include "BKE_DerivedMesh.h"
13 #include "BKE_cdderivedmesh.h"
14
15 #include "BLI_editVert.h"
16 #include "mesh_intern.h"
17 #include "ED_mesh.h"
18
19 #include "BLI_blenlib.h"
20 #include "BLI_edgehash.h"
21
22 #include "bmesh.h"
23
24 /*
25  * EDITMESH TO BMESH.C
26  *
27  * This file contains functions
28  * for converting an editmesh
29  * into a Bmesh
30  *
31 */
32
33 /*
34  * EDITMESH CORNERS TO LOOPS
35  * 
36  * Converts editmesh face corner data
37  * (UVs, Vert colors, ect) to N-Gon 
38  * face-edge ('loop') data.
39  *
40 */
41
42 static void editmesh_corners_to_loops(BMesh *bm, CustomData *facedata, void *face_block, BMFace *f,int numCol, int numTex){
43         int i, j;
44         BMLoop *l;
45         MTFace *texface;
46         MTexPoly *texpoly;
47         MCol *mcol;
48         MLoopCol *mloopcol;
49         MLoopUV *mloopuv;
50         BMIter iter;
51
52         for(i=0; i < numTex; i++){
53                 texface = CustomData_em_get_n(facedata, face_block, CD_MTFACE, i);
54                 texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i);
55                 
56                 texpoly->tpage = texface->tpage;
57                 texpoly->flag = texface->flag;
58                 texpoly->transp = texface->transp;
59                 texpoly->mode = texface->mode;
60                 texpoly->tile = texface->tile;
61                 texpoly->unwrap = texface->unwrap;
62                 
63                 for (j=0, l=BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, f); l; j++, l=BMIter_Step(&iter)) {
64                         mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
65                         mloopuv->uv[0] = texface->uv[j][0];
66                         mloopuv->uv[1] = texface->uv[j][1];
67                 }
68
69         }
70         for(i=0; i < numCol; i++){
71                 mcol = CustomData_em_get_n(facedata, face_block, CD_MCOL, i);
72                 for (j=0, l=BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, f); l; j++, l=BMIter_Step(&iter)) {
73                         mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i);
74                         mloopcol->r = mcol[j].r;
75                         mloopcol->g = mcol[j].g;
76                         mloopcol->b = mcol[j].b;
77                         mloopcol->a = mcol[j].a;
78                 }
79         }
80 }
81
82 /*
83  * EDITVERT TO BMVert
84  *
85  * Converts an editvert to
86  * a BMVert.
87  *
88 */
89
90 static BMVert *editvert_to_BMVert(BMesh *bm, BMOperator *op, EditMesh *em, EditVert *eve)
91 {
92                 BMVert *v = NULL;
93
94                 v = BM_Make_Vert(bm, eve->co, NULL);
95                 VECCOPY(v->no, eve->no);
96
97                 /*transfer flags*/
98                 v->head.flag = eve->h ? BM_HIDDEN : 0;
99                 if(eve->f & SELECT) BM_Select_Vert(bm, v, 1);
100                 v->bweight = eve->bweight;
101
102                 BMO_Insert_MapPointer(bm, op, "map", eve, v);
103
104                 /*Copy Custom Data*/
105                 CustomData_bmesh_copy_data(&em->vdata, &bm->vdata, eve->data, &v->head.data);
106                 
107                 return v;
108 }       
109
110 /*
111  * EDITEDGE TO BMEdge
112  *
113  * Converts an editedge to 
114  * a BMEdge
115  *
116 */
117
118 static void editedge_to_BMEdge_internal(BMesh *bm, BMOperator *op, EditMesh *em, BMEdge *e, EditEdge *eed)
119 {
120         e->crease = eed->crease;
121         e->bweight = eed->bweight;
122         
123         BM_Select(bm, e, eed->f & SELECT);
124         e->head.flag |= eed->seam ? BM_SEAM : 0;
125         e->head.flag |= eed->h & 1 ? BM_HIDDEN : 0;
126         e->head.flag |= eed->h & EM_FGON ? BM_FGON : 0;
127         e->head.flag |= eed->sharp ? BM_SHARP : 0;
128
129         CustomData_bmesh_copy_data(&em->edata, &bm->edata, eed->data, &e->head.data);
130
131         BMO_Insert_MapPointer(bm, op, "map", eed, e);
132 }
133
134 static BMEdge *editedge_to_BMEdge(BMesh *bm, BMOperator *op, EditMesh *em, EditEdge *eed)
135 {
136                 BMVert *v1 = NULL, *v2 = NULL;
137                 BMEdge *e = NULL;
138                 
139                 v1 = eed->v1->tmp.p;
140                 v2 = eed->v2->tmp.p;
141         
142                 e = BM_Make_Edge(bm, v1, v2,NULL, 0); 
143
144                 editedge_to_BMEdge_internal(bm, op, em, e, eed);
145
146                 return e;
147 }
148 /*
149  * EDITFACE TO BMFace
150  *
151  * Converts an editface to a BMFace.
152  * Note that this also convert per-face
153  * corner data as well.
154  *
155 */
156
157 static BMFace *editface_to_BMFace(BMesh *bm, BMOperator *op, EditMesh *em, EditFace *efa, int numCol, int numTex)
158 {
159                 BMVert *v1 = NULL, *v2 = NULL;
160                 BMFace *f = NULL;
161                 BMEdge *edar[4];
162                 int len;
163
164                 edar[0] = BM_Make_Edge(bm, efa->v1->tmp.p, efa->v2->tmp.p, NULL, 1); 
165                 edar[1] = BM_Make_Edge(bm, efa->v2->tmp.p, efa->v3->tmp.p, NULL, 1); 
166                 if(efa->v4){
167                         edar[2] = BM_Make_Edge(bm, efa->v3->tmp.p, efa->v4->tmp.p, NULL, 1); 
168                         edar[3] = BM_Make_Edge(bm, efa->v4->tmp.p, efa->v1->tmp.p, NULL, 1); 
169                 }else{
170                         edar[2] = BM_Make_Edge(bm, efa->v3->tmp.p, efa->v1->tmp.p, NULL, 1); 
171                 }
172
173                 editedge_to_BMEdge_internal(bm, op, em, edar[0], efa->e1);
174                 editedge_to_BMEdge_internal(bm, op, em, edar[1], efa->e2);
175                 editedge_to_BMEdge_internal(bm, op, em, edar[2], efa->e3);
176                 if(efa->v4)
177                         editedge_to_BMEdge_internal(bm, op, em, edar[3], efa->e4);
178
179
180                 if(efa->e1->fgoni) edar[0]->head.flag |= BM_FGON;
181                 if(efa->e2->fgoni) edar[1]->head.flag |= BM_FGON;
182                 if(efa->e3->fgoni) edar[2]->head.flag |= BM_FGON;
183                 if(efa->v4 && efa->e4->fgoni) edar[3]->head.flag |= BM_FGON;
184
185                 if(efa->v4) len = 4;
186                 else len = 3;
187
188                 /*find v1 and v2*/
189                 v1 = efa->v1->tmp.p;
190                 v2 = efa->v2->tmp.p;
191
192                 f = BM_Make_Ngon(bm, v1, v2, edar, len, 0);
193                 
194                 VECCOPY(f->no, efa->n);
195
196                 BMO_Insert_MapPointer(bm, op, "map", efa, f);
197
198                 f->head.flag = 0;
199                 f->mat_nr = efa->mat_nr;
200                 if(efa->f & SELECT) BM_Select_Face(bm, f, 1);
201                 if (efa->flag & ME_SMOOTH) f->head.flag |= BM_SMOOTH;
202                 if(efa->h) f->head.flag |= BM_HIDDEN;
203
204                 if (efa == em->act_face) f->head.flag |= BM_ACTIVE;
205                 
206                 CustomData_bmesh_copy_data(&em->fdata, &bm->pdata, efa->data, &f->head.data);
207                 editmesh_corners_to_loops(bm, &em->fdata, efa->data, f,numCol,numTex);
208
209                 return f;
210 }
211
212 /*
213  * BMESH FGONCONVERT
214  *
215  * This function and its associated structures
216  * /helpers (fgonsort, sortfgon, fuse_fgon) are
217  * used to convert f-gons to bmesh n-gons. This
218  * is accomplished by sorting a list of fgon faces
219  * such that faces that are part of the same fgon
220  * are next to each other. These faces are then
221  * converted as is into bmesh faces and
222  * fused togather.
223  *
224  * Note that currently, there is no support for 
225  * holes in faces in the bmesh structure, so 
226  * f-gons with holes will only partially convert.
227  *
228 */
229
230 typedef struct fgonsort {
231         unsigned long x;
232         struct EditFace *efa;
233         struct BMFace *f;
234         int done;
235 }fgonsort;
236
237 static int sortfgon(const void *v1, const void *v2)
238 {
239         const struct fgonsort *x1=v1, *x2=v2;
240         
241         if( x1->x > x2->x ) return 1;
242         else if( x1->x < x2->x) return -1;
243         return 0;
244 }
245
246 static void fuse_fgon(BMesh *bm, BMFace *f)
247 {
248         BMFace *sf;
249         BMLoop *l;
250         int done, act=0;
251
252         sf = f;
253         done = 0;
254         while(!done){
255                 done = 1;
256                 l = sf->loopbase;
257                 do{
258                         if(l->e->head.flag & BM_FGON) { 
259                                 if (l->f->head.flag & BM_ACTIVE) act = BM_ACTIVE;
260                                 if (((BMLoop*)l->radial.next->data)->f->head.flag & BM_ACTIVE) act = BM_ACTIVE;
261
262                                 sf = BM_Join_Faces(bm,l->f, ((BMLoop*)l->radial.next->data)->f, l->e);
263                                 if (!sf) {
264                                         //tesselation error
265                                         break;
266                                 }
267
268                                 sf->head.flag |= act;
269                                 if(sf){
270                                         done = 0;
271                                         break;
272                                 } else { /*we have to get out of here...*/
273                                         return;
274                                 }
275                         }
276                         l = ((BMLoop*)(l->head.next));
277                 }while(l != sf->loopbase);
278         }
279 }
280
281 static BM_fgonconvert(BMesh *bm, BMOperator *op, EditMesh *em, int numCol, int numTex)
282 {
283         EditFace *efa;
284         BMFace *f;
285         BMIter iter;
286         struct fgonsort *sortblock, *sb, *sb1;
287         int a, b, amount=0;
288         
289         /*
290         for (efa=em->faces.first; efa; efa=efa->next) {
291                 f = editface_to_BMFace(bm, em, efa, numCol, numTex);
292         }
293
294         for (f=bm->polys.first; f; f=f->head.next) {
295                 fuse_fgon(bm, f);
296         }
297
298         return;*/
299
300         EM_fgon_flags(em);
301
302         /*zero out efa->tmp, we store fgon index here*/
303         for(efa = em->faces.first; efa; efa = efa->next){ 
304                 efa->tmp.l = 0;
305                 amount++;
306         }
307         /*go through and give each editface an fgon index*/
308         for(efa = em->faces.first; efa; efa = efa->next){
309                 if(efa->e1->fgoni) efa->tmp.l = efa->e1->fgoni;
310                 else if(efa->e2->fgoni) efa->tmp.l = efa->e2->fgoni;
311                 else if(efa->e3->fgoni) efa->tmp.l = efa->e3->fgoni;
312                 else if(efa->e4 && efa->e4->fgoni) efa->tmp.l = efa->e4->fgoni;
313         }
314
315         sb= sortblock= MEM_mallocN(sizeof(fgonsort)* amount,"fgon sort block");
316
317         for(efa = em->faces.first; efa; efa=efa->next){
318                 sb->x = efa->tmp.l;
319                 sb->efa = efa;
320                 sb->done = 0;
321                 sb++;
322         }
323
324         qsort(sortblock, amount, sizeof(fgonsort), sortfgon);
325
326         sb = sortblock;
327         for(a=0; a<amount; a++, sb++) {
328                 if(sb->x && sb->done == 0){
329                         /*first pass: add in faces for this fgon*/
330                         for(b=a, sb1 = sb; b<amount && sb1->x == sb->x; b++, sb1++){
331                                 efa = sb1->efa;
332                                 sb1->f = editface_to_BMFace(bm, op, em, efa, numCol, numTex);
333                                 sb1->done = 1;
334                         }
335                         /*fuse fgon*/
336                         fuse_fgon(bm, sb->f);
337                 }
338         }
339         MEM_freeN(sortblock);
340 }
341
342 /*
343  * TAG WIRE EDGES
344  *
345  * Flags editedges 'f1' member
346  * if the edge has no faces.
347  *
348 */
349
350 static void tag_wire_edges(EditMesh *em){
351         EditFace *efa;
352         EditEdge *eed;
353         for(eed = em->edges.first; eed; eed = eed->next) eed->f1 = 1;
354         for(efa = em->faces.first; efa; efa = efa->next){
355                 efa->e1->f1 = 0;
356                 efa->e2->f1 = 0;
357                 efa->e3->f1 = 0;
358                 if(efa->e4) efa->e4->f1 = 0;
359         }
360 }
361
362 /*
363  * EDITMESH TO BMESH
364  *
365  * Function to convert an editmesh to a bmesh
366  * Currently all custom data as well as 
367  * f-gons should be converted correctly.
368  *
369 */
370
371 BMesh *editmesh_to_bmesh_intern(EditMesh *em, BMesh *bm, BMOperator *op) {
372         BMVert *v;
373         EditVert *eve;
374         EditEdge *eed;
375         EditFace *efa;
376         BMEdge *e;
377         BMIter iter;
378         int allocsize[4] = {512,512,2048,512}, numTex, numCol;
379
380         /*make sure to update FGon flags*/
381         EM_fgon_flags(em);
382
383         /*copy custom data layout*/
384         CustomData_copy(&em->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
385         CustomData_copy(&em->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
386         CustomData_copy(&em->fdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
387
388         /*copy face corner data*/
389         CustomData_to_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata);
390         
391         CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
392         CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
393         CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]);
394         CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]);
395
396         /*needed later*/
397         numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
398         numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
399
400         /*copy over selection mode*/
401         bm->selectmode = 0;
402         if(em->selectmode & SCE_SELECT_VERTEX) bm->selectmode |= SCE_SELECT_VERTEX;
403         if(em->selectmode & SCE_SELECT_EDGE) bm->selectmode |= SCE_SELECT_EDGE;
404         if(em->selectmode & SCE_SELECT_FACE) bm->selectmode |= SCE_SELECT_FACE;
405
406
407         /*begin editloop*/
408         //BM_Begin_Edit(bm);
409
410         /*tag wire edges*/
411         tag_wire_edges(em);
412
413         /*add verts*/
414         for(eve = em->verts.first; eve; eve = eve->next){
415                 v = editvert_to_BMVert(bm, op, em, eve);
416                 eve->tmp.p = v;
417         }
418         /*convert f-gons*/
419         BM_fgonconvert(bm, op, em, numCol, numTex);
420         
421         /*clean up any dangling fgon flags*/
422         for (e=BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); e; e=BMIter_Step(&iter)){
423                 e->head.flag &= ~BM_FGON;
424         }
425
426         /*do quads + triangles*/
427         for(efa = em->faces.first; efa; efa = efa->next){
428                 if(!efa->tmp.l) editface_to_BMFace(bm, op, em, efa, numCol, numTex);
429         }
430
431         /*add wire edges*/      
432         for(eed = em->edges.first; eed; eed = eed->next){
433                 if(eed->f1) editedge_to_BMEdge(bm, op, em, eed);
434         }
435         //BM_end_edit(bm, BM_CALC_NORM);
436         return bm;
437 }
438
439 void edit2bmesh_exec(BMesh *bmesh, BMOperator *op)
440 {
441         editmesh_to_bmesh_intern(BMO_Get_Pnt(op, "em"), bmesh, op);
442 }
443
444 BMesh *editmesh_to_bmesh(EditMesh *em)
445 {
446         BMOperator conv;
447         BMesh *bm;
448         int allocsize[4] = {512,512,2048,512};
449
450         /*allocate a bmesh*/
451         bm = BM_Make_Mesh(allocsize);
452
453         BMO_Init_Op(&conv, "editmesh_to_bmesh");
454         BMO_Set_Pnt(&conv, "em", em);
455         BMO_Exec_Op(bm, &conv);
456         BMO_Finish_Op(bm, &conv);
457
458         return bm;
459 }
460
461 BMesh *init_editmesh_to_bmesh(EditMesh *em, BMOperator *op)
462 {
463         BMesh *bm;
464         int allocsize[4] = {512,512,2048,512}, numTex, numCol;
465
466         /*allocate a bmesh*/
467         bm = BM_Make_Mesh(allocsize);
468
469         BMO_Init_Op(op, "editmesh_to_bmesh");
470         BMO_Set_Pnt(op, "em", em);
471
472         return bm;
473 }