Sign in to follow this  
squizm

Help with Display List memory leak

Recommended Posts

Hello,

I'm having some trouble with a function that creates/recreates my display list. This is called once at the beginning of the application and once every time a different terrain hex is selected. However, every time this function runs, the application eats up ~2400k more. Each time I run the function I delete the old display list and create a new one using these three lines:

[code]

glDeleteLists(terrainList, 1);
terrainList = glGenLists(1);
glNewList(terrainList, GL_COMPILE_AND_EXECUTE);
[/code]


Is this the correct method to do this? Or is this the culprit?


Here is the full function:
[code]

void PlayScreen::generateTerrainList()
{
for(int i = 0; i < tilesX; i++)
{
for(int j = 0; j < tilesY; j++)
{
heightMap[i][j] = perlin.GetHeight(i, j);
if(createNewMap)
hexMap[i][j] = HexNode(i+100, 0, j+100);
}
}


bool even = true;
glDeleteLists(terrainList, 1);
terrainList = glGenLists(1);
glNewList(terrainList, GL_COMPILE_AND_EXECUTE);
for( int x = 0; x < tilesX; x++ )
{
for( int y = 0; y < tilesY; y++ )
{
glMatrixMode(GL_MODELVIEW);
glShadeModel(GL_SMOOTH);
glPushMatrix();
glEnable(GL_COLOR_MATERIAL);

int height = heightMap[x][y];
if(height > 1.0f)
{
height = 4.0f;
hexMap[x][y].terrainType = TEX_DIRT;
hexMap[x][y].hexHeight = height;
glColor3f(1.0f, 1.0f, 1.0f);
}
else if(height > 0.3f)
{
height = 3.0f;
hexMap[x][y].terrainType = TEX_DIRT;
hexMap[x][y].hexHeight = height;
glColor3f(0.8f, 0.8f, 0.8f);
}
else if (height > -0.5)
{
height = 2.0f;
hexMap[x][y].terrainType = TEX_DIRT;
hexMap[x][y].hexHeight = height;
glColor3f(0.6f, 0.6f, 0.6f);
}
else
{
height = 1.0f;
hexMap[x][y].terrainType = TEX_DIRT;
glColor3f(0.4f, 0.4f, 0.4f);
}

glTranslatef(0, y*2, height);

hexMap[x][y].drawRenderMode();

//selected Hex
if(selectedX == x && selectedY == y)
{
glTranslatef(0.0f, 0.0f, height);
props[x][y].drawSelectBox();
glTranslatef(0.0f, 0.0f, -height);
}

glPopMatrix();
}
if(even)
{
glTranslatef(1.5, -1, 0);
even = false;
}
else
{
glTranslatef(1.5, 1, 0);
even = true;
}
}
glEndList();
createNewMap = false;
}
[/code]

Share this post


Link to post
Share on other sites
Hi! What does [font=CourierNew, monospace][size=2]createNewMap()[/size][/font][size=2][font="Arial"] do?[/font][/size]
[size=2][font="Arial"]
[/font][/size]
[size=2][font="Arial"]If it contains a "new" statement, remember to "delete" when you're done with the object.[/font][/size]
[size=2][font="Arial"]I advice to avoid using new unless you absolutely have to, -there's typically an easier way.[/font][/size]

Share this post


Link to post
Share on other sites
[quote name='SuperVGA' timestamp='1305552668' post='4811416']
Hi! What does [font="CourierNew, monospace"][size="2"]createNewMap()[/size][/font][size="2"][font="Arial"] do?[/font][/size]
[size="2"] [/size]
[size="2"][font="Arial"]If it contains a "new" statement, remember to "delete" when you're done with the object.[/font][/size]
[size="2"][font="Arial"]I advice to avoid using new unless you absolutely have to, -there's typically an easier way.[/font][/size]
[/quote]


createNewMap is a boolean that is used to determine if I need to get new perlin noise values used for the heightmap. There is no 'new' statement used.

Share this post


Link to post
Share on other sites
[quote name='Faireth' timestamp='1305553182' post='4811419']
[quote name='SuperVGA' timestamp='1305552668' post='4811416']
Hi! What does [font="CourierNew, monospace"][size="2"]createNewMap()[/size][/font][size="2"][font="Arial"] do?[/font][/size]

