diff options
-rw-r--r-- | source/blender/blenkernel/BKE_mesh.h | 33 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh.c | 130 | ||||
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 110 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_mesh_types.h | 4 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_ngoninterp.c | 4 |
5 files changed, 246 insertions, 35 deletions
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index e1eb34782ff..9b5e38dfea7 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -61,22 +61,27 @@ extern "C" { struct BMesh *BKE_mesh_to_bmesh(struct Mesh *me, struct Object *ob); /* - this function recreates a tesselation. - returns number of tesselation faces. - - use_poly_origindex sets whether or not the tesselation faces' origindex - layer should point to original poly indices or real poly indices. - - use_face_origindex sets the tesselation faces' origindex layer - to point to the tesselation faces themselves, not the polys. - - if both of the above are 0, it'll use the indices of the mpolys of the MPoly - data in pdata, and ignore the origindex layer altogether. + * this function recreates a tesselation. + * returns number of tesselation faces. + * + * use_poly_origindex sets whether or not the tesselation faces' origindex + * layer should point to original poly indices or real poly indices. + * + * use_face_origindex sets the tesselation faces' origindex layer + * to point to the tesselation faces themselves, not the polys. + * + * if both of the above are 0, it'll use the indices of the mpolys of the MPoly + * data in pdata, and ignore the origindex layer altogether. */ int mesh_recalcTesselation(struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata, struct MVert *mvert, int totface, int totloop, int totpoly); +/* for forwards compat only quad->tri polys to mface, skip ngons. + */ +int mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata, + struct CustomData *pdata, int totface, int totloop, int totpoly); + /*calculates a face normal.*/ void mesh_calc_poly_normal(struct MPoly *mpoly, struct MLoop *loopstart, struct MVert *mvarray, float no[3]); @@ -207,9 +212,9 @@ void BKE_mesh_calc_edges(struct Mesh *mesh, int update); void BKE_mesh_ensure_navmesh(struct Mesh *me); /*convert a triangle of loop facedata to mface facedata*/ -void mesh_loops_to_tri_corners(struct CustomData *fdata, struct CustomData *ldata, - struct CustomData *pdata, int lindex[3], int findex, - int polyindex); +void mesh_loops_to_mface_corners(struct CustomData *fdata, struct CustomData *ldata, + struct CustomData *pdata, int lindex[4], int findex, + const int polyindex, const int mf_len); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 4ebcc528dac..d918e8a7e0b 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -2138,9 +2138,11 @@ void create_vert_edge_map(ListBase **map, IndexNode **mem, const MEdge *medge, c } } -void mesh_loops_to_tri_corners(CustomData *fdata, CustomData *ldata, - CustomData *pdata, int lindex[3], int findex, - int polyindex) +void mesh_loops_to_mface_corners(CustomData *fdata, CustomData *ldata, + CustomData *pdata, int lindex[4], int findex, + const int polyindex, + const int mf_len /* 3 or 4 */ + ) { MTFace *texface; MTexPoly *texpoly; @@ -2162,7 +2164,7 @@ void mesh_loops_to_tri_corners(CustomData *fdata, CustomData *ldata, texface->tile = texpoly->tile; texface->unwrap = texpoly->unwrap; - for (j=0; j<3; j++) { + for (j=0; j < mf_len; j++) { mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, lindex[j], i); texface->uv[j][0] = mloopuv->uv[0]; texface->uv[j][1] = mloopuv->uv[1]; @@ -2172,7 +2174,7 @@ void mesh_loops_to_tri_corners(CustomData *fdata, CustomData *ldata, for(i=0; i < numCol; i++){ mcol = CustomData_get_n(fdata, CD_MCOL, findex, i); - for (j=0; j<3; j++) { + for (j=0; j < mf_len; j++) { mloopcol = CustomData_get_n(ldata, CD_MLOOPCOL, lindex[j], i); mcol[j].r = mloopcol->r; mcol[j].g = mloopcol->g; @@ -2184,7 +2186,7 @@ void mesh_loops_to_tri_corners(CustomData *fdata, CustomData *ldata, if (hasWCol) { mcol = CustomData_get(fdata, findex, CD_WEIGHT_MCOL); - for (j=0; j<3; j++) { + for (j=0; j < mf_len; j++) { mloopcol = CustomData_get(ldata, lindex[j], CD_WEIGHT_MLOOPCOL); mcol[j].r = mloopcol->r; mcol[j].g = mloopcol->g; @@ -2219,7 +2221,9 @@ int mesh_recalcTesselation(CustomData *fdata, BLI_array_declare(origIndex); int *polyIndex = NULL; BLI_array_declare(polyIndex); - int i, j, k, lindex[4], *polyorigIndex; + int lindex[4]; /* only ever use 3 in this case */ + int *polyorigIndex; + int i, j, k; int numTex, numCol; mpoly = CustomData_get_layer(pdata, CD_MPOLY); @@ -2360,8 +2364,8 @@ int mesh_recalcTesselation(CustomData *fdata, mf->v2 = mloop[mf->v2].v; mf->v3 = mloop[mf->v3].v; - mesh_loops_to_tri_corners(fdata, ldata, pdata, - lindex, i, polyIndex[i]); + mesh_loops_to_mface_corners(fdata, ldata, pdata, + lindex, i, polyIndex[i], 3); } return totface; @@ -2370,6 +2374,114 @@ int mesh_recalcTesselation(CustomData *fdata, } + +#ifdef USE_MESH_FORWARDS_COMAT + +/* + * this function recreates a tesselation. + * returns number of tesselation faces. + */ +int mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata, + struct CustomData *pdata, int totface, int UNUSED(totloop), int totpoly) +{ + MLoop *mloop; + + int lindex[4]; + int i; + int k; + + MPoly *mp, *mpoly; + MFace *mface = NULL, *mf; + BLI_array_declare(mface); + + mpoly = CustomData_get_layer(pdata, CD_MPOLY); + mloop = CustomData_get_layer(ldata, CD_MLOOP); + + mp = mpoly; + k = 0; + for (i = 0; i<totpoly; i++, mp++) { + if (ELEM(mp->totloop, 3, 4)) { + BLI_array_growone(mface); + mf = &mface[k]; + + mf->mat_nr = mp->mat_nr; + mf->flag = mp->flag; + + mf->v1 = mp->loopstart + 0; + mf->v2 = mp->loopstart + 1; + mf->v3 = mp->loopstart + 2; + mf->v4 = (mp->totloop == 4) ? (mp->loopstart + 3) : 0; + + /* abuse edcode for temp storage and clear next loop */ + mf->edcode = (char)mp->totloop; /* only ever 3 or 4 */ + + k++; + } + } + + CustomData_free(fdata, totface); + memset(fdata, 0, sizeof(CustomData)); + + totface= k; + + CustomData_add_layer(fdata, CD_MFACE, CD_ASSIGN, mface, totface); + + CustomData_from_bmeshpoly(fdata, pdata, ldata, totface); + + mp = mpoly; + k = 0; + for (i = 0; i<totpoly; i++, mp++) { + if (ELEM(mp->totloop, 3, 4)) { + mf = &mface[k]; + + if (mf->edcode == 3) { + /*sort loop indices to ensure winding is correct*/ + /* NO SORT - looks like we can skip this */ + + lindex[0] = mf->v1; + lindex[1] = mf->v2; + lindex[2] = mf->v3; + lindex[3] = 0; /* unused */ + + /*transform loop indices to vert indices*/ + mf->v1 = mloop[mf->v1].v; + mf->v2 = mloop[mf->v2].v; + mf->v3 = mloop[mf->v3].v; + + mesh_loops_to_mface_corners(fdata, ldata, pdata, + lindex, k, i, 3); + test_index_face(mf, fdata, totface, 3); + } + else { + /*sort loop indices to ensure winding is correct*/ + /* NO SORT - looks like we can skip this */ + + lindex[0] = mf->v1; + lindex[1] = mf->v2; + lindex[2] = mf->v3; + lindex[3] = mf->v4; + + /*transform loop indices to vert indices*/ + mf->v1 = mloop[mf->v1].v; + mf->v2 = mloop[mf->v2].v; + mf->v3 = mloop[mf->v3].v; + mf->v4 = mloop[mf->v4].v; + + mesh_loops_to_mface_corners(fdata, ldata, pdata, + lindex, k, i, 4); + test_index_face(mf, fdata, totface, 4); + } + + mf->edcode= 0; + + k++; + } + } + + return k; +} +#endif /* USE_MESH_FORWARDS_COMAT */ + /* * COMPUTE POLY NORMAL * diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 0f10deed1f8..eb4321c57ec 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -152,6 +152,7 @@ Any case: direct data is ALWAYS after the lib block #include "BKE_modifier.h" #include "BKE_fcurve.h" #include "BKE_pointcache.h" +#include "BKE_mesh.h" #include "BLO_writefile.h" #include "BLO_readfile.h" @@ -1678,24 +1679,113 @@ static void write_customdata(WriteData *wd, ID *id, int count, CustomData *data, static void write_meshs(WriteData *wd, ListBase *idbase) { Mesh *mesh; + int save_for_old_blender= 0; + +#ifdef USE_MESH_FORWARDS_COMAT + /* TODO, add UI option to allow bmesh to save for pre-bmesh blender versions */ +#endif mesh= idbase->first; while(mesh) { if(mesh->id.us>0 || wd->current) { /* write LibData */ - writestruct(wd, ID_ME, "Mesh", 1, mesh); + if (!save_for_old_blender) { + writestruct(wd, ID_ME, "Mesh", 1, mesh); - /* direct data */ - if (mesh->id.properties) IDP_WriteProperty(mesh->id.properties, wd); - if (mesh->adt) write_animdata(wd, mesh->adt); + /* direct data */ + if (mesh->id.properties) IDP_WriteProperty(mesh->id.properties, wd); + if (mesh->adt) write_animdata(wd, mesh->adt); - writedata(wd, DATA, sizeof(void *)*mesh->totcol, mesh->mat); + writedata(wd, DATA, sizeof(void *)*mesh->totcol, mesh->mat); - write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, -1, 0); - write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, -1, 0); - write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, -1, 0); - write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, -1, 0); - write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, -1, 0); + write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, -1, 0); + write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, -1, 0); + write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, -1, 0); + write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, -1, 0); + write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, -1, 0); + } + else { + +#ifdef USE_MESH_FORWARDS_COMAT + + Mesh backup_mesh = {{0}}; + + /* backup */ + backup_mesh.mpoly = mesh->mpoly; + mesh->mpoly = NULL; + /* -- */ + backup_mesh.mface = mesh->mface; + mesh->mface = NULL; + /* -- */ + backup_mesh.totface = mesh->totface; + mesh->totface = 0; + /* -- */ + backup_mesh.totpoly = mesh->totpoly; + mesh->totpoly = 0; + /* -- */ + backup_mesh.totloop = mesh->totloop; + mesh->totloop = 0; + /* -- */ + backup_mesh.fdata = mesh->fdata; + memset(&mesh->fdata, 0, sizeof(CustomData)); + /* -- */ + backup_mesh.pdata = mesh->pdata; + memset(&mesh->pdata, 0, sizeof(CustomData)); + /* -- */ + backup_mesh.ldata = mesh->ldata; + memset(&mesh->ldata, 0, sizeof(CustomData)); + /* -- */ + backup_mesh.edit_btmesh = mesh->edit_btmesh; + mesh->edit_btmesh = NULL; + /* backup */ + + + /* now fill in polys to mfaces*/ + mesh->totface= mesh_mpoly_to_mface(&mesh->fdata, &backup_mesh.ldata, &backup_mesh.pdata, + mesh->totface, backup_mesh.totloop, backup_mesh.totpoly); + + mesh_update_customdata_pointers(mesh, FALSE); + + writestruct(wd, ID_ME, "Mesh", 1, mesh); + + /* direct data */ + if (mesh->id.properties) IDP_WriteProperty(mesh->id.properties, wd); + if (mesh->adt) write_animdata(wd, mesh->adt); + + writedata(wd, DATA, sizeof(void *)*mesh->totcol, mesh->mat); + + write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, -1, 0); + write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, -1, 0); + write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, -1, 0); + /* harmless for older blender versioins but _not_ writing these keeps file size down */ + /* + write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, -1, 0); + write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, -1, 0); + */ + + /* restore */ + mesh->mpoly = backup_mesh.mpoly; + mesh->totface = backup_mesh.totface; + mesh->totpoly = backup_mesh.totpoly; + mesh->totloop = backup_mesh.totloop; + /* -- */ + mesh->mface = backup_mesh.mface; + /* -- */ + CustomData_free(&mesh->fdata, mesh->totface); + /* -- */ + mesh->fdata= backup_mesh.fdata; + /* -- */ + mesh->pdata= backup_mesh.pdata; + /* -- */ + mesh->ldata= backup_mesh.ldata; + /* -- */ + mesh_update_customdata_pointers(mesh, FALSE); + /* --*/ + mesh->edit_btmesh = backup_mesh.edit_btmesh; /* keep this after updating custom pointers */ + /* restore */ + +#endif /* USE_MESH_FORWARDS_COMAT */ + } } mesh= mesh->id.next; } diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index 20517000068..bb8c6083ea1 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -209,4 +209,8 @@ typedef struct TFace { #define MESH_MAX_VERTS 2000000000L +/* this is so we can save bmesh files that load in trunk, ignoring NGons + * will eventually be removed */ +#define USE_MESH_FORWARDS_COMAT + #endif diff --git a/source/blender/modifiers/intern/MOD_ngoninterp.c b/source/blender/modifiers/intern/MOD_ngoninterp.c index 60833463d2f..54e46fc0956 100644 --- a/source/blender/modifiers/intern/MOD_ngoninterp.c +++ b/source/blender/modifiers/intern/MOD_ngoninterp.c @@ -226,7 +226,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob), MPoly *mp = mpoly + *of; MLoop *ml; float co[3], cent[3] = {0.0f, 0.0f, 0.0f}; - int j, lindex[3] = {0, 1, 2}; + int j, lindex[4] = {0, 1, 2}; /* only ever use 3 in this case */ BLI_array_empty(w); BLI_array_empty(cos); @@ -262,7 +262,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob), interp_weights_poly_v3(w, cos, mp->totloop, co); CustomData_interp(&dm->loopData, &dummy->loopData, loops, w, NULL, mp->totloop, 2); - mesh_loops_to_tri_corners(&cddm->faceData, &dummy->loopData, &dm->polyData, lindex, i, origf[i]); + mesh_loops_to_mface_corners(&cddm->faceData, &dummy->loopData, &dm->polyData, lindex, i, origf[i], 3); } CustomData_copy_data(&dm->vertData, &cddm->vertData, 0, 0, dm->numVertData); |