Open GL Super Bible

Previous Table of Contents Next


Listing 6-7 Code from LSTIPPLE that demonstrates the effect of factor on the bit pattern

// Called to draw scene
void RenderScene(void)
        {
        GLfloat y;                   // Storage for varying Y coordinate
        GLint factor = 1;            // Stippling factor
        GLushort pattern = 0x5555;   // Stipple pattern

        …
        …
        // Enable Stippling
        glEnable(GL_LINE_STIPPLE);

        // Step up Y axis 20 units at a time
        for(y = -90.0f; y < 90.0f; y += 20.0f)
                {
                // Reset the repeat factor and pattern
                glLineStipple(factor,pattern);

                // Draw the line
                glBegin(GL_LINES);
                        glVertex2f(-80.0f, y);
                        glVertex2f(80.0f, y);
                glEnd();

                factor++;
                }
        …
        …
        }

Drawing Triangles in 3D

You’ve seen how to draw points and lines, and even how to draw some enclosed polygons with GL_LINE_LOOP. With just these primitives, you could easily draw any shape possible in three dimensions. You could, for example, draw six squares and arrange them so they form the sides of a cube.

You may have noticed, however, that any shapes you create with these primitives are not filled with any color—after all, you are only drawing lines. In fact, all the previous example draws is a wireframe cube, not a solid cube. To draw a solid surface, you need more than just points and lines; you need polygons. A polygon is a closed shape that may or may not be filled with the currently selected color, and it is the basis of all solid-object composition in OpenGL.

Triangles: Your First Polygon

The simplest polygon possible is the triangle, with only three sides. The GL_TRIANGLES primitive is used to draw triangles, and it does so by connecting three vertices together. The following code draws two triangles using three vertices each, as shown in Figure 6-12:


Figure 6-12  Two triangles drawn using GL_TRIANGLES

glBegin(GL_TRIANGLES);
        glVertex2f(0.0f, 0.0f);         // V0
        glVertex2f(25.0f, 25.0f);       // V1
        glVertex2f(50.0f, 0.0f);        // V2

        glVertex2f(-50.0f, 0.0f);       // V3
        glVertex2f(-75.0f, 50.0f);      // V4
        glVertex2f(-25.0f, 0.0f);       // V5
glEnd();

Note that the triangles will be filled with the currently selected drawing color. If you don’t specify a drawing color at some point, you can’t be certain of the result (there is no default drawing color).


Choose the Fastest Primitives for Performance Tip
The triangle is the primitive of choice for the OpenGL programmer. You will find that, with a little work, any polygonal shape can be composed of one or more triangles placed carefully together. Most 3D accelerated hardware is highly optimized for the drawing of triangles. In fact, you will see many 3D benchmarks measured in triangles per second.

Winding

An important characteristic of any polygonal primitive is illustrated in Figure 6-12. Notice the arrows on the lines that connect the vertices. When the first triangle is drawn, the lines are drawn from V0 to V1, then to V2, and finally back to V0 to close the triangle. This path is in the order that the vertices are specified, and for this example, that order is clockwise from your point of view. The same directional characteristic is present for the second triangle, as well.

The combination of order and direction in which the vertices are specified is called winding. The triangles in Figure 6-12 are said to have clockwise winding because they are literally wound in the clockwise direction. If we reverse the positions of V4 and V5 on the triangle on the left, we get counterclockwise winding as shown in Figure 6-13.


Figure 6-13  Two triangles with different windings

OpenGL by default considers polygons that have counterclockwise winding to be front facing. This means that the triangle on the left in Figure 6-13 is showing us the front of the triangle, and the one on the right is showing the back side of the triangle.

Why is this important? As you will soon see, you will often want to give the front and back of a polygon different physical characteristics. You can hide the back of a polygon altogether, or give it a different color and reflective property as well (see Chapter 9). It’s very important to keep the winding of all polygons in a scene consistent, using front-facing polygons to draw the outside surface of any solid objects. In the upcoming section on solid objects, we will demonstrate this principle using some models that are more complex.

If you need to reverse the default behavior of OpenGL, you can do so by calling the function

glFrontFace(GL_CW);

The GL_CW parameter tells OpenGL that clockwise-wound polygons are to be considered front facing. To change back to counterclockwise winding for the front face, use GL_CCW.

Triangle Strips

For many surfaces and shapes, you will need to draw several connected triangles. You can save a lot of time by drawing a strip of connected triangles with the GL_TRIANGLE_STRIP primitive. Figure 6-14 shows the progression of a strip of three triangles specified by a set of five vertices numbered V0 through V4. Here you see the vertices are not necessarily traversed in the same order they were specified. The reason for this is to preserve the winding (counterclockwise) of each triangle.


Figure 6-14  The progression of a GL_TRIANGLE_STRIP

(By the way, for the rest of our discussion of polygonal primitives, we won’t be showing you any more code fragments to demonstrate the vertices and the glBegin statements. You should have the swing of things by now. Later, when we have a real sample program to work with, we’ll resume the examples.)

There are two advantages to using a strip of triangles instead of just specifying each triangle separately. First, after specifying the first three vertices for the initial triangle, you only need to specify a single point for each additional triangle. This saves a lot of time (as well as data space) when you have many triangles to draw. The second advantage is that it’s a good idea, as mentioned previously, to compose an object or surface out of triangles rather than some of the other primitives.


Another advantage to composing large flat surfaces out of several smaller triangles is that when lighting effects are applied to the scene, the simulated effects can be better reproduced by OpenGL. You’ll learn to apply this technique in Chapter 9.


Previous Table of Contents Next