From 4b4bf1146997636e581465a73074b8f68b56f8a9 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 4 Jun 2012 12:10:38 +0000 Subject: [PATCH] Fix #31172: applying boolean removes uv maps The issue was caused by CDDM_tessfaces_to_faces not dealing with CD layers. There was already function BKE_mesh_convert_mfaces_to_mpolys which converted mfaces to mpolys with converting all CD layers. Made it a bit more general so it might work with given arrays of faces/polys and re-used it from CDDM module. Checked with UV and sculpt data from Blender 2.61 and it loaded nice, so hopefully there's no regressions in loading older files. --- source/blender/blenkernel/BKE_mesh.h | 8 + .../blender/blenkernel/intern/cdderivedmesh.c | 93 +---------- source/blender/blenkernel/intern/mesh.c | 147 +++++++++++------- 3 files changed, 102 insertions(+), 146 deletions(-) diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 7abec074647..1878e43f577 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -33,6 +33,7 @@ /***/ +struct ID; struct BoundBox; struct DispList; struct ListBase; @@ -150,6 +151,13 @@ void copy_dverts(struct MDeformVert *dst, struct MDeformVert *src, int totvert); void BKE_mesh_delete_material_index(struct Mesh *me, short index); void BKE_mesh_smooth_flag_set(struct Object *meshOb, int enableSmooth); void BKE_mesh_convert_mfaces_to_mpolys(struct Mesh *mesh); +void BKE_mesh_convert_mfaces_to_mpolys_ex(struct ID *id, + struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata, + int totedge_i, int totface_i, int totloop_i, int totpoly_i, + struct MEdge *medge, struct MFace *mface, + int *totloop_r, int *totpoly_r, + struct MLoop **mloop_r, struct MPoly **mpoly_r); + void BKE_mesh_calc_normals_tessface(struct MVert *mverts, int numVerts, struct MFace *mfaces, int numFaces, float (*faceNors_r)[3]); /* used for unit testing; compares two meshes, checking only diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 4e6a4b4a43c..e5e73061d52 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -2594,94 +2594,15 @@ MPoly *CDDM_get_polys(DerivedMesh *dm) void CDDM_tessfaces_to_faces(DerivedMesh *dm) { - /*converts mfaces to mpolys/mloops*/ + /* converts mfaces to mpolys/mloops */ CDDerivedMesh *cddm = (CDDerivedMesh *)dm; - MFace *mf; - MEdge *me; - EdgeHash *eh = BLI_edgehash_new(); - int i, totloop; - /* ... on second thaughts, better comment this and assume caller knows edge state. */ -#if 0 - /* ensure we have all the edges we need */ - CDDM_calc_edges_tessface(dm); -#else -# ifndef NDEBUG - { - /* ensure we have correct edges on non release builds */ - i = cddm->dm.numEdgeData; - CDDM_calc_edges_tessface(dm); - BLI_assert(cddm->dm.numEdgeData == i); - } -# endif -#endif - - /*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.numTessFaceData; 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.numTessFaceData; - - 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.numTessFaceData, "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.numTessFaceData); - - 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.numTessFaceData; i++, mf++, mp++, polyindex++) { - 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); + BKE_mesh_convert_mfaces_to_mpolys_ex(NULL, &cddm->dm.faceData, &cddm->dm.loopData, &cddm->dm.polyData, + cddm->dm.numEdgeData, cddm->dm.numTessFaceData, + cddm->dm.numLoopData, cddm->dm.numPolyData, + cddm->medge, cddm->mface, + &cddm->dm.numLoopData, &cddm->dm.numPolyData, + &cddm->mloop, &cddm->mpoly); } void CDDM_set_mvert(DerivedMesh *dm, MVert *mvert) diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index fd952b7b518..5db565d343c 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -1946,8 +1946,8 @@ void BKE_mesh_calc_normals_tessface(MVert *mverts, int numVerts, MFace *mfaces, MEM_freeN(fnors); } - -static void bm_corners_to_loops(Mesh *me, int findex, int loopstart, int numTex, int numCol) +static void bm_corners_to_loops_ex(ID *id, CustomData *fdata, CustomData *ldata, CustomData *pdata, + MFace *mface, int totloop, int findex, int loopstart, int numTex, int numCol) { MTFace *texface; MTexPoly *texpoly; @@ -1957,15 +1957,15 @@ static void bm_corners_to_loops(Mesh *me, int findex, int loopstart, int numTex, MFace *mf; int i; - mf = me->mface + findex; + mf = mface + findex; for (i = 0; i < numTex; i++) { - texface = CustomData_get_n(&me->fdata, CD_MTFACE, findex, i); - texpoly = CustomData_get_n(&me->pdata, CD_MTEXPOLY, findex, i); - + texface = CustomData_get_n(fdata, CD_MTFACE, findex, i); + texpoly = CustomData_get_n(pdata, CD_MTEXPOLY, findex, i); + ME_MTEXFACE_CPY(texpoly, texface); - - mloopuv = CustomData_get_n(&me->ldata, CD_MLOOPUV, loopstart, i); + + mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, loopstart, i); copy_v2_v2(mloopuv->uv, texface->uv[0]); mloopuv++; copy_v2_v2(mloopuv->uv, texface->uv[1]); mloopuv++; copy_v2_v2(mloopuv->uv, texface->uv[2]); mloopuv++; @@ -1976,8 +1976,8 @@ static void bm_corners_to_loops(Mesh *me, int findex, int loopstart, int numTex, } for (i = 0; i < numCol; i++) { - mloopcol = CustomData_get_n(&me->ldata, CD_MLOOPCOL, loopstart, i); - mcol = CustomData_get_n(&me->fdata, CD_MCOL, findex, i); + mloopcol = CustomData_get_n(ldata, CD_MLOOPCOL, loopstart, i); + mcol = CustomData_get_n(fdata, CD_MCOL, findex, i); MESH_MLOOPCOL_FROM_MCOL(mloopcol, &mcol[0]); mloopcol++; MESH_MLOOPCOL_FROM_MCOL(mloopcol, &mcol[1]); mloopcol++; @@ -1986,21 +1986,23 @@ static void bm_corners_to_loops(Mesh *me, int findex, int loopstart, int numTex, MESH_MLOOPCOL_FROM_MCOL(mloopcol, &mcol[3]); mloopcol++; } } - - if (CustomData_has_layer(&me->fdata, CD_MDISPS)) { - MDisps *ld = CustomData_get(&me->ldata, loopstart, CD_MDISPS); - MDisps *fd = CustomData_get(&me->fdata, findex, CD_MDISPS); + + if (CustomData_has_layer(fdata, CD_MDISPS)) { + MDisps *ld = CustomData_get(ldata, loopstart, CD_MDISPS); + MDisps *fd = CustomData_get(fdata, findex, CD_MDISPS); float (*disps)[3] = fd->disps; int i, tot = mf->v4 ? 4 : 3; int side, corners; - if (CustomData_external_test(&me->fdata, CD_MDISPS)) { - CustomData_external_add(&me->ldata, &me->id, CD_MDISPS, - me->totloop, me->fdata.external->filename); + if (CustomData_external_test(fdata, CD_MDISPS)) { + if (id) { + CustomData_external_add(ldata, id, CD_MDISPS, + totloop, fdata->external->filename); + } } - + corners = multires_mdisp_corners(fd); - + if (corners == 0) { /* Empty MDisp layers appear in at least one of the sintel.blend files. * Not sure why this happens, but it seems fine to just ignore them here. @@ -2009,14 +2011,14 @@ static void bm_corners_to_loops(Mesh *me, int findex, int loopstart, int numTex, } else { side = sqrt(fd->totdisp / corners); - + for (i = 0; i < tot; i++, disps += side * side, ld++) { ld->totdisp = side * side; ld->level = (int)(logf(side - 1.0f) / (float)M_LN2) + 1; - + if (ld->disps) MEM_freeN(ld->disps); - + ld->disps = MEM_callocN(sizeof(float) * 3 * side * side, "converted loop mdisps"); if (fd->disps) { memcpy(ld->disps, disps, sizeof(float) * 3 * side * side); @@ -2027,71 +2029,88 @@ static void bm_corners_to_loops(Mesh *me, int findex, int loopstart, int numTex, } void BKE_mesh_convert_mfaces_to_mpolys(Mesh *mesh) +{ + BKE_mesh_convert_mfaces_to_mpolys_ex(&mesh->id, &mesh->fdata, &mesh->ldata, &mesh->pdata, + mesh->totedge, mesh->totface, mesh->totloop, mesh->totpoly, + mesh->medge, mesh->mface, + &mesh->totloop, &mesh->totpoly, &mesh->mloop, &mesh->mpoly); + + mesh_update_customdata_pointers(mesh, TRUE); +} + +void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id, CustomData *fdata, CustomData *ldata, CustomData *pdata, + int totedge_i, int totface_i, int totloop_i, int totpoly_i, + MEdge *medge, MFace *mface, + int *totloop_r, int *totpoly_r, + MLoop **mloop_r, MPoly **mpoly_r) { MFace *mf; - MLoop *ml; - MPoly *mp; + MLoop *ml, *mloop; + MPoly *mp, *mpoly; MEdge *me; EdgeHash *eh; int numTex, numCol; - int i, j, totloop; + int i, j, totloop, totpoly, *polyindex; /* just in case some of these layers are filled in (can happen with python created meshes) */ - CustomData_free(&mesh->ldata, mesh->totloop); - CustomData_free(&mesh->pdata, mesh->totpoly); - memset(&mesh->ldata, 0, sizeof(mesh->ldata)); - memset(&mesh->pdata, 0, sizeof(mesh->pdata)); + CustomData_free(ldata, totloop_i); + CustomData_free(pdata, totpoly_i); + memset(ldata, 0, sizeof(*ldata)); + memset(pdata, 0, sizeof(*pdata)); - mesh->totpoly = mesh->totface; - mesh->mpoly = MEM_callocN(sizeof(MPoly) * mesh->totpoly, "mpoly converted"); - CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_ASSIGN, mesh->mpoly, mesh->totpoly); + totpoly = totface_i; + mpoly = MEM_callocN(sizeof(MPoly) * totpoly, "mpoly converted"); + CustomData_add_layer(pdata, CD_MPOLY, CD_ASSIGN, mpoly, totpoly); + + numTex = CustomData_number_of_layers(fdata, CD_MTFACE); + numCol = CustomData_number_of_layers(fdata, CD_MCOL); - numTex = CustomData_number_of_layers(&mesh->fdata, CD_MTFACE); - numCol = CustomData_number_of_layers(&mesh->fdata, CD_MCOL); - totloop = 0; - mf = mesh->mface; - for (i = 0; i < mesh->totface; i++, mf++) { + mf = mface; + for (i = 0; i < totface_i; i++, mf++) { totloop += mf->v4 ? 4 : 3; } - - mesh->totloop = totloop; - mesh->mloop = MEM_callocN(sizeof(MLoop) * mesh->totloop, "mloop converted"); - CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_ASSIGN, mesh->mloop, totloop); - CustomData_to_bmeshpoly(&mesh->fdata, &mesh->pdata, &mesh->ldata, - mesh->totloop, mesh->totpoly); + mloop = MEM_callocN(sizeof(MLoop) * totloop, "mloop converted"); - /* ensure external data is transferred */ - CustomData_external_read(&mesh->fdata, &mesh->id, CD_MASK_MDISPS, mesh->totface); + CustomData_add_layer(ldata, CD_MLOOP, CD_ASSIGN, mloop, totloop); + + CustomData_to_bmeshpoly(fdata, pdata, ldata, totloop, totpoly); + + if (id) { + /* ensure external data is transferred */ + CustomData_external_read(fdata, id, CD_MASK_MDISPS, totface_i); + } eh = BLI_edgehash_new(); - /*build edge hash*/ - me = mesh->medge; - for (i = 0; i < mesh->totedge; i++, me++) { + /* build edge hash */ + me = medge; + for (i = 0; i < totedge_i; i++, me++) { BLI_edgehash_insert(eh, me->v1, me->v2, SET_INT_IN_POINTER(i)); /* unrelated but avoid having the FGON flag enabled, so we can reuse it later for something else */ me->flag &= ~ME_FGON; } - j = 0; /*current loop index*/ - ml = mesh->mloop; - mf = mesh->mface; - mp = mesh->mpoly; - for (i = 0; i < mesh->totface; i++, mf++, mp++) { + polyindex = CustomData_get_layer(fdata, CD_POLYINDEX); + + j = 0; /* current loop index */ + ml = mloop; + mf = mface; + mp = mpoly; + for (i = 0; i < totface_i; i++, mf++, mp++) { mp->loopstart = j; - + mp->totloop = mf->v4 ? 4 : 3; mp->mat_nr = mf->mat_nr; mp->flag = mf->flag; - + # define ML(v1, v2) { \ ml->v = mf->v1; ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v1, mf->v2)); ml++; j++; \ } (void)0 - + ML(v1, v2); ML(v2, v3); if (mf->v4) { @@ -2101,18 +2120,26 @@ void BKE_mesh_convert_mfaces_to_mpolys(Mesh *mesh) else { ML(v3, v1); } - + # undef ML - bm_corners_to_loops(mesh, i, mp->loopstart, numTex, numCol); + bm_corners_to_loops_ex(id, fdata, ldata, pdata, mface, totloop, i, mp->loopstart, numTex, numCol); + + if (polyindex) { + *polyindex = i; + polyindex++; + } } /* note, we don't convert FGons at all, these are not even real ngons, * they have their own UV's, colors etc - its more an editing feature. */ - mesh_update_customdata_pointers(mesh, TRUE); - BLI_edgehash_free(eh, NULL); + + *totpoly_r = totpoly; + *totloop_r = totloop; + *mpoly_r = mpoly; + *mloop_r = mloop; } float (*mesh_getVertexCos(Mesh * me, int *numVerts_r))[3]