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