/* * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Contributor(s): Joseph Eagar, Geoffrey Bantle, Campbell Barton * * ***** END GPL LICENSE BLOCK ***** */ /** \file blender/bmesh/intern/editmesh_to_bmesh.c * \ingroup bmesh * * Unused */ #if 0 #include "MEM_guardedalloc.h" #include "BKE_customdata.h" #include "DNA_listBase.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include #include "BKE_utildefines.h" #include "BKE_mesh.h" #include "BKE_global.h" #include "BKE_DerivedMesh.h" #include "BKE_cdderivedmesh.h" #include "BLI_editVert.h" #include "mesh_intern.h" #include "ED_mesh.h" #include "BLI_blenlib.h" #include "BLI_edgehash.h" #include "BLI_array.h" #include "bmesh.h" /* * EDITMESH TO BMESH.C * * This file contains functions * for converting an editmesh * into a Bmesh * */ /* * EDITMESH CORNERS TO LOOPS * * Converts editmesh face corner data * (UVs, Vert colors, ect) to N-Gon * face-edge ('loop') data. * */ static void editmesh_corners_to_loops(BMesh *bm, CustomData *facedata, void *face_block, BMFace *f,int numCol, int numTex) { int i, j; BMLoop *l; MTFace *texface; MTexPoly *texpoly; MCol *mcol; MLoopCol *mloopcol; MLoopUV *mloopuv; BMIter iter; for(i=0; i < numTex; i++) { texface = CustomData_em_get_n(facedata, face_block, CD_MTFACE, i); texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i); texpoly->tpage = texface->tpage; texpoly->flag = texface->flag; texpoly->transp = texface->transp; texpoly->mode = texface->mode; texpoly->tile = texface->tile; texpoly->unwrap = texface->unwrap; for (j=0, l=BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, f); l; j++, l=BMIter_Step(&iter)) { mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i); mloopuv->uv[0] = texface->uv[j][0]; mloopuv->uv[1] = texface->uv[j][1]; } } for(i=0; i < numCol; i++) { mcol = CustomData_em_get_n(facedata, face_block, CD_MCOL, i); for (j=0, l=BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, f); l; j++, l=BMIter_Step(&iter)) { mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i); mloopcol->r = mcol[j].r; mloopcol->g = mcol[j].g; mloopcol->b = mcol[j].b; mloopcol->a = mcol[j].a; } } } /* * EDITVERT TO BMVert * * Converts an editvert to * a BMVert. * */ static BMVert *editvert_to_BMVert(BMesh *bm, BMOperator *op, EditMesh *em, EditVert *eve) { BMVert *v = NULL; v = BM_Make_Vert(bm, eve->co, NULL); VECCOPY(v->no, eve->no); /*transfer flags*/ v->head.flag = eve->h ? BM_HIDDEN : 0; if(eve->f & SELECT) BM_Select_Vert(bm, v, TRUE); v->bweight = eve->bweight; BMO_Insert_MapPointer(bm, op, "map", eve, v); /*Copy Custom Data*/ CustomData_bmesh_copy_data(&em->vdata, &bm->vdata, eve->data, &v->head.data); return v; } /* * EDITEDGE TO BMEdge * * Converts an editedge to * a BMEdge * */ static void editedge_to_BMEdge_internal(BMesh *bm, BMOperator *op, EditMesh *em, BMEdge *e, EditEdge *eed) { e->crease = eed->crease; e->bweight = eed->bweight; BM_Select(bm, e, eed->f & SELECT); e->head.flag |= eed->seam ? BM_SEAM : 0; e->head.flag |= eed->h & 1 ? BM_HIDDEN : 0; e->head.flag |= eed->h & EM_FGON ? BM_FGON : 0; e->head.flag |= eed->sharp ? BM_SHARP : 0; CustomData_bmesh_copy_data(&em->edata, &bm->edata, eed->data, &e->head.data); BMO_Insert_MapPointer(bm, op, "map", eed, e); } static BMEdge *editedge_to_BMEdge(BMesh *bm, BMOperator *op, EditMesh *em, EditEdge *eed) { BMVert *v1 = NULL, *v2 = NULL; BMEdge *e = NULL; v1 = eed->v1->tmp.p; v2 = eed->v2->tmp.p; e = BM_Make_Edge(bm, v1, v2,NULL, 0); editedge_to_BMEdge_internal(bm, op, em, e, eed); return e; } /* * EDITFACE TO BMFace * * Converts an editface to a BMFace. * Note that this also convert per-face * corner data as well. * */ static BMFace *editface_to_BMFace(BMesh *bm, BMOperator *op, EditMesh *em, EditFace *efa, int numCol, int numTex) { BMVert *v1 = NULL, *v2 = NULL; BMFace *f = NULL; BMEdge *edar[4]; int len; edar[0] = BM_Make_Edge(bm, efa->v1->tmp.p, efa->v2->tmp.p, NULL, 1); edar[1] = BM_Make_Edge(bm, efa->v2->tmp.p, efa->v3->tmp.p, NULL, 1); if(efa->v4) { edar[2] = BM_Make_Edge(bm, efa->v3->tmp.p, efa->v4->tmp.p, NULL, 1); edar[3] = BM_Make_Edge(bm, efa->v4->tmp.p, efa->v1->tmp.p, NULL, 1); } else { edar[2] = BM_Make_Edge(bm, efa->v3->tmp.p, efa->v1->tmp.p, NULL, 1); } editedge_to_BMEdge_internal(bm, op, em, edar[0], efa->e1); editedge_to_BMEdge_internal(bm, op, em, edar[1], efa->e2); editedge_to_BMEdge_internal(bm, op, em, edar[2], efa->e3); if(efa->v4) editedge_to_BMEdge_internal(bm, op, em, edar[3], efa->e4); if(efa->e1->fgoni) edar[0]->head.flag |= BM_FGON; if(efa->e2->fgoni) edar[1]->head.flag |= BM_FGON; if(efa->e3->fgoni) edar[2]->head.flag |= BM_FGON; if(efa->v4 && efa->e4->fgoni) edar[3]->head.flag |= BM_FGON; if(efa->v4) len = 4; else len = 3; /*find v1 and v2*/ v1 = efa->v1->tmp.p; v2 = efa->v2->tmp.p; f = BM_Make_Ngon(bm, v1, v2, edar, len, 0); VECCOPY(f->no, efa->n); BMO_Insert_MapPointer(bm, op, "map", efa, f); f->head.flag = 0; f->mat_nr = efa->mat_nr; if(efa->f & SELECT) BM_Select_Face(bm, f, TRUE); if (efa->flag & ME_SMOOTH) f->head.flag |= BM_SMOOTH; if(efa->h) f->head.flag |= BM_HIDDEN; if (efa == em->act_face) f->head.flag |= BM_ACTIVE; CustomData_bmesh_copy_data(&em->fdata, &bm->pdata, efa->data, &f->head.data); editmesh_corners_to_loops(bm, &em->fdata, efa->data, f,numCol,numTex); return f; } /* * BMESH FGONCONVERT * * This function and its associated structures * /helpers (fgonsort, sortfgon, fuse_fgon) are * used to convert f-gons to bmesh n-gons. This * is accomplished by sorting a list of fgon faces * such that faces that are part of the same fgon * are next to each other. These faces are then * converted as is into bmesh faces and * fused togather. * * Note that currently, there is no support for * holes in faces in the bmesh structure, so * f-gons with holes will only partially convert. * */ typedef struct fgonsort { unsigned long x; struct EditFace *efa; struct BMFace *f; int done; }fgonsort; static int sortfgon(const void *v1, const void *v2) { const struct fgonsort *x1=v1, *x2=v2; if( x1->x > x2->x ) return 1; else if( x1->x < x2->x) return -1; return 0; } static void fuse_fgon(BMesh *bm, BMFace *f) { BMFace *sf; BMLoop *l; int done, act=0; sf = f; done = 0; while(!done) { done = 1; l = sf->loopbase; do{ if(l->e->head.flag & BM_FGON) { if (l->f->head.flag & BM_ACTIVE) act = BM_ACTIVE; if (l->radial.next->data->f->head.flag & BM_ACTIVE) act = BM_ACTIVE; sf = BM_Join_TwoFaces(bm,l->f, l->radial.next->data->f, l->e); if (!sf) { //tesselation error break; } sf->head.flag |= act; if(sf) { done = 0; break; } else { /*we have to get out of here...*/ return; } } l = l->next; } while(l != sf->loopbase); } } static BM_fgonconvert(BMesh *bm, BMOperator *op, EditMesh *em, int numCol, int numTex) { EditFace *efa; BMFace *f; BMIter iter; struct fgonsort *sortblock, *sb, *sb1; int a, b, amount=0; /* for (efa=em->faces.first; efa; efa=efa->next) { f = editface_to_BMFace(bm, em, efa, numCol, numTex); } for (f=bm->polys.first; f; f=f->next) { fuse_fgon(bm, f); } return;*/ EM_fgon_flags(em); /*zero out efa->tmp, we store fgon index here*/ for(efa = em->faces.first; efa; efa = efa->next) { efa->tmp.l = 0; amount++; } /*go through and give each editface an fgon index*/ for(efa = em->faces.first; efa; efa = efa->next) { if(efa->e1->fgoni) efa->tmp.l = efa->e1->fgoni; else if(efa->e2->fgoni) efa->tmp.l = efa->e2->fgoni; else if(efa->e3->fgoni) efa->tmp.l = efa->e3->fgoni; else if(efa->e4 && efa->e4->fgoni) efa->tmp.l = efa->e4->fgoni; } sb= sortblock= MEM_mallocN(sizeof(fgonsort)* amount,"fgon sort block"); for(efa = em->faces.first; efa; efa=efa->next) { sb->x = efa->tmp.l; sb->efa = efa; sb->done = 0; sb++; } qsort(sortblock, amount, sizeof(fgonsort), sortfgon); sb = sortblock; for(a=0; ax && sb->done == 0) { /*first pass: add in faces for this fgon*/ for(b=a, sb1 = sb; bx == sb->x; b++, sb1++) { efa = sb1->efa; sb1->f = editface_to_BMFace(bm, op, em, efa, numCol, numTex); sb1->done = 1; } /*fuse fgon*/ fuse_fgon(bm, sb->f); } } MEM_freeN(sortblock); } /* * TAG WIRE EDGES * * Flags editedges 'f1' member * if the edge has no faces. * */ static void tag_wire_edges(EditMesh *em) { EditFace *efa; EditEdge *eed; for(eed = em->edges.first; eed; eed = eed->next) eed->f1 = 1; for(efa = em->faces.first; efa; efa = efa->next) { efa->e1->f1 = 0; efa->e2->f1 = 0; efa->e3->f1 = 0; if(efa->e4) efa->e4->f1 = 0; } } /* * EDITMESH TO BMESH * * Function to convert an editmesh to a bmesh * Currently all custom data as well as * f-gons should be converted correctly. * */ BMesh *editmesh_to_bmesh_intern(EditMesh *em, BMesh *bm, BMOperator *op) { BMVert *v; EditVert *eve; EditEdge *eed; EditFace *efa; BMEdge *e; BMIter iter; int allocsize[4] = {512,512,2048,512}, numTex, numCol; /*make sure to update FGon flags*/ EM_fgon_flags(em); /*copy custom data layout*/ CustomData_copy(&em->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0); CustomData_copy(&em->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0); CustomData_copy(&em->fdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0); /*copy face corner data*/ CustomData_to_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata, 0, 0); CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]); CustomData_bmesh_init_pool(&bm->edata, allocsize[1]); CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]); CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]); /*needed later*/ numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY); numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL); /*copy over selection mode*/ bm->selectmode = 0; if(em->selectmode & SCE_SELECT_VERTEX) bm->selectmode |= SCE_SELECT_VERTEX; if(em->selectmode & SCE_SELECT_EDGE) bm->selectmode |= SCE_SELECT_EDGE; if(em->selectmode & SCE_SELECT_FACE) bm->selectmode |= SCE_SELECT_FACE; /*begin editloop*/ //BM_Begin_Edit(bm); /*tag wire edges*/ tag_wire_edges(em); /*add verts*/ for(eve = em->verts.first; eve; eve = eve->next) { v = editvert_to_BMVert(bm, op, em, eve); eve->tmp.p = v; } /*convert f-gons*/ BM_fgonconvert(bm, op, em, numCol, numTex); /*clean up any dangling fgon flags*/ for (e=BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); e; e=BMIter_Step(&iter)) { e->head.flag &= ~BM_FGON; } /*do quads + triangles*/ for(efa = em->faces.first; efa; efa = efa->next) { if(!efa->tmp.l) editface_to_BMFace(bm, op, em, efa, numCol, numTex); } /*add wire edges*/ for(eed = em->edges.first; eed; eed = eed->next) { if(eed->f1) editedge_to_BMEdge(bm, op, em, eed); } //BM_end_edit(bm, BM_CALC_NORM); return bm; } void edit2bmesh_exec(BMesh *bmesh, BMOperator *op) { editmesh_to_bmesh_intern(BMO_Get_Pnt(op, "em"), bmesh, op); } BMesh *editmesh_to_bmesh(EditMesh *em) { BMOperator conv; BMesh *bm; int allocsize[4] = {512,512,2048,512}; /*allocate a bmesh*/ bm = BM_Make_Mesh(allocsize); BMO_Init_Op(&conv, "editmesh_to_bmesh"); BMO_Set_Pnt(&conv, "em", em); BMO_Exec_Op(bm, &conv); BMO_Finish_Op(bm, &conv); return bm; } BMesh *init_editmesh_to_bmesh(EditMesh *em, BMOperator *op) { BMesh *bm; int allocsize[4] = {512,512,2048,512}, numTex, numCol; /*allocate a bmesh*/ bm = BM_Make_Mesh(allocsize); BMO_Init_Op(op, "editmesh_to_bmesh"); BMO_Set_Pnt(op, "em", em); return bm; } #endif