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).

This commit is contained in:
Paolo Cignoni cignoni 2012-10-30 17:22:02 +00:00
parent 345824ffe0
commit 6afeecb7db
4 changed files with 53 additions and 18 deletions

View File

@ -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 <i>" + mp->fullName() + "</i> : Failure loading textures:<br>";
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)

View File

@ -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);

View File

@ -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;
}

View File

@ -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);