option to save bmesh files in older mesh format so they can load in older versoons...
authorCampbell Barton <ideasman42@gmail.com>
Tue, 27 Dec 2011 08:39:55 +0000 (08:39 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 27 Dec 2011 08:39:55 +0000 (08:39 +0000)
- saves UV's and VCols
- skips NGons
- resulting files load in both BMesh and Trunk.

TODO - add an option in the UI to access this.

source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/intern/mesh.c
source/blender/blenloader/intern/writefile.c
source/blender/makesdna/DNA_mesh_types.h
source/blender/modifiers/intern/MOD_ngoninterp.c

index e1eb34782ffc5f0fcefcc00b3f4bbea02f1fe2c9..9b5e38dfea7aba497d13158eb46f7ab5022b4beb 100644 (file)
@@ -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
 }
index 4ebcc528dac8de5fcc7b8057bde946a6d77cd3c7..d918e8a7e0b0e565c46383061c9ea435a5c69ded 100644 (file)
@@ -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
  *
index 0f10deed1f8c96d380d35e2821607cc90cde906c..eb4321c57ec4f95269c211783ca162e4d58f0bed 100644 (file)
@@ -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;
        }
index 205170000681f4eb632f066ed953d2d24ec841b2..bb8c6083ea15a2d931c71e7e67dd57c8b6029544 100644 (file)
@@ -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
index 60833463d2f70e14422a71ff6b518702ce3644cc..54e46fc095657e3bdd916abf821879b145a71175 100644 (file)
@@ -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);