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