From d217d1af28a4b3dae03412417b3ca96b7bcddb26 Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Fri, 7 Apr 2017 15:23:26 +1000 Subject: [PATCH] - the STL "unify vertices" parameter is now a global one --- src/common/pluginmanager.cpp | 7 +- src/meshlab/mainwindow_RunTime.cpp | 4 +- src/meshlabplugins/io_base/baseio.cpp | 778 +++++++++++++------------- src/meshlabplugins/io_base/baseio.h | 38 +- 4 files changed, 425 insertions(+), 402 deletions(-) diff --git a/src/common/pluginmanager.cpp b/src/common/pluginmanager.cpp index cf6144e5a..2ba0f344f 100644 --- a/src/common/pluginmanager.cpp +++ b/src/common/pluginmanager.cpp @@ -115,8 +115,11 @@ void PluginManager::loadPlugins(RichParameterSet& defaultGlobal) } } MeshIOInterface *iIO = qobject_cast(plugin); - if (iIO) - meshIOPlug.push_back(iIO); + if (iIO) + { + meshIOPlug.push_back(iIO); + iIO->initGlobalParameterSet(NULL,defaultGlobal); + } MeshDecorateInterface *iDecorator = qobject_cast(plugin); if (iDecorator) diff --git a/src/meshlab/mainwindow_RunTime.cpp b/src/meshlab/mainwindow_RunTime.cpp index 89648f474..b2f088f82 100644 --- a/src/meshlab/mainwindow_RunTime.cpp +++ b/src/meshlab/mainwindow_RunTime.cpp @@ -1288,7 +1288,7 @@ void MainWindow::updateSharedContextDataAfterFilterExecution(int postcondmask,in bool(postcondmask & MeshModel::MM_FACENUMBER) || bool(postcondmask & MeshModel::MM_FACEVERT) || bool(postcondmask & MeshModel::MM_VERTFACETOPO) || bool(postcondmask & MeshModel::MM_FACEFACETOPO)) { - updatemask = mm->dataMask(); + updatemask = MeshModel::MM_ALL; connectivitychanged = true; } else @@ -2852,6 +2852,7 @@ bool MainWindow::importMesh(QString fileName,bool isareload) preOpenDialog.setFocus(); preOpenDialog.exec(); } + prePar.join(currentGlobalParams); int mask = 0; //MeshModel *mm= new MeshModel(gla->meshDoc); QFileInfo info(fileName); @@ -2929,6 +2930,7 @@ bool MainWindow::loadMeshWithStandardParams(QString& fullPath, MeshModel* mm, co { RichParameterSet prePar; pCurrentIOPlugin->initPreOpenParameter(extension, fullPath,prePar); + prePar = prePar.join(currentGlobalParams); int mask = 0; QTime t;t.start(); bool open = loadMesh(fullPath,pCurrentIOPlugin,mm,mask,&prePar,mtr,isreload); diff --git a/src/meshlabplugins/io_base/baseio.cpp b/src/meshlabplugins/io_base/baseio.cpp index 9d190f3c6..c50936c59 100644 --- a/src/meshlabplugins/io_base/baseio.cpp +++ b/src/meshlabplugins/io_base/baseio.cpp @@ -47,412 +47,426 @@ class PEdge; class PFace; class PVertex; struct PUsedTypes : public UsedTypes ::AsVertexType, - Use ::AsEdgeType, - Use ::AsFaceType> {}; + Use ::AsEdgeType, + Use ::AsFaceType> {}; -class PVertex : public Vertex{}; -class PEdge : public Edge< PUsedTypes, edge::VertexRef, edge::BitFlags>{}; -class PFace:public vcg::Face< - PUsedTypes, - face::PolyInfo, // this is necessary if you use component in vcg/simplex/face/component_polygon.h - face::PFVAdj, // Pointer to the vertices (just like FVAdj ) - face::Color4b, - face::BitFlags, // bit flags - face::Normal3f, // normal - face::WedgeTexCoord2f +class PVertex : public Vertex {}; +class PEdge : public Edge< PUsedTypes, edge::VertexRef, edge::BitFlags> {}; +class PFace :public vcg::Face< + PUsedTypes, + face::PolyInfo, // this is necessary if you use component in vcg/simplex/face/component_polygon.h + face::PFVAdj, // Pointer to the vertices (just like FVAdj ) + face::Color4b, + face::BitFlags, // bit flags + face::Normal3f, // normal + face::WedgeTexCoord2f > {}; -class PMesh : public tri::TriMesh< vector, vector, vector > {}; +class PMesh : public tri::TriMesh< vector, vector, vector > {}; // initialize importing parameters void BaseMeshIOPlugin::initPreOpenParameter(const QString &formatName, const QString &/*filename*/, RichParameterSet &parlst) { - if (formatName.toUpper() == tr("PTX")) - { - parlst.addParam(new RichInt("meshindex",0,"Index of Range Map to be Imported", - "PTX files may contain more than one range map. 0 is the first range map. If the number if higher than the actual mesh number, the import will fail")); - parlst.addParam(new RichBool("anglecull",true,"Cull faces by angle","short")); - parlst.addParam(new RichFloat("angle",85.0,"Angle limit for face culling","short")); - parlst.addParam(new RichBool("usecolor",true,"import color","Read color from PTX, if color is not present, uses reflectance instead")); - parlst.addParam(new RichBool("pointcull",true,"delete unsampled points","Deletes unsampled points in the grid that are normally located in [0,0,0]")); - parlst.addParam(new RichBool("pointsonly",true,"Keep only points","Import points a point cloud only, with radius and normals, no triangulation involved, isolated points and points with normals with steep angles are removed.")); - parlst.addParam(new RichBool("switchside",false,"Swap rows/columns","On some PTX, the rows and columns number are switched over")); - parlst.addParam(new RichBool("flipfaces",false,"Flip all faces","Flip the orientation of all the triangles")); - } + if (formatName.toUpper() == tr("PTX")) + { + parlst.addParam(new RichInt("meshindex", 0, "Index of Range Map to be Imported", + "PTX files may contain more than one range map. 0 is the first range map. If the number if higher than the actual mesh number, the import will fail")); + parlst.addParam(new RichBool("anglecull", true, "Cull faces by angle", "short")); + parlst.addParam(new RichFloat("angle", 85.0, "Angle limit for face culling", "short")); + parlst.addParam(new RichBool("usecolor", true, "import color", "Read color from PTX, if color is not present, uses reflectance instead")); + parlst.addParam(new RichBool("pointcull", true, "delete unsampled points", "Deletes unsampled points in the grid that are normally located in [0,0,0]")); + parlst.addParam(new RichBool("pointsonly", true, "Keep only points", "Import points a point cloud only, with radius and normals, no triangulation involved, isolated points and points with normals with steep angles are removed.")); + parlst.addParam(new RichBool("switchside", false, "Swap rows/columns", "On some PTX, the rows and columns number are switched over")); + parlst.addParam(new RichBool("flipfaces", false, "Flip all faces", "Flip the orientation of all the triangles")); + } } bool BaseMeshIOPlugin::open(const QString &formatName, const QString &fileName, MeshModel &m, int& mask, const RichParameterSet &parlst, CallBackPos *cb, QWidget * /*parent*/) { - bool normalsUpdated = false; + bool normalsUpdated = false; - // initializing mask - mask = 0; + // initializing mask + mask = 0; - // initializing progress bar status - if (cb != NULL) (*cb)(0, "Loading..."); + // initializing progress bar status + if (cb != NULL) (*cb)(0, "Loading..."); - QString errorMsgFormat = "Error encountered while loading file:\n\"%1\"\n\nError details: %2"; + QString errorMsgFormat = "Error encountered while loading file:\n\"%1\"\n\nError details: %2"; - //string filename = fileName.toUtf8().data(); - string filename = QFile::encodeName(fileName).constData (); + //string filename = fileName.toUtf8().data(); + string filename = QFile::encodeName(fileName).constData(); - if (formatName.toUpper() == tr("PLY")) - { - tri::io::ImporterPLY::LoadMask(filename.c_str(), mask); - // small patch to allow the loading of per wedge color into faces. - if(mask & tri::io::Mask::IOM_WEDGCOLOR) mask |= tri::io::Mask::IOM_FACECOLOR; - m.Enable(mask); + if (formatName.toUpper() == tr("PLY")) + { + tri::io::ImporterPLY::LoadMask(filename.c_str(), mask); + // small patch to allow the loading of per wedge color into faces. + if (mask & tri::io::Mask::IOM_WEDGCOLOR) mask |= tri::io::Mask::IOM_FACECOLOR; + m.Enable(mask); - int result = tri::io::ImporterPLY::Open(m.cm, filename.c_str(), mask, cb); - if (result != 0) // all the importers return 0 on success - { - if(tri::io::ImporterPLY::ErrorCritical(result) ) - { - errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterPLY::ErrorMsg(result)); - return false; - } - } - } - else if (formatName.toUpper() == tr("STL")) - { - if (!tri::io::ImporterSTL::LoadMask(filename.c_str(), mask)) - { - errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterSTL::ErrorMsg(tri::io::ImporterSTL::E_CANTOPEN)); - return false; - } - m.Enable(mask); - int result = tri::io::ImporterSTL::Open(m.cm, filename.c_str(), mask, cb); - if (result != 0) // all the importers return 0 on success - { - errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterSTL::ErrorMsg(result)); - return false; - } - } - else if( (formatName.toUpper() == tr("OBJ")) || (formatName.toUpper() == tr("QOBJ")) ) - { - tri::io::ImporterOBJ::Info oi; - oi.cb = cb; - if (!tri::io::ImporterOBJ::LoadMask(filename.c_str(), oi)) - return false; - m.Enable(oi.mask); + int result = tri::io::ImporterPLY::Open(m.cm, filename.c_str(), mask, cb); + if (result != 0) // all the importers return 0 on success + { + if (tri::io::ImporterPLY::ErrorCritical(result)) + { + errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterPLY::ErrorMsg(result)); + return false; + } + } + } + else if (formatName.toUpper() == tr("STL")) + { + if (!tri::io::ImporterSTL::LoadMask(filename.c_str(), mask)) + { + errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterSTL::ErrorMsg(tri::io::ImporterSTL::E_CANTOPEN)); + return false; + } + m.Enable(mask); + int result = tri::io::ImporterSTL::Open(m.cm, filename.c_str(), mask, cb); + if (result != 0) // all the importers return 0 on success + { + errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterSTL::ErrorMsg(result)); + return false; + } - int result = tri::io::ImporterOBJ::Open(m.cm, filename.c_str(), oi); - if (result != tri::io::ImporterOBJ::E_NOERROR) - { - if (result & tri::io::ImporterOBJ::E_NON_CRITICAL_ERROR) - errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterOBJ::ErrorMsg(result)); - else - { - errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterOBJ::ErrorMsg(result)); - return false; - } - } - - if(oi.mask & tri::io::Mask::IOM_WEDGNORMAL) - normalsUpdated = true; - m.Enable(oi.mask); - if(m.hasDataMask(MeshModel::MM_POLYGONAL)) qDebug("Mesh is Polygonal!"); - mask = oi.mask; - } - else if (formatName.toUpper() == tr("PTX")) - { - tri::io::ImporterPTX::Info importparams; - - importparams.meshnum = parlst.getInt("meshindex"); - importparams.anglecull =parlst.getBool("anglecull"); - importparams.angle = parlst.getFloat("angle"); - importparams.savecolor = parlst.getBool("usecolor"); - importparams.pointcull = parlst.getBool("pointcull"); - importparams.pointsonly = parlst.getBool("pointsonly"); - importparams.switchside = parlst.getBool("switchside"); - importparams.flipfaces = parlst.getBool("flipfaces"); - - // if color, add to mesh - if(importparams.savecolor) - importparams.mask |= tri::io::Mask::IOM_VERTCOLOR; - if(importparams.pointsonly) - importparams.mask |= tri::io::Mask::IOM_VERTRADIUS; - - // reflectance is stored in quality - importparams.mask |= tri::io::Mask::IOM_VERTQUALITY; - - m.Enable(importparams.mask); - - int result = tri::io::ImporterPTX::Open(m.cm, filename.c_str(), importparams, cb); - if (result == 1) - { - errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterPTX::ErrorMsg(result)); - return false; - } - - // update mask - mask = importparams.mask; - } - else if (formatName.toUpper() == tr("OFF")) - { - int loadMask; - if (!tri::io::ImporterOFF::LoadMask(filename.c_str(),loadMask)) - { - errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterOFF::ErrorMsg(tri::io::ImporterOFF::InvalidFile)); - return false; - } - m.Enable(loadMask); - - int result = tri::io::ImporterOFF::Open(m.cm, filename.c_str(), mask, cb); - if (result != 0) // OFFCodes enum is protected - { - errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterOFF::ErrorMsg(result)); - return false; - } - } - else if (formatName.toUpper() == tr("VMI")) - { - int loadMask; - if (!tri::io::ImporterVMI::LoadMask(filename.c_str(),loadMask)) - return false; - m.Enable(loadMask); - - int result = tri::io::ImporterVMI::Open(m.cm, filename.c_str(), mask, cb); - if (result != 0) - { - errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterOFF::ErrorMsg(result)); - return false; - } - } - else if (formatName.toUpper() == tr("GTS")) - { - int loadMask; - if (!tri::io::ImporterGTS::LoadMask(filename.c_str(),loadMask)) - return false; - m.Enable(loadMask); - - tri::io::ImporterGTS::Options opt; - opt.flipFaces = true; - - int result = tri::io::ImporterGTS::Open(m.cm, filename.c_str(), mask, opt, cb); - if (result != 0) - { - errorMessage = errorMsgFormat.arg(fileName, vcg::tri::io::ImporterGTS::ErrorMsg(result)); - return false; - } - } - else - { - assert(0); // Unknown File type - return false; - } - - // verify if texture files are present - QString missingTextureFilesMsg = "The following texture files were not found:\n"; - bool someTextureNotFound = false; - for ( unsigned textureIdx = 0; textureIdx < m.cm.textures.size(); ++textureIdx) - { - if (!QFile::exists(m.cm.textures[textureIdx].c_str())) - { - missingTextureFilesMsg.append("\n"); - missingTextureFilesMsg.append(m.cm.textures[textureIdx].c_str()); - someTextureNotFound = true; - } - } - if (someTextureNotFound) - Log("Missing texture files: %s", qPrintable(missingTextureFilesMsg)); - - if (cb != NULL) (*cb)(99, "Done"); - - return true; -} - -bool BaseMeshIOPlugin::save(const QString &formatName,const QString &fileName, MeshModel &m, const int mask, const RichParameterSet & par, CallBackPos *cb, QWidget */*parent*/) -{ - QString errorMsgFormat = "Error encountered while exportering file %1:\n%2"; - string filename = QFile::encodeName(fileName).constData (); - //string filename = fileName.toUtf8().data(); - string ex = formatName.toUtf8().data(); - bool binaryFlag = false; - if(formatName.toUpper() == tr("STL") || formatName.toUpper() == tr("PLY")) - binaryFlag = par.findParameter("Binary")->val->getBool(); - - if(formatName.toUpper() == tr("PLY")) - { - int result = tri::io::ExporterPLY::Save(m.cm,filename.c_str(),mask,binaryFlag,cb); - if(result!=0) - { - errorMessage = errorMsgFormat.arg(fileName, tri::io::ExporterPLY::ErrorMsg(result)); - return false; - } - return true; - } - if(formatName.toUpper() == tr("STL")) - { - bool magicsFlag = par.getBool("ColorMode"); - - int result = tri::io::ExporterSTL::Save(m.cm,filename.c_str(),binaryFlag,mask,"STL generated by MeshLab",magicsFlag); - if(result!=0) - { - errorMessage = errorMsgFormat.arg(fileName, tri::io::ExporterSTL::ErrorMsg(result)); - return false; - } - return true; - } - if(formatName.toUpper() == tr("WRL")) - { - int result = tri::io::ExporterWRL::Save(m.cm,filename.c_str(),mask,cb); - if(result!=0) - { - errorMessage = errorMsgFormat.arg(fileName, tri::io::ExporterWRL::ErrorMsg(result)); - return false; - } - return true; - } - if( formatName.toUpper() == tr("OFF")) - { - if(mask && tri::io::Mask::IOM_BITPOLYGONAL) - m.updateDataMask(MeshModel::MM_FACEFACETOPO); - int result = tri::io::Exporter::Save(m.cm,filename.c_str(),mask,cb); - if(result!=0) - { - errorMessage = errorMsgFormat.arg(fileName, tri::io::Exporter::ErrorMsg(result)); - return false; - } - return true; - } - - if( formatName.toUpper() == tr("OBJ")) - { - tri::Allocator::CompactEveryVector(m.cm); - int result; - - if ((mask & tri::io::Mask::IOM_BITPOLYGONAL) && (par.findParameter("poligonalize")->val->getBool())) - { - m.updateDataMask(MeshModel::MM_FACEFACETOPO); - PMesh pm; - tri::PolygonSupport::ImportFromTriMesh(pm,m.cm); - result = tri::io::ExporterOBJ::Save(pm,filename.c_str(),mask,cb); - } - else - { - result = tri::io::ExporterOBJ::Save(m.cm, filename.c_str(), mask, cb); - } - if(result!=0) - { - errorMessage = errorMsgFormat.arg(fileName, tri::io::Exporter::ErrorMsg(result)); - return false; - } - return true; - } - - if( formatName.toUpper() == tr("DXF") ) - { - int result = tri::io::Exporter::Save(m.cm,filename.c_str(),mask,cb); - if(result!=0) - { - errorMessage = errorMsgFormat.arg(fileName, tri::io::Exporter::ErrorMsg(result)); - return false; - } - return true; - } - if( formatName.toUpper() == tr("GTS") ) - { - int result = vcg::tri::io::ExporterGTS::Save(m.cm,filename.c_str(),mask); - if(result!=0) - { - errorMessage = errorMsgFormat.arg(fileName, vcg::tri::io::ExporterGTS::ErrorMsg(result)); - return false; - } - return true; - } - assert(0); // unknown format - return false; -} - -/* - returns the list of the file's type which can be imported -*/ -QList BaseMeshIOPlugin::importFormats() const -{ - QList formatList; - formatList << Format("Stanford Polygon File Format" , tr("PLY")); - formatList << Format("STL File Format" , tr("STL")); - formatList << Format("Alias Wavefront Object" , tr("OBJ")); - formatList << Format("Quad Object" , tr("QOBJ")); - formatList << Format("Object File Format" , tr("OFF")); - formatList << Format("PTX File Format" , tr("PTX")); - formatList << Format("VCG Dump File Format" , tr("VMI")); - - return formatList; -} - -/* - returns the list of the file's type which can be exported -*/ -QList BaseMeshIOPlugin::exportFormats() const -{ - QList formatList; - formatList << Format("Stanford Polygon File Format", tr("PLY")); - formatList << Format("STL File Format", tr("STL")); - formatList << Format("Alias Wavefront Object", tr("OBJ")); - formatList << Format("Object File Format", tr("OFF")); - formatList << Format("VRML File Format", tr("WRL")); - formatList << Format("DXF File Format", tr("DXF")); - return formatList; -} - -/* - returns the mask on the basis of the file's type. - otherwise it returns 0 if the file format is unknown -*/ -void BaseMeshIOPlugin::GetExportMaskCapability(QString &format, int &capability, int &defaultBits) const -{ - if(format.toUpper() == tr("PLY")){ - capability = tri::io::ExporterPLY::GetExportMaskCapability(); - // For the default bits of the ply format disable flags and normals that usually are not useful. - defaultBits=capability; - defaultBits &= (~tri::io::Mask::IOM_FLAGS); - defaultBits &= (~tri::io::Mask::IOM_VERTNORMAL); - } - if(format.toUpper() == tr("STL")){ - capability = tri::io::ExporterSTL::GetExportMaskCapability(); - defaultBits=capability; - } - if(format.toUpper() == tr("OBJ")){ - capability=defaultBits= tri::io::ExporterOBJ::GetExportMaskCapability() | tri::io::Mask::IOM_BITPOLYGONAL; - } - if(format.toUpper() == tr("OFF")){capability=defaultBits= tri::io::ExporterOFF::GetExportMaskCapability();} - if(format.toUpper() == tr("WRL")){capability=defaultBits= tri::io::ExporterWRL::GetExportMaskCapability();} - -} - -void BaseMeshIOPlugin::initOpenParameter(const QString &format, MeshModel &/*m*/, RichParameterSet &par) -{ - if(format.toUpper() == tr("STL")) - par.addParam(new RichBool("Unify",true, "Unify Duplicated Vertices", - "The STL format is not an vertex-indexed format. Each triangle is composed by independent vertices, so, usually, duplicated vertices should be unified")); -} - -void BaseMeshIOPlugin::initSaveParameter(const QString &format, MeshModel &m, RichParameterSet &par) -{ - if(format.toUpper() == tr("STL") || format.toUpper() == tr("PLY")) - par.addParam(new RichBool("Binary",true, "Binary encoding", - "Save the mesh using a binary encoding. If false the mesh is saved in a plain, readable ascii format.")); - - if(format.toUpper() == tr("STL")) - par.addParam(new RichBool("ColorMode",true, "Materialise Color Encoding", - "Save the color using a binary encoding according to the Materialise's Magic style (e.g. RGB coding instead of BGR coding).")); - - if (format.toUpper() == tr("OBJ") && m.hasDataMask(MeshModel::MM_POLYGONAL)) //only shows up when the poligonalization is possible - par.addParam(new RichBool("poligonalize", false, "Convert triangles to polygons", - "The layer seems to have faux-edges, if true, MeshLab will try to convert triangles to polygons before exporting.")); -} -void BaseMeshIOPlugin::applyOpenParameter(const QString &format, MeshModel &m, const RichParameterSet &par) -{ - if(format.toUpper() == tr("STL")) - if (par.findParameter("Unify")->val->getBool()) + RichParameter* stlunif = parlst.findParameter(stlUnifyParName()); + if ((stlunif != NULL) && (stlunif->val->getBool())) { tri::Clean::RemoveDuplicateVertex(m.cm); tri::Allocator::CompactEveryVector(m.cm); } + + } + else if ((formatName.toUpper() == tr("OBJ")) || (formatName.toUpper() == tr("QOBJ"))) + { + tri::io::ImporterOBJ::Info oi; + oi.cb = cb; + if (!tri::io::ImporterOBJ::LoadMask(filename.c_str(), oi)) + return false; + m.Enable(oi.mask); + + int result = tri::io::ImporterOBJ::Open(m.cm, filename.c_str(), oi); + if (result != tri::io::ImporterOBJ::E_NOERROR) + { + if (result & tri::io::ImporterOBJ::E_NON_CRITICAL_ERROR) + errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterOBJ::ErrorMsg(result)); + else + { + errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterOBJ::ErrorMsg(result)); + return false; + } + } + + if (oi.mask & tri::io::Mask::IOM_WEDGNORMAL) + normalsUpdated = true; + m.Enable(oi.mask); + if (m.hasDataMask(MeshModel::MM_POLYGONAL)) qDebug("Mesh is Polygonal!"); + mask = oi.mask; + } + else if (formatName.toUpper() == tr("PTX")) + { + tri::io::ImporterPTX::Info importparams; + + importparams.meshnum = parlst.getInt("meshindex"); + importparams.anglecull = parlst.getBool("anglecull"); + importparams.angle = parlst.getFloat("angle"); + importparams.savecolor = parlst.getBool("usecolor"); + importparams.pointcull = parlst.getBool("pointcull"); + importparams.pointsonly = parlst.getBool("pointsonly"); + importparams.switchside = parlst.getBool("switchside"); + importparams.flipfaces = parlst.getBool("flipfaces"); + + // if color, add to mesh + if (importparams.savecolor) + importparams.mask |= tri::io::Mask::IOM_VERTCOLOR; + if (importparams.pointsonly) + importparams.mask |= tri::io::Mask::IOM_VERTRADIUS; + + // reflectance is stored in quality + importparams.mask |= tri::io::Mask::IOM_VERTQUALITY; + + m.Enable(importparams.mask); + + int result = tri::io::ImporterPTX::Open(m.cm, filename.c_str(), importparams, cb); + if (result == 1) + { + errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterPTX::ErrorMsg(result)); + return false; + } + + // update mask + mask = importparams.mask; + } + else if (formatName.toUpper() == tr("OFF")) + { + int loadMask; + if (!tri::io::ImporterOFF::LoadMask(filename.c_str(), loadMask)) + { + errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterOFF::ErrorMsg(tri::io::ImporterOFF::InvalidFile)); + return false; + } + m.Enable(loadMask); + + int result = tri::io::ImporterOFF::Open(m.cm, filename.c_str(), mask, cb); + if (result != 0) // OFFCodes enum is protected + { + errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterOFF::ErrorMsg(result)); + return false; + } + } + else if (formatName.toUpper() == tr("VMI")) + { + int loadMask; + if (!tri::io::ImporterVMI::LoadMask(filename.c_str(), loadMask)) + return false; + m.Enable(loadMask); + + int result = tri::io::ImporterVMI::Open(m.cm, filename.c_str(), mask, cb); + if (result != 0) + { + errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterOFF::ErrorMsg(result)); + return false; + } + } + else if (formatName.toUpper() == tr("GTS")) + { + int loadMask; + if (!tri::io::ImporterGTS::LoadMask(filename.c_str(), loadMask)) + return false; + m.Enable(loadMask); + + tri::io::ImporterGTS::Options opt; + opt.flipFaces = true; + + int result = tri::io::ImporterGTS::Open(m.cm, filename.c_str(), mask, opt, cb); + if (result != 0) + { + errorMessage = errorMsgFormat.arg(fileName, vcg::tri::io::ImporterGTS::ErrorMsg(result)); + return false; + } + } + else + { + assert(0); // Unknown File type + return false; + } + + // verify if texture files are present + QString missingTextureFilesMsg = "The following texture files were not found:\n"; + bool someTextureNotFound = false; + for (unsigned textureIdx = 0; textureIdx < m.cm.textures.size(); ++textureIdx) + { + if (!QFile::exists(m.cm.textures[textureIdx].c_str())) + { + missingTextureFilesMsg.append("\n"); + missingTextureFilesMsg.append(m.cm.textures[textureIdx].c_str()); + someTextureNotFound = true; + } + } + if (someTextureNotFound) + Log("Missing texture files: %s", qPrintable(missingTextureFilesMsg)); + + if (cb != NULL) (*cb)(99, "Done"); + + return true; } +bool BaseMeshIOPlugin::save(const QString &formatName, const QString &fileName, MeshModel &m, const int mask, const RichParameterSet & par, CallBackPos *cb, QWidget */*parent*/) +{ + QString errorMsgFormat = "Error encountered while exportering file %1:\n%2"; + string filename = QFile::encodeName(fileName).constData(); + //string filename = fileName.toUtf8().data(); + string ex = formatName.toUtf8().data(); + bool binaryFlag = false; + if (formatName.toUpper() == tr("STL") || formatName.toUpper() == tr("PLY")) + binaryFlag = par.findParameter("Binary")->val->getBool(); + + if (formatName.toUpper() == tr("PLY")) + { + int result = tri::io::ExporterPLY::Save(m.cm, filename.c_str(), mask, binaryFlag, cb); + if (result != 0) + { + errorMessage = errorMsgFormat.arg(fileName, tri::io::ExporterPLY::ErrorMsg(result)); + return false; + } + return true; + } + if (formatName.toUpper() == tr("STL")) + { + bool magicsFlag = par.getBool("ColorMode"); + + int result = tri::io::ExporterSTL::Save(m.cm, filename.c_str(), binaryFlag, mask, "STL generated by MeshLab", magicsFlag); + if (result != 0) + { + errorMessage = errorMsgFormat.arg(fileName, tri::io::ExporterSTL::ErrorMsg(result)); + return false; + } + return true; + } + if (formatName.toUpper() == tr("WRL")) + { + int result = tri::io::ExporterWRL::Save(m.cm, filename.c_str(), mask, cb); + if (result != 0) + { + errorMessage = errorMsgFormat.arg(fileName, tri::io::ExporterWRL::ErrorMsg(result)); + return false; + } + return true; + } + if (formatName.toUpper() == tr("OFF")) + { + if (mask && tri::io::Mask::IOM_BITPOLYGONAL) + m.updateDataMask(MeshModel::MM_FACEFACETOPO); + int result = tri::io::Exporter::Save(m.cm, filename.c_str(), mask, cb); + if (result != 0) + { + errorMessage = errorMsgFormat.arg(fileName, tri::io::Exporter::ErrorMsg(result)); + return false; + } + return true; + } + + if (formatName.toUpper() == tr("OBJ")) + { + tri::Allocator::CompactEveryVector(m.cm); + int result; + + if ((mask & tri::io::Mask::IOM_BITPOLYGONAL) && (par.findParameter("poligonalize")->val->getBool())) + { + m.updateDataMask(MeshModel::MM_FACEFACETOPO); + PMesh pm; + tri::PolygonSupport::ImportFromTriMesh(pm, m.cm); + result = tri::io::ExporterOBJ::Save(pm, filename.c_str(), mask, cb); + } + else + { + result = tri::io::ExporterOBJ::Save(m.cm, filename.c_str(), mask, cb); + } + if (result != 0) + { + errorMessage = errorMsgFormat.arg(fileName, tri::io::Exporter::ErrorMsg(result)); + return false; + } + return true; + } + + if (formatName.toUpper() == tr("DXF")) + { + int result = tri::io::Exporter::Save(m.cm, filename.c_str(), mask, cb); + if (result != 0) + { + errorMessage = errorMsgFormat.arg(fileName, tri::io::Exporter::ErrorMsg(result)); + return false; + } + return true; + } + if (formatName.toUpper() == tr("GTS")) + { + int result = vcg::tri::io::ExporterGTS::Save(m.cm, filename.c_str(), mask); + if (result != 0) + { + errorMessage = errorMsgFormat.arg(fileName, vcg::tri::io::ExporterGTS::ErrorMsg(result)); + return false; + } + return true; + } + assert(0); // unknown format + return false; +} + +/* + returns the list of the file's type which can be imported +*/ +QList BaseMeshIOPlugin::importFormats() const +{ + QList formatList; + formatList << Format("Stanford Polygon File Format", tr("PLY")); + formatList << Format("STL File Format", tr("STL")); + formatList << Format("Alias Wavefront Object", tr("OBJ")); + formatList << Format("Quad Object", tr("QOBJ")); + formatList << Format("Object File Format", tr("OFF")); + formatList << Format("PTX File Format", tr("PTX")); + formatList << Format("VCG Dump File Format", tr("VMI")); + + return formatList; +} + +/* + returns the list of the file's type which can be exported +*/ +QList BaseMeshIOPlugin::exportFormats() const +{ + QList formatList; + formatList << Format("Stanford Polygon File Format", tr("PLY")); + formatList << Format("STL File Format", tr("STL")); + formatList << Format("Alias Wavefront Object", tr("OBJ")); + formatList << Format("Object File Format", tr("OFF")); + formatList << Format("VRML File Format", tr("WRL")); + formatList << Format("DXF File Format", tr("DXF")); + return formatList; +} + +/* + returns the mask on the basis of the file's type. + otherwise it returns 0 if the file format is unknown +*/ +void BaseMeshIOPlugin::GetExportMaskCapability(QString &format, int &capability, int &defaultBits) const +{ + if (format.toUpper() == tr("PLY")) { + capability = tri::io::ExporterPLY::GetExportMaskCapability(); + // For the default bits of the ply format disable flags and normals that usually are not useful. + defaultBits = capability; + defaultBits &= (~tri::io::Mask::IOM_FLAGS); + defaultBits &= (~tri::io::Mask::IOM_VERTNORMAL); + } + if (format.toUpper() == tr("STL")) { + capability = tri::io::ExporterSTL::GetExportMaskCapability(); + defaultBits = capability; + } + if (format.toUpper() == tr("OBJ")) { + capability = defaultBits = tri::io::ExporterOBJ::GetExportMaskCapability() | tri::io::Mask::IOM_BITPOLYGONAL; + } + if (format.toUpper() == tr("OFF")) { capability = defaultBits = tri::io::ExporterOFF::GetExportMaskCapability(); } + if (format.toUpper() == tr("WRL")) { capability = defaultBits = tri::io::ExporterWRL::GetExportMaskCapability(); } + +} + +//void BaseMeshIOPlugin::initOpenParameter(const QString &format, MeshModel &/*m*/, RichParameterSet &par) +//{ +// if(format.toUpper() == tr("STL")) +// par.addParam(new RichBool("Unify",true, "Unify Duplicated Vertices", +// "The STL format is not an vertex-indexed format. Each triangle is composed by independent vertices, so, usually, duplicated vertices should be unified")); +//} + +void BaseMeshIOPlugin::initSaveParameter(const QString &format, MeshModel &m, RichParameterSet &par) +{ + if (format.toUpper() == tr("STL") || format.toUpper() == tr("PLY")) + par.addParam(new RichBool("Binary", true, "Binary encoding", + "Save the mesh using a binary encoding. If false the mesh is saved in a plain, readable ascii format.")); + + if (format.toUpper() == tr("STL")) + par.addParam(new RichBool("ColorMode", true, "Materialise Color Encoding", + "Save the color using a binary encoding according to the Materialise's Magic style (e.g. RGB coding instead of BGR coding).")); + + if (format.toUpper() == tr("OBJ") && m.hasDataMask(MeshModel::MM_POLYGONAL)) //only shows up when the poligonalization is possible + par.addParam(new RichBool("poligonalize", false, "Convert triangles to polygons", + "The layer seems to have faux-edges, if true, MeshLab will try to convert triangles to polygons before exporting.")); +} + +void BaseMeshIOPlugin::initGlobalParameterSet(QAction * /*format*/, RichParameterSet & globalparam) +{ + globalparam.addParam(new RichBool(stlUnifyParName(), true, "Unify Duplicated Vertices in STL files", "The STL format is not an vertex-indexed format. Each triangle is composed by independent vertices, so, usually, duplicated vertices should be unified")); +} + +//void BaseMeshIOPlugin::applyOpenParameter(const QString &format, MeshModel &m, const RichParameterSet &par) +//{ +// if(format.toUpper() == tr("STL")) +// if (par.findParameter(stlUnifyParName())->val->getBool()) +// { +// tri::Clean::RemoveDuplicateVertex(m.cm); +// tri::Allocator::CompactEveryVector(m.cm); +// } +//} + MESHLAB_PLUGIN_NAME_EXPORTER(BaseMeshIOPlugin) diff --git a/src/meshlabplugins/io_base/baseio.h b/src/meshlabplugins/io_base/baseio.h index 49991cbbe..d01432b4c 100644 --- a/src/meshlabplugins/io_base/baseio.h +++ b/src/meshlabplugins/io_base/baseio.h @@ -1,4 +1,4 @@ - /**************************************************************************** +/**************************************************************************** * MeshLab o o * * A versatile mesh processing toolbox o o * * _ O _ * @@ -8,7 +8,7 @@ * \ * * 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 * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * @@ -27,26 +27,30 @@ class BaseMeshIOPlugin : public QObject, public MeshIOInterface { - Q_OBJECT - MESHLAB_PLUGIN_IID_EXPORTER(MESH_IO_INTERFACE_IID) - Q_INTERFACES(MeshIOInterface) + Q_OBJECT + MESHLAB_PLUGIN_IID_EXPORTER(MESH_IO_INTERFACE_IID) + Q_INTERFACES(MeshIOInterface) + - public: - - BaseMeshIOPlugin() : MeshIOInterface() {} - QList importFormats() const; - QList exportFormats() const; + BaseMeshIOPlugin() : MeshIOInterface() {} - void GetExportMaskCapability(QString &format, int &capability, int &defaultBits) const; + QList importFormats() const; + QList exportFormats() const; - bool open(const QString &formatName, const QString &fileName, MeshModel &m, int& mask,const RichParameterSet & par, vcg::CallBackPos *cb=0, QWidget *parent=0); - bool save(const QString &formatName, const QString &fileName, MeshModel &m, const int mask, const RichParameterSet & par, vcg::CallBackPos *cb=0, QWidget *parent= 0); - void initOpenParameter(const QString &format, MeshModel &/*m*/, RichParameterSet & par); - void applyOpenParameter(const QString &format, MeshModel &m, const RichParameterSet &par); - void initPreOpenParameter(const QString &formatName, const QString &filename, RichParameterSet &parlst); - void initSaveParameter(const QString &format, MeshModel &/*m*/, RichParameterSet & par); + void GetExportMaskCapability(QString &format, int &capability, int &defaultBits) const; + + bool open(const QString &formatName, const QString &fileName, MeshModel &m, int& mask, const RichParameterSet & par, vcg::CallBackPos *cb = 0, QWidget *parent = 0); + bool save(const QString &formatName, const QString &fileName, MeshModel &m, const int mask, const RichParameterSet & par, vcg::CallBackPos *cb = 0, QWidget *parent = 0); + //void initOpenParameter(const QString &format, MeshModel &/*m*/, RichParameterSet & par); + //void applyOpenParameter(const QString &format, MeshModel &m, const RichParameterSet &par); + void initPreOpenParameter(const QString &formatName, const QString &filename, RichParameterSet &parlst); + void initSaveParameter(const QString &format, MeshModel &/*m*/, RichParameterSet & par); + + void initGlobalParameterSet(QAction * /*format*/, RichParameterSet & /*globalparam*/); +private: + static QString stlUnifyParName() { return QString("MeshLab::IO::STL::UnifyVertices"); } }; #endif