diff --git a/wrap/io_trimesh/export_obj.h b/wrap/io_trimesh/export_obj.h index 6e00ca5f..0f96aeee 100644 --- a/wrap/io_trimesh/export_obj.h +++ b/wrap/io_trimesh/export_obj.h @@ -60,8 +60,9 @@ public: E_UNESPECTEDEOF, // 3 E_ABORTED, // 4 E_NOTDEFINITION, // 5 - E_NOTVEXTEXVALID, // 6 - E_NOTFACESVALID // 7 + E_NO_VERTICES, // 6 + E_NOTFACESVALID, // 7 + E_NO_VALID_MATERIAL }; /* @@ -78,7 +79,8 @@ public: "File saving aborted", // 4 "Function not defined", // 5 "Vertices not valid", // 6 - "Faces not valid" // 7 + "Faces not valid", // 7 + "The mesh has not a attribute containing the vector of materials" // 8 }; if(error>7 || error<0) return "Unknown error"; @@ -107,13 +109,20 @@ public: 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 + return Save(m,filename,mask,false,cb); + } + + /** + * main function to export a mesh in OBJ file format + * + * if you enable the useMaterialAttribute flag, the exporter will assume that the mesh has a consistent per mesh attribute and a per face attribute containing the index of the material + */ + static int Save(SaveMeshType &m, const char * filename, int mask, bool useMaterialAttribute ,CallBackPos *cb=0) + { + // texture coord and color: in obj we cannot save BOTH per vertex and per wedge information. We default on wedge if (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD && mask & vcg::tri::io::Mask::IOM_VERTTEXCOORD ) { mask &= ~vcg::tri::io::Mask::IOM_VERTTEXCOORD; @@ -122,39 +131,40 @@ public: 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; + if(m.vn == 0) return E_NO_VERTICES; + + typename SaveMeshType::template PerMeshAttributeHandle > materialVecHandle = + vcg::tri::Allocator::template FindPerMeshAttribute >(m, "materialVector"); + typename SaveMeshType::template PerFaceAttributeHandle materialIndexHandle = + vcg::tri::Allocator::template FindPerFaceAttribute(m, "materialIndex"); + + if(useMaterialAttribute && (!Allocator::IsValidHandle(m,materialVecHandle)) && + (!Allocator::IsValidHandle(m,materialIndexHandle)) ) + return E_NO_VALID_MATERIAL; - int current = 0; - int totalPrimitives = m.vn+m.fn; - - typename SaveMeshType::template PerMeshAttributeHandle > materialsHandle = - vcg::tri::Allocator::template FindPerMeshAttribute >(m, "materials"); - - std::string fn(filename); - int LastSlash=fn.size()-1; - while(LastSlash>=0 && fn[LastSlash]!='/') - --LastSlash; - - FILE *fp; - fp = fopen(filename,"w"); + FILE *fp = fopen(filename,"w"); if(fp == NULL) return E_CANTOPENFILE; - + std::string shortFilename(filename); + int LastSlash=shortFilename.size()-1; + while(LastSlash>=0 && shortFilename[LastSlash]!='/') + --LastSlash; + shortFilename = shortFilename.substr(LastSlash+1); + fprintf(fp,"####\n#\n# OBJ File Generated by Meshlab\n#\n####\n"); - fprintf(fp,"# Object %s\n#\n# Vertices: %d\n# Faces: %d\n#\n####\n",fn.substr(LastSlash+1).c_str(),m.vn,m.fn); - + fprintf(fp,"# Object %s\n#\n# Vertices: %d\n# Faces: %d\n#\n####\n",shortFilename.c_str(),m.vn,m.fn); + //library materialVec if( (mask & vcg::tri::io::Mask::IOM_FACECOLOR) || (mask & Mask::IOM_WEDGTEXCOORD) || (mask & Mask::IOM_VERTTEXCOORD) ) - fprintf(fp,"mtllib ./%s.mtl\n\n",fn.substr(LastSlash+1).c_str()); + fprintf(fp,"mtllib ./%s.mtl\n\n",shortFilename.c_str()); - //vertexs + normal - VertexIterator vi; std::map NormalVertex; std::vector VertexId(m.vert.size()); int numvert = 0; int curNormalIndex = 1; - for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi) if( !(*vi).IsD() ) + int current = 0; + const int totalPrimitives = m.vn+m.fn; + /*********************************** VERTICES *********************************/ + for(auto vi=m.vert.begin(); vi!=m.vert.end(); ++vi) if( !(*vi).IsD() ) { VertexId[vi-m.vert.begin()]=numvert; //saves normal per vertex @@ -169,17 +179,14 @@ public: 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) + + if(mask & Mask::IOM_VERTCOLOR) // the socially accepted extension to the obj format. fprintf(fp," %f %f %f",double((*vi).C()[0])/255.,double((*vi).C()[1])/255.,double((*vi).C()[2])/255.); fprintf(fp,"\n"); @@ -194,20 +201,23 @@ public: numvert++; } assert(numvert == m.vn); - fprintf(fp,"# %d vertices, %d vertices normals\n\n",m.vn,int(NormalVertex.size())); + /********************* FACES ************************/ //faces + texture coords - typename SaveMeshType::template PerFaceAttributeHandle mIndHandle = - vcg::tri::Allocator::template FindPerFaceAttribute(m, "mInd"); std::map CoordIndexTexture; int curTexCoordIndex = 1; int curMatIndex = -1; + std::vector materialVec; //used if we do not have material attributes + for(FaceIterator fi=m.face.begin(); fi!=m.face.end(); ++fi) if( !(*fi).IsD() ) { if((mask & Mask::IOM_FACECOLOR) || (mask & Mask::IOM_WEDGTEXCOORD) || (mask & Mask::IOM_VERTTEXCOORD)) { - int index = mIndHandle[fi]; + int index=-1; + if(useMaterialAttribute) index = materialIndexHandle[fi]; + else index = Materials::CreateNewMaterial(m,materialVec,fi); + if(index != curMatIndex) { fprintf(fp,"\nusemtl material_%d\n", index); curMatIndex = index; @@ -225,7 +235,6 @@ public: } } - fprintf(fp,"f "); for(int k=0;k<(*fi).VN();k++) { @@ -256,7 +265,7 @@ public: { fclose(fp); return E_ABORTED;} } - }//for faces + } // end for faces for(EdgeIterator ei=m.edge.begin(); ei!=m.edge.end(); ++ei) if( !(*ei).IsD() ) { @@ -272,7 +281,10 @@ public: int errCode = E_NOERROR; if((mask & Mask::IOM_WEDGTEXCOORD) || (mask & Mask::IOM_FACECOLOR) || (mask & Mask::IOM_VERTTEXCOORD) ) - errCode = WriteMaterials(materialsHandle(), filename,cb);//write material + { + if(useMaterialAttribute) errCode = WriteMaterials(materialVecHandle(), filename,cb); + else errCode = WriteMaterials(materialVec, filename,cb); + } if(errCode!= E_NOERROR) return errCode; diff --git a/wrap/io_trimesh/import_obj.h b/wrap/io_trimesh/import_obj.h index 5cb9258c..9ad96174 100644 --- a/wrap/io_trimesh/import_obj.h +++ b/wrap/io_trimesh/import_obj.h @@ -257,9 +257,9 @@ namespace vcg { } typename OpenMeshType::template PerMeshAttributeHandle > materialsHandle = - vcg::tri::Allocator:: template GetPerMeshAttribute >(m, std::string("materials")); + vcg::tri::Allocator:: template GetPerMeshAttribute >(m, std::string("materialVector")); typename OpenMeshType::template PerFaceAttributeHandle mIndHandle = - vcg::tri::Allocator:: template GetPerFaceAttribute(m, std::string("mInd")); + vcg::tri::Allocator:: template GetPerFaceAttribute(m, std::string("materialIndex")); std::vector& materials = materialsHandle(); // materials vector std::vector texCoords; // texture coordinates std::vector normals; // vertex normals diff --git a/wrap/io_trimesh/io_material.h b/wrap/io_trimesh/io_material.h index 9ee74214..483b0f9e 100644 --- a/wrap/io_trimesh/io_material.h +++ b/wrap/io_trimesh/io_material.h @@ -23,30 +23,30 @@ /**************************************************************************** History - + $Log: not supported by cvs2svn $ Revision 1.5 2008/02/27 00:34:43 cignoni corrected various bugs in the export of texture coords - + Revision 1.4 2007/06/20 10:28:04 tarini "newline at end of file" and "endif" warnings fixed - + Revision 1.3 2006/11/09 07:51:44 cignoni bug due to wrong access to eventually unexistent FaceColor - + Revision 1.2 2006/10/09 19:58:08 cignoni Added casts to remove warnings - + Revision 1.1 2006/03/07 13:19:29 cignoni First Release with OBJ import support - + Revision 1.1 2006/02/16 19:28:36 fmazzant transfer of Export_3ds.h, Export_obj.h, Io_3ds_obj_material.h from Meshlab to vcg - + Revision 1.1 2006/02/06 11:04:40 fmazzant added file material.h. it include struct Material, CreateNewMaterial(...) and MaterialsCompare(...) - - + + ****************************************************************************/ #ifndef __VCGLIB_MATERIAL @@ -59,96 +59,91 @@ namespace vcg { namespace tri { namespace io { - - /* - structures material - */ - struct Material - { - unsigned int index;//index of material - std::string materialName; - Point3f Ka;//ambient - Point3f Kd;//diffuse - Point3f Ks;//specular - - float d;//alpha - float Tr;//alpha - - int illum;//specular illumination - float Ns; +/* + structures material + */ +struct Material +{ + unsigned int index;//index of material + std::string materialName; + + Point3f Ka;//ambient + Point3f Kd;//diffuse + Point3f Ks;//specular + + float d;//alpha + float Tr;//alpha + + int illum;//specular illumination + float Ns; + + std::string map_Kd; //filename texture +}; - std::string map_Kd; //filename texture - }; - - template - class Materials - { - public: - typedef typename SaveMeshType::FaceIterator FaceIterator; - typedef typename SaveMeshType::VertexIterator VertexIterator; - typedef typename SaveMeshType::VertexType VertexType; - - /* - creates a new meterial - */ - inline static int CreateNewMaterial(SaveMeshType &m, std::vector &materials, unsigned int index, FaceIterator &fi) - { - Point3f diffuse(1,1,1); - float Transp = 1; - if(HasPerFaceColor(m)){ - diffuse = Point3f((float)((*fi).C()[0])/255.0f,(float)((*fi).C()[1])/255.0f,(float)((*fi).C()[2])/255.0f);//diffuse - Transp = (float)((*fi).C()[3])/255.0f;//alpha - } - - int illum = 2; //default not use Ks! - float ns = 0.0; //default - - Material mtl; - - mtl.index = index;//index of materials - mtl.Ka = Point3f(0.2f,0.2f,0.2f);//ambient - mtl.Kd = diffuse;//diffuse - mtl.Ks = Point3f(1.0f,1.0f,1.0f);//specular - mtl.Tr = Transp;//alpha - mtl.Ns = ns; - mtl.illum = illum;//illumination - - if(m.textures.size() && (*fi).WT(0).n() >=0 ) - mtl.map_Kd = m.textures[(*fi).WT(0).n()]; - else - mtl.map_Kd = ""; - - int i = -1; - if((i = MaterialsCompare(materials,mtl)) == -1) - { - materials.push_back(mtl); - return materials.size(); - } - return i; - } - - /* - returns the index of the material if it exists inside the list of the materials, - otherwise it returns -1. - */ - inline static int MaterialsCompare(std::vector &materials, Material mtl) - { - for(unsigned int i=0;i +class Materials +{ +public: + typedef typename SaveMeshType::FaceIterator FaceIterator; + typedef typename SaveMeshType::VertexIterator VertexIterator; + typedef typename SaveMeshType::VertexType VertexType; + + /* + creates a new meterial + */ + inline static int CreateNewMaterial(SaveMeshType &m, std::vector &materials, FaceIterator &fi) + { + Material mtl; + mtl.index = -1; // index of materials + mtl.Ka = Point3f(0.2f,0.2f,0.2f); // ambient + mtl.Kd = Point3f(1,1,1); // diffuse + mtl.Ks = Point3f(1.0f,1.0f,1.0f); // specular + mtl.Tr = 1.0f; // alpha + mtl.Ns = 0.0f; + mtl.illum = 2; // illumination + + if(HasPerFaceColor(m)){ + mtl.Kd = Point3f((float)((*fi).C()[0])/255.0f,(float)((*fi).C()[1])/255.0f,(float)((*fi).C()[2])/255.0f);//diffuse + mtl.Tr = (float)((*fi).C()[3])/255.0f;//alpha + } + + if(m.textures.size() && (*fi).WT(0).n() >=0 ) + mtl.map_Kd = m.textures[(*fi).WT(0).n()]; + else + mtl.map_Kd = ""; + + int matInd = MaterialsCompare(materials,mtl); + if(matInd == -1) + { + mtl.index = int(materials.size()); + materials.push_back(mtl); + return mtl.index; + } + return matInd; + } + + /* + returns the index of the material if it exists inside the list of the materials, + otherwise it returns -1. + */ + inline static int MaterialsCompare(std::vector &materials, Material mtl) + { + for(unsigned int i=0;i