Logo ROOT  
Reference Guide
tess.c
Go to the documentation of this file.
1/*
2 * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3 * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice including the dates of first publication and
13 * either this permission notice or a reference to
14 * http://oss.sgi.com/projects/FreeB/
15 * shall be included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Except as contained in this notice, the name of Silicon Graphics, Inc.
26 * shall not be used in advertising or otherwise to promote the sale, use or
27 * other dealings in this Software without prior written authorization from
28 * Silicon Graphics, Inc.
29 */
30/*
31** Author: Eric Veach, July 1994.
32**
33*/
34
35#include "gluos.h"
36#include <stddef.h>
37#include <assert.h>
38#include <setjmp.h>
39#include "memalloc.h"
40#include "tess.h"
41#include "mesh.h"
42#include "normal.h"
43#include "sweep.h"
44#include "tessmono.h"
45#include "render.h"
46
47#define GLU_TESS_DEFAULT_TOLERANCE 0.0
48#define GLU_TESS_MESH 100112 /* void (*)(GLUmesh *mesh) */
49
50#ifndef TRUE
51#define TRUE 1
52#endif
53#ifndef FALSE
54#define FALSE 0
55#endif
56
57#if defined(__GNUC__) || defined(__clang__)
58#pragma GCC diagnostic push
59/* A padding warning is just plain useless */
60#pragma GCC diagnostic ignored "-Wunused-parameter"
61#endif
62
63/*ARGSUSED*/ static void GLAPIENTRY noBegin( GLenum type ) {}
64/*ARGSUSED*/ static void GLAPIENTRY noEdgeFlag( GLboolean boundaryEdge ) {}
65/*ARGSUSED*/ static void GLAPIENTRY noVertex( void *data ) {}
66/*ARGSUSED*/ static void GLAPIENTRY noEnd( void ) {}
67/*ARGSUSED*/ static void GLAPIENTRY noError( GLenum errnum ) {}
68/*ARGSUSED*/ static void GLAPIENTRY noCombine( GLdouble coords[3], void *data[4],
69 GLfloat weight[4], void **dataOut ) {}
70/*ARGSUSED*/ static void GLAPIENTRY noMesh( GLUmesh *mesh ) {}
71
72
74 void *polygonData ) {}
75/*ARGSUSED*/ void GLAPIENTRY __gl_noEdgeFlagData( GLboolean boundaryEdge,
76 void *polygonData ) {}
77/*ARGSUSED*/ void GLAPIENTRY __gl_noVertexData( void *data,
78 void *polygonData ) {}
79/*ARGSUSED*/ void GLAPIENTRY __gl_noEndData( void *polygonData ) {}
80/*ARGSUSED*/ void GLAPIENTRY __gl_noErrorData( GLenum errnum,
81 void *polygonData ) {}
82/*ARGSUSED*/ void GLAPIENTRY __gl_noCombineData( GLdouble coords[3],
83 void *data[4],
84 GLfloat weight[4],
85 void **outData,
86 void *polygonData ) {}
87
88#if defined(__GNUC__) || defined(__clang__)
89#pragma GCC diagnostic pop
90#endif
91
92/* Half-edges are allocated in pairs (see mesh.c) */
93//typedef struct { GLUhalfEdge e, eSym; } EdgePair;
94
95#undef MAX
96#define MAX(a,b) ((a) > (b) ? (a) : (b))
97#define MAX_FAST_ALLOC (MAX(sizeof(EdgePair), \
98 MAX(sizeof(GLUvertex),sizeof(GLUface))))
99
100
103{
104 GLUtesselator *tess;
105
106 /* Only initialize fields which can be changed by the api. Other fields
107 * are initialized where they are used.
108 */
109
110 if (memInit( MAX_FAST_ALLOC ) == 0) {
111 return 0; /* out of memory */
112 }
113 tess = (GLUtesselator *)memAlloc( sizeof( GLUtesselator ));
114 if (tess == NULL) {
115 return 0; /* out of memory */
116 }
117
118 tess->state = T_DORMANT;
119
120 tess->normal[0] = 0;
121 tess->normal[1] = 0;
122 tess->normal[2] = 0;
123
126 tess->flagBoundary = FALSE;
127 tess->boundaryOnly = FALSE;
128
129 tess->callBegin = &noBegin;
130 tess->callEdgeFlag = &noEdgeFlag;
131 tess->callVertex = &noVertex;
132 tess->callEnd = &noEnd;
133
134 tess->callError = &noError;
135 tess->callCombine = &noCombine;
136 tess->callMesh = &noMesh;
137
138 tess->callBeginData= &__gl_noBeginData;
139 tess->callEdgeFlagData= &__gl_noEdgeFlagData;
140 tess->callVertexData= &__gl_noVertexData;
141 tess->callEndData= &__gl_noEndData;
142 tess->callErrorData= &__gl_noErrorData;
143 tess->callCombineData= &__gl_noCombineData;
144
145 tess->polygonData= NULL;
146
147 return tess;
148}
149
150static void MakeDormant( GLUtesselator *tess )
151{
152 /* Return the tessellator to its original dormant state. */
153
154 if( tess->mesh != NULL ) {
155 __gl_meshDeleteMesh( tess->mesh );
156 }
157 tess->state = T_DORMANT;
158 tess->lastEdge = NULL;
159 tess->mesh = NULL;
160}
161
162#define RequireState( tess, s ) if( tess->state != s ) GotoState(tess,s)
163
164static void GotoState( GLUtesselator *tess, enum TessState newState )
165{
166 while( tess->state != newState ) {
167 /* We change the current state one level at a time, to get to
168 * the desired state.
169 */
170 if( tess->state < newState ) {
171 switch( tess->state ) {
172 case T_DORMANT:
174 gluTessBeginPolygon( tess, NULL );
175 break;
176 case T_IN_POLYGON:
178 gluTessBeginContour( tess );
179 break;
180 default:
181 ;
182 }
183 } else {
184 switch( tess->state ) {
185 case T_IN_CONTOUR:
187 gluTessEndContour( tess );
188 break;
189 case T_IN_POLYGON:
191 /* gluTessEndPolygon( tess ) is too much work! */
192 MakeDormant( tess );
193 break;
194 default:
195 ;
196 }
197 }
198 }
199}
200
201
202void GLAPIENTRY
204{
205 RequireState( tess, T_DORMANT );
206 memFree( tess );
207}
208
209
210void GLAPIENTRY
212{
213 GLenum windingRule;
214
215 switch( which ) {
217 if( value < 0.0 || value > 1.0 ) break;
218 tess->relTolerance = value;
219 return;
220
222 windingRule = (GLenum) value;
223 if( windingRule != value ) break; /* not an integer */
224
225 switch( windingRule ) {
231 tess->windingRule = windingRule;
232 return;
233 default:
234 break;
235 }
236
238 tess->boundaryOnly = (value != 0);
239 return;
240
241 default:
243 return;
244 }
246}
247
248/* Returns tessellator property */
249void GLAPIENTRY
251{
252 switch (which) {
254 /* tolerance should be in range [0..1] */
255 assert(0.0 <= tess->relTolerance && tess->relTolerance <= 1.0);
256 *value= tess->relTolerance;
257 break;
259 assert(tess->windingRule == GLU_TESS_WINDING_ODD ||
264 *value= tess->windingRule;
265 break;
267 assert(tess->boundaryOnly == TRUE || tess->boundaryOnly == FALSE);
268 *value= tess->boundaryOnly;
269 break;
270 default:
271 *value= 0.0;
273 break;
274 }
275} /* gluGetTessProperty() */
276
277void GLAPIENTRY
279{
280 tess->normal[0] = x;
281 tess->normal[1] = y;
282 tess->normal[2] = z;
283}
284
285void GLAPIENTRY
286gluTessCallback( GLUtesselator *tess, GLenum which, _GLUfuncptr fn)
287{
288 switch( which ) {
289 case GLU_TESS_BEGIN:
290 tess->callBegin = (fn == NULL) ? &noBegin : (void (GLAPIENTRY *)(GLenum)) fn;
291 return;
293 tess->callBeginData = (fn == NULL) ?
294 &__gl_noBeginData : (void (GLAPIENTRY *)(GLenum, void *)) fn;
295 return;
297 tess->callEdgeFlag = (fn == NULL) ? &noEdgeFlag :
298 (void (GLAPIENTRY *)(GLboolean)) fn;
299 /* If the client wants boundary edges to be flagged,
300 * we render everything as separate triangles (no strips or fans).
301 */
302 tess->flagBoundary = (fn != NULL);
303 return;
305 tess->callEdgeFlagData= (fn == NULL) ?
306 &__gl_noEdgeFlagData : (void (GLAPIENTRY *)(GLboolean, void *)) fn;
307 /* If the client wants boundary edges to be flagged,
308 * we render everything as separate triangles (no strips or fans).
309 */
310 tess->flagBoundary = (fn != NULL);
311 return;
312 case GLU_TESS_VERTEX:
313 tess->callVertex = (fn == NULL) ? &noVertex :
314 (void (GLAPIENTRY *)(void *)) fn;
315 return;
317 tess->callVertexData = (fn == NULL) ?
318 &__gl_noVertexData : (void (GLAPIENTRY *)(void *, void *)) fn;
319 return;
320 case GLU_TESS_END:
321 tess->callEnd = (fn == NULL) ? &noEnd : (void (GLAPIENTRY *)(void)) fn;
322 return;
324 tess->callEndData = (fn == NULL) ? &__gl_noEndData :
325 (void (GLAPIENTRY *)(void *)) fn;
326 return;
327 case GLU_TESS_ERROR:
328 tess->callError = (fn == NULL) ? &noError : (void (GLAPIENTRY *)(GLenum)) fn;
329 return;
331 tess->callErrorData = (fn == NULL) ?
332 &__gl_noErrorData : (void (GLAPIENTRY *)(GLenum, void *)) fn;
333 return;
334 case GLU_TESS_COMBINE:
335 tess->callCombine = (fn == NULL) ? &noCombine :
336 (void (GLAPIENTRY *)(GLdouble [3],void *[4], GLfloat [4], void ** )) fn;
337 return;
339 tess->callCombineData = (fn == NULL) ? &__gl_noCombineData :
340 (void (GLAPIENTRY *)(GLdouble [3],
341 void *[4],
342 GLfloat [4],
343 void **,
344 void *)) fn;
345 return;
346 case GLU_TESS_MESH:
347 tess->callMesh = (fn == NULL) ? &noMesh : (void (GLAPIENTRY *)(GLUmesh *)) fn;
348 return;
349 default:
351 return;
352 }
353}
354
355static int AddVertex( GLUtesselator *tess, GLdouble coords[3], void *data )
356{
357 GLUhalfEdge *e;
358
359 e = tess->lastEdge;
360 if( e == NULL ) {
361 /* Make a self-loop (one vertex, one edge). */
362
363 e = __gl_meshMakeEdge( tess->mesh );
364 if (e == NULL) return 0;
365 if ( !__gl_meshSplice( e, e->Sym ) ) return 0;
366 } else {
367 /* Create a new vertex and edge which immediately follow e
368 * in the ordering around the left face.
369 */
370 if (__gl_meshSplitEdge( e ) == NULL) return 0;
371 e = e->Lnext;
372 }
373
374 /* The new vertex is now e->Org. */
375 e->Org->data = data;
376 e->Org->coords[0] = coords[0];
377 e->Org->coords[1] = coords[1];
378 e->Org->coords[2] = coords[2];
379
380 /* The winding of an edge says how the winding number changes as we
381 * cross from the edge''s right face to its left face. We add the
382 * vertices in such an order that a CCW contour will add +1 to
383 * the winding number of the region inside the contour.
384 */
385 e->winding = 1;
386 e->Sym->winding = -1;
387
388 tess->lastEdge = e;
389
390 return 1;
391}
392
393
394static void CacheVertex( GLUtesselator *tess, GLdouble coords[3], void *data )
395{
396 CachedVertex *v = &tess->cache[tess->cacheCount];
397
398 v->data = data;
399 v->coords[0] = coords[0];
400 v->coords[1] = coords[1];
401 v->coords[2] = coords[2];
402 ++tess->cacheCount;
403}
404
405
406static int EmptyCache( GLUtesselator *tess )
407{
408 CachedVertex *v = tess->cache;
409 CachedVertex *vLast;
410
411 tess->mesh = __gl_meshNewMesh();
412 if (tess->mesh == NULL) return 0;
413
414 for( vLast = v + tess->cacheCount; v < vLast; ++v ) {
415 if ( !AddVertex( tess, v->coords, v->data ) ) return 0;
416 }
417 tess->cacheCount = 0;
418 tess->emptyCache = FALSE;
419
420 return 1;
421}
422
423
424void GLAPIENTRY
425gluTessVertex( GLUtesselator *tess, GLdouble coords[3], void *data )
426{
427 int i, tooLarge = FALSE;
428 GLdouble x, clamped[3];
429
430 RequireState( tess, T_IN_CONTOUR );
431
432 if( tess->emptyCache ) {
433 if ( !EmptyCache( tess ) ) {
435 return;
436 }
437 tess->lastEdge = NULL;
438 }
439 for( i = 0; i < 3; ++i ) {
440 x = coords[i];
441 if( x < - GLU_TESS_MAX_COORD ) {
443 tooLarge = TRUE;
444 }
445 if( x > GLU_TESS_MAX_COORD ) {
447 tooLarge = TRUE;
448 }
449 clamped[i] = x;
450 }
451 if( tooLarge ) {
453 }
454
455 if( tess->mesh == NULL ) {
456 if( tess->cacheCount < TESS_MAX_CACHE ) {
457 CacheVertex( tess, clamped, data );
458 return;
459 }
460 if ( !EmptyCache( tess ) ) {
462 return;
463 }
464 }
465 if ( !AddVertex( tess, clamped, data ) ) {
467 }
468}
469
470
471void GLAPIENTRY
473{
474 RequireState( tess, T_DORMANT );
475
476 tess->state = T_IN_POLYGON;
477 tess->cacheCount = 0;
478 tess->emptyCache = FALSE;
479 tess->mesh = NULL;
480
481 tess->polygonData= data;
482}
483
484
485void GLAPIENTRY
487{
488 RequireState( tess, T_IN_POLYGON );
489
490 tess->state = T_IN_CONTOUR;
491 tess->lastEdge = NULL;
492 if( tess->cacheCount > 0 ) {
493 /* Just set a flag so we don't get confused by empty contours
494 * -- these can be generated accidentally with the obsolete
495 * NextContour() interface.
496 */
497 tess->emptyCache = TRUE;
498 }
499}
500
501
502void GLAPIENTRY
504{
505 RequireState( tess, T_IN_CONTOUR );
506 tess->state = T_IN_POLYGON;
507}
508
509void GLAPIENTRY
511{
512 GLUmesh *mesh;
513
514 if (setjmp(tess->env) != 0) {
515 /* come back here if out of memory */
517 return;
518 }
519
520 RequireState( tess, T_IN_POLYGON );
521 tess->state = T_DORMANT;
522
523 if( tess->mesh == NULL ) {
524 if( ! tess->flagBoundary && tess->callMesh == &noMesh ) {
525
526 /* Try some special code to make the easy cases go quickly
527 * (eg. convex polygons). This code does NOT handle multiple contours,
528 * intersections, edge flags, and of course it does not generate
529 * an explicit mesh either.
530 */
531 if( __gl_renderCache( tess )) {
532 tess->polygonData= NULL;
533 return;
534 }
535 }
536 if ( !EmptyCache( tess ) ) longjmp(tess->env,1); /* could've used a label*/
537 }
538
539 /* Determine the polygon normal and project vertices onto the plane
540 * of the polygon.
541 */
542 __gl_projectPolygon( tess );
543
544 /* __gl_computeInterior( tess ) computes the planar arrangement specified
545 * by the given contours, and further subdivides this arrangement
546 * into regions. Each region is marked "inside" if it belongs
547 * to the polygon, according to the rule given by tess->windingRule.
548 * Each interior region is guaranteed be monotone.
549 */
550 if ( !__gl_computeInterior( tess ) ) {
551 longjmp(tess->env,1); /* could've used a label */
552 }
553
554 mesh = tess->mesh;
555 if( ! tess->fatalError ) {
556 int rc = 1;
557
558 /* If the user wants only the boundary contours, we throw away all edges
559 * except those which separate the interior from the exterior.
560 * Otherwise we tessellate all the regions marked "inside".
561 */
562 if( tess->boundaryOnly ) {
563 rc = __gl_meshSetWindingNumber( mesh, 1, TRUE );
564 } else {
565 rc = __gl_meshTessellateInterior( mesh );
566 }
567 if (rc == 0) longjmp(tess->env,1); /* could've used a label */
568
569 __gl_meshCheckMesh( mesh );
570
571 if( tess->callBegin != &noBegin || tess->callEnd != &noEnd
572 || tess->callVertex != &noVertex || tess->callEdgeFlag != &noEdgeFlag
573 || tess->callBeginData != &__gl_noBeginData
574 || tess->callEndData != &__gl_noEndData
575 || tess->callVertexData != &__gl_noVertexData
576 || tess->callEdgeFlagData != &__gl_noEdgeFlagData )
577 {
578 if( tess->boundaryOnly ) {
579 __gl_renderBoundary( tess, mesh ); /* output boundary contours */
580 } else {
581 __gl_renderMesh( tess, mesh ); /* output strips and fans */
582 }
583 }
584 if( tess->callMesh != &noMesh ) {
585
586 /* Throw away the exterior faces, so that all faces are interior.
587 * This way the user doesn't have to check the "inside" flag,
588 * and we don't need to even reveal its existence. It also leaves
589 * the freedom for an implementation to not generate the exterior
590 * faces in the first place.
591 */
593 (*tess->callMesh)( mesh ); /* user wants the mesh itself */
594 tess->mesh = NULL;
595 tess->polygonData= NULL;
596 return;
597 }
598 }
599 __gl_meshDeleteMesh( mesh );
600 tess->polygonData= NULL;
601 tess->mesh = NULL;
602}
603
604
605/*XXXblythe unused function*/
606#if 0
607void GLAPIENTRY
608gluDeleteMesh( GLUmesh *mesh )
609{
610 __gl_meshDeleteMesh( mesh );
611}
612#endif
613
614
615
616/*******************************************************/
617
618/* Obsolete calls -- for backward compatibility */
619
620void GLAPIENTRY
622{
623 gluTessBeginPolygon( tess, NULL );
624 gluTessBeginContour( tess );
625}
626
627
628/*ARGSUSED*/
629void GLAPIENTRY
631{
632 gluTessEndContour( tess );
633 gluTessBeginContour( tess );
634 (void)type;
635}
636
637
638void GLAPIENTRY
640{
641 gluTessEndContour( tess );
642 gluTessEndPolygon( tess );
643}
#define GLU_TESS_WINDING_NONZERO
Definition: GL_glu.h:254
#define GLU_TESS_VERTEX
Definition: GL_glu.h:209
#define GLU_TESS_WINDING_POSITIVE
Definition: GL_glu.h:255
#define GLU_INVALID_ENUM
Definition: GL_glu.h:81
#define GLU_TESS_BOUNDARY_ONLY
Definition: GL_glu.h:233
#define GLU_TESS_BEGIN_DATA
Definition: GL_glu.h:217
#define GLU_TESS_COMBINE_DATA
Definition: GL_glu.h:222
#define GLU_TESS_MISSING_BEGIN_CONTOUR
Definition: GL_glu.h:246
float GLfloat
Definition: GL_glu.h:277
#define GLU_TESS_WINDING_NEGATIVE
Definition: GL_glu.h:256
#define GLU_TESS_END_DATA
Definition: GL_glu.h:219
double GLdouble
Definition: GL_glu.h:279
#define GLU_TESS_END
Definition: GL_glu.h:211
#define GLU_TESS_WINDING_RULE
Definition: GL_glu.h:232
#define GLU_TESS_EDGE_FLAG
Definition: GL_glu.h:214
unsigned int GLenum
Definition: GL_glu.h:266
#define GLU_TESS_MISSING_END_CONTOUR
Definition: GL_glu.h:248
#define GLU_TESS_TOLERANCE
Definition: GL_glu.h:234
#define GLU_TESS_EDGE_FLAG_DATA
Definition: GL_glu.h:221
unsigned char GLboolean
Definition: GL_glu.h:267
#define GLU_TESS_WINDING_ODD
Definition: GL_glu.h:253
#define GLU_TESS_COORD_TOO_LARGE
Definition: GL_glu.h:249
#define GLU_TESS_VERTEX_DATA
Definition: GL_glu.h:218
#define GLU_TESS_BEGIN
Definition: GL_glu.h:207
#define GLAPIENTRY
Definition: GL_glu.h:46
#define GLU_TESS_COMBINE
Definition: GL_glu.h:216
#define GLU_TESS_ERROR
Definition: GL_glu.h:213
#define GLU_TESS_MISSING_BEGIN_POLYGON
Definition: GL_glu.h:245
#define GLU_TESS_MAX_COORD
Definition: GL_glu.h:311
#define GLU_OUT_OF_MEMORY
Definition: GL_glu.h:83
#define GLU_TESS_MISSING_END_POLYGON
Definition: GL_glu.h:247
#define GLU_TESS_ERROR_DATA
Definition: GL_glu.h:220
#define GLU_INVALID_VALUE
Definition: GL_glu.h:82
#define GLU_TESS_WINDING_ABS_GEQ_TWO
Definition: GL_glu.h:257
#define e(i)
Definition: RSha256.hxx:103
int type
Definition: TGX11.cxx:120
typedef void((*Func_t)())
Double_t y[n]
Definition: legend1.C:17
Double_t x[n]
Definition: legend1.C:17
#define memAlloc
Definition: memalloc.h:48
#define memInit
Definition: memalloc.h:43
#define memFree
Definition: memalloc.h:41
GLUhalfEdge * __gl_meshMakeEdge(GLUmesh *mesh)
Definition: mesh.c:270
GLUhalfEdge * __gl_meshSplitEdge(GLUhalfEdge *eOrg)
Definition: mesh.c:470
void __gl_meshCheckMesh(GLUmesh *mesh)
Definition: mesh.c:737
void __gl_meshDeleteMesh(GLUmesh *mesh)
Definition: mesh.c:706
GLUmesh * __gl_meshNewMesh(void)
Definition: mesh.c:598
int __gl_meshSplice(GLUhalfEdge *eOrg, GLUhalfEdge *eDst)
Definition: mesh.c:323
void __gl_projectPolygon(GLUtesselator *tess)
Definition: normal.c:198
GLboolean __gl_renderCache(GLUtesselator *tess)
Definition: render.c:442
void __gl_renderMesh(GLUtesselator *tess, GLUmesh *mesh)
Definition: render.c:82
void __gl_renderBoundary(GLUtesselator *tess, GLUmesh *mesh)
Definition: render.c:340
Definition: mesh.h:168
GLboolean flagBoundary
Definition: tess.h:92
int cacheCount
Definition: tess.h:107
GLUhalfEdge * lastEdge
Definition: tess.h:65
GLboolean emptyCache
Definition: tess.h:106
enum TessState state
Definition: tess.h:63
GLdouble normal[3]
Definition: tess.h:73
GLboolean boundaryOnly
Definition: tess.h:93
GLdouble relTolerance
Definition: tess.h:79
GLenum windingRule
Definition: tess.h:80
GLboolean fatalError
Definition: tess.h:81
GLUmesh * mesh
Definition: tess.h:66
void * polygonData
Definition: tess.h:111
jmp_buf env
Definition: tess.h:121
CachedVertex cache[TESS_MAX_CACHE]
Definition: tess.h:108
int __gl_computeInterior(GLUtesselator *tess)
Definition: sweep.c:1301
void GLAPIENTRY __gl_noErrorData(GLenum errnum, void *polygonData)
Definition: tess.c:80
void GLAPIENTRY gluGetTessProperty(GLUtesselator *tess, GLenum which, GLdouble *value)
Definition: tess.c:250
static int AddVertex(GLUtesselator *tess, GLdouble coords[3], void *data)
Definition: tess.c:355
static void GLAPIENTRY noEdgeFlag(GLboolean boundaryEdge)
Definition: tess.c:64
void GLAPIENTRY gluNextContour(GLUtesselator *tess, GLenum type)
Definition: tess.c:630
void GLAPIENTRY __gl_noEdgeFlagData(GLboolean boundaryEdge, void *polygonData)
Definition: tess.c:75
#define MAX_FAST_ALLOC
Definition: tess.c:97
static int EmptyCache(GLUtesselator *tess)
Definition: tess.c:406
void GLAPIENTRY gluBeginPolygon(GLUtesselator *tess)
Definition: tess.c:621
static void MakeDormant(GLUtesselator *tess)
Definition: tess.c:150
static void GLAPIENTRY noBegin(GLenum type)
Definition: tess.c:63
#define GLU_TESS_MESH
Definition: tess.c:48
void GLAPIENTRY gluTessNormal(GLUtesselator *tess, GLdouble x, GLdouble y, GLdouble z)
Definition: tess.c:278
void GLAPIENTRY gluTessProperty(GLUtesselator *tess, GLenum which, GLdouble value)
Definition: tess.c:211
GLUtesselator *GLAPIENTRY gluNewTess(void)
Definition: tess.c:102
static void CacheVertex(GLUtesselator *tess, GLdouble coords[3], void *data)
Definition: tess.c:394
#define RequireState(tess, s)
Definition: tess.c:162
void GLAPIENTRY gluDeleteTess(GLUtesselator *tess)
Definition: tess.c:203
static void GLAPIENTRY noMesh(GLUmesh *mesh)
Definition: tess.c:70
void GLAPIENTRY __gl_noEndData(void *polygonData)
Definition: tess.c:79
void GLAPIENTRY gluTessBeginContour(GLUtesselator *tess)
Definition: tess.c:486
void GLAPIENTRY gluTessCallback(GLUtesselator *tess, GLenum which, _GLUfuncptr fn)
Definition: tess.c:286
#define TRUE
Definition: tess.c:51
#define FALSE
Definition: tess.c:54
#define GLU_TESS_DEFAULT_TOLERANCE
Definition: tess.c:47
void GLAPIENTRY gluTessEndContour(GLUtesselator *tess)
Definition: tess.c:503
void GLAPIENTRY __gl_noVertexData(void *data, void *polygonData)
Definition: tess.c:77
void GLAPIENTRY gluTessVertex(GLUtesselator *tess, GLdouble coords[3], void *data)
Definition: tess.c:425
static void GLAPIENTRY noError(GLenum errnum)
Definition: tess.c:67
void GLAPIENTRY gluTessEndPolygon(GLUtesselator *tess)
Definition: tess.c:510
static void GLAPIENTRY noEnd(void)
Definition: tess.c:66
void GLAPIENTRY __gl_noCombineData(GLdouble coords[3], void *data[4], GLfloat weight[4], void **outData, void *polygonData)
Definition: tess.c:82
static void GotoState(GLUtesselator *tess, enum TessState newState)
Definition: tess.c:164
void GLAPIENTRY gluTessBeginPolygon(GLUtesselator *tess, void *data)
Definition: tess.c:472
static void GLAPIENTRY noCombine(GLdouble coords[3], void *data[4], GLfloat weight[4], void **dataOut)
Definition: tess.c:68
void GLAPIENTRY gluEndPolygon(GLUtesselator *tess)
Definition: tess.c:639
static void GLAPIENTRY noVertex(void *data)
Definition: tess.c:65
void GLAPIENTRY __gl_noBeginData(GLenum type, void *polygonData)
Definition: tess.c:73
#define CALL_ERROR_OR_ERROR_DATA(a)
Definition: tess.h:160
TessState
Definition: tess.h:47
@ T_IN_CONTOUR
Definition: tess.h:47
@ T_IN_POLYGON
Definition: tess.h:47
@ T_DORMANT
Definition: tess.h:47
#define TESS_MAX_CACHE
Definition: tess.h:52
int __gl_meshSetWindingNumber(GLUmesh *mesh, int value, GLboolean keepOnlyBoundary)
Definition: tessmono.c:179
void __gl_meshDiscardExterior(GLUmesh *mesh)
Definition: tessmono.c:155
int __gl_meshTessellateInterior(GLUmesh *mesh)
Definition: tessmono.c:133