| 1 | /* $Id: mesh.h,v 1.1 2000-02-09 08:47:35 jeroen Exp $ */
|
|---|
| 2 | /*
|
|---|
| 3 | ** License Applicability. Except to the extent portions of this file are
|
|---|
| 4 | ** made subject to an alternative license as permitted in the SGI Free
|
|---|
| 5 | ** Software License B, Version 1.0 (the "License"), the contents of this
|
|---|
| 6 | ** file are subject only to the provisions of the License. You may not use
|
|---|
| 7 | ** this file except in compliance with the License. You may obtain a copy
|
|---|
| 8 | ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
|
|---|
| 9 | ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
|
|---|
| 10 | **
|
|---|
| 11 | ** http://oss.sgi.com/projects/FreeB
|
|---|
| 12 | **
|
|---|
| 13 | ** Note that, as provided in the License, the Software is distributed on an
|
|---|
| 14 | ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
|
|---|
| 15 | ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
|
|---|
| 16 | ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
|
|---|
| 17 | ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
|
|---|
| 18 | **
|
|---|
| 19 | ** Original Code. The Original Code is: OpenGL Sample Implementation,
|
|---|
| 20 | ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
|
|---|
| 21 | ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
|
|---|
| 22 | ** Copyright in any portions created by third parties is as indicated
|
|---|
| 23 | ** elsewhere herein. All Rights Reserved.
|
|---|
| 24 | **
|
|---|
| 25 | ** Additional Notice Provisions: The application programming interfaces
|
|---|
| 26 | ** established by SGI in conjunction with the Original Code are The
|
|---|
| 27 | ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
|
|---|
| 28 | ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
|
|---|
| 29 | ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
|
|---|
| 30 | ** Window System(R) (Version 1.3), released October 19, 1998. This software
|
|---|
| 31 | ** was created using the OpenGL(R) version 1.2.1 Sample Implementation
|
|---|
| 32 | ** published by SGI, but has not been independently verified as being
|
|---|
| 33 | ** compliant with the OpenGL(R) version 1.2.1 Specification.
|
|---|
| 34 | **
|
|---|
| 35 | */
|
|---|
| 36 | /*
|
|---|
| 37 | ** Author: Eric Veach, July 1994.
|
|---|
| 38 | **
|
|---|
| 39 | ** $Date: 2000-02-09 08:47:35 $ $Revision: 1.1 $
|
|---|
| 40 | ** $Header: /home/ktk/tmp/odin/2007/netlabs.cvs/odin32/src/opengl/glu/tess/mesh.h,v 1.1 2000-02-09 08:47:35 jeroen Exp $
|
|---|
| 41 | */
|
|---|
| 42 |
|
|---|
| 43 | #ifndef __mesh_h_
|
|---|
| 44 | #define __mesh_h_
|
|---|
| 45 |
|
|---|
| 46 | #include "glu.h"
|
|---|
| 47 |
|
|---|
| 48 | typedef struct GLUmesh GLUmesh;
|
|---|
| 49 |
|
|---|
| 50 | typedef struct GLUvertex GLUvertex;
|
|---|
| 51 | typedef struct GLUface GLUface;
|
|---|
| 52 | typedef struct GLUhalfEdge GLUhalfEdge;
|
|---|
| 53 |
|
|---|
| 54 | typedef struct ActiveRegion ActiveRegion; /* Internal data */
|
|---|
| 55 |
|
|---|
| 56 | /* The mesh structure is similar in spirit, notation, and operations
|
|---|
| 57 | * to the "quad-edge" structure (see L. Guibas and J. Stolfi, Primitives
|
|---|
| 58 | * for the manipulation of general subdivisions and the computation of
|
|---|
| 59 | * Voronoi diagrams, ACM Transactions on Graphics, 4(2):74-123, April 1985).
|
|---|
| 60 | * For a simplified description, see the course notes for CS348a,
|
|---|
| 61 | * "Mathematical Foundations of Computer Graphics", available at the
|
|---|
| 62 | * Stanford bookstore (and taught during the fall quarter).
|
|---|
| 63 | * The implementation also borrows a tiny subset of the graph-based approach
|
|---|
| 64 | * use in Mantyla's Geometric Work Bench (see M. Mantyla, An Introduction
|
|---|
| 65 | * to Sold Modeling, Computer Science Press, Rockville, Maryland, 1988).
|
|---|
| 66 | *
|
|---|
| 67 | * The fundamental data structure is the "half-edge". Two half-edges
|
|---|
| 68 | * go together to make an edge, but they point in opposite directions.
|
|---|
| 69 | * Each half-edge has a pointer to its mate (the "symmetric" half-edge Sym),
|
|---|
| 70 | * its origin vertex (Org), the face on its left side (Lface), and the
|
|---|
| 71 | * adjacent half-edges in the CCW direction around the origin vertex
|
|---|
| 72 | * (Onext) and around the left face (Lnext). There is also a "next"
|
|---|
| 73 | * pointer for the global edge list (see below).
|
|---|
| 74 | *
|
|---|
| 75 | * The notation used for mesh navigation:
|
|---|
| 76 | * Sym = the mate of a half-edge (same edge, but opposite direction)
|
|---|
| 77 | * Onext = edge CCW around origin vertex (keep same origin)
|
|---|
| 78 | * Dnext = edge CCW around destination vertex (keep same dest)
|
|---|
| 79 | * Lnext = edge CCW around left face (dest becomes new origin)
|
|---|
| 80 | * Rnext = edge CCW around right face (origin becomes new dest)
|
|---|
| 81 | *
|
|---|
| 82 | * "prev" means to substitute CW for CCW in the definitions above.
|
|---|
| 83 | *
|
|---|
| 84 | * The mesh keeps global lists of all vertices, faces, and edges,
|
|---|
| 85 | * stored as doubly-linked circular lists with a dummy header node.
|
|---|
| 86 | * The mesh stores pointers to these dummy headers (vHead, fHead, eHead).
|
|---|
| 87 | *
|
|---|
| 88 | * The circular edge list is special; since half-edges always occur
|
|---|
| 89 | * in pairs (e and e->Sym), each half-edge stores a pointer in only
|
|---|
| 90 | * one direction. Starting at eHead and following the e->next pointers
|
|---|
| 91 | * will visit each *edge* once (ie. e or e->Sym, but not both).
|
|---|
| 92 | * e->Sym stores a pointer in the opposite direction, thus it is
|
|---|
| 93 | * always true that e->Sym->next->Sym->next == e.
|
|---|
| 94 | *
|
|---|
| 95 | * Each vertex has a pointer to next and previous vertices in the
|
|---|
| 96 | * circular list, and a pointer to a half-edge with this vertex as
|
|---|
| 97 | * the origin (NULL if this is the dummy header). There is also a
|
|---|
| 98 | * field "data" for client data.
|
|---|
| 99 | *
|
|---|
| 100 | * Each face has a pointer to the next and previous faces in the
|
|---|
| 101 | * circular list, and a pointer to a half-edge with this face as
|
|---|
| 102 | * the left face (NULL if this is the dummy header). There is also
|
|---|
| 103 | * a field "data" for client data.
|
|---|
| 104 | *
|
|---|
| 105 | * Note that what we call a "face" is really a loop; faces may consist
|
|---|
| 106 | * of more than one loop (ie. not simply connected), but there is no
|
|---|
| 107 | * record of this in the data structure. The mesh may consist of
|
|---|
| 108 | * several disconnected regions, so it may not be possible to visit
|
|---|
| 109 | * the entire mesh by starting at a half-edge and traversing the edge
|
|---|
| 110 | * structure.
|
|---|
| 111 | *
|
|---|
| 112 | * The mesh does NOT support isolated vertices; a vertex is deleted along
|
|---|
| 113 | * with its last edge. Similarly when two faces are merged, one of the
|
|---|
| 114 | * faces is deleted (see __gl_meshDelete below). For mesh operations,
|
|---|
| 115 | * all face (loop) and vertex pointers must not be NULL. However, once
|
|---|
| 116 | * mesh manipulation is finished, __gl_MeshZapFace can be used to delete
|
|---|
| 117 | * faces of the mesh, one at a time. All external faces can be "zapped"
|
|---|
| 118 | * before the mesh is returned to the client; then a NULL face indicates
|
|---|
| 119 | * a region which is not part of the output polygon.
|
|---|
| 120 | */
|
|---|
| 121 |
|
|---|
| 122 | struct GLUvertex {
|
|---|
| 123 | GLUvertex *next; /* next vertex (never NULL) */
|
|---|
| 124 | GLUvertex *prev; /* previous vertex (never NULL) */
|
|---|
| 125 | GLUhalfEdge *anEdge; /* a half-edge with this origin */
|
|---|
| 126 | void *data; /* client's data */
|
|---|
| 127 |
|
|---|
| 128 | /* Internal data (keep hidden) */
|
|---|
| 129 | GLdouble coords[3]; /* vertex location in 3D */
|
|---|
| 130 | GLdouble s, t; /* projection onto the sweep plane */
|
|---|
| 131 | long pqHandle; /* to allow deletion from priority queue */
|
|---|
| 132 | };
|
|---|
| 133 |
|
|---|
| 134 | struct GLUface {
|
|---|
| 135 | GLUface *next; /* next face (never NULL) */
|
|---|
| 136 | GLUface *prev; /* previous face (never NULL) */
|
|---|
| 137 | GLUhalfEdge *anEdge; /* a half edge with this left face */
|
|---|
| 138 | void *data; /* room for client's data */
|
|---|
| 139 |
|
|---|
| 140 | /* Internal data (keep hidden) */
|
|---|
| 141 | GLUface *trail; /* "stack" for conversion to strips */
|
|---|
| 142 | GLboolean marked; /* flag for conversion to strips */
|
|---|
| 143 | GLboolean inside; /* this face is in the polygon interior */
|
|---|
| 144 | };
|
|---|
| 145 |
|
|---|
| 146 | struct GLUhalfEdge {
|
|---|
| 147 | GLUhalfEdge *next; /* doubly-linked list (prev==Sym->next) */
|
|---|
| 148 | GLUhalfEdge *Sym; /* same edge, opposite direction */
|
|---|
| 149 | GLUhalfEdge *Onext; /* next edge CCW around origin */
|
|---|
| 150 | GLUhalfEdge *Lnext; /* next edge CCW around left face */
|
|---|
| 151 | GLUvertex *Org; /* origin vertex (Overtex too long) */
|
|---|
| 152 | GLUface *Lface; /* left face */
|
|---|
| 153 |
|
|---|
| 154 | /* Internal data (keep hidden) */
|
|---|
| 155 | ActiveRegion *activeRegion; /* a region with this upper edge (sweep.c) */
|
|---|
| 156 | int winding; /* change in winding number when crossing
|
|---|
| 157 | from the right face to the left face */
|
|---|
| 158 | };
|
|---|
| 159 |
|
|---|
| 160 | #define Rface Sym->Lface
|
|---|
| 161 | #define Dst Sym->Org
|
|---|
| 162 |
|
|---|
| 163 | #define Oprev Sym->Lnext
|
|---|
| 164 | #define Lprev Onext->Sym
|
|---|
| 165 | #define Dprev Lnext->Sym
|
|---|
| 166 | #define Rprev Sym->Onext
|
|---|
| 167 | #define Dnext Rprev->Sym /* 3 pointers */
|
|---|
| 168 | #define Rnext Oprev->Sym /* 3 pointers */
|
|---|
| 169 |
|
|---|
| 170 |
|
|---|
| 171 | struct GLUmesh {
|
|---|
| 172 | GLUvertex vHead; /* dummy header for vertex list */
|
|---|
| 173 | GLUface fHead; /* dummy header for face list */
|
|---|
| 174 | GLUhalfEdge eHead; /* dummy header for edge list */
|
|---|
| 175 | GLUhalfEdge eHeadSym; /* and its symmetric counterpart */
|
|---|
| 176 | };
|
|---|
| 177 |
|
|---|
| 178 | /* The mesh operations below have three motivations: completeness,
|
|---|
| 179 | * convenience, and efficiency. The basic mesh operations are MakeEdge,
|
|---|
| 180 | * Splice, and Delete. All the other edge operations can be implemented
|
|---|
| 181 | * in terms of these. The other operations are provided for convenience
|
|---|
| 182 | * and/or efficiency.
|
|---|
| 183 | *
|
|---|
| 184 | * When a face is split or a vertex is added, they are inserted into the
|
|---|
| 185 | * global list *before* the existing vertex or face (ie. e->Org or e->Lface).
|
|---|
| 186 | * This makes it easier to process all vertices or faces in the global lists
|
|---|
| 187 | * without worrying about processing the same data twice. As a convenience,
|
|---|
| 188 | * when a face is split, the "inside" flag is copied from the old face.
|
|---|
| 189 | * Other internal data (v->data, v->activeRegion, f->data, f->marked,
|
|---|
| 190 | * f->trail, e->winding) is set to zero.
|
|---|
| 191 | *
|
|---|
| 192 | * ********************** Basic Edge Operations **************************
|
|---|
| 193 | *
|
|---|
| 194 | * __gl_meshMakeEdge( mesh ) creates one edge, two vertices, and a loop.
|
|---|
| 195 | * The loop (face) consists of the two new half-edges.
|
|---|
| 196 | *
|
|---|
| 197 | * __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the
|
|---|
| 198 | * mesh connectivity and topology. It changes the mesh so that
|
|---|
| 199 | * eOrg->Onext <- OLD( eDst->Onext )
|
|---|
| 200 | * eDst->Onext <- OLD( eOrg->Onext )
|
|---|
| 201 | * where OLD(...) means the value before the meshSplice operation.
|
|---|
| 202 | *
|
|---|
| 203 | * This can have two effects on the vertex structure:
|
|---|
| 204 | * - if eOrg->Org != eDst->Org, the two vertices are merged together
|
|---|
| 205 | * - if eOrg->Org == eDst->Org, the origin is split into two vertices
|
|---|
| 206 | * In both cases, eDst->Org is changed and eOrg->Org is untouched.
|
|---|
| 207 | *
|
|---|
| 208 | * Similarly (and independently) for the face structure,
|
|---|
| 209 | * - if eOrg->Lface == eDst->Lface, one loop is split into two
|
|---|
| 210 | * - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one
|
|---|
| 211 | * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected.
|
|---|
| 212 | *
|
|---|
| 213 | * __gl_meshDelete( eDel ) removes the edge eDel. There are several cases:
|
|---|
| 214 | * if (eDel->Lface != eDel->Rface), we join two loops into one; the loop
|
|---|
| 215 | * eDel->Lface is deleted. Otherwise, we are splitting one loop into two;
|
|---|
| 216 | * the newly created loop will contain eDel->Dst. If the deletion of eDel
|
|---|
| 217 | * would create isolated vertices, those are deleted as well.
|
|---|
| 218 | *
|
|---|
| 219 | * ********************** Other Edge Operations **************************
|
|---|
| 220 | *
|
|---|
| 221 | * __gl_meshAddEdgeVertex( eOrg ) creates a new edge eNew such that
|
|---|
| 222 | * eNew == eOrg->Lnext, and eNew->Dst is a newly created vertex.
|
|---|
| 223 | * eOrg and eNew will have the same left face.
|
|---|
| 224 | *
|
|---|
| 225 | * __gl_meshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew,
|
|---|
| 226 | * such that eNew == eOrg->Lnext. The new vertex is eOrg->Dst == eNew->Org.
|
|---|
| 227 | * eOrg and eNew will have the same left face.
|
|---|
| 228 | *
|
|---|
| 229 | * __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg->Dst
|
|---|
| 230 | * to eDst->Org, and returns the corresponding half-edge eNew.
|
|---|
| 231 | * If eOrg->Lface == eDst->Lface, this splits one loop into two,
|
|---|
| 232 | * and the newly created loop is eNew->Lface. Otherwise, two disjoint
|
|---|
| 233 | * loops are merged into one, and the loop eDst->Lface is destroyed.
|
|---|
| 234 | *
|
|---|
| 235 | * ************************ Other Operations *****************************
|
|---|
| 236 | *
|
|---|
| 237 | * __gl_meshNewMesh() creates a new mesh with no edges, no vertices,
|
|---|
| 238 | * and no loops (what we usually call a "face").
|
|---|
| 239 | *
|
|---|
| 240 | * __gl_meshUnion( mesh1, mesh2 ) forms the union of all structures in
|
|---|
| 241 | * both meshes, and returns the new mesh (the old meshes are destroyed).
|
|---|
| 242 | *
|
|---|
| 243 | * __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh.
|
|---|
| 244 | *
|
|---|
| 245 | * __gl_meshZapFace( fZap ) destroys a face and removes it from the
|
|---|
| 246 | * global face list. All edges of fZap will have a NULL pointer as their
|
|---|
| 247 | * left face. Any edges which also have a NULL pointer as their right face
|
|---|
| 248 | * are deleted entirely (along with any isolated vertices this produces).
|
|---|
| 249 | * An entire mesh can be deleted by zapping its faces, one at a time,
|
|---|
| 250 | * in any order. Zapped faces cannot be used in further mesh operations!
|
|---|
| 251 | *
|
|---|
| 252 | * __gl_meshCheckMesh( mesh ) checks a mesh for self-consistency.
|
|---|
| 253 | */
|
|---|
| 254 |
|
|---|
| 255 | GLUhalfEdge *__gl_meshMakeEdge( GLUmesh *mesh );
|
|---|
| 256 | int __gl_meshSplice( GLUhalfEdge *eOrg, GLUhalfEdge *eDst );
|
|---|
| 257 | int __gl_meshDelete( GLUhalfEdge *eDel );
|
|---|
| 258 |
|
|---|
| 259 | GLUhalfEdge *__gl_meshAddEdgeVertex( GLUhalfEdge *eOrg );
|
|---|
| 260 | GLUhalfEdge *__gl_meshSplitEdge( GLUhalfEdge *eOrg );
|
|---|
| 261 | GLUhalfEdge *__gl_meshConnect( GLUhalfEdge *eOrg, GLUhalfEdge *eDst );
|
|---|
| 262 |
|
|---|
| 263 | GLUmesh *__gl_meshNewMesh( void );
|
|---|
| 264 | GLUmesh *__gl_meshUnion( GLUmesh *mesh1, GLUmesh *mesh2 );
|
|---|
| 265 | void __gl_meshDeleteMesh( GLUmesh *mesh );
|
|---|
| 266 | void __gl_meshZapFace( GLUface *fZap );
|
|---|
| 267 |
|
|---|
| 268 | #ifdef NDEBUG
|
|---|
| 269 | #define __gl_meshCheckMesh( mesh )
|
|---|
| 270 | #else
|
|---|
| 271 | void __gl_meshCheckMesh( GLUmesh *mesh );
|
|---|
| 272 | #endif
|
|---|
| 273 |
|
|---|
| 274 | #endif
|
|---|