📄 mesh.c
字号:
Splice( eDel, eDel->Oprev ); if( ! joiningLoops ) { GLUface *newFace= allocFace(); if (newFace == NULL) return 0; /* 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->Oprev; eDelSym->Org->anEdge = eDelSym->Onext; Splice( eDelSym, eDelSym->Oprev ); } /* Any isolated vertices or faces have already been freed. */ KillEdge( eDel ); return 1;}/******************** 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. */GLUhalfEdge *__gl_meshAddEdgeVertex( GLUhalfEdge *eOrg ){ GLUhalfEdge *eNewSym; GLUhalfEdge *eNew = MakeEdge( eOrg ); if (eNew == NULL) return NULL; eNewSym = eNew->Sym; /* Connect the new edge appropriately */ Splice( eNew, eOrg->Lnext ); /* Set the vertex and face information */ eNew->Org = eOrg->Dst; { GLUvertex *newVertex= allocVertex(); if (newVertex == NULL) return NULL; 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->Dst == eNew->Org. * eOrg and eNew will have the same left face. */GLUhalfEdge *__gl_meshSplitEdge( GLUhalfEdge *eOrg ){ GLUhalfEdge *eNew; GLUhalfEdge *tempHalfEdge= __gl_meshAddEdgeVertex( eOrg ); if (tempHalfEdge == NULL) return NULL; eNew = tempHalfEdge->Sym; /* Disconnect eOrg from eOrg->Dst and connect it to eNew->Org */ Splice( eOrg->Sym, eOrg->Sym->Oprev ); Splice( eOrg->Sym, eNew ); /* Set the vertex and face information */ eOrg->Dst = eNew->Org; eNew->Dst->anEdge = eNew->Sym; /* may have pointed to eOrg->Sym */ eNew->Rface = eOrg->Rface; 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->Dst * 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. */GLUhalfEdge *__gl_meshConnect( GLUhalfEdge *eOrg, GLUhalfEdge *eDst ){ GLUhalfEdge *eNewSym; int joiningLoops = FALSE; GLUhalfEdge *eNew = MakeEdge( eOrg ); if (eNew == NULL) return NULL; 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->Dst; 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 ) { GLUface *newFace= allocFace(); if (newFace == NULL) return NULL; /* 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! */void __gl_meshZapFace( GLUface *fZap ){ GLUhalfEdge *eStart = fZap->anEdge; GLUhalfEdge *e, *eNext, *eSym; 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->Rface == 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->Oprev ); } 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->Oprev ); } KillEdge( e ); } } while( e != eStart ); /* delete from circular doubly-linked list */ fPrev = fZap->prev; fNext = fZap->next; fNext->prev = fPrev; fPrev->next = fNext; memFree( fZap );}/* __gl_meshNewMesh() creates a new mesh with no edges, no vertices, * and no loops (what we usually call a "face"). */GLUmesh *__gl_meshNewMesh( void ){ GLUvertex *v; GLUface *f; GLUhalfEdge *e; GLUhalfEdge *eSym; GLUmesh *mesh = (GLUmesh *)memAlloc( sizeof( GLUmesh )); if (mesh == NULL) { return NULL; } 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). */GLUmesh *__gl_meshUnion( GLUmesh *mesh1, GLUmesh *mesh2 ){ GLUface *f1 = &mesh1->fHead; GLUvertex *v1 = &mesh1->vHead; GLUhalfEdge *e1 = &mesh1->eHead; GLUface *f2 = &mesh2->fHead; GLUvertex *v2 = &mesh2->vHead; 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; } memFree( mesh2 ); return mesh1;}#ifdef DELETE_BY_ZAPPING/* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh. */void __gl_meshDeleteMesh( GLUmesh *mesh ){ GLUface *fHead = &mesh->fHead; while( fHead->next != fHead ) { __gl_meshZapFace( fHead->next ); } assert( mesh->vHead.next == &mesh->vHead ); memFree( mesh );}#else/* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh. */void __gl_meshDeleteMesh( GLUmesh *mesh ){ GLUface *f, *fNext; GLUvertex *v, *vNext; GLUhalfEdge *e, *eNext; for( f = mesh->fHead.next; f != &mesh->fHead; f = fNext ) { fNext = f->next; memFree( f ); } for( v = mesh->vHead.next; v != &mesh->vHead; v = vNext ) { vNext = v->next; memFree( v ); } for( e = mesh->eHead.next; e != &mesh->eHead; e = eNext ) { /* One call frees both e and e->Sym (see EdgePair above) */ eNext = e->next; memFree( e ); } memFree( mesh );}#endif#ifndef NDEBUG/* __gl_meshCheckMesh( mesh ) checks a mesh for self-consistency. */void __gl_meshCheckMesh( GLUmesh *mesh ){ GLUface *fHead = &mesh->fHead; GLUvertex *vHead = &mesh->vHead; GLUhalfEdge *eHead = &mesh->eHead; GLUface *f, *fPrev; GLUvertex *v, *vPrev; 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->Dst != 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->Dst == NULL && e->Lface == NULL && e->Rface == NULL );}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -