option to save bmesh files in older mesh format so they can load in older versoons of blender.

- 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.
This commit is contained in:
Campbell Barton
2011-12-27 08:39:55 +00:00
parent dab71f9b12
commit de14457abf
5 changed files with 246 additions and 35 deletions

View 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
}

View 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
*

View 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;
}

View 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

View 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);