1f220fa62Smrg/*
2f220fa62Smrg * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3f220fa62Smrg * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4f220fa62Smrg *
5f220fa62Smrg * Permission is hereby granted, free of charge, to any person obtaining a
6f220fa62Smrg * copy of this software and associated documentation files (the "Software"),
7f220fa62Smrg * to deal in the Software without restriction, including without limitation
8f220fa62Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9f220fa62Smrg * and/or sell copies of the Software, and to permit persons to whom the
10f220fa62Smrg * Software is furnished to do so, subject to the following conditions:
11f220fa62Smrg *
12f220fa62Smrg * The above copyright notice including the dates of first publication and
13f220fa62Smrg * either this permission notice or a reference to
14f220fa62Smrg * http://oss.sgi.com/projects/FreeB/
15f220fa62Smrg * shall be included in all copies or substantial portions of the Software.
16f220fa62Smrg *
17f220fa62Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18f220fa62Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19f220fa62Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20f220fa62Smrg * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21f220fa62Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22f220fa62Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23f220fa62Smrg * SOFTWARE.
24f220fa62Smrg *
25f220fa62Smrg * Except as contained in this notice, the name of Silicon Graphics, Inc.
26f220fa62Smrg * shall not be used in advertising or otherwise to promote the sale, use or
27f220fa62Smrg * other dealings in this Software without prior written authorization from
28f220fa62Smrg * Silicon Graphics, Inc.
29f220fa62Smrg */
30f220fa62Smrg/*
31f220fa62Smrg** Author: Eric Veach, July 1994.
32f220fa62Smrg**
33f220fa62Smrg*/
34f220fa62Smrg
35f220fa62Smrg#ifndef __mesh_h_
36f220fa62Smrg#define __mesh_h_
37f220fa62Smrg
38f220fa62Smrg#include <GL/glu.h>
39f220fa62Smrg
40f220fa62Smrgtypedef struct GLUmesh GLUmesh;
41f220fa62Smrg
42f220fa62Smrgtypedef struct GLUvertex GLUvertex;
43f220fa62Smrgtypedef struct GLUface GLUface;
44f220fa62Smrgtypedef struct GLUhalfEdge GLUhalfEdge;
45f220fa62Smrg
46f220fa62Smrgtypedef struct ActiveRegion ActiveRegion;	/* Internal data */
47f220fa62Smrg
48f220fa62Smrg/* The mesh structure is similar in spirit, notation, and operations
49f220fa62Smrg * to the "quad-edge" structure (see L. Guibas and J. Stolfi, Primitives
50f220fa62Smrg * for the manipulation of general subdivisions and the computation of
51f220fa62Smrg * Voronoi diagrams, ACM Transactions on Graphics, 4(2):74-123, April 1985).
52f220fa62Smrg * For a simplified description, see the course notes for CS348a,
53f220fa62Smrg * "Mathematical Foundations of Computer Graphics", available at the
54f220fa62Smrg * Stanford bookstore (and taught during the fall quarter).
55f220fa62Smrg * The implementation also borrows a tiny subset of the graph-based approach
56f220fa62Smrg * use in Mantyla's Geometric Work Bench (see M. Mantyla, An Introduction
57f220fa62Smrg * to Sold Modeling, Computer Science Press, Rockville, Maryland, 1988).
58f220fa62Smrg *
59f220fa62Smrg * The fundamental data structure is the "half-edge".  Two half-edges
60f220fa62Smrg * go together to make an edge, but they point in opposite directions.
61f220fa62Smrg * Each half-edge has a pointer to its mate (the "symmetric" half-edge Sym),
62f220fa62Smrg * its origin vertex (Org), the face on its left side (Lface), and the
63f220fa62Smrg * adjacent half-edges in the CCW direction around the origin vertex
64f220fa62Smrg * (Onext) and around the left face (Lnext).  There is also a "next"
65f220fa62Smrg * pointer for the global edge list (see below).
66f220fa62Smrg *
67f220fa62Smrg * The notation used for mesh navigation:
68f220fa62Smrg *	Sym   = the mate of a half-edge (same edge, but opposite direction)
69f220fa62Smrg *	Onext = edge CCW around origin vertex (keep same origin)
70f220fa62Smrg *	Dnext = edge CCW around destination vertex (keep same dest)
71f220fa62Smrg *	Lnext = edge CCW around left face (dest becomes new origin)
72f220fa62Smrg *	Rnext = edge CCW around right face (origin becomes new dest)
73f220fa62Smrg *
74f220fa62Smrg * "prev" means to substitute CW for CCW in the definitions above.
75f220fa62Smrg *
76f220fa62Smrg * The mesh keeps global lists of all vertices, faces, and edges,
77f220fa62Smrg * stored as doubly-linked circular lists with a dummy header node.
78f220fa62Smrg * The mesh stores pointers to these dummy headers (vHead, fHead, eHead).
79f220fa62Smrg *
80f220fa62Smrg * The circular edge list is special; since half-edges always occur
81f220fa62Smrg * in pairs (e and e->Sym), each half-edge stores a pointer in only
82f220fa62Smrg * one direction.  Starting at eHead and following the e->next pointers
83f220fa62Smrg * will visit each *edge* once (ie. e or e->Sym, but not both).
84f220fa62Smrg * e->Sym stores a pointer in the opposite direction, thus it is
85f220fa62Smrg * always true that e->Sym->next->Sym->next == e.
86f220fa62Smrg *
87f220fa62Smrg * Each vertex has a pointer to next and previous vertices in the
88f220fa62Smrg * circular list, and a pointer to a half-edge with this vertex as
89f220fa62Smrg * the origin (NULL if this is the dummy header).  There is also a
90f220fa62Smrg * field "data" for client data.
91f220fa62Smrg *
92f220fa62Smrg * Each face has a pointer to the next and previous faces in the
93f220fa62Smrg * circular list, and a pointer to a half-edge with this face as
94f220fa62Smrg * the left face (NULL if this is the dummy header).  There is also
95f220fa62Smrg * a field "data" for client data.
96f220fa62Smrg *
97f220fa62Smrg * Note that what we call a "face" is really a loop; faces may consist
98f220fa62Smrg * of more than one loop (ie. not simply connected), but there is no
99f220fa62Smrg * record of this in the data structure.  The mesh may consist of
100f220fa62Smrg * several disconnected regions, so it may not be possible to visit
101f220fa62Smrg * the entire mesh by starting at a half-edge and traversing the edge
102f220fa62Smrg * structure.
103f220fa62Smrg *
104f220fa62Smrg * The mesh does NOT support isolated vertices; a vertex is deleted along
105f220fa62Smrg * with its last edge.  Similarly when two faces are merged, one of the
106f220fa62Smrg * faces is deleted (see __gl_meshDelete below).  For mesh operations,
107f220fa62Smrg * all face (loop) and vertex pointers must not be NULL.  However, once
108f220fa62Smrg * mesh manipulation is finished, __gl_MeshZapFace can be used to delete
109f220fa62Smrg * faces of the mesh, one at a time.  All external faces can be "zapped"
110f220fa62Smrg * before the mesh is returned to the client; then a NULL face indicates
111f220fa62Smrg * a region which is not part of the output polygon.
112f220fa62Smrg */
113f220fa62Smrg
114f220fa62Smrgstruct GLUvertex {
115f220fa62Smrg  GLUvertex	*next;		/* next vertex (never NULL) */
116f220fa62Smrg  GLUvertex	*prev;		/* previous vertex (never NULL) */
117f220fa62Smrg  GLUhalfEdge	*anEdge;	/* a half-edge with this origin */
118f220fa62Smrg  void		*data;		/* client's data */
119f220fa62Smrg
120f220fa62Smrg  /* Internal data (keep hidden) */
121f220fa62Smrg  GLdouble	coords[3];	/* vertex location in 3D */
122f220fa62Smrg  GLdouble	s, t;		/* projection onto the sweep plane */
123f220fa62Smrg  long		pqHandle;	/* to allow deletion from priority queue */
124f220fa62Smrg};
125f220fa62Smrg
126f220fa62Smrgstruct GLUface {
127f220fa62Smrg  GLUface	*next;		/* next face (never NULL) */
128f220fa62Smrg  GLUface	*prev;		/* previous face (never NULL) */
129f220fa62Smrg  GLUhalfEdge	*anEdge;	/* a half edge with this left face */
130f220fa62Smrg  void		*data;		/* room for client's data */
131f220fa62Smrg
132f220fa62Smrg  /* Internal data (keep hidden) */
133f220fa62Smrg  GLUface	*trail;		/* "stack" for conversion to strips */
134f220fa62Smrg  GLboolean	marked;		/* flag for conversion to strips */
135f220fa62Smrg  GLboolean	inside;		/* this face is in the polygon interior */
136f220fa62Smrg};
137f220fa62Smrg
138f220fa62Smrgstruct GLUhalfEdge {
139f220fa62Smrg  GLUhalfEdge	*next;		/* doubly-linked list (prev==Sym->next) */
140f220fa62Smrg  GLUhalfEdge	*Sym;		/* same edge, opposite direction */
141f220fa62Smrg  GLUhalfEdge	*Onext;		/* next edge CCW around origin */
142f220fa62Smrg  GLUhalfEdge	*Lnext;		/* next edge CCW around left face */
143f220fa62Smrg  GLUvertex	*Org;		/* origin vertex (Overtex too long) */
144f220fa62Smrg  GLUface	*Lface;		/* left face */
145f220fa62Smrg
146f220fa62Smrg  /* Internal data (keep hidden) */
147f220fa62Smrg  ActiveRegion	*activeRegion;	/* a region with this upper edge (sweep.c) */
148f220fa62Smrg  int		winding;	/* change in winding number when crossing
149f220fa62Smrg                                   from the right face to the left face */
150f220fa62Smrg};
151f220fa62Smrg
152f220fa62Smrg#define	Rface	Sym->Lface
153f220fa62Smrg#define Dst	Sym->Org
154f220fa62Smrg
155f220fa62Smrg#define Oprev	Sym->Lnext
156f220fa62Smrg#define Lprev   Onext->Sym
157f220fa62Smrg#define Dprev	Lnext->Sym
158f220fa62Smrg#define Rprev	Sym->Onext
159f220fa62Smrg#define Dnext	Rprev->Sym	/* 3 pointers */
160f220fa62Smrg#define Rnext	Oprev->Sym	/* 3 pointers */
161f220fa62Smrg
162f220fa62Smrg
163f220fa62Smrgstruct GLUmesh {
164f220fa62Smrg  GLUvertex	vHead;		/* dummy header for vertex list */
165f220fa62Smrg  GLUface	fHead;		/* dummy header for face list */
166f220fa62Smrg  GLUhalfEdge	eHead;		/* dummy header for edge list */
167f220fa62Smrg  GLUhalfEdge	eHeadSym;	/* and its symmetric counterpart */
168f220fa62Smrg};
169f220fa62Smrg
170f220fa62Smrg/* The mesh operations below have three motivations: completeness,
171f220fa62Smrg * convenience, and efficiency.  The basic mesh operations are MakeEdge,
172f220fa62Smrg * Splice, and Delete.  All the other edge operations can be implemented
173f220fa62Smrg * in terms of these.  The other operations are provided for convenience
174f220fa62Smrg * and/or efficiency.
175f220fa62Smrg *
176f220fa62Smrg * When a face is split or a vertex is added, they are inserted into the
177f220fa62Smrg * global list *before* the existing vertex or face (ie. e->Org or e->Lface).
178f220fa62Smrg * This makes it easier to process all vertices or faces in the global lists
179f220fa62Smrg * without worrying about processing the same data twice.  As a convenience,
180f220fa62Smrg * when a face is split, the "inside" flag is copied from the old face.
181f220fa62Smrg * Other internal data (v->data, v->activeRegion, f->data, f->marked,
182f220fa62Smrg * f->trail, e->winding) is set to zero.
183f220fa62Smrg *
184f220fa62Smrg * ********************** Basic Edge Operations **************************
185f220fa62Smrg *
186f220fa62Smrg * __gl_meshMakeEdge( mesh ) creates one edge, two vertices, and a loop.
187f220fa62Smrg * The loop (face) consists of the two new half-edges.
188f220fa62Smrg *
189f220fa62Smrg * __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the
190f220fa62Smrg * mesh connectivity and topology.  It changes the mesh so that
191f220fa62Smrg *	eOrg->Onext <- OLD( eDst->Onext )
192f220fa62Smrg *	eDst->Onext <- OLD( eOrg->Onext )
193f220fa62Smrg * where OLD(...) means the value before the meshSplice operation.
194f220fa62Smrg *
195f220fa62Smrg * This can have two effects on the vertex structure:
196f220fa62Smrg *  - if eOrg->Org != eDst->Org, the two vertices are merged together
197f220fa62Smrg *  - if eOrg->Org == eDst->Org, the origin is split into two vertices
198f220fa62Smrg * In both cases, eDst->Org is changed and eOrg->Org is untouched.
199f220fa62Smrg *
200f220fa62Smrg * Similarly (and independently) for the face structure,
201f220fa62Smrg *  - if eOrg->Lface == eDst->Lface, one loop is split into two
202f220fa62Smrg *  - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one
203f220fa62Smrg * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected.
204f220fa62Smrg *
205f220fa62Smrg * __gl_meshDelete( eDel ) removes the edge eDel.  There are several cases:
206f220fa62Smrg * if (eDel->Lface != eDel->Rface), we join two loops into one; the loop
207f220fa62Smrg * eDel->Lface is deleted.  Otherwise, we are splitting one loop into two;
208f220fa62Smrg * the newly created loop will contain eDel->Dst.  If the deletion of eDel
209f220fa62Smrg * would create isolated vertices, those are deleted as well.
210f220fa62Smrg *
211f220fa62Smrg * ********************** Other Edge Operations **************************
212f220fa62Smrg *
213f220fa62Smrg * __gl_meshAddEdgeVertex( eOrg ) creates a new edge eNew such that
214f220fa62Smrg * eNew == eOrg->Lnext, and eNew->Dst is a newly created vertex.
215f220fa62Smrg * eOrg and eNew will have the same left face.
216f220fa62Smrg *
217f220fa62Smrg * __gl_meshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew,
218f220fa62Smrg * such that eNew == eOrg->Lnext.  The new vertex is eOrg->Dst == eNew->Org.
219f220fa62Smrg * eOrg and eNew will have the same left face.
220f220fa62Smrg *
221f220fa62Smrg * __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg->Dst
222f220fa62Smrg * to eDst->Org, and returns the corresponding half-edge eNew.
223f220fa62Smrg * If eOrg->Lface == eDst->Lface, this splits one loop into two,
224f220fa62Smrg * and the newly created loop is eNew->Lface.  Otherwise, two disjoint
225f220fa62Smrg * loops are merged into one, and the loop eDst->Lface is destroyed.
226f220fa62Smrg *
227f220fa62Smrg * ************************ Other Operations *****************************
228f220fa62Smrg *
229f220fa62Smrg * __gl_meshNewMesh() creates a new mesh with no edges, no vertices,
230f220fa62Smrg * and no loops (what we usually call a "face").
231f220fa62Smrg *
232f220fa62Smrg * __gl_meshUnion( mesh1, mesh2 ) forms the union of all structures in
233f220fa62Smrg * both meshes, and returns the new mesh (the old meshes are destroyed).
234f220fa62Smrg *
235f220fa62Smrg * __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh.
236f220fa62Smrg *
237f220fa62Smrg * __gl_meshZapFace( fZap ) destroys a face and removes it from the
238f220fa62Smrg * global face list.  All edges of fZap will have a NULL pointer as their
239f220fa62Smrg * left face.  Any edges which also have a NULL pointer as their right face
240f220fa62Smrg * are deleted entirely (along with any isolated vertices this produces).
241f220fa62Smrg * An entire mesh can be deleted by zapping its faces, one at a time,
242f220fa62Smrg * in any order.  Zapped faces cannot be used in further mesh operations!
243f220fa62Smrg *
244f220fa62Smrg * __gl_meshCheckMesh( mesh ) checks a mesh for self-consistency.
245f220fa62Smrg */
246f220fa62Smrg
247f220fa62SmrgGLUhalfEdge	*__gl_meshMakeEdge( GLUmesh *mesh );
248f220fa62Smrgint		__gl_meshSplice( GLUhalfEdge *eOrg, GLUhalfEdge *eDst );
249f220fa62Smrgint		__gl_meshDelete( GLUhalfEdge *eDel );
250f220fa62Smrg
251f220fa62SmrgGLUhalfEdge	*__gl_meshAddEdgeVertex( GLUhalfEdge *eOrg );
252f220fa62SmrgGLUhalfEdge	*__gl_meshSplitEdge( GLUhalfEdge *eOrg );
253f220fa62SmrgGLUhalfEdge	*__gl_meshConnect( GLUhalfEdge *eOrg, GLUhalfEdge *eDst );
254f220fa62Smrg
255f220fa62SmrgGLUmesh		*__gl_meshNewMesh( void );
256f220fa62SmrgGLUmesh		*__gl_meshUnion( GLUmesh *mesh1, GLUmesh *mesh2 );
257f220fa62Smrgvoid		__gl_meshDeleteMesh( GLUmesh *mesh );
258f220fa62Smrgvoid		__gl_meshZapFace( GLUface *fZap );
259f220fa62Smrg
260f220fa62Smrg#ifdef NDEBUG
261f220fa62Smrg#define		__gl_meshCheckMesh( mesh )
262f220fa62Smrg#else
263f220fa62Smrgvoid		__gl_meshCheckMesh( GLUmesh *mesh );
264f220fa62Smrg#endif
265f220fa62Smrg
266f220fa62Smrg#endif
267