## Draw Something!

Now, we have a way of specifying a point in space to OpenGL. What can we make of it, and how do we tell OpenGL what to do with it? Is this vertex a point that should just be plotted? Is it the endpoint of a line or the corner of a cube? The geometric definition of a vertex is not just a point in space, but rather the point at which an intersection of two lines or curves occurs. This is the essence of primitives.

A primitive is simply the interpretation of a set or list of vertices into
some shape drawn on the screen. There are 10 primitives in OpenGL, from a simple
point drawn in space to a closed polygon of any number of sides. One way to draw
primitives is to use the `glBegin` command to tell OpenGL to begin
interpreting a list of vertices as a particular primitive. You then end the list
of vertices for that primitive with the `glEnd` command. Kind of
intuitive, don't you think?

### Drawing Points

Let's begin with the first and simplest of primitives: points. Look at the following code:

glBegin(GL_POINTS); // Select points as the primitive glVertex3f(0.0f, 0.0f, 0.0f); // Specify a point glVertex3f(50.0f, 50.0f, 50.0f); // Specify another point glEnd(); // Done drawing points

The argument to `glBegin`, `GL_POINTS`, tells OpenGL that the
following vertices are to be interpreted and drawn as points. Two vertices are
listed here, which translates to two specific points, both of which would be
drawn.

This example brings up an important point about `glBegin` and
`glEnd`: You can list multiple primitives between calls as long as they
are for the same primitive type. In this way, with a single
`glBegin`/`glEnd` sequence, you can include as many primitives as
you like. This next code segment is wasteful and will execute more slowly than
the preceding code:

glBegin(GL_POINTS); // Specify point drawing glVertex3f(0.0f, 0.0f, 0.0f); glEnd(); glBegin(GL_POINTS); // Specify another point glVertex3f(50.0f, 50.0f, 50.0f); glEnd()

**Indenting Your Code**

In the foregoing examples, did you notice the indenting style used for the
calls to `glVertex`? Most OpenGL programmers use this convention to make
the code easier to read. It is not required, but it does make finding where
primitives start and stop easier.

#### Our First Example

The code in Listing 3.2 draws some points in our 3D environment. It uses some
simple trigonometry to draw a series of points that form a corkscrew path up the
z-axis. This code is from the POINTS program, which is on the CD in the
subdirectory for this chapter. All the sample programs use the framework we
established in Chapter 2. Notice that in the `SetupRC` function, we are
setting the current drawing color to green.

#### Listing 3.2 Rendering Code to Produce a Spring-Shaped Path of Points

// Define a constant for the value of PI #define GL_PI 3.1415f // This function does any needed initialization on the rendering // context. void SetupRC() { // Black background glClearColor(0.0f, 0.0f, 0.0f, 1.0f ); // Set drawing color to green glColor3f(0.0f, 1.0f, 0.0f); } // Called to draw scene void RenderScene(void) { GLfloat x,y,z,angle; // Storage for coordinates and angles // Clear the window with current clearing color glClear(GL_COLOR_BUFFER_BIT); // Save matrix state and do the rotation glPushMatrix(); glRotatef(xRot, 1.0f, 0.0f, 0.0f); glRotatef(yRot, 0.0f, 1.0f, 0.0f); // Call only once for all remaining points glBegin(GL_POINTS); 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(); // Restore transformations glPopMatrix(); // Flush drawing commands glFlush(); }

Only the code between calls to `glBegin` and `glEnd` is
important for our purpose in this and the other examples for this chapter. This
code calculates the x and y coordinates for an angle that spins between 0°
and 360° three times. We express this programmatically in radians rather
than degrees; if you don't know trigonometry, you can take our word for it.
If you're interested, see the box "The Trigonometry of
Radians/Degrees." Each time a point is drawn, the z value is increased
slightly. When this program is run, all you see is a circle of points because
you are initially looking directly down the z-axis. To see the effect, use the
arrow keys to spin the drawing around the x- and y-axes. The effect is
illustrated in Figure 3.3.

**Figure 3.3 Output from the POINTS sample program.**

**One Thing at a Time**

Again, don't get too distracted by the functions in this example that we
haven't covered yet (`glPushMatrix`, `glPopMatrix`, and
`glRotate`). These functions are used to rotate the image around so you
can better see the positioning of the points as they are drawn in 3D space. We
cover these functions in some detail in Chapter 4. If we hadn't used these
features now, you wouldn't be able to see the effects of your 3D drawings,
and this and the following sample programs wouldn't be very interesting to
look at. For the rest of the sample code in this chapter, we show only the code
that includes the `glBegin` and `glEnd` statements.

**The Trigonometry of Radians/Degrees**

The figure in this box shows a circle drawn in the xy plane. A line segment
from the origin (0,0) to any point on the circle makes an angle (a) with the
x-axis. For any given angle, the trigonometric functions sine and cosine return
the x and y values of the point on the circle. By stepping a variable that
represents the angle all the way around the origin, we can calculate all the
points on the circle. Note that the C runtime functions `sin()` and
`cos()` accept angle values measured in radians instead of degrees. There
are 2*PI radians in a circle, where PI is a nonrational number that is
approximately 3.1415. (*Nonrational* means there are an infinite number of
values past the decimal point.)