1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3*c2c66affSColin Finck * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4*c2c66affSColin Finck *
5*c2c66affSColin Finck * Permission is hereby granted, free of charge, to any person obtaining a
6*c2c66affSColin Finck * copy of this software and associated documentation files (the "Software"),
7*c2c66affSColin Finck * to deal in the Software without restriction, including without limitation
8*c2c66affSColin Finck * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9*c2c66affSColin Finck * and/or sell copies of the Software, and to permit persons to whom the
10*c2c66affSColin Finck * Software is furnished to do so, subject to the following conditions:
11*c2c66affSColin Finck *
12*c2c66affSColin Finck * The above copyright notice including the dates of first publication and
13*c2c66affSColin Finck * either this permission notice or a reference to
14*c2c66affSColin Finck * http://oss.sgi.com/projects/FreeB/
15*c2c66affSColin Finck * shall be included in all copies or substantial portions of the Software.
16*c2c66affSColin Finck *
17*c2c66affSColin Finck * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18*c2c66affSColin Finck * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19*c2c66affSColin Finck * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20*c2c66affSColin Finck * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21*c2c66affSColin Finck * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22*c2c66affSColin Finck * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23*c2c66affSColin Finck * SOFTWARE.
24*c2c66affSColin Finck *
25*c2c66affSColin Finck * Except as contained in this notice, the name of Silicon Graphics, Inc.
26*c2c66affSColin Finck * shall not be used in advertising or otherwise to promote the sale, use or
27*c2c66affSColin Finck * other dealings in this Software without prior written authorization from
28*c2c66affSColin Finck * Silicon Graphics, Inc.
29*c2c66affSColin Finck */
30*c2c66affSColin Finck /*
31*c2c66affSColin Finck ** Author: Eric Veach, July 1994.
32*c2c66affSColin Finck **
33*c2c66affSColin Finck */
34*c2c66affSColin Finck
35*c2c66affSColin Finck #include "gluos.h"
36*c2c66affSColin Finck #include <assert.h>
37*c2c66affSColin Finck //#include <stddef.h>
38*c2c66affSColin Finck //#include "mesh.h"
39*c2c66affSColin Finck #include "tess.h"
40*c2c66affSColin Finck //#include "render.h"
41*c2c66affSColin Finck
42*c2c66affSColin Finck #ifndef TRUE
43*c2c66affSColin Finck #define TRUE 1
44*c2c66affSColin Finck #endif
45*c2c66affSColin Finck #ifndef FALSE
46*c2c66affSColin Finck #define FALSE 0
47*c2c66affSColin Finck #endif
48*c2c66affSColin Finck
49*c2c66affSColin Finck /* This structure remembers the information we need about a primitive
50*c2c66affSColin Finck * to be able to render it later, once we have determined which
51*c2c66affSColin Finck * primitive is able to use the most triangles.
52*c2c66affSColin Finck */
53*c2c66affSColin Finck struct FaceCount {
54*c2c66affSColin Finck long size; /* number of triangles used */
55*c2c66affSColin Finck GLUhalfEdge *eStart; /* edge where this primitive starts */
56*c2c66affSColin Finck void (*render)(GLUtesselator *, GLUhalfEdge *, long);
57*c2c66affSColin Finck /* routine to render this primitive */
58*c2c66affSColin Finck };
59*c2c66affSColin Finck
60*c2c66affSColin Finck static struct FaceCount MaximumFan( GLUhalfEdge *eOrig );
61*c2c66affSColin Finck static struct FaceCount MaximumStrip( GLUhalfEdge *eOrig );
62*c2c66affSColin Finck
63*c2c66affSColin Finck static void RenderFan( GLUtesselator *tess, GLUhalfEdge *eStart, long size );
64*c2c66affSColin Finck static void RenderStrip( GLUtesselator *tess, GLUhalfEdge *eStart, long size );
65*c2c66affSColin Finck static void RenderTriangle( GLUtesselator *tess, GLUhalfEdge *eStart,
66*c2c66affSColin Finck long size );
67*c2c66affSColin Finck
68*c2c66affSColin Finck static void RenderMaximumFaceGroup( GLUtesselator *tess, GLUface *fOrig );
69*c2c66affSColin Finck static void RenderLonelyTriangles( GLUtesselator *tess, GLUface *head );
70*c2c66affSColin Finck
71*c2c66affSColin Finck
72*c2c66affSColin Finck
73*c2c66affSColin Finck /************************ Strips and Fans decomposition ******************/
74*c2c66affSColin Finck
75*c2c66affSColin Finck /* __gl_renderMesh( tess, mesh ) takes a mesh and breaks it into triangle
76*c2c66affSColin Finck * fans, strips, and separate triangles. A substantial effort is made
77*c2c66affSColin Finck * to use as few rendering primitives as possible (ie. to make the fans
78*c2c66affSColin Finck * and strips as large as possible).
79*c2c66affSColin Finck *
80*c2c66affSColin Finck * The rendering output is provided as callbacks (see the api).
81*c2c66affSColin Finck */
__gl_renderMesh(GLUtesselator * tess,GLUmesh * mesh)82*c2c66affSColin Finck void __gl_renderMesh( GLUtesselator *tess, GLUmesh *mesh )
83*c2c66affSColin Finck {
84*c2c66affSColin Finck GLUface *f;
85*c2c66affSColin Finck
86*c2c66affSColin Finck /* Make a list of separate triangles so we can render them all at once */
87*c2c66affSColin Finck tess->lonelyTriList = NULL;
88*c2c66affSColin Finck
89*c2c66affSColin Finck for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) {
90*c2c66affSColin Finck f->marked = FALSE;
91*c2c66affSColin Finck }
92*c2c66affSColin Finck for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) {
93*c2c66affSColin Finck
94*c2c66affSColin Finck /* We examine all faces in an arbitrary order. Whenever we find
95*c2c66affSColin Finck * an unprocessed face F, we output a group of faces including F
96*c2c66affSColin Finck * whose size is maximum.
97*c2c66affSColin Finck */
98*c2c66affSColin Finck if( f->inside && ! f->marked ) {
99*c2c66affSColin Finck RenderMaximumFaceGroup( tess, f );
100*c2c66affSColin Finck assert( f->marked );
101*c2c66affSColin Finck }
102*c2c66affSColin Finck }
103*c2c66affSColin Finck if( tess->lonelyTriList != NULL ) {
104*c2c66affSColin Finck RenderLonelyTriangles( tess, tess->lonelyTriList );
105*c2c66affSColin Finck tess->lonelyTriList = NULL;
106*c2c66affSColin Finck }
107*c2c66affSColin Finck }
108*c2c66affSColin Finck
109*c2c66affSColin Finck
RenderMaximumFaceGroup(GLUtesselator * tess,GLUface * fOrig)110*c2c66affSColin Finck static void RenderMaximumFaceGroup( GLUtesselator *tess, GLUface *fOrig )
111*c2c66affSColin Finck {
112*c2c66affSColin Finck /* We want to find the largest triangle fan or strip of unmarked faces
113*c2c66affSColin Finck * which includes the given face fOrig. There are 3 possible fans
114*c2c66affSColin Finck * passing through fOrig (one centered at each vertex), and 3 possible
115*c2c66affSColin Finck * strips (one for each CCW permutation of the vertices). Our strategy
116*c2c66affSColin Finck * is to try all of these, and take the primitive which uses the most
117*c2c66affSColin Finck * triangles (a greedy approach).
118*c2c66affSColin Finck */
119*c2c66affSColin Finck GLUhalfEdge *e = fOrig->anEdge;
120*c2c66affSColin Finck struct FaceCount max, newFace;
121*c2c66affSColin Finck
122*c2c66affSColin Finck max.size = 1;
123*c2c66affSColin Finck max.eStart = e;
124*c2c66affSColin Finck max.render = &RenderTriangle;
125*c2c66affSColin Finck
126*c2c66affSColin Finck if( ! tess->flagBoundary ) {
127*c2c66affSColin Finck newFace = MaximumFan( e ); if( newFace.size > max.size ) { max = newFace; }
128*c2c66affSColin Finck newFace = MaximumFan( e->Lnext ); if( newFace.size > max.size ) { max = newFace; }
129*c2c66affSColin Finck newFace = MaximumFan( e->Lprev ); if( newFace.size > max.size ) { max = newFace; }
130*c2c66affSColin Finck
131*c2c66affSColin Finck newFace = MaximumStrip( e ); if( newFace.size > max.size ) { max = newFace; }
132*c2c66affSColin Finck newFace = MaximumStrip( e->Lnext ); if( newFace.size > max.size ) { max = newFace; }
133*c2c66affSColin Finck newFace = MaximumStrip( e->Lprev ); if( newFace.size > max.size ) { max = newFace; }
134*c2c66affSColin Finck }
135*c2c66affSColin Finck (*(max.render))( tess, max.eStart, max.size );
136*c2c66affSColin Finck }
137*c2c66affSColin Finck
138*c2c66affSColin Finck
139*c2c66affSColin Finck /* Macros which keep track of faces we have marked temporarily, and allow
140*c2c66affSColin Finck * us to backtrack when necessary. With triangle fans, this is not
141*c2c66affSColin Finck * really necessary, since the only awkward case is a loop of triangles
142*c2c66affSColin Finck * around a single origin vertex. However with strips the situation is
143*c2c66affSColin Finck * more complicated, and we need a general tracking method like the
144*c2c66affSColin Finck * one here.
145*c2c66affSColin Finck */
146*c2c66affSColin Finck #define Marked(f) (! (f)->inside || (f)->marked)
147*c2c66affSColin Finck
148*c2c66affSColin Finck #define AddToTrail(f,t) ((f)->trail = (t), (t) = (f), (f)->marked = TRUE)
149*c2c66affSColin Finck
150*c2c66affSColin Finck #define FreeTrail(t) do { \
151*c2c66affSColin Finck while( (t) != NULL ) { \
152*c2c66affSColin Finck (t)->marked = FALSE; t = (t)->trail; \
153*c2c66affSColin Finck } \
154*c2c66affSColin Finck } while(0) /* absorb trailing semicolon */
155*c2c66affSColin Finck
156*c2c66affSColin Finck
157*c2c66affSColin Finck
MaximumFan(GLUhalfEdge * eOrig)158*c2c66affSColin Finck static struct FaceCount MaximumFan( GLUhalfEdge *eOrig )
159*c2c66affSColin Finck {
160*c2c66affSColin Finck /* eOrig->Lface is the face we want to render. We want to find the size
161*c2c66affSColin Finck * of a maximal fan around eOrig->Org. To do this we just walk around
162*c2c66affSColin Finck * the origin vertex as far as possible in both directions.
163*c2c66affSColin Finck */
164*c2c66affSColin Finck struct FaceCount newFace = { 0, NULL, &RenderFan };
165*c2c66affSColin Finck GLUface *trail = NULL;
166*c2c66affSColin Finck GLUhalfEdge *e;
167*c2c66affSColin Finck
168*c2c66affSColin Finck for( e = eOrig; ! Marked( e->Lface ); e = e->Onext ) {
169*c2c66affSColin Finck AddToTrail( e->Lface, trail );
170*c2c66affSColin Finck ++newFace.size;
171*c2c66affSColin Finck }
172*c2c66affSColin Finck for( e = eOrig; ! Marked( e->Rface ); e = e->Oprev ) {
173*c2c66affSColin Finck AddToTrail( e->Rface, trail );
174*c2c66affSColin Finck ++newFace.size;
175*c2c66affSColin Finck }
176*c2c66affSColin Finck newFace.eStart = e;
177*c2c66affSColin Finck /*LINTED*/
178*c2c66affSColin Finck FreeTrail( trail );
179*c2c66affSColin Finck return newFace;
180*c2c66affSColin Finck }
181*c2c66affSColin Finck
182*c2c66affSColin Finck
183*c2c66affSColin Finck #define IsEven(n) (((n) & 1) == 0)
184*c2c66affSColin Finck
MaximumStrip(GLUhalfEdge * eOrig)185*c2c66affSColin Finck static struct FaceCount MaximumStrip( GLUhalfEdge *eOrig )
186*c2c66affSColin Finck {
187*c2c66affSColin Finck /* Here we are looking for a maximal strip that contains the vertices
188*c2c66affSColin Finck * eOrig->Org, eOrig->Dst, eOrig->Lnext->Dst (in that order or the
189*c2c66affSColin Finck * reverse, such that all triangles are oriented CCW).
190*c2c66affSColin Finck *
191*c2c66affSColin Finck * Again we walk forward and backward as far as possible. However for
192*c2c66affSColin Finck * strips there is a twist: to get CCW orientations, there must be
193*c2c66affSColin Finck * an *even* number of triangles in the strip on one side of eOrig.
194*c2c66affSColin Finck * We walk the strip starting on a side with an even number of triangles;
195*c2c66affSColin Finck * if both side have an odd number, we are forced to shorten one side.
196*c2c66affSColin Finck */
197*c2c66affSColin Finck struct FaceCount newFace = { 0, NULL, &RenderStrip };
198*c2c66affSColin Finck long headSize = 0, tailSize = 0;
199*c2c66affSColin Finck GLUface *trail = NULL;
200*c2c66affSColin Finck GLUhalfEdge *e, *eTail, *eHead;
201*c2c66affSColin Finck
202*c2c66affSColin Finck for( e = eOrig; ! Marked( e->Lface ); ++tailSize, e = e->Onext ) {
203*c2c66affSColin Finck AddToTrail( e->Lface, trail );
204*c2c66affSColin Finck ++tailSize;
205*c2c66affSColin Finck e = e->Dprev;
206*c2c66affSColin Finck if( Marked( e->Lface )) break;
207*c2c66affSColin Finck AddToTrail( e->Lface, trail );
208*c2c66affSColin Finck }
209*c2c66affSColin Finck eTail = e;
210*c2c66affSColin Finck
211*c2c66affSColin Finck for( e = eOrig; ! Marked( e->Rface ); ++headSize, e = e->Dnext ) {
212*c2c66affSColin Finck AddToTrail( e->Rface, trail );
213*c2c66affSColin Finck ++headSize;
214*c2c66affSColin Finck e = e->Oprev;
215*c2c66affSColin Finck if( Marked( e->Rface )) break;
216*c2c66affSColin Finck AddToTrail( e->Rface, trail );
217*c2c66affSColin Finck }
218*c2c66affSColin Finck eHead = e;
219*c2c66affSColin Finck
220*c2c66affSColin Finck newFace.size = tailSize + headSize;
221*c2c66affSColin Finck if( IsEven( tailSize )) {
222*c2c66affSColin Finck newFace.eStart = eTail->Sym;
223*c2c66affSColin Finck } else if( IsEven( headSize )) {
224*c2c66affSColin Finck newFace.eStart = eHead;
225*c2c66affSColin Finck } else {
226*c2c66affSColin Finck /* Both sides have odd length, we must shorten one of them. In fact,
227*c2c66affSColin Finck * we must start from eHead to guarantee inclusion of eOrig->Lface.
228*c2c66affSColin Finck */
229*c2c66affSColin Finck --newFace.size;
230*c2c66affSColin Finck newFace.eStart = eHead->Onext;
231*c2c66affSColin Finck }
232*c2c66affSColin Finck /*LINTED*/
233*c2c66affSColin Finck FreeTrail( trail );
234*c2c66affSColin Finck return newFace;
235*c2c66affSColin Finck }
236*c2c66affSColin Finck
237*c2c66affSColin Finck
RenderTriangle(GLUtesselator * tess,GLUhalfEdge * e,long size)238*c2c66affSColin Finck static void RenderTriangle( GLUtesselator *tess, GLUhalfEdge *e, long size )
239*c2c66affSColin Finck {
240*c2c66affSColin Finck /* Just add the triangle to a triangle list, so we can render all
241*c2c66affSColin Finck * the separate triangles at once.
242*c2c66affSColin Finck */
243*c2c66affSColin Finck assert( size == 1 );
244*c2c66affSColin Finck AddToTrail( e->Lface, tess->lonelyTriList );
245*c2c66affSColin Finck }
246*c2c66affSColin Finck
247*c2c66affSColin Finck
RenderLonelyTriangles(GLUtesselator * tess,GLUface * f)248*c2c66affSColin Finck static void RenderLonelyTriangles( GLUtesselator *tess, GLUface *f )
249*c2c66affSColin Finck {
250*c2c66affSColin Finck /* Now we render all the separate triangles which could not be
251*c2c66affSColin Finck * grouped into a triangle fan or strip.
252*c2c66affSColin Finck */
253*c2c66affSColin Finck GLUhalfEdge *e;
254*c2c66affSColin Finck int newState;
255*c2c66affSColin Finck int edgeState = -1; /* force edge state output for first vertex */
256*c2c66affSColin Finck
257*c2c66affSColin Finck CALL_BEGIN_OR_BEGIN_DATA( GL_TRIANGLES );
258*c2c66affSColin Finck
259*c2c66affSColin Finck for( ; f != NULL; f = f->trail ) {
260*c2c66affSColin Finck /* Loop once for each edge (there will always be 3 edges) */
261*c2c66affSColin Finck
262*c2c66affSColin Finck e = f->anEdge;
263*c2c66affSColin Finck do {
264*c2c66affSColin Finck if( tess->flagBoundary ) {
265*c2c66affSColin Finck /* Set the "edge state" to TRUE just before we output the
266*c2c66affSColin Finck * first vertex of each edge on the polygon boundary.
267*c2c66affSColin Finck */
268*c2c66affSColin Finck newState = ! e->Rface->inside;
269*c2c66affSColin Finck if( edgeState != newState ) {
270*c2c66affSColin Finck edgeState = newState;
271*c2c66affSColin Finck CALL_EDGE_FLAG_OR_EDGE_FLAG_DATA( edgeState );
272*c2c66affSColin Finck }
273*c2c66affSColin Finck }
274*c2c66affSColin Finck CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
275*c2c66affSColin Finck
276*c2c66affSColin Finck e = e->Lnext;
277*c2c66affSColin Finck } while( e != f->anEdge );
278*c2c66affSColin Finck }
279*c2c66affSColin Finck CALL_END_OR_END_DATA();
280*c2c66affSColin Finck }
281*c2c66affSColin Finck
282*c2c66affSColin Finck
RenderFan(GLUtesselator * tess,GLUhalfEdge * e,long size)283*c2c66affSColin Finck static void RenderFan( GLUtesselator *tess, GLUhalfEdge *e, long size )
284*c2c66affSColin Finck {
285*c2c66affSColin Finck /* Render as many CCW triangles as possible in a fan starting from
286*c2c66affSColin Finck * edge "e". The fan *should* contain exactly "size" triangles
287*c2c66affSColin Finck * (otherwise we've goofed up somewhere).
288*c2c66affSColin Finck */
289*c2c66affSColin Finck CALL_BEGIN_OR_BEGIN_DATA( GL_TRIANGLE_FAN );
290*c2c66affSColin Finck CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
291*c2c66affSColin Finck CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
292*c2c66affSColin Finck
293*c2c66affSColin Finck while( ! Marked( e->Lface )) {
294*c2c66affSColin Finck e->Lface->marked = TRUE;
295*c2c66affSColin Finck --size;
296*c2c66affSColin Finck e = e->Onext;
297*c2c66affSColin Finck CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
298*c2c66affSColin Finck }
299*c2c66affSColin Finck
300*c2c66affSColin Finck assert( size == 0 );
301*c2c66affSColin Finck CALL_END_OR_END_DATA();
302*c2c66affSColin Finck }
303*c2c66affSColin Finck
304*c2c66affSColin Finck
RenderStrip(GLUtesselator * tess,GLUhalfEdge * e,long size)305*c2c66affSColin Finck static void RenderStrip( GLUtesselator *tess, GLUhalfEdge *e, long size )
306*c2c66affSColin Finck {
307*c2c66affSColin Finck /* Render as many CCW triangles as possible in a strip starting from
308*c2c66affSColin Finck * edge "e". The strip *should* contain exactly "size" triangles
309*c2c66affSColin Finck * (otherwise we've goofed up somewhere).
310*c2c66affSColin Finck */
311*c2c66affSColin Finck CALL_BEGIN_OR_BEGIN_DATA( GL_TRIANGLE_STRIP );
312*c2c66affSColin Finck CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
313*c2c66affSColin Finck CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
314*c2c66affSColin Finck
315*c2c66affSColin Finck while( ! Marked( e->Lface )) {
316*c2c66affSColin Finck e->Lface->marked = TRUE;
317*c2c66affSColin Finck --size;
318*c2c66affSColin Finck e = e->Dprev;
319*c2c66affSColin Finck CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
320*c2c66affSColin Finck if( Marked( e->Lface )) break;
321*c2c66affSColin Finck
322*c2c66affSColin Finck e->Lface->marked = TRUE;
323*c2c66affSColin Finck --size;
324*c2c66affSColin Finck e = e->Onext;
325*c2c66affSColin Finck CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
326*c2c66affSColin Finck }
327*c2c66affSColin Finck
328*c2c66affSColin Finck assert( size == 0 );
329*c2c66affSColin Finck CALL_END_OR_END_DATA();
330*c2c66affSColin Finck }
331*c2c66affSColin Finck
332*c2c66affSColin Finck
333*c2c66affSColin Finck /************************ Boundary contour decomposition ******************/
334*c2c66affSColin Finck
335*c2c66affSColin Finck /* __gl_renderBoundary( tess, mesh ) takes a mesh, and outputs one
336*c2c66affSColin Finck * contour for each face marked "inside". The rendering output is
337*c2c66affSColin Finck * provided as callbacks (see the api).
338*c2c66affSColin Finck */
__gl_renderBoundary(GLUtesselator * tess,GLUmesh * mesh)339*c2c66affSColin Finck void __gl_renderBoundary( GLUtesselator *tess, GLUmesh *mesh )
340*c2c66affSColin Finck {
341*c2c66affSColin Finck GLUface *f;
342*c2c66affSColin Finck GLUhalfEdge *e;
343*c2c66affSColin Finck
344*c2c66affSColin Finck for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) {
345*c2c66affSColin Finck if( f->inside ) {
346*c2c66affSColin Finck CALL_BEGIN_OR_BEGIN_DATA( GL_LINE_LOOP );
347*c2c66affSColin Finck e = f->anEdge;
348*c2c66affSColin Finck do {
349*c2c66affSColin Finck CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
350*c2c66affSColin Finck e = e->Lnext;
351*c2c66affSColin Finck } while( e != f->anEdge );
352*c2c66affSColin Finck CALL_END_OR_END_DATA();
353*c2c66affSColin Finck }
354*c2c66affSColin Finck }
355*c2c66affSColin Finck }
356*c2c66affSColin Finck
357*c2c66affSColin Finck
358*c2c66affSColin Finck /************************ Quick-and-dirty decomposition ******************/
359*c2c66affSColin Finck
360*c2c66affSColin Finck #define SIGN_INCONSISTENT 2
361*c2c66affSColin Finck
ComputeNormal(GLUtesselator * tess,GLdouble norm[3],int check)362*c2c66affSColin Finck static int ComputeNormal( GLUtesselator *tess, GLdouble norm[3], int check )
363*c2c66affSColin Finck /*
364*c2c66affSColin Finck * If check==FALSE, we compute the polygon normal and place it in norm[].
365*c2c66affSColin Finck * If check==TRUE, we check that each triangle in the fan from v0 has a
366*c2c66affSColin Finck * consistent orientation with respect to norm[]. If triangles are
367*c2c66affSColin Finck * consistently oriented CCW, return 1; if CW, return -1; if all triangles
368*c2c66affSColin Finck * are degenerate return 0; otherwise (no consistent orientation) return
369*c2c66affSColin Finck * SIGN_INCONSISTENT.
370*c2c66affSColin Finck */
371*c2c66affSColin Finck {
372*c2c66affSColin Finck CachedVertex *v0 = tess->cache;
373*c2c66affSColin Finck CachedVertex *vn = v0 + tess->cacheCount;
374*c2c66affSColin Finck CachedVertex *vc;
375*c2c66affSColin Finck GLdouble dot, xc, yc, zc, xp, yp, zp, n[3];
376*c2c66affSColin Finck int sign = 0;
377*c2c66affSColin Finck
378*c2c66affSColin Finck /* Find the polygon normal. It is important to get a reasonable
379*c2c66affSColin Finck * normal even when the polygon is self-intersecting (eg. a bowtie).
380*c2c66affSColin Finck * Otherwise, the computed normal could be very tiny, but perpendicular
381*c2c66affSColin Finck * to the true plane of the polygon due to numerical noise. Then all
382*c2c66affSColin Finck * the triangles would appear to be degenerate and we would incorrectly
383*c2c66affSColin Finck * decompose the polygon as a fan (or simply not render it at all).
384*c2c66affSColin Finck *
385*c2c66affSColin Finck * We use a sum-of-triangles normal algorithm rather than the more
386*c2c66affSColin Finck * efficient sum-of-trapezoids method (used in CheckOrientation()
387*c2c66affSColin Finck * in normal.c). This lets us explicitly reverse the signed area
388*c2c66affSColin Finck * of some triangles to get a reasonable normal in the self-intersecting
389*c2c66affSColin Finck * case.
390*c2c66affSColin Finck */
391*c2c66affSColin Finck if( ! check ) {
392*c2c66affSColin Finck norm[0] = norm[1] = norm[2] = 0.0;
393*c2c66affSColin Finck }
394*c2c66affSColin Finck
395*c2c66affSColin Finck vc = v0 + 1;
396*c2c66affSColin Finck xc = vc->coords[0] - v0->coords[0];
397*c2c66affSColin Finck yc = vc->coords[1] - v0->coords[1];
398*c2c66affSColin Finck zc = vc->coords[2] - v0->coords[2];
399*c2c66affSColin Finck while( ++vc < vn ) {
400*c2c66affSColin Finck xp = xc; yp = yc; zp = zc;
401*c2c66affSColin Finck xc = vc->coords[0] - v0->coords[0];
402*c2c66affSColin Finck yc = vc->coords[1] - v0->coords[1];
403*c2c66affSColin Finck zc = vc->coords[2] - v0->coords[2];
404*c2c66affSColin Finck
405*c2c66affSColin Finck /* Compute (vp - v0) cross (vc - v0) */
406*c2c66affSColin Finck n[0] = yp*zc - zp*yc;
407*c2c66affSColin Finck n[1] = zp*xc - xp*zc;
408*c2c66affSColin Finck n[2] = xp*yc - yp*xc;
409*c2c66affSColin Finck
410*c2c66affSColin Finck dot = n[0]*norm[0] + n[1]*norm[1] + n[2]*norm[2];
411*c2c66affSColin Finck if( ! check ) {
412*c2c66affSColin Finck /* Reverse the contribution of back-facing triangles to get
413*c2c66affSColin Finck * a reasonable normal for self-intersecting polygons (see above)
414*c2c66affSColin Finck */
415*c2c66affSColin Finck if( dot >= 0 ) {
416*c2c66affSColin Finck norm[0] += n[0]; norm[1] += n[1]; norm[2] += n[2];
417*c2c66affSColin Finck } else {
418*c2c66affSColin Finck norm[0] -= n[0]; norm[1] -= n[1]; norm[2] -= n[2];
419*c2c66affSColin Finck }
420*c2c66affSColin Finck } else if( dot != 0 ) {
421*c2c66affSColin Finck /* Check the new orientation for consistency with previous triangles */
422*c2c66affSColin Finck if( dot > 0 ) {
423*c2c66affSColin Finck if( sign < 0 ) return SIGN_INCONSISTENT;
424*c2c66affSColin Finck sign = 1;
425*c2c66affSColin Finck } else {
426*c2c66affSColin Finck if( sign > 0 ) return SIGN_INCONSISTENT;
427*c2c66affSColin Finck sign = -1;
428*c2c66affSColin Finck }
429*c2c66affSColin Finck }
430*c2c66affSColin Finck }
431*c2c66affSColin Finck return sign;
432*c2c66affSColin Finck }
433*c2c66affSColin Finck
434*c2c66affSColin Finck /* __gl_renderCache( tess ) takes a single contour and tries to render it
435*c2c66affSColin Finck * as a triangle fan. This handles convex polygons, as well as some
436*c2c66affSColin Finck * non-convex polygons if we get lucky.
437*c2c66affSColin Finck *
438*c2c66affSColin Finck * Returns TRUE if the polygon was successfully rendered. The rendering
439*c2c66affSColin Finck * output is provided as callbacks (see the api).
440*c2c66affSColin Finck */
__gl_renderCache(GLUtesselator * tess)441*c2c66affSColin Finck GLboolean __gl_renderCache( GLUtesselator *tess )
442*c2c66affSColin Finck {
443*c2c66affSColin Finck CachedVertex *v0 = tess->cache;
444*c2c66affSColin Finck CachedVertex *vn = v0 + tess->cacheCount;
445*c2c66affSColin Finck CachedVertex *vc;
446*c2c66affSColin Finck GLdouble norm[3];
447*c2c66affSColin Finck int sign;
448*c2c66affSColin Finck
449*c2c66affSColin Finck if( tess->cacheCount < 3 ) {
450*c2c66affSColin Finck /* Degenerate contour -- no output */
451*c2c66affSColin Finck return TRUE;
452*c2c66affSColin Finck }
453*c2c66affSColin Finck
454*c2c66affSColin Finck norm[0] = tess->normal[0];
455*c2c66affSColin Finck norm[1] = tess->normal[1];
456*c2c66affSColin Finck norm[2] = tess->normal[2];
457*c2c66affSColin Finck if( norm[0] == 0 && norm[1] == 0 && norm[2] == 0 ) {
458*c2c66affSColin Finck ComputeNormal( tess, norm, FALSE );
459*c2c66affSColin Finck }
460*c2c66affSColin Finck
461*c2c66affSColin Finck sign = ComputeNormal( tess, norm, TRUE );
462*c2c66affSColin Finck if( sign == SIGN_INCONSISTENT ) {
463*c2c66affSColin Finck /* Fan triangles did not have a consistent orientation */
464*c2c66affSColin Finck return FALSE;
465*c2c66affSColin Finck }
466*c2c66affSColin Finck if( sign == 0 ) {
467*c2c66affSColin Finck /* All triangles were degenerate */
468*c2c66affSColin Finck return TRUE;
469*c2c66affSColin Finck }
470*c2c66affSColin Finck
471*c2c66affSColin Finck /* Make sure we do the right thing for each winding rule */
472*c2c66affSColin Finck switch( tess->windingRule ) {
473*c2c66affSColin Finck case GLU_TESS_WINDING_ODD:
474*c2c66affSColin Finck case GLU_TESS_WINDING_NONZERO:
475*c2c66affSColin Finck break;
476*c2c66affSColin Finck case GLU_TESS_WINDING_POSITIVE:
477*c2c66affSColin Finck if( sign < 0 ) return TRUE;
478*c2c66affSColin Finck break;
479*c2c66affSColin Finck case GLU_TESS_WINDING_NEGATIVE:
480*c2c66affSColin Finck if( sign > 0 ) return TRUE;
481*c2c66affSColin Finck break;
482*c2c66affSColin Finck case GLU_TESS_WINDING_ABS_GEQ_TWO:
483*c2c66affSColin Finck return TRUE;
484*c2c66affSColin Finck }
485*c2c66affSColin Finck
486*c2c66affSColin Finck CALL_BEGIN_OR_BEGIN_DATA( tess->boundaryOnly ? GL_LINE_LOOP
487*c2c66affSColin Finck : (tess->cacheCount > 3) ? GL_TRIANGLE_FAN
488*c2c66affSColin Finck : GL_TRIANGLES );
489*c2c66affSColin Finck
490*c2c66affSColin Finck CALL_VERTEX_OR_VERTEX_DATA( v0->data );
491*c2c66affSColin Finck if( sign > 0 ) {
492*c2c66affSColin Finck for( vc = v0+1; vc < vn; ++vc ) {
493*c2c66affSColin Finck CALL_VERTEX_OR_VERTEX_DATA( vc->data );
494*c2c66affSColin Finck }
495*c2c66affSColin Finck } else {
496*c2c66affSColin Finck for( vc = vn-1; vc > v0; --vc ) {
497*c2c66affSColin Finck CALL_VERTEX_OR_VERTEX_DATA( vc->data );
498*c2c66affSColin Finck }
499*c2c66affSColin Finck }
500*c2c66affSColin Finck CALL_END_OR_END_DATA();
501*c2c66affSColin Finck return TRUE;
502*c2c66affSColin Finck }
503