diff options
Diffstat (limited to 'source/blender/bmesh/intern/editmesh_to_bmesh.c')
-rw-r--r-- | source/blender/bmesh/intern/editmesh_to_bmesh.c | 476 |
1 files changed, 476 insertions, 0 deletions
diff --git a/source/blender/bmesh/intern/editmesh_to_bmesh.c b/source/blender/bmesh/intern/editmesh_to_bmesh.c new file mode 100644 index 00000000000..89e03277dd4 --- /dev/null +++ b/source/blender/bmesh/intern/editmesh_to_bmesh.c @@ -0,0 +1,476 @@ +#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 <string.h> +#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, 1); + 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, 1); + 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; a<amount; a++, sb++) { + if(sb->x && sb->done == 0){ + /*first pass: add in faces for this fgon*/ + for(b=a, sb1 = sb; b<amount && sb1->x == 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 |