diff --git a/wrap/io_trimesh/export_idtf.h b/wrap/io_trimesh/export_idtf.h index d5eba098..352e2fee 100644 --- a/wrap/io_trimesh/export_idtf.h +++ b/wrap/io_trimesh/export_idtf.h @@ -48,6 +48,11 @@ private: std::string _tab; }; +#include +#include +#include +#include + namespace vcg { namespace tri { @@ -103,27 +108,59 @@ typedef typename SaveMeshType::CoordType CoordType; idtf.write(3,"}"); idtf.write(2,"}"); idtf.write(1,"}"); - idtf.write(1,"RESOURCE_NAME \"VcgMesh01\""); + idtf.write(1,"RESOURCE_NAME \"MyVcgMesh01\""); idtf.write(0,"}"); if (mask & Mask::IOM_WEDGTEXCOORD) { - - idtf.write(0,"RESOURCE_LIST \"TEXTURE\" {"); + idtf.write(0,""); + idtf.write(0,"RESOURCE_LIST \"SHADER\" {"); + idtf.write(1,"RESOURCE_COUNT " + TextUtility::nmbToStr(m.textures.size())); + for(unsigned int ii = 0; ii < m.textures.size(); ++ii) + { + idtf.write(1,"RESOURCE " + TextUtility::nmbToStr(ii) + " {"); + idtf.write(2,"RESOURCE_NAME \"ModelShader" + TextUtility::nmbToStr(ii) +"\""); + idtf.write(2,"SHADER_MATERIAL_NAME \"Material1\""); + idtf.write(2,"SHADER_ACTIVE_TEXTURE_COUNT 1"); + idtf.write(2,"SHADER_TEXTURE_LAYER_LIST {"); + idtf.write(3,"TEXTURE_LAYER 0 {"); + idtf.write(4,"TEXTURE_NAME \"Texture" + TextUtility::nmbToStr(ii) +"\""); + idtf.write(3,"}"); + idtf.write(2,"}"); + } + idtf.write(1,"}"); + idtf.write(0,"}"); + idtf.write(0,""); + idtf.write(0,"RESOURCE_LIST \"MATERIAL\" {"); idtf.write(1,"RESOURCE_COUNT 1"); idtf.write(1,"RESOURCE 0 {"); - idtf.write(2,"RESOURCE_NAME \"Texture0\""); - if (m.textures.size() != 0) - idtf.write(2,"TEXTURE_PATH \"" + m.textures[0] + "\""); + idtf.write(2,"RESOURCE_NAME \"Material1\""); + idtf.write(2,"MATERIAL_AMBIENT 0.180000 0.060000 0.060000"); + idtf.write(2,"MATERIAL_DIFFUSE 0.878431 0.560784 0.341176"); + idtf.write(2,"MATERIAL_SPECULAR 0.0720000 0.0720000 0.0720000"); + idtf.write(2,"MATERIAL_EMISSIVE 0.320000 0.320000 0.320000"); + idtf.write(2,"MATERIAL_REFLECTIVITY 0.100000"); + idtf.write(2,"MATERIAL_OPACITY 1.000000"); + idtf.write(1,"}"); + idtf.write(0,"}"); + idtf.write(0,""); + idtf.write(0,"RESOURCE_LIST \"TEXTURE\" {"); + idtf.write(1,"RESOURCE_COUNT " + TextUtility::nmbToStr(m.textures.size())); + for(unsigned int ii = 0; ii < m.textures.size();++ii) + { + idtf.write(1,"RESOURCE " + TextUtility::nmbToStr(ii) + " {"); + idtf.write(2,"RESOURCE_NAME \"Texture" + TextUtility::nmbToStr(ii) + "\""); + idtf.write(2,"TEXTURE_PATH \"" + m.textures[ii] + "\""); + } idtf.write(1,"}"); idtf.write(0,"}"); } - + idtf.write(0,""); idtf.write(0,"RESOURCE_LIST \"MODEL\" {"); idtf.write(1,"RESOURCE_COUNT 1"); idtf.write(1,"RESOURCE 0 {"); - idtf.write(2,"RESOURCE_NAME \"VcgMesh01\""); + idtf.write(2,"RESOURCE_NAME \"MyVcgMesh01\""); idtf.write(2,"MODEL_TYPE \"MESH\""); idtf.write(2,"MESH {"); idtf.write(3,"FACE_COUNT " + TextUtility::nmbToStr(m.face.size())); @@ -131,22 +168,32 @@ typedef typename SaveMeshType::CoordType CoordType; idtf.write(3,"MODEL_NORMAL_COUNT " + TextUtility::nmbToStr(m.face.size() * 3)); idtf.write(3,"MODEL_DIFFUSE_COLOR_COUNT 0"); idtf.write(3,"MODEL_SPECULAR_COLOR_COUNT 0"); - if (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD) idtf.write(3,"MODEL_TEXTURE_COORD_COUNT" + TextUtility::nmbToStr(m.face.size() * 3)); + if (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD) idtf.write(3,"MODEL_TEXTURE_COORD_COUNT " + TextUtility::nmbToStr(m.face.size() * 3)); else idtf.write(3,"MODEL_TEXTURE_COORD_COUNT 0"); idtf.write(3,"MODEL_BONE_COUNT 0"); - idtf.write(3,"MODEL_SHADING_COUNT 1"); + idtf.write(3,"MODEL_SHADING_COUNT " + TextUtility::nmbToStr(m.textures.size())); idtf.write(3,"MODEL_SHADING_DESCRIPTION_LIST {"); - idtf.write(4,"SHADING_DESCRIPTION 0 {"); - if (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD) + unsigned int hh = 0; + do { - idtf.write(5,"TEXTURE_LAYER_COUNT 1"); - idtf.write(5,"TEXTURE_COORD_DIMENSION_LIST {"); - idtf.write(6,"TEXTURE_LAYER 0 DIMENSION: 2"); - idtf.write(5,"}"); + idtf.write(4,"SHADING_DESCRIPTION " + TextUtility::nmbToStr(hh) + " {"); + if (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD) + { + idtf.write(5,"TEXTURE_LAYER_COUNT 1"); + idtf.write(5,"TEXTURE_COORD_DIMENSION_LIST {"); + idtf.write(6,"TEXTURE_LAYER 0 DIMENSION: 2"); + idtf.write(5,"}"); + idtf.write(5,"SHADER_ID 0"); + } + else + { + idtf.write(5,"TEXTURE_LAYER_COUNT 0"); + idtf.write(5,"SHADER_ID 0"); + } + idtf.write(4,"}"); + ++hh; } - else idtf.write(5,"TEXTURE_LAYER_COUNT 0"); - idtf.write(5,"SHADER_ID 0"); - idtf.write(4,"}"); + while(hh < m.textures.size()); idtf.write(3,"}"); idtf.write(3,"MESH_FACE_POSITION_LIST {"); for(ConstFaceIterator fit = m.face.begin();fit != m.face.end();++fit) @@ -169,30 +216,25 @@ typedef typename SaveMeshType::CoordType CoordType; } idtf.write(3,"}"); - if (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD) - { - idtf.write(3,"MESH_FACE_TEXTURE_COORD_LIST {"); - unsigned int nn = 0; - for(ConstFaceIterator fit = m.face.begin();fit != m.face.end();++fit) - { - idtf.write(4,"FACE " + TextUtility::nmbToStr(nn) + "{"); - idtf.write(5,"TEXTURE_LAYER 0 TEX_COORD: " + TextUtility::nmbToStr(nn) + " " + - TextUtility::nmbToStr(nn + 1) + " " + - TextUtility::nmbToStr(nn + 2)); - nn += 3; - } - idtf.write(3,"}"); - } - idtf.write(3,"MESH_FACE_SHADING_LIST {"); - for(ConstFaceIterator fit = m.face.begin();fit != m.face.end();++fit) + for(FaceIterator fit = m.face.begin();fit != m.face.end();++fit) { - idtf.write(4,TextUtility::nmbToStr(0)); + idtf.write(4,TextUtility::nmbToStr(fit->WT(0).N())); } idtf.write(3,"}"); + if (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD) + { + idtf.write(3,"MESH_FACE_TEXTURE_COORD_LIST {"); + for(unsigned int ii = 0; ii < m.face.size();++ii) + { + idtf.write(4,"FACE " + TextUtility::nmbToStr(ii) + " {"); + idtf.write(5,"TEXTURE_LAYER 0 TEX_COORD: " + TextUtility::nmbToStr(ii * 3) + " " + TextUtility::nmbToStr(ii * 3 + 2) + " " + TextUtility::nmbToStr(ii * 3 + 1)); + idtf.write(4,"}"); + } + idtf.write(3,"}"); + } idtf.write(3,"MODEL_POSITION_LIST {"); - vcg::tri::UpdateBounding::Box(m); //ScalarType diag = m.bbox.Diag(); CoordType center = m.bbox.Center(); @@ -226,7 +268,7 @@ typedef typename SaveMeshType::CoordType CoordType; for(unsigned int ii = 0;ii < 3;++ii) { idtf.write(4,TextUtility::nmbToStr(fitn->WT(ii).U()) + " " + - TextUtility::nmbToStr(fitn->WT(ii).V()) + TextUtility::nmbToStr(0.0f)); + TextUtility::nmbToStr(fitn->WT(ii).V()) + " " + TextUtility::nmbToStr(0.0f) + " " + TextUtility::nmbToStr(0.0f)); } } idtf.write(3,"}"); @@ -235,6 +277,27 @@ typedef typename SaveMeshType::CoordType CoordType; idtf.write(2,"}"); idtf.write(1,"}"); idtf.write(0,"}"); + if (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD) + { + idtf.write(0,""); + idtf.write(0,"MODIFIER \"SHADING\" {"); + idtf.write(1,"MODIFIER_NAME \"VcgMesh01\""); + idtf.write(1,"PARAMETERS {"); + idtf.write(2,"SHADER_LIST_COUNT " + TextUtility::nmbToStr(m.textures.size())); + idtf.write(2,"SHADING_GROUP {"); + for(unsigned int ii = 0; ii < m.textures.size();++ii) + { + idtf.write(3,"SHADER_LIST " + TextUtility::nmbToStr(ii) + "{"); + idtf.write(4,"SHADER_COUNT 1"); + idtf.write(4,"SHADER_NAME_LIST {"); + idtf.write(5,"SHADER 0 NAME: \"ModelShader" + TextUtility::nmbToStr(ii) + "\""); + idtf.write(4,"}"); + idtf.write(3,"}"); + } + idtf.write(2,"}"); + idtf.write(1,"}"); + idtf.write(0,"}"); + } return E_NOERROR; } diff --git a/wrap/io_trimesh/export_u3d.h b/wrap/io_trimesh/export_u3d.h index 62a3cc6e..5574e84e 100644 --- a/wrap/io_trimesh/export_u3d.h +++ b/wrap/io_trimesh/export_u3d.h @@ -6,6 +6,7 @@ #include #include #include +#include #include "export_idtf.h" #include @@ -52,8 +53,9 @@ namespace u3dparametersclasses CameraParameters(const float cam_fov_angle,const float cam_roll_angle, const vcg::Point3f& obj_to_cam_dir,const float obj_to_cam_dist, + const float obj_bbox_diag, const vcg::Point3f& obj_pos = vcg::Point3f(0.0f,0.0f,0.0f)) - :_cam_fov_angle(cam_fov_angle),_cam_roll_angle(cam_roll_angle),_obj_to_cam_dir(obj_to_cam_dir),_obj_to_cam_dist(obj_to_cam_dist),_obj_pos(obj_pos),_obj_bbox_diag(0.0f) + :_cam_fov_angle(cam_fov_angle),_cam_roll_angle(cam_roll_angle),_obj_to_cam_dir(obj_to_cam_dir),_obj_to_cam_dist(obj_to_cam_dist),_obj_pos(obj_pos),_obj_bbox_diag(obj_bbox_diag) { } @@ -81,12 +83,119 @@ namespace QtUtilityFunctions static QString fileNameFromTrimmedPath(const QStringList& file_path) { + if (file_path.size() > 0) return file_path.at(file_path.size() - 1); - return QString(); + else + return QString(); + } + + static QString fileNameFromPath(const QString& filepath) + { + QStringList list; + splitFilePath(filepath,list); + return fileNameFromTrimmedPath(list); + } + + static QString pathWithoutFileName(const QString& filepath) + { + QString tmp(filepath); + tmp.remove(fileNameFromPath(filepath)); + return tmp; + } + + static QString fileExtension(const QString& filepath) + { + QStringList trim_list; + splitFilePath(filepath,trim_list); + QString file = fileNameFromTrimmedPath(trim_list); + trim_list = file.split("."); + return trim_list.at(trim_list.size() - 1); } } +class TGA_Exporter +{ +public: + + struct TGAHeader + { + unsigned char identsize; + unsigned char colourmaptype; + unsigned char imagetype; + + unsigned char colormapspecs[5]; + + short xstart; + short ystart; + short width; + short height; + unsigned char bits; + unsigned char descriptor; + }; + + static void convert(const QString& outfile,const QImage& im) + { + TGAHeader tga; + tga.identsize = 0; + tga.colourmaptype = 0; + tga.imagetype = 2; + + memset(tga.colormapspecs,0,5); + tga.xstart = (short) im.offset().x(); + tga.ystart = (short) im.offset().y(); + tga.height = (short) im.height(); + tga.width = (short) im.width(); + + std::ofstream file(qPrintable(outfile),std::ofstream::binary); + unsigned char* tmpchan; + int totbyte; + if (im.hasAlphaChannel()) + { + //is a 8-digits binary number code + // always 0 0 | mirroring | bits + //(future uses)| image | for alpha-channel + //-------------------------------------------- + // 7 6 | 5 4 | 3 2 1 0 + //-------------------------------------------- + // 0 0 | 1 0 | 1 0 0 0 + tga.descriptor = (char) 40; + tga.bits = (char) 32; + } + else + { + //is a 8-digits binary number code + // always 0 0 | mirroring | bits + //(future uses)| image | for alpha-channel + //-------------------------------------------- + // 7 6 | 5 4 | 3 2 1 0 + //-------------------------------------------- + // 0 0 | 1 0 | 0 0 0 0 + tga.descriptor = (char) 32; + tga.bits = (char) 24; + } + + totbyte = tga.height * tga.width * (tga.bits / 8); + + if (im.hasAlphaChannel()) + tmpchan = const_cast(im.bits()); + else + { + tmpchan = new unsigned char[totbyte]; + + unsigned int ii = 0; + while(ii < totbyte) + { + tmpchan[ii] = const_cast(im.bits())[ii + (ii/3)]; + ++ii; + } + } + + file.write((char *) &tga,sizeof(tga)); + file.write(reinterpret_cast(tmpchan),totbyte); + file.close(); + } +}; template class ExporterU3D @@ -155,6 +264,37 @@ private: latex.write(0,"\\end{document}"); } + static void convertTexturesFiles(SaveMeshType& m,const QString& file_path,QStringList& conv_file) + { + for(unsigned int ii = 0; ii < m.textures.size(); ++ii) + { + QString qtmp(m.textures[ii].c_str()); + QString ext = QtUtilityFunctions::fileExtension(qtmp); + if (ext.toLower() != "tga") + { + QImage img(qtmp); + QString stmp; + if ((file_path.at(file_path.length() - 1) != '/') || (file_path.at(file_path.length() - 1) != '\\')) + stmp = file_path + QString("/"); + else + stmp = file_path; + qtmp = stmp + qtmp.remove(ext) + "tga"; + m.textures[ii] = qtmp.toStdString(); + TGA_Exporter::convert(qtmp,img); + conv_file.push_back(qtmp); + } + } + } + + static void removeConvertedTexturesFiles(QStringList& conv_file) + { + for(unsigned int ii = 0;ii < conv_file.size();++ii) + { + QDir dir(QtUtilityFunctions::pathWithoutFileName(conv_file[ii])); + dir.remove(QtUtilityFunctions::fileNameFromPath(conv_file[ii])); + } + } + public: static int Save(SaveMeshType& m,const char* output_file,const char* conv_loc,const u3dparametersclasses::Movie15Parameters& mov_par,const int mask) @@ -164,22 +304,45 @@ public: QStringList out_trim; QtUtilityFunctions::splitFilePath(out,out_trim); QString tmp(QDir::tempPath()); + + tmp = tmp + "/" + QtUtilityFunctions::fileNameFromTrimmedPath(out_trim) + ".idtf"; - vcg::tri::io::ExporterIDTF::Save(m,qPrintable(tmp),mask); QString conv_loc_st(conv_loc); QString output_file_st(output_file); + + //if there are textures file that aren't in tga format I have to convert them + //I maintain the converted file name (i.e. file_path + originalname without extension + tga) in mesh.textures but I have to revert to the original ones + //before the function return. + + QStringList oldtextname; + for(unsigned int ii = 0; ii < m.textures.size();++ii) + oldtextname.push_back(m.textures[ii].c_str()); + + //tmp vector to save the tga created files that should be deleted. + QStringList convfile; + convertTexturesFiles(m,curr,convfile); + + vcg::tri::io::ExporterIDTF::Save(m,qPrintable(tmp),mask); u3dparametersclasses::IDTFConverterParameters idtfpar(conv_loc_st,tmp,output_file_st); qDebug("conv_loc_st '%s'", qPrintable(conv_loc_st)); qDebug("conv_loc '%s'", conv_loc); qDebug("idtfpar._converter_loc '%s'", qPrintable(idtfpar._converter_loc)); int res = InvokeConverter(idtfpar); + + + m.textures.clear(); + for(QStringList::iterator it = oldtextname.begin(); it != oldtextname.end();++it) + m.textures.push_back(it->toStdString()); + //if some tga files have been created I have to delete them + removeConvertedTexturesFiles(convfile); + QDir::setCurrent(curr); QString lat (output_file); QStringList l = lat.split("."); SaveLatex(m,l[0],mov_par); QDir dir(QDir::tempPath()); - //dir.remove(tmp); + dir.remove(tmp); if (res) return 0;