textures saved in MeshModel - loadMesh works as expected

This commit is contained in:
alemuntoni 2021-06-01 13:10:44 +02:00
parent eb257d8cb6
commit cedf7f1dfd
9 changed files with 118 additions and 53 deletions

View File

@ -125,6 +125,8 @@ set(SOURCES
mlapplication.cpp
searcher.cpp)
set(RESOURCES meshlab-common.qrc)
set(TARGET_TYPE SHARED)
if(WIN32)
set(TARGET_TYPE STATIC)

View File

@ -122,6 +122,9 @@ SOURCES += \
ml_selection_buffers.cpp \
$$MESHLAB_EXTERNAL_DIRECTORY/easyexif/exif.cpp
RESOURCES += \
meshlab-common.qrc
macx:QMAKE_POST_LINK = "\
if [ -d $$MESHLAB_DISTRIB_DIRECTORY/meshlab.app/Contents/Frameworks/ ]; \
then \

BIN
src/common/img/dummy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/">
<file>img/dummy.png</file>
</qresource>
</RCC>

View File

@ -26,6 +26,7 @@
#include <QFileInfo>
#include "mesh_model.h"
#include "../utilities/load_save.h"
#include <wrap/gl/math.h>
@ -78,6 +79,66 @@ QString MeshModel::relativePathName(const QString& path) const
return relPath;
}
/**
* @brief Starting from the (still unloaded) textures contained in the contained
* CMeshO, loads the textures in the map of QImages contained in the MeshModel.
*
* The contained CMeshO will have a list of texture names like ":filename.png",
* and these names will be mapped with the actual loaded image in the map
* "textures".
*
* When a texture is not found, a dummy texture will be used (":dummy.png").
*
* Returns the list of non-loaded textures that have been modified with
* ":dummy.png" in the contained mesh.
*/
std::list<std::string> MeshModel::loadTextures(
GLLogStream* log,
vcg::CallBackPos* cb)
{
std::list<std::string> unloadedTextures;
for (std::string& textName : cm.textures){
if (textName.front() != ':'){
QImage img(":/img/dummy.png");
QFileInfo finfo(QString::fromStdString(textName));
try {
img = meshlab::loadImage(finfo.absoluteFilePath(), log, cb);
textName = ":" + finfo.fileName().toStdString();
} catch (const MLException& e) {
try { //could be relative to the meshmodel
QFileInfo mfi(fullName());
QString fn2 = mfi.absolutePath() + "/" + finfo.fileName();
img = meshlab::loadImage(fn2, log, cb);
textName = ":" + finfo.fileName().toStdString();
} catch (const MLException& e) {
if (log){
log->log(
GLLogStream::WARNING, "Failed loading " + textName +
"; using a dummy texture");
}
else {
std::cerr <<
"Failed loading " + textName + "; using a dummy texture\n";
}
unloadedTextures.push_back(textName);
textName = ":dummy.png";
}
}
textures[textName] = img;
}
}
return unloadedTextures;
}
QImage MeshModel::getTexture(const std::string& tn)
{
auto it = textures.find(tn);
if (it != textures.end())
return it->second;
else
return QImage();
}
int MeshModel::io2mm(int single_iobit)
{
switch(single_iobit)

View File

@ -133,7 +133,6 @@ public:
int idInFile() const {return idInsideFile;}
void setIdInFile(int id) {idInsideFile = id;}
// Some notes about the files and naming.
// Each mesh when shown in the layer dialog has a label.
// By default the label is just the name of the file, but the
@ -168,6 +167,10 @@ public:
bool visible; // used in rendering; Needed for toggling on and off the meshes
bool isVisible() const { return visible; }
std::list<std::string> loadTextures(GLLogStream* log = nullptr, vcg::CallBackPos* cb = nullptr);
QImage getTexture(const std::string& tn);
// This function is roughly equivalent to the updateDataMask,
// but it takes in input a mask coming from a filetype instead of a filter requirement (like topology etc)
void enable(int openingFileMask);

View File

@ -33,8 +33,15 @@
namespace meshlab {
void loadMesh(const QString& fileName, IOPlugin* ioPlugin, const RichParameterList& prePar, const std::list<MeshModel*>& meshList, std::list<int>& maskList, vcg::CallBackPos *cb)
std::list<std::string> loadMesh(
const QString& fileName,
IOPlugin* ioPlugin,
const RichParameterList& prePar,
const std::list<MeshModel*>& meshList,
std::list<int>& maskList,
vcg::CallBackPos *cb)
{
std::list<std::string> unloadedTextures;
QFileInfo fi(fileName);
QString extension = fi.suffix();
@ -61,6 +68,9 @@ void loadMesh(const QString& fileName, IOPlugin* ioPlugin, const RichParameterLi
MeshModel* mm = *itmesh;
int mask = *itmask;
std::list<std::string> tmp = mm->loadTextures(nullptr, cb);
unloadedTextures.insert(unloadedTextures.end(), tmp.begin(), tmp.end());
// 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...
@ -100,6 +110,7 @@ void loadMesh(const QString& fileName, IOPlugin* ioPlugin, const RichParameterLi
++itmask;
}
QDir::setCurrent(origDir); // undo the change of directory before leaving
return unloadedTextures;
}

View File

@ -34,7 +34,7 @@
namespace meshlab {
void loadMesh(
std::list<std::string> loadMesh(
const QString& fileName,
IOPlugin* ioPlugin,
const RichParameterList& prePar,

View File

@ -2164,19 +2164,19 @@ bool MainWindow::loadMesh(const QString& fileName, IOPlugin *pCurrentIOPlugin, c
{
if ((GLA() == NULL))
return false;
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();
// retrieving corresponding IO plugin
if (pCurrentIOPlugin == 0)
{
@ -2187,7 +2187,7 @@ bool MainWindow::loadMesh(const QString& fileName, IOPlugin *pCurrentIOPlugin, c
}
meshDoc()->setBusy(true);
pCurrentIOPlugin->setLog(&meshDoc()->Log);
unsigned int nMeshes = pCurrentIOPlugin->numberMeshesContainedInFile(extension, fileNameSansDir, prePar);
if (nMeshes != meshList.size()) {
QMessageBox::warning(
@ -2200,7 +2200,7 @@ bool MainWindow::loadMesh(const QString& fileName, IOPlugin *pCurrentIOPlugin, c
}
try {
pCurrentIOPlugin->open(extension, fileNameSansDir, meshList ,maskList, prePar, QCallBack);
meshlab::loadMesh(fileName, pCurrentIOPlugin, prePar, meshList, maskList, QCallBack);
}
catch(const MLException& e) {
QMessageBox::warning(
@ -2211,8 +2211,7 @@ bool MainWindow::loadMesh(const QString& fileName, IOPlugin *pCurrentIOPlugin, c
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.
@ -2221,15 +2220,15 @@ bool MainWindow::loadMesh(const QString& fileName, IOPlugin *pCurrentIOPlugin, c
//RichParameterSet par;
//pCurrentIOPlugin->initOpenParameter(extension, *mm, par);
//pCurrentIOPlugin->applyOpenParameter(extension, *mm, par);
QString err = pCurrentIOPlugin->warningMessageString();
if (!err.isEmpty())
{
QMessageBox::warning(this, tr("Opening Problems"), QString("While opening: '%1'\n\n").arg(fileName)+ err);
}
saveRecentFileList(fileName);
auto itmesh = meshList.begin();
auto itmask = maskList.begin();
for (unsigned int i = 0; i < meshList.size(); ++i){
@ -2284,12 +2283,11 @@ bool MainWindow::loadMesh(const QString& fileName, IOPlugin *pCurrentIOPlugin, c
}
updateLayerDialog();
meshDoc()->setBusy(false);
QDir::setCurrent(origDir); // undo the change of directory before leaving
return true;
}
@ -2442,7 +2440,8 @@ bool MainWindow::importMesh(QString fileName)
try {
QElapsedTimer t;
t.start();
meshlab::loadMesh(fileName, pCurrentIOPlugin, prePar, meshList, masks, QCallBack);
std::list<std::string> unloadedTextures =
meshlab::loadMesh(fileName, pCurrentIOPlugin, prePar, meshList, masks, QCallBack);
saveRecentFileList(fileName);
updateLayerDialog();
for (MeshModel* mm : meshList) {
@ -2451,6 +2450,11 @@ bool MainWindow::importMesh(QString fileName)
updateTexture(mm->id());
}
QString warningString = pCurrentIOPlugin->warningMessageString();
if (unloadedTextures.size() > 0){
warningString += "\n\nThe following textures have not been loaded: \n";
for (const std::string& txt : unloadedTextures)
warningString += QString::fromStdString(txt) + "\n";
}
if (!warningString.isEmpty()){
QMessageBox::warning(this, "Meshlab Opening Warning", warningString);
}
@ -2947,39 +2951,15 @@ void MainWindow::updateTexture(int meshid)
totalTextureNum+=mp->cm.textures.size();
int singleMaxTextureSizeMpx = int(textmemMB/((totalTextureNum != 0)? totalTextureNum : 1));
bool sometextfailed = false;
QString unexistingtext = "In mesh file <i>" + mymesh->fullName() + "</i> : Failure loading textures:<br>";
for(size_t i =0; i< mymesh->cm.textures.size();++i)
bool sometextnotfound = false;
for(const std::string& textname : mymesh->cm.textures)
{
QImage img;
QFileInfo fi(mymesh->cm.textures[i].c_str());
QFileInfo mfi(mymesh->fullName());
QString filename = fi.absoluteFilePath();
bool res = img.load(filename);
if(!res)
{
QString fn2 = mfi.absolutePath() + "/" + fi.fileName();
res = img.load(fn2);
if(!res)
{
QString errmsg = QString("Failure of loading texture %1").arg(fi.fileName());
meshDoc()->Log.log(GLLogStream::WARNING,qUtf8Printable(errmsg));
unexistingtext += "<font color=red>" + fi.fileName() + "</font><br>";
sometextfailed = sometextfailed || !res;
}
}
/*PLEASE EXPLAIN ME!*********************************************************************************************************************************************************************************/
//if(!res && filename.endsWith("dds",Qt::CaseInsensitive))
//{
// qDebug("DDS binding!");
// int newTexId = shared->bindTexture(filename);
// shared->txtcont.push_back(newTexId);
//}
/*PLEASE EXPLAIN ME!*********************************************************************************************************************************************************************************/
if (!res)
QImage img = mymesh->getTexture(textname);
if (img.isNull()){
img.load(":/images/dummy.png");
}
GLuint textid = shared->allocateTexturePerMesh(meshid,img,singleMaxTextureSizeMpx);
for(int tt = 0;tt < mvc->viewerCounter();++tt)
@ -2989,8 +2969,8 @@ void MainWindow::updateTexture(int meshid)
ar->setupTextureEnv(textid);
}
}
if (sometextfailed)
QMessageBox::warning(this,"Texture file has not been correctly loaded",unexistingtext);
if (sometextnotfound)
QMessageBox::warning(this,"Texture error", "Some texture has not been found. Using dummy texture.");
QDir::setCurrent(cwd);
}