diff options
Diffstat (limited to 'source/blender/blenkernel/intern/cdderivedmesh.c')
-rw-r--r-- | source/blender/blenkernel/intern/cdderivedmesh.c | 902 |
1 files changed, 814 insertions, 88 deletions
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 0f9033ca461..ddc8d536d25 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1,4 +1,4 @@ -/* + /* * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or @@ -36,11 +36,23 @@ #include "GL/glew.h" +#include "BKE_cdderivedmesh.h" +#include "BKE_global.h" +#include "BKE_mesh.h" +#include "BKE_paint.h" +#include "BKE_utildefines.h" +#include "BKE_tessmesh.h" + +#include "BLI_editVert.h" +#include "BLI_scanfill.h" +#include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_edgehash.h" #include "BLI_editVert.h" #include "BLI_math.h" #include "BLI_pbvh.h" +#include "BLI_array.h" +#include "BLI_smallhash.h" #include "BLI_utildefines.h" #include "BKE_cdderivedmesh.h" @@ -72,6 +84,8 @@ typedef struct { MVert *mvert; MEdge *medge; MFace *mface; + MLoop *mloop; + MPoly *mpoly; /* Cached */ struct PBVH *pbvh; @@ -93,11 +107,16 @@ static int cdDM_getNumEdges(DerivedMesh *dm) return dm->numEdgeData; } -static int cdDM_getNumFaces(DerivedMesh *dm) +static int cdDM_getNumTessFaces(DerivedMesh *dm) { return dm->numFaceData; } +static int cdDM_getNumFaces(DerivedMesh *dm) +{ + return dm->numPolyData; +} + static void cdDM_getVert(DerivedMesh *dm, int index, MVert *vert_r) { CDDerivedMesh *cddm = (CDDerivedMesh *)dm; @@ -134,6 +153,18 @@ static void cdDM_copyFaceArray(DerivedMesh *dm, MFace *face_r) memcpy(face_r, cddm->mface, sizeof(*face_r) * dm->numFaceData); } +static void cdDM_copyLoopArray(DerivedMesh *dm, MLoop *loop_r) +{ + CDDerivedMesh *cddm = (CDDerivedMesh *)dm; + memcpy(loop_r, cddm->mloop, sizeof(*loop_r) * dm->numLoopData); +} + +static void cdDM_copyPolyArray(DerivedMesh *dm, MPoly *poly_r) +{ + CDDerivedMesh *cddm = (CDDerivedMesh *)dm; + memcpy(poly_r, cddm->mpoly, sizeof(*poly_r) * dm->numPolyData); +} + static void cdDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; @@ -203,7 +234,7 @@ static int can_pbvh_draw(Object *ob, DerivedMesh *dm) if(deformed) return 0; - return (cddm->mvert == me->mvert) || ob->sculpt->kb; + return cddm->mvert == me->mvert || ob->sculpt->kb; } static struct PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm) @@ -292,7 +323,7 @@ static void cdDM_drawUVEdges(DerivedMesh *dm) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; MFace *mf = cddm->mface; - MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE); + MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE); int i; if(mf) { @@ -463,7 +494,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, CDDerivedMesh *cddm = (CDDerivedMesh*) dm; MVert *mvert = cddm->mvert; MFace *mface = cddm->mface; - float *nors= dm->getFaceDataArray(dm, CD_NORMAL); + float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL); int a, glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1; #define PASSVERT(index) { \ @@ -651,15 +682,15 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; MVert *mv = cddm->mvert; - MFace *mf = DM_get_face_data_layer(dm, CD_MFACE); - MCol *realcol = dm->getFaceDataArray(dm, CD_TEXTURE_MCOL); - float *nors= dm->getFaceDataArray(dm, CD_NORMAL); - MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE); - int i, j, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX); + MFace *mf = DM_get_tessface_data_layer(dm, CD_MFACE); + MCol *realcol = dm->getTessFaceDataArray(dm, CD_TEXTURE_MCOL); + float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL); + MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE); + int i, j, orig, *index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX); int startFace = 0, lastFlag = 0xdeadbeef; - MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL); + MCol *mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL); if(!mcol) - mcol = dm->getFaceDataArray(dm, CD_MCOL); + mcol = dm->getTessFaceDataArray(dm, CD_MCOL); cdDM_update_normals_from_pbvh(dm); @@ -751,8 +782,8 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, } if( col != 0 ) {*/ - unsigned char *colors = MEM_mallocN(dm->getNumFaces(dm)*4*3*sizeof(unsigned char), "cdDM_drawFacesTex_common"); - for( i=0; i < dm->getNumFaces(dm); i++ ) { + unsigned char *colors = MEM_mallocN(dm->getNumTessFaces(dm)*4*3*sizeof(unsigned char), "cdDM_drawFacesTex_common"); + for( i=0; i < dm->getNumTessFaces(dm); i++ ) { for( j=0; j < 4; j++ ) { /* bgr -> rgb is intentional (and stupid), but how its stored internally */ colors[i*12+j*3] = col[i*4+j].b; @@ -846,14 +877,14 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us MVert *mv = cddm->mvert; MFace *mf = cddm->mface; MCol *mc; - float *nors= dm->getFaceDataArray(dm, CD_NORMAL); - int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX); + float *nors= DM_get_tessface_data_layer(dm, CD_NORMAL); + int i, orig, *index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX); - mc = DM_get_face_data_layer(dm, CD_ID_MCOL); + mc = DM_get_tessface_data_layer(dm, CD_ID_MCOL); if(!mc) - mc = DM_get_face_data_layer(dm, CD_WEIGHT_MCOL); + mc = DM_get_tessface_data_layer(dm, CD_WEIGHT_MCOL); if(!mc) - mc = DM_get_face_data_layer(dm, CD_MCOL); + mc = DM_get_tessface_data_layer(dm, CD_MCOL); cdDM_update_normals_from_pbvh(dm); @@ -862,15 +893,17 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us if( GPU_buffer_legacy(dm) || G.f & G_BACKBUFSEL) { DEBUG_VBO( "Using legacy code. cdDM_drawMappedFaces\n" ); for(i = 0; i < dm->numFaceData; i++, mf++) { - int drawSmooth = (mf->flag & ME_SMOOTH); - int draw= 1; + int drawSmooth = (mf->flag & ME_SMOOTH) != 0; + int draw = (mf->flag & ME_HIDE) == 0; orig= (index==NULL) ? i : *index++; - - if(orig == ORIGINDEX_NONE) - draw= setMaterial(mf->mat_nr + 1, NULL); - else if (setDrawOptions != NULL) - draw= setDrawOptions(userData, orig, &drawSmooth); + + if (orig == ORIGINDEX_NONE) { + draw = draw && setMaterial(mf->mat_nr + 1, NULL); + } + else if (setDrawOptions != NULL) { + draw = draw && setDrawOptions(userData, orig, &drawSmooth); + } if(draw) { unsigned char *cp = NULL; @@ -925,7 +958,9 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us } glEnd(); - } + } /*else { + printf("eek in cddm draw mapped faces!\n"); + }*/ if (nors) nors += 3; } @@ -956,7 +991,7 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us int actualFace = next_actualFace; MFace *mface= mf + actualFace; int drawSmooth= (mface->flag & ME_SMOOTH); - int draw = 1; + int draw = (mf->flag & ME_HIDE) == 0; int flush = 0; if(i != tottri-1) @@ -964,10 +999,12 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us orig= (index==NULL) ? actualFace : index[actualFace]; - if(orig == ORIGINDEX_NONE) - draw= setMaterial(mface->mat_nr + 1, NULL); - else if (setDrawOptions != NULL) - draw= setDrawOptions(userData, orig, &drawSmooth); + if (orig == ORIGINDEX_NONE) { + draw = draw && setMaterial(mface->mat_nr + 1, NULL); + } + else if (setDrawOptions != NULL) { + draw = draw && setDrawOptions(userData, orig, &drawSmooth); + } /* Goal is to draw as long of a contiguous triangle array as possible, so draw when we hit either an @@ -1065,10 +1102,10 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo DMVertexAttribs attribs; MVert *mvert = cddm->mvert; MFace *mface = cddm->mface; - /* MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */ - float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL); + /* MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */ + float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL); int a, b, dodraw, matnr, new_matnr; - int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX); + int orig, *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); cdDM_update_normals_from_pbvh(dm); @@ -1362,9 +1399,9 @@ static void cdDM_drawMappedFacesMat(DerivedMesh *dm, DMVertexAttribs attribs; MVert *mvert = cddm->mvert; MFace *mf = cddm->mface; - float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL); + float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL); int a, matnr, new_matnr; - int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX); + int orig, *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); cdDM_update_normals_from_pbvh(dm); @@ -1506,10 +1543,13 @@ static void cdDM_foreachMappedFaceCenter( { CDDerivedMesh *cddm = (CDDerivedMesh*)dm; MVert *mv = cddm->mvert; - MFace *mf = cddm->mface; - int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX); + MPoly *mf = cddm->mpoly; + MLoop *ml = cddm->mloop; + int i, j, orig, *index; - for(i = 0; i < dm->numFaceData; i++, mf++) { + index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX); + mf = cddm->mpoly; + for(i = 0; i < dm->numPolyData; i++, mf++) { float cent[3]; float no[3]; @@ -1519,22 +1559,41 @@ static void cdDM_foreachMappedFaceCenter( } else orig = i; + + ml = &cddm->mloop[mf->loopstart]; + cent[0] = cent[1] = cent[2] = 0.0f; + for (j=0; j<mf->totloop; j++, ml++) { + add_v3_v3v3(cent, cent, mv[ml->v].co); + } + mul_v3_fl(cent, 1.0f / (float)j); - copy_v3_v3(cent, mv[mf->v1].co); - add_v3_v3(cent, mv[mf->v2].co); - add_v3_v3(cent, mv[mf->v3].co); - - if (mf->v4) { - normal_quad_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co); - add_v3_v3(cent, mv[mf->v4].co); - mul_v3_fl(cent, 0.25f); + ml = &cddm->mloop[mf->loopstart]; + if (j > 3) { + normal_quad_v3(no, mv[ml->v].co, mv[(ml+1)->v].co, + mv[(ml+2)->v].co, mv[(ml+3)->v].co); } else { - normal_tri_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co); - mul_v3_fl(cent, 0.33333333333f); + normal_tri_v3(no, mv[ml->v].co, mv[(ml+1)->v].co, mv[(ml+2)->v].co); } func(userData, orig, cent, no); } + +} + +void CDDM_recalc_tesselation(DerivedMesh *dm) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + + dm->numFaceData = mesh_recalcTesselation(&dm->faceData, &dm->loopData, + &dm->polyData, cddm->mvert, dm->numFaceData, dm->numLoopData, + dm->numPolyData); + + if (!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX)) { + int *polyIndex = CustomData_get_layer(&dm->faceData, CD_POLYINDEX); + CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_REFERENCE, polyIndex, dm->numFaceData); + } + + cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE); } static void cdDM_free_internal(CDDerivedMesh *cddm) @@ -1553,6 +1612,11 @@ static void cdDM_release(DerivedMesh *dm) } } +int CDDM_Check(DerivedMesh *dm) +{ + return dm && dm->getMinMax == cdDM_getMinMax; +} + /**************** CDDM interface functions ****************/ static CDDerivedMesh *cdDM_create(const char *desc) { @@ -1565,21 +1629,21 @@ static CDDerivedMesh *cdDM_create(const char *desc) dm->getMinMax = cdDM_getMinMax; dm->getNumVerts = cdDM_getNumVerts; - dm->getNumFaces = cdDM_getNumFaces; dm->getNumEdges = cdDM_getNumEdges; + dm->getNumTessFaces = cdDM_getNumTessFaces; + dm->getNumFaces = cdDM_getNumFaces; dm->getVert = cdDM_getVert; dm->getEdge = cdDM_getEdge; - dm->getFace = cdDM_getFace; + dm->getTessFace = cdDM_getFace; dm->copyVertArray = cdDM_copyVertArray; dm->copyEdgeArray = cdDM_copyEdgeArray; - dm->copyFaceArray = cdDM_copyFaceArray; - dm->getVertData = DM_get_vert_data; - dm->getEdgeData = DM_get_edge_data; - dm->getFaceData = DM_get_face_data; - dm->getVertDataArray = DM_get_vert_data_layer; - dm->getEdgeDataArray = DM_get_edge_data_layer; - dm->getFaceDataArray = DM_get_face_data_layer; + dm->copyTessFaceArray = cdDM_copyFaceArray; + dm->copyLoopArray = cdDM_copyLoopArray; + dm->copyPolyArray = cdDM_copyPolyArray; + + dm->calcNormals = CDDM_calc_normals; + dm->recalcTesselation = CDDM_recalc_tesselation; dm->getVertCos = cdDM_getVertCos; dm->getVertCo = cdDM_getVertCo; @@ -1613,24 +1677,30 @@ static CDDerivedMesh *cdDM_create(const char *desc) return cddm; } -DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces) +DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces, int numLoops, int numPolys) { CDDerivedMesh *cddm = cdDM_create("CDDM_new dm"); DerivedMesh *dm = &cddm->dm; - DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces); + DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces, numLoops, numPolys); CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts); CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces); + CustomData_add_layer(&dm->faceData, CD_POLYINDEX, CD_CALLOC, NULL, numFaces); + CustomData_add_layer(&dm->polyData, CD_ORIGINDEX, CD_CALLOC, NULL, numPolys); CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts); CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges); CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces); + CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops); + CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys); cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT); cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE); cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE); + cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP); + cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY); return dm; } @@ -1641,10 +1711,12 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob)) DerivedMesh *dm = &cddm->dm; CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS); int alloctype; + int *polyindex = NULL; /* this does a referenced copy, with an exception for fluidsim */ - DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface); + DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface, + mesh->totloop, mesh->totpoly); dm->deformedOnly = 1; @@ -1654,21 +1726,38 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob)) mesh->totvert); CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype, mesh->totedge); - CustomData_merge(&mesh->fdata, &dm->faceData, mask, alloctype, + CustomData_merge(&mesh->fdata, &dm->faceData, mask|CD_MASK_POLYINDEX, alloctype, mesh->totface); + CustomData_merge(&mesh->ldata, &dm->loopData, mask, alloctype, + mesh->totloop); + CustomData_merge(&mesh->pdata, &dm->polyData, mask, alloctype, + mesh->totpoly); cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT); cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE); + cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP); + cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY); cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE); + /* commented since even when CD_POLYINDEX was first added this line fails + * on the default cube, (after editmode toggle too) - campbell */ +#if 0 + BLI_assert(CustomData_has_layer(&cddm->dm.faceData, CD_POLYINDEX)); +#endif + + polyindex = CustomData_get_layer(&dm->faceData, CD_POLYINDEX); + if (!CustomData_has_layer(&cddm->dm.faceData, CD_ORIGINDEX)) { + CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_REFERENCE, polyindex, mesh->totface); + } + return dm; } -DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me)) +static DerivedMesh *UNUSED_FUNCTION(CDDM_from_editmesh)(EditMesh *em, Mesh *UNUSED(me)) { DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts), - BLI_countlist(&em->edges), - BLI_countlist(&em->faces)); + BLI_countlist(&em->edges), + BLI_countlist(&em->faces), 0, 0); CDDerivedMesh *cddm = (CDDerivedMesh*)dm; EditVert *eve; EditEdge *eed; @@ -1686,6 +1775,8 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me)) CD_CALLOC, dm->numEdgeData); */ CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH, CD_CALLOC, dm->numFaceData); + CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH, + CD_CALLOC, dm->numFaceData); /* set eve->hash to vert index */ for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i) @@ -1739,7 +1830,7 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me)) /* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */ } - index = dm->getFaceDataArray(dm, CD_ORIGINDEX); + index = dm->getTessFaceDataArray(dm, CD_POLYINDEX); for(i = 0, efa = em->faces.first; i < dm->numFaceData; i++, efa = efa->next, index++) { MFace *mf = &mface[i]; @@ -1772,15 +1863,17 @@ DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase) MVert *allvert; MEdge *alledge; MFace *allface; - int totvert, totedge, totface; + MLoop *allloop; + MPoly *allpoly; + int totvert, totedge, totface, totloop, totpoly; if (nurbs_to_mdata_customdb(ob, dispbase, &allvert, &totvert, &alledge, - &totedge, &allface, &totface) != 0) { + &totedge, &allface, &allloop, &allpoly, &totface, &totloop, &totpoly) != 0) { /* Error initializing mdata. This often happens when curve is empty */ - return CDDM_new(0, 0, 0); + return CDDM_new(0, 0, 0, 0, 0); } - dm = CDDM_new(totvert, totedge, totface); + dm = CDDM_new(totvert, totedge, totface, totloop, totpoly); dm->deformedOnly = 1; cddm = (CDDerivedMesh*)dm; @@ -1788,29 +1881,239 @@ DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase) memcpy(cddm->mvert, allvert, totvert*sizeof(MVert)); memcpy(cddm->medge, alledge, totedge*sizeof(MEdge)); memcpy(cddm->mface, allface, totface*sizeof(MFace)); + memcpy(cddm->mloop, allloop, totloop*sizeof(MLoop)); + memcpy(cddm->mpoly, allpoly, totpoly*sizeof(MPoly)); MEM_freeN(allvert); MEM_freeN(alledge); MEM_freeN(allface); + MEM_freeN(allloop); + MEM_freeN(allpoly); return dm; } -DerivedMesh *CDDM_copy(DerivedMesh *source) +static void loops_to_customdata_corners(BMesh *bm, CustomData *facedata, + int cdindex, BMLoop *l3[3], + int numCol, int numTex) +{ + BMLoop *l; + BMFace *f = l3[0]->f; + MTFace *texface; + MTexPoly *texpoly; + MCol *mcol; + MLoopCol *mloopcol; + MLoopUV *mloopuv; + int i, j, hasWCol = CustomData_has_layer(&bm->ldata, CD_WEIGHT_MLOOPCOL); + + for(i=0; i < numTex; i++){ + texface = CustomData_get_n(facedata, CD_MTFACE, cdindex, i); + texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i); + + texface->tpage = texpoly->tpage; + texface->flag = texpoly->flag; + texface->transp = texpoly->transp; + texface->mode = texpoly->mode; + texface->tile = texpoly->tile; + texface->unwrap = texpoly->unwrap; + + for (j=0; j<3; j++) { + l = l3[j]; + mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i); + texface->uv[j][0] = mloopuv->uv[0]; + texface->uv[j][1] = mloopuv->uv[1]; + } + } + + for(i=0; i < numCol; i++){ + mcol = CustomData_get_n(facedata, CD_MCOL, cdindex, i); + + for (j=0; j<3; j++) { + l = l3[j]; + mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i); + mcol[j].r = mloopcol->r; + mcol[j].g = mloopcol->g; + mcol[j].b = mloopcol->b; + mcol[j].a = mloopcol->a; + } + } + + if (hasWCol) { + mcol = CustomData_get(facedata, cdindex, CD_WEIGHT_MCOL); + + for (j=0; j<3; j++) { + l = l3[j]; + mloopcol = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_WEIGHT_MLOOPCOL); + mcol[j].r = mloopcol->r; + mcol[j].g = mloopcol->g; + mcol[j].b = mloopcol->b; + mcol[j].a = mloopcol->a; + } + } +} + +DerivedMesh *CDDM_from_BMEditMesh(BMEditMesh *em, Mesh *UNUSED(me), int use_mdisps) +{ + DerivedMesh *dm = CDDM_new(em->bm->totvert, em->bm->totedge, + em->tottri, em->bm->totloop, em->bm->totface); + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + BMesh *bm = em->bm; + BMIter iter, liter; + BMVert *eve; + BMEdge *eed; + BMFace *efa; + MVert *mvert = cddm->mvert; + MEdge *medge = cddm->medge; + MFace *mface = cddm->mface; + MLoop *mloop = cddm->mloop; + MPoly *mpoly = cddm->mpoly; + int numCol = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPCOL); + int numTex = CustomData_number_of_layers(&em->bm->pdata, CD_MTEXPOLY); + int i, j, *index, *polyindex, add_orig; + int has_crease, has_edge_bweight, has_vert_bweight; + int flag; + + has_edge_bweight = CustomData_has_layer(&em->bm->edata, CD_BWEIGHT); + has_vert_bweight = CustomData_has_layer(&em->bm->vdata, CD_BWEIGHT); + has_crease = CustomData_has_layer(&em->bm->edata, CD_CREASE); + + dm->deformedOnly = 1; + + /*don't add origindex layer if one already exists*/ + add_orig = !CustomData_has_layer(&em->bm->pdata, CD_ORIGINDEX); + + flag = use_mdisps ? CD_MASK_DERIVEDMESH|CD_MASK_MDISPS : CD_MASK_DERIVEDMESH; + + /*don't process shapekeys, we only feed them through the modifier stack as needed, + e.g. for applying modifiers or the like*/ + flag &= ~CD_SHAPEKEY; + CustomData_merge(&em->bm->vdata, &dm->vertData, flag, + CD_CALLOC, dm->numVertData); + CustomData_merge(&em->bm->edata, &dm->edgeData, flag, + CD_CALLOC, dm->numEdgeData); + CustomData_merge(&em->bm->ldata, &dm->loopData, flag, + CD_CALLOC, dm->numLoopData); + CustomData_merge(&em->bm->pdata, &dm->polyData, flag, + CD_CALLOC, dm->numPolyData); + + /*add tesselation mface layers*/ + CustomData_from_bmeshpoly(&dm->faceData, &dm->polyData, &dm->loopData, em->tottri); + + index = dm->getVertDataArray(dm, CD_ORIGINDEX); + + eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++, index++) { + MVert *mv = &mvert[i]; + + copy_v3_v3(mv->co, eve->co); + + BM_SetIndex(eve, i); /* set_inline */ + + normal_float_to_short_v3(mv->no, eve->no); + + mv->flag = BMFlags_To_MEFlags(eve); + + if (has_vert_bweight) + mv->bweight = (unsigned char)(BM_GetCDf(&bm->vdata, eve, CD_BWEIGHT)*255.0f); + + if (add_orig) *index = i; + + CustomData_from_bmesh_block(&bm->vdata, &dm->vertData, eve->head.data, i); + } + bm->elem_index_dirty &= ~BM_VERT; + + index = dm->getEdgeDataArray(dm, CD_ORIGINDEX); + eed = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); + for (i=0; eed; eed=BMIter_Step(&iter), i++, index++) { + MEdge *med = &medge[i]; + + BM_SetIndex(eed, i); /* set_inline */ + + med->v1 = BM_GetIndex(eed->v1); + med->v2 = BM_GetIndex(eed->v2); + + if (has_crease) + med->crease = (unsigned char)(BM_GetCDf(&bm->edata, eed, CD_CREASE)*255.0f); + if (has_edge_bweight) + med->bweight = (unsigned char)(BM_GetCDf(&bm->edata, eed, CD_BWEIGHT)*255.0f); + + med->flag = BMFlags_To_MEFlags(eed); + + CustomData_from_bmesh_block(&bm->edata, &dm->edgeData, eed->head.data, i); + if (add_orig) *index = i; + } + bm->elem_index_dirty &= ~BM_EDGE; + + BM_ElemIndex_Ensure(em->bm, BM_FACE); + + polyindex = dm->getTessFaceDataArray(dm, CD_POLYINDEX); + index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + for(i = 0; i < dm->numFaceData; i++, index++, polyindex++) { + MFace *mf = &mface[i]; + BMLoop **l = em->looptris[i]; + efa = l[0]->f; + + mf->v1 = BM_GetIndex(l[0]->v); + mf->v2 = BM_GetIndex(l[1]->v); + mf->v3 = BM_GetIndex(l[2]->v); + mf->v4 = 0; + mf->mat_nr = efa->mat_nr; + mf->flag = BMFlags_To_MEFlags(efa); + + *index = add_orig ? BM_GetIndex(efa) : *(int*)CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_ORIGINDEX); + *polyindex = BM_GetIndex(efa); + + loops_to_customdata_corners(bm, &dm->faceData, i, l, numCol, numTex); + test_index_face(mf, &dm->faceData, i, 3); + } + + index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX); + j = 0; + efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); + for (i=0; efa; i++, efa=BMIter_Step(&iter), index++) { + BMLoop *l; + MPoly *mp = &mpoly[i]; + + mp->totloop = efa->len; + mp->flag = BMFlags_To_MEFlags(efa); + mp->loopstart = j; + mp->mat_nr = efa->mat_nr; + + BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, efa) { + mloop->v = BM_GetIndex(l->v); + mloop->e = BM_GetIndex(l->e); + CustomData_from_bmesh_block(&bm->ldata, &dm->loopData, l->head.data, j); + + j++; + mloop++; + } + + CustomData_from_bmesh_block(&bm->pdata, &dm->polyData, efa->head.data, i); + + if (add_orig) *index = i; + } + + return dm; +} + +DerivedMesh *CDDM_copy(DerivedMesh *source, int faces_from_tessfaces) { CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm"); DerivedMesh *dm = &cddm->dm; int numVerts = source->numVertData; int numEdges = source->numEdgeData; int numFaces = source->numFaceData; + int numLoops = source->numLoopData; + int numPolys = source->numPolyData; /* ensure these are created if they are made on demand */ source->getVertDataArray(source, CD_ORIGINDEX); source->getEdgeDataArray(source, CD_ORIGINDEX); - source->getFaceDataArray(source, CD_ORIGINDEX); + source->getTessFaceDataArray(source, CD_ORIGINDEX); /* this initializes dm, and copies all non mvert/medge/mface layers */ - DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces); + DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces, + numLoops, numPolys); dm->deformedOnly = source->deformedOnly; CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts); @@ -1820,19 +2123,32 @@ DerivedMesh *CDDM_copy(DerivedMesh *source) /* now add mvert/medge/mface layers */ cddm->mvert = source->dupVertArray(source); cddm->medge = source->dupEdgeArray(source); - cddm->mface = source->dupFaceArray(source); + cddm->mface = source->dupTessFaceArray(source); CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts); CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges); CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numFaces); + + if (!faces_from_tessfaces) + DM_DupPolys(source, dm); + else + CDDM_tessfaces_to_faces(dm); + + cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP); + cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY); + /* BMESH_TODO: Find out why this is necessary (or else find a way to remove + it). If it is necessary, add a comment explaining why. */ + CDDM_recalc_tesselation((DerivedMesh *)cddm); + return dm; } /* note, the CD_ORIGINDEX layers are all 0, so if there is a direct * relationship betwen mesh data this needs to be set by the caller. */ DerivedMesh *CDDM_from_template(DerivedMesh *source, - int numVerts, int numEdges, int numFaces) + int numVerts, int numEdges, int numFaces, + int numLoops, int numPolys) { CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest"); DerivedMesh *dm = &cddm->dm; @@ -1840,15 +2156,17 @@ DerivedMesh *CDDM_from_template(DerivedMesh *source, /* ensure these are created if they are made on demand */ source->getVertDataArray(source, CD_ORIGINDEX); source->getEdgeDataArray(source, CD_ORIGINDEX); - source->getFaceDataArray(source, CD_ORIGINDEX); + source->getTessFaceDataArray(source, CD_ORIGINDEX); /* this does a copy of all non mvert/medge/mface layers */ - DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces); + DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces, numLoops, numPolys); /* now add mvert/medge/mface layers */ CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts); CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges); CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces); + CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops); + CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys); if(!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX)) CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts); @@ -1856,10 +2174,14 @@ DerivedMesh *CDDM_from_template(DerivedMesh *source, CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); if(!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX)) CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces); + if(!CustomData_get_layer(&dm->faceData, CD_POLYINDEX)) + CustomData_add_layer(&dm->faceData, CD_POLYINDEX, CD_CALLOC, NULL, numFaces); cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT); cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE); cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE); + cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP); + cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY); return dm; } @@ -1895,23 +2217,232 @@ void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3]) void CDDM_calc_normals(DerivedMesh *dm) { CDDerivedMesh *cddm = (CDDerivedMesh*)dm; - float (*face_nors)[3]; - + float (*face_nors)[3] = NULL; + if(dm->numVertData == 0) return; /* we don't want to overwrite any referenced layers */ cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT); - /* make a face normal layer if not present */ - face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL); - if(!face_nors) - face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC, - NULL, dm->numFaceData); + if (dm->numFaceData == 0) { + /* No tesselation on this mesh yet, need to calculate one */ + CDDM_recalc_tesselation(dm); + } + else { + /* A tesselation already exists, it should always have a CD_POLYINDEX */ + BLI_assert(CustomData_has_layer(&dm->faceData, CD_POLYINDEX)); + CustomData_free_layers(&dm->faceData, CD_NORMAL, dm->numFaceData); + } + face_nors = MEM_mallocN(sizeof(float)*3*dm->numFaceData, "face_nors"); + /* calculate face normals */ - mesh_calc_normals(cddm->mvert, dm->numVertData, CDDM_get_faces(dm), dm->numFaceData, face_nors); + mesh_calc_normals(cddm->mvert, dm->numVertData, CDDM_get_loops(dm), CDDM_get_polys(dm), + dm->numLoopData, dm->numPolyData, NULL, cddm->mface, dm->numFaceData, + CustomData_get_layer(&dm->faceData, CD_POLYINDEX), face_nors); + + CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_ASSIGN, + face_nors, dm->numFaceData); } +#if 1 +/*merge verts + + vtargetmap is a table that maps vertices to target vertices. a value of -1 + indicates a vertex is a target, and is to be kept. + + this frees dm, and returns a new one. + + this is a really horribly written function. ger. - joeedh + + */ +DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, int *vtargetmap) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + CDDerivedMesh *cddm2 = NULL; + MVert *mv, *mvert = NULL; + BLI_array_declare(mvert); + MEdge *me, *medge = NULL; + BLI_array_declare(medge); + MPoly *mp, *mpoly = NULL; + BLI_array_declare(mpoly); + MLoop *ml, *mloop = NULL; + BLI_array_declare(mloop); + EdgeHash *ehash = BLI_edgehash_new(); + int *newv = NULL, *newe = NULL, *newl = NULL; + int *oldv = NULL, *olde = NULL, *oldl = NULL, *oldp = NULL; + BLI_array_declare(oldv); BLI_array_declare(olde); BLI_array_declare(oldl); BLI_array_declare(oldp); + int i, j, c, totloop, totpoly; + + totloop = dm->numLoopData; + totpoly = dm->numPolyData; + + newv = MEM_callocN(sizeof(int)*dm->numVertData, "newv vtable CDDM_merge_verts"); + newe = MEM_callocN(sizeof(int)*dm->numEdgeData, "newv etable CDDM_merge_verts"); + newl = MEM_callocN(sizeof(int)*totloop, "newv ltable CDDM_merge_verts"); + + /*fill newl with destination vertex indices*/ + mv = cddm->mvert; + c = 0; + for (i=0; i<dm->numVertData; i++, mv++) { + if (vtargetmap[i] == -1) { + BLI_array_append(oldv, i); + newv[i] = c++; + BLI_array_append(mvert, *mv); + } + } + + /*now link target vertices to destination indices*/ + for (i=0; i<dm->numVertData; i++) { + if (vtargetmap[i] != -1) { + newv[i] = newv[vtargetmap[i]]; + } + } + + /*find-replace merged vertices with target vertices*/ + ml = cddm->mloop; + c = 0; + for (i=0; i<totloop; i++, ml++) { + if (ml->v == -1) + continue; + + if (vtargetmap[ml->v] != -1) + ml->v = vtargetmap[ml->v]; + } + + /*now go through and fix edges and faces*/ + me = cddm->medge; + c = 0; + for (i=0; i<dm->numEdgeData; i++, me++) { + int v1, v2; + + if (me->v1 == me->v2) { + newe[i] = -1; + continue; + } + + if (vtargetmap[me->v1] != -1) + v1 = vtargetmap[me->v1]; + else + v1 = me->v1; + + if (vtargetmap[me->v2] != -1) + v2 = vtargetmap[me->v2]; + else + v2 = me->v2; + + if (BLI_edgehash_haskey(ehash, v1, v2)) { + newe[i] = GET_INT_FROM_POINTER(BLI_edgehash_lookup(ehash, v1, v2)); + } else { + BLI_array_append(olde, i); + newe[i] = c; + BLI_array_append(medge, *me); + BLI_edgehash_insert(ehash, v1, v2, SET_INT_IN_POINTER(c)); + c++; + } + } + + mp = cddm->mpoly; + for (i=0; i<totpoly; i++, mp++) { + MPoly *mp2; + + ml = cddm->mloop + mp->loopstart; + + c = 0; + for (j=0; j<mp->totloop; j++, ml++) { + if (ml->v == -1) + continue; + + me = cddm->medge + ml->e; + if (me->v1 != me->v2) { + BLI_array_append(oldl, j+mp->loopstart); + BLI_array_append(mloop, *ml); + newl[j+mp->loopstart] = BLI_array_count(mloop)-1; + c++; + } + } + + if (!c) + continue; + + mp2 = BLI_array_append_r(mpoly, *mp); + mp2->totloop = c; + mp2->loopstart = BLI_array_count(mloop) - c; + + BLI_array_append(oldp, i); + } + + /*create new cddm*/ + cddm2 = (CDDerivedMesh*) CDDM_from_template((DerivedMesh*)cddm, BLI_array_count(mvert), BLI_array_count(medge), 0, BLI_array_count(mloop), BLI_array_count(mpoly)); + + /*update edge indices and copy customdata*/ + me = medge; + for (i=0; i<cddm2->dm.numEdgeData; i++, me++) { + if (newv[me->v1] != -1) + me->v1 = newv[me->v1]; + if (newv[me->v2] != -1) + me->v2 = newv[me->v2]; + + CustomData_copy_data(&dm->edgeData, &cddm2->dm.edgeData, olde[i], i, 1); + } + + /*update loop indices and copy customdata*/ + ml = mloop; + for (i=0; i<cddm2->dm.numLoopData; i++, ml++) { + if (newe[ml->e] != -1) + ml->e = newe[ml->e]; + if (newv[ml->v] != -1) + ml->v = newv[ml->v]; + + CustomData_copy_data(&dm->loopData, &cddm2->dm.loopData, oldl[i], i, 1); + } + + /*copy vertex customdata*/ + mv = mvert; + for (i=0; i<cddm2->dm.numVertData; i++, mv++) { + CustomData_copy_data(&dm->vertData, &cddm2->dm.vertData, oldv[i], i, 1); + } + + /*copy poly customdata*/ + mp = mpoly; + for (i=0; i<cddm2->dm.numPolyData; i++, mp++) { + CustomData_copy_data(&dm->polyData, &cddm2->dm.polyData, oldp[i], i, 1); + } + + /*copy over data. CustomData_add_layer can do this, need to look it up.*/ + memcpy(cddm2->mvert, mvert, sizeof(MVert)*BLI_array_count(mvert)); + memcpy(cddm2->medge, medge, sizeof(MEdge)*BLI_array_count(medge)); + memcpy(cddm2->mloop, mloop, sizeof(MLoop)*BLI_array_count(mloop)); + memcpy(cddm2->mpoly, mpoly, sizeof(MPoly)*BLI_array_count(mpoly)); + BLI_array_free(mvert); BLI_array_free(medge); BLI_array_free(mloop); BLI_array_free(mpoly); + + CDDM_recalc_tesselation((DerivedMesh*)cddm2); + + if (newv) + MEM_freeN(newv); + if (newe) + MEM_freeN(newe); + if (newl) + MEM_freeN(newl); + if (oldv) + MEM_freeN(oldv); + if (olde) + MEM_freeN(olde); + if (oldl) + MEM_freeN(oldl); + if (oldp) + MEM_freeN(oldp); + if (ehash) + BLI_edgehash_free(ehash, NULL); + + /*free old derivedmesh*/ + dm->needsFree = 1; + dm->release(dm); + + return (DerivedMesh*)cddm2; +} +#endif + void CDDM_calc_edges(DerivedMesh *dm) { CDDerivedMesh *cddm = (CDDerivedMesh*)dm; @@ -1968,6 +2499,82 @@ void CDDM_calc_edges(DerivedMesh *dm) BLI_edgehash_free(eh, NULL); } +/* warning, this uses existing edges but CDDM_calc_edges() doesn't */ +void CDDM_calc_edges_poly(DerivedMesh *dm) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + CustomData edgeData; + EdgeHashIterator *ehi; + MPoly *mp = cddm->mpoly; + MLoop *ml; + MEdge *med; + EdgeHash *eh = BLI_edgehash_new(); + int v1, v2; + int *eindex; + int i, j, *index, numEdges = cddm->dm.numEdgeData, maxFaces = dm->numPolyData; + + eindex = DM_get_edge_data_layer(dm, CD_ORIGINDEX); + + med = cddm->medge; + if (med) { + for (i=0; i < numEdges; i++, med++) { + BLI_edgehash_insert(eh, med->v1, med->v2, SET_INT_IN_POINTER(i+1)); + } + } + + for (i=0; i < maxFaces; i++, mp++) { + ml = cddm->mloop + mp->loopstart; + for (j=0; j<mp->totloop; j++, ml++) { + v1 = ml->v; + v2 = (cddm->mloop + mp->loopstart + ((j+1)%mp->totloop))->v; + if (!BLI_edgehash_haskey(eh, v1, v2)) { + BLI_edgehash_insert(eh, v1, v2, NULL); + } + } + } + + numEdges = BLI_edgehash_size(eh); + + /* write new edges into a temporary CustomData */ + memset(&edgeData, 0, sizeof(edgeData)); + CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges); + CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); + + ehi = BLI_edgehashIterator_new(eh); + med = CustomData_get_layer(&edgeData, CD_MEDGE); + index = CustomData_get_layer(&edgeData, CD_ORIGINDEX); + for(i = 0; !BLI_edgehashIterator_isDone(ehi); + BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) { + BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2); + j = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi)); + + med->flag = ME_EDGEDRAW|ME_EDGERENDER; + *index = j==0 ? ORIGINDEX_NONE : eindex[j-1]; + + BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(i)); + } + BLI_edgehashIterator_free(ehi); + + /* free old CustomData and assign new one */ + CustomData_free(&dm->edgeData, dm->numEdgeData); + dm->edgeData = edgeData; + dm->numEdgeData = numEdges; + + cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE); + + mp = cddm->mpoly; + for (i=0; i < maxFaces; i++, mp++) { + ml = cddm->mloop + mp->loopstart; + for (j=0; j<mp->totloop; j++, ml++) { + v1 = ml->v; + v2 = (cddm->mloop + mp->loopstart + ((j+1)%mp->totloop))->v; + ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, v1, v2)); + } + } + + BLI_edgehash_free(eh, NULL); +} + void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts) { if (numVerts < dm->numVertData) @@ -2002,7 +2609,7 @@ MEdge *CDDM_get_edge(DerivedMesh *dm, int index) return &((CDDerivedMesh*)dm)->medge[index]; } -MFace *CDDM_get_face(DerivedMesh *dm, int index) +MFace *CDDM_get_tessface(DerivedMesh *dm, int index) { return &((CDDerivedMesh*)dm)->mface[index]; } @@ -2017,8 +2624,127 @@ MEdge *CDDM_get_edges(DerivedMesh *dm) return ((CDDerivedMesh*)dm)->medge; } -MFace *CDDM_get_faces(DerivedMesh *dm) +MFace *CDDM_get_tessfaces(DerivedMesh *dm) { return ((CDDerivedMesh*)dm)->mface; } +MLoop *CDDM_get_loops(DerivedMesh *dm) +{ + return ((CDDerivedMesh*)dm)->mloop; +} + +MPoly *CDDM_get_polys(DerivedMesh *dm) +{ + return ((CDDerivedMesh*)dm)->mpoly; +} + +void CDDM_tessfaces_to_faces(DerivedMesh *dm) +{ + /*converts mfaces to mpolys/mloops*/ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + MFace *mf; + MEdge *me; + EdgeHash *eh = BLI_edgehash_new(); + int i, totloop; + + /*ensure we have all the edges we need*/ + CDDM_calc_edges(dm); + + /*build edge hash*/ + me = cddm->medge; + for (i=0; i<cddm->dm.numEdgeData; i++, me++) { + BLI_edgehash_insert(eh, me->v1, me->v2, SET_INT_IN_POINTER(i)); + } + + mf = cddm->mface; + totloop = 0; + for (i=0; i<cddm->dm.numFaceData; i++, mf++) { + totloop += mf->v4 ? 4 : 3; + } + + CustomData_free(&cddm->dm.polyData, cddm->dm.numPolyData); + CustomData_free(&cddm->dm.loopData, cddm->dm.numLoopData); + + cddm->dm.numLoopData = totloop; + cddm->dm.numPolyData = cddm->dm.numFaceData; + + if (totloop) { + MLoop *ml; + MPoly *mp; + int l, *polyindex; + + cddm->mloop = MEM_callocN(sizeof(MLoop)*totloop, "cddm->mloop in CDDM_tessfaces_to_faces"); + cddm->mpoly = MEM_callocN(sizeof(MPoly)*cddm->dm.numFaceData, "cddm->mpoly in CDDM_tessfaces_to_faces"); + + CustomData_add_layer(&cddm->dm.loopData, CD_MLOOP, CD_ASSIGN, cddm->mloop, totloop); + CustomData_add_layer(&cddm->dm.polyData, CD_MPOLY, CD_ASSIGN, cddm->mpoly, cddm->dm.numPolyData); + CustomData_merge(&cddm->dm.faceData, &cddm->dm.polyData, + CD_MASK_ORIGINDEX, CD_DUPLICATE, cddm->dm.numFaceData); + + polyindex = CustomData_get_layer(&cddm->dm.faceData, CD_POLYINDEX); + + mf = cddm->mface; + mp = cddm->mpoly; + ml = cddm->mloop; + l = 0; + for (i=0; i<cddm->dm.numFaceData; i++, mf++, mp++) { + mp->flag = mf->flag; + mp->loopstart = l; + mp->mat_nr = mf->mat_nr; + mp->totloop = mf->v4 ? 4 : 3; + + ml->v = mf->v1; + ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v1, mf->v2)); + ml++, l++; + + ml->v = mf->v2; + ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v2, mf->v3)); + ml++, l++; + + ml->v = mf->v3; + ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v3, mf->v4?mf->v4:mf->v1)); + ml++, l++; + + if (mf->v4) { + ml->v = mf->v4; + ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v4, mf->v1)); + ml++, l++; + } + + *polyindex = i; + } + } + + BLI_edgehash_free(eh, NULL); +} + +void CDDM_set_mvert(DerivedMesh *dm, MVert *mvert) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + + if (!CustomData_has_layer(&dm->vertData, CD_MVERT)) + CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, mvert, dm->numVertData); + + cddm->mvert = mvert; +} + +void CDDM_set_medge(DerivedMesh *dm, MEdge *medge) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + + if (!CustomData_has_layer(&dm->edgeData, CD_MEDGE)) + CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, medge, dm->numEdgeData); + + cddm->medge = medge; +} + +void CDDM_set_mface(DerivedMesh *dm, MFace *mface) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + + if (!CustomData_has_layer(&dm->faceData, CD_MFACE)) + CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, mface, dm->numFaceData); + + cddm->mface = mface; +} |