Open GL Super Bible

Previous Table of Contents Next


A better way of approximating a curve is to use a GL_LINE_STRIP to play connect-the-dots. As the dots move closer together, a smoother curve materializes, without your having to specify all those points. Listing 6-5 shows the code from Listing 6-2, with the GL_POINTS replaced by GL_LINE_STRIP. The output from this new program, LSTRIPS, is shown in Figure 6-8. As you can see, the approximation of the curve is quite good. You will find this handy technique almost ubiquitous among OpenGL programs.


Figure 6-8  Output from the LSTRIPS program approximating a smooth curve

Listing 6-5 Code from the sample program LSTRIPS, demonstrating Line Strips

        // Call only once for all remaining points
        glBegin(GL_LINE_STRIP);
        z = -50.0f; 
        
        for(angle = 0.0f; angle <= (2.0f*GL_PI)*3.0f; angle += 0.1f)
                {
                x = 50.0f*sin(angle);
                y = 50.0f*cos(angle); 
        
                // Specify the point and move the Z value up a little
                glVertex3f(x, y, z);
                z += 0.5f;
                } 
        
        // Done drawing points
        glEnd();

Setting the Line Width

Just as you can set different point sizes, you can also specify various line widths when drawing lines. This is done with the glLineWidth function:

void glLineWidth(GLfloat width);

The glLineWidth function takes a single parameter that specifies the approximate width, in pixels, of the line drawn. Just like point sizes, not all line widths are supported, and you should check to make sure the line width you want to specify is available. Use the following code to get the range of line widths, and the smallest interval between them:

GLfloat sizes[2];   // Store supported line width range
GLfloat step;       // Store supported line width increments

// Get supported line width range and step size
glGetFloatv(GL_LINE_WIDTH_RANGE,sizes);
glGetFloatv(GL_LINE_WIDTH_GRANULARITY,&step);

Here the sizes array will contain two elements that contain the smallest and the largest valid value for glLineWidth. In addition, the variable step will hold the smallest step size allowable between the line widths. The OpenGL specification only requires that one line width, 1.0, be supported. The Microsoft implementation of OpenGL allows for line widths from 0.5 to 10.0, with 0.125 the smallest step size.

Listing 6-6 shows code for a more substantial example of glLineWidth. It’s from the program LINESW and draws ten lines of varying widths. It starts at the bottom of the window at –90 on the y-axis and climbs the y-axis 20 units for each new line. Every time it draws a new line, it increases the line width by 1. Figure 6-9 shows the output for this program.


Figure 6-9  Demonstration of glLineWidth from LINESW program

Listing 6-6 Drawing lines of various widths

// Called to draw scene
void RenderScene(void)
        {
        GLfloat y;             // Storage for varying Y coordinate
        GLfloat fSizes[2];     // Line width range metrics
        GLfloat fCurrSize;     // Save current size

        …
        …
        …

        // Get line size metrics and save the smallest value
        glGetFloatv(GL_LINE_WIDTH_RANGE,fSizes);
        fCurrSize = fSizes[0];

        // Step up Y axis 20 units at a time
        for(y = -90.0f; y < 90.0f; y += 20.0f)
                {
                // Set the line width
                glLineWidth(fCurrSize);

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

              // Increase the line width
              fCurrSize += 1.0f;
              }

        …
        …
        }

Notice that we used glVertex2f() this time instead of glVertex3f() to specify the coordinates for our lines. As mentioned, this is only a convenience because we are drawing in the xy plane, with a z value of zero. To see that you are still drawing lines in three dimensions, simply use the arrow keys to spin your lines around. You will see easily that all the lines lie on a single plane.

Line Stippling

In addition to changing line widths, you can create lines with a dotted or dashed pattern, called stippling. To use line stippling, you must first enable stippling with a call to

glEnable(GL_LINE_STIPPLE);

Then the function glLineStipple establishes the pattern that the lines will use for drawing.

void glLineStipple(GLint factor, GLushort pattern);


Reminder
Any feature or ability that is enabled by a call to glEnable() can be disabled by a call to glDisable().

The pattern parameter is a 16-bit value that specifies a pattern to use when drawing the lines. Each bit represents a section of the line segment that is either on or off. By default, each bit corresponds to a single pixel, but the factor parameter serves as a multiplier to increase the width of the pattern. For example, setting factor to 5 would cause each bit in the pattern to represent five pixels in a row that would be either on or off. Furthermore, bit 0 (the least significant bit) of the pattern is used first to specify the line. Figure 6-10 illustrates a sample bit pattern applied to a line segment.


Figure 6-10  Stipple pattern is used to construct a line segment


Why Are These Patterns Backward?
You might wonder why the bit pattern used for stippling is used in reverse when drawing the line. Internally, it’s much faster for OpenGL to shift this pattern to the left one place, each time it needs to get the next mask value. For high-performance applications, reversing this pattern internally (to make it easier for humans to understand) can take up precious processor time.

Listing 6-7 shows a sample of using a stippling pattern that is just a series of alternating On and Off bits (0101010101010101). This program draws ten lines from the bottom of the window up the y-axis to the top. Each line is stippled with the pattern 0x5555, but for each new line the pattern multiplier is increased by 1. You can clearly see the effects of the widened stipple pattern in Figure 6-11.


Figure 6-11  Output from the LSTIPPLE program


Previous Table of Contents Next