~ubuntu-branches/debian/experimental/stellarium/experimental

« back to all changes in this revision

Viewing changes to src/external/glues_stel/source/libtess/tess.c

  • Committer: Bazaar Package Importer
  • Author(s): Cédric Delfosse
  • Date: 2010-07-31 15:44:02 UTC
  • mfrom: (1.2.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20100731154402-511dojtyt5ycuizd
Tags: 0.10.5-1
* New upstream release (Closes: #586804)
* Remove 01_fix_pow10_function_check.diff, now applied upstream
* Remove 02_remove_unknown_locale_code.diff, no more needed
* Rendering of `old_style' landscapes fixed by upstream (Closes: #581657)
* Update debian/control:
  - Bump Standards-Version from 3.8.4 to 3.9.0
  - Add libqt4-sql-sqlite to Depends (Closes: #582726)
* Update debian/copyright:
  - Fix FSF address

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 * Important: Fabien Chereau - September 2009
34
 
 * Modifs for the use of Stellarium
35
 
 *
36
 
**
37
 
*/
38
 
 
39
 
#include <stddef.h>
40
 
#include <assert.h>
41
 
#include <setjmp.h>
42
 
#include "memalloc.h"
43
 
#include "tess.h"
44
 
#include "mesh.h"
45
 
#include "normal.h"
46
 
#include "sweep.h"
47
 
#include "tessmono.h"
48
 
#include "render.h"
49
 
 
50
 
#define GLUES_TESS_DEFAULT_TOLERANCE 0.0f
51
 
#define GLUES_TESS_MESH              100112  /* void (*)(GLUESmesh *mesh) */
52
 
 
53
 
#define TRUE  1
54
 
#define FALSE 0
55
 
 
56
 
 
57
 
/*ARGSUSED*/ static void  noBegin(GLenum type) {}
58
 
/*ARGSUSED*/ static void  noEdgeFlag(GLboolean boundaryEdge ) {}
59
 
/*ARGSUSED*/ static void  noVertex(void* data) {}
60
 
/*ARGSUSED*/ static void  noEnd(void) {}
61
 
/*ARGSUSED*/ static void  noError(GLenum errnum) {}
62
 
/*ARGSUSED*/ static void  noCombine(double coords[3], void *data[4],
63
 
                                            GLfloat weight[4], void **dataOut) {}
64
 
/*ARGSUSED*/ static void  noMesh(GLUESmesh* mesh) {}
65
 
 
66
 
/*ARGSUSED*/ void  __gl_noBeginData(GLenum type, void* polygonData) {}
67
 
/*ARGSUSED*/ void  __gl_noEdgeFlagData(GLboolean boundaryEdge, void* polygonData) {}
68
 
/*ARGSUSED*/ void  __gl_noVertexData(void* data, void* polygonData) {}
69
 
/*ARGSUSED*/ void  __gl_noEndData(void* polygonData) {}
70
 
/*ARGSUSED*/ void  __gl_noErrorData( GLenum errnum, void* polygonData) {}
71
 
/*ARGSUSED*/ void  __gl_noCombineData(double coords[3], void* data[4],
72
 
                                              GLfloat weight[4], void** outData,
73
 
                                              void* polygonData) {}
74
 
 
75
 
/* Half-edges are allocated in pairs (see mesh.c) */
76
 
typedef struct {GLUEShalfEdge e, eSym;} EdgePair;
77
 
 
78
 
#undef  MAX
79
 
#define MAX(a, b)       ((a)>(b) ? (a): (b))
80
 
#define MAX_FAST_ALLOC  (MAX(sizeof(EdgePair), \
81
 
                         MAX(sizeof(GLUESvertex), sizeof(GLUESface))))
82
 
 
83
 
GLUEStesselator*  gluesNewTess(void)
84
 
{
85
 
   GLUEStesselator* tess;
86
 
 
87
 
   /* Only initialize fields which can be changed by the api.  Other fields
88
 
    * are initialized where they are used.
89
 
    */
90
 
 
91
 
   if (memInit(MAX_FAST_ALLOC)==0)
92
 
   {
93
 
      return 0; /* out of memory */
94
 
   }
95
 
   tess=(GLUEStesselator*)memAlloc(sizeof(GLUEStesselator));
96
 
   if (tess==NULL)
97
 
   {
98
 
      return 0; /* out of memory */
99
 
   }
100
 
 
101
 
   tess->state=T_DORMANT;
102
 
 
103
 
   tess->normal[0]=0;
104
 
   tess->normal[1]=0;
105
 
   tess->normal[2]=0;
106
 
 
107
 
   tess->relTolerance=GLUES_TESS_DEFAULT_TOLERANCE;
108
 
   tess->windingRule=GLUES_TESS_WINDING_ODD;
109
 
   tess->flagBoundary=FALSE;
110
 
   tess->boundaryOnly=FALSE;
111
 
 
112
 
   tess->callBegin=&noBegin;
113
 
   tess->callEdgeFlag=&noEdgeFlag;
114
 
   tess->callVertex=&noVertex;
115
 
   tess->callEnd=&noEnd;
116
 
 
117
 
   tess->callError=&noError;
118
 
   tess->callCombine=&noCombine;
119
 
   tess->callMesh=&noMesh;
120
 
 
121
 
   tess->callBeginData=&__gl_noBeginData;
122
 
   tess->callEdgeFlagData=&__gl_noEdgeFlagData;
123
 
   tess->callVertexData=&__gl_noVertexData;
124
 
   tess->callEndData=&__gl_noEndData;
125
 
   tess->callErrorData=&__gl_noErrorData;
126
 
   tess->callCombineData=&__gl_noCombineData;
127
 
 
128
 
   tess->polygonData=NULL;
129
 
 
130
 
   return tess;
131
 
}
132
 
 
133
 
static void MakeDormant( GLUEStesselator *tess )
134
 
{
135
 
   /* Return the tessellator to its original dormant state. */
136
 
   if (tess->mesh!=NULL)
137
 
   {
138
 
      __gl_meshDeleteMesh(tess->mesh);
139
 
   }
140
 
   tess->state=T_DORMANT;
141
 
   tess->lastEdge=NULL;
142
 
   tess->mesh=NULL;
143
 
}
144
 
 
145
 
#define RequireState(tess, s) if (tess->state!=s) { GotoState(tess, s); }
146
 
 
147
 
static void GotoState(GLUEStesselator* tess, enum TessState newState)
148
 
{
149
 
   while (tess->state!=newState)
150
 
   {
151
 
      /* We change the current state one level at a time, to get to
152
 
       * the desired state.
153
 
       */
154
 
      if (tess->state<newState)
155
 
      {
156
 
         switch (tess->state)
157
 
         {
158
 
            case T_DORMANT:
159
 
                 CALL_ERROR_OR_ERROR_DATA(GLUES_TESS_MISSING_BEGIN_POLYGON);
160
 
                 gluesTessBeginPolygon(tess, NULL);
161
 
                 break;
162
 
            case T_IN_POLYGON:
163
 
                 CALL_ERROR_OR_ERROR_DATA(GLUES_TESS_MISSING_BEGIN_CONTOUR);
164
 
                 gluesTessBeginContour(tess);
165
 
                 break;
166
 
            default:
167
 
                 break;
168
 
         }
169
 
      }
170
 
      else
171
 
      {
172
 
         switch (tess->state)
173
 
         {
174
 
            case T_IN_CONTOUR:
175
 
                 CALL_ERROR_OR_ERROR_DATA( GLUES_TESS_MISSING_END_CONTOUR );
176
 
                 gluesTessEndContour(tess);
177
 
                 break;
178
 
            case T_IN_POLYGON:
179
 
                 CALL_ERROR_OR_ERROR_DATA(GLUES_TESS_MISSING_END_POLYGON);
180
 
                 /* gluesTessEndPolygon(tess) is too much work! */
181
 
                 MakeDormant(tess);
182
 
                 break;
183
 
            default:
184
 
                 break;
185
 
         }
186
 
      }
187
 
   }
188
 
}
189
 
 
190
 
void  gluesDeleteTess(GLUEStesselator* tess)
191
 
{
192
 
   RequireState(tess, T_DORMANT);
193
 
   memFree(tess);
194
 
}
195
 
 
196
 
void  gluesTessProperty(GLUEStesselator* tess, GLenum which, double value)
197
 
{
198
 
   GLenum windingRule;
199
 
 
200
 
   switch (which)
201
 
   {
202
 
      case GLUES_TESS_TOLERANCE:
203
 
           if (value<0.0f || value>1.0f)
204
 
           {
205
 
              break;
206
 
           }
207
 
           tess->relTolerance = value;
208
 
           return;
209
 
      case GLUES_TESS_WINDING_RULE:
210
 
           windingRule=(GLenum)value;
211
 
           if (windingRule!=value)
212
 
           {
213
 
              break;    /* not an integer */
214
 
           }
215
 
 
216
 
           switch (windingRule)
217
 
           {
218
 
              case GLUES_TESS_WINDING_ODD:
219
 
              case GLUES_TESS_WINDING_NONZERO:
220
 
              case GLUES_TESS_WINDING_POSITIVE:
221
 
              case GLUES_TESS_WINDING_NEGATIVE:
222
 
              case GLUES_TESS_WINDING_ABS_GEQ_TWO:
223
 
                   tess->windingRule=windingRule;
224
 
                   return;
225
 
              default:
226
 
                   break;
227
 
           }
228
 
           break;
229
 
      case GLUES_TESS_BOUNDARY_ONLY:
230
 
           tess->boundaryOnly=(value!=0);
231
 
           return;
232
 
      default:
233
 
           CALL_ERROR_OR_ERROR_DATA(GLUES_INVALID_ENUM);
234
 
           return;
235
 
   }
236
 
 
237
 
   CALL_ERROR_OR_ERROR_DATA(GLUES_INVALID_VALUE);
238
 
}
239
 
 
240
 
/* Returns tessellator property */
241
 
void  gluesGetTessProperty(GLUEStesselator* tess, GLenum which, double* value)
242
 
{
243
 
   switch (which)
244
 
   {
245
 
      case GLUES_TESS_TOLERANCE:
246
 
           /* tolerance should be in range [0..1] */
247
 
           assert(0.0f<=tess->relTolerance && tess->relTolerance<=1.0f);
248
 
           *value=tess->relTolerance;
249
 
           break;
250
 
      case GLUES_TESS_WINDING_RULE:
251
 
           assert(tess->windingRule==GLUES_TESS_WINDING_ODD ||
252
 
                  tess->windingRule==GLUES_TESS_WINDING_NONZERO ||
253
 
                  tess->windingRule==GLUES_TESS_WINDING_POSITIVE ||
254
 
                  tess->windingRule==GLUES_TESS_WINDING_NEGATIVE ||
255
 
                  tess->windingRule==GLUES_TESS_WINDING_ABS_GEQ_TWO);
256
 
           *value=(GLfloat)tess->windingRule;
257
 
           break;
258
 
      case GLUES_TESS_BOUNDARY_ONLY:
259
 
           assert(tess->boundaryOnly==TRUE || tess->boundaryOnly==FALSE);
260
 
           *value=tess->boundaryOnly;
261
 
           break;
262
 
      default:
263
 
           *value=0.0f;
264
 
           CALL_ERROR_OR_ERROR_DATA(GLUES_INVALID_ENUM);
265
 
           break;
266
 
   }
267
 
}
268
 
 
269
 
void  gluesTessNormal(GLUEStesselator* tess, double x, double y, double z)
270
 
{
271
 
   tess->normal[0]=x;
272
 
   tess->normal[1]=y;
273
 
   tess->normal[2]=z;
274
 
}
275
 
 
276
 
void  gluesTessCallback(GLUEStesselator* tess, GLenum which, _GLUESfuncptr fn)
277
 
{
278
 
   switch (which)
279
 
   {
280
 
      case GLUES_TESS_BEGIN:
281
 
           tess->callBegin=(fn==NULL) ? &noBegin: (void (*)(GLenum))fn;
282
 
           return;
283
 
      case GLUES_TESS_BEGIN_DATA:
284
 
           tess->callBeginData=(fn==NULL) ?
285
 
              &__gl_noBeginData: (void (*)(GLenum, void*))fn;
286
 
           return;
287
 
      case GLUES_TESS_EDGE_FLAG:
288
 
           tess->callEdgeFlag=(fn==NULL) ? &noEdgeFlag: (void (*)(GLboolean))fn;
289
 
           /* If the client wants boundary edges to be flagged,
290
 
            * we render everything as separate triangles (no strips or fans).
291
 
            */
292
 
           tess->flagBoundary=(fn!=NULL);
293
 
           return;
294
 
      case GLUES_TESS_EDGE_FLAG_DATA:
295
 
           tess->callEdgeFlagData=(fn==NULL) ?
296
 
              &__gl_noEdgeFlagData: (void (*)(GLboolean, void*))fn;
297
 
           /* If the client wants boundary edges to be flagged,
298
 
            * we render everything as separate triangles (no strips or fans).
299
 
            */
300
 
           tess->flagBoundary=(fn!=NULL);
301
 
           return;
302
 
      case GLUES_TESS_VERTEX:
303
 
           tess->callVertex=(fn==NULL) ? &noVertex: (void (*)(void*))fn;
304
 
           return;
305
 
      case GLUES_TESS_VERTEX_DATA:
306
 
           tess->callVertexData=(fn==NULL) ?
307
 
              &__gl_noVertexData: (void (*)(void*, void*))fn;
308
 
           return;
309
 
      case GLUES_TESS_END:
310
 
           tess->callEnd=(fn==NULL) ? &noEnd: (void (*)(void))fn;
311
 
           return;
312
 
      case GLUES_TESS_END_DATA:
313
 
           tess->callEndData=(fn==NULL) ? &__gl_noEndData: (void (*)(void*))fn;
314
 
           return;
315
 
      case GLUES_TESS_ERROR:
316
 
           tess->callError=(fn==NULL) ? &noError: (void (*)(GLenum))fn;
317
 
           return;
318
 
      case GLUES_TESS_ERROR_DATA:
319
 
           tess->callErrorData=(fn==NULL) ? &__gl_noErrorData: (void (*)(GLenum, void*))fn;
320
 
           return;
321
 
      case GLUES_TESS_COMBINE:
322
 
           tess->callCombine=(fn==NULL) ? &noCombine:
323
 
                           (void (*)(double[3], void*[4], GLfloat[4], void**))fn;
324
 
           return;
325
 
      case GLUES_TESS_COMBINE_DATA:
326
 
           tess->callCombineData=(fn==NULL) ? &__gl_noCombineData:
327
 
                           (void (*)(double [3], void*[4], GLfloat[4], void**, void*))fn;
328
 
           return;
329
 
      case GLUES_TESS_MESH:
330
 
           tess->callMesh=(fn==NULL) ? &noMesh: (void (*)(GLUESmesh*))fn;
331
 
           return;
332
 
      default:
333
 
           CALL_ERROR_OR_ERROR_DATA( GLUES_INVALID_ENUM );
334
 
           return;
335
 
   }
336
 
}
337
 
 
338
 
static int AddVertex(GLUEStesselator* tess, double coords[3], void* data)
339
 
{
340
 
   GLUEShalfEdge* e=NULL;
341
 
 
342
 
   e=tess->lastEdge;
343
 
   if (e==NULL)
344
 
   {
345
 
      /* Make a self-loop (one vertex, one edge). */
346
 
      e=__gl_meshMakeEdge(tess->mesh);
347
 
      if (e==NULL)
348
 
      {
349
 
         return 0;
350
 
      }
351
 
      if (!__gl_meshSplice(e, e->Sym))
352
 
      {
353
 
         return 0;
354
 
      }
355
 
   }
356
 
   else
357
 
   {
358
 
      /* Create a new vertex and edge which immediately follow e
359
 
       * in the ordering around the left face.
360
 
       */
361
 
      if (__gl_meshSplitEdge(e)==NULL)
362
 
      {
363
 
         return 0;
364
 
      }
365
 
      e=e->Lnext;
366
 
   }
367
 
 
368
 
   /* The new vertex is now e->Org. */
369
 
   e->Org->data=data;
370
 
   e->Org->coords[0]=coords[0];
371
 
   e->Org->coords[1]=coords[1];
372
 
   e->Org->coords[2]=coords[2];
373
 
 
374
 
   /* The winding of an edge says how the winding number changes as we
375
 
    * cross from the edge''s right face to its left face.  We add the
376
 
    * vertices in such an order that a CCW contour will add +1 to
377
 
    * the winding number of the region inside the contour.
378
 
    */
379
 
   e->winding=1;
380
 
   e->Sym->winding=-1;
381
 
 
382
 
   tess->lastEdge=e;
383
 
 
384
 
   return 1;
385
 
}
386
 
 
387
 
static void CacheVertex(GLUEStesselator* tess, double coords[3], void* data)
388
 
{
389
 
   CachedVertex* v=&tess->cache[tess->cacheCount];
390
 
 
391
 
   v->data=data;
392
 
   v->coords[0]=coords[0];
393
 
   v->coords[1]=coords[1];
394
 
   v->coords[2]=coords[2];
395
 
   ++tess->cacheCount;
396
 
}
397
 
 
398
 
static int EmptyCache(GLUEStesselator* tess)
399
 
{
400
 
   CachedVertex* v=tess->cache;
401
 
   CachedVertex* vLast;
402
 
 
403
 
   tess->mesh=__gl_meshNewMesh();
404
 
   if (tess->mesh==NULL)
405
 
   {
406
 
      return 0;
407
 
   }
408
 
 
409
 
   for(vLast=v+tess->cacheCount; v<vLast; ++v)
410
 
   {
411
 
      if (!AddVertex(tess, v->coords, v->data))
412
 
      {
413
 
         return 0;
414
 
      }
415
 
   }
416
 
   tess->cacheCount=0;
417
 
   tess->emptyCache=FALSE;
418
 
 
419
 
   return 1;
420
 
}
421
 
 
422
 
 
423
 
void  gluesTessVertex(GLUEStesselator* tess, double coords[3], void* data)
424
 
{
425
 
   int i;
426
 
   int tooLarge=FALSE;
427
 
   double x, clamped[3];
428
 
 
429
 
   RequireState(tess, T_IN_CONTOUR);
430
 
 
431
 
   if (tess->emptyCache)
432
 
   {
433
 
      if (!EmptyCache(tess))
434
 
      {
435
 
         CALL_ERROR_OR_ERROR_DATA( GLUES_OUT_OF_MEMORY );
436
 
         return;
437
 
      }
438
 
      tess->lastEdge=NULL;
439
 
   }
440
 
 
441
 
   for (i=0; i<3; ++i)
442
 
   {
443
 
      x=coords[i];
444
 
      if (x<-GLUES_TESS_MAX_COORD)
445
 
      {
446
 
         x=-GLUES_TESS_MAX_COORD;
447
 
         tooLarge=TRUE;
448
 
      }
449
 
      if (x>GLUES_TESS_MAX_COORD)
450
 
      {
451
 
         x=GLUES_TESS_MAX_COORD;
452
 
         tooLarge=TRUE;
453
 
      }
454
 
      clamped[i]=x;
455
 
   }
456
 
   if (tooLarge)
457
 
   {
458
 
      CALL_ERROR_OR_ERROR_DATA(GLUES_TESS_COORD_TOO_LARGE);
459
 
   }
460
 
 
461
 
   if (tess->mesh==NULL)
462
 
   {
463
 
      if (tess->cacheCount<TESS_MAX_CACHE)
464
 
      {
465
 
         CacheVertex(tess, clamped, data);
466
 
         return;
467
 
      }
468
 
      if (!EmptyCache(tess))
469
 
      {
470
 
         CALL_ERROR_OR_ERROR_DATA(GLUES_OUT_OF_MEMORY);
471
 
         return;
472
 
      }
473
 
   }
474
 
 
475
 
   if (!AddVertex(tess, clamped, data))
476
 
   {
477
 
      CALL_ERROR_OR_ERROR_DATA(GLUES_OUT_OF_MEMORY);
478
 
   }
479
 
}
480
 
 
481
 
void  gluesTessBeginPolygon(GLUEStesselator* tess, void* data)
482
 
{
483
 
   RequireState(tess, T_DORMANT);
484
 
 
485
 
   tess->state=T_IN_POLYGON;
486
 
   tess->cacheCount=0;
487
 
   tess->emptyCache=FALSE;
488
 
   tess->mesh=NULL;
489
 
 
490
 
   tess->polygonData=data;
491
 
}
492
 
 
493
 
void  gluesTessBeginContour(GLUEStesselator* tess)
494
 
{
495
 
   RequireState(tess, T_IN_POLYGON);
496
 
 
497
 
   tess->state=T_IN_CONTOUR;
498
 
   tess->lastEdge=NULL;
499
 
   if (tess->cacheCount>0)
500
 
   {
501
 
      /* Just set a flag so we don't get confused by empty contours
502
 
       * -- these can be generated accidentally with the obsolete
503
 
       * NextContour() interface.
504
 
       */
505
 
      tess->emptyCache=TRUE;
506
 
   }
507
 
}
508
 
 
509
 
void  gluesTessEndContour(GLUEStesselator* tess)
510
 
{
511
 
   RequireState(tess, T_IN_CONTOUR);
512
 
   tess->state=T_IN_POLYGON;
513
 
}
514
 
 
515
 
void  gluesTessEndPolygon(GLUEStesselator* tess)
516
 
{
517
 
   GLUESmesh* mesh;
518
 
 
519
 
   if (setjmp(tess->env)!=0)
520
 
   {
521
 
      /* come back here if out of memory */
522
 
      CALL_ERROR_OR_ERROR_DATA(GLUES_OUT_OF_MEMORY);
523
 
      return;
524
 
   }
525
 
 
526
 
   RequireState(tess, T_IN_POLYGON);
527
 
   tess->state=T_DORMANT;
528
 
 
529
 
   if (tess->mesh==NULL)
530
 
   {
531
 
      if (!tess->flagBoundary && tess->callMesh==&noMesh)
532
 
      {
533
 
         /* Try some special code to make the easy cases go quickly
534
 
          * (eg. convex polygons).  This code does NOT handle multiple contours,
535
 
          * intersections, edge flags, and of course it does not generate
536
 
          * an explicit mesh either.
537
 
          */
538
 
         if (__gl_renderCache(tess))
539
 
         {
540
 
            tess->polygonData= NULL;
541
 
            return;
542
 
         }
543
 
      }
544
 
      if (!EmptyCache(tess))
545
 
      {
546
 
         longjmp(tess->env, 1); /* could've used a label */
547
 
      }
548
 
   }
549
 
 
550
 
   /* Determine the polygon normal and project vertices onto the plane
551
 
    * of the polygon.
552
 
    */
553
 
   __gl_projectPolygon(tess);
554
 
 
555
 
   /* __gl_computeInterior( tess ) computes the planar arrangement specified
556
 
    * by the given contours, and further subdivides this arrangement
557
 
    * into regions.  Each region is marked "inside" if it belongs
558
 
    * to the polygon, according to the rule given by tess->windingRule.
559
 
    * Each interior region is guaranteed be monotone.
560
 
    */
561
 
   if (!__gl_computeInterior(tess))
562
 
   {
563
 
      longjmp(tess->env, 1);     /* could've used a label */
564
 
   }
565
 
 
566
 
   mesh=tess->mesh;
567
 
   if (!tess->fatalError)
568
 
   {
569
 
      int rc=1;
570
 
 
571
 
      /* If the user wants only the boundary contours, we throw away all edges
572
 
       * except those which separate the interior from the exterior.
573
 
       * Otherwise we tessellate all the regions marked "inside".
574
 
       */
575
 
      if (tess->boundaryOnly)
576
 
      {
577
 
         rc=__gl_meshSetWindingNumber(mesh, 1, TRUE);
578
 
      }
579
 
      else
580
 
      {
581
 
         rc=__gl_meshTessellateInterior(mesh);
582
 
      }
583
 
      if (rc==0)
584
 
      {
585
 
         longjmp(tess->env,1);   /* could've used a label */
586
 
      }
587
 
 
588
 
      __gl_meshCheckMesh(mesh);
589
 
 
590
 
      if (tess->callBegin!=&noBegin || tess->callEnd!=&noEnd ||
591
 
          tess->callVertex!=&noVertex || tess->callEdgeFlag!=&noEdgeFlag ||
592
 
          tess->callBeginData!=&__gl_noBeginData || tess->callEndData!=&__gl_noEndData ||
593
 
          tess->callVertexData!=&__gl_noVertexData || tess->callEdgeFlagData!=&__gl_noEdgeFlagData)
594
 
      {
595
 
         if (tess->boundaryOnly)
596
 
         {
597
 
            __gl_renderBoundary(tess, mesh);  /* output boundary contours */
598
 
         }
599
 
         else
600
 
         {
601
 
            __gl_renderMesh(tess, mesh);    /* output strips and fans */
602
 
         }
603
 
      }
604
 
 
605
 
      if (tess->callMesh!=&noMesh)
606
 
      {
607
 
         /* Throw away the exterior faces, so that all faces are interior.
608
 
          * This way the user doesn't have to check the "inside" flag,
609
 
          * and we don't need to even reveal its existence.  It also leaves
610
 
          * the freedom for an implementation to not generate the exterior
611
 
          * faces in the first place.
612
 
          */
613
 
         __gl_meshDiscardExterior(mesh);
614
 
         (*tess->callMesh)(mesh);       /* user wants the mesh itself */
615
 
         tess->mesh = NULL;
616
 
         tess->polygonData= NULL;
617
 
         return;
618
 
      }
619
 
   }
620
 
   __gl_meshDeleteMesh(mesh);
621
 
   tess->polygonData=NULL;
622
 
   tess->mesh=NULL;
623
 
}
624
 
 
625
 
/*******************************************************/
626
 
 
627
 
/* Obsolete calls -- for backward compatibility */
628
 
void  gluesBeginPolygon(GLUEStesselator* tess)
629
 
{
630
 
   gluesTessBeginPolygon(tess, NULL);
631
 
   gluesTessBeginContour(tess);
632
 
}
633
 
 
634
 
/*ARGSUSED*/
635
 
void  gluesNextContour(GLUEStesselator* tess, GLenum type)
636
 
{
637
 
   gluesTessEndContour(tess);
638
 
   gluesTessBeginContour(tess);
639
 
}
640
 
 
641
 
void  gluesEndPolygon(GLUEStesselator* tess)
642
 
{
643
 
   gluesTessEndContour(tess);
644
 
   gluesTessEndPolygon(tess);
645
 
}