[size="2"][font="Arial"]If it contains a "new" statement, remember to "delete" when you're done with the object.[/font][/size]
[size="2"][font="Arial"]I advice to avoid using new unless you absolutely have to, -there's typically an easier way.[/font][/size]
[/quote]


createNewMap is a boolean that is used to determine if I need to get new perlin noise values used for the heightmap. There is no 'new' statement used.


[/quote]


My bad, i meant [color=#660066][font=CourierNew, monospace][size=2]GetHeight()[/size][/font][/color][color=#660066][size=2][font="Arial"], Also what does [/font][/size][/color][color=#1C2837][size=2][color=#000000][font=CourierNew, monospace]hexMap[/font][/color][color=#666600][font=CourierNew, monospace][[/font][/color][color=#000000][font=CourierNew, monospace]x[/font][/color][color=#666600][font=CourierNew, monospace]][[/font][/color][color=#000000][font=CourierNew, monospace]y[/font][/color][color=#666600][font=CourierNew, monospace]].[/font][/color][color=#000000][font=CourierNew, monospace]drawRenderMode[/font][/color][color=#666600][font="CourierNew, monospace"]()[/font][font="Arial"] do?[/font][/color][/size][/color]
The posted code looks fine, the problem is where stuff is created and destroyed. No new-statements : good for you! :)

Share this post


Link to post
Share on other sites
[quote]
My bad, i meant [color="#660066"][font="CourierNew, monospace"][size="2"]GetHeight()[/size][/font][/color][color="#660066"][size="2"][font="Arial"], Also what does [/font][/size][/color][color="#1C2837"][size="2"][color="#000000"][font="CourierNew, monospace"]hexMap[/font][/color][color="#666600"][font="CourierNew, monospace"][[/font][/color][color="#000000"][font="CourierNew, monospace"]x[/font][/color][color="#666600"][font="CourierNew, monospace"]][[/font][/color][color="#000000"][font="CourierNew, monospace"]y[/font][/color][color="#666600"][font="CourierNew, monospace"]].[/font][/color][color="#000000"][font="CourierNew, monospace"]drawRenderMode[/font][/color][color="#666600"][font="CourierNew, monospace"]()[/font][font="Arial"] do?[/font][/color][/size][/color]
The posted code looks fine, the problem is where stuff is created and destroyed. No new-statements : good for you! :)
[/quote]

PerlinNoise.cpp

[code]

double PerlinNoise::GetHeight(double x, double y) const
{
return amplitude * Total(x, y);
}
double PerlinNoise::Total(double i, double j) const
{
//properties of one octave (changing each loop)
double t = 0.0f;
double _amplitude = 1;
double freq = frequency;

for(int k = 0; k < octaves; k++)
{
t += GetValue(j * freq + randomseed, i * freq + randomseed) * _amplitude;
_amplitude *= persistence;
freq *= 2;
}

return t;
}

double PerlinNoise::GetValue(double x, double y) const
{
int Xint = (int)x;
int Yint = (int)y;
double Xfrac = x - Xint;
double Yfrac = y - Yint;

//noise values
double n01 = Noise(Xint-1, Yint-1);
double n02 = Noise(Xint+1, Yint-1);
double n03 = Noise(Xint-1, Yint+1);
double n04 = Noise(Xint+1, Yint+1);
double n05 = Noise(Xint-1, Yint);
double n06 = Noise(Xint+1, Yint);
double n07 = Noise(Xint, Yint-1);
double n08 = Noise(Xint, Yint+1);
double n09 = Noise(Xint, Yint);

double n12 = Noise(Xint+2, Yint-1);
double n14 = Noise(Xint+2, Yint+1);
double n16 = Noise(Xint+2, Yint);

double n23 = Noise(Xint-1, Yint+2);
double n24 = Noise(Xint+1, Yint+2);
double n28 = Noise(Xint, Yint+2);

double n34 = Noise(Xint+2, Yint+2);

//find the noise values of the four corners
double x0y0 = 0.0625*(n01+n02+n03+n04) + 0.125*(n05+n06+n07+n08) + 0.25*(n09);
double x1y0 = 0.0625*(n07+n12+n08+n14) + 0.125*(n09+n16+n02+n04) + 0.25*(n06);
double x0y1 = 0.0625*(n05+n06+n23+n24) + 0.125*(n03+n04+n09+n28) + 0.25*(n08);
double x1y1 = 0.0625*(n09+n16+n28+n34) + 0.125*(n08+n14+n06+n24) + 0.25*(n04);

//interpolate between those values according to the x and y fractions
double v1 = Interpolate(x0y0, x1y0, Xfrac); //interpolate in x direction (y)
double v2 = Interpolate(x0y1, x1y1, Xfrac); //interpolate in x direction (y+1)
double fin = Interpolate(v1, v2, Yfrac); //interpolate in y direction

return fin;
}

