c++openglglu

How do I assign Multiple Display List IDs to GLU Modeling in OpenGL?


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:

depiction of 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?


Solution

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

    screenshot of application window displaying desired result


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

    screenshot of application window

    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.