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"
8 #include "BKE_utildefines.h"
10 #include "BKE_global.h"
11 #include "BKE_DerivedMesh.h"
12 #include "BKE_cdderivedmesh.h"
14 #include "BLI_editVert.h"
15 #include "mesh_intern.h"
18 #include "BLI_blenlib.h"
19 #include "BLI_edgehash.h"
26 * This file contains functions
27 * for converting an editmesh
33 * EDITMESH CORNERS TO LOOPS
35 * Converts editmesh face corner data
36 * (UVs, Vert colors, ect) to N-Gon
37 * face-edge ('loop') data.
41 static void editmesh_corners_to_loops(BMesh *bm, CustomData *facedata, void *face_block, BMFace *f,int numCol, int numTex){
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);
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;
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];
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;
84 * Converts an editvert to
89 static BMVert *editvert_to_BMVert(BMesh *bm, EditMesh *em, EditVert *eve)
93 v = BM_Make_Vert(bm, eve->co, NULL);
94 VECCOPY(v->no, eve->no);
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;
102 CustomData_bmesh_copy_data(&em->vdata, &bm->vdata, eve->data, &v->data);
110 * Converts an editedge to
115 static void editedge_to_BMEdge_internal(BMesh *bm, EditMesh *em, BMEdge *e, EditEdge *eed)
117 e->crease = eed->crease;
118 e->bweight = eed->bweight;
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;
126 CustomData_bmesh_copy_data(&em->edata, &bm->edata, eed->data, &e->data);
129 static BMEdge *editedge_to_BMEdge(BMesh *bm, EditMesh *em, EditEdge *eed)
131 BMVert *v1 = NULL, *v2 = NULL;
137 e = BM_Make_Edge(bm, v1, v2,NULL, 0);
139 editedge_to_BMEdge_internal(bm, em, e, eed);
146 * Converts an editface to a BMFace.
147 * Note that this also convert per-face
148 * corner data as well.
152 static BMFace *editface_to_BMFace(BMesh *bm, EditMesh *em, EditFace *efa, int numCol, int numTex)
154 BMVert *v1 = NULL, *v2 = NULL;
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);
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);
165 edar[2] = BM_Make_Edge(bm, efa->v3->tmp.p, efa->v1->tmp.p, NULL, 1);
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);
172 editedge_to_BMEdge_internal(bm, em, edar[3], efa->e4);
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;
187 f = BM_Make_Ngon(bm, v1, v2, edar, len, 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;
193 if (efa == em->act_face) f->head.flag |= BM_ACTIVE;
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);
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
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.
219 typedef struct fgonsort {
221 struct EditFace *efa;
226 static int sortfgon(const void *v1, const void *v2)
228 const struct fgonsort *x1=v1, *x2=v2;
230 if( x1->x > x2->x ) return 1;
231 else if( x1->x < x2->x) return -1;
235 static void fuse_fgon(BMesh *bm, BMFace *f)
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;
251 sf = BM_Join_Faces(bm,l->f, ((BMLoop*)l->radial.next->data)->f, l->e, 0,0);
252 sf->head.flag |= act;
256 } else { /*we have to get out of here...*/
260 l = ((BMLoop*)(l->head.next));
261 }while(l != sf->loopbase);
265 static BM_fgonconvert(BMesh *bm, EditMesh *em, int numCol, int numTex)
270 struct fgonsort *sortblock, *sb, *sb1;
274 for (efa=em->faces.first; efa; efa=efa->next) {
275 f = editface_to_BMFace(bm, em, efa, numCol, numTex);
278 for (f=bm->polys.first; f; f=f->head.next) {
286 /*zero out efa->tmp, we store fgon index here*/
287 for(efa = em->faces.first; efa; efa = efa->next){
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;
299 sb= sortblock= MEM_mallocN(sizeof(fgonsort)* amount,"fgon sort block");
301 for(efa = em->faces.first; efa; efa=efa->next){
308 qsort(sortblock, amount, sizeof(fgonsort), sortfgon);
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++){
316 sb1->f = editface_to_BMFace(bm, em, efa, numCol, numTex);
320 fuse_fgon(bm, sb->f);
323 MEM_freeN(sortblock);
329 * Flags editedges 'f1' member
330 * if the edge has no faces.
334 static void tag_wire_edges(EditMesh *em){
337 for(eed = em->edges.first; eed; eed = eed->next) eed->f1 = 1;
338 for(efa = em->faces.first; efa; efa = efa->next){
342 if(efa->e4) efa->e4->f1 = 0;
349 * Function to convert an editmesh to a bmesh
350 * Currently all custom data as well as
351 * f-gons should be converted correctly.
355 BMesh *editmesh_to_bmesh_intern(EditMesh *em, BMesh *bm) {
360 int allocsize[4] = {512,512,2048,512}, numTex, numCol;
362 /*make sure to update FGon flags*/
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);
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]);
378 numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
379 numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
381 /*copy over selection mode*/
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;
395 for(eve = em->verts.first; eve; eve = eve->next){
396 v = editvert_to_BMVert(bm, em, eve);
400 BM_fgonconvert(bm, em, numCol, numTex);
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);
408 for(eed = em->edges.first; eed; eed = eed->next){
409 if(eed->f1) editedge_to_BMEdge(bm, em, eed);
411 //BM_end_edit(bm, BM_CALC_NORM);
415 void edit2bmesh_exec(BMesh *bmesh, BMOperator *op)
417 editmesh_to_bmesh_intern(op->slots[BMOP_FROM_EDITMESH_EM].data.p, bmesh);
420 BMesh *editmesh_to_bmesh(EditMesh *em)
424 int allocsize[4] = {512,512,2048,512}, numTex, numCol;
427 bm = BM_Make_Mesh(allocsize);
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);