double PerlinNoise::Interpolate(double x, double y, double a) const
{
double negA = 1.0 - a;
double negASqr = negA * negA;
double fac1 = 3.0 * (negASqr) - 2.0 * (negASqr * negA);
double aSqr = a * a;
double fac2 = 3.0 * aSqr - 2.0 * (aSqr * a);

return x * fac1 + y * fac2; //add the weighted factors
}

double PerlinNoise::Noise(int x, int y) const
{
int n = x + y * 57;
n = (n << 13) ^ n;
int t = (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff;
return 1.0 - double(t) * 0.931322574615478515625e-9;/// 1073741824.0);
}
[/code]


HexNode.cpp

[code]

void HexNode::drawRenderMode()
{
glBindTexture(GL_TEXTURE_2D, terrainType);
// Top Hexagon
glBegin(GL_TRIANGLE_FAN);
glNormal3d(0, 1, 0);
glTexCoord2f(0.5f, 0.5f); glVertex3f( 0.0f, 0.0f, hexHeight ); //center
glTexCoord2f(1.0f, 0.5f); glVertex3f( 1.0f, 0.0f, hexHeight ); //right
glTexCoord2f(0.75f, 1.0f); glVertex3f( 0.5f, 1.0f, hexHeight ); //top right
glTexCoord2f(0.25f, 1.0f); glVertex3f( -0.5f, 1.0f, hexHeight ); //Top left
glTexCoord2f(0.0f, 0.5f); glVertex3f( -1.0f, 0.0f, hexHeight ); //left
glTexCoord2f(0.25f, 0.0f); glVertex3f( -0.5f, -1.0f, hexHeight ); //bottom left
glTexCoord2f(0.75f, 0.0f); glVertex3f( 0.5f, -1.0f, hexHeight ); //bottom right
glTexCoord2f(1.0f, 0.5f); glVertex3f( 1.0f, 0.0f, hexHeight ); //right
glEnd();

glBindTexture(GL_TEXTURE_2D, TEX_ROCK);
// bottom Hexagon
glBegin(GL_TRIANGLE_FAN);
glNormal3d(0, -1, 0);
glTexCoord2f(0.5f, 0.5f); glVertex3f( 0.0f, 0.0f, 0.0f ); //center
glTexCoord2f(1.0f, 0.5f); glVertex3f( 1.0f, 0.0f, 0.0f ); //right
glTexCoord2f(0.75f, 1.0f); glVertex3f( 0.5f, 1.0f, 0.0f ); //top right
glTexCoord2f(0.25f, 1.0f); glVertex3f( -0.5f, 1.0f, 0.0f ); //Top left
glTexCoord2f(0.0f, 0.5f); glVertex3f( -1.0f, 0.0f, 0.0f ); //left
glTexCoord2f(0.25f, 0.0f); glVertex3f( -0.5f, -1.0f, 0.0f ); //bottom left
glTexCoord2f(0.75f, 0.0f); glVertex3f( 0.5f, -1.0f, 0.0f ); //bottom right
glTexCoord2f(1.0f, 0.5f); glVertex3f( 1.0f, 0.0f, 0.0f ); //right
glEnd();

float vertices[3][3];
glBegin(GL_QUADS);
vertices[0][0] = 1.0f; vertices[0][1] = 0.0f; vertices[0][2] = hexHeight;
vertices[1][0] = 0.5f; vertices[1][1] = 1.0f; vertices[1][2] = hexHeight;
vertices[2][0] = 0.5f; vertices[2][1] = 1.0f; vertices[2][2] = 0.0f;
GameUtils::getInstance()->calcNormal(vertices, normal);
glNormal3d(normal[0], normal[1], normal[2]);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 0.0f, hexHeight ); //right vertex
glTexCoord2f(0.0f, 0.0f); glVertex3f( 0.5f, 1.0f, hexHeight );
glTexCoord2f(0.0f, 1.0f); glVertex3f( 0.5f, 1.0f, 0.0f );
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 0.0f, 0.0f );

vertices[0][0] = 0.5f; vertices[0][1] = 1.0f; vertices[0][2] = hexHeight;
vertices[1][0] = -0.5f; vertices[1][1] = 1.0f; vertices[1][2] = hexHeight;
vertices[2][0] = -0.5f; vertices[2][1] = 1.0f; vertices[2][2] = 0.0f;
GameUtils::getInstance()->calcNormal(vertices, normal);
glNormal3d(normal[0], normal[1], normal[2]);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 0.5f, 1.0f, hexHeight ); // top right vertex
glTexCoord2f(0.0f, 0.0f); glVertex3f( -0.5f, 1.0f, hexHeight );
glTexCoord2f(0.0f, 1.0f); glVertex3f( -0.5f, 1.0f, 0.0f );
glTexCoord2f(1.0f, 1.0f); glVertex3f( 0.5f, 1.0f, 0.0f );

vertices[0][0] = -0.5f; vertices[0][1] = 1.0f; vertices[0][2] = hexHeight;
vertices[1][0] = -1.0f; vertices[1][1] = 0.0f; vertices[1][2] = hexHeight;
vertices[2][0] = -1.0f; vertices[2][1] = 0.0f; vertices[2][2] = 0.0f;
GameUtils::getInstance()->calcNormal(vertices, normal);
glNormal3d(normal[0], normal[1], normal[2]);
glTexCoord2f(1.0f, 0.0f); glVertex3f( -0.5f, 1.0f, hexHeight ); // top left vertex
glTexCoord2f(0.0f, 0.0f); glVertex3f( -1.0f, 0.0f, hexHeight );
glTexCoord2f(0.0f, 1.0f); glVertex3f( -1.0f, 0.0f, 0.0f );
glTexCoord2f(1.0f, 1.0f); glVertex3f( -0.5f, 1.0f, 0.0f );

vertices[0][0] = -1.0f; vertices[0][1] = 0.0f; vertices[0][2] = hexHeight;
vertices[1][0] = -0.5f; vertices[1][1] = -1.0f; vertices[1][2] = hexHeight;
vertices[2][0] = -0.5f; vertices[2][1] = 0.0f; vertices[2][2] = 0.0f;
GameUtils::getInstance()->calcNormal(vertices, normal);
glNormal3d(normal[0], normal[1], normal[2]);
glTexCoord2f(1.0f, 0.0f); glVertex3f( -1.0f, 0.0f, hexHeight ); // left vertex
glTexCoord2f(0.0f, 0.0f); glVertex3f( -0.5f, -1.0f, hexHeight );
glTexCoord2f(0.0f, 1.0f); glVertex3f( -0.5f, -1.0f, 0.0f );
glTexCoord2f(1.0f, 1.0f); glVertex3f( -1.0f, 0.0f, 0.0f );

vertices[0][0] = -0.5f; vertices[0][1] = -1.0f; vertices[0][2] = hexHeight;
vertices[1][0] = 0.5f; vertices[1][1] = -1.0f; vertices[1][2] = hexHeight;
vertices[2][0] = 0.5f; vertices[2][1] = -1.0f; vertices[2][2] = 0.0f;
GameUtils::getInstance()->calcNormal(vertices, normal);
glNormal3d(normal[0], normal[1], normal[2]);
glTexCoord2f(1.0f, 0.0f); glVertex3f( -0.5f, -1.0f, hexHeight ); // bottom left vertex
glTexCoord2f(0.0f, 0.0f); glVertex3f( 0.5f, -1.0f, hexHeight );
glTexCoord2f(0.0f, 1.0f); glVertex3f( 0.5f, -1.0f, 0.0f );
glTexCoord2f(1.0f, 1.0f); glVertex3f( -0.5f, -1.0f, 0.0f );

vertices[0][0] = 0.5f; vertices[0][1] = -1.0f; vertices[0][2] = hexHeight;
vertices[1][0] = 1.0f; vertices[1][1] = 0.0f; vertices[1][2] = hexHeight;
vertices[2][0] = 1.0f; vertices[2][1] = 0.0f; vertices[2][2] = 0.0f;
GameUtils::getInstance()->calcNormal(vertices, normal);
glNormal3d(normal[0], normal[1], normal[2]);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 0.5f, -1.0f, hexHeight ); // bottom right vertex
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, 0.0f, hexHeight );
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 0.0f, 0.0f );
glTexCoord2f(1.0f, 1.0f); glVertex3f( 0.5f, -1.0f, 0.0f );
glEnd();

if(character.name != "null")
{
glColor3f(1.0f, 0.0f, 0.0f);
glDisable(GL_TEXTURE_2D);
glTranslatef(0.0f, 0.0f, 1.0f);
character.drawRenderMode();
glTranslatef(0.0f, 0.0f, -1.0f);
glEnable(GL_TEXTURE_2D);

glLineWidth(3.0f);
glBegin(GL_LINE_STRIP);
glVertex3f( 1.0f, 0.0f, hexHeight ); //right
glVertex3f( 0.5f, 1.0f, hexHeight ); //top right
glVertex3f( -0.5f, 1.0f, hexHeight ); //Top left
glVertex3f( -1.0f, 0.0f, hexHeight ); //left
glVertex3f( -0.5f, -1.0f, hexHeight ); //bottom left
glVertex3f( 0.5f, -1.0f, hexHeight ); //bottom right
glVertex3f( 1.0f, 0.0f, hexHeight );
glEnd();
glColor3f(1.0f, 1.0f, 1.0f);
}
}
[/code]

GameUtils

[code]

GLvoid GameUtils::calcNormal(float v[3][3], float normal[3])
{
float v1[3],v2[3]; // Vector 1 (x,y,z) & Vector 2 (x,y,z)
static const int x = 0; // Define X Coord
static const int y = 1; // Define Y Coord
static const int z = 2; // Define Z Coord

// Finds The Vector Between 2 Points By Subtracting
// The x,y,z Coordinates From One Point To Another.

// Calculate The Vector From Point 1 To Point 0
v1[x] = v[0][x] - v[1][x]; // Vector 1.x=Vertex[0].x-Vertex[1].x
v1[y] = v[0][y] - v[1][y]; // Vector 1.y=Vertex[0].y-Vertex[1].y
v1[z] = v[0][z] - v[1][z]; // Vector 1.z=Vertex[0].y-Vertex[1].z
// Calculate The Vector From Point 2 To Point 1
v2[x] = v[1][x] - v[2][x]; // Vector 2.x=Vertex[0].x-Vertex[1].x
v2[y] = v[1][y] - v[2][y]; // Vector 2.y=Vertex[0].y-Vertex[1].y
v2[z] = v[1][z] - v[2][z]; // Vector 2.z=Vertex[0].z-Vertex[1].z
// Compute The Cross Product To Give Us A Surface Normal
normal[x] = v1[y]*v2[z] - v1[z]*v2[y]; // Cross Product For Y - Z
normal[y] = v1[z]*v2[x] - v1[x]*v2[z]; // Cross Product For X - Z
normal[z] = v1[x]*v2[y] - v1[y]*v2[x]; // Cross Product For X - Y

normalize(normal); // Normalize The Vectors
}

GLvoid GameUtils::normalize(float vector[3])
{
float length; // Holds Unit Length
// Calculates The Length Of The Vector
length = (float)sqrt((vector[0]*vector[0]) + (vector[1]*vector[1]) + (vector[2]*vector[2]));

if(length == 0.0f) // Prevents Divide By 0 Error By Providing
length = 1.0f; // An Acceptable Value For Vectors To Close To 0.

vector[0] /= length; // Dividing Each Element By
vector[1] /= length; // The Length Results In A
vector[2] /= length; // Unit Normal Vector.

}
[/code]

Share this post


Link to post
Share on other sites
glDeleteLists (or any other glDelete* function) may not delete the object immediately. All that is required is that the object name be available for reuse immediately; the actual deletion may be placed in the command buffer (in which case it will occur when it's turn comes around) and memory associated with the list may be queued for deletion at a later time, may be retained in case the driver needs to reuse it again shortly, etc.

Share this post


Link to post
Share on other sites
[quote name='V-man' timestamp='1305561315' post='4811474']
[url="http://www.opengl.org/wiki/FAQ#Memory_Usage"]http://www.opengl.or...AQ#Memory_Usage[/url]
[/quote]

...interesting. Thank you for the link. I'll put this on the back burner for now and address it again if it starts to cause out of memory errors. Thanks all!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this