1 /* $Id: tess.c,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
4 * Mesa 3-D graphics library
6 * Copyright (C) 1995-2000 Brian Paul
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.
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.
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.
25 * This file is part of the polygon tesselation code contributed by
40 * This is ugly, but seems the easiest way to do things to make the
41 * code work under YellowBox for Windows
43 #if defined(OPENSTEP) && defined(CALLBACK)
49 static void delete_contours(GLUtriangulatorObj
*);
54 #define _CALLBACK GLCALLBACK
59 init_callbacks(tess_callbacks
* callbacks
)
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;
69 tess_call_user_error(GLUtriangulatorObj
* tobj
, GLenum gluerr
)
71 if (tobj
->error
== GLU_NO_ERROR
)
73 if (tobj
->callbacks
.error
!= NULL
)
74 (tobj
->callbacks
.error
) (gluerr
);
77 GLUtriangulatorObj
*GLAPIENTRY
80 GLUtriangulatorObj
*tobj
;
82 if ((tobj
= (GLUtriangulatorObj
*)
83 malloc(sizeof(struct GLUtesselator
))) == 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;
95 gluTessCallback(GLUtriangulatorObj
* tobj
, GLenum which
,
96 void (GLCALLBACK
* fn
) ())
100 tobj
->callbacks
.begin
= (void (_CALLBACK
*) (GLenum
)) fn
;
103 tobj
->callbacks
.edgeFlag
= (void (_CALLBACK
*) (GLboolean
)) fn
;
106 tobj
->callbacks
.vertex
= (void (_CALLBACK
*) (void *)) fn
;
109 tobj
->callbacks
.end
= (void (_CALLBACK
*) (void)) fn
;
112 tobj
->callbacks
.error
= (void (_CALLBACK
*) (GLenum
)) fn
;
115 tobj
->error
= GLU_INVALID_ENUM
;
123 gluDeleteTess(GLUtriangulatorObj
* tobj
)
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
);
135 gluBeginPolygon(GLUtriangulatorObj
* tobj
)
138 if(tobj->error!=GLU_NO_ERROR)
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
);
149 if ((tobj
->current_polygon
=
150 (tess_polygon
*) malloc(sizeof(tess_polygon
))) == NULL
) {
151 tess_call_user_error(tobj
, GLU_OUT_OF_MEMORY
);
154 tobj
->current_polygon
->vertex_cnt
= 0;
155 tobj
->current_polygon
->vertices
=
156 tobj
->current_polygon
->last_vertex
= NULL
;
162 gluEndPolygon(GLUtriangulatorObj
* tobj
)
164 /*tess_contour *contour_ptr; */
166 /* there was an error */
167 if (tobj
->error
!= GLU_NO_ERROR
)
170 /* check if gluBeginPolygon was called */
171 if (tobj
->current_polygon
== NULL
) {
172 tess_call_user_error(tobj
, GLU_TESS_ERROR2
);
175 tess_test_polygon(tobj
);
176 /* there was an error */
177 if (tobj
->error
!= GLU_NO_ERROR
)
180 /* any real contours? */
181 if (tobj
->contour_cnt
== 0) {
182 /* delete all internal structures */
183 delete_contours(tobj
);
186 tess_find_contour_hierarchies(tobj
);
187 /* there was an error */
188 if (tobj
->error
!= GLU_NO_ERROR
)
191 tess_handle_holes(tobj
);
192 /* there was an error */
193 if (tobj
->error
!= GLU_NO_ERROR
)
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
);
202 tess_tesselate_with_edge_flag(tobj
);
206 /* delete all internal structures */
207 delete_contours(tobj
);
212 gluNextContour(GLUtriangulatorObj
* tobj
, GLenum type
)
214 if (tobj
->error
!= GLU_NO_ERROR
)
216 if (tobj
->current_polygon
== NULL
) {
217 tess_call_user_error(tobj
, GLU_TESS_ERROR2
);
221 if (tobj
->current_polygon
->vertex_cnt
)
222 tess_test_polygon(tobj
);
227 gluTessVertex(GLUtriangulatorObj
* tobj
, GLdouble v
[3], void *data
)
229 tess_polygon
*polygon
= tobj
->current_polygon
;
230 tess_vertex
*last_vertex_ptr
;
232 if (tobj
->error
!= GLU_NO_ERROR
)
234 if (polygon
== NULL
) {
235 tess_call_user_error(tobj
, GLU_TESS_ERROR2
);
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
);
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
);
256 tess_vertex
*vertex_ptr
;
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
);
265 if ((vertex_ptr
= (tess_vertex
*)
266 malloc(sizeof(tess_vertex
))) == NULL
) {
267 tess_call_user_error(tobj
, GLU_OUT_OF_MEMORY
);
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
;
284 delete_contours(GLUtriangulatorObj
* tobj
)
286 tess_polygon
*polygon
= tobj
->current_polygon
;
287 tess_contour
*contour
, *contour_tmp
;
288 tess_vertex
*vertex
, *vertex_tmp
;
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
;
301 tobj
->current_polygon
= NULL
;
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
;
311 contour_tmp
= contour
->next
;
313 contour
= contour_tmp
;
315 tobj
->contours
= tobj
->last_contour
= NULL
;
316 tobj
->contour_cnt
= 0;
321 gluTessNormal(GLUtesselator
*tess
, GLdouble valueX
, GLdouble valueY
, GLdouble valueZ
)