Open GL Super Bible

Previous Table of Contents Next


Listing 6-3 Code from POINTSZ that produces a spiral with gradually increasing point sizes

// Define a constant for the value of PI
#define GL_PI 3.1415f

// Called to draw scene
void RenderScene(void)
        {
        GLfloat x,y,z,angle;   // Storage for coordinates and angles
        GLfloat sizes[2];      // Store supported point size range
        GLfloat step;          // Store supported point size increments
        GLfloat curSize;       // Store current point size
        Ö
        Ö

        // Get supported point size range and step size
        glGetFloatv(GL_POINT_SIZE_RANGE,sizes);
        glGetFloatv(GL_POINT_SIZE_GRANULARITY,&step); 
  
        // Set the initial point size
        curSize = sizes[0];

        // Set beginning z coordinate
        z = -50.0f;

        // Loop around in a circle three times
        for(angle = 0.0f; angle <= (2.0f*GL_PI)*3.0f; angle += 0.1f)
                {
                // Calculate x and y values on the circle
                x = 50.0f*sin(angle);
                y = 50.0f*cos(angle); 
  
                // Specify the point size before the primitive is specified
                glPointSize(curSize);

                // Draw the point
                glBegin(GL_POINTS);
                        glVertex3f(x, y, z);
                glEnd();

                // Bump up the z value and the point size
                z += 0.5f;
                curSize += step;
                }

        Ö
        Ö
        }

This example demonstrates a couple of important things. For starters, notice that glPointSize must be called outside the glBegin/glEnd statements. Not all OpenGL functions are valid between these function calls. Though glPointSize affects all points drawn after it, you donít begin drawing points until you call glBegin(GL_POINTS). For a complete list of valid functions that you can call within a glBegin/glEnd sequence, see the Reference Section.

The most obvious thing you probably noticed about the POINTSZ excerpt is that the larger point sizes are represented simply by larger squares. This is the default behavior, but it typically is undesirable for many applications. Also, you may be wondering why you can increase the point size by a value less than one. If a value of 1.0 represents one pixel, how do you draw less than a pixel or, say, 2.5 pixels?

The answer is that the point size specified in glPointSize isnít the exact point size in pixels, but the approximate diameter of a circle containing all the pixels that will be used to draw the point. You can get OpenGL to draw the points as better points (that is, small filled circles) by enabling point smoothing, with a call to

glEnable(GL_POINT_SMOOTH);

Other functions affect how points and lines are smoothed, but this falls under the larger topic of anti-aliasing (Chapter 16). Anti-aliasing is a technique used to smooth out jagged edges and round out corners. We mention it now only in case you want to play with this on your own, and to whet your appetite for the rest of the book!

Drawing Lines in 3D

The GL_POINTS primitive we have been using thus far is pretty straightforward; for each vertex specified, it draws a point. The next logical step is to specify two vertices and draw a line between them. This is exactly what the next primitive, GL_LINES, does. The following short section of code draws a single line between two points (0,0,0) and (50, 50, 50):

glBegin(GL_LINES);
        glVertex3f(0.0f, 0.0f, 0.0f);
        glVertex3f(50.0f, 50.0f, 50.0f);
glEnd();

Note here that two vertices are used to specify a single primitive. For every two vertices specified, a single line is drawn. If you specify an odd number of vertices for GL_LINES, the last vertex is just ignored. Listing 6-4, from the LINES sample program on the CD, shows a more complex sample that draws a series of lines fanned around in a circle. The output from this program is shown in Figure 6-5.


Figure 6-5  Output from the LINES sample program

Listing 6-4 Code from the sample program LINES that displays a series of lines fanned in a circle

        // Call only once for all remaining points
        glBegin(GL_LINES);
        // All lines lie in the xy plane.
        z = 0.0f;
        for(angle = 0.0f; angle <= GL_PI*3.0f; angle += 0.5f)
                {
                // Top half of the circle
                x = 50.0f*sin(angle);
                y = 50.0f*cos(angle);
                glVertex3f(x, y, z);       // First end point of line 
        
                // Bottom half of the circle
                x = 50.0f*sin(angle+3.1415f);
                y = 50.0f*cos(angle+3.1415f);
                glVertex3f(x, y, z);       // Second end point of line
                } 
        
        // Done drawing points
glEnd();

Line Strips and Loops

The next two OpenGL primitives build on GL_LINES by allowing you to specify a list of vertices through which a line is drawn. When you specify GL_LINE_STRIP, a line is drawn from one vertex to the next in a continuous segment. The following code draws two lines in the xy plane that are specified by three vertices. Figure 6-6 shows an example.

glBegin(GL_LINE_STRIP);
        glVertex3f(0.0f, 0.0f, 0.0f);     // V0
        glVertex3f(50.0f, 50.0f, 0.0f);   // V1
        glVertex3f(50.0f, 100.0f, 0.0f);  // V2
glEnd();


Figure 6-6  An example of a GL_LINE_STRIP specified by three vertices

The last line-based primitive is the GL_LINE_LOOP. This primitive behaves just like a GL_LINE_STRIP, but one final line is drawn between the last vertex specified and the first one specified. This is an easy way to draw a closed-line figure. Figure 6-7 shows a GL_LINE_LOOP drawn using the same vertices as for the GL_LINE_STRIP in Figure 6-6.


Figure 6-7  The same vertices from Figure 6-6, used by a GL_LINE_LOOP primitive

Approximating Curves with Straight Lines

The POINTS example program, shown earlier in Figure 6-3, showed you how to plot points along a spring-shaped path. You may have been tempted to push the points closer and closer together (by setting smaller values for the angle increment) to create a smooth spring-shaped curve instead of the broken points that only approximated the shape. This is a perfectly valid operation, but it can be quite slow for larger and more complex curves with thousands of points.


Previous Table of Contents Next