3 * Mesa 3-D graphics library
5 * Copyright (C) 1995-2000 Brian Paul
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 * This file is part of the polygon tesselation code contributed by
39 * This is ugly, but seems the easiest way to do things to make the
40 * code work under YellowBox for Windows
42 #if defined(OPENSTEP) && defined(CALLBACK)
48 static void delete_contours(GLUtriangulatorObj
*);
53 #define _CALLBACK GLCALLBACK
58 init_callbacks(tess_callbacks
* callbacks
)
60 callbacks
->begin
= (void (_CALLBACK
*) (GLenum
)) 0;
61 callbacks
->edgeFlag
= (void (_CALLBACK
*) (GLboolean
)) 0;
62 callbacks
->vertex
= (void (_CALLBACK
*) (void *)) 0;
63 callbacks
->end
= (void (_CALLBACK
*) (void)) 0;
64 callbacks
->error
= (void (_CALLBACK
*) (GLenum
)) 0;
68 tess_call_user_error(GLUtriangulatorObj
* tobj
, GLenum gluerr
)
70 if (tobj
->error
== GLU_NO_ERROR
)
72 if (tobj
->callbacks
.error
!= NULL
)
73 (tobj
->callbacks
.error
) (gluerr
);
76 GLUtriangulatorObj
*GLAPIENTRY
79 GLUtriangulatorObj
*tobj
;
81 if ((tobj
= (GLUtriangulatorObj
*)
82 malloc(sizeof(struct GLUtesselator
))) == NULL
)
84 tobj
->contours
= tobj
->last_contour
= NULL
;
85 init_callbacks(&tobj
->callbacks
);
86 tobj
->error
= GLU_NO_ERROR
;
87 tobj
->current_polygon
= NULL
;
88 tobj
->contour_cnt
= 0;
94 gluTessCallback(GLUtriangulatorObj
* tobj
, GLenum which
,
95 void (GLCALLBACK
* fn
) ())
99 tobj
->callbacks
.begin
= (void (_CALLBACK
*) (GLenum
)) fn
;
102 tobj
->callbacks
.edgeFlag
= (void (_CALLBACK
*) (GLboolean
)) fn
;
105 tobj
->callbacks
.vertex
= (void (_CALLBACK
*) (void *)) fn
;
108 tobj
->callbacks
.end
= (void (_CALLBACK
*) (void)) fn
;
111 tobj
->callbacks
.error
= (void (_CALLBACK
*) (GLenum
)) fn
;
114 tobj
->error
= GLU_INVALID_ENUM
;
122 gluDeleteTess(GLUtriangulatorObj
* tobj
)
124 if (tobj
->error
== GLU_NO_ERROR
&& tobj
->contour_cnt
)
125 /* was gluEndPolygon called? */
126 tess_call_user_error(tobj
, GLU_TESS_ERROR1
);
127 /* delete all internal structures */
128 delete_contours(tobj
);
134 gluBeginPolygon(GLUtriangulatorObj
* tobj
)
137 if(tobj->error!=GLU_NO_ERROR)
140 tobj
->error
= GLU_NO_ERROR
;
141 if (tobj
->current_polygon
!= NULL
) {
142 /* gluEndPolygon was not called */
143 tess_call_user_error(tobj
, GLU_TESS_ERROR1
);
144 /* delete all internal structures */
145 delete_contours(tobj
);
148 if ((tobj
->current_polygon
=
149 (tess_polygon
*) malloc(sizeof(tess_polygon
))) == NULL
) {
150 tess_call_user_error(tobj
, GLU_OUT_OF_MEMORY
);
153 tobj
->current_polygon
->vertex_cnt
= 0;
154 tobj
->current_polygon
->vertices
=
155 tobj
->current_polygon
->last_vertex
= NULL
;
161 gluEndPolygon(GLUtriangulatorObj
* tobj
)
163 /*tess_contour *contour_ptr; */
165 /* there was an error */
166 if (tobj
->error
!= GLU_NO_ERROR
)
169 /* check if gluBeginPolygon was called */
170 if (tobj
->current_polygon
== NULL
) {
171 tess_call_user_error(tobj
, GLU_TESS_ERROR2
);
174 tess_test_polygon(tobj
);
175 /* there was an error */
176 if (tobj
->error
!= GLU_NO_ERROR
)
179 /* any real contours? */
180 if (tobj
->contour_cnt
== 0) {
181 /* delete all internal structures */
182 delete_contours(tobj
);
185 tess_find_contour_hierarchies(tobj
);
186 /* there was an error */
187 if (tobj
->error
!= GLU_NO_ERROR
)
190 tess_handle_holes(tobj
);
191 /* there was an error */
192 if (tobj
->error
!= GLU_NO_ERROR
)
195 /* if no callbacks, nothing to do */
196 if (tobj
->callbacks
.begin
!= NULL
&& tobj
->callbacks
.vertex
!= NULL
&&
197 tobj
->callbacks
.end
!= NULL
) {
198 if (tobj
->callbacks
.edgeFlag
== NULL
)
199 tess_tesselate(tobj
);
201 tess_tesselate_with_edge_flag(tobj
);
205 /* delete all internal structures */
206 delete_contours(tobj
);
211 gluNextContour(GLUtriangulatorObj
* tobj
, GLenum type
)
213 if (tobj
->error
!= GLU_NO_ERROR
)
215 if (tobj
->current_polygon
== NULL
) {
216 tess_call_user_error(tobj
, GLU_TESS_ERROR2
);
220 if (tobj
->current_polygon
->vertex_cnt
)
221 tess_test_polygon(tobj
);
226 gluTessVertex(GLUtriangulatorObj
* tobj
, GLdouble v
[3], void *data
)
228 tess_polygon
*polygon
= tobj
->current_polygon
;
229 tess_vertex
*last_vertex_ptr
;
231 if (tobj
->error
!= GLU_NO_ERROR
)
233 if (polygon
== NULL
) {
234 tess_call_user_error(tobj
, GLU_TESS_ERROR2
);
237 last_vertex_ptr
= polygon
->last_vertex
;
238 if (last_vertex_ptr
== NULL
) {
239 if ((last_vertex_ptr
= (tess_vertex
*)
240 malloc(sizeof(tess_vertex
))) == NULL
) {
241 tess_call_user_error(tobj
, GLU_OUT_OF_MEMORY
);
244 polygon
->vertices
= last_vertex_ptr
;
245 polygon
->last_vertex
= last_vertex_ptr
;
246 last_vertex_ptr
->data
= data
;
247 last_vertex_ptr
->location
[0] = v
[0];
248 last_vertex_ptr
->location
[1] = v
[1];
249 last_vertex_ptr
->location
[2] = v
[2];
250 last_vertex_ptr
->next
= NULL
;
251 last_vertex_ptr
->previous
= NULL
;
252 ++(polygon
->vertex_cnt
);
255 tess_vertex
*vertex_ptr
;
257 /* same point twice? */
258 if (fabs(last_vertex_ptr
->location
[0] - v
[0]) < EPSILON
&&
259 fabs(last_vertex_ptr
->location
[1] - v
[1]) < EPSILON
&&
260 fabs(last_vertex_ptr
->location
[2] - v
[2]) < EPSILON
) {
261 tess_call_user_error(tobj
, GLU_TESS_ERROR6
);
264 if ((vertex_ptr
= (tess_vertex
*)
265 malloc(sizeof(tess_vertex
))) == NULL
) {
266 tess_call_user_error(tobj
, GLU_OUT_OF_MEMORY
);
269 vertex_ptr
->data
= data
;
270 vertex_ptr
->location
[0] = v
[0];
271 vertex_ptr
->location
[1] = v
[1];
272 vertex_ptr
->location
[2] = v
[2];
273 vertex_ptr
->next
= NULL
;
274 vertex_ptr
->previous
= last_vertex_ptr
;
275 ++(polygon
->vertex_cnt
);
276 last_vertex_ptr
->next
= vertex_ptr
;
277 polygon
->last_vertex
= vertex_ptr
;
283 delete_contours(GLUtriangulatorObj
* tobj
)
285 tess_polygon
*polygon
= tobj
->current_polygon
;
286 tess_contour
*contour
, *contour_tmp
;
287 tess_vertex
*vertex
, *vertex_tmp
;
289 /* remove current_polygon list - if exists due to detected error */
290 if (polygon
!= NULL
) {
291 if (polygon
->vertices
) {
292 for (vertex
= polygon
->vertices
; vertex
!= polygon
->last_vertex
;) {
293 vertex_tmp
= vertex
->next
;
300 tobj
->current_polygon
= NULL
;
302 /* remove all contour data */
303 for (contour
= tobj
->contours
; contour
!= NULL
;) {
304 for (vertex
= contour
->vertices
; vertex
!= contour
->last_vertex
;) {
305 vertex_tmp
= vertex
->next
;
310 contour_tmp
= contour
->next
;
312 contour
= contour_tmp
;
314 tobj
->contours
= tobj
->last_contour
= NULL
;
315 tobj
->contour_cnt
= 0;
320 gluTessNormal(GLUtesselator
*tess
, GLdouble valueX
, GLdouble valueY
, GLdouble valueZ
)