2
** $Header: /cvs/projects/ogl-sample/main/gfx/lib/glu/libtess/README,v 1.1 2000/04/26 05:53:59 ljp Exp $
5
General Polygon Tesselation
6
---------------------------
8
This note describes a tesselator for polygons consisting of one or
9
more closed contours. It is backward-compatible with the current
10
OpenGL Utilities tesselator, and is intended to replace it. Here is
11
a summary of the major differences:
13
- input contours can be intersecting, self-intersecting, or degenerate.
15
- supports a choice of several winding rules for determining which parts
16
of the polygon are on the "interior". This makes it possible to do
17
CSG operations on polygons.
19
- boundary extraction: instead of tesselating the polygon, returns a
20
set of closed contours which separate the interior from the exterior.
22
- returns the output as a small number of triangle fans and strips,
23
rather than a list of independent triangles (when possible).
25
- output is available as an explicit mesh (a quad-edge structure),
26
in addition to the normal callback interface.
28
- the algorithm used is extremely robust.
34
The tesselator state is maintained in a "tesselator object".
35
These are allocated and destroyed using
37
GLUtesselator *gluNewTess( void );
38
void gluDeleteTess( GLUtesselator *tess );
40
Several tesselator objects may be used simultaneously.
45
The input contours are specified with the following routines:
47
void gluTessBeginPolygon( GLUtesselator *tess );
48
void gluTessBeginContour( GLUtesselator *tess );
49
void gluTessVertex( GLUtesselator *tess, GLUcoord coords[3], void *data );
50
void gluTessEndContour( GLUtesselator *tess );
51
void gluTessEndPolygon( GLUtesselator *tess );
53
Within each BeginPolygon/EndPolygon pair, there can be zero or more
54
calls to BeginContour/EndContour. Within each contour, there are zero
55
or more calls to gluTessVertex(). The vertices specify a closed
56
contour (the last vertex of each contour is automatically linked to
59
"coords" give the coordinates of the vertex in 3-space. For useful
60
results, all vertices should lie in some plane, since the vertices
61
are projected onto a plane before tesselation. "data" is a pointer
62
to a user-defined vertex structure, which typically contains other
63
information such as color, texture coordinates, normal, etc. It is
64
used to refer to the vertex during rendering.
66
The library can be compiled in single- or double-precision; the type
67
GLUcoord represents either "float" or "double" accordingly. The GLU
68
version will be available in double-precision only. Compile with
69
GLU_TESS_API_FLOAT defined to get the single-precision version.
71
When EndPolygon is called, the tesselation algorithm determines
72
which regions are interior to the given contours, according to one
73
of several "winding rules" described below. The interior regions
74
are then tesselated, and the output is provided as callbacks.
80
Callbacks are specified by the client using
82
void gluTessCallback( GLUtesselator *tess, GLenum which, void (*fn)());
84
If "fn" is NULL, any previously defined callback is discarded.
86
The callbacks used to provide output are: /* which == */
88
void begin( GLenum type ); /* GLU_TESS_BEGIN */
89
void edgeFlag( GLboolean flag ); /* GLU_TESS_EDGE_FLAG */
90
void vertex( void *data ); /* GLU_TESS_VERTEX */
91
void end( void ); /* GLU_TESS_END */
93
Any of the callbacks may be left undefined; if so, the corresponding
94
information will not be supplied during rendering.
96
The "begin" callback indicates the start of a primitive; type is one
97
of GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, or GL_TRIANGLES (but see the
98
notes on "boundary extraction" below).
100
It is followed by any number of "vertex" callbacks, which supply the
101
vertices in the same order as expected by the corresponding glBegin()
102
call. After the last vertex of a given primitive, there is a callback
105
If the "edgeFlag" callback is provided, no triangle fans or strips
106
will be used. When edgeFlag is called, if "flag" is GL_TRUE then each
107
vertex which follows begins an edge which lies on the polygon boundary
108
(ie. an edge which separates an interior region from an exterior one).
109
If "flag" is GL_FALSE, each vertex which follows begins an edge which lies
110
in the polygon interior. "edgeFlag" will be called before the first
116
void mesh( GLUmesh *mesh ); /* GLU_TESS_MESH */
118
- Returns an explicit mesh, represented using the quad-edge structure
119
(Guibas/Stolfi '85). Other implementations of this interface might
120
use a different mesh structure, so this is available only only as an
121
SGI extension. When the mesh is no longer needed, it should be freed
124
void gluDeleteMesh( GLUmesh *mesh );
126
There is a brief description of this data structure in the include
127
file "mesh.h". For the full details, see L. Guibas and J. Stolfi,
128
Primitives for the manipulation of general subdivisions and the
129
computation of Voronoi diagrams, ACM Transactions on Graphics,
130
4(2):74-123, April 1985. For an introduction, see the course notes
131
for CS348a, "Mathematical Foundations of Computer Graphics",
132
available at the Stanford bookstore (and taught during the fall
135
void error( GLenum errno ); /* GLU_TESS_ERROR */
137
- errno is one of GLU_TESS_MISSING_BEGIN_POLYGON,
138
GLU_TESS_MISSING_END_POLYGON,
139
GLU_TESS_MISSING_BEGIN_CONTOUR,
140
GLU_TESS_MISSING_END_CONTOUR,
141
GLU_TESS_COORD_TOO_LARGE,
142
GLU_TESS_NEED_COMBINE_CALLBACK
144
The first four are obvious. The interface recovers from these
145
errors by inserting the missing call(s).
147
GLU_TESS_COORD_TOO_LARGE says that some vertex coordinate exceeded
148
the predefined constant GLU_TESS_MAX_COORD in absolute value, and
149
that the value has been clamped. (Coordinate values must be small
150
enough so that two can be multiplied together without overflow.)
152
GLU_TESS_NEED_COMBINE_CALLBACK says that the algorithm detected an
153
intersection between two edges in the input data, and the "combine"
154
callback (below) was not provided. No output will be generated.
157
void combine( GLUcoord coords[3], void *data[4], /* GLU_TESS_COMBINE */
158
GLUcoord weight[4], void **outData );
160
- When the algorithm detects an intersection, or wishes to merge
161
features, it needs to create a new vertex. The vertex is defined
162
as a linear combination of up to 4 existing vertices, referenced
163
by data[0..3]. The coefficients of the linear combination are
164
given by weight[0..3]; these weights always sum to 1.0. All vertex
165
pointers are valid even when some of the weights are zero.
166
"coords" gives the location of the new vertex.
168
The user must allocate another vertex, interpolate parameters
169
using "data" and "weights", and return the new vertex pointer in
170
"outData". This handle is supplied during rendering callbacks.
171
For example, if the polygon lies in an arbitrary plane in 3-space,
172
and we associate a color with each vertex, the combine callback might
175
void myCombine( GLUcoord coords[3], VERTEX *d[4],
176
GLUcoord w[4], VERTEX **dataOut )
178
VERTEX *new = new_vertex();
183
new->r = w[0]*d[0]->r + w[1]*d[1]->r + w[2]*d[2]->r + w[3]*d[3]->r;
184
new->g = w[0]*d[0]->g + w[1]*d[1]->g + w[2]*d[2]->g + w[3]*d[3]->g;
185
new->b = w[0]*d[0]->b + w[1]*d[1]->b + w[2]*d[2]->b + w[3]*d[3]->b;
186
new->a = w[0]*d[0]->a + w[1]*d[1]->a + w[2]*d[2]->a + w[3]*d[3]->a;
190
If the algorithm detects an intersection, then the "combine" callback
191
must be defined, and must write a non-NULL pointer into "dataOut".
192
Otherwise the GLU_TESS_NEED_COMBINE_CALLBACK error occurs, and no
193
output is generated. This is the only error that can occur during
194
tesselation and rendering.
197
Control over Tesselation
198
------------------------
200
void gluTessProperty( GLUtesselator *tess, GLenum which, GLUcoord value );
204
- GLU_TESS_WINDING_RULE. Possible values:
207
GLU_TESS_WINDING_NONZERO
208
GLU_TESS_WINDING_POSITIVE
209
GLU_TESS_WINDING_NEGATIVE
210
GLU_TESS_WINDING_ABS_GEQ_TWO
212
The input contours parition the plane into regions. A winding
213
rule determines which of these regions are inside the polygon.
215
For a single contour C, the winding number of a point x is simply
216
the signed number of revolutions we make around x as we travel
217
once around C (where CCW is positive). When there are several
218
contours, the individual winding numbers are summed. This
219
procedure associates a signed integer value with each point x in
220
the plane. Note that the winding number is the same for all
221
points in a single region.
223
The winding rule classifies a region as "inside" if its winding
224
number belongs to the chosen category (odd, nonzero, positive,
225
negative, or absolute value of at least two). The current GLU
226
tesselator implements the "odd" rule. The "nonzero" rule is another
227
common way to define the interior. The other three rules are
228
useful for polygon CSG operations (see below).
230
- GLU_TESS_BOUNDARY_ONLY. Values: TRUE (non-zero) or FALSE (zero).
232
If TRUE, returns a set of closed contours which separate the
233
polygon interior and exterior (rather than a tesselation).
234
Exterior contours are oriented CCW with respect to the normal,
235
interior contours are oriented CW. The GLU_TESS_BEGIN callback
236
uses the type GL_LINE_LOOP for each contour.
238
- GLU_TESS_TOLERANCE. Value: a real number between 0.0 and 1.0.
240
This specifies a tolerance for merging features to reduce the size
241
of the output. For example, two vertices which are very close to
242
each other might be replaced by a single vertex. The tolerance
243
is multiplied by the largest coordinate magnitude of any input vertex;
244
this specifies the maximum distance that any feature can move as the
245
result of a single merge operation. If a single feature takes part
246
in several merge operations, the total distance moved could be larger.
248
Feature merging is completely optional; the tolerance is only a hint.
249
The implementation is free to merge in some cases and not in others,
250
or to never merge features at all. The default tolerance is zero.
252
The current implementation merges vertices only if they are exactly
253
coincident, regardless of the current tolerance. A vertex is
254
spliced into an edge only if the implementation is unable to
255
distinguish which side of the edge the vertex lies on.
256
Two edges are merged only when both endpoints are identical.
259
void gluTessNormal( GLUtesselator *tess,
260
GLUcoord x, GLUcoord y, GLUcoord z )
262
- Lets the user supply the polygon normal, if known. All input data
263
is projected into a plane perpendicular to the normal before
264
tesselation. All output triangles are oriented CCW with
265
respect to the normal (CW orientation can be obtained by
266
reversing the sign of the supplied normal). For example, if
267
you know that all polygons lie in the x-y plane, call
268
"gluTessNormal(tess, 0.0, 0.0, 1.0)" before rendering any polygons.
270
- If the supplied normal is (0,0,0) (the default value), the
271
normal is determined as follows. The direction of the normal,
272
up to its sign, is found by fitting a plane to the vertices,
273
without regard to how the vertices are connected. It is
274
expected that the input data lies approximately in plane;
275
otherwise projection perpendicular to the computed normal may
276
substantially change the geometry. The sign of the normal is
277
chosen so that the sum of the signed areas of all input contours
278
is non-negative (where a CCW contour has positive area).
280
- The supplied normal persists until it is changed by another
281
call to gluTessNormal.
284
Backward compatibility with the GLU tesselator
285
----------------------------------------------
287
The preferred interface is the one described above. The following
288
routines are obsolete, and are provided only for backward compatibility:
290
typedef GLUtesselator GLUtriangulatorObj; /* obsolete name */
292
void gluBeginPolygon( GLUtesselator *tess );
293
void gluNextContour( GLUtesselator *tess, GLenum type );
294
void gluEndPolygon( GLUtesselator *tess );
296
"type" is one of GLU_EXTERIOR, GLU_INTERIOR, GLU_CCW, GLU_CW, or
297
GLU_UNKNOWN. It is ignored by the current GLU tesselator.
299
GLU_BEGIN, GLU_VERTEX, GLU_END, GLU_ERROR, and GLU_EDGE_FLAG are defined
300
as synonyms for GLU_TESS_BEGIN, GLU_TESS_VERTEX, GLU_TESS_END,
301
GLU_TESS_ERROR, and GLU_TESS_EDGE_FLAG.
304
Polygon CSG operations
305
----------------------
307
The features of the tesselator make it easy to find the union, difference,
308
or intersection of several polygons.
310
First, assume that each polygon is defined so that the winding number
311
is 0 for each exterior region, and 1 for each interior region. Under
312
this model, CCW contours define the outer boundary of the polygon, and
313
CW contours define holes. Contours may be nested, but a nested
314
contour must be oriented oppositely from the contour that contains it.
316
If the original polygons do not satisfy this description, they can be
317
converted to this form by first running the tesselator with the
318
GLU_TESS_BOUNDARY_ONLY property turned on. This returns a list of
319
contours satisfying the restriction above. By allocating two
320
tesselator objects, the callbacks from one tesselator can be fed
321
directly to the input of another.
323
Given two or more polygons of the form above, CSG operations can be
324
implemented as follows:
327
Draw all the input contours as a single polygon. The winding number
328
of each resulting region is the number of original polygons
329
which cover it. The union can be extracted using the
330
GLU_TESS_WINDING_NONZERO or GLU_TESS_WINDING_POSITIVE winding rules.
331
Note that with the nonzero rule, we would get the same result if
332
all contour orientations were reversed.
334
Intersection (two polygons at a time only)
335
Draw a single polygon using the contours from both input polygons.
336
Extract the result using GLU_TESS_WINDING_ABS_GEQ_TWO. (Since this
337
winding rule looks at the absolute value, reversing all contour
338
orientations does not change the result.)
342
Suppose we want to compute A \ (B union C union D). Draw a single
343
polygon consisting of the unmodified contours from A, followed by
344
the contours of B,C,D with the vertex order reversed (this changes
345
the winding number of the interior regions to -1). To extract the
346
result, use the GLU_TESS_WINDING_POSITIVE rule.
348
If B,C,D are the result of a GLU_TESS_BOUNDARY_ONLY call, an
349
alternative to reversing the vertex order is to reverse the sign of
350
the supplied normal. For example in the x-y plane, call
351
gluTessNormal( tess, 0.0, 0.0, -1.0 ).
357
The tesselator is not intended for immediate-mode rendering; when
358
possible the output should be cached in a user structure or display
359
list. General polygon tesselation is an inherently difficult problem,
360
especially given the goal of extreme robustness.
362
The implementation makes an effort to output a small number of fans
363
and strips; this should improve the rendering performance when the
364
output is used in a display list.
366
Single-contour input polygons are first tested to see whether they can
367
be rendered as a triangle fan with respect to the first vertex (to
368
avoid running the full decomposition algorithm on convex polygons).
369
Non-convex polygons may be rendered by this "fast path" as well, if
370
the algorithm gets lucky in its choice of a starting vertex.
372
For best performance follow these guidelines:
374
- supply the polygon normal, if available, using gluTessNormal().
375
This represents about 10% of the computation time. For example,
376
if all polygons lie in the x-y plane, use gluTessNormal(tess,0,0,1).
378
- render many polygons using the same tesselator object, rather than
379
allocating a new tesselator for each one. (In a multi-threaded,
380
multi-processor environment you may get better performance using
381
several tesselators.)
384
Comparison with the GLU tesselator
385
----------------------------------
387
On polygons which make it through the "fast path", the tesselator is
388
3 to 5 times faster than the GLU tesselator.
390
On polygons which don't make it through the fast path (but which don't
391
have self-intersections or degeneracies), it is about 2 times slower.
393
On polygons with self-intersections or degeneraces, there is nothing
396
The new tesselator generates many more fans and strips, reducing the
397
number of vertices that need to be sent to the hardware.
399
Key to the statistics:
401
vert number of input vertices on all contours
402
cntr number of input contours
403
tri number of triangles in all output primitives
404
strip number of triangle strips
405
fan number of triangle fans
406
ind number of independent triangles
407
ms number of milliseconds for tesselation
408
(on a 150MHz R4400 Indy)
410
Convex polygon examples:
412
New: 3 vert, 1 cntr, 1 tri, 0 strip, 0 fan, 1 ind, 0.0459 ms
413
Old: 3 vert, 1 cntr, 1 tri, 0 strip, 0 fan, 1 ind, 0.149 ms
414
New: 4 vert, 1 cntr, 2 tri, 0 strip, 1 fan, 0 ind, 0.0459 ms
415
Old: 4 vert, 1 cntr, 2 tri, 0 strip, 0 fan, 2 ind, 0.161 ms
416
New: 36 vert, 1 cntr, 34 tri, 0 strip, 1 fan, 0 ind, 0.153 ms
417
Old: 36 vert, 1 cntr, 34 tri, 0 strip, 0 fan, 34 ind, 0.621 ms
419
Concave single-contour polygons:
421
New: 5 vert, 1 cntr, 3 tri, 0 strip, 1 fan, 0 ind, 0.052 ms
422
Old: 5 vert, 1 cntr, 3 tri, 0 strip, 0 fan, 3 ind, 0.252 ms
423
New: 19 vert, 1 cntr, 17 tri, 2 strip, 2 fan, 1 ind, 0.911 ms
424
Old: 19 vert, 1 cntr, 17 tri, 0 strip, 0 fan, 17 ind, 0.529 ms
425
New: 151 vert, 1 cntr, 149 tri, 13 strip, 18 fan, 3 ind, 6.82 ms
426
Old: 151 vert, 1 cntr, 149 tri, 0 strip, 3 fan, 143 ind, 2.7 ms
427
New: 574 vert, 1 cntr, 572 tri, 59 strip, 54 fan, 11 ind, 26.6 ms
428
Old: 574 vert, 1 cntr, 572 tri, 0 strip, 31 fan, 499 ind, 12.4 ms
430
Multiple contours, but no intersections:
432
New: 7 vert, 2 cntr, 7 tri, 1 strip, 0 fan, 0 ind, 0.527 ms
433
Old: 7 vert, 2 cntr, 7 tri, 0 strip, 0 fan, 7 ind, 0.274 ms
434
New: 81 vert, 6 cntr, 89 tri, 9 strip, 7 fan, 6 ind, 3.88 ms
435
Old: 81 vert, 6 cntr, 89 tri, 0 strip, 13 fan, 61 ind, 2.2 ms
436
New: 391 vert, 19 cntr, 413 tri, 37 strip, 32 fan, 26 ind, 20.2 ms
437
Old: 391 vert, 19 cntr, 413 tri, 0 strip, 25 fan, 363 ind, 8.68 ms
439
Self-intersecting and degenerate examples:
441
Bowtie: 4 vert, 1 cntr, 2 tri, 0 strip, 0 fan, 2 ind, 0.483 ms
442
Star: 5 vert, 1 cntr, 5 tri, 0 strip, 0 fan, 5 ind, 0.91 ms
443
Random: 24 vert, 7 cntr, 46 tri, 2 strip, 12 fan, 7 ind, 5.32 ms
444
Font: 333 vert, 2 cntr, 331 tri, 32 strip, 16 fan, 3 ind, 14.1 ms
445
: 167 vert, 35 cntr, 254 tri, 8 strip, 56 fan, 52 ind, 46.3 ms
446
: 78 vert, 1 cntr, 2675 tri, 148 strip, 207 fan, 180 ind, 243 ms
447
: 12480 vert, 2 cntr, 12478 tri, 736 strip,1275 fan, 5 ind, 1010 ms