diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index b8251cdb3..b1f377488 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -42,22 +42,6 @@ else() endif() set(HEADERS - globals.h - plugins/containers/generic_container_iterator.h - plugins/containers/decorate_plugin_container.h - plugins/containers/edit_plugin_container.h - plugins/containers/filter_plugin_container.h - plugins/containers/io_plugin_container.h - plugins/containers/render_plugin_container.h - plugins/interfaces/meshlab_plugin.h - plugins/interfaces/meshlab_plugin_logger.h - plugins/interfaces/decorate_plugin.h - plugins/interfaces/edit_plugin.h - plugins/interfaces/filter_plugin.h - plugins/interfaces/io_plugin.h - plugins/interfaces/render_plugin.h - plugins/meshlab_plugin_type.h - plugins/plugin_manager.h ml_document/helpers/mesh_document_state_data.h ml_document/helpers/mesh_model_state_data.h ml_document/base_types.h @@ -73,11 +57,28 @@ set(HEADERS parameters/rich_parameter.h parameters/rich_parameter_list.h parameters/value.h + plugins/containers/generic_container_iterator.h + plugins/containers/decorate_plugin_container.h + plugins/containers/edit_plugin_container.h + plugins/containers/filter_plugin_container.h + plugins/containers/io_plugin_container.h + plugins/containers/render_plugin_container.h + plugins/interfaces/meshlab_plugin.h + plugins/interfaces/meshlab_plugin_logger.h + plugins/interfaces/decorate_plugin.h + plugins/interfaces/edit_plugin.h + plugins/interfaces/filter_plugin.h + plugins/interfaces/io_plugin.h + plugins/interfaces/render_plugin.h + plugins/meshlab_plugin_type.h + plugins/plugin_manager.h python/function.h python/function_parameter.h python/function_set.h python/python_utils.h utilities/file_format.h + utilities/load_save.h + globals.h GLExtensionsManager.h GLLogStream.h filterscript.h @@ -91,18 +92,6 @@ set(HEADERS searcher.h) set(SOURCES - globals.cpp - plugins/containers/decorate_plugin_container.cpp - plugins/containers/edit_plugin_container.cpp - plugins/containers/filter_plugin_container.cpp - plugins/containers/io_plugin_container.cpp - plugins/containers/render_plugin_container.cpp - plugins/interfaces/meshlab_plugin_logger.cpp - plugins/interfaces/decorate_plugin.cpp - plugins/interfaces/filter_plugin.cpp - plugins/interfaces/io_plugin.cpp - plugins/meshlab_plugin_type.cpp - plugins/plugin_manager.cpp ml_document/helpers/mesh_document_state_data.cpp ml_document/cmesh.cpp ml_document/mesh_document.cpp @@ -116,10 +105,23 @@ set(SOURCES parameters/rich_parameter.cpp parameters/rich_parameter_list.cpp parameters/value.cpp + plugins/containers/decorate_plugin_container.cpp + plugins/containers/edit_plugin_container.cpp + plugins/containers/filter_plugin_container.cpp + plugins/containers/io_plugin_container.cpp + plugins/containers/render_plugin_container.cpp + plugins/interfaces/meshlab_plugin_logger.cpp + plugins/interfaces/decorate_plugin.cpp + plugins/interfaces/filter_plugin.cpp + plugins/interfaces/io_plugin.cpp + plugins/meshlab_plugin_type.cpp + plugins/plugin_manager.cpp python/function.cpp python/function_parameter.cpp python/function_set.cpp python/python_utils.cpp + utilities/load_save.cpp + globals.cpp GLExtensionsManager.cpp GLLogStream.cpp filterscript.cpp diff --git a/src/common/utilities/load_save.cpp b/src/common/utilities/load_save.cpp new file mode 100644 index 000000000..f847abea3 --- /dev/null +++ b/src/common/utilities/load_save.cpp @@ -0,0 +1,222 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2020 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* 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. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#include "load_save.h" + +#include +#include + +#include "../globals.h" +#include "../plugins/plugin_manager.h" + +namespace meshlab { + +void loadMesh(const QString& fileName, IOPlugin* ioPlugin, const RichParameterList& prePar, const std::list& meshList, std::list& maskList, vcg::CallBackPos *cb) +{ + QFileInfo fi(fileName); + QString extension = fi.suffix(); + + // the original directory path before we switch it + QString origDir = QDir::current().path(); + + // this change of dir is needed for subsequent textures/materials loading + QDir::setCurrent(fi.absoluteDir().absolutePath()); + + // Adjust the file name after changing the directory + QString fileNameSansDir = fi.fileName(); + + try { + ioPlugin->open(extension, fileNameSansDir, meshList ,maskList, prePar, cb); + } + catch(const MLException& e) { + QDir::setCurrent(origDir); // undo the change of directory before leaving + throw e; + } + + QString warningError = ioPlugin->warningMessageString(); + + //saveRecentFileList(fileName); + + auto itmesh = meshList.begin(); + auto itmask = maskList.begin(); + for (unsigned int i = 0; i < meshList.size(); ++i){ + MeshModel* mm = *itmesh; + int mask = *itmask; + + //if (!(mm->cm.textures.empty())) + // updateTexture(mm->id()); + + // In case of polygonal meshes the normal should be updated accordingly + if( mask & vcg::tri::io::Mask::IOM_BITPOLYGONAL) { + mm->updateDataMask(MeshModel::MM_POLYGONAL); // just to be sure. Hopefully it should be done in the plugin... + int degNum = vcg::tri::Clean::RemoveDegenerateFace(mm->cm); + if(degNum) + ioPlugin->log("Warning model contains " + std::to_string(degNum) +" degenerate faces. Removed them."); + mm->updateDataMask(MeshModel::MM_FACEFACETOPO); + vcg::tri::UpdateNormal::PerBitQuadFaceNormalized(mm->cm); + vcg::tri::UpdateNormal::PerVertexFromCurrentFaceNormal(mm->cm); + } // standard case + else { + vcg::tri::UpdateNormal::PerFaceNormalized(mm->cm); + if(!( mask & vcg::tri::io::Mask::IOM_VERTNORMAL) ) + vcg::tri::UpdateNormal::PerVertexAngleWeighted(mm->cm); + } + + vcg::tri::UpdateBounding::Box(mm->cm); + if(mm->cm.fn==0 && mm->cm.en==0) { + if(mask & vcg::tri::io::Mask::IOM_VERTNORMAL) + mm->updateDataMask(MeshModel::MM_VERTNORMAL); + } + + if(mm->cm.fn==0 && mm->cm.en>0) { + if (mask & vcg::tri::io::Mask::IOM_VERTNORMAL) + mm->updateDataMask(MeshModel::MM_VERTNORMAL); + } + + //updateMenus(); + int delVertNum = vcg::tri::Clean::RemoveDegenerateVertex(mm->cm); + int delFaceNum = vcg::tri::Clean::RemoveDegenerateFace(mm->cm); + vcg::tri::Allocator::CompactEveryVector(mm->cm); + if(delVertNum>0 || delFaceNum>0 ) + ioPlugin->reportWarning(warningError + "\n" + QString("Warning mesh contains %1 vertices with NAN coords and %2 degenerated faces.\nCorrected.").arg(delVertNum).arg(delFaceNum)); + //QMessageBox::warning(this, "MeshLab Warning", QString("Warning mesh contains %1 vertices with NAN coords and %2 degenerated faces.\nCorrected.").arg(delVertNum).arg(delFaceNum) ); + + //mm->cm.Tr = mtr; + + //computeRenderingDataOnLoading(mm,isareload, rendOpt); + ++itmesh; + ++itmask; + } + + //updateLayerDialog(); + + + //meshDoc()->setBusy(false); + + QDir::setCurrent(origDir); // undo the change of directory before leaving +} + + +void loadWithStandardParameters(const QString& filename, MeshDocument& md, vcg::CallBackPos *cb) +{ + QFileInfo fi(filename); + QString extension = fi.suffix(); + PluginManager& pm = meshlab::pluginManagerInstance(); + IOPlugin *ioPlugin = pm.inputMeshPlugin(extension); + + if (ioPlugin == nullptr) + throw MLException( + "Mesh " + filename + " cannot be opened. Your MeshLab version " + "has not plugin to read " + extension + " file format"); + + + RichParameterList prePar; + ioPlugin->initPreOpenParameter(extension, prePar); + prePar.join(meshlab::defaultGlobalParameterList()); + + + unsigned int nMeshes = ioPlugin->numberMeshesContainedInFile(extension, filename); + std::list meshList; + for (unsigned int i = 0; i < nMeshes; i++) { + MeshModel *mm = md.addNewMesh(filename, fi.fileName()); + if (nMeshes != 1) { + // if the file contains more than one mesh, this id will be + // != -1 + mm->setIdInFile(i); + } + meshList.push_back(mm); + } + + std::list masks; + + loadMesh(fi.fileName(), ioPlugin, prePar, meshList, masks, cb); + RichParameterList par; + ioPlugin->initOpenParameter(extension, meshList, par); + ioPlugin->applyOpenParameter(extension, meshList, par); +} + + +void reloadMesh( + const QString& filename, + MeshDocument& md, + MeshModel& mm, + vcg::CallBackPos* cb) +{ + // reload can affect only meshes loaded from files containing a single mesh, + // or if the mesh is the first one loaded from that file. + // if a file contains more than one meshes (idInFile != -1), the reload of + // all the contained meshes will be performed by the mesh with idInFile == 0 + if (mm.idInFile() < 1) { + QFileInfo fi(filename); + QString extension = fi.suffix(); + PluginManager& pm = meshlab::pluginManagerInstance(); + IOPlugin *ioPlugin = pm.inputMeshPlugin(extension); + + if (ioPlugin == nullptr) { + throw MLException( + "Mesh " + filename + " cannot be opened. Your MeshLab " + "version has not plugin to read " + extension + + " file format"); + } + + RichParameterList prePar; + ioPlugin->initPreOpenParameter(extension, prePar); + prePar.join(meshlab::defaultGlobalParameterList()); + + unsigned int nMeshes = ioPlugin->numberMeshesContainedInFile(extension, filename); + std::list meshList; + + //simple case: just one meshe expected in the file + if (mm.idInFile() == -1 && nMeshes == 1) { + meshList.push_back(&mm); + } + else if (mm.idInFile() == 0 && nMeshes > 1) { + //looking for all the other meshes that should be reloaded from the file + for (MeshModel* m : md.meshIterator()) { + if (m->fullName() == mm.fullName() && m->idInFile() >= 0) { + meshList.push_back(m); + } + } + if (meshList.size() != nMeshes){ + throw MLException( + "Cannot reload " + filename + ": the number of layers " + "in this meshlab project associated to this file is " + "different from the number of meshes contained in the " + "file."); + } + } + else { + throw MLException( + "Cannot reload " + filename + ": expected number layers is " + "different from the number of meshes contained in th file."); + } + + std::list masks; + loadMesh(fi.fileName(), ioPlugin, prePar, meshList, masks, cb); + RichParameterList par; + ioPlugin->initOpenParameter(extension, meshList, par); + ioPlugin->applyOpenParameter(extension, meshList, par); + } +} + +} diff --git a/src/common/utilities/load_save.h b/src/common/utilities/load_save.h new file mode 100644 index 000000000..8f118c4f7 --- /dev/null +++ b/src/common/utilities/load_save.h @@ -0,0 +1,45 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2020 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* 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. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#ifndef MESHLAB_LOAD_SAVE_H +#define MESHLAB_LOAD_SAVE_H + +#include "../ml_shared_data_context/ml_shared_data_context.h" +#include "../plugins/interfaces/io_plugin.h" + +/** + * Utility functions to load/save meshes using plugins loaded in the plugin + * manager. + */ + +namespace meshlab { + +void loadMesh(const QString& fileName, IOPlugin* ioPlugin, const RichParameterList& prePar, const std::list& meshList, std::list& maskList, vcg::CallBackPos *cb); + +void loadWithStandardParameters(const QString& filename, MeshDocument& mm, vcg::CallBackPos *cb); + +void reloadMesh(const QString& filename, MeshDocument& md, MeshModel& mm, vcg::CallBackPos *cb); + +} + +#endif // MESHLAB_LOAD_SAVE_H diff --git a/src/meshlab/mainwindow_RunTime.cpp b/src/meshlab/mainwindow_RunTime.cpp index aa0693b3a..45456a566 100644 --- a/src/meshlab/mainwindow_RunTime.cpp +++ b/src/meshlab/mainwindow_RunTime.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include "rich_parameter_gui/richparameterlistdialog.h" @@ -2370,28 +2371,22 @@ bool MainWindow::importMeshWithLayerManagement(QString fileName) // Opening files in a transparent form (IO plugins contribution is hidden to user) bool MainWindow::importMesh(QString fileName) { - if (!GLA()) - { + if (!GLA()) { this->newProject(); if(!GLA()) return false; } - - //QStringList suffixList; - // HashTable storing all supported formats together with - // the (1-based) index of first plugin which is able to open it - //QHash allKnownFormats; - //PM.LoadFormats(suffixList, allKnownFormats,PluginManager::IMPORT); QStringList fileNameList; if (fileName.isEmpty()) fileNameList = QFileDialog::getOpenFileNames(this,tr("Import Mesh"), lastUsedDirectory.path(), PM.inputMeshFormatListDialog().join(";;")); else fileNameList.push_back(fileName); - if (fileNameList.isEmpty()) return false; - else - { + if (fileNameList.isEmpty()) { + return false; + } + else { //save path away so we can use it again QString path = fileNameList.first(); path.truncate(path.lastIndexOf("/")); @@ -2400,8 +2395,7 @@ bool MainWindow::importMesh(QString fileName) QElapsedTimer allFileTime; allFileTime.start(); - for(const QString& fileName : fileNameList) - { + for(const QString& fileName : fileNameList) { QFileInfo fi(fileName); if(!fi.exists()) { QString errorMsgFormat = "Unable to open file:\n\"%1\"\n\nError details: file %1 does not exist."; @@ -2417,8 +2411,7 @@ bool MainWindow::importMesh(QString fileName) QString extension = fi.suffix(); IOPlugin *pCurrentIOPlugin = PM.inputMeshPlugin(extension); - if (pCurrentIOPlugin == nullptr) - { + if (pCurrentIOPlugin == nullptr) { QString errorMsgFormat("Unable to open file:\n\"%1\"\n\nError details: file format " + extension + " not supported."); QMessageBox::critical(this, tr("Meshlab Opening Error"), errorMsgFormat.arg(fileName)); return false; @@ -2449,14 +2442,19 @@ bool MainWindow::importMesh(QString fileName) meshList.push_back(mm); } qb->show(); - QElapsedTimer t; - t.start(); - Matrix44m mtr; - mtr.SetIdentity(); std::list masks; - bool open = loadMesh(fileName,pCurrentIOPlugin, meshList, masks,&prePar,mtr,false); - if(open) - { + try { + QElapsedTimer t; + t.start(); + meshlab::loadMesh(fileName, pCurrentIOPlugin, prePar, meshList, masks, QCallBack); + saveRecentFileList(fileName); + updateLayerDialog(); + for (MeshModel* mm : meshList) + computeRenderingDataOnLoading(mm, false, nullptr); + QString warningString = pCurrentIOPlugin->warningMessageString(); + if (!warningString.isEmpty()){ + QMessageBox::warning(this, "Meshlab Opening Warning", warningString); + } GLA()->Logf(0, "Opened mesh %s in %i msec", qUtf8Printable(fileName), t.elapsed()); RichParameterList par; @@ -2470,22 +2468,12 @@ bool MainWindow::importMesh(QString fileName) for (MeshModel* mm : meshList) pCurrentIOPlugin->applyOpenParameter(extension, *mm, par); } - /*MultiViewer_Container* mv = GLA()->mvc(); - if (mv != NULL) - { - for(int glarid = 0;glarid < mv->viewerCounter();++glarid) - { - GLArea* ar = mv->getViewer(glarid); - if (ar != NULL) - MLSceneRenderModeAdapter::setupRequestedAttributesAccordingToRenderMode(mm->id(),*ar); - } - }*/ } - else - { + catch (const MLException& e){ for (MeshModel* mm : meshList) meshDoc()->delMesh(mm); - GLA()->Logf(0, "Warning: Mesh %s has not been opened", qUtf8Printable(fileName)); + GLA()->Logf(0, "Error: File %s has not been loaded", qUtf8Printable(fileName)); + QMessageBox::critical(this, "Meshlab Opening Error", e.what()); } }// end foreach file of the input list GLA()->Logf(0,"All files opened in %i msec",allFileTime.elapsed());