Subversion Repositories shark

Rev

Rev 55 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
55 pj 1
/* $Id: tess.c,v 1.1 2003-02-28 11:42:08 pj Exp $ */
2
 
3
/*
4
 * Mesa 3-D graphics library
5
 * Version:  3.3
6
 * Copyright (C) 1995-2000  Brian Paul
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Library General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2 of the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Library General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Library General Public
19
 * License along with this library; if not, write to the Free
20
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
 */
22
 
23
 
24
/*
25
 * This file is part of the polygon tesselation code contributed by
26
 * Bogdan Sikorski
27
 */
28
 
29
 
30
#ifdef PC_HEADER
31
#include "all.h"
32
#else
33
#include <math.h>
34
#include <stdlib.h>
35
#include "tess.h"
36
#endif
37
 
38
 
39
/*
40
 * This is ugly, but seems the easiest way to do things to make the
41
 * code work under YellowBox for Windows
42
 */
43
#if defined(OPENSTEP) && defined(CALLBACK)
44
#undef CALLBACK
45
#define CALLBACK
46
#endif
47
 
48
 
49
static void delete_contours(GLUtriangulatorObj *);
50
 
51
#ifdef __CYGWIN32__
52
#define _CALLBACK
53
#else
54
#define _CALLBACK GLCALLBACK
55
#endif
56
 
57
 
58
static void
59
init_callbacks(tess_callbacks * callbacks)
60
{
61
   callbacks->begin = (void (_CALLBACK *) (GLenum)) 0;
62
   callbacks->edgeFlag = (void (_CALLBACK *) (GLboolean)) 0;
63
   callbacks->vertex = (void (_CALLBACK *) (void *)) 0;
64
   callbacks->end = (void (_CALLBACK *) (void)) 0;
65
   callbacks->error = (void (_CALLBACK *) (GLenum)) 0;
66
}
67
 
68
void
69
tess_call_user_error(GLUtriangulatorObj * tobj, GLenum gluerr)
70
{
71
   if (tobj->error == GLU_NO_ERROR)
72
      tobj->error = gluerr;
73
   if (tobj->callbacks.error != NULL)
74
      (tobj->callbacks.error) (gluerr);
75
}
76
 
77
GLUtriangulatorObj *GLAPIENTRY
78
gluNewTess(void)
79
{
80
   GLUtriangulatorObj *tobj;
81
 
82
   if ((tobj = (GLUtriangulatorObj *)
83
        malloc(sizeof(struct GLUtesselator))) == NULL)
84
      return NULL;
85
   tobj->contours = tobj->last_contour = NULL;
86
   init_callbacks(&tobj->callbacks);
87
   tobj->error = GLU_NO_ERROR;
88
   tobj->current_polygon = NULL;
89
   tobj->contour_cnt = 0;
90
   return tobj;
91
}
92
 
93
 
94
void GLAPIENTRY
95
gluTessCallback(GLUtriangulatorObj * tobj, GLenum which,
96
                void (GLCALLBACK * fn) ())
97
{
98
   switch (which) {
99
   case GLU_BEGIN:
100
      tobj->callbacks.begin = (void (_CALLBACK *) (GLenum)) fn;
101
      break;
102
   case GLU_EDGE_FLAG:
103
      tobj->callbacks.edgeFlag = (void (_CALLBACK *) (GLboolean)) fn;
104
      break;
105
   case GLU_VERTEX:
106
      tobj->callbacks.vertex = (void (_CALLBACK *) (void *)) fn;
107
      break;
108
   case GLU_END:
109
      tobj->callbacks.end = (void (_CALLBACK *) (void)) fn;
110
      break;
111
   case GLU_ERROR:
112
      tobj->callbacks.error = (void (_CALLBACK *) (GLenum)) fn;
113
      break;
114
   default:
115
      tobj->error = GLU_INVALID_ENUM;
116
      break;
117
   }
118
}
119
 
120
 
121
 
122
void GLAPIENTRY
123
gluDeleteTess(GLUtriangulatorObj * tobj)
124
{
125
   if (tobj->error == GLU_NO_ERROR && tobj->contour_cnt)
126
      /* was gluEndPolygon called? */
127
      tess_call_user_error(tobj, GLU_TESS_ERROR1);
128
   /* delete all internal structures */
129
   delete_contours(tobj);
130
   free(tobj);
131
}
132
 
133
 
134
void GLAPIENTRY
135
gluBeginPolygon(GLUtriangulatorObj * tobj)
136
{
137
/*
138
        if(tobj->error!=GLU_NO_ERROR)
139
                return;
140
*/
141
   tobj->error = GLU_NO_ERROR;
142
   if (tobj->current_polygon != NULL) {
143
      /* gluEndPolygon was not called */
144
      tess_call_user_error(tobj, GLU_TESS_ERROR1);
145
      /* delete all internal structures */
146
      delete_contours(tobj);
147
   }
148
   else {
149
      if ((tobj->current_polygon =
150
           (tess_polygon *) malloc(sizeof(tess_polygon))) == NULL) {
151
         tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
152
         return;
153
      }
154
      tobj->current_polygon->vertex_cnt = 0;
155
      tobj->current_polygon->vertices =
156
         tobj->current_polygon->last_vertex = NULL;
157
   }
158
}
159
 
160
 
