From 6afeecb7dbef4fa05cc242302ec697163be256f5 Mon Sep 17 00:00:00 2001 From: Paolo Cignoni cignoni Date: Tue, 30 Oct 2012 17:22:02 +0000 Subject: [PATCH] Cleaned up the texture loading procedure for meshes. Now there is texture deletion and a check that we do not load too much texture data. Added a global parameter MaxTextureSize, accessible by the preferences to control the maximum allowed texture data (default to 256mb). --- src/meshlab/glarea.cpp | 64 +++++++++++++++++++++++++--------- src/meshlab/glarea.h | 2 +- src/meshlab/glarea_setting.cpp | 2 ++ src/meshlab/glarea_setting.h | 3 +- 4 files changed, 53 insertions(+), 18 deletions(-) diff --git a/src/meshlab/glarea.cpp b/src/meshlab/glarea.cpp index 6e4e9be74..9d78d98c9 100644 --- a/src/meshlab/glarea.cpp +++ b/src/meshlab/glarea.cpp @@ -332,7 +332,12 @@ void GLArea::paintEvent(QPaintEvent */*event*/) QTime time; time.start(); - initTexture(); + if(!this->md()->isBusy()) + { + initTexture(hasToUpdateTexture); + hasToUpdateTexture=false; + } + glClearColor(1.0,1.0,1.0,0.0); glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); @@ -996,31 +1001,58 @@ int GLArea::RoundUpToTheNextHighestPowerOf2(unsigned int v) v++; return v; } -/** initTexture loads all the required textures (if necessary). -It is called every time in the glpaint. +/** \brief Manage the loading/allocation of the textures of the meshes + +It is called at every redraw for within the paint event with an active gl context. + It assumes that: -- there is a shared gl wrapper for all the contexts (same texture id for different glareas) -- the values stored in the glwrapper for the texture id are an indicator if there is the need of loading a texture (0 means load that texture) +- there is a single shared gl wrapper for each mesh for all the contexts (eg same texture id for different glareas), + +- No attempt of avoiding texture duplication if two models share the same texture file there are two texture id. + +- the values stored in the glwrapper for the texture id (glw.TMId()) is an indicator if there is the need of + loading a texture (empty vector means load that texture). */ -void GLArea::initTexture() +void GLArea::initTexture(bool reloadAllTexture) { - if(hasToUpdateTexture) + if(reloadAllTexture) // ALL the texture must to be re-loaded, so we clear all the TMId vectors { foreach (MeshModel *mp,this->md()->meshList) + { + if(!mp->glw.TMId.empty()) + { + glDeleteTextures(1,&(mp->glw.TMId[0])); mp->glw.TMId.clear(); + } + } + } + int totalTextureNum=0, toBeUpdatedNum=0; + foreach (MeshModel *mp, this->md()->meshList) + { + totalTextureNum+=mp->cm.textures.size(); + if(!mp->cm.textures.empty() && mp->glw.TMId.empty()) toBeUpdatedNum++; + } - qDebug("Beware: deleting the texutres could lead to problems for shared textures."); - hasToUpdateTexture = false; + if(toBeUpdatedNum==0) return; + + int singleMaxTextureSizeMpx = glas.maxTextureMemory/totalTextureNum; + int singleMaxTextureSize = RoundUpToTheNextHighestPowerOf2(int(sqrt(float(singleMaxTextureSizeMpx))*1024.0))/2; + + glEnable(GL_TEXTURE_2D); + GLint MaxTextureSize; + glGetIntegerv(GL_MAX_TEXTURE_SIZE,&MaxTextureSize); + if(singleMaxTextureSize < MaxTextureSize) + { + this->Logf(0,"There are too many textures (%i), reducing max texture size from %i to %i",totalTextureNum,MaxTextureSize,singleMaxTextureSize); + MaxTextureSize = singleMaxTextureSize; } foreach (MeshModel *mp, this->md()->meshList) { - if(!mp->cm.textures.empty() && mp->glw.TMId.empty()){ - glEnable(GL_TEXTURE_2D); - GLint MaxTextureSize; - glGetIntegerv(GL_MAX_TEXTURE_SIZE,&MaxTextureSize); + if(!mp->cm.textures.empty() && mp->glw.TMId.empty()) + { QString unexistingtext = "In mesh file " + mp->fullName() + " : Failure loading textures:
"; bool sometextfailed = false; for(unsigned int i =0; i< mp->cm.textures.size();++i) @@ -1064,9 +1096,9 @@ void GLArea::initTexture() imgScaled=img.scaled(bestW,bestH,Qt::IgnoreAspectRatio,Qt::SmoothTransformation); imgGL=convertToGLFormat(imgScaled); mp->glw.TMId.push_back(0); - qDebug(" will be loaded as GL texture id %i ( %i x %i )",mp->glw.TMId.back() ,imgGL.width(), imgGL.height()); glGenTextures( 1, (GLuint*)&(mp->glw.TMId.back()) ); glBindTexture( GL_TEXTURE_2D, mp->glw.TMId.back() ); + qDebug(" will be loaded as GL texture id %i ( %i x %i )",mp->glw.TMId.back() ,imgGL.width(), imgGL.height()); glTexImage2D( GL_TEXTURE_2D, 0, 3, imgGL.width(), imgGL.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, imgGL.bits() ); gluBuild2DMipmaps(GL_TEXTURE_2D, 3, imgGL.width(), imgGL.height(), GL_RGBA, GL_UNSIGNED_BYTE, imgGL.bits() ); } @@ -1080,9 +1112,9 @@ void GLArea::initTexture() if (sometextfailed) QMessageBox::warning(this,"Texture files has not been correctly loaded",unexistingtext); } - glDisable(GL_TEXTURE_2D); } - + glDisable(GL_TEXTURE_2D); + } void GLArea::setTextureMode(vcg::GLW::TextureMode mode) diff --git a/src/meshlab/glarea.h b/src/meshlab/glarea.h index ae4efaa63..a55b5f643 100644 --- a/src/meshlab/glarea.h +++ b/src/meshlab/glarea.h @@ -254,7 +254,7 @@ protected: void initializeGL(); int RoundUpToTheNextHighestPowerOf2(unsigned int v); - void initTexture(); + void initTexture(bool reloadAllTexture); void displayInfo(QPainter *painter); void displayRealTimeLog(QPainter *painter); diff --git a/src/meshlab/glarea_setting.cpp b/src/meshlab/glarea_setting.cpp index 50f88ab22..17b7ffe4c 100644 --- a/src/meshlab/glarea_setting.cpp +++ b/src/meshlab/glarea_setting.cpp @@ -23,6 +23,7 @@ void GLAreaSetting::initGlobalParameterSet( RichParameterSet * defaultGlobalPara defaultGlobalParamSet->addParam(new RichBool(pointDistanceAttenuationParam() , true,"Perspective Varying Point Size","If true the size of the points is drawn with a size proprtional to the distance from the observer.")); defaultGlobalParamSet->addParam(new RichBool(pointSmoothParam() , false,"Antialiased Point","If true the points are drawn with small circles instead of fast squared dots.")); defaultGlobalParamSet->addParam(new RichFloat(pointSizeParam() , 2.0, "Point Size","The base size of points when drawn")); + defaultGlobalParamSet->addParam(new RichInt(maxTextureMemoryParam() , 256, "Max Texture Memory (in MB)","The maximum quantity of texture memory allowed to load mesh textures")); } @@ -45,5 +46,6 @@ void GLAreaSetting::updateGlobalParameterSet( RichParameterSet& rps ) pointDistanceAttenuation = rps.getBool(this->pointDistanceAttenuationParam()); pointSmooth = rps.getBool(this->pointSmoothParam()); pointSize = rps.getFloat(this->pointSizeParam()); + maxTextureMemory = rps.getInt(this->maxTextureMemoryParam()); currentGlobalParamSet=&rps; } diff --git a/src/meshlab/glarea_setting.h b/src/meshlab/glarea_setting.h index 09ec74245..567298140 100644 --- a/src/meshlab/glarea_setting.h +++ b/src/meshlab/glarea_setting.h @@ -37,7 +37,8 @@ public: inline static QString pointSmoothParam() {return "MeshLab::Appearance::pointSmooth";} float pointSize; inline static QString pointSizeParam() {return "MeshLab::Appearance::pointSize";} - + inline static QString maxTextureMemoryParam() {return "MeshLab::Appearance::maxTextureMemory";} + int maxTextureMemory; void updateGlobalParameterSet( RichParameterSet& rps ); static void initGlobalParameterSet( RichParameterSet * defaultGlobalParamSet);