56 void (*render)(GLUtesselator *, GLUhalfEdge *, long);
60 static struct FaceCount MaximumFan( GLUhalfEdge *eOrig );
61 static struct FaceCount MaximumStrip( GLUhalfEdge *eOrig );
63 static void RenderFan( GLUtesselator *tess, GLUhalfEdge *eStart,
long size );
64 static void RenderStrip( GLUtesselator *tess, GLUhalfEdge *eStart,
long size );
65 static void RenderTriangle( GLUtesselator *tess, GLUhalfEdge *eStart,
68 static void RenderMaximumFaceGroup( GLUtesselator *tess, GLUface *fOrig );
69 static void RenderLonelyTriangles( GLUtesselator *tess, GLUface *head );
82 void __gl_renderMesh( GLUtesselator *tess, GLUmesh *mesh )
87 tess->lonelyTriList = NULL;
89 for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) {
92 for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) {
98 if( f->inside && ! f->marked ) {
99 RenderMaximumFaceGroup( tess, f );
103 if( tess->lonelyTriList != NULL ) {
104 RenderLonelyTriangles( tess, tess->lonelyTriList );
105 tess->lonelyTriList = NULL;
110 static void RenderMaximumFaceGroup( GLUtesselator *tess, GLUface *fOrig )
119 GLUhalfEdge *e = fOrig->anEdge;
120 struct FaceCount max, newFace;
124 max.render = &RenderTriangle;
126 if( ! tess->flagBoundary ) {
127 newFace = MaximumFan( e );
if( newFace.size > max.size ) { max = newFace; }
128 newFace = MaximumFan( e->Lnext );
if( newFace.size > max.size ) { max = newFace; }
129 newFace = MaximumFan( e->Lprev );
if( newFace.size > max.size ) { max = newFace; }
131 newFace = MaximumStrip( e );
if( newFace.size > max.size ) { max = newFace; }
132 newFace = MaximumStrip( e->Lnext );
if( newFace.size > max.size ) { max = newFace; }
133 newFace = MaximumStrip( e->Lprev );
if( newFace.size > max.size ) { max = newFace; }
135 (*(max.render))( tess, max.eStart, max.size );
146 #define Marked(f) (! (f)->inside || (f)->marked)
148 #define AddToTrail(f,t) ((f)->trail = (t), (t) = (f), (f)->marked = TRUE)
150 #define FreeTrail(t) do { \
151 while( (t) != NULL ) { \
152 (t)->marked = FALSE; t = (t)->trail; \
158 static struct FaceCount MaximumFan( GLUhalfEdge *eOrig )
164 struct FaceCount newFace = { 0, NULL, &RenderFan };
165 GLUface *trail = NULL;
168 for( e = eOrig; ! Marked( e->Lface ); e = e->Onext ) {
169 AddToTrail( e->Lface, trail );
172 for( e = eOrig; ! Marked( e->Rface ); e = e->Oprev ) {
173 AddToTrail( e->Rface, trail );
183 #define IsEven(n) (((n) & 1) == 0)
185 static struct FaceCount MaximumStrip( GLUhalfEdge *eOrig )
197 struct FaceCount newFace = { 0, NULL, &RenderStrip };
198 long headSize = 0, tailSize = 0;
199 GLUface *trail = NULL;
200 GLUhalfEdge *e, *eTail, *eHead;
202 for( e = eOrig; ! Marked( e->Lface ); ++tailSize, e = e->Onext ) {
203 AddToTrail( e->Lface, trail );
206 if( Marked( e->Lface ))
break;
207 AddToTrail( e->Lface, trail );
211 for( e = eOrig; ! Marked( e->Rface ); ++headSize, e = e->Dnext ) {
212 AddToTrail( e->Rface, trail );
215 if( Marked( e->Rface ))
break;
216 AddToTrail( e->Rface, trail );
220 newFace.size = tailSize + headSize;
221 if( IsEven( tailSize )) {
222 newFace.eStart = eTail->Sym;
223 }
else if( IsEven( headSize )) {
224 newFace.eStart = eHead;
230 newFace.eStart = eHead->Onext;
238 static void RenderTriangle( GLUtesselator *tess, GLUhalfEdge *e,
long size )
245 AddToTrail( e->Lface, tess->lonelyTriList );
249 static void RenderLonelyTriangles( GLUtesselator *tess, GLUface *f )
258 CALL_BEGIN_OR_BEGIN_DATA( GL_TRIANGLES );
260 for( ; f != NULL; f = f->trail ) {
265 if( tess->flagBoundary ) {
269 newState = ! e->Rface->inside;
270 if( edgeState != newState ) {
271 edgeState = newState;
272 CALL_EDGE_FLAG_OR_EDGE_FLAG_DATA( edgeState );
275 CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
278 }
while( e != f->anEdge );
280 CALL_END_OR_END_DATA();
284 static void RenderFan( GLUtesselator *tess, GLUhalfEdge *e,
long size )
290 CALL_BEGIN_OR_BEGIN_DATA( GL_TRIANGLE_FAN );
291 CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
292 CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
294 while( ! Marked( e->Lface )) {
295 e->Lface->marked = TRUE;
298 CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
302 CALL_END_OR_END_DATA();
306 static void RenderStrip( GLUtesselator *tess, GLUhalfEdge *e,
long size )
312 CALL_BEGIN_OR_BEGIN_DATA( GL_TRIANGLE_STRIP );
313 CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
314 CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
316 while( ! Marked( e->Lface )) {
317 e->Lface->marked = TRUE;
320 CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
321 if( Marked( e->Lface ))
break;
323 e->Lface->marked = TRUE;
326 CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
330 CALL_END_OR_END_DATA();
340 void __gl_renderBoundary( GLUtesselator *tess, GLUmesh *mesh )
345 for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) {
347 CALL_BEGIN_OR_BEGIN_DATA( GL_LINE_LOOP );
350 CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
352 }
while( e != f->anEdge );
353 CALL_END_OR_END_DATA();
361 #define SIGN_INCONSISTENT 2
363 static int ComputeNormal( GLUtesselator *tess, GLdouble norm[3],
int check )
373 CachedVertex *v0 = tess->cache;
374 CachedVertex *vn = v0 + tess->cacheCount;
376 GLdouble dot, xc, yc, zc, xp, yp, zp, n[3];
393 norm[0] = norm[1] = norm[2] = 0.0;
397 xc = vc->coords[0] - v0->coords[0];
398 yc = vc->coords[1] - v0->coords[1];
399 zc = vc->coords[2] - v0->coords[2];
401 xp = xc; yp = yc; zp = zc;
402 xc = vc->coords[0] - v0->coords[0];
403 yc = vc->coords[1] - v0->coords[1];
404 zc = vc->coords[2] - v0->coords[2];
407 n[0] = yp*zc - zp*yc;
408 n[1] = zp*xc - xp*zc;
409 n[2] = xp*yc - yp*xc;
411 dot = n[0]*norm[0] + n[1]*norm[1] + n[2]*norm[2];
417 norm[0] += n[0]; norm[1] += n[1]; norm[2] += n[2];
419 norm[0] -= n[0]; norm[1] -= n[1]; norm[2] -= n[2];
421 }
else if( dot != 0 ) {
424 if( sign < 0 )
return SIGN_INCONSISTENT;
427 if( sign > 0 )
return SIGN_INCONSISTENT;
442 GLboolean __gl_renderCache( GLUtesselator *tess )
444 CachedVertex *v0 = tess->cache;
445 CachedVertex *vn = v0 + tess->cacheCount;
450 if( tess->cacheCount < 3 ) {
455 norm[0] = tess->normal[0];
456 norm[1] = tess->normal[1];
457 norm[2] = tess->normal[2];
458 if( norm[0] == 0 && norm[1] == 0 && norm[2] == 0 ) {
459 ComputeNormal( tess, norm, FALSE );
462 sign = ComputeNormal( tess, norm, TRUE );
463 if( sign == SIGN_INCONSISTENT ) {
473 switch( tess->windingRule ) {
474 case GLU_TESS_WINDING_ODD:
475 case GLU_TESS_WINDING_NONZERO:
477 case GLU_TESS_WINDING_POSITIVE:
478 if( sign < 0 )
return TRUE;
480 case GLU_TESS_WINDING_NEGATIVE:
481 if( sign > 0 )
return TRUE;
483 case GLU_TESS_WINDING_ABS_GEQ_TWO:
487 CALL_BEGIN_OR_BEGIN_DATA( tess->boundaryOnly ? GL_LINE_LOOP
488 : (tess->cacheCount > 3) ? GL_TRIANGLE_FAN
491 CALL_VERTEX_OR_VERTEX_DATA( v0->data );
493 for( vc = v0+1; vc < vn; ++vc ) {
494 CALL_VERTEX_OR_VERTEX_DATA( vc->data );
497 for( vc = vn-1; vc > v0; --vc ) {
498 CALL_VERTEX_OR_VERTEX_DATA( vc->data );
501 CALL_END_OR_END_DATA();