a1102e6e5a6bdfb0b0a18564c56f0d58989c8a98
1 /* $Id: tesselat.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 static GLboolean edge_flag
;
42 static void emit_triangle(GLUtriangulatorObj
*, tess_vertex
*,
43 tess_vertex
*, tess_vertex
*);
45 static void emit_triangle_with_edge_flag(GLUtriangulatorObj
*,
46 tess_vertex
*, GLboolean
,
47 tess_vertex
*, GLboolean
,
48 tess_vertex
*, GLboolean
);
51 twice_the_triangle_area(tess_vertex
* va
, tess_vertex
* vb
, tess_vertex
* vc
)
53 return (vb
->x
- va
->x
) * (vc
->y
- va
->y
) - (vb
->y
- va
->y
) * (vc
->x
-
58 left(GLdouble A
, GLdouble B
, GLdouble C
, GLdouble x
, GLdouble y
)
60 if (A
* x
+ B
* y
+ C
> -EPSILON
)
67 right(GLdouble A
, GLdouble B
, GLdouble C
, GLdouble x
, GLdouble y
)
69 if (A
* x
+ B
* y
+ C
< EPSILON
)
76 convex_ccw(tess_vertex
* va
,
77 tess_vertex
* vb
, tess_vertex
* vc
, GLUtriangulatorObj
* tobj
)
81 d
= twice_the_triangle_area(va
, vb
, vc
);
86 else if (d
< -EPSILON
) {
95 convex_cw(tess_vertex
* va
,
96 tess_vertex
* vb
, tess_vertex
* vc
, GLUtriangulatorObj
* tobj
)
100 d
= twice_the_triangle_area(va
, vb
, vc
);
105 else if (d
> EPSILON
) {
114 diagonal_ccw(tess_vertex
* va
,
116 GLUtriangulatorObj
* tobj
, tess_contour
* contour
)
118 tess_vertex
*vc
= va
->next
, *vertex
, *shadow_vertex
;
126 GLint res
= convex_ccw(va
, vc
, vb
, tobj
);
132 ba
.A
= vb
->y
- va
->y
;
133 ba
.B
= va
->x
- vb
->x
;
134 ba
.C
= -ba
.A
* va
->x
- ba
.B
* va
->y
;
135 ac
.A
= va
->y
- vc
->y
;
136 ac
.B
= vc
->x
- va
->x
;
137 ac
.C
= -ac
.A
* vc
->x
- ac
.B
* vc
->y
;
138 cb
.A
= vc
->y
- vb
->y
;
139 cb
.B
= vb
->x
- vc
->x
;
140 cb
.C
= -cb
.A
* vb
->x
- cb
.B
* vb
->y
;
141 for (vertex
= vb
->next
; vertex
!= va
; vertex
= vertex
->next
) {
142 shadow_vertex
= vertex
->shadow_vertex
;
143 if (shadow_vertex
!= NULL
&&
144 (shadow_vertex
== va
|| shadow_vertex
== vb
|| shadow_vertex
== vc
))
148 if (left(ba
.A
, ba
.B
, ba
.C
, x
, y
) &&
149 left(ac
.A
, ac
.B
, ac
.C
, x
, y
) && left(cb
.A
, cb
.B
, cb
.C
, x
, y
))
156 diagonal_cw(tess_vertex
* va
,
158 GLUtriangulatorObj
* tobj
, tess_contour
* contour
)
160 tess_vertex
*vc
= va
->next
, *vertex
, *shadow_vertex
;
168 GLint res
= convex_cw(va
, vc
, vb
, tobj
);
174 ba
.A
= vb
->y
- va
->y
;
175 ba
.B
= va
->x
- vb
->x
;
176 ba
.C
= -ba
.A
* va
->x
- ba
.B
* va
->y
;
177 ac
.A
= va
->y
- vc
->y
;
178 ac
.B
= vc
->x
- va
->x
;
179 ac
.C
= -ac
.A
* vc
->x
- ac
.B
* vc
->y
;
180 cb
.A
= vc
->y
- vb
->y
;
181 cb
.B
= vb
->x
- vc
->x
;
182 cb
.C
= -cb
.A
* vb
->x
- cb
.B
* vb
->y
;
183 for (vertex
= vb
->next
; vertex
!= va
; vertex
= vertex
->next
) {
184 shadow_vertex
= vertex
->shadow_vertex
;
185 if (shadow_vertex
!= NULL
&&
186 (shadow_vertex
== va
|| shadow_vertex
== vb
|| shadow_vertex
== vc
))
190 if (right(ba
.A
, ba
.B
, ba
.C
, x
, y
) &&
191 right(ac
.A
, ac
.B
, ac
.C
, x
, y
) && right(cb
.A
, cb
.B
, cb
.C
, x
, y
))
198 clip_ear(GLUtriangulatorObj
* tobj
, tess_vertex
* v
, tess_contour
* contour
)
200 emit_triangle(tobj
, v
->previous
, v
, v
->next
);
201 /* the first in the list */
202 if (contour
->vertices
== v
) {
203 contour
->vertices
= v
->next
;
204 contour
->last_vertex
->next
= v
->next
;
205 v
->next
->previous
= contour
->last_vertex
;
209 if (contour
->last_vertex
== v
) {
210 contour
->vertices
->previous
= v
->previous
;
211 v
->previous
->next
= v
->next
;
212 contour
->last_vertex
= v
->previous
;
215 v
->next
->previous
= v
->previous
;
216 v
->previous
->next
= v
->next
;
219 --(contour
->vertex_cnt
);
223 clip_ear_with_edge_flag(GLUtriangulatorObj
* tobj
,
224 tess_vertex
* v
, tess_contour
* contour
)
226 emit_triangle_with_edge_flag(tobj
, v
->previous
, v
->previous
->edge_flag
,
227 v
, v
->edge_flag
, v
->next
, GL_FALSE
);
228 v
->previous
->edge_flag
= GL_FALSE
;
229 /* the first in the list */
230 if (contour
->vertices
== v
) {
231 contour
->vertices
= v
->next
;
232 contour
->last_vertex
->next
= v
->next
;
233 v
->next
->previous
= contour
->last_vertex
;
237 if (contour
->last_vertex
== v
) {
238 contour
->vertices
->previous
= v
->previous
;
239 v
->previous
->next
= v
->next
;
240 contour
->last_vertex
= v
->previous
;
243 v
->next
->previous
= v
->previous
;
244 v
->previous
->next
= v
->next
;
247 --(contour
->vertex_cnt
);
251 triangulate_ccw(GLUtriangulatorObj
* tobj
, tess_contour
* contour
)
254 GLuint vertex_cnt
= contour
->vertex_cnt
;
256 while (vertex_cnt
> 3) {
257 vertex
= contour
->vertices
;
258 while (diagonal_ccw(vertex
, vertex
->next
->next
, tobj
, contour
) ==
259 GL_FALSE
&& tobj
->error
== GLU_NO_ERROR
)
260 vertex
= vertex
->next
;
261 if (tobj
->error
!= GLU_NO_ERROR
)
263 clip_ear(tobj
, vertex
->next
, contour
);
269 triangulate_cw(GLUtriangulatorObj
* tobj
, tess_contour
* contour
)
272 GLuint vertex_cnt
= contour
->vertex_cnt
;
274 while (vertex_cnt
> 3) {
275 vertex
= contour
->vertices
;
276 while (diagonal_cw(vertex
, vertex
->next
->next
, tobj
, contour
) ==
277 GL_FALSE
&& tobj
->error
== GLU_NO_ERROR
)
278 vertex
= vertex
->next
;
279 if (tobj
->error
!= GLU_NO_ERROR
)
281 clip_ear(tobj
, vertex
->next
, contour
);
287 triangulate_ccw_with_edge_flag(GLUtriangulatorObj
* tobj
,
288 tess_contour
* contour
)
291 GLuint vertex_cnt
= contour
->vertex_cnt
;
293 while (vertex_cnt
> 3) {
294 vertex
= contour
->vertices
;
295 while (diagonal_ccw(vertex
, vertex
->next
->next
, tobj
, contour
) ==
296 GL_FALSE
&& tobj
->error
== GLU_NO_ERROR
)
297 vertex
= vertex
->next
;
298 if (tobj
->error
!= GLU_NO_ERROR
)
300 clip_ear_with_edge_flag(tobj
, vertex
->next
, contour
);
306 triangulate_cw_with_edge_flag(GLUtriangulatorObj
* tobj
,
307 tess_contour
* contour
)
310 GLuint vertex_cnt
= contour
->vertex_cnt
;
312 while (vertex_cnt
> 3) {
313 vertex
= contour
->vertices
;
314 while (diagonal_cw(vertex
, vertex
->next
->next
, tobj
, contour
) ==
315 GL_FALSE
&& tobj
->error
== GLU_NO_ERROR
)
316 vertex
= vertex
->next
;
317 if (tobj
->error
!= GLU_NO_ERROR
)
319 clip_ear_with_edge_flag(tobj
, vertex
->next
, contour
);
325 tess_tesselate(GLUtriangulatorObj
* tobj
)
327 tess_contour
*contour
;
329 for (contour
= tobj
->contours
; contour
!= NULL
; contour
= contour
->next
) {
330 if (contour
->orientation
== GLU_CCW
) {
331 triangulate_ccw(tobj
, contour
);
334 triangulate_cw(tobj
, contour
);
336 if (tobj
->error
!= GLU_NO_ERROR
)
339 /* emit the last triangle */
340 emit_triangle(tobj
, contour
->vertices
, contour
->vertices
->next
,
341 contour
->vertices
->next
->next
);
346 tess_tesselate_with_edge_flag(GLUtriangulatorObj
* tobj
)
348 tess_contour
*contour
;
351 /* first callback with edgeFlag set to GL_TRUE */
352 (tobj
->callbacks
.edgeFlag
) (GL_TRUE
);
354 for (contour
= tobj
->contours
; contour
!= NULL
; contour
= contour
->next
) {
355 if (contour
->orientation
== GLU_CCW
)
356 triangulate_ccw_with_edge_flag(tobj
, contour
);
358 triangulate_cw_with_edge_flag(tobj
, contour
);
359 if (tobj
->error
!= GLU_NO_ERROR
)
361 /* emit the last triangle */
362 emit_triangle_with_edge_flag(tobj
, contour
->vertices
,
363 contour
->vertices
->edge_flag
,
364 contour
->vertices
->next
,
365 contour
->vertices
->next
->edge_flag
,
366 contour
->vertices
->next
->next
,
367 contour
->vertices
->next
->next
->edge_flag
);
372 emit_triangle(GLUtriangulatorObj
* tobj
,
373 tess_vertex
* v1
, tess_vertex
* v2
, tess_vertex
* v3
)
375 (tobj
->callbacks
.begin
) (GL_TRIANGLES
);
376 (tobj
->callbacks
.vertex
) (v1
->data
);
377 (tobj
->callbacks
.vertex
) (v2
->data
);
378 (tobj
->callbacks
.vertex
) (v3
->data
);
379 (tobj
->callbacks
.end
) ();
383 emit_triangle_with_edge_flag(GLUtriangulatorObj
* tobj
,
385 GLboolean edge_flag1
,
387 GLboolean edge_flag2
,
388 tess_vertex
* v3
, GLboolean edge_flag3
)
390 (tobj
->callbacks
.begin
) (GL_TRIANGLES
);
391 if (edge_flag1
!= edge_flag
) {
392 edge_flag
= (edge_flag
== GL_TRUE
? GL_FALSE
: GL_TRUE
);
393 (tobj
->callbacks
.edgeFlag
) (edge_flag
);
395 (tobj
->callbacks
.vertex
) (v1
->data
);
396 if (edge_flag2
!= edge_flag
) {
397 edge_flag
= (edge_flag
== GL_TRUE
? GL_FALSE
: GL_TRUE
);
398 (tobj
->callbacks
.edgeFlag
) (edge_flag
);
400 (tobj
->callbacks
.vertex
) (v2
->data
);
401 if (edge_flag3
!= edge_flag
) {
402 edge_flag
= (edge_flag
== GL_TRUE
? GL_FALSE
: GL_TRUE
);
403 (tobj
->callbacks
.edgeFlag
) (edge_flag
);
405 (tobj
->callbacks
.vertex
) (v3
->data
);
406 (tobj
->callbacks
.end
) ();