ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

mesh.c
Go to the documentation of this file.
00001 /*
00002 ** License Applicability. Except to the extent portions of this file are
00003 ** made subject to an alternative license as permitted in the SGI Free
00004 ** Software License B, Version 1.1 (the "License"), the contents of this
00005 ** file are subject only to the provisions of the License. You may not use
00006 ** this file except in compliance with the License. You may obtain a copy
00007 ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
00008 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
00009 **
00010 ** http://oss.sgi.com/projects/FreeB
00011 **
00012 ** Note that, as provided in the License, the Software is distributed on an
00013 ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
00014 ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
00015 ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
00016 ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
00017 **
00018 ** Original Code. The Original Code is: OpenGL Sample Implementation,
00019 ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
00020 ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
00021 ** Copyright in any portions created by third parties is as indicated
00022 ** elsewhere herein. All Rights Reserved.
00023 **
00024 ** Additional Notice Provisions: The application programming interfaces
00025 ** established by SGI in conjunction with the Original Code are The
00026 ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
00027 ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
00028 ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
00029 ** Window System(R) (Version 1.3), released October 19, 1998. This software
00030 ** was created using the OpenGL(R) version 1.2.1 Sample Implementation
00031 ** published by SGI, but has not been independently verified as being
00032 ** compliant with the OpenGL(R) version 1.2.1 Specification.
00033 **
00034 */
00035 /*
00036 ** Author: Eric Veach, July 1994.
00037 **
00038 ** $Date: 2007-10-19 23:21:45 +0000 (Fri, 19 Oct 2007) $ $Revision: 1.1 $
00039 ** $Header: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/glu32/libtess/mesh.c,v 1.1 2004/02/02 16:39:15 navaraf Exp $
00040 */
00041 
00042 #include "gluos.h"
00043 #include <stddef.h>
00044 #include <assert.h>
00045 #include "mesh.h"
00046 #include "memalloc.h"
00047 
00048 #define TRUE 1
00049 #define FALSE 0
00050 
00051 static GLUvertex *allocVertex()
00052 {
00053    return (GLUvertex *)memAlloc( sizeof( GLUvertex ));
00054 }
00055 
00056 static GLUface *allocFace()
00057 {
00058    return (GLUface *)memAlloc( sizeof( GLUface ));
00059 }
00060 
00061 /************************ Utility Routines ************************/
00062 
00063 /* Allocate and free half-edges in pairs for efficiency.
00064  * The *only* place that should use this fact is allocation/free.
00065  */
00066 typedef struct { GLUhalfEdge e, eSym; } EdgePair;
00067 
00068 /* MakeEdge creates a new pair of half-edges which form their own loop.
00069  * No vertex or face structures are allocated, but these must be assigned
00070  * before the current edge operation is completed.
00071  */
00072 static GLUhalfEdge *MakeEdge( GLUhalfEdge *eNext )
00073 {
00074   GLUhalfEdge *e;
00075   GLUhalfEdge *eSym;
00076   GLUhalfEdge *ePrev;
00077   EdgePair *pair = (EdgePair *)memAlloc( sizeof( EdgePair ));
00078   if (pair == NULL) return NULL;
00079 
00080   e = &pair->e;
00081   eSym = &pair->eSym;
00082 
00083   /* Make sure eNext points to the first edge of the edge pair */
00084   if( eNext->Sym < eNext ) { eNext = eNext->Sym; }
00085 
00086   /* Insert in circular doubly-linked list before eNext.
00087    * Note that the prev pointer is stored in Sym->next.
00088    */
00089   ePrev = eNext->Sym->next;
00090   eSym->next = ePrev;
00091   ePrev->Sym->next = e;
00092   e->next = eNext;
00093   eNext->Sym->next = eSym;
00094 
00095   e->Sym = eSym;
00096   e->Onext = e;
00097   e->Lnext = eSym;
00098   e->Org = NULL;
00099   e->Lface = NULL;
00100   e->winding = 0;
00101   e->activeRegion = NULL;
00102 
00103   eSym->Sym = e;
00104   eSym->Onext = eSym;
00105   eSym->Lnext = e;
00106   eSym->Org = NULL;
00107   eSym->Lface = NULL;
00108   eSym->winding = 0;
00109   eSym->activeRegion = NULL;
00110 
00111   return e;
00112 }
00113 
00114 /* Splice( a, b ) is best described by the Guibas/Stolfi paper or the
00115  * CS348a notes (see mesh.h).  Basically it modifies the mesh so that
00116  * a->Onext and b->Onext are exchanged.  This can have various effects
00117  * depending on whether a and b belong to different face or vertex rings.
00118  * For more explanation see __gl_meshSplice() below.
00119  */
00120 static void Splice( GLUhalfEdge *a, GLUhalfEdge *b )
00121 {
00122   GLUhalfEdge *aOnext = a->Onext;
00123   GLUhalfEdge *bOnext = b->Onext;
00124 
00125   aOnext->Sym->Lnext = b;
00126   bOnext->Sym->Lnext = a;
00127   a->Onext = bOnext;
00128   b->Onext = aOnext;
00129 }
00130 
00131 /* MakeVertex( newVertex, eOrig, vNext ) attaches a new vertex and makes it the
00132  * origin of all edges in the vertex loop to which eOrig belongs. "vNext" gives
00133  * a place to insert the new vertex in the global vertex list.  We insert
00134  * the new vertex *before* vNext so that algorithms which walk the vertex
00135  * list will not see the newly created vertices.
00136  */
00137 static void MakeVertex( GLUvertex *newVertex,
00138             GLUhalfEdge *eOrig, GLUvertex *vNext )
00139 {
00140   GLUhalfEdge *e;
00141   GLUvertex *vPrev;
00142   GLUvertex *vNew = newVertex;
00143 
00144   assert(vNew != NULL);
00145 
00146   /* insert in circular doubly-linked list before vNext */
00147   vPrev = vNext->prev;
00148   vNew->prev = vPrev;
00149   vPrev->next = vNew;
00150   vNew->next = vNext;
00151   vNext->prev = vNew;
00152 
00153   vNew->anEdge = eOrig;
00154   vNew->data = NULL;
00155   /* leave coords, s, t undefined */
00156 
00157   /* fix other edges on this vertex loop */
00158   e = eOrig;
00159   do {
00160     e->Org = vNew;
00161     e = e->Onext;
00162   } while( e != eOrig );
00163 }
00164 
00165 /* MakeFace( newFace, eOrig, fNext ) attaches a new face and makes it the left
00166  * face of all edges in the face loop to which eOrig belongs.  "fNext" gives
00167  * a place to insert the new face in the global face list.  We insert
00168  * the new face *before* fNext so that algorithms which walk the face
00169  * list will not see the newly created faces.
00170  */
00171 static void MakeFace( GLUface *newFace, GLUhalfEdge *eOrig, GLUface *fNext )
00172 {
00173   GLUhalfEdge *e;
00174   GLUface *fPrev;
00175   GLUface *fNew = newFace;
00176 
00177   assert(fNew != NULL);
00178 
00179   /* insert in circular doubly-linked list before fNext */
00180   fPrev = fNext->prev;
00181   fNew->prev = fPrev;
00182   fPrev->next = fNew;
00183   fNew->next = fNext;
00184   fNext->prev = fNew;
00185 
00186   fNew->anEdge = eOrig;
00187   fNew->data = NULL;
00188   fNew->trail = NULL;
00189   fNew->marked = FALSE;
00190 
00191   /* The new face is marked "inside" if the old one was.  This is a
00192    * convenience for the common case where a face has been split in two.
00193    */
00194   fNew->inside = fNext->inside;
00195 
00196   /* fix other edges on this face loop */
00197   e = eOrig;
00198   do {
00199     e->Lface = fNew;
00200     e = e->Lnext;
00201   } while( e != eOrig );
00202 }
00203 
00204 /* KillEdge( eDel ) destroys an edge (the half-edges eDel and eDel->Sym),
00205  * and removes from the global edge list.
00206  */
00207 static void KillEdge( GLUhalfEdge *eDel )
00208 {
00209   GLUhalfEdge *ePrev, *eNext;
00210 
00211   /* Half-edges are allocated in pairs, see EdgePair above */
00212   if( eDel->Sym < eDel ) { eDel = eDel->Sym; }
00213 
00214   /* delete from circular doubly-linked list */
00215   eNext = eDel->next;
00216   ePrev = eDel->Sym->next;
00217   eNext->Sym->next = ePrev;
00218   ePrev->Sym->next = eNext;
00219 
00220   memFree( eDel );
00221 }
00222 
00223 
00224 /* KillVertex( vDel ) destroys a vertex and removes it from the global
00225  * vertex list.  It updates the vertex loop to point to a given new vertex.
00226  */
00227 static void KillVertex( GLUvertex *vDel, GLUvertex *newOrg )
00228 {
00229   GLUhalfEdge *e, *eStart = vDel->anEdge;
00230   GLUvertex *vPrev, *vNext;
00231 
00232   /* change the origin of all affected edges */
00233   e = eStart;
00234   do {
00235     e->Org = newOrg;
00236     e = e->Onext;
00237   } while( e != eStart );
00238 
00239   /* delete from circular doubly-linked list */
00240   vPrev = vDel->prev;
00241   vNext = vDel->next;
00242   vNext->prev = vPrev;
00243   vPrev->next = vNext;
00244 
00245   memFree( vDel );
00246 }
00247 
00248 /* KillFace( fDel ) destroys a face and removes it from the global face
00249  * list.  It updates the face loop to point to a given new face.
00250  */
00251 static void KillFace( GLUface *fDel, GLUface *newLface )
00252 {
00253   GLUhalfEdge *e, *eStart = fDel->anEdge;
00254   GLUface *fPrev, *fNext;
00255 
00256   /* change the left face of all affected edges */
00257   e = eStart;
00258   do {
00259     e->Lface = newLface;
00260     e = e->Lnext;
00261   } while( e != eStart );
00262 
00263   /* delete from circular doubly-linked list */
00264   fPrev = fDel->prev;
00265   fNext = fDel->next;
00266   fNext->prev = fPrev;
00267   fPrev->next = fNext;
00268 
00269   memFree( fDel );
00270 }
00271 
00272 
00273 /****************** Basic Edge Operations **********************/
00274 
00275 /* __gl_meshMakeEdge creates one edge, two vertices, and a loop (face).
00276  * The loop consists of the two new half-edges.
00277  */
00278 GLUhalfEdge *__gl_meshMakeEdge( GLUmesh *mesh )
00279 {
00280   GLUvertex *newVertex1= allocVertex();
00281   GLUvertex *newVertex2= allocVertex();
00282   GLUface *newFace= allocFace();
00283   GLUhalfEdge *e;
00284 
00285   /* if any one is null then all get freed */
00286   if (newVertex1 == NULL || newVertex2 == NULL || newFace == NULL) {
00287      if (newVertex1 != NULL) memFree(newVertex1);
00288      if (newVertex2 != NULL) memFree(newVertex2);
00289      if (newFace != NULL) memFree(newFace);
00290      return NULL;
00291   }
00292 
00293   e = MakeEdge( &mesh->eHead );
00294   if (e == NULL) return NULL;
00295 
00296   MakeVertex( newVertex1, e, &mesh->vHead );
00297   MakeVertex( newVertex2, e->Sym, &mesh->vHead );
00298   MakeFace( newFace, e, &mesh->fHead );
00299   return e;
00300 }
00301 
00302 
00303 /* __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the
00304  * mesh connectivity and topology.  It changes the mesh so that
00305  *  eOrg->Onext <- OLD( eDst->Onext )
00306  *  eDst->Onext <- OLD( eOrg->Onext )
00307  * where OLD(...) means the value before the meshSplice operation.
00308  *
00309  * This can have two effects on the vertex structure:
00310  *  - if eOrg->Org != eDst->Org, the two vertices are merged together
00311  *  - if eOrg->Org == eDst->Org, the origin is split into two vertices
00312  * In both cases, eDst->Org is changed and eOrg->Org is untouched.
00313  *
00314  * Similarly (and independently) for the face structure,
00315  *  - if eOrg->Lface == eDst->Lface, one loop is split into two
00316  *  - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one
00317  * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected.
00318  *
00319  * Some special cases:
00320  * If eDst == eOrg, the operation has no effect.
00321  * If eDst == eOrg->Lnext, the new face will have a single edge.
00322  * If eDst == eOrg->Lprev, the old face will have a single edge.
00323  * If eDst == eOrg->Onext, the new vertex will have a single edge.
00324  * If eDst == eOrg->Oprev, the old vertex will have a single edge.
00325  */
00326 int __gl_meshSplice( GLUhalfEdge *eOrg, GLUhalfEdge *eDst )
00327 {
00328   int joiningLoops = FALSE;
00329   int joiningVertices = FALSE;
00330 
00331   if( eOrg == eDst ) return 1;
00332 
00333   if( eDst->Org != eOrg->Org ) {
00334     /* We are merging two disjoint vertices -- destroy eDst->Org */
00335     joiningVertices = TRUE;
00336     KillVertex( eDst->Org, eOrg->Org );
00337   }
00338   if( eDst->Lface != eOrg->Lface ) {
00339     /* We are connecting two disjoint loops -- destroy eDst->Lface */
00340     joiningLoops = TRUE;
00341     KillFace( eDst->Lface, eOrg->Lface );
00342   }
00343 
00344   /* Change the edge structure */
00345   Splice( eDst, eOrg );
00346 
00347   if( ! joiningVertices ) {
00348     GLUvertex *newVertex= allocVertex();
00349     if (newVertex == NULL) return 0;
00350 
00351     /* We split one vertex into two -- the new vertex is eDst->Org.
00352      * Make sure the old vertex points to a valid half-edge.
00353      */
00354     MakeVertex( newVertex, eDst, eOrg->Org );
00355     eOrg->Org->anEdge = eOrg;
00356   }
00357   if( ! joiningLoops ) {
00358     GLUface *newFace= allocFace();
00359     if (newFace == NULL) return 0;
00360 
00361     /* We split one loop into two -- the new loop is eDst->Lface.
00362      * Make sure the old face points to a valid half-edge.
00363      */
00364     MakeFace( newFace, eDst, eOrg->Lface );
00365     eOrg->Lface->anEdge = eOrg;
00366   }
00367 
00368   return 1;
00369 }
00370 
00371 
00372 /* __gl_meshDelete( eDel ) removes the edge eDel.  There are several cases:
00373  * if (eDel->Lface != eDel->Rface), we join two loops into one; the loop
00374  * eDel->Lface is deleted.  Otherwise, we are splitting one loop into two;
00375  * the newly created loop will contain eDel->Dst.  If the deletion of eDel
00376  * would create isolated vertices, those are deleted as well.
00377  *
00378  * This function could be implemented as two calls to __gl_meshSplice
00379  * plus a few calls to memFree, but this would allocate and delete
00380  * unnecessary vertices and faces.
00381  */
00382 int __gl_meshDelete( GLUhalfEdge *eDel )
00383 {
00384   GLUhalfEdge *eDelSym = eDel->Sym;
00385   int joiningLoops = FALSE;
00386 
00387   /* First step: disconnect the origin vertex eDel->Org.  We make all
00388    * changes to get a consistent mesh in this "intermediate" state.
00389    */
00390   if( eDel->Lface != eDel->Rface ) {
00391     /* We are joining two loops into one -- remove the left face */
00392     joiningLoops = TRUE;
00393     KillFace( eDel->Lface, eDel->Rface );
00394   }
00395 
00396   if( eDel->Onext == eDel ) {
00397     KillVertex( eDel->Org, NULL );
00398   } else {
00399     /* Make sure that eDel->Org and eDel->Rface point to valid half-edges */
00400     eDel->Rface->anEdge = eDel->Oprev;
00401     eDel->Org->anEdge = eDel->Onext;
00402 
00403     Splice( eDel, eDel->Oprev );
00404     if( ! joiningLoops ) {
00405       GLUface *newFace= allocFace();
00406       if (newFace == NULL) return 0;
00407 
00408       /* We are splitting one loop into two -- create a new loop for eDel. */
00409       MakeFace( newFace, eDel, eDel->Lface );
00410     }
00411   }
00412 
00413   /* Claim: the mesh is now in a consistent state, except that eDel->Org
00414    * may have been deleted.  Now we disconnect eDel->Dst.
00415    */
00416   if( eDelSym->Onext == eDelSym ) {
00417     KillVertex( eDelSym->Org, NULL );
00418     KillFace( eDelSym->Lface, NULL );
00419   } else {
00420     /* Make sure that eDel->Dst and eDel->Lface point to valid half-edges */
00421     eDel->Lface->anEdge = eDelSym->Oprev;
00422     eDelSym->Org->anEdge = eDelSym->Onext;
00423     Splice( eDelSym, eDelSym->Oprev );
00424   }
00425 
00426   /* Any isolated vertices or faces have already been freed. */
00427   KillEdge( eDel );
00428 
00429   return 1;
00430 }
00431 
00432 
00433 /******************** Other Edge Operations **********************/
00434 
00435 /* All these routines can be implemented with the basic edge
00436  * operations above.  They are provided for convenience and efficiency.
00437  */
00438 
00439 
00440 /* __gl_meshAddEdgeVertex( eOrg ) creates a new edge eNew such that
00441  * eNew == eOrg->Lnext, and eNew->Dst is a newly created vertex.
00442  * eOrg and eNew will have the same left face.
00443  */
00444 GLUhalfEdge *__gl_meshAddEdgeVertex( GLUhalfEdge *eOrg )
00445 {
00446   GLUhalfEdge *eNewSym;
00447   GLUhalfEdge *eNew = MakeEdge( eOrg );
00448   if (eNew == NULL) return NULL;
00449 
00450   eNewSym = eNew->Sym;
00451 
00452   /* Connect the new edge appropriately */
00453   Splice( eNew, eOrg->Lnext );
00454 
00455   /* Set the vertex and face information */
00456   eNew->Org = eOrg->Dst;
00457   {
00458     GLUvertex *newVertex= allocVertex();
00459     if (newVertex == NULL) return NULL;
00460 
00461     MakeVertex( newVertex, eNewSym, eNew->Org );
00462   }
00463   eNew->Lface = eNewSym->Lface = eOrg->Lface;
00464 
00465   return eNew;
00466 }
00467 
00468 
00469 /* __gl_meshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew,
00470  * such that eNew == eOrg->Lnext.  The new vertex is eOrg->Dst == eNew->Org.
00471  * eOrg and eNew will have the same left face.
00472  */
00473 GLUhalfEdge *__gl_meshSplitEdge( GLUhalfEdge *eOrg )
00474 {
00475   GLUhalfEdge *eNew;
00476   GLUhalfEdge *tempHalfEdge= __gl_meshAddEdgeVertex( eOrg );
00477   if (tempHalfEdge == NULL) return NULL;
00478 
00479   eNew = tempHalfEdge->Sym;
00480 
00481   /* Disconnect eOrg from eOrg->Dst and connect it to eNew->Org */
00482   Splice( eOrg->Sym, eOrg->Sym->Oprev );
00483   Splice( eOrg->Sym, eNew );
00484 
00485   /* Set the vertex and face information */
00486   eOrg->Dst = eNew->Org;
00487   eNew->Dst->anEdge = eNew->Sym;    /* may have pointed to eOrg->Sym */
00488   eNew->Rface = eOrg->Rface;
00489   eNew->winding = eOrg->winding;    /* copy old winding information */
00490   eNew->Sym->winding = eOrg->Sym->winding;
00491 
00492   return eNew;
00493 }
00494 
00495 
00496 /* __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg->Dst
00497  * to eDst->Org, and returns the corresponding half-edge eNew.
00498  * If eOrg->Lface == eDst->Lface, this splits one loop into two,
00499  * and the newly created loop is eNew->Lface.  Otherwise, two disjoint
00500  * loops are merged into one, and the loop eDst->Lface is destroyed.
00501  *
00502  * If (eOrg == eDst), the new face will have only two edges.
00503  * If (eOrg->Lnext == eDst), the old face is reduced to a single edge.
00504  * If (eOrg->Lnext->Lnext == eDst), the old face is reduced to two edges.
00505  */
00506 GLUhalfEdge *__gl_meshConnect( GLUhalfEdge *eOrg, GLUhalfEdge *eDst )
00507 {
00508   GLUhalfEdge *eNewSym;
00509   int joiningLoops = FALSE;
00510   GLUhalfEdge *eNew = MakeEdge( eOrg );
00511   if (eNew == NULL) return NULL;
00512 
00513   eNewSym = eNew->Sym;
00514 
00515   if( eDst->Lface != eOrg->Lface ) {
00516     /* We are connecting two disjoint loops -- destroy eDst->Lface */
00517     joiningLoops = TRUE;
00518     KillFace( eDst->Lface, eOrg->Lface );
00519   }
00520 
00521   /* Connect the new edge appropriately */
00522   Splice( eNew, eOrg->Lnext );
00523   Splice( eNewSym, eDst );
00524 
00525   /* Set the vertex and face information */
00526   eNew->Org = eOrg->Dst;
00527   eNewSym->Org = eDst->Org;
00528   eNew->Lface = eNewSym->Lface = eOrg->Lface;
00529 
00530   /* Make sure the old face points to a valid half-edge */
00531   eOrg->Lface->anEdge = eNewSym;
00532 
00533   if( ! joiningLoops ) {
00534     GLUface *newFace= allocFace();
00535     if (newFace == NULL) return NULL;
00536 
00537     /* We split one loop into two -- the new loop is eNew->Lface */
00538     MakeFace( newFace, eNew, eOrg->Lface );
00539   }
00540   return eNew;
00541 }
00542 
00543 
00544 /******************** Other Operations **********************/
00545 
00546 /* __gl_meshZapFace( fZap ) destroys a face and removes it from the
00547  * global face list.  All edges of fZap will have a NULL pointer as their
00548  * left face.  Any edges which also have a NULL pointer as their right face
00549  * are deleted entirely (along with any isolated vertices this produces).
00550  * An entire mesh can be deleted by zapping its faces, one at a time,
00551  * in any order.  Zapped faces cannot be used in further mesh operations!
00552  */
00553 void __gl_meshZapFace( GLUface *fZap )
00554 {
00555   GLUhalfEdge *eStart = fZap->anEdge;
00556   GLUhalfEdge *e, *eNext, *eSym;
00557   GLUface *fPrev, *fNext;
00558 
00559   /* walk around face, deleting edges whose right face is also NULL */
00560   eNext = eStart->Lnext;
00561   do {
00562     e = eNext;
00563     eNext = e->Lnext;
00564 
00565     e->Lface = NULL;
00566     if( e->Rface == NULL ) {
00567       /* delete the edge -- see __gl_MeshDelete above */
00568 
00569       if( e->Onext == e ) {
00570     KillVertex( e->Org, NULL );
00571       } else {
00572     /* Make sure that e->Org points to a valid half-edge */
00573     e->Org->anEdge = e->Onext;
00574     Splice( e, e->Oprev );
00575       }
00576       eSym = e->Sym;
00577       if( eSym->Onext == eSym ) {
00578     KillVertex( eSym->Org, NULL );
00579       } else {
00580     /* Make sure that eSym->Org points to a valid half-edge */
00581     eSym->Org->anEdge = eSym->Onext;
00582     Splice( eSym, eSym->Oprev );
00583       }
00584       KillEdge( e );
00585     }
00586   } while( e != eStart );
00587 
00588   /* delete from circular doubly-linked list */
00589   fPrev = fZap->prev;
00590   fNext = fZap->next;
00591   fNext->prev = fPrev;
00592   fPrev->next = fNext;
00593 
00594   memFree( fZap );
00595 }
00596 
00597 
00598 /* __gl_meshNewMesh() creates a new mesh with no edges, no vertices,
00599  * and no loops (what we usually call a "face").
00600  */
00601 GLUmesh *__gl_meshNewMesh( void )
00602 {
00603   GLUvertex *v;
00604   GLUface *f;
00605   GLUhalfEdge *e;
00606   GLUhalfEdge *eSym;
00607   GLUmesh *mesh = (GLUmesh *)memAlloc( sizeof( GLUmesh ));
00608   if (mesh == NULL) {
00609      return NULL;
00610   }
00611 
00612   v = &mesh->vHead;
00613   f = &mesh->fHead;
00614   e = &mesh->eHead;
00615   eSym = &mesh->eHeadSym;
00616 
00617   v->next = v->prev = v;
00618   v->anEdge = NULL;
00619   v->data = NULL;
00620 
00621   f->next = f->prev = f;
00622   f->anEdge = NULL;
00623   f->data = NULL;
00624   f->trail = NULL;
00625   f->marked = FALSE;
00626   f->inside = FALSE;
00627 
00628   e->next = e;
00629   e->Sym = eSym;
00630   e->Onext = NULL;
00631   e->Lnext = NULL;
00632   e->Org = NULL;
00633   e->Lface = NULL;
00634   e->winding = 0;
00635   e->activeRegion = NULL;
00636 
00637   eSym->next = eSym;
00638   eSym->Sym = e;
00639   eSym->Onext = NULL;
00640   eSym->Lnext = NULL;
00641   eSym->Org = NULL;
00642   eSym->Lface = NULL;
00643   eSym->winding = 0;
00644   eSym->activeRegion = NULL;
00645 
00646   return mesh;
00647 }
00648 
00649 
00650 /* __gl_meshUnion( mesh1, mesh2 ) forms the union of all structures in
00651  * both meshes, and returns the new mesh (the old meshes are destroyed).
00652  */
00653 GLUmesh *__gl_meshUnion( GLUmesh *mesh1, GLUmesh *mesh2 )
00654 {
00655   GLUface *f1 = &mesh1->fHead;
00656   GLUvertex *v1 = &mesh1->vHead;
00657   GLUhalfEdge *e1 = &mesh1->eHead;
00658   GLUface *f2 = &mesh2->fHead;
00659   GLUvertex *v2 = &mesh2->vHead;
00660   GLUhalfEdge *e2 = &mesh2->eHead;
00661 
00662   /* Add the faces, vertices, and edges of mesh2 to those of mesh1 */
00663   if( f2->next != f2 ) {
00664     f1->prev->next = f2->next;
00665     f2->next->prev = f1->prev;
00666     f2->prev->next = f1;
00667     f1->prev = f2->prev;
00668   }
00669 
00670   if( v2->next != v2 ) {
00671     v1->prev->next = v2->next;
00672     v2->next->prev = v1->prev;
00673     v2->prev->next = v1;
00674     v1->prev = v2->prev;
00675   }
00676 
00677   if( e2->next != e2 ) {
00678     e1->Sym->next->Sym->next = e2->next;
00679     e2->next->Sym->next = e1->Sym->next;
00680     e2->Sym->next->Sym->next = e1;
00681     e1->Sym->next = e2->Sym->next;
00682   }
00683 
00684   memFree( mesh2 );
00685   return mesh1;
00686 }
00687 
00688 
00689 #ifdef DELETE_BY_ZAPPING
00690 
00691 /* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh.
00692  */
00693 void __gl_meshDeleteMesh( GLUmesh *mesh )
00694 {
00695   GLUface *fHead = &mesh->fHead;
00696 
00697   while( fHead->next != fHead ) {
00698     __gl_meshZapFace( fHead->next );
00699   }
00700   assert( mesh->vHead.next == &mesh->vHead );
00701 
00702   memFree( mesh );
00703 }
00704 
00705 #else
00706 
00707 /* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh.
00708  */
00709 void __gl_meshDeleteMesh( GLUmesh *mesh )
00710 {
00711   GLUface *f, *fNext;
00712   GLUvertex *v, *vNext;
00713   GLUhalfEdge *e, *eNext;
00714 
00715   for( f = mesh->fHead.next; f != &mesh->fHead; f = fNext ) {
00716     fNext = f->next;
00717     memFree( f );
00718   }
00719 
00720   for( v = mesh->vHead.next; v != &mesh->vHead; v = vNext ) {
00721     vNext = v->next;
00722     memFree( v );
00723   }
00724 
00725   for( e = mesh->eHead.next; e != &mesh->eHead; e = eNext ) {
00726     /* One call frees both e and e->Sym (see EdgePair above) */
00727     eNext = e->next;
00728     memFree( e );
00729   }
00730 
00731   memFree( mesh );
00732 }
00733 
00734 #endif
00735 
00736 #ifndef NDEBUG
00737 
00738 /* __gl_meshCheckMesh( mesh ) checks a mesh for self-consistency.
00739  */
00740 void __gl_meshCheckMesh( GLUmesh *mesh )
00741 {
00742   GLUface *fHead = &mesh->fHead;
00743   GLUvertex *vHead = &mesh->vHead;
00744   GLUhalfEdge *eHead = &mesh->eHead;
00745   GLUface *f, *fPrev;
00746   GLUvertex *v, *vPrev;
00747   GLUhalfEdge *e, *ePrev;
00748 
00749   fPrev = fHead;
00750   for( fPrev = fHead ; (f = fPrev->next) != fHead; fPrev = f) {
00751     assert( f->prev == fPrev );
00752     e = f->anEdge;
00753     do {
00754       assert( e->Sym != e );
00755       assert( e->Sym->Sym == e );
00756       assert( e->Lnext->Onext->Sym == e );
00757       assert( e->Onext->Sym->Lnext == e );
00758       assert( e->Lface == f );
00759       e = e->Lnext;
00760     } while( e != f->anEdge );
00761   }
00762   assert( f->prev == fPrev && f->anEdge == NULL && f->data == NULL );
00763 
00764   vPrev = vHead;
00765   for( vPrev = vHead ; (v = vPrev->next) != vHead; vPrev = v) {
00766     assert( v->prev == vPrev );
00767     e = v->anEdge;
00768     do {
00769       assert( e->Sym != e );
00770       assert( e->Sym->Sym == e );
00771       assert( e->Lnext->Onext->Sym == e );
00772       assert( e->Onext->Sym->Lnext == e );
00773       assert( e->Org == v );
00774       e = e->Onext;
00775     } while( e != v->anEdge );
00776   }
00777   assert( v->prev == vPrev && v->anEdge == NULL && v->data == NULL );
00778 
00779   ePrev = eHead;
00780   for( ePrev = eHead ; (e = ePrev->next) != eHead; ePrev = e) {
00781     assert( e->Sym->next == ePrev->Sym );
00782     assert( e->Sym != e );
00783     assert( e->Sym->Sym == e );
00784     assert( e->Org != NULL );
00785     assert( e->Dst != NULL );
00786     assert( e->Lnext->Onext->Sym == e );
00787     assert( e->Onext->Sym->Lnext == e );
00788   }
00789   assert( e->Sym->next == ePrev->Sym
00790        && e->Sym == &mesh->eHeadSym
00791        && e->Sym->Sym == e
00792        && e->Org == NULL && e->Dst == NULL
00793        && e->Lface == NULL && e->Rface == NULL );
00794 }
00795 
00796 #endif

Generated on Sat May 26 2012 04:20:42 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.