Cleaned up a bit the indentation and added support for saving line mesh in OBJ
This commit is contained in:
parent
c5549f607a
commit
636f818107
|
@ -8,7 +8,7 @@
|
||||||
* \ *
|
* \ *
|
||||||
* All rights reserved. *
|
* All rights reserved. *
|
||||||
* *
|
* *
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU General Public License as published by *
|
* it under the terms of the GNU General Public License as published by *
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
* (at your option) any later version. *
|
* (at your option) any later version. *
|
||||||
|
@ -37,369 +37,366 @@ namespace vcg {
|
||||||
namespace tri {
|
namespace tri {
|
||||||
namespace io {
|
namespace io {
|
||||||
|
|
||||||
template <class SaveMeshType>
|
template <class SaveMeshType>
|
||||||
class ExporterOBJ
|
class ExporterOBJ
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef typename SaveMeshType::FaceIterator FaceIterator;
|
typedef typename SaveMeshType::FaceIterator FaceIterator;
|
||||||
typedef typename SaveMeshType::VertexIterator VertexIterator;
|
typedef typename SaveMeshType::EdgeIterator EdgeIterator;
|
||||||
typedef typename SaveMeshType::VertexType VertexType;
|
typedef typename SaveMeshType::VertexIterator VertexIterator;
|
||||||
typedef typename SaveMeshType::ScalarType ScalarType;
|
typedef typename SaveMeshType::VertexType VertexType;
|
||||||
typedef typename SaveMeshType::CoordType CoordType;
|
typedef typename SaveMeshType::ScalarType ScalarType;
|
||||||
/*
|
typedef typename SaveMeshType::CoordType CoordType;
|
||||||
enum of all the types of error
|
/*
|
||||||
*/
|
enum of all the types of error
|
||||||
enum SaveError
|
*/
|
||||||
{
|
enum SaveError
|
||||||
E_NOERROR, // 0
|
{
|
||||||
E_CANTOPENFILE, // 1
|
E_NOERROR, // 0
|
||||||
E_CANTCLOSEFILE, // 2
|
E_CANTOPENFILE, // 1
|
||||||
E_UNESPECTEDEOF, // 3
|
E_CANTCLOSEFILE, // 2
|
||||||
E_ABORTED, // 4
|
E_UNESPECTEDEOF, // 3
|
||||||
E_NOTDEFINITION, // 5
|
E_ABORTED, // 4
|
||||||
E_NOTVEXTEXVALID, // 6
|
E_NOTDEFINITION, // 5
|
||||||
E_NOTFACESVALID // 7
|
E_NOTVEXTEXVALID, // 6
|
||||||
};
|
E_NOTFACESVALID // 7
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
this function takes an index and the relative error message gets back
|
this function takes an index and the relative error message gets back
|
||||||
*/
|
*/
|
||||||
static const char* ErrorMsg(int error)
|
static const char* ErrorMsg(int error)
|
||||||
{
|
{
|
||||||
static const char* obj_error_msg[] =
|
static const char* obj_error_msg[] =
|
||||||
{
|
{
|
||||||
"No errors", // 0
|
"No errors", // 0
|
||||||
"Can't open file", // 1
|
"Can't open file", // 1
|
||||||
"can't close file", // 2
|
"can't close file", // 2
|
||||||
"Premature End of file", // 3
|
"Premature End of file", // 3
|
||||||
"File saving aborted", // 4
|
"File saving aborted", // 4
|
||||||
"Function not defined", // 5
|
"Function not defined", // 5
|
||||||
"Vertices not valid", // 6
|
"Vertices not valid", // 6
|
||||||
"Faces not valid" // 7
|
"Faces not valid" // 7
|
||||||
};
|
};
|
||||||
|
|
||||||
if(error>7 || error<0) return "Unknown error";
|
if(error>7 || error<0) return "Unknown error";
|
||||||
else return obj_error_msg[error];
|
else return obj_error_msg[error];
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
returns mask of capability one define with what are the saveable information of the format.
|
returns mask of capability one define with what are the saveable information of the format.
|
||||||
*/
|
*/
|
||||||
static int GetExportMaskCapability()
|
static int GetExportMaskCapability()
|
||||||
{
|
{
|
||||||
int capability = 0;
|
int capability = 0;
|
||||||
|
|
||||||
//vert
|
|
||||||
capability |= vcg::tri::io::Mask::IOM_VERTNORMAL;
|
|
||||||
capability |= vcg::tri::io::Mask::IOM_VERTTEXCOORD;
|
|
||||||
capability |= vcg::tri::io::Mask::IOM_VERTCOLOR;
|
|
||||||
|
|
||||||
//face
|
//vert
|
||||||
capability |= vcg::tri::io::Mask::IOM_FACECOLOR;
|
capability |= vcg::tri::io::Mask::IOM_VERTNORMAL;
|
||||||
|
capability |= vcg::tri::io::Mask::IOM_VERTTEXCOORD;
|
||||||
|
capability |= vcg::tri::io::Mask::IOM_VERTCOLOR;
|
||||||
|
|
||||||
//wedg
|
//face
|
||||||
capability |= vcg::tri::io::Mask::IOM_WEDGTEXCOORD;
|
capability |= vcg::tri::io::Mask::IOM_FACECOLOR;
|
||||||
capability |= vcg::tri::io::Mask::IOM_WEDGNORMAL;
|
|
||||||
|
|
||||||
return capability;
|
capability |= vcg::tri::io::Mask::IOM_EDGEINDEX;
|
||||||
}
|
//wedg
|
||||||
|
capability |= vcg::tri::io::Mask::IOM_WEDGTEXCOORD;
|
||||||
|
capability |= vcg::tri::io::Mask::IOM_WEDGNORMAL;
|
||||||
|
|
||||||
/*
|
return capability;
|
||||||
function which saves in OBJ file format
|
}
|
||||||
*/
|
|
||||||
static int Save(SaveMeshType &m, const char * filename, int mask, CallBackPos *cb=0)
|
|
||||||
{
|
|
||||||
// texture coord and normal: cannot be saved BOTH per vertex and per wedge
|
|
||||||
if (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD &&
|
|
||||||
mask & vcg::tri::io::Mask::IOM_VERTTEXCOORD ) {
|
|
||||||
mask &= ~vcg::tri::io::Mask::IOM_VERTTEXCOORD;
|
|
||||||
}
|
|
||||||
if (mask & vcg::tri::io::Mask::IOM_WEDGCOLOR &&
|
|
||||||
mask & vcg::tri::io::Mask::IOM_VERTCOLOR ) {
|
|
||||||
mask &= ~vcg::tri::io::Mask::IOM_VERTCOLOR;
|
|
||||||
}
|
|
||||||
if(m.vn == 0) return E_NOTVEXTEXVALID;
|
|
||||||
// Commented out this control. You should be allowed to save a point cloud.
|
|
||||||
// if(m.fn == 0) return E_NOTFACESVALID;
|
|
||||||
|
|
||||||
int current = 0;
|
/*
|
||||||
int totalPrimitives = m.vn+m.fn;
|
function which saves in OBJ file format
|
||||||
|
*/
|
||||||
std::vector<Material> materialVec;
|
static int Save(SaveMeshType &m, const char * filename, int mask, CallBackPos *cb=0)
|
||||||
|
{
|
||||||
std::string fn(filename);
|
// texture coord and normal: cannot be saved BOTH per vertex and per wedge
|
||||||
int LastSlash=fn.size()-1;
|
if (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD &&
|
||||||
while(LastSlash>=0 && fn[LastSlash]!='/')
|
mask & vcg::tri::io::Mask::IOM_VERTTEXCOORD ) {
|
||||||
--LastSlash;
|
mask &= ~vcg::tri::io::Mask::IOM_VERTTEXCOORD;
|
||||||
|
}
|
||||||
|
if (mask & vcg::tri::io::Mask::IOM_WEDGCOLOR &&
|
||||||
|
mask & vcg::tri::io::Mask::IOM_VERTCOLOR ) {
|
||||||
|
mask &= ~vcg::tri::io::Mask::IOM_VERTCOLOR;
|
||||||
|
}
|
||||||
|
if(m.vn == 0) return E_NOTVEXTEXVALID;
|
||||||
|
// Commented out this control. You should be allowed to save a point cloud.
|
||||||
|
// if(m.fn == 0) return E_NOTFACESVALID;
|
||||||
|
|
||||||
FILE *fp;
|
int current = 0;
|
||||||
fp = fopen(filename,"w");
|
int totalPrimitives = m.vn+m.fn;
|
||||||
if(fp == NULL) return E_CANTOPENFILE;
|
|
||||||
|
|
||||||
fprintf(fp,"####\n#\n# OBJ File Generated by Meshlab\n#\n####\n");
|
std::vector<Material> materialVec;
|
||||||
fprintf(fp,"# Object %s\n#\n# Vertices: %d\n# Faces: %d\n#\n####\n",fn.substr(LastSlash+1).c_str(),m.vn,m.fn);
|
|
||||||
|
std::string fn(filename);
|
||||||
//library materialVec
|
int LastSlash=fn.size()-1;
|
||||||
if( (mask & vcg::tri::io::Mask::IOM_FACECOLOR) || (mask & Mask::IOM_WEDGTEXCOORD) )
|
while(LastSlash>=0 && fn[LastSlash]!='/')
|
||||||
fprintf(fp,"mtllib ./%s.mtl\n\n",fn.substr(LastSlash+1).c_str());
|
--LastSlash;
|
||||||
|
|
||||||
//vertexs + normal
|
FILE *fp;
|
||||||
VertexIterator vi;
|
fp = fopen(filename,"w");
|
||||||
std::map<CoordType,int> NormalVertex;
|
if(fp == NULL) return E_CANTOPENFILE;
|
||||||
std::vector<int> VertexId(m.vert.size());
|
|
||||||
int numvert = 0;
|
fprintf(fp,"####\n#\n# OBJ File Generated by Meshlab\n#\n####\n");
|
||||||
int curNormalIndex = 1;
|
fprintf(fp,"# Object %s\n#\n# Vertices: %d\n# Faces: %d\n#\n####\n",fn.substr(LastSlash+1).c_str(),m.vn,m.fn);
|
||||||
for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi) if( !(*vi).IsD() )
|
|
||||||
{
|
//library materialVec
|
||||||
VertexId[vi-m.vert.begin()]=numvert;
|
if( (mask & vcg::tri::io::Mask::IOM_FACECOLOR) || (mask & Mask::IOM_WEDGTEXCOORD) )
|
||||||
//saves normal per vertex
|
fprintf(fp,"mtllib ./%s.mtl\n\n",fn.substr(LastSlash+1).c_str());
|
||||||
if (mask & Mask::IOM_WEDGNORMAL )
|
|
||||||
{
|
//vertexs + normal
|
||||||
if(AddNewNormalVertex(NormalVertex,(*vi).N(),curNormalIndex))
|
VertexIterator vi;
|
||||||
{
|
std::map<CoordType,int> NormalVertex;
|
||||||
fprintf(fp,"vn %f %f %f\n",(*vi).N()[0],(*vi).N()[1],(*vi).N()[2]);
|
std::vector<int> VertexId(m.vert.size());
|
||||||
curNormalIndex++;
|
int numvert = 0;
|
||||||
}
|
int curNormalIndex = 1;
|
||||||
}
|
for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi) if( !(*vi).IsD() )
|
||||||
if (mask & Mask::IOM_VERTNORMAL ) {
|
{
|
||||||
|
VertexId[vi-m.vert.begin()]=numvert;
|
||||||
|
//saves normal per vertex
|
||||||
|
if (mask & Mask::IOM_WEDGNORMAL )
|
||||||
|
{
|
||||||
|
if(AddNewNormalVertex(NormalVertex,(*vi).N(),curNormalIndex))
|
||||||
|
{
|
||||||
fprintf(fp,"vn %f %f %f\n",(*vi).N()[0],(*vi).N()[1],(*vi).N()[2]);
|
fprintf(fp,"vn %f %f %f\n",(*vi).N()[0],(*vi).N()[1],(*vi).N()[2]);
|
||||||
|
curNormalIndex++;
|
||||||
}
|
}
|
||||||
if (mask & Mask::IOM_VERTTEXCOORD ) {
|
}
|
||||||
fprintf(fp,"vt %f %f\n",(*vi).T().P()[0],(*vi).T().P()[1]);
|
if (mask & Mask::IOM_VERTNORMAL ) {
|
||||||
|
fprintf(fp,"vn %f %f %f\n",(*vi).N()[0],(*vi).N()[1],(*vi).N()[2]);
|
||||||
|
}
|
||||||
|
if (mask & Mask::IOM_VERTTEXCOORD ) {
|
||||||
|
fprintf(fp,"vt %f %f\n",(*vi).T().P()[0],(*vi).T().P()[1]);
|
||||||
|
}
|
||||||
|
//if (mask & Mask::IOM_VERTCOLOR ) {
|
||||||
|
// fprintf(fp,"vc %f %f %f\n",(*vi).T().P()[0],(*vi).T().P()[1]);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//saves vertex
|
||||||
|
|
||||||
|
fprintf(fp,"v %f %f %f",(*vi).P()[0],(*vi).P()[1],(*vi).P()[2]);
|
||||||
|
if(mask & Mask::IOM_VERTCOLOR)
|
||||||
|
fprintf(fp," %f %f %f",double((*vi).C()[0])/255.,double((*vi).C()[1])/255.,double((*vi).C()[2])/255.);
|
||||||
|
fprintf(fp,"\n");
|
||||||
|
|
||||||
|
if (cb !=NULL)
|
||||||
|
{
|
||||||
|
if(!(*cb)((100*++current)/totalPrimitives, "writing vertices "))
|
||||||
|
{
|
||||||
|
fclose(fp);
|
||||||
|
return E_ABORTED;
|
||||||
}
|
}
|
||||||
//if (mask & Mask::IOM_VERTCOLOR ) {
|
}
|
||||||
// fprintf(fp,"vc %f %f %f\n",(*vi).T().P()[0],(*vi).T().P()[1]);
|
numvert++;
|
||||||
//}
|
}
|
||||||
|
assert(numvert == m.vn);
|
||||||
|
|
||||||
//saves vertex
|
fprintf(fp,"# %d vertices, %d vertices normals\n\n",m.vn,int(NormalVertex.size()));
|
||||||
|
|
||||||
fprintf(fp,"v %f %f %f",(*vi).P()[0],(*vi).P()[1],(*vi).P()[2]);
|
|
||||||
if(mask & Mask::IOM_VERTCOLOR)
|
|
||||||
fprintf(fp," %f %f %f",double((*vi).C()[0])/255.,double((*vi).C()[1])/255.,double((*vi).C()[2])/255.);
|
|
||||||
fprintf(fp,"\n");
|
|
||||||
|
|
||||||
if (cb !=NULL)
|
//faces + texture coords
|
||||||
{
|
std::map<vcg::TexCoord2<ScalarType>,int> CoordIndexTexture;
|
||||||
if(!(*cb)((100*++current)/totalPrimitives, "writing vertices "))
|
unsigned int material_num = 0;
|
||||||
{
|
int mem_index = 0; //var temporany
|
||||||
fclose(fp);
|
int curTexCoordIndex = 1;
|
||||||
return E_ABORTED;
|
for(FaceIterator fi=m.face.begin(); fi!=m.face.end(); ++fi) if( !(*fi).IsD() )
|
||||||
}
|
{
|
||||||
}
|
if((mask & Mask::IOM_FACECOLOR) || (mask & Mask::IOM_WEDGTEXCOORD) )
|
||||||
numvert++;
|
{
|
||||||
}
|
int index = Materials<SaveMeshType>::CreateNewMaterial(m,materialVec,material_num,fi);
|
||||||
assert(numvert == m.vn);
|
|
||||||
|
|
||||||
fprintf(fp,"# %d vertices, %d vertices normals\n\n",m.vn,int(NormalVertex.size()));
|
if(index == (int)materialVec.size())//inserts a new element material
|
||||||
|
{
|
||||||
//faces + texture coords
|
material_num++;
|
||||||
FaceIterator fi;
|
fprintf(fp,"\nusemtl material_%d\n",materialVec[index-1].index);
|
||||||
std::map<vcg::TexCoord2<ScalarType>,int> CoordIndexTexture;
|
mem_index = index-1;
|
||||||
unsigned int material_num = 0;
|
}
|
||||||
int mem_index = 0; //var temporany
|
else
|
||||||
int curTexCoordIndex = 1;
|
{
|
||||||
for(fi=m.face.begin(); fi!=m.face.end(); ++fi) if( !(*fi).IsD() )
|
if(index != mem_index)//inserts old name elemente material
|
||||||
{
|
{
|
||||||
if((mask & Mask::IOM_FACECOLOR) || (mask & Mask::IOM_WEDGTEXCOORD) )
|
fprintf(fp,"\nusemtl material_%d\n",materialVec[index].index);
|
||||||
{
|
mem_index=index;
|
||||||
int index = Materials<SaveMeshType>::CreateNewMaterial(m,materialVec,material_num,fi);
|
}
|
||||||
|
}
|
||||||
if(index == (int)materialVec.size())//inserts a new element material
|
}
|
||||||
{
|
|
||||||
material_num++;
|
|
||||||
fprintf(fp,"\nusemtl material_%d\n",materialVec[index-1].index);
|
|
||||||
mem_index = index-1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(index != mem_index)//inserts old name elemente material
|
|
||||||
{
|
|
||||||
fprintf(fp,"\nusemtl material_%d\n",materialVec[index].index);
|
|
||||||
mem_index=index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//saves texture coord x wedge
|
//saves texture coord x wedge
|
||||||
if(HasPerWedgeTexCoord(m) && (mask & Mask::IOM_WEDGTEXCOORD))
|
if(HasPerWedgeTexCoord(m) && (mask & Mask::IOM_WEDGTEXCOORD))
|
||||||
for(int k=0;k<(*fi).VN();k++)
|
for(int k=0;k<(*fi).VN();k++)
|
||||||
{
|
{
|
||||||
{
|
if(AddNewTextureCoord(CoordIndexTexture,(*fi).WT(k),curTexCoordIndex))
|
||||||
if(AddNewTextureCoord(CoordIndexTexture,(*fi).WT(k),curTexCoordIndex))
|
{
|
||||||
{
|
fprintf(fp,"vt %f %f\n",(*fi).WT(k).u(),(*fi).WT(k).v());
|
||||||
fprintf(fp,"vt %f %f\n",(*fi).WT(k).u(),(*fi).WT(k).v());
|
curTexCoordIndex++; //ncreases the value number to be associated to the Texture
|
||||||
curTexCoordIndex++; //ncreases the value number to be associated to the Texture
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fprintf(fp,"f ");
|
|
||||||
for(int k=0;k<(*fi).VN();k++)
|
|
||||||
{
|
|
||||||
if(k!=0) fprintf(fp," ");
|
|
||||||
int vInd = -1;
|
|
||||||
// +1 because Obj file format begins from index = 1 but not from index = 0.
|
|
||||||
vInd = VertexId[GetIndexVertex(m, (*fi).V(k))] + 1;//index of vertex per face
|
|
||||||
|
|
||||||
int vt = -1;
|
|
||||||
if(mask & Mask::IOM_WEDGTEXCOORD)
|
|
||||||
vt = GetIndexVertexTexture(CoordIndexTexture,(*fi).WT(k));//index of vertex texture per face
|
|
||||||
if (mask & Mask::IOM_VERTTEXCOORD)
|
|
||||||
vt = vInd;
|
|
||||||
|
|
||||||
int vn = -1;
|
|
||||||
if(mask & Mask::IOM_WEDGNORMAL )
|
|
||||||
vn = GetIndexVertexNormal(m, NormalVertex, (*fi).V(k)->cN());//index of vertex normal per face.
|
|
||||||
if (mask & Mask::IOM_VERTNORMAL)
|
|
||||||
vn = vInd;
|
|
||||||
|
|
||||||
//writes elements on file obj
|
|
||||||
WriteFacesElement(fp,vInd,vt,vn);
|
|
||||||
}
|
|
||||||
fprintf(fp,"\n");
|
|
||||||
if (cb !=NULL) {
|
|
||||||
if(!(*cb)((100*++current)/totalPrimitives, "writing vertices "))
|
|
||||||
{ fclose(fp); return E_ABORTED;}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}//for
|
|
||||||
fprintf(fp,"# %d faces, %d coords texture\n\n",m.fn,int(CoordIndexTexture.size()));
|
|
||||||
|
|
||||||
fprintf(fp,"# End of File\n");
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
int r = 0;
|
fprintf(fp,"f ");
|
||||||
if((mask & Mask::IOM_WEDGTEXCOORD) || (mask & Mask::IOM_FACECOLOR) )
|
for(int k=0;k<(*fi).VN();k++)
|
||||||
r = WriteMaterials(materialVec, filename,cb);//write material
|
{
|
||||||
|
if(k!=0) fprintf(fp," ");
|
||||||
if(r!= E_NOERROR)
|
int vInd = -1;
|
||||||
return r;
|
// +1 because Obj file format begins from index = 1 but not from index = 0.
|
||||||
return E_NOERROR;
|
vInd = VertexId[tri::Index(m, (*fi).V(k))] + 1;//index of vertex per face
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
int vt = -1;
|
||||||
returns index of the vertex
|
if(mask & Mask::IOM_WEDGTEXCOORD)
|
||||||
*/
|
vt = GetIndexVertexTexture(CoordIndexTexture,(*fi).WT(k));//index of vertex texture per face
|
||||||
inline static int GetIndexVertex(SaveMeshType &m, VertexType *p)
|
if (mask & Mask::IOM_VERTTEXCOORD)
|
||||||
{
|
vt = vInd;
|
||||||
return p-&*(m.vert.begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
returns index of the texture coord
|
|
||||||
*/
|
|
||||||
inline static int GetIndexVertexTexture(typename std::map<TexCoord2<ScalarType>,int> &mapTexToInt, const vcg::TexCoord2<ScalarType> &wt)
|
|
||||||
{
|
|
||||||
typename std::map<vcg::TexCoord2<ScalarType>,int>::iterator iter= mapTexToInt.find(wt);
|
|
||||||
if(iter != mapTexToInt.end()) return (*iter).second;
|
|
||||||
else return -1;
|
|
||||||
// Old wrong version.
|
|
||||||
// int index = mapTexToInt[wt];
|
|
||||||
// if(index!=0){return index;}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
int vn = -1;
|
||||||
returns index of the vertex normal
|
if(mask & Mask::IOM_WEDGNORMAL )
|
||||||
*/
|
vn = GetIndexVertexNormal(m, NormalVertex, (*fi).V(k)->cN());//index of vertex normal per face.
|
||||||
inline static int GetIndexVertexNormal(SaveMeshType &/*m*/, std::map<CoordType,int> &mapNormToInt, const CoordType &norm )
|
if (mask & Mask::IOM_VERTNORMAL)
|
||||||
{
|
vn = vInd;
|
||||||
typename std::map<CoordType,int>::iterator iter= mapNormToInt.find(norm);
|
|
||||||
if(iter != mapNormToInt.end()) return (*iter).second;
|
|
||||||
else return -1;
|
|
||||||
// Old wrong version.
|
|
||||||
// int index = mapNormToInt[m.vert[iv].N()];
|
|
||||||
// if(index!=0){return index;}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
write elements on file
|
|
||||||
|
|
||||||
f v/tc/vn v/tc/vn v/tc/vn ...
|
|
||||||
f v/tc v/tc v/tc ...
|
|
||||||
f v//vn v//vn v//vn ...
|
|
||||||
f v v v ...
|
|
||||||
|
|
||||||
*/
|
|
||||||
inline static void WriteFacesElement(FILE *fp,int v,int vt, int vn)
|
|
||||||
{
|
|
||||||
fprintf(fp,"%d",v);
|
|
||||||
if(vt!=-1)
|
|
||||||
{
|
|
||||||
fprintf(fp,"/%d",vt);
|
|
||||||
if(vn!=-1)
|
|
||||||
fprintf(fp,"/%d",vn);
|
|
||||||
}
|
|
||||||
else if(vn!=-1)
|
|
||||||
fprintf(fp,"//%d",vn);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
adds a new index to the coordinate of Texture if it is the first time
|
|
||||||
which is otherwise met not execute anything
|
|
||||||
*/
|
|
||||||
inline static bool AddNewTextureCoord(std::map<typename vcg::TexCoord2<ScalarType>,int> &m,
|
|
||||||
const typename vcg::TexCoord2<ScalarType> &wt,int value)
|
|
||||||
{
|
|
||||||
int index = m[wt];
|
|
||||||
if(index==0){m[wt]=value;return true;}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
//writes elements on file obj
|
||||||
adds a new index to the normal per vertex if it is the first time
|
WriteFacesElement(fp,vInd,vt,vn);
|
||||||
which is otherwise met does not execute anything
|
}
|
||||||
*/
|
fprintf(fp,"\n");
|
||||||
inline static bool AddNewNormalVertex(typename std::map<CoordType,int> &m, CoordType &n ,int value)
|
|
||||||
{
|
|
||||||
int index = m[n];
|
|
||||||
if(index==0){m[n]=value;return true;}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
writes material into file
|
|
||||||
*/
|
|
||||||
inline static int WriteMaterials(std::vector<Material> &materialVec, const char * filename, CallBackPos *cb=0)
|
|
||||||
{
|
|
||||||
std::string fileName = std::string(filename);
|
|
||||||
fileName+=".mtl";
|
|
||||||
|
|
||||||
if(materialVec.size() > 0)
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
fp = fopen(fileName.c_str(),"w");
|
|
||||||
if(fp==NULL)return E_ABORTED;
|
|
||||||
|
|
||||||
fprintf(fp,"#\n# Wavefront material file\n# Converted by Meshlab Group\n#\n\n");
|
|
||||||
|
|
||||||
int current = 0;
|
|
||||||
|
|
||||||
for(unsigned int i=0;i<materialVec.size();i++)
|
if (cb !=NULL) {
|
||||||
{
|
if(!(*cb)((100*++current)/totalPrimitives, "writing vertices "))
|
||||||
if (cb !=NULL)
|
{ fclose(fp); return E_ABORTED;}
|
||||||
(*cb)((100 * ++current)/materialVec.size(), "saving material file ");
|
}
|
||||||
else
|
|
||||||
{ /* fclose(fp); return E_ABORTED; */ }
|
|
||||||
|
|
||||||
fprintf(fp,"newmtl material_%d\n",materialVec[i].index);
|
}//for faces
|
||||||
fprintf(fp,"Ka %f %f %f\n",materialVec[i].Ka[0],materialVec[i].Ka[1],materialVec[i].Ka[2]);
|
|
||||||
fprintf(fp,"Kd %f %f %f\n",materialVec[i].Kd[0],materialVec[i].Kd[1],materialVec[i].Kd[2]);
|
|
||||||
fprintf(fp,"Ks %f %f %f\n",materialVec[i].Ks[0],materialVec[i].Ks[1],materialVec[i].Ks[2]);
|
|
||||||
fprintf(fp,"Tr %f\n",materialVec[i].Tr);
|
|
||||||
fprintf(fp,"illum %d\n",materialVec[i].illum);
|
|
||||||
fprintf(fp,"Ns %f\n",materialVec[i].Ns);
|
|
||||||
|
|
||||||
if(materialVec[i].map_Kd.size()>0)
|
for(EdgeIterator ei=m.edge.begin(); ei!=m.edge.end(); ++ei) if( !(*ei).IsD() )
|
||||||
fprintf(fp,"map_Kd %s\n",materialVec[i].map_Kd.c_str());
|
{
|
||||||
fprintf(fp,"\n");
|
fprintf(fp,"l %i %i\n",
|
||||||
}
|
VertexId[tri::Index(m, (*ei).V(0))] + 1,
|
||||||
fclose(fp);
|
VertexId[tri::Index(m, (*ei).V(1))] + 1);
|
||||||
}
|
}
|
||||||
return E_NOERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
}; // end class
|
fprintf(fp,"# %d faces, %d coords texture\n\n",m.fn,int(CoordIndexTexture.size()));
|
||||||
|
|
||||||
|
fprintf(fp,"# End of File\n");
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
int errCode = E_NOERROR;
|
||||||
|
if((mask & Mask::IOM_WEDGTEXCOORD) || (mask & Mask::IOM_FACECOLOR) )
|
||||||
|
errCode = WriteMaterials(materialVec, filename,cb);//write material
|
||||||
|
|
||||||
|
if(errCode!= E_NOERROR)
|
||||||
|
return errCode;
|
||||||
|
return E_NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
returns index of the texture coord
|
||||||
|
*/
|
||||||
|
inline static int GetIndexVertexTexture(typename std::map<TexCoord2<ScalarType>,int> &mapTexToInt, const vcg::TexCoord2<ScalarType> &wt)
|
||||||
|
{
|
||||||
|
typename std::map<vcg::TexCoord2<ScalarType>,int>::iterator iter= mapTexToInt.find(wt);
|
||||||
|
if(iter != mapTexToInt.end()) return (*iter).second;
|
||||||
|
else return -1;
|
||||||
|
// Old wrong version.
|
||||||
|
// int index = mapTexToInt[wt];
|
||||||
|
// if(index!=0){return index;}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
returns index of the vertex normal
|
||||||
|
*/
|
||||||
|
inline static int GetIndexVertexNormal(SaveMeshType &/*m*/, std::map<CoordType,int> &mapNormToInt, const CoordType &norm )
|
||||||
|
{
|
||||||
|
typename std::map<CoordType,int>::iterator iter= mapNormToInt.find(norm);
|
||||||
|
if(iter != mapNormToInt.end()) return (*iter).second;
|
||||||
|
else return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
write elements on file
|
||||||
|
|
||||||
|
f v/tc/vn v/tc/vn v/tc/vn ...
|
||||||
|
f v/tc v/tc v/tc ...
|
||||||
|
f v//vn v//vn v//vn ...
|
||||||
|
f v v v ...
|
||||||
|
|
||||||
|
*/
|
||||||
|
inline static void WriteFacesElement(FILE *fp,int v,int vt, int vn)
|
||||||
|
{
|
||||||
|
fprintf(fp,"%d",v);
|
||||||
|
if(vt!=-1)
|
||||||
|
{
|
||||||
|
fprintf(fp,"/%d",vt);
|
||||||
|
if(vn!=-1)
|
||||||
|
fprintf(fp,"/%d",vn);
|
||||||
|
}
|
||||||
|
else if(vn!=-1)
|
||||||
|
fprintf(fp,"//%d",vn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
adds a new index to the coordinate of Texture if it is the first time
|
||||||
|
which is otherwise met not execute anything
|
||||||
|
*/
|
||||||
|
inline static bool AddNewTextureCoord(std::map<typename vcg::TexCoord2<ScalarType>,int> &m,
|
||||||
|
const typename vcg::TexCoord2<ScalarType> &wt,int value)
|
||||||
|
{
|
||||||
|
int index = m[wt];
|
||||||
|
if(index==0){m[wt]=value;return true;}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
adds a new index to the normal per vertex if it is the first time
|
||||||
|
which is otherwise met does not execute anything
|
||||||
|
*/
|
||||||
|
inline static bool AddNewNormalVertex(typename std::map<CoordType,int> &m, CoordType &n ,int value)
|
||||||
|
{
|
||||||
|
int index = m[n];
|
||||||
|
if(index==0){m[n]=value;return true;}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
writes material into file
|
||||||
|
*/
|
||||||
|
inline static int WriteMaterials(std::vector<Material> &materialVec, const char * filename, CallBackPos *cb=0)
|
||||||
|
{
|
||||||
|
std::string fileName = std::string(filename);
|
||||||
|
fileName+=".mtl";
|
||||||
|
|
||||||
|
if(materialVec.size() > 0)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
fp = fopen(fileName.c_str(),"w");
|
||||||
|
if(fp==NULL)return E_ABORTED;
|
||||||
|
|
||||||
|
fprintf(fp,"#\n# Wavefront material file\n# Converted by Meshlab Group\n#\n\n");
|
||||||
|
|
||||||
|
int current = 0;
|
||||||
|
|
||||||
|
for(unsigned int i=0;i<materialVec.size();i++)
|
||||||
|
{
|
||||||
|
if (cb !=NULL)
|
||||||
|
(*cb)((100 * ++current)/materialVec.size(), "saving material file ");
|
||||||
|
else
|
||||||
|
{ /* fclose(fp); return E_ABORTED; */ }
|
||||||
|
|
||||||
|
fprintf(fp,"newmtl material_%d\n",materialVec[i].index);
|
||||||
|
fprintf(fp,"Ka %f %f %f\n",materialVec[i].Ka[0],materialVec[i].Ka[1],materialVec[i].Ka[2]);
|
||||||
|
fprintf(fp,"Kd %f %f %f\n",materialVec[i].Kd[0],materialVec[i].Kd[1],materialVec[i].Kd[2]);
|
||||||
|
fprintf(fp,"Ks %f %f %f\n",materialVec[i].Ks[0],materialVec[i].Ks[1],materialVec[i].Ks[2]);
|
||||||
|
fprintf(fp,"Tr %f\n",materialVec[i].Tr);
|
||||||
|
fprintf(fp,"illum %d\n",materialVec[i].illum);
|
||||||
|
fprintf(fp,"Ns %f\n",materialVec[i].Ns);
|
||||||
|
|
||||||
|
if(materialVec[i].map_Kd.size()>0)
|
||||||
|
fprintf(fp,"map_Kd %s\n",materialVec[i].map_Kd.c_str());
|
||||||
|
fprintf(fp,"\n");
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
return E_NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // end class
|
||||||
} // end Namespace tri
|
} // end Namespace tri
|
||||||
} // end Namespace io
|
} // end Namespace io
|
||||||
} // end Namespace vcg
|
} // end Namespace vcg
|
||||||
|
|
Loading…
Reference in New Issue