1 /*
2  * Copyright (c) 2002-2008 LWJGL Project
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of 'LWJGL' nor the names of
17  *   its contributors may be used to endorse or promote products derived
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34 * Portions Copyright (C) 2003-2006 Sun Microsystems, Inc.
35 * All rights reserved.
36 */
37 
38 /*
39 ** License Applicability. Except to the extent portions of this file are
40 ** made subject to an alternative license as permitted in the SGI Free
41 ** Software License B, Version 1.1 (the "License"), the contents of this
42 ** file are subject only to the provisions of the License. You may not use
43 ** this file except in compliance with the License. You may obtain a copy
44 ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
45 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
46 **
47 ** http://oss.sgi.com/projects/FreeB
48 **
49 ** Note that, as provided in the License, the Software is distributed on an
50 ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
51 ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
52 ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
53 ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
54 **
55 ** NOTE:  The Original Code (as defined below) has been licensed to Sun
56 ** Microsystems, Inc. ("Sun") under the SGI Free Software License B
57 ** (Version 1.1), shown above ("SGI License").   Pursuant to Section
58 ** 3.2(3) of the SGI License, Sun is distributing the Covered Code to
59 ** you under an alternative license ("Alternative License").  This
60 ** Alternative License includes all of the provisions of the SGI License
61 ** except that Section 2.2 and 11 are omitted.  Any differences between
62 ** the Alternative License and the SGI License are offered solely by Sun
63 ** and not by SGI.
64 **
65 ** Original Code. The Original Code is: OpenGL Sample Implementation,
66 ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
67 ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
68 ** Copyright in any portions created by third parties is as indicated
69 ** elsewhere herein. All Rights Reserved.
70 **
71 ** Additional Notice Provisions: The application programming interfaces
72 ** established by SGI in conjunction with the Original Code are The
73 ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
74 ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
75 ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
76 ** Window System(R) (Version 1.3), released October 19, 1998. This software
77 ** was created using the OpenGL(R) version 1.2.1 Sample Implementation
78 ** published by SGI, but has not been independently verified as being
79 ** compliant with the OpenGL(R) version 1.2.1 Specification.
80 **
81 ** Author: Eric Veach, July 1994
82 ** Java Port: Pepijn Van Eeckhoudt, July 2003
83 ** Java Port: Nathan Parker Burg, August 2003
84 */
85 package org.lwjgl.util.glu.tessellation;
86 
87 import static org.lwjgl.opengl.GL11.*;
88 import static org.lwjgl.util.glu.GLU.*;
89 
90 class Render {
91     private static final boolean USE_OPTIMIZED_CODE_PATH = false;
92 
Render()93     private Render() {
94     }
95 
96     private static final RenderFan renderFan = new RenderFan();
97     private static final RenderStrip renderStrip = new RenderStrip();
98     private static final RenderTriangle renderTriangle = new RenderTriangle();
99 
100 /* This structure remembers the information we need about a primitive
101  * to be able to render it later, once we have determined which
102  * primitive is able to use the most triangles.
103  */
104     private static class FaceCount {
FaceCount()105         private FaceCount() {
106         }
107 
FaceCount(long size, GLUhalfEdge eStart, renderCallBack render)108         private FaceCount(long size, GLUhalfEdge eStart, renderCallBack render) {
109             this.size = size;
110             this.eStart = eStart;
111             this.render = render;
112         }
113 
114         long size;		/* number of triangles used */
115         GLUhalfEdge eStart;	/* edge where this primitive starts */
116         renderCallBack render;
117     };
118 
119     private interface renderCallBack {
render(GLUtessellatorImpl tess, GLUhalfEdge e, long size)120         void render(GLUtessellatorImpl tess, GLUhalfEdge e, long size);
121     }
122 
123     /************************ Strips and Fans decomposition ******************/
124 
125 /* __gl_renderMesh( tess, mesh ) takes a mesh and breaks it into triangle
126  * fans, strips, and separate triangles.  A substantial effort is made
127  * to use as few rendering primitives as possible (ie. to make the fans
128  * and strips as large as possible).
129  *
130  * The rendering output is provided as callbacks (see the api).
131  */
__gl_renderMesh(GLUtessellatorImpl tess, GLUmesh mesh)132     public static void __gl_renderMesh(GLUtessellatorImpl tess, GLUmesh mesh) {
133         GLUface f;
134 
135         /* Make a list of separate triangles so we can render them all at once */
136         tess.lonelyTriList = null;
137 
138         for (f = mesh.fHead.next; f != mesh.fHead; f = f.next) {
139             f.marked = false;
140         }
141         for (f = mesh.fHead.next; f != mesh.fHead; f = f.next) {
142 
143             /* We examine all faces in an arbitrary order.  Whenever we find
144              * an unprocessed face F, we output a group of faces including F
145              * whose size is maximum.
146              */
147             if (f.inside && !f.marked) {
148                 RenderMaximumFaceGroup(tess, f);
149                 assert (f.marked);
150             }
151         }
152         if (tess.lonelyTriList != null) {
153             RenderLonelyTriangles(tess, tess.lonelyTriList);
154             tess.lonelyTriList = null;
155         }
156     }
157 
158 
RenderMaximumFaceGroup(GLUtessellatorImpl tess, GLUface fOrig)159     static void RenderMaximumFaceGroup(GLUtessellatorImpl tess, GLUface fOrig) {
160         /* We want to find the largest triangle fan or strip of unmarked faces
161          * which includes the given face fOrig.  There are 3 possible fans
162          * passing through fOrig (one centered at each vertex), and 3 possible
163          * strips (one for each CCW permutation of the vertices).  Our strategy
164          * is to try all of these, and take the primitive which uses the most
165          * triangles (a greedy approach).
166          */
167         GLUhalfEdge e = fOrig.anEdge;
168         FaceCount max = new FaceCount();
169         FaceCount newFace;
170 
171         max.size = 1;
172         max.eStart = e;
173         max.render = renderTriangle;
174 
175         if (!tess.flagBoundary) {
176             newFace = MaximumFan(e);
177             if (newFace.size > max.size) {
178                 max = newFace;
179             }
180             newFace = MaximumFan(e.Lnext);
181             if (newFace.size > max.size) {
182                 max = newFace;
183             }
184             newFace = MaximumFan(e.Onext.Sym);
185             if (newFace.size > max.size) {
186                 max = newFace;
187             }
188 
189             newFace = MaximumStrip(e);
190             if (newFace.size > max.size) {
191                 max = newFace;
192             }
193             newFace = MaximumStrip(e.Lnext);
194             if (newFace.size > max.size) {
195                 max = newFace;
196             }
197             newFace = MaximumStrip(e.Onext.Sym);
198             if (newFace.size > max.size) {
199                 max = newFace;
200             }
201         }
202         max.render.render(tess, max.eStart, max.size);
203     }
204 
205 
206 /* Macros which keep track of faces we have marked temporarily, and allow
207  * us to backtrack when necessary.  With triangle fans, this is not
208  * really necessary, since the only awkward case is a loop of triangles
209  * around a single origin vertex.  However with strips the situation is
210  * more complicated, and we need a general tracking method like the
211  * one here.
212  */
Marked(GLUface f)213     private static boolean Marked(GLUface f) {
214         return !f.inside || f.marked;
215     }
216 
AddToTrail(GLUface f, GLUface t)217     private static GLUface AddToTrail(GLUface f, GLUface t) {
218         f.trail = t;
219         f.marked = true;
220         return f;
221     }
222 
FreeTrail(GLUface t)223     private static void FreeTrail(GLUface t) {
224         if (true) {
225             while (t != null) {
226                 t.marked = false;
227                 t = t.trail;
228             }
229         } else {
230             /* absorb trailing semicolon */
231         }
232     }
233 
MaximumFan(GLUhalfEdge eOrig)234     static FaceCount MaximumFan(GLUhalfEdge eOrig) {
235         /* eOrig.Lface is the face we want to render.  We want to find the size
236          * of a maximal fan around eOrig.Org.  To do this we just walk around
237          * the origin vertex as far as possible in both directions.
238          */
239         FaceCount newFace = new FaceCount(0, null, renderFan);
240         GLUface trail = null;
241         GLUhalfEdge e;
242 
243         for (e = eOrig; !Marked(e.Lface); e = e.Onext) {
244             trail = AddToTrail(e.Lface, trail);
245             ++newFace.size;
246         }
247         for (e = eOrig; !Marked(e.Sym.Lface); e = e.Sym.Lnext) {
248             trail = AddToTrail(e.Sym.Lface, trail);
249             ++newFace.size;
250         }
251         newFace.eStart = e;
252         /*LINTED*/
253         FreeTrail(trail);
254         return newFace;
255     }
256 
257 
IsEven(long n)258     private static boolean IsEven(long n) {
259         return (n & 0x1L) == 0;
260     }
261 
MaximumStrip(GLUhalfEdge eOrig)262     static FaceCount MaximumStrip(GLUhalfEdge eOrig) {
263         /* Here we are looking for a maximal strip that contains the vertices
264          * eOrig.Org, eOrig.Dst, eOrig.Lnext.Dst (in that order or the
265          * reverse, such that all triangles are oriented CCW).
266          *
267          * Again we walk forward and backward as far as possible.  However for
268          * strips there is a twist: to get CCW orientations, there must be
269          * an *even* number of triangles in the strip on one side of eOrig.
270          * We walk the strip starting on a side with an even number of triangles;
271          * if both side have an odd number, we are forced to shorten one side.
272          */
273         FaceCount newFace = new FaceCount(0, null, renderStrip);
274         long headSize = 0, tailSize = 0;
275         GLUface trail = null;
276         GLUhalfEdge e, eTail, eHead;
277 
278         for (e = eOrig; !Marked(e.Lface); ++tailSize, e = e.Onext) {
279             trail = AddToTrail(e.Lface, trail);
280             ++tailSize;
281             e = e.Lnext.Sym;
282             if (Marked(e.Lface)) break;
283             trail = AddToTrail(e.Lface, trail);
284         }
285         eTail = e;
286 
287         for (e = eOrig; !Marked(e.Sym.Lface); ++headSize, e = e.Sym.Onext.Sym) {
288             trail = AddToTrail(e.Sym.Lface, trail);
289             ++headSize;
290             e = e.Sym.Lnext;
291             if (Marked(e.Sym.Lface)) break;
292             trail = AddToTrail(e.Sym.Lface, trail);
293         }
294         eHead = e;
295 
296         newFace.size = tailSize + headSize;
297         if (IsEven(tailSize)) {
298             newFace.eStart = eTail.Sym;
299         } else if (IsEven(headSize)) {
300             newFace.eStart = eHead;
301         } else {
302             /* Both sides have odd length, we must shorten one of them.  In fact,
303              * we must start from eHead to guarantee inclusion of eOrig.Lface.
304              */
305             --newFace.size;
306             newFace.eStart = eHead.Onext;
307         }
308         /*LINTED*/
309         FreeTrail(trail);
310         return newFace;
311     }
312 
313     private static class RenderTriangle implements renderCallBack {
render(GLUtessellatorImpl tess, GLUhalfEdge e, long size)314         public void render(GLUtessellatorImpl tess, GLUhalfEdge e, long size) {
315             /* Just add the triangle to a triangle list, so we can render all
316              * the separate triangles at once.
317              */
318             assert (size == 1);
319             tess.lonelyTriList = AddToTrail(e.Lface, tess.lonelyTriList);
320         }
321     }
322 
323 
RenderLonelyTriangles(GLUtessellatorImpl tess, GLUface f)324     static void RenderLonelyTriangles(GLUtessellatorImpl tess, GLUface f) {
325         /* Now we render all the separate triangles which could not be
326          * grouped into a triangle fan or strip.
327          */
328         GLUhalfEdge e;
329         int newState;
330         int edgeState = -1;	/* force edge state output for first vertex */
331 
332         tess.callBeginOrBeginData(GL_TRIANGLES);
333 
334         for (; f != null; f = f.trail) {
335             /* Loop once for each edge (there will always be 3 edges) */
336 
337             e = f.anEdge;
338             do {
339                 if (tess.flagBoundary) {
340                     /* Set the "edge state" to true just before we output the
341                      * first vertex of each edge on the polygon boundary.
342                      */
343                     newState = (!e.Sym.Lface.inside) ? 1 : 0;
344                     if (edgeState != newState) {
345                         edgeState = newState;
346                         tess.callEdgeFlagOrEdgeFlagData( edgeState != 0);
347                     }
348                 }
349                 tess.callVertexOrVertexData( e.Org.data);
350 
351                 e = e.Lnext;
352             } while (e != f.anEdge);
353         }
354         tess.callEndOrEndData();
355     }
356 
357     private static class RenderFan implements renderCallBack {
render(GLUtessellatorImpl tess, GLUhalfEdge e, long size)358         public void render(GLUtessellatorImpl tess, GLUhalfEdge e, long size) {
359             /* Render as many CCW triangles as possible in a fan starting from
360              * edge "e".  The fan *should* contain exactly "size" triangles
361              * (otherwise we've goofed up somewhere).
362              */
363             tess.callBeginOrBeginData(GL_TRIANGLE_FAN);
364             tess.callVertexOrVertexData( e.Org.data);
365             tess.callVertexOrVertexData( e.Sym.Org.data);
366 
367             while (!Marked(e.Lface)) {
368                 e.Lface.marked = true;
369                 --size;
370                 e = e.Onext;
371                 tess.callVertexOrVertexData( e.Sym.Org.data);
372             }
373 
374             assert (size == 0);
375             tess.callEndOrEndData();
376         }
377     }
378 
379     private static class RenderStrip implements renderCallBack {
render(GLUtessellatorImpl tess, GLUhalfEdge e, long size)380         public void render(GLUtessellatorImpl tess, GLUhalfEdge e, long size) {
381             /* Render as many CCW triangles as possible in a strip starting from
382              * edge "e".  The strip *should* contain exactly "size" triangles
383              * (otherwise we've goofed up somewhere).
384              */
385             tess.callBeginOrBeginData(GL_TRIANGLE_STRIP);
386             tess.callVertexOrVertexData( e.Org.data);
387             tess.callVertexOrVertexData( e.Sym.Org.data);
388 
389             while (!Marked(e.Lface)) {
390                 e.Lface.marked = true;
391                 --size;
392                 e = e.Lnext.Sym;
393                 tess.callVertexOrVertexData( e.Org.data);
394                 if (Marked(e.Lface)) break;
395 
396                 e.Lface.marked = true;
397                 --size;
398                 e = e.Onext;
399                 tess.callVertexOrVertexData( e.Sym.Org.data);
400             }
401 
402             assert (size == 0);
403             tess.callEndOrEndData();
404         }
405     }
406 
407     /************************ Boundary contour decomposition ******************/
408 
409 /* __gl_renderBoundary( tess, mesh ) takes a mesh, and outputs one
410  * contour for each face marked "inside".  The rendering output is
411  * provided as callbacks (see the api).
412  */
__gl_renderBoundary(GLUtessellatorImpl tess, GLUmesh mesh)413     public static void __gl_renderBoundary(GLUtessellatorImpl tess, GLUmesh mesh) {
414         GLUface f;
415         GLUhalfEdge e;
416 
417         for (f = mesh.fHead.next; f != mesh.fHead; f = f.next) {
418             if (f.inside) {
419                 tess.callBeginOrBeginData(GL_LINE_LOOP);
420                 e = f.anEdge;
421                 do {
422                     tess.callVertexOrVertexData( e.Org.data);
423                     e = e.Lnext;
424                 } while (e != f.anEdge);
425                 tess.callEndOrEndData();
426             }
427         }
428     }
429 
430 
431     /************************ Quick-and-dirty decomposition ******************/
432 
433     private static final int SIGN_INCONSISTENT = 2;
434 
ComputeNormal(GLUtessellatorImpl tess, double[] norm, boolean check)435     static int ComputeNormal(GLUtessellatorImpl tess, double[] norm, boolean check)
436 /*
437  * If check==false, we compute the polygon normal and place it in norm[].
438  * If check==true, we check that each triangle in the fan from v0 has a
439  * consistent orientation with respect to norm[].  If triangles are
440  * consistently oriented CCW, return 1; if CW, return -1; if all triangles
441  * are degenerate return 0; otherwise (no consistent orientation) return
442  * SIGN_INCONSISTENT.
443  */ {
444         CachedVertex[] v = tess.cache;
445 //            CachedVertex vn = v0 + tess.cacheCount;
446         int vn = tess.cacheCount;
447 //            CachedVertex vc;
448         int vc;
449         double dot, xc, yc, zc, xp, yp, zp;
450         double[] n = new double[3];
451         int sign = 0;
452 
453         /* Find the polygon normal.  It is important to get a reasonable
454          * normal even when the polygon is self-intersecting (eg. a bowtie).
455          * Otherwise, the computed normal could be very tiny, but perpendicular
456          * to the true plane of the polygon due to numerical noise.  Then all
457          * the triangles would appear to be degenerate and we would incorrectly
458          * decompose the polygon as a fan (or simply not render it at all).
459          *
460          * We use a sum-of-triangles normal algorithm rather than the more
461          * efficient sum-of-trapezoids method (used in CheckOrientation()
462          * in normal.c).  This lets us explicitly reverse the signed area
463          * of some triangles to get a reasonable normal in the self-intersecting
464          * case.
465          */
466         if (!check) {
467             norm[0] = norm[1] = norm[2] = 0.0;
468         }
469 
470         vc = 1;
471         xc = v[vc].coords[0] - v[0].coords[0];
472         yc = v[vc].coords[1] - v[0].coords[1];
473         zc = v[vc].coords[2] - v[0].coords[2];
474         while (++vc < vn) {
475             xp = xc;
476             yp = yc;
477             zp = zc;
478             xc = v[vc].coords[0] - v[0].coords[0];
479             yc = v[vc].coords[1] - v[0].coords[1];
480             zc = v[vc].coords[2] - v[0].coords[2];
481 
482             /* Compute (vp - v0) cross (vc - v0) */
483             n[0] = yp * zc - zp * yc;
484             n[1] = zp * xc - xp * zc;
485             n[2] = xp * yc - yp * xc;
486 
487             dot = n[0] * norm[0] + n[1] * norm[1] + n[2] * norm[2];
488             if (!check) {
489                 /* Reverse the contribution of back-facing triangles to get
490                  * a reasonable normal for self-intersecting polygons (see above)
491                  */
492                 if (dot >= 0) {
493                     norm[0] += n[0];
494                     norm[1] += n[1];
495                     norm[2] += n[2];
496                 } else {
497                     norm[0] -= n[0];
498                     norm[1] -= n[1];
499                     norm[2] -= n[2];
500                 }
501             } else if (dot != 0) {
502                 /* Check the new orientation for consistency with previous triangles */
503                 if (dot > 0) {
504                     if (sign < 0) return SIGN_INCONSISTENT;
505                     sign = 1;
506                 } else {
507                     if (sign > 0) return SIGN_INCONSISTENT;
508                     sign = -1;
509                 }
510             }
511         }
512         return sign;
513     }
514 
515 /* __gl_renderCache( tess ) takes a single contour and tries to render it
516  * as a triangle fan.  This handles convex polygons, as well as some
517  * non-convex polygons if we get lucky.
518  *
519  * Returns true if the polygon was successfully rendered.  The rendering
520  * output is provided as callbacks (see the api).
521  */
__gl_renderCache(GLUtessellatorImpl tess)522     public static boolean __gl_renderCache(GLUtessellatorImpl tess) {
523         CachedVertex[] v = tess.cache;
524 //            CachedVertex vn = v0 + tess.cacheCount;
525         int vn = tess.cacheCount;
526 //            CachedVertex vc;
527         int vc;
528         double[] norm = new double[3];
529         int sign;
530 
531         if (tess.cacheCount < 3) {
532             /* Degenerate contour -- no output */
533             return true;
534         }
535 
536         norm[0] = tess.normal[0];
537         norm[1] = tess.normal[1];
538         norm[2] = tess.normal[2];
539         if (norm[0] == 0 && norm[1] == 0 && norm[2] == 0) {
540             ComputeNormal( tess, norm, false);
541         }
542 
543         sign = ComputeNormal( tess, norm, true);
544         if (sign == SIGN_INCONSISTENT) {
545             /* Fan triangles did not have a consistent orientation */
546             return false;
547         }
548         if (sign == 0) {
549             /* All triangles were degenerate */
550             return true;
551         }
552 
553         if ( !USE_OPTIMIZED_CODE_PATH ) {
554             return false;
555         } else {
556             /* Make sure we do the right thing for each winding rule */
557             switch (tess.windingRule) {
558                 case GLU_TESS_WINDING_ODD:
559                 case GLU_TESS_WINDING_NONZERO:
560                     break;
561                 case GLU_TESS_WINDING_POSITIVE:
562                     if (sign < 0) return true;
563                     break;
564                 case GLU_TESS_WINDING_NEGATIVE:
565                     if (sign > 0) return true;
566                     break;
567                 case GLU_TESS_WINDING_ABS_GEQ_TWO:
568                     return true;
569             }
570 
571             tess.callBeginOrBeginData( tess.boundaryOnly ? GL_LINE_LOOP
572                     : (tess.cacheCount > 3) ? GL_TRIANGLE_FAN
573                     : GL_TRIANGLES);
574 
575             tess.callVertexOrVertexData( v[0].data);
576             if (sign > 0) {
577                 for (vc = 1; vc < vn; ++vc) {
578                     tess.callVertexOrVertexData( v[vc].data);
579                 }
580             } else {
581                 for (vc = vn - 1; vc > 0; --vc) {
582                     tess.callVertexOrVertexData( v[vc].data);
583                 }
584             }
585             tess.callEndOrEndData();
586             return true;
587         }
588     }
589 }
590