I am curious about how OpenGL assigns Multiple Display List IDs.
Currently I have:
void MyCreateList() {
MyListID = glGenLists(1);
glNewList(MyListID, GL_COMPILE);
//gluSphere(qobj, 1.0, 20, 20); //Sphere
//gluCylinder(qobj, 1.0, 0.0, 2.0, 20, 8); //Cylinder
gluDisk(qobj, 0.25, 1.0, 20, 3); //Disk
//gluPartialDisk(qobj, 0.5, 1.0, 26, 13, 0, 180); //PartialDisk
glEndList();
}
=> ID of One Display List.
void MyCreateList() {
GLuint listOne, listTwo, listThree, listFour;
listOne = glGenLists(4);
listTwo = listOne + 1;
listThree = listTwo + 1;
listFour = listThree + 1;
glNewList(listThree, GL_COMPILE);
gluSphere(qobj, 1.0, 20, 20); //Sphere
gluCylinder(qobj, 1.0, 0.0, 2.0, 20, 8); //Cylinder
gluDisk(qobj, 0.25, 1.0, 20, 3); //Disk
gluPartialDisk(qobj, 0.5, 1.0, 26, 13, 0, 180); //PartialDisk
glEndList();
}
=> ID of Multiple Display Lists.
Here's the desired result:
If you assign only one ID using the Display List, there is no problem, but if you assign more than one ID, it will not work.
Any ideas?
A display list groups a sequence of OpenGL commands and data, so that it can be executed repeatedly after its initial creation, in order to improve the program's performance (more information on display lists with various code examples can be found here).
Note that display lists have been deprecated in OpenGL 3.0 and removed in OpenGL 3.1, which was already discussed here: Why were display lists deprecated in opengl 3.1?
The four glu*()
calls in your second code snippet create graphics primitives, that are stored in only one of the four generated display lists, namely in listThree
. In that display list, the sphere, cylinder, disk and the partial disk are placed at the same position, and will therefore overlap. Also, the four display list ID variables listOne, listTwo, listThree, listFour
are local to the scope of the function MyCreateList()
, so they will not be accessible after the function call.
If the program should generate the result from the posted screenshot, then only one shape (generated with gluDisk()
) and one display list is required. (Why should multiple display lists be used for that task?)
If this is an educational exercise, I think it's about putting transforms into a display list, to generate the shown skewed scape, for example like this (disk stretched with glScalef()
and turned with glRotatef()
):
/* $ gcc -Wall -pedantic skewed.c -o skewed -lGL -lGLU -lglut && ./skewed */
#include <GL/glut.h>
static GLuint _displayList = 0;
static void _create_display_list(void)
{
GLUquadricObj *qobj = NULL;
_displayList = glGenLists(1);
qobj = gluNewQuadric();
glNewList(_displayList, GL_COMPILE);
glPushMatrix();
glRotatef(30.0f, 0.0f, 0.0f, 1.0f);
glScalef(0.8f, 1.0f, 0.8f);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
gluDisk(qobj, 0.25, 1.0, 20, 3);
glPopMatrix();
glEndList();
gluDeleteQuadric(qobj);
qobj = NULL;
}
static void _reshape(GLint w, GLint h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-1.0f, 1.0f, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
static void _display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glCallList(_displayList);
glFlush();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutCreateWindow("test");
glutDisplayFunc(_display);
glutReshapeFunc(_reshape);
_create_display_list();
glutMainLoop();
return 0;
}
And, here a modified example, that illustrates the use of multiple display lists:
/* $ gcc -Wall -pedantic test_gl.c -o test_gl -lGL -lGLU -lglut && ./test_gl */
#include <GL/glut.h>
static GLuint _displayList = 0;
static void _create_display_lists(void)
{
GLUquadricObj *qobj = NULL;
_displayList = glGenLists(4);
/* shapes (white) */
qobj = gluNewQuadric();
glNewList(_displayList + 2, GL_COMPILE);
glPushMatrix();
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glTranslatef(-2.0f, -2.0f, 0.0f);
gluSphere(qobj, 1.0, 20, 20);
glTranslatef(4.0f, 0.0f, 0.0f);
gluCylinder(qobj, 1.0, 0.0, 2.0, 20, 8);
glTranslatef(0.0f, 4.0f, 0.0f);
gluDisk(qobj, 0.25, 1.0, 20, 3);
glTranslatef(-4.0f, 0.0f, 0.0f);
gluPartialDisk(qobj, 0.5, 1.0, 26, 13, 0, 180);
glPopMatrix();
glEndList();
gluDeleteQuadric(qobj);
qobj = NULL;
/* diagonal line (cyan) */
glNewList(_displayList, GL_COMPILE);
glBegin(GL_LINES);
glColor4f(1.0f, 1.0f, 0.0f, 1.0f);
glVertex4f(-3.0f, 3.0f, 0.0f, 1.0f);
glVertex4f(3.0f, 3.0f, 0.0f, 1.0f);
glEnd();
glEndList();
/* horizontal line (yellow) */
glNewList(_displayList + 1, GL_COMPILE);
glBegin(GL_LINES);
glColor4f(0.0f, 1.0f, 1.0f, 1.0f);
glVertex4f(-3.0f, -3.0f, 0.0f, 1.0f);
glVertex4f(3.0f, 3.0f, 0.0f, 1.0f);
glEnd();
glEndList();
/* diagonal line (magenta) */
glNewList(_displayList + 3, GL_COMPILE);
glBegin(GL_LINES);
glColor4f(1.0f, 0.0f, 1.0f, 1.0f);
glVertex4f(-3.0f, 3.0f, 0.0f, 1.0f);
glVertex4f(3.0f, -3.0f, 0.0f, 1.0f);
glEnd();
glEndList();
}
static void _reshape(GLint w, GLint h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-4.0f, 4.0f, -4.0f, 4.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
static void _display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glCallList(_displayList);
glCallList(_displayList + 1);
glCallList(_displayList + 2);
glCallList(_displayList + 3);
glFlush();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutCreateWindow("test");
glutDisplayFunc(_display);
glutReshapeFunc(_reshape);
glLineWidth(5.0f);
glDisable(GL_DEPTH_TEST);
_create_display_lists();
glutMainLoop();
return 0;
}
The documentation of all the used GL/GLU functions can be found there:
https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/
The documentation of all the used GLUT functions can be found there:
https://www.opengl.org/resources/libraries/glut/spec3/spec3.html
More information on the topic of "Legacy OpenGL" can be found here.