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