aboutsummaryrefslogtreecommitdiffstats
path: root/src/classes/com/sun/opengl/impl/tessellator/Mesh.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/classes/com/sun/opengl/impl/tessellator/Mesh.java')
-rw-r--r--src/classes/com/sun/opengl/impl/tessellator/Mesh.java734
1 files changed, 734 insertions, 0 deletions
diff --git a/src/classes/com/sun/opengl/impl/tessellator/Mesh.java b/src/classes/com/sun/opengl/impl/tessellator/Mesh.java
new file mode 100644
index 000000000..290fb1037
--- /dev/null
+++ b/src/classes/com/sun/opengl/impl/tessellator/Mesh.java
@@ -0,0 +1,734 @@
+/*
+* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc.
+* All rights reserved.
+*/
+
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** NOTE: The Original Code (as defined below) has been licensed to Sun
+** Microsystems, Inc. ("Sun") under the SGI Free Software License B
+** (Version 1.1), shown above ("SGI License"). Pursuant to Section
+** 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+** you under an alternative license ("Alternative License"). This
+** Alternative License includes all of the provisions of the SGI License
+** except that Section 2.2 and 11 are omitted. Any differences between
+** the Alternative License and the SGI License are offered solely by Sun
+** and not by SGI.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** Author: Eric Veach, July 1994
+** Java Port: Pepijn Van Eeckhoudt, July 2003
+** Java Port: Nathan Parker Burg, August 2003
+*/
+package com.sun.opengl.impl.glu.tessellator;
+
+class Mesh {
+ private Mesh() {
+ }
+
+ /************************ Utility Routines ************************/
+/* MakeEdge creates a new pair of half-edges which form their own loop.
+ * No vertex or face structures are allocated, but these must be assigned
+ * before the current edge operation is completed.
+ */
+ static com.sun.opengl.impl.glu.tessellator.GLUhalfEdge MakeEdge(com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eNext) {
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e;
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eSym;
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge ePrev;
+
+// EdgePair * pair = (EdgePair *)
+// memAlloc(sizeof(EdgePair));
+// if (pair == NULL) return NULL;
+//
+// e = &pair - > e;
+ e = new com.sun.opengl.impl.glu.tessellator.GLUhalfEdge(true);
+// eSym = &pair - > eSym;
+ eSym = new com.sun.opengl.impl.glu.tessellator.GLUhalfEdge(false);
+
+
+ /* Make sure eNext points to the first edge of the edge pair */
+ if (!eNext.first) {
+ eNext = eNext.Sym;
+ }
+
+ /* Insert in circular doubly-linked list before eNext.
+ * Note that the prev pointer is stored in Sym->next.
+ */
+ ePrev = eNext.Sym.next;
+ eSym.next = ePrev;
+ ePrev.Sym.next = e;
+ e.next = eNext;
+ eNext.Sym.next = eSym;
+
+ e.Sym = eSym;
+ e.Onext = e;
+ e.Lnext = eSym;
+ e.Org = null;
+ e.Lface = null;
+ e.winding = 0;
+ e.activeRegion = null;
+
+ eSym.Sym = e;
+ eSym.Onext = eSym;
+ eSym.Lnext = e;
+ eSym.Org = null;
+ eSym.Lface = null;
+ eSym.winding = 0;
+ eSym.activeRegion = null;
+
+ return e;
+ }
+
+/* Splice( a, b ) is best described by the Guibas/Stolfi paper or the
+ * CS348a notes (see mesh.h). Basically it modifies the mesh so that
+ * a->Onext and b->Onext are exchanged. This can have various effects
+ * depending on whether a and b belong to different face or vertex rings.
+ * For more explanation see __gl_meshSplice() below.
+ */
+ static void Splice(com.sun.opengl.impl.glu.tessellator.GLUhalfEdge a, com.sun.opengl.impl.glu.tessellator.GLUhalfEdge b) {
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge aOnext = a.Onext;
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge bOnext = b.Onext;
+
+ aOnext.Sym.Lnext = b;
+ bOnext.Sym.Lnext = a;
+ a.Onext = bOnext;
+ b.Onext = aOnext;
+ }
+
+/* MakeVertex( newVertex, eOrig, vNext ) attaches a new vertex and makes it the
+ * origin of all edges in the vertex loop to which eOrig belongs. "vNext" gives
+ * a place to insert the new vertex in the global vertex list. We insert
+ * the new vertex *before* vNext so that algorithms which walk the vertex
+ * list will not see the newly created vertices.
+ */
+ static void MakeVertex(com.sun.opengl.impl.glu.tessellator.GLUvertex newVertex,
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eOrig, com.sun.opengl.impl.glu.tessellator.GLUvertex vNext) {
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e;
+ com.sun.opengl.impl.glu.tessellator.GLUvertex vPrev;
+ com.sun.opengl.impl.glu.tessellator.GLUvertex vNew = newVertex;
+
+ assert (vNew != null);
+
+ /* insert in circular doubly-linked list before vNext */
+ vPrev = vNext.prev;
+ vNew.prev = vPrev;
+ vPrev.next = vNew;
+ vNew.next = vNext;
+ vNext.prev = vNew;
+
+ vNew.anEdge = eOrig;
+ vNew.data = null;
+ /* leave coords, s, t undefined */
+
+ /* fix other edges on this vertex loop */
+ e = eOrig;
+ do {
+ e.Org = vNew;
+ e = e.Onext;
+ } while (e != eOrig);
+ }
+
+/* MakeFace( newFace, eOrig, fNext ) attaches a new face and makes it the left
+ * face of all edges in the face loop to which eOrig belongs. "fNext" gives
+ * a place to insert the new face in the global face list. We insert
+ * the new face *before* fNext so that algorithms which walk the face
+ * list will not see the newly created faces.
+ */
+ static void MakeFace(com.sun.opengl.impl.glu.tessellator.GLUface newFace, com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eOrig, com.sun.opengl.impl.glu.tessellator.GLUface fNext) {
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e;
+ com.sun.opengl.impl.glu.tessellator.GLUface fPrev;
+ com.sun.opengl.impl.glu.tessellator.GLUface fNew = newFace;
+
+ assert (fNew != null);
+
+ /* insert in circular doubly-linked list before fNext */
+ fPrev = fNext.prev;
+ fNew.prev = fPrev;
+ fPrev.next = fNew;
+ fNew.next = fNext;
+ fNext.prev = fNew;
+
+ fNew.anEdge = eOrig;
+ fNew.data = null;
+ fNew.trail = null;
+ fNew.marked = false;
+
+ /* The new face is marked "inside" if the old one was. This is a
+ * convenience for the common case where a face has been split in two.
+ */
+ fNew.inside = fNext.inside;
+
+ /* fix other edges on this face loop */
+ e = eOrig;
+ do {
+ e.Lface = fNew;
+ e = e.Lnext;
+ } while (e != eOrig);
+ }
+
+/* KillEdge( eDel ) destroys an edge (the half-edges eDel and eDel->Sym),
+ * and removes from the global edge list.
+ */
+ static void KillEdge(com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eDel) {
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge ePrev, eNext;
+
+ /* Half-edges are allocated in pairs, see EdgePair above */
+ if (!eDel.first) {
+ eDel = eDel.Sym;
+ }
+
+ /* delete from circular doubly-linked list */
+ eNext = eDel.next;
+ ePrev = eDel.Sym.next;
+ eNext.Sym.next = ePrev;
+ ePrev.Sym.next = eNext;
+ }
+
+
+/* KillVertex( vDel ) destroys a vertex and removes it from the global
+ * vertex list. It updates the vertex loop to point to a given new vertex.
+ */
+ static void KillVertex(com.sun.opengl.impl.glu.tessellator.GLUvertex vDel, com.sun.opengl.impl.glu.tessellator.GLUvertex newOrg) {
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e, eStart = vDel.anEdge;
+ com.sun.opengl.impl.glu.tessellator.GLUvertex vPrev, vNext;
+
+ /* change the origin of all affected edges */
+ e = eStart;
+ do {
+ e.Org = newOrg;
+ e = e.Onext;
+ } while (e != eStart);
+
+ /* delete from circular doubly-linked list */
+ vPrev = vDel.prev;
+ vNext = vDel.next;
+ vNext.prev = vPrev;
+ vPrev.next = vNext;
+ }
+
+/* KillFace( fDel ) destroys a face and removes it from the global face
+ * list. It updates the face loop to point to a given new face.
+ */
+ static void KillFace(com.sun.opengl.impl.glu.tessellator.GLUface fDel, com.sun.opengl.impl.glu.tessellator.GLUface newLface) {
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e, eStart = fDel.anEdge;
+ com.sun.opengl.impl.glu.tessellator.GLUface fPrev, fNext;
+
+ /* change the left face of all affected edges */
+ e = eStart;
+ do {
+ e.Lface = newLface;
+ e = e.Lnext;
+ } while (e != eStart);
+
+ /* delete from circular doubly-linked list */
+ fPrev = fDel.prev;
+ fNext = fDel.next;
+ fNext.prev = fPrev;
+ fPrev.next = fNext;
+ }
+
+
+ /****************** Basic Edge Operations **********************/
+
+/* __gl_meshMakeEdge creates one edge, two vertices, and a loop (face).
+ * The loop consists of the two new half-edges.
+ */
+ public static com.sun.opengl.impl.glu.tessellator.GLUhalfEdge __gl_meshMakeEdge(com.sun.opengl.impl.glu.tessellator.GLUmesh mesh) {
+ com.sun.opengl.impl.glu.tessellator.GLUvertex newVertex1 = new com.sun.opengl.impl.glu.tessellator.GLUvertex();
+ com.sun.opengl.impl.glu.tessellator.GLUvertex newVertex2 = new com.sun.opengl.impl.glu.tessellator.GLUvertex();
+ com.sun.opengl.impl.glu.tessellator.GLUface newFace = new com.sun.opengl.impl.glu.tessellator.GLUface();
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e;
+
+ e = MakeEdge(mesh.eHead);
+ if (e == null) return null;
+
+ MakeVertex(newVertex1, e, mesh.vHead);
+ MakeVertex(newVertex2, e.Sym, mesh.vHead);
+ MakeFace(newFace, e, mesh.fHead);
+ return e;
+ }
+
+
+/* __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the
+ * mesh connectivity and topology. It changes the mesh so that
+ * eOrg->Onext <- OLD( eDst->Onext )
+ * eDst->Onext <- OLD( eOrg->Onext )
+ * where OLD(...) means the value before the meshSplice operation.
+ *
+ * This can have two effects on the vertex structure:
+ * - if eOrg->Org != eDst->Org, the two vertices are merged together
+ * - if eOrg->Org == eDst->Org, the origin is split into two vertices
+ * In both cases, eDst->Org is changed and eOrg->Org is untouched.
+ *
+ * Similarly (and independently) for the face structure,
+ * - if eOrg->Lface == eDst->Lface, one loop is split into two
+ * - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one
+ * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected.
+ *
+ * Some special cases:
+ * If eDst == eOrg, the operation has no effect.
+ * If eDst == eOrg->Lnext, the new face will have a single edge.
+ * If eDst == eOrg->Lprev, the old face will have a single edge.
+ * If eDst == eOrg->Onext, the new vertex will have a single edge.
+ * If eDst == eOrg->Oprev, the old vertex will have a single edge.
+ */
+ public static boolean __gl_meshSplice(com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eOrg, com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eDst) {
+ boolean joiningLoops = false;
+ boolean joiningVertices = false;
+
+ if (eOrg == eDst) return true;
+
+ if (eDst.Org != eOrg.Org) {
+ /* We are merging two disjoint vertices -- destroy eDst->Org */
+ joiningVertices = true;
+ KillVertex(eDst.Org, eOrg.Org);
+ }
+ if (eDst.Lface != eOrg.Lface) {
+ /* We are connecting two disjoint loops -- destroy eDst.Lface */
+ joiningLoops = true;
+ KillFace(eDst.Lface, eOrg.Lface);
+ }
+
+ /* Change the edge structure */
+ Splice(eDst, eOrg);
+
+ if (!joiningVertices) {
+ com.sun.opengl.impl.glu.tessellator.GLUvertex newVertex = new com.sun.opengl.impl.glu.tessellator.GLUvertex();
+
+ /* We split one vertex into two -- the new vertex is eDst.Org.
+ * Make sure the old vertex points to a valid half-edge.
+ */
+ MakeVertex(newVertex, eDst, eOrg.Org);
+ eOrg.Org.anEdge = eOrg;
+ }
+ if (!joiningLoops) {
+ com.sun.opengl.impl.glu.tessellator.GLUface newFace = new com.sun.opengl.impl.glu.tessellator.GLUface();
+
+ /* We split one loop into two -- the new loop is eDst.Lface.
+ * Make sure the old face points to a valid half-edge.
+ */
+ MakeFace(newFace, eDst, eOrg.Lface);
+ eOrg.Lface.anEdge = eOrg;
+ }
+
+ return true;
+ }
+
+
+/* __gl_meshDelete( eDel ) removes the edge eDel. There are several cases:
+ * if (eDel.Lface != eDel.Rface), we join two loops into one; the loop
+ * eDel.Lface is deleted. Otherwise, we are splitting one loop into two;
+ * the newly created loop will contain eDel.Dst. If the deletion of eDel
+ * would create isolated vertices, those are deleted as well.
+ *
+ * This function could be implemented as two calls to __gl_meshSplice
+ * plus a few calls to memFree, but this would allocate and delete
+ * unnecessary vertices and faces.
+ */
+ static boolean __gl_meshDelete(com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eDel) {
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eDelSym = eDel.Sym;
+ boolean joiningLoops = false;
+
+ /* First step: disconnect the origin vertex eDel.Org. We make all
+ * changes to get a consistent mesh in this "intermediate" state.
+ */
+ if (eDel.Lface != eDel.Sym.Lface) {
+ /* We are joining two loops into one -- remove the left face */
+ joiningLoops = true;
+ KillFace(eDel.Lface, eDel.Sym.Lface);
+ }
+
+ if (eDel.Onext == eDel) {
+ KillVertex(eDel.Org, null);
+ } else {
+ /* Make sure that eDel.Org and eDel.Sym.Lface point to valid half-edges */
+ eDel.Sym.Lface.anEdge = eDel.Sym.Lnext;
+ eDel.Org.anEdge = eDel.Onext;
+
+ Splice(eDel, eDel.Sym.Lnext);
+ if (!joiningLoops) {
+ com.sun.opengl.impl.glu.tessellator.GLUface newFace = new com.sun.opengl.impl.glu.tessellator.GLUface();
+
+ /* We are splitting one loop into two -- create a new loop for eDel. */
+ MakeFace(newFace, eDel, eDel.Lface);
+ }
+ }
+
+ /* Claim: the mesh is now in a consistent state, except that eDel.Org
+ * may have been deleted. Now we disconnect eDel.Dst.
+ */
+ if (eDelSym.Onext == eDelSym) {
+ KillVertex(eDelSym.Org, null);
+ KillFace(eDelSym.Lface, null);
+ } else {
+ /* Make sure that eDel.Dst and eDel.Lface point to valid half-edges */
+ eDel.Lface.anEdge = eDelSym.Sym.Lnext;
+ eDelSym.Org.anEdge = eDelSym.Onext;
+ Splice(eDelSym, eDelSym.Sym.Lnext);
+ }
+
+ /* Any isolated vertices or faces have already been freed. */
+ KillEdge(eDel);
+
+ return true;
+ }
+
+
+ /******************** Other Edge Operations **********************/
+
+/* All these routines can be implemented with the basic edge
+ * operations above. They are provided for convenience and efficiency.
+ */
+
+
+/* __gl_meshAddEdgeVertex( eOrg ) creates a new edge eNew such that
+ * eNew == eOrg.Lnext, and eNew.Dst is a newly created vertex.
+ * eOrg and eNew will have the same left face.
+ */
+ static com.sun.opengl.impl.glu.tessellator.GLUhalfEdge __gl_meshAddEdgeVertex(com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eOrg) {
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eNewSym;
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eNew = MakeEdge(eOrg);
+
+ eNewSym = eNew.Sym;
+
+ /* Connect the new edge appropriately */
+ Splice(eNew, eOrg.Lnext);
+
+ /* Set the vertex and face information */
+ eNew.Org = eOrg.Sym.Org;
+ {
+ com.sun.opengl.impl.glu.tessellator.GLUvertex newVertex = new com.sun.opengl.impl.glu.tessellator.GLUvertex();
+
+ MakeVertex(newVertex, eNewSym, eNew.Org);
+ }
+ eNew.Lface = eNewSym.Lface = eOrg.Lface;
+
+ return eNew;
+ }
+
+
+/* __gl_meshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew,
+ * such that eNew == eOrg.Lnext. The new vertex is eOrg.Sym.Org == eNew.Org.
+ * eOrg and eNew will have the same left face.
+ */
+ public static com.sun.opengl.impl.glu.tessellator.GLUhalfEdge __gl_meshSplitEdge(com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eOrg) {
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eNew;
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge tempHalfEdge = __gl_meshAddEdgeVertex(eOrg);
+
+ eNew = tempHalfEdge.Sym;
+
+ /* Disconnect eOrg from eOrg.Sym.Org and connect it to eNew.Org */
+ Splice(eOrg.Sym, eOrg.Sym.Sym.Lnext);
+ Splice(eOrg.Sym, eNew);
+
+ /* Set the vertex and face information */
+ eOrg.Sym.Org = eNew.Org;
+ eNew.Sym.Org.anEdge = eNew.Sym; /* may have pointed to eOrg.Sym */
+ eNew.Sym.Lface = eOrg.Sym.Lface;
+ eNew.winding = eOrg.winding; /* copy old winding information */
+ eNew.Sym.winding = eOrg.Sym.winding;
+
+ return eNew;
+ }
+
+
+/* __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg.Sym.Org
+ * to eDst.Org, and returns the corresponding half-edge eNew.
+ * If eOrg.Lface == eDst.Lface, this splits one loop into two,
+ * and the newly created loop is eNew.Lface. Otherwise, two disjoint
+ * loops are merged into one, and the loop eDst.Lface is destroyed.
+ *
+ * If (eOrg == eDst), the new face will have only two edges.
+ * If (eOrg.Lnext == eDst), the old face is reduced to a single edge.
+ * If (eOrg.Lnext.Lnext == eDst), the old face is reduced to two edges.
+ */
+ static com.sun.opengl.impl.glu.tessellator.GLUhalfEdge __gl_meshConnect(com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eOrg, com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eDst) {
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eNewSym;
+ boolean joiningLoops = false;
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eNew = MakeEdge(eOrg);
+
+ eNewSym = eNew.Sym;
+
+ if (eDst.Lface != eOrg.Lface) {
+ /* We are connecting two disjoint loops -- destroy eDst.Lface */
+ joiningLoops = true;
+ KillFace(eDst.Lface, eOrg.Lface);
+ }
+
+ /* Connect the new edge appropriately */
+ Splice(eNew, eOrg.Lnext);
+ Splice(eNewSym, eDst);
+
+ /* Set the vertex and face information */
+ eNew.Org = eOrg.Sym.Org;
+ eNewSym.Org = eDst.Org;
+ eNew.Lface = eNewSym.Lface = eOrg.Lface;
+
+ /* Make sure the old face points to a valid half-edge */
+ eOrg.Lface.anEdge = eNewSym;
+
+ if (!joiningLoops) {
+ com.sun.opengl.impl.glu.tessellator.GLUface newFace = new com.sun.opengl.impl.glu.tessellator.GLUface();
+
+ /* We split one loop into two -- the new loop is eNew.Lface */
+ MakeFace(newFace, eNew, eOrg.Lface);
+ }
+ return eNew;
+ }
+
+
+ /******************** Other Operations **********************/
+
+/* __gl_meshZapFace( fZap ) destroys a face and removes it from the
+ * global face list. All edges of fZap will have a null pointer as their
+ * left face. Any edges which also have a null pointer as their right face
+ * are deleted entirely (along with any isolated vertices this produces).
+ * An entire mesh can be deleted by zapping its faces, one at a time,
+ * in any order. Zapped faces cannot be used in further mesh operations!
+ */
+ static void __gl_meshZapFace(com.sun.opengl.impl.glu.tessellator.GLUface fZap) {
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eStart = fZap.anEdge;
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e, eNext, eSym;
+ com.sun.opengl.impl.glu.tessellator.GLUface fPrev, fNext;
+
+ /* walk around face, deleting edges whose right face is also null */
+ eNext = eStart.Lnext;
+ do {
+ e = eNext;
+ eNext = e.Lnext;
+
+ e.Lface = null;
+ if (e.Sym.Lface == null) {
+ /* delete the edge -- see __gl_MeshDelete above */
+
+ if (e.Onext == e) {
+ KillVertex(e.Org, null);
+ } else {
+ /* Make sure that e.Org points to a valid half-edge */
+ e.Org.anEdge = e.Onext;
+ Splice(e, e.Sym.Lnext);
+ }
+ eSym = e.Sym;
+ if (eSym.Onext == eSym) {
+ KillVertex(eSym.Org, null);
+ } else {
+ /* Make sure that eSym.Org points to a valid half-edge */
+ eSym.Org.anEdge = eSym.Onext;
+ Splice(eSym, eSym.Sym.Lnext);
+ }
+ KillEdge(e);
+ }
+ } while (e != eStart);
+
+ /* delete from circular doubly-linked list */
+ fPrev = fZap.prev;
+ fNext = fZap.next;
+ fNext.prev = fPrev;
+ fPrev.next = fNext;
+ }
+
+
+/* __gl_meshNewMesh() creates a new mesh with no edges, no vertices,
+ * and no loops (what we usually call a "face").
+ */
+ public static com.sun.opengl.impl.glu.tessellator.GLUmesh __gl_meshNewMesh() {
+ com.sun.opengl.impl.glu.tessellator.GLUvertex v;
+ com.sun.opengl.impl.glu.tessellator.GLUface f;
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e;
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eSym;
+ com.sun.opengl.impl.glu.tessellator.GLUmesh mesh = new com.sun.opengl.impl.glu.tessellator.GLUmesh();
+
+ v = mesh.vHead;
+ f = mesh.fHead;
+ e = mesh.eHead;
+ eSym = mesh.eHeadSym;
+
+ v.next = v.prev = v;
+ v.anEdge = null;
+ v.data = null;
+
+ f.next = f.prev = f;
+ f.anEdge = null;
+ f.data = null;
+ f.trail = null;
+ f.marked = false;
+ f.inside = false;
+
+ e.next = e;
+ e.Sym = eSym;
+ e.Onext = null;
+ e.Lnext = null;
+ e.Org = null;
+ e.Lface = null;
+ e.winding = 0;
+ e.activeRegion = null;
+
+ eSym.next = eSym;
+ eSym.Sym = e;
+ eSym.Onext = null;
+ eSym.Lnext = null;
+ eSym.Org = null;
+ eSym.Lface = null;
+ eSym.winding = 0;
+ eSym.activeRegion = null;
+
+ return mesh;
+ }
+
+
+/* __gl_meshUnion( mesh1, mesh2 ) forms the union of all structures in
+ * both meshes, and returns the new mesh (the old meshes are destroyed).
+ */
+ static com.sun.opengl.impl.glu.tessellator.GLUmesh __gl_meshUnion(com.sun.opengl.impl.glu.tessellator.GLUmesh mesh1, com.sun.opengl.impl.glu.tessellator.GLUmesh mesh2) {
+ com.sun.opengl.impl.glu.tessellator.GLUface f1 = mesh1.fHead;
+ com.sun.opengl.impl.glu.tessellator.GLUvertex v1 = mesh1.vHead;
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e1 = mesh1.eHead;
+ com.sun.opengl.impl.glu.tessellator.GLUface f2 = mesh2.fHead;
+ com.sun.opengl.impl.glu.tessellator.GLUvertex v2 = mesh2.vHead;
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e2 = mesh2.eHead;
+
+ /* Add the faces, vertices, and edges of mesh2 to those of mesh1 */
+ if (f2.next != f2) {
+ f1.prev.next = f2.next;
+ f2.next.prev = f1.prev;
+ f2.prev.next = f1;
+ f1.prev = f2.prev;
+ }
+
+ if (v2.next != v2) {
+ v1.prev.next = v2.next;
+ v2.next.prev = v1.prev;
+ v2.prev.next = v1;
+ v1.prev = v2.prev;
+ }
+
+ if (e2.next != e2) {
+ e1.Sym.next.Sym.next = e2.next;
+ e2.next.Sym.next = e1.Sym.next;
+ e2.Sym.next.Sym.next = e1;
+ e1.Sym.next = e2.Sym.next;
+ }
+
+ return mesh1;
+ }
+
+
+/* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh.
+ */
+ static void __gl_meshDeleteMeshZap(com.sun.opengl.impl.glu.tessellator.GLUmesh mesh) {
+ com.sun.opengl.impl.glu.tessellator.GLUface fHead = mesh.fHead;
+
+ while (fHead.next != fHead) {
+ __gl_meshZapFace(fHead.next);
+ }
+ assert (mesh.vHead.next == mesh.vHead);
+ }
+
+/* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh.
+ */
+ public static void __gl_meshDeleteMesh(com.sun.opengl.impl.glu.tessellator.GLUmesh mesh) {
+ com.sun.opengl.impl.glu.tessellator.GLUface f, fNext;
+ com.sun.opengl.impl.glu.tessellator.GLUvertex v, vNext;
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e, eNext;
+
+ for (f = mesh.fHead.next; f != mesh.fHead; f = fNext) {
+ fNext = f.next;
+ }
+
+ for (v = mesh.vHead.next; v != mesh.vHead; v = vNext) {
+ vNext = v.next;
+ }
+
+ for (e = mesh.eHead.next; e != mesh.eHead; e = eNext) {
+ /* One call frees both e and e.Sym (see EdgePair above) */
+ eNext = e.next;
+ }
+ }
+
+/* __gl_meshCheckMesh( mesh ) checks a mesh for self-consistency.
+ */
+ public static void __gl_meshCheckMesh(com.sun.opengl.impl.glu.tessellator.GLUmesh mesh) {
+ com.sun.opengl.impl.glu.tessellator.GLUface fHead = mesh.fHead;
+ com.sun.opengl.impl.glu.tessellator.GLUvertex vHead = mesh.vHead;
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eHead = mesh.eHead;
+ com.sun.opengl.impl.glu.tessellator.GLUface f, fPrev;
+ com.sun.opengl.impl.glu.tessellator.GLUvertex v, vPrev;
+ com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e, ePrev;
+
+ fPrev = fHead;
+ for (fPrev = fHead; (f = fPrev.next) != fHead; fPrev = f) {
+ assert (f.prev == fPrev);
+ e = f.anEdge;
+ do {
+ assert (e.Sym != e);
+ assert (e.Sym.Sym == e);
+ assert (e.Lnext.Onext.Sym == e);
+ assert (e.Onext.Sym.Lnext == e);
+ assert (e.Lface == f);
+ e = e.Lnext;
+ } while (e != f.anEdge);
+ }
+ assert (f.prev == fPrev && f.anEdge == null && f.data == null);
+
+ vPrev = vHead;
+ for (vPrev = vHead; (v = vPrev.next) != vHead; vPrev = v) {
+ assert (v.prev == vPrev);
+ e = v.anEdge;
+ do {
+ assert (e.Sym != e);
+ assert (e.Sym.Sym == e);
+ assert (e.Lnext.Onext.Sym == e);
+ assert (e.Onext.Sym.Lnext == e);
+ assert (e.Org == v);
+ e = e.Onext;
+ } while (e != v.anEdge);
+ }
+ assert (v.prev == vPrev && v.anEdge == null && v.data == null);
+
+ ePrev = eHead;
+ for (ePrev = eHead; (e = ePrev.next) != eHead; ePrev = e) {
+ assert (e.Sym.next == ePrev.Sym);
+ assert (e.Sym != e);
+ assert (e.Sym.Sym == e);
+ assert (e.Org != null);
+ assert (e.Sym.Org != null);
+ assert (e.Lnext.Onext.Sym == e);
+ assert (e.Onext.Sym.Lnext == e);
+ }
+ assert (e.Sym.next == ePrev.Sym
+ && e.Sym == mesh.eHeadSym
+ && e.Sym.Sym == e
+ && e.Org == null && e.Sym.Org == null
+ && e.Lface == null && e.Sym.Lface == null);
+ }
+}