By using the move-draw style subroutines, it is possible to draw any of the primitive geometric figures in GL (except curves and surfaces). However, because these primitives are drawn so often, GL provides subroutines to draw them. The following sections explain GL high-level drawing:

- Rectangles
- Circles
- Arcs
- Polygon outlines and filled polygons

Most of the high-level subroutine names
follow a pattern. If the geometric figures they draw are filled, the original
subroutine name has a lowercase **f** appended to it. For example, the
**rect**
subroutine draws a rectangular outline, while **rectf**
draws a filled (solid) rectangle. The parameters to the subroutines can
be short integers (16 bits), long integers (32 bits), or floating-point
numbers (32 bits). Floating point is the default, but if the parameter
type is a short integer, there is a lowercase **s** suffix. If the parameter
type is a long integer, the subroutine name takes a lowercase **i**
suffix. As with the **v**
subroutine, only the least significant 24 bits of the long integer are
considered .

arc | |

Draws a circular arc. | |

arcf | |

Draws a pie-shaped filled circular arc. | |

circ | |

Draws a circle. | |

circf | |

Draws a filled circle. | |

polf | |

Draws a filled polygon. | |

poly | |

Draws a polygon. | |

polygonlist | |

Draws multiple, disjointed polygons. | |

polylinelist | |

Draws multiple, disjointed polylines. | |

rect | |

Draws a rectangle. | |

rectf | |

Draws a filled rectangle. | |

sbox | |

Draws a screen-aligned rectangle. | |

sboxf | |

Draws a filled screen-aligned rectangle. | |

splf | |

Draws a shaded filled polygon. |

GL provides two types of rectangle subroutines:
filled and unfilled. Filled rectangles are just rectangular polygons, and
unfilled rectangles are rectangular outlines. In both types of subroutines,
only the *x* and *y* coordinates of the corners of the rectangle
are given, and the *z* coordinate is assumed to be zero. The rectangle
is assumed to be aligned with the *x* and *y* axes.

The following table lists the six different forms of the rectangle subroutine.

Forms of the Rectangle Subroutine | ||

Parameter type |
Filled |
Unfilled |

short integer | rectfs |
rects |

long integer | rectfi |
recti |

floating point | rectf |
rect |

The parameters to all six versions of
the **rect**
rectangle subroutines are the same: rect(*x1, y1, x2, y2*).
The point defined by the *x1, y1* parameters is one corner of
the rectangle and that defined by the *x2, y2* parameters is
the opposite corner. Because the rectangle is assumed to be aligned with
the axes, the coordinates of the other corners are defined by the *x1, y2*
and *y1, x2* parameters, respectively. The syntax is as follows:

void rect(Coord x1, Coord y1, Coord x2, Coord y2)

Rectangles can undergo three-dimensional
geometric transformations, and the resulting figure need not appear to
be a rectangle. (For example, imagine rotating the rectangle about the
*x* axis so that one end is farther from you and then viewing it in
perspective. On the screen, the rotated rectangle appears to be a trapezoid.)
Rectangles drawn with the **rect**
subroutine (and also circles, arcs, and other 2-D figures) can be positioned
anywhere in world space with the use of the routines described in "Working
With Coordinate Systems".

It is important to understand that the
matrix manipulation routines (for instance, **translate**,
**rotate**,
and **scale**)
execute considerably slower than the drawing subroutines such as the begin-end
style subroutines. Therefore, it is almost always more efficient to draw
the desired rectangle in its final position with the subroutines **bgnpolygon**
and **endpolygon**,
rather than using the **rect**
subroutine with **translate**, **rotate**, and **scale**. Performance
considerations do not necessarily apply to circles and arcs, in part because
these are more complex figures and are unique in the convenience they provide.

The following example program draws a
chess board with black and white squares on a green background using the
**rect**
subroutine. In addition, to demonstrate the unfilled rectangle subroutines,
there is a red line outlining the board.

#include <gl/gl.h>

main() { Int32 i, j;

prefposition(100, 500, 100, 500); winopen("chessboard"); color(GREEN); clear(); for (i = 0; i < 8; i = i+1) for (j = 0; j < 8; j = j+1) { if (odd(i+j)) color(WHITE); else color(BLACK); rectfi(100 + i*25, 100 + j*25, 124 + i*25, 124 + j*25); } color(RED); recti(97, 97, 302, 302); sleep(3); }

odd(n) /* returns 1 if n is odd; 0 otherwise. */ Int32 n; { return n&1; }

The **sbox**
subroutine draws a two-dimensional, screen-aligned rectangle using the
current color, writemask,
linestyle, and linestyle repeat. Only these attributes, not the normal
line attributes, are used. Most of the lighting/shading/viewing pipeline
is bypassed.

Forms of the sbox Subroutine | ||

Parameter type |
Filled |
Unfilled |

short integer | sboxfs |
sboxs |

long integer | sboxfi |
sboxi |

floating point | sboxf |
sbox |

void sbox(Coord x1, Coord y1,Coord x2, Coord y2)

The **sboxf** subroutine draws a filled
rectangle.

When you use the **sbox** subroutine,
you must not use lighting,
backfacing,
depth-cueing,
z buffering,
Gouraud shading,
or alphablending.

Like rectangles, circles are two-dimensional
figures, and lie in the* x*-*y *plane, with* z* coordinates
equal to zero. If they are viewed at an angle, circles will be appear to
be ellipses.

The parameters for the circle subroutines
include the center point, defined by the *x, y* parameters, and
the radius. Like rectangles, circles are either filled or unfilled, and
the center coordinates and radius are specified in integers, short integers,
or floating-point numbers.

The following table lists the six different
forms of the **circ**
subroutine. The parameters to all six subroutines are the same: **circ**(*x*, *y*, *radius*).

Forms of the Circle Subroutine | ||

Parameter type |
Filled |
Unfilled |

short integer | circfs |
circs |

long integer | circfi |
circi |

floating point | circf |
circ |

Circles are drawn with 80 equally spaced points, either as a closed line (for unfilled circles), or as a polygon (for filled circles). If your application draws many tiny circles, it is a good idea to write a circle primitive that uses fewer line segments, and which can therefore be drawn much more quickly. A similar problem can arise for very large circles. If they are magnified enough, you can see the individual straight line segments. However, circles drawn with 80 segments look smooth over a wide range of sizes. The syntax is as follows:

void circ(Coord x, Coord y, Coord radius)

The following example program, `bullseye`
,
draws an archery target using filled circles:

#include <gl/gl.h>

main() {

prefposition(100, 500, 100, 500); winopen("bullseye"); ortho2(-1.0, 1.0, -1.0, 1.0); color(BLACK); clear(); color(GREEN); circf(0.0, 0.0, 0.9); color(YELLOW); circf(0.0, 0.0, 0.7); color(BLUE); circf(0.0, 0.0, 0.5); color(CYAN); circf(0.0, 0.0, 0.3); color(RED); circf(0.0, 0.0, 0.1); sleep(3); }

Arcs are also two-dimensional figures,
and like circles and rectangles, GL assumes they lie in the plane *z*
= 0. When viewed at an angle, arcs appear to be segments of ellipses. Arcs
can be either filled or unfilled. As shown in the Unfilled
Arc figure, these are simply segments of circles, whereas filled arcs,
shown in the Filled Arc figure, look
like sections of a pie.

Arcs are defined by a center (*x, y*),
a radius, a starting angle, and an ending angle. The angles are measured
from the positive *x* axis in a counterclockwise (right-hand
rule) direction. Negative angles are measured clockwise. Both angles
are expressed as integers in tenths of degrees, so a 90 degree angle is
expressed as 900.

An arc is always drawn counterclockwise
from the starting angle to the ending angle, so if `startang = 0`
and `endang = 100`
, a 10-degree arc is be drawn. If the
starting angle is 100 and the ending angle is 0, a 350-degree arc is drawn.

The circular portions of the arcs drawn are approximated by straight lines, and a full 360-degree arc consists of 80 segments. If your application draws many tiny arcs, it is a good idea to write an arcs primitive that uses fewer line segments and that can therefore be drawn much more quickly. A similar problem can arise for very large arcs. If they are magnified enough, you can easily see the individual straight line segments. However, arcs drawn with 80 segments look reasonably good over a wide range of sizes.

Arcs subroutines come in the same six forms as subroutines for circles and rectangles as shown in the following table:

Forms of the Arc Subroutine | ||

Parameter type |
Filled |
Unfilled |

short integer | arcfs |
arcs |

long integer | arcfi |
arci |

floating point | arcf |
arc |

The parameter order for all six versions
of the **arc**
subroutine is *x*, *y*, *radius*, *startang*, *endang*.
The syntax is as follows:

void arc(Coord x, Coord y, Coord radius, Angle startang, Angle endang)

The following example program, `piechart`
,
draws a pie chart using filled arcs:

#include <gl/gl.h>

main() {

prefposition(100, 500, 100, 500); winopen("piechart"); ortho2(-1.0, 1.0, -1.0, 1.0); color(BLACK); clear(); color(RED); arcf(0.0, 0.0, 0.9, 0, 800); color(GREEN); arcf(0.0, 0.0, 0.9, 800, 1200); color(YELLOW); arcf(0.0, 0.0, 0.9, 1200, 2200); color(MAGENTA); arcf(0.0, 0.0, 0.9, 2200, 3400); color(BLUE); arcf(0.0, 0.0, 0.9, 3400, 0); sleep(3); }

GL has two sets of subroutines that take arrays of vertex coordinates and draw filled and unfilled polygons. These subroutines draw exactly the same figures as the move-draw (or polygon move and polygon draw) subroutines, but are often more convenient to use.

Filled polygons are drawn by the **polf**
subroutine, and polygon outlines are drawn by the **poly**
subroutine. The following table is a complete list of the polygon and filled
polygon subroutines.

Forms of the Polygon Subroutines | ||

Parameter type |
2-D |
3-D |

short integer | poly2s |
polys |

long integer | poly2i |
polyi |

floating point | poly2 |
poly |

short integer | polf2s |
polfs |

long integer | polf2i |
polfi |

floating point | polf2 |
polf |

Both the **polf** and the **poly**
subroutines take two parameters. The first parameter, *n*, is the
number of vertices in the polygon, and the second, *parray*, is a
two-dimensional array containing the coordinates. The syntax for the **polf**
and **poly** subroutines is as follows:

void polf(Int32 n, Coord parray[][3])

void poly(Int32 n, Coord parray[][3])

This example program draws a hexagon using
the **polf** subroutine:

#include <gl/gl.h>

Int32 parray[6][2] = {{200,100},{100,300},{200,500}, {400,500},{500,300},{400,100}};

main() {

prefposition(100, 600, 100, 600); winopen("hexagon"); color(BLACK); clear(); color(GREEN); polf2i(6, parray); sleep(3); }