What you’ll learn in this chapter:
The OpenGL Utility library (glu32.lib) includes a robust polygon tessellation interface that can handle rendering of complex polygons and surfaces. What is tessellation, you ask? According to the American Heritage Dictionary:
To form into a mosaic pattern, as by using small squares of stone or glass.
A computer graphics tessellator takes one or more connected sets of points and forms a series of polygons that fill to form the described shape. In place of stone and glass, it uses triangles and pixels. A polygon tessellator is specially designed to manage the drawing of polygons that have unusual attributes such as holes.
What makes polygons complex? Well, in OpenGL a complex polygon is one that is either concave (the polygon contains a “dent”) or has holes in it. Figure 18-1 contains some simple and complex polygons that you may need to render at some time.
OpenGL’s GL_POLYGON primitive can only render simple, convex polygons. A polygon is convex if no point lies inside a line between any two vertices. That is, if you can draw a line between two vertices of a polygon and the line goes into empty space outside the polygon edge, the polygon is not convex; it is concave or complex.
Concave polygons are nonconvex polygons that have no unfilled holes in their interiors. The top-right polygon in Figure 18-1 is concave, but the one below it is not because it contains a hole in the middle of the filled area.
Complex polygons have holes or twists in them. The lower-right polygon in Figure 18-1 is complex.
Drawing concave polygons with the glu is not difficult. The first thing you must do is create a tessellator object, as shown here:
GLUtriangulatorObj *tess; tess = gluNewTess();
The GLUtriangulatorObj structure contains state information that is used by the tessellator to render the polygon.
Next, you call a sequence of gluBeginPolygon, gluTessVertex, and gluEndPolygon to render the polygon:
GLdouble vertices; gluBeginPolygon(tess); gluTessVertex(tess, vertices, NULL); gluTessVertex(tess, vertices, NULL); … gluTessVertex(tess, vertices, NULL); gluEndPolygon(tess);
After the gluEndPolygon call, the tessellator does its work and generates a series of triangles, triangle strips, and triangle fans. Because this process can take a long time, it’s a good idea to put tessellated polygons into display lists to improve display performance (see Chapter 10).
Drawing complex polygons is a little more involved than for concave polygons but is not as hard as it would seem. Complex polygons can have holes and twists in them, so the gluNextContour function is provided to identify the type of path you are defining. Table 18-1 lists the path types for gluNextContour.
For the example shown in Figure 18-2, we will define an exterior path for the outline, and an interior path for the triangular hole in the middle (see Figure 18-3).
To draw the letter A, we call gluNextContour only once before providing the interior points. The example in Listing 18-1, LETTER.C, uses this code to display a rotating A.
tess = gluNewTess(); gluBeginPolygon(tess); gluTessVertex(tess, outside, outside); gluTessVertex(tess, outside, outside); gluTessVertex(tess, outside, outside); gluTessVertex(tess, outside, outside); gluTessVertex(tess, outside, outside); gluTessVertex(tess, outside, outside); gluTessVertex(tess, outside, outside); gluNextContour(tess, GLU_INTERIOR); gluTessVertex(tess, inside, inside); gluTessVertex(tess, inside, inside); gluTessVertex(tess, inside, inside); gluEndPolygon(tess); gluDeleteTess(tess);