Heirarchical Display List Problem

I am having problems with the following piece of code. Display lists are supposed to support heirarchy. But this code does not work. Here is the code.

// empty.cpp : Defines the entry point for the console application.
//

#include <gl\glut.h>

#define width 32
GLuint texName;
GLubyte stripeImage[4*width];
GLfloat zero[] = {1,0,0,0};
GLfloat slanted[] = {1,1,1,0};
GLfloat *coeff;
GLenum plane;
GLint genMode;
GLuint backList=0,legList=0,seatList=0,supportList=0,chairList=0,tableList=0;
GLUquadricObj *qobj;
GLfloat legTx=0,legTy=0,legTz=0,tfactor=0.05,sceneRot=0;

void drawLegList()
{
if(!legList)
{
//glBindTexture(GL_TEXTURE_2D,texture(TEX_WOOD1));
legList = glGenLists(1);
glNewList(legList,GL_COMPILE);
glPushMatrix();
glRotatef(90,1,0,0);
gluCylinder(qobj,0.1,0.1,0.85,20,20);
glPopMatrix();
glEndList();

	glCallList(legList);
}
else if(legList)
{
	glCallList(legList);
	//printf("

call list called
");
}
}

void init()
{
glClearColor(0,0,0,0);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);

glFrontFace(GL_CW);
//glCullFace(GL_BACK);
glMaterialf(GL_FRONT,GL_SHININESS,64.0);
qobj = gluNewQuadric();
gluQuadricDrawStyle(qobj,GLU_SILHOUETTE);
//gluQuadricDrawStyle(qobj,GLU_FILL);
gluQuadricNormals(qobj,GLU_SMOOTH);
gluQuadricOrientation(qobj,GLU_OUTSIDE);
gluQuadricTexture(qobj,GL_TRUE);

}

void display(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
if(!chairList)
{
chairList = glGenLists(1);
glNewList(chairList,GL_COMPILE);
drawLegList();
glTranslatef(-1.5,0,0);
glutSolidSphere(0.6,20,20);
glTranslatef(1.5,0,0);
glEndList();
glCallList(chairList);
}
else
{
glCallList(chairList);
}
glFlush();
//glutPostRedisplay();
}

void reshape(int w,int h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60,(float)w/(float)h,0.1,100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,1,-3,0,0,0,0,1,0);
}

void keyboard(unsigned char key,int x, int y)
{
switch(key)
{
case 27:
exit(0);
break;
case ‘e’:
genMode = GL_EYE_LINEAR;
plane = GL_EYE_PLANE;

	glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,genMode);
	glTexGenfv(GL_S,plane,coeff);
	glutPostRedisplay();
	break;

case 'o':
	genMode = GL_OBJECT_LINEAR;
	plane = GL_OBJECT_PLANE;

	glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,genMode);
	glTexGenfv(GL_S,plane,coeff);
	glutPostRedisplay();
	break;
case 'j':
	//teapotRot+=factor;
	legTx+=tfactor;
	glutPostRedisplay();
	break;
case 'k':
	//teapotTranslateX+=tfactor;
	legTy+=tfactor;
	glutPostRedisplay();
	break;
case 'l':
	//teapotTranslateY+=tfactor;
	legTz+=tfactor;
	glutPostRedisplay();
	break;
case '-':
	tfactor*=-1;
	break;
case 'p':
		sceneRot+=5;
		glutPostRedisplay();
		break;

}

}

int main(int argc, char* argv[])
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(200,200);
glutCreateWindow(“Empty”);

init();
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutDisplayFunc(display);
glutMainLoop();

return 0;

}

The ouput of this code should b a cylinder with a sphere to left of it. In the first screen both appear, but when screen is resized, the sphere vanishes. You can update the screen by any other means. If we remove the heirarchical display lists from the display routine, the code will run fine . Am i ignoring something ? Plz let me know

To define hierarchical display lists the internal display lists must have already been defined.

According to the glNewList reference -

Error - GL_INVALID_OPERATION is generated if glEndList is called wihtout a preceding glNewList, or if glNewList is called while a display list is being defined.

What is happening is that chairList is being defined, it enters the drawLegList function, ignores the glNewList(legList,…) because it is an error, defines the display list based on what is in that function, then hits the glEndList which ends the definition of the chairList. Then it returns to the display functions and draws the gluQuadric immediately. When you update the image by resizing the chairList is displayed using what you would expect to be the legList.

Solution: Define the legList before defining the chairList. When defining the chairList call glCallList( legList ) within the display list definition and it should work. Modifications below - you can ignore the #include <stdlib.h> needed it for Linux build.

 
// empty.cpp : Defines the entry point for the console application.
//

#include <stdlib.h>
#include <GL/glut.h>

#define width 32
GLuint texName;
GLubyte stripeImage[4*width];
GLfloat zero[] = {1,0,0,0};
GLfloat slanted[] = {1,1,1,0};
GLfloat *coeff;
GLenum plane;
GLint genMode;
GLuint backList=0,legList=0,seatList=0,supportList=0,chairList=0,tableList=0;
GLUquadricObj *qobj;
GLfloat legTx=0,legTy=0,legTz=0,tfactor=0.05,sceneRot=0;

void drawLegList()
{
//if(!legList)
//{
//glBindTexture(GL_TEXTURE_2D,texture(TEX_WOOD1));
legList = glGenLists(1);
glNewList(legList,GL_COMPILE);
glPushMatrix();
glRotatef(90,1,0,0);
gluCylinder(qobj,0.1,0.1,0.85,20,20);
glPopMatrix();
glEndList();

//glCallList(legList);
//}
//else if(legList)
//{
//glCallList(legList);
//printf("
call list called
");
//}
}

void init()
{
glClearColor(0,0,0,0);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);

glFrontFace(GL_CW);
//glCullFace(GL_BACK);
glMaterialf(GL_FRONT,GL_SHININESS,64.0);
qobj = gluNewQuadric();
gluQuadricDrawStyle(qobj,GLU_SILHOUETTE);
//gluQuadricDrawStyle(qobj,GLU_FILL);
gluQuadricNormals(qobj,GLU_SMOOTH);
gluQuadricOrientation(qobj,GLU_OUTSIDE);
gluQuadricTexture(qobj,GL_TRUE);

drawLegList();
chairList = glGenLists(1);
glNewList(chairList,GL_COMPILE);
glCallList( legList );
glTranslatef(-1.5,0,0);
glutSolidSphere(0.6,20,20);
glTranslatef(1.5,0,0);
glEndList();
}

void display(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glCallList(chairList);
glFlush();
//glutPostRedisplay();
}

void reshape(int w,int h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60,(float)w/(float)h,0.1,100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,1,-3,0,0,0,0,1,0);
}

void keyboard(unsigned char key,int x, int y)
{
switch(key)
{
case 27:
exit(0);
break;
case 'e':
genMode = GL_EYE_LINEAR;
plane = GL_EYE_PLANE;

glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,genMode);
glTexGenfv(GL_S,plane,coeff);
glutPostRedisplay();
break;

case 'o':
genMode = GL_OBJECT_LINEAR;
plane = GL_OBJECT_PLANE;

glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,genMode);
glTexGenfv(GL_S,plane,coeff);
glutPostRedisplay();
break;
case 'j':
//teapotRot+=factor;
legTx+=tfactor;
glutPostRedisplay();
break;
case 'k':
//teapotTranslateX+=tfactor;
legTy+=tfactor;
glutPostRedisplay();
break;
case 'l':
//teapotTranslateY+=tfactor;
legTz+=tfactor;
glutPostRedisplay();
break;
case '-':
tfactor*=-1;
break;
case 'p':
sceneRot+=5;
glutPostRedisplay();
break;

}
}

int main(int argc, char* argv[])
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(200,200);
glutCreateWindow("Empty");

init();
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutDisplayFunc(display);
glutMainLoop();

return 0;
}

 

thanx a lot man