Open GL Super Bible

Previous Table of Contents Next


Chapter 10
3D Modeling and Object Composition

What you’ll learn in this chapter:

How to… Functions You’ll Use

Assemble polygons to create 3D objects glBegin/glEnd/glVertex
Optimize object display with display lists glNewList/glEndList/glCallList

Your quiver is quite full of OpenGL arrows by now and it’s time to go hunting. Unlike previous chapters, this is going to be a project chapter, where you can put some of this stuff to practical use. We are going to define a problem or goal and pursue it to its logical end: a finished program. Along the way, you’ll gain some insight in how to break your objects and scenes into smaller, more manageable pieces. We’ll compose a complex object out of smaller, simpler objects, which in turn are composed of just the OpenGL primitives.

As a finishing touch we’ll show you why and how to apply display lists. One of the biggest reasons for using display lists is speed, so for the icing on the cake, we’ll even give you a crude but effective means of benchmarking your code.

Defining the Task

To demonstrate building a figure out of smaller simpler figures, we will use an interesting, yet simple example that creates a model of a metallic bolt (like those holding your disk drive together). Although this particular bolt may not exist in any hardware store, it will have the essential features. We shall make the bolt as simple as possible while still retaining the flavor of our task.

The bolt will have a six-sided head and a threaded shaft, like many typical steel bolts. Since this is a learning exercise, we’ll simplify the threads by making them raised on the surface of the bolt shaft rather than carved out of the shaft.

Figure 10-1 is a rough sketch of what we’re aiming for. We will build the three major components of this bolt—the head, the shaft, and the threads—individually and then put them together to form the final object.


Figure 10-1  The hex bolt to be modeled in this chapter

Choosing a Projection

Before we start constructing, we need a projection, a frame of reference for placing the objects. For an example like this, an orthogonal projection is the best choice. This is a typical choice for applications such as CAD, in which an object is being modeled and measured exactly. This bolt has a specific width, height, and number of threads and is comparatively small. Using a perspective projection would make sense if we were modeling something larger such as a landscape, where the effect would be more apparent.

Listing 10-1 is the code that creates the viewing volume. It creates an orthogonal projection and represents a coordinate system that reaches 100 units along the x- and y-axis. An extra 100 units is supplied along the z-axis where the viewer will be located.

Listing 10-1 Setting up the orthogonal projection for this chapter’s examples

// Change viewing volume and viewport.  Called when window is resized
void ChangeSize(GLsizei w, GLsizei h)
        {
        GLfloat nRange = 100.0f;

        // Prevent a divide by zero
        if(h == 0)
                h = 1;


        // Set Viewport to window dimensions
        glViewport(0, 0, w, h);

        // Reset coordinate system
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();

        // Establish clipping volume (left, right, bottom, top, near, far)
        if (w <= h)
                   glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w,
                    -nRange*2.0f, nRange*2.0f);
            else
                   glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange,
                    -nRange*2.0f, nRange*2.0f);

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        }

Choosing the Lighting and Material Properties

With the projection chosen, the next step is to select a lighting model for our view of the bolt. Listing 10-2 is the code to set up the rendering context including the lighting and material properties. We make sure the ambient light is bright enough to see all the features, and include a specular component to make it glisten just as a real metal bolt would. The single light source is positioned to the upper-left of the viewer.

Listing 10-2 Setting up the rendering context and lighting conditions

// This function does any needed initialization on the rendering
// context.  Here it sets up and initializes the lighting for
// the scene.
void SetupRC()
        {
        // Light values and coordinates
        GLfloat  ambientLight[] = {0.4f, 0.4f, 0.4f, 1.0f };
        GLfloat  diffuseLight[] = {0.7f, 0.7f, 0.7f, 1.0f };
        GLfloat  specular[] = { 0.9f, 0.9f, 0.9f, 1.0f};
        Glfloat  lightPos[] = { -50.0f, 200.0f, 200.0f, 1.0f };
        GLfloat  specref[] =  { 0.6f, 0.6f, 0.6f, 1.0f };


        glEnable(GL_DEPTH_TEST);       // Hidden surface removal
        glEnable(GL_CULL_FACE);// Do not calculate inside of solid object
        // Enable lighting
        glEnable(GL_LIGHTING);

        // Set up light 0
        glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambientLight);
        glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight);
        glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);
        glLightfv(GL_LIGHT0,GL_SPECULAR,specular);

        // Position and turn on the light
        glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
        glEnable(GL_LIGHT0);

        // Enable color tracking
        glEnable(GL_COLOR_MATERIAL);

        // Set material properties to follow glColor values
        glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

        // All materials hereafter have full specular reflectivity
        // with a moderate shine
        glMaterialfv(GL_FRONT, GL_SPECULAR,specref);
        glMateriali(GL_FRONT,GL_SHININESS,64);

        // Black background
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
        }


Previous Table of Contents Next