161
void GLAPIENTRY
162
gluEndPolygon(GLUtriangulatorObj * tobj)
163
{
164
   /*tess_contour *contour_ptr; */
165
 
166
   /* there was an error */
167
   if (tobj->error != GLU_NO_ERROR)
168
      goto end;
169
 
170
   /* check if gluBeginPolygon was called */
171
   if (tobj->current_polygon == NULL) {
172
      tess_call_user_error(tobj, GLU_TESS_ERROR2);
173
      return;
174
   }
175
   tess_test_polygon(tobj);
176
   /* there was an error */
177
   if (tobj->error != GLU_NO_ERROR)
178
      goto end;
179
 
180
   /* any real contours? */
181
   if (tobj->contour_cnt == 0) {
182
      /* delete all internal structures */
183
      delete_contours(tobj);
184
      return;
185
   }
186
   tess_find_contour_hierarchies(tobj);
187
   /* there was an error */
188
   if (tobj->error != GLU_NO_ERROR)
189
      goto end;
190
 
191
   tess_handle_holes(tobj);
192
   /* there was an error */
193
   if (tobj->error != GLU_NO_ERROR)
194
      goto end;
195
 
196
   /* if no callbacks, nothing to do */
197
   if (tobj->callbacks.begin != NULL && tobj->callbacks.vertex != NULL &&
198
       tobj->callbacks.end != NULL) {
199
      if (tobj->callbacks.edgeFlag == NULL)
200
         tess_tesselate(tobj);
201
      else
202
         tess_tesselate_with_edge_flag(tobj);
203
   }
204
 
205
 end:
206
   /* delete all internal structures */
207
   delete_contours(tobj);
208
}
209
 
210
 
211
void GLAPIENTRY
212
gluNextContour(GLUtriangulatorObj * tobj, GLenum type)
213
{
214
   if (tobj->error != GLU_NO_ERROR)
215
      return;
216
   if (tobj->current_polygon == NULL) {
217
      tess_call_user_error(tobj, GLU_TESS_ERROR2);
218
      return;
219
   }
220
   /* first contour? */
221
   if (tobj->current_polygon->vertex_cnt)
222
      tess_test_polygon(tobj);
223
}
224
 
225
 
226
void GLAPIENTRY
227
gluTessVertex(GLUtriangulatorObj * tobj, GLdouble v[3], void *data)
228
{
229
   tess_polygon *polygon = tobj->current_polygon;
230
   tess_vertex *last_vertex_ptr;
231
 
232
   if (tobj->error != GLU_NO_ERROR)
233
      return;
234
   if (polygon == NULL) {
235
      tess_call_user_error(tobj, GLU_TESS_ERROR2);
236
      return;
237
   }
238
   last_vertex_ptr = polygon->last_vertex;
239
   if (last_vertex_ptr == NULL) {
240
      if ((last_vertex_ptr = (tess_vertex *)
241
           malloc(sizeof(tess_vertex))) == NULL) {
242
         tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
243
         return;
244
      }
245
      polygon->vertices = last_vertex_ptr;
246
      polygon->last_vertex = last_vertex_ptr;
247
      last_vertex_ptr->data = data;
248
      last_vertex_ptr->location[0] = v[0];
249
      last_vertex_ptr->location[1] = v[1];
250
      last_vertex_ptr->location[2] = v[2];
251
      last_vertex_ptr->next = NULL;
252
      last_vertex_ptr->previous = NULL;
253
      ++(polygon->vertex_cnt);
254
   }
255
   else {
256
      tess_vertex *vertex_ptr;
257
 
258
      /* same point twice? */
259
      if (fabs(last_vertex_ptr->location[0] - v[0]) < EPSILON &&
260
          fabs(last_vertex_ptr->location[1] - v[1]) < EPSILON &&
261
          fabs(last_vertex_ptr->location[2] - v[2]) < EPSILON) {
262
         tess_call_user_error(tobj, GLU_TESS_ERROR6);
263
         return;
264
      }
265
      if ((vertex_ptr = (tess_vertex *)
266
           malloc(sizeof(tess_vertex))) == NULL) {
267
         tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
268
         return;
269
      }
270
      vertex_ptr->data = data;
271
      vertex_ptr->location[0] = v[0];
272
      vertex_ptr->location[1] = v[1];
273
      vertex_ptr->location[2] = v[2];
274
      vertex_ptr->next = NULL;
275
      vertex_ptr->previous = last_vertex_ptr;
276
      ++(polygon->vertex_cnt);
277
      last_vertex_ptr->next = vertex_ptr;
278
      polygon->last_vertex = vertex_ptr;
279
   }
280
}
281
 
282
 
283
static void
284
delete_contours(GLUtriangulatorObj * tobj)
285
{
286
   tess_polygon *polygon = tobj->current_polygon;
287
   tess_contour *contour, *contour_tmp;
288
   tess_vertex *vertex, *vertex_tmp;
289
 
290
   /* remove current_polygon list - if exists due to detected error */
291
   if (polygon != NULL) {
292
      if (polygon->vertices) {
293
         for (vertex = polygon->vertices; vertex != polygon->last_vertex;) {
294
            vertex_tmp = vertex->next;
295
            free(vertex);
296
            vertex = vertex_tmp;
297
         }
298
         free(vertex);
299
      }
300
      free(polygon);
301
      tobj->current_polygon = NULL;
302
   }
303
   /* remove all contour data */
304
   for (contour = tobj->contours; contour != NULL;) {
305
      for (vertex = contour->vertices; vertex != contour->last_vertex;) {
306
         vertex_tmp = vertex->next;
307
         free(vertex);
308
         vertex = vertex_tmp;
309
      }
310
      free(vertex);
311
      contour_tmp = contour->next;
312
      free(contour);
313
      contour = contour_tmp;
314
   }
315
   tobj->contours = tobj->last_contour = NULL;
316
   tobj->contour_cnt = 0;
317
}
318
 
319
 
320
void GLAPIENTRY
321
gluTessNormal(GLUtesselator *tess, GLdouble valueX, GLdouble valueY, GLdouble valueZ)
322
{
323
   /* dummy function */
324
   (void) tess;
325
   (void) valueX;
326
   (void) valueY;
327
   (void) valueZ;
328
}