diff --git a/sample/furniture.3ds b/sample/furniture.3ds new file mode 100644 index 000000000..ea39757e0 Binary files /dev/null and b/sample/furniture.3ds differ diff --git a/src/common/plugins/interfaces/io_plugin.cpp b/src/common/plugins/interfaces/io_plugin.cpp index aaeb04743..6782b0baf 100644 --- a/src/common/plugins/interfaces/io_plugin.cpp +++ b/src/common/plugins/interfaces/io_plugin.cpp @@ -45,12 +45,12 @@ void IOPlugin::reportWarning(const QString& warningMessage) const } } -void IOPlugin::wrongOpenFormat(const QString& format) +void IOPlugin::wrongOpenFormat(const QString& format) const { throw MLException("Internal error: unknown open format " + format + " to " + pluginName() + " plugin."); } -void IOPlugin::wrongSaveFormat(const QString& format) +void IOPlugin::wrongSaveFormat(const QString& format) const { throw MLException("Internal error: unknown save format " + format + " to " + pluginName() + " plugin."); } diff --git a/src/common/plugins/interfaces/io_plugin.h b/src/common/plugins/interfaces/io_plugin.h index cf406c937..974582ccf 100644 --- a/src/common/plugins/interfaces/io_plugin.h +++ b/src/common/plugins/interfaces/io_plugin.h @@ -276,14 +276,14 @@ public: * (initPreOpenParameters, load...) whenever you receive as parameter a * format that is not supported by your plugin */ - void wrongOpenFormat(const QString& format); + void wrongOpenFormat(const QString& format) const; /** * @brief call this function in any of the export functions * (exportMaskCapability, save...) whenever you receive as parameter a * format that is not supported by your plugin */ - void wrongSaveFormat(const QString& format); + void wrongSaveFormat(const QString& format) const; /** * @brief The warningMessageString is invoked by the framework after the diff --git a/src/meshlab/mainwindow_RunTime.cpp b/src/meshlab/mainwindow_RunTime.cpp index ff85fec93..5e7a73978 100644 --- a/src/meshlab/mainwindow_RunTime.cpp +++ b/src/meshlab/mainwindow_RunTime.cpp @@ -2410,6 +2410,7 @@ bool MainWindow::importMesh(QString fileName) return false; } + pCurrentIOPlugin->setLog(&meshDoc()->Log); RichParameterList prePar; pCurrentIOPlugin->initPreOpenParameter(extension,prePar); if(!prePar.isEmpty()) diff --git a/src/meshlabplugins/io_3ds/meshio.cpp b/src/meshlabplugins/io_3ds/meshio.cpp index 2cce37448..9154eb210 100644 --- a/src/meshlabplugins/io_3ds/meshio.cpp +++ b/src/meshlabplugins/io_3ds/meshio.cpp @@ -75,28 +75,75 @@ void ExtraMeshIOPlugin::exportMaskCapability(const QString &format, int &capabil return; } -void ExtraMeshIOPlugin::initPreOpenParameter( +unsigned int ExtraMeshIOPlugin::numberMeshesContainedInFile( const QString& format, - RichParameterList& parameters) + const QString& fileName) const { - if (format.toUpper() == tr("3DS")){ - parameters.addParam(RichBool(paramNames[SEPARATE_LAYERS], true, "Separate layers", "Import each mesh contained in the file as a separate layer")); + if (format.toUpper() == tr("3DS")) { + Lib3dsFile *file = NULL; + file = lib3ds_file_load(fileName.toStdString().c_str()); + if (!file) + throw MLException("Malformed file."); + // No nodes? Fabricate nodes to display all the meshes. + if( !file->nodes && file->meshes) { + Lib3dsMesh *mesh; + Lib3dsNode *node; + + for (mesh = file->meshes; mesh != NULL; mesh = mesh->next) { + node = lib3ds_node_new_object(); + strcpy(node->name, mesh->name); + node->parent_id = LIB3DS_NO_PARENT; + lib3ds_file_insert_node(file, node); + } + } + if( !file->nodes) { + lib3ds_file_free(file); + throw MLException("Malformed file."); + } + lib3ds_file_eval(file, 0); + unsigned int i = 0; + Lib3dsNode *p = file->nodes; + while (p) { + i++; + p = p->next; + } + log("Expected meshes in file: " + std::to_string(i) ); + lib3ds_file_free(file); + return i; } + else { + wrongOpenFormat(format); + return 0; + } +} + +void ExtraMeshIOPlugin::open( + const QString& formatName, + const QString&, + MeshModel&, + int&, + const RichParameterList&, + CallBackPos*) +{ + wrongOpenFormat(formatName); } void ExtraMeshIOPlugin::open( const QString &formatName, const QString &fileName, - MeshModel &m, - int& mask, - const RichParameterList& params, + const std::list& meshList, + std::list& maskList, + const RichParameterList&, CallBackPos *cb) { // initializing mask - mask = 0; + maskList.clear(); + for (unsigned int i = 0; i < meshList.size(); i++) + maskList.push_back(0); // initializing progress bar status - if (cb != NULL) (*cb)(0, "Loading..."); + if (cb != nullptr) + (*cb)(0, "Loading..."); QString errorMsgFormat = "Error encountered while loading file:\n\"%1\"\n\nError details: %2"; //QString error_2MsgFormat = "Error encountered while loading file:\n\"%1\"\n\n File with more than a mesh.\n Load only the first!"; @@ -136,92 +183,43 @@ void ExtraMeshIOPlugin::open( } lib3ds_file_eval(file, 0); - - bool singleLayer = true; - if ( file->nodes->next) { - singleLayer = params.getBool(paramNames[SEPARATE_LAYERS]); - } - - if (!singleLayer) - { - Lib3dsNode *p; - mask = 0; - int i=1; - for (p=file->nodes; p!=0; p=p->next, ++i) - { - bool normalsUpdated = false; - - MeshModel &mm = *m.parent->addNewMesh(qUtf8Printable(fileName), QString(p->name), false); - if (cb != NULL) (*cb)(i, (QString("Loading Mesh ")+QString(p->name)).toStdString().c_str()); - - vcg::tri::io::Importer3DS::LoadMask(file, p, info); - mm.Enable(info.mask); - - int result = vcg::tri::io::Importer3DS::Load(mm.cm, file, p, info); - if (result != vcg::tri::io::Importer3DS::E_NOERROR) { - reportWarning("3DS Opening Error: " + errorMsgFormat.arg(fileName, vcg::tri::io::Importer3DS::ErrorMsg(result))); - continue; - } - - if(info.mask & vcg::tri::io::Mask::IOM_WEDGNORMAL) - normalsUpdated = true; - - mask |= info.mask; - - // verify if texture files are present - QString missingTextureFilesMsg = "The following texture files were not found:\n"; - bool someTextureNotFound = false; - for ( unsigned textureIdx = 0; textureIdx < mm.cm.textures.size(); ++textureIdx) - { - FILE* pFile = fopen (mm.cm.textures[textureIdx].c_str(), "r"); - if (pFile == nullptr) { - missingTextureFilesMsg.append("\n"); - missingTextureFilesMsg.append(mm.cm.textures[textureIdx].c_str()); - someTextureNotFound = true; - } - else { - fclose (pFile); - } - } - if (someTextureNotFound){ - reportWarning("Missing texture files: " + missingTextureFilesMsg); - } - - vcg::tri::UpdateBounding::Box(mm.cm); // updates bounding box - if (!normalsUpdated) - vcg::tri::UpdateNormal::PerVertex(mm.cm); // updates normals - } - } - else + + Lib3dsNode *p; + int i=1; + auto iter = meshList.begin(); + auto miter = maskList.begin(); + for (p=file->nodes; p!=nullptr; p=p->next, ++iter, ++miter) { bool normalsUpdated = false; - - vcg::tri::io::Importer3DS::LoadMask(file, 0, info); - m.Enable(info.mask); - - int result = vcg::tri::io::Importer3DS::Load(m.cm, file, 0, info); - if (result != vcg::tri::io::Importer3DS::E_NOERROR) - { - lib3ds_file_free(file); - throw MLException("3DS Opening Error: " + errorMsgFormat.arg(fileName, vcg::tri::io::Importer3DS::ErrorMsg(result))); + + MeshModel &mm = *(*iter); + mm.setLabel(QString(p->name)); + if (cb != nullptr) + (*cb)(i/meshList.size() * 100, (QString("Loading Mesh ")+QString(p->name)).toStdString().c_str()); + + vcg::tri::io::Importer3DS::LoadMask(file, p, info); + mm.Enable(info.mask); + + int result = vcg::tri::io::Importer3DS::Load(mm.cm, file, p, info); + if (result != vcg::tri::io::Importer3DS::E_NOERROR) { + reportWarning("3DS Opening Error: " + errorMsgFormat.arg(fileName, vcg::tri::io::Importer3DS::ErrorMsg(result))); + continue; } - + if(info.mask & vcg::tri::io::Mask::IOM_WEDGNORMAL) normalsUpdated = true; - - mask = info.mask; - - + + (*miter) |= info.mask; + // 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) + for ( unsigned textureIdx = 0; textureIdx < mm.cm.textures.size(); ++textureIdx) { - FILE* pFile = fopen (m.cm.textures[textureIdx].c_str(), "r"); - if (pFile == nullptr) - { + FILE* pFile = fopen (mm.cm.textures[textureIdx].c_str(), "r"); + if (pFile == nullptr) { missingTextureFilesMsg.append("\n"); - missingTextureFilesMsg.append(m.cm.textures[textureIdx].c_str()); + missingTextureFilesMsg.append(mm.cm.textures[textureIdx].c_str()); someTextureNotFound = true; } else { @@ -231,12 +229,12 @@ void ExtraMeshIOPlugin::open( if (someTextureNotFound){ reportWarning("Missing texture files: " + missingTextureFilesMsg); } - - vcg::tri::UpdateBounding::Box(m.cm); // updates bounding box - if (!normalsUpdated) - vcg::tri::UpdateNormal::PerVertex(m.cm); // updates normals + + vcg::tri::UpdateBounding::Box(mm.cm); // updates bounding box + if (!normalsUpdated) + vcg::tri::UpdateNormal::PerVertex(mm.cm); // updates normals } - + if (cb != NULL) (*cb)(99, "Done"); // freeing memory diff --git a/src/meshlabplugins/io_3ds/meshio.h b/src/meshlabplugins/io_3ds/meshio.h index 0dd8506d7..23ea813d1 100644 --- a/src/meshlabplugins/io_3ds/meshio.h +++ b/src/meshlabplugins/io_3ds/meshio.h @@ -44,15 +44,24 @@ public: void exportMaskCapability(const QString& format, int &capability, int &defaultBits) const; - void initPreOpenParameter( - const QString& format, - RichParameterList& parameters); + unsigned int numberMeshesContainedInFile( + const QString& format, + const QString& fileName) const; - void open(const QString &formatName, + void open( + const QString &formatName, const QString &fileName, - MeshModel &m, + MeshModel& m, int& mask, - const RichParameterList ¶ms, + const RichParameterList& params, + vcg::CallBackPos *cb=0); + + void open( + const QString &formatName, + const QString &fileName, + const std::list& meshList, + std::list& maskList, + const RichParameterList& params, vcg::CallBackPos *cb=0); void save(