mirror of
https://github.com/lucaspalomodevelop/meshlab.git
synced 2026-03-14 00:24:38 +00:00
Allow all filetypes supported by meshlab to be opened with meshlabserver
VisualSFM (and some other formats) output *.nvm, *.rd.out projects that meshlab can easily import and use, but the logic for this never made it into meshlabserver. I pretty much just wholesale copied/adapted the existing code from meshlab into meshlabserver, allowing any supported project to be imported like any other mlb file.
This commit is contained in:
parent
b51f9e01ac
commit
74f55f5273
@ -30,7 +30,6 @@
|
||||
#include "saveSnapshotDialog.h"
|
||||
#include "ui_aboutDialog.h"
|
||||
#include "savemaskexporter.h"
|
||||
#include "alnParser.h"
|
||||
#include <exception>
|
||||
#include "ml_default_decorators.h"
|
||||
|
||||
@ -44,6 +43,7 @@
|
||||
#include "../common/meshlabdocumentxml.h"
|
||||
#include "../common/meshlabdocumentbundler.h"
|
||||
#include "../common/mlapplication.h"
|
||||
#include "../common/alnParser.h"
|
||||
#include "../common/filterscript.h"
|
||||
#include "../common/mlexception.h"
|
||||
|
||||
|
||||
@ -21,7 +21,7 @@ HEADERS = plymc.h \
|
||||
trivial_walker.h \
|
||||
tri_edge_collapse_mc.h \
|
||||
simplemeshprovider.h \
|
||||
../../meshlab/alnParser.h
|
||||
../../common/alnParser.h
|
||||
|
||||
!CONFIG(system_glew): INCLUDEPATH *= ../../code/lib/glew/include
|
||||
|
||||
|
||||
@ -28,6 +28,8 @@
|
||||
#include <common/pluginmanager.h>
|
||||
#include <common/filterscript.h>
|
||||
#include <common/meshlabdocumentxml.h>
|
||||
#include <common/meshlabdocumentbundler.h>
|
||||
#include <common/alnParser.h>
|
||||
#include <common/mlexception.h>
|
||||
#include <common/filterparameter.h>
|
||||
#include <wrap/qt/qt_thread_safe_memory_info.h>
|
||||
@ -242,40 +244,282 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool openProject(MeshDocument& md,const QString& filename)
|
||||
bool loadMesh(const QString& fileName, MeshIOInterface *pCurrentIOPlugin, MeshModel* mm, int& mask,RichParameterSet* prePar, const Matrix44m &mtr, MeshDocument* md, FILE* fp = stdout)
|
||||
{
|
||||
QDir curDir = QDir::current();
|
||||
QFileInfo fi(filename);
|
||||
std::map<int, MLRenderingData> tmp;
|
||||
bool opened = MeshDocumentFromXML(md,fi.absoluteFilePath(), fi.suffix().toLower() == "mlb",tmp);
|
||||
if (!opened)
|
||||
if (mm == NULL)
|
||||
return false;
|
||||
QDir::setCurrent(fi.absolutePath());
|
||||
//WARNING! I'm not putting inside MeshDocumentFromXML function because I'm too scared of what can happen inside MeshLab code....
|
||||
md.setFileName(fi.absoluteFilePath());
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
for (int i=0; i<md.meshList.size(); i++)
|
||||
QFileInfo fi(fileName);
|
||||
QString extension = fi.suffix();
|
||||
if(!fi.exists())
|
||||
{
|
||||
if (md.meshList[i] != NULL)
|
||||
QString errorMsgFormat = "Unable to open file:\n\"%1\"\n\nError details: file %1 does not exist.";
|
||||
fprintf(fp, "Meshlab Opening Error: %s", errorMsgFormat.arg(fileName).toStdString().c_str());
|
||||
return false;
|
||||
}
|
||||
if(!fi.isReadable())
|
||||
{
|
||||
QString errorMsgFormat = "Unable to open file:\n\"%1\"\n\nError details: file %1 is not readable.";
|
||||
fprintf(fp, "Meshlab Opening Error: %s", errorMsgFormat.arg(fileName).toStdString().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
// retrieving corresponding IO plugin
|
||||
if (pCurrentIOPlugin == 0)
|
||||
{
|
||||
QString errorMsgFormat = "Error encountered while opening file:\n\"%1\"\n\nError details: The \"%2\" file extension does not correspond to any supported format.";
|
||||
fprintf(fp, "Opening Error: %s", errorMsgFormat.arg(fileName, extension).toStdString().c_str());
|
||||
QDir::setCurrent(origDir); // undo the change of directory before leaving
|
||||
return false;
|
||||
}
|
||||
md->setBusy(true);
|
||||
pCurrentIOPlugin->setLog(&md->Log);
|
||||
|
||||
if (!pCurrentIOPlugin->open(extension, fileNameSansDir, *mm ,mask,*prePar))
|
||||
{
|
||||
fprintf(fp, "Opening Failure: %s", (QString("While opening: '%1'\n\n").arg(fileName)+pCurrentIOPlugin->errorMsg()).toStdString().c_str()); // text+
|
||||
pCurrentIOPlugin->clearErrorString();
|
||||
md->setBusy(false);
|
||||
QDir::setCurrent(origDir); // undo the change of directory before leaving
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//std::cout << "Opened mesh: in " << tm.elapsed() << " secs\n";
|
||||
// After opening the mesh lets ask to the io plugin if this format
|
||||
// requires some optional, or userdriven post-opening processing.
|
||||
// and in that case ask for the required parameters and then
|
||||
// ask to the plugin to perform that processing
|
||||
//RichParameterSet par;
|
||||
//pCurrentIOPlugin->initOpenParameter(extension, *mm, par);
|
||||
//pCurrentIOPlugin->applyOpenParameter(extension, *mm, par);
|
||||
|
||||
QString err = pCurrentIOPlugin->errorMsg();
|
||||
if (!err.isEmpty())
|
||||
{
|
||||
fprintf(fp, "Opening Problems: %s", (QString("While opening: '%1'\n\n").arg(fileName)+pCurrentIOPlugin->errorMsg()).toStdString().c_str());
|
||||
pCurrentIOPlugin->clearErrorString();
|
||||
}
|
||||
|
||||
//saveRecentFileList(fileName);
|
||||
|
||||
//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<CMeshO>::RemoveDegenerateFace(mm->cm);
|
||||
if(degNum)
|
||||
fprintf(stdout, "Warning model contains %i degenerate faces. Removed them.",degNum);
|
||||
mm->updateDataMask(MeshModel::MM_FACEFACETOPO);
|
||||
vcg::tri::UpdateNormal<CMeshO>::PerBitQuadFaceNormalized(mm->cm);
|
||||
vcg::tri::UpdateNormal<CMeshO>::PerVertexFromCurrentFaceNormal(mm->cm);
|
||||
} // standard case
|
||||
else
|
||||
{
|
||||
vcg::tri::UpdateNormal<CMeshO>::PerFaceNormalized(mm->cm);
|
||||
if(!( mask & vcg::tri::io::Mask::IOM_VERTNORMAL) )
|
||||
vcg::tri::UpdateNormal<CMeshO>::PerVertexAngleWeighted(mm->cm);
|
||||
}
|
||||
|
||||
vcg::tri::UpdateBounding<CMeshO>::Box(mm->cm); // updates bounding box
|
||||
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<CMeshO>::RemoveDegenerateVertex(mm->cm);
|
||||
int delFaceNum = vcg::tri::Clean<CMeshO>::RemoveDegenerateFace(mm->cm);
|
||||
vcg::tri::Allocator<CMeshO>::CompactEveryVector(mm->cm);
|
||||
if(delVertNum>0 || delFaceNum>0 )
|
||||
fprintf(fp, "MeshLab Warning: %s", (QString("Warning mesh contains %1 vertices with NAN coords and %2 degenerated faces.\nCorrected.").arg(delVertNum).arg(delFaceNum)).toStdString().c_str() );
|
||||
mm->cm.Tr = mtr;
|
||||
|
||||
//computeRenderingDataOnLoading(mm,isareload, rendOpt);
|
||||
//updateLayerDialog();
|
||||
|
||||
|
||||
md->setBusy(false);
|
||||
|
||||
QDir::setCurrent(origDir); // undo the change of directory before leaving
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool loadMeshWithStandardParams(QString& fullPath, MeshModel* mm, const Matrix44m &mtr = Matrix44m::Identity(), MeshDocument* md = NULL)
|
||||
{
|
||||
if ((mm == NULL) || (md == NULL))
|
||||
return false;
|
||||
bool ret = false;
|
||||
if (!mm->isVisible())
|
||||
{
|
||||
mm->Clear();
|
||||
mm->visible = false;
|
||||
}
|
||||
else
|
||||
mm->Clear();
|
||||
QFileInfo fi(fullPath);
|
||||
QString extension = fi.suffix();
|
||||
MeshIOInterface *pCurrentIOPlugin = PM.allKnowInputFormats[extension.toLower()];
|
||||
|
||||
if(pCurrentIOPlugin != NULL)
|
||||
{
|
||||
RichParameterSet prePar;
|
||||
pCurrentIOPlugin->initPreOpenParameter(extension, fullPath,prePar);
|
||||
//prePar = prePar.join(currentGlobalParams);
|
||||
int mask = 0;
|
||||
QElapsedTimer t;t.start();
|
||||
bool open = loadMesh(fullPath,pCurrentIOPlugin,mm,mask,&prePar,mtr, md, stdout);
|
||||
if(open)
|
||||
{
|
||||
QString fullPath = md.meshList[i]->fullName();
|
||||
md.setBusy(true);
|
||||
Matrix44m trm = md.meshList[i]->cm.Tr; // save the matrix, because loadMeshClear it...
|
||||
if (!importMesh(*md.meshList[i],fullPath))
|
||||
{
|
||||
md.delMesh(md.meshList[i]);
|
||||
md.setBusy(false);
|
||||
QDir::setCurrent(curDir.absolutePath());
|
||||
return false;
|
||||
}
|
||||
else
|
||||
md.meshList[i]->cm.Tr=trm;
|
||||
md.setCurrentMesh(md.meshList[i]->id());
|
||||
md.setBusy(false);
|
||||
RichParameterSet par;
|
||||
pCurrentIOPlugin->initOpenParameter(extension, *mm, par);
|
||||
pCurrentIOPlugin->applyOpenParameter(extension,*mm,par);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
QDir::setCurrent(curDir.absolutePath());
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool openProject(MeshDocument& md,const QString& fileName,FILE* fp = stdout)
|
||||
{
|
||||
//bool visiblelayer = layerDialog->isVisible();
|
||||
//showLayerDlg(false);
|
||||
//globrendtoolbar->setEnabled(false);
|
||||
if (fileName.isEmpty()) return false;
|
||||
|
||||
QFileInfo fi(fileName);
|
||||
//lastUsedDirectory = fi.absoluteDir();
|
||||
//TODO: move this to main()
|
||||
if((fi.suffix().toLower()!="aln") && (fi.suffix().toLower()!="mlp") && (fi.suffix().toLower() != "mlb") && (fi.suffix().toLower()!="out") && (fi.suffix().toLower()!="nvm"))
|
||||
{
|
||||
//QMessageBox::critical(this, tr("Meshlab Opening Error"), "Unknown project file extension");
|
||||
fprintf(fp, "Meshlab Opening Error: Unknown project file extension\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Common Part: init a Doc if necessary, and
|
||||
//bool activeDoc = (bool) !mdiarea->subWindowList().empty() && mdiarea->currentSubWindow();
|
||||
//bool activeEmpty = activeDoc && md.meshList.empty();
|
||||
|
||||
//if (!activeEmpty) newProject(fileName);
|
||||
|
||||
md.setFileName(fileName);
|
||||
//mdiarea->currentSubWindow()->setWindowTitle(fileName);
|
||||
md.setDocLabel(fileName);
|
||||
|
||||
md.setBusy(true);
|
||||
|
||||
// this change of dir is needed for subsequent textures/materials loading
|
||||
QDir::setCurrent(fi.absoluteDir().absolutePath());
|
||||
//qb->show();
|
||||
|
||||
if (QString(fi.suffix()).toLower() == "aln")
|
||||
{
|
||||
std::vector<RangeMap> rmv;
|
||||
int retVal = ALNParser::ParseALN(rmv, qUtf8Printable(fileName));
|
||||
if(retVal != ALNParser::NoError)
|
||||
{
|
||||
//QMessageBox::critical(this, tr("Meshlab Opening Error"), "Unable to open ALN file");
|
||||
fprintf(fp,"Meshlab Opening Error: Unable to open ALN file\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool openRes=true;
|
||||
std::vector<RangeMap>::iterator ir;
|
||||
for(ir=rmv.begin();ir!=rmv.end() && openRes;++ir)
|
||||
{
|
||||
QString relativeToProj = fi.absoluteDir().absolutePath() + "/" + (*ir).filename.c_str();
|
||||
md.addNewMesh(relativeToProj,relativeToProj);
|
||||
openRes = loadMeshWithStandardParams(relativeToProj,md.mm(),ir->trasformation, &md);
|
||||
if(!openRes)
|
||||
md.delMesh(md.mm());
|
||||
}
|
||||
}
|
||||
|
||||
if (QString(fi.suffix()).toLower() == "mlp" || QString(fi.suffix()).toLower() == "mlb")
|
||||
{
|
||||
std::map<int, MLRenderingData> rendOpt;
|
||||
if (!MeshDocumentFromXML(md, fileName, (QString(fi.suffix()).toLower() == "mlb"), rendOpt))
|
||||
{
|
||||
//QMessageBox::critical(this, tr("Meshlab Opening Error"), "Unable to open MeshLab Project file");
|
||||
fprintf(fp,"Meshlab Opening Error: Unable to open MeshLab Project file\n");
|
||||
return false;
|
||||
}
|
||||
//GLA()->updateMeshSetVisibilities();
|
||||
for (int i=0; i<md.meshList.size(); i++)
|
||||
{
|
||||
QString fullPath = md.meshList[i]->fullName();
|
||||
//md.setBusy(true);
|
||||
Matrix44m trm = md.meshList[i]->cm.Tr; // save the matrix, because loadMeshClear it...
|
||||
if (!loadMeshWithStandardParams(fullPath, md.meshList[i], trm, &md))
|
||||
md.delMesh(md.meshList[i]);
|
||||
}
|
||||
}
|
||||
|
||||
////// BUNDLER
|
||||
if (QString(fi.suffix()).toLower() == "out"){
|
||||
|
||||
QString cameras_filename = fileName;
|
||||
QString image_list_filename;
|
||||
QString model_filename;
|
||||
|
||||
image_list_filename = "list.txt";
|
||||
if(image_list_filename.isEmpty())
|
||||
return false;
|
||||
|
||||
if(!MeshDocumentFromBundler(md,cameras_filename,image_list_filename,model_filename)){
|
||||
//QMessageBox::critical(this, tr("Meshlab Opening Error"), "Unable to open OUTs file");
|
||||
fprintf(fp,"Meshlab Opening Error: Unable to open OUTs file\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//WARNING!!!!! i suppose it's not useful anymore but.......
|
||||
/*GLA()->setColorMode(GLW::CMPerVert);
|
||||
GLA()->setDrawMode(GLW::DMPoints);*/
|
||||
/////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
//////NVM
|
||||
if (QString(fi.suffix()).toLower() == "nvm"){
|
||||
|
||||
QString cameras_filename = fileName;
|
||||
QString model_filename;
|
||||
|
||||
if(!MeshDocumentFromNvm(md,cameras_filename,model_filename)){
|
||||
//QMessageBox::critical(this, tr("Meshlab Opening Error"), "Unable to open NVMs file");
|
||||
fprintf(fp,"Meshlab Opening Error: Unable to open NVMs file\n");
|
||||
return false;
|
||||
}
|
||||
//WARNING!!!!! i suppose it's not useful anymore but.......
|
||||
/*GLA()->setColorMode(GLW::CMPerVert);
|
||||
GLA()->setDrawMode(GLW::DMPoints);*/
|
||||
/////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
md.setBusy(false);
|
||||
//qb->reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -655,13 +899,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
QFileInfo finfo(argv[i+1]);
|
||||
QString inputproject = finfo.absoluteFilePath();
|
||||
if (finfo.completeSuffix().toLower() != "mlp")
|
||||
{
|
||||
fprintf(logfp,"Project %s is not a valid \'mlp\' file format. MeshLabServer application will exit.\n",qUtf8Printable(inputproject));
|
||||
//system("pause");
|
||||
exit(-1);
|
||||
}
|
||||
bool opened = server.openProject(meshDocument,inputproject);
|
||||
bool opened = server.openProject(meshDocument,inputproject, logfp);
|
||||
if (!opened)
|
||||
{
|
||||
fprintf(logfp,"MeshLab Project %s has not been correctly opened. MeshLabServer application will exit.\n",qUtf8Printable(inputproject));
|
||||
|
||||
@ -10,7 +10,8 @@ meshlabserver [logargs] [args]
|
||||
|
||||
where args can be:
|
||||
|
||||
-p filename meshlab project (.mlp) to be loaded
|
||||
-p filename meshlab project (.mlp/.mlb/.aln/.out/.nvm) to
|
||||
be loaded
|
||||
|
||||
-w filename [-x] output meshlab project (.mlp) to be saved.
|
||||
If -x flag is specified a 3D model meshfile.ext
|
||||
|
||||
@ -42,7 +42,7 @@ $Log: meshedit.cpp,v $
|
||||
#include <vcg/complex/algorithms/clustering.h>
|
||||
#include <vcg/complex/algorithms/hole.h>
|
||||
#include <wrap/io_trimesh/export_ply.h>
|
||||
#include <meshlab/alnParser.h>
|
||||
#include <common/alnParser.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace vcg;
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
#include <vcg/complex/algorithms/clustering.h>
|
||||
#include <vcg/complex/algorithms/hole.h>
|
||||
#include <wrap/io_trimesh/export_ply.h>
|
||||
#include <meshlab/alnParser.h>
|
||||
#include <common/alnParser.h>
|
||||
|
||||
|
||||
class EditArc3DPlugin : public QObject, public MeshEditInterface
|
||||
|
||||
@ -40,7 +40,7 @@
|
||||
#include <vcg/complex/algorithms/clustering.h>
|
||||
#include <vcg/complex/algorithms/hole.h>
|
||||
#include <wrap/io_trimesh/export_ply.h>
|
||||
#include <meshlab/alnParser.h>
|
||||
#include <common/alnParser.h>
|
||||
|
||||
FILE *logFP=0;
|
||||
using namespace std;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#ifndef SIMPLEMESHPROVIDER_H
|
||||
#define SIMPLEMESHPROVIDER_H
|
||||
#include "../../meshlab/alnParser.h"
|
||||
#include "../../common/alnParser.h"
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <vcg/space/box3.h>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user