Пример #1
0
/* __gl_meshDelete( eDel ) removes the edge eDel.  There are several cases:
 * if (eDel->Lface != eDel->Rface), we join two loops into one; the loop
 * eDel->Lface is deleted.  Otherwise, we are splitting one loop into two;
 * the newly created loop will contain eDel->Dst.  If the deletion of eDel
 * would create isolated vertices, those are deleted as well.
 *
 * This function could be implemented as two calls to __gl_meshSplice
 * plus a few calls to memFree, but this would allocate and delete
 * unnecessary vertices and faces.
 */
int __gl_meshDelete(GLUhalfEdge* eDel)
{
   GLUhalfEdge* eDelSym=eDel->Sym;
   int joiningLoops=FALSE;

   /* First step: disconnect the origin vertex eDel->Org.  We make all
    * changes to get a consistent mesh in this "intermediate" state.
    */
   if (eDel->Lface!=eDel->Rface)
   {
      /* We are joining two loops into one -- remove the left face */
      joiningLoops=TRUE;
      KillFace(eDel->Lface, eDel->Rface);
   }

   if (eDel->Onext==eDel)
   {
      KillVertex(eDel->Org, NULL);
   }
   else
   {
      /* Make sure that eDel->Org and eDel->Rface point to valid half-edges */
      eDel->Rface->anEdge=eDel->Oprev;
      eDel->Org->anEdge=eDel->Onext;

      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;
}
Пример #2
0
/* tessMeshDelete (eDel)  removes the edge eDel.  There are several cases:
* if (eDel->Lface != eDel->Rface), we join two loops into one; the loop
* eDel->Lface is deleted.  Otherwise, we are splitting one loop into two;
* the newly created loop will contain eDel->Dst.  If the deletion of eDel
* would create isolated vertices, those are deleted as well.
*
* This function could be implemented as two calls to tessMeshSplice
* plus a few calls to memFree, but this would allocate and delete
* unnecessary vertices and faces.
*/
int tessMeshDelete (TMesh *mesh, THalfEdge *eDel) 
{
	THalfEdge *eDelSym = eDel->Sym;
	int joiningLoops = false;

	/* First step: disconnect the origin vertex eDel->Org.  We make all
	* changes to get a consistent mesh in this "intermediate" state.
	*/
	if (eDel->Lface != eDel->Rface)  
    {
		/* We are joining two loops into one -- remove the left face */
		joiningLoops = true;
		KillFace (mesh, eDel->Lface, eDel->Rface) ;
	}

	if (eDel->Onext == eDel)  
    {
		KillVertex (mesh, eDel->pOrigin, NULL) ;
	} 
    else 
    {
		/* Make sure that eDel->Org and eDel->Rface point to valid half-edges */
		eDel->Rface->pHalfEdge = eDel->Oprev;
		eDel->pOrigin->pHalfEdge = eDel->Onext;

		Splice (eDel, eDel->Oprev) ;
		if (! joiningLoops)  
        {
			TFace *newFace= (TFace*)BucketAlloc (mesh->pFaceBucket) ;
			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 (mesh, eDelSym->pOrigin, NULL) ;
		KillFace (mesh, eDelSym->Lface, NULL) ;
	} 
    else 
    {
		/* Make sure that eDel->Dst and eDel->Lface point to valid half-edges */
		eDel->Lface->pHalfEdge = eDelSym->Oprev;
		eDelSym->pOrigin->pHalfEdge = eDelSym->Onext;
		Splice (eDelSym, eDelSym->Oprev) ;
	}

	/* Any isolated vertices or faces have already been freed. */
	KillEdge (mesh, eDel) ;

	return 1;
}
Пример #3
0
/* __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);
}
Пример #4
0
/* __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the
 * mesh connectivity and topology.  It changes the mesh so that
 *      eOrg->Onext <- OLD(eDst->Onext)
 *      eDst->Onext <- OLD(eOrg->Onext)
 * where OLD(...) means the value before the meshSplice operation.
 *
 * This can have two effects on the vertex structure:
 *  - if eOrg->Org != eDst->Org, the two vertices are merged together
 *  - if eOrg->Org == eDst->Org, the origin is split into two vertices
 * In both cases, eDst->Org is changed and eOrg->Org is untouched.
 *
 * Similarly (and independently) for the face structure,
 *  - if eOrg->Lface == eDst->Lface, one loop is split into two
 *  - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one
 * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected.
 *
 * Some special cases:
 * If eDst == eOrg, the operation has no effect.
 * If eDst == eOrg->Lnext, the new face will have a single edge.
 * If eDst == eOrg->Lprev, the old face will have a single edge.
 * If eDst == eOrg->Onext, the new vertex will have a single edge.
 * If eDst == eOrg->Oprev, the old vertex will have a single edge.
 */
int __gl_meshSplice(GLUhalfEdge* eOrg, GLUhalfEdge* eDst)
{
   int joiningLoops=FALSE;
   int joiningVertices=FALSE;

   if (eOrg==eDst)
   {
      return 1;
   }

   if (eDst->Org!=eOrg->Org)
   {
      /* We are merging two disjoint vertices -- destroy eDst->Org */
      joiningVertices=TRUE;
      KillVertex(eDst->Org, eOrg->Org);
   }

   if (eDst->Lface!=eOrg->Lface)
   {
      /* We are connecting two disjoint loops -- destroy eDst->Lface */
      joiningLoops=TRUE;
      KillFace(eDst->Lface, eOrg->Lface);
   }

   /* Change the edge structure */
   Splice(eDst, eOrg);

   if (!joiningVertices)
   {
      GLUvertex* newVertex=allocVertex();
      if (newVertex==NULL)
      {
         return 0;
      }

      /* We split one vertex into two -- the new vertex is eDst->Org.
       * Make sure the old vertex points to a valid half-edge.
       */
      MakeVertex(newVertex, eDst, eOrg->Org);
      eOrg->Org->anEdge=eOrg;
   }

   if (!joiningLoops)
   {
      GLUface* newFace=allocFace();
      if (newFace==NULL)
      {
         return 0;
      }

      /* We split one loop into two -- the new loop is eDst->Lface.
       * Make sure the old face points to a valid half-edge.
       */
      MakeFace(newFace, eDst, eOrg->Lface);
      eOrg->Lface->anEdge=eOrg;
   }

   return 1;
}
Пример #5
0
/* tessMeshZapFace (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 tessMeshZapFace (TMesh *mesh, TFace *fZap) 
{
	THalfEdge *eStart = fZap->pHalfEdge;
	THalfEdge *e, *eNext, *eSym;
	TFace *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 TESSmeshDelete above */

			if (e->Onext == e)  {
				KillVertex (mesh, e->pOrigin, NULL) ;
			} else {
				/* Make sure that e->Org points to a valid half-edge */
				e->pOrigin->pHalfEdge = e->Onext;
				Splice (e, e->Oprev) ;
			}
			eSym = e->Sym;
			if (eSym->Onext == eSym)  {
				KillVertex (mesh, eSym->pOrigin, NULL) ;
			} else {
				/* Make sure that eSym->Org points to a valid half-edge */
				eSym->pOrigin->pHalfEdge = eSym->Onext;
				Splice (eSym, eSym->Oprev) ;
			}
			KillEdge (mesh, e) ;
		}
	} while (e != eStart) ;

	/* delete from circular doubly-linked list */
	fPrev = fZap->pPrev;
	fNext = fZap->pNext;
	fNext->pPrev = fPrev;
	fPrev->pNext = fNext;

	BucketFree (mesh->pFaceBucket, fZap) ;
}
Пример #6
0
/* tessMeshSplice (eOrg, eDst)  is the basic operation for changing the
* mesh connectivity and topology.  It changes the mesh so that
*	eOrg->Onext <- OLD (eDst->Onext) 
*	eDst->Onext <- OLD (eOrg->Onext) 
* where OLD(...) means the value before the meshSplice operation.
*
* This can have two effects on the vertex structure:
*  - if eOrg->Org != eDst->Org, the two vertices are merged together
*  - if eOrg->Org == eDst->Org, the origin is split into two vertices
* In both cases, eDst->Org is changed and eOrg->Org is untouched.
*
* Similarly (and independently) for the face structure,
*  - if eOrg->Lface == eDst->Lface, one loop is split into two
*  - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one
* In both cases, eDst->Lface is changed and eOrg->Lface is unaffected.
*
* Some special cases:
* If eDst == eOrg, the operation has no effect.
* If eDst == eOrg->Lnext, the new face will have a single edge.
* If eDst == eOrg->Lprev, the old face will have a single edge.
* If eDst == eOrg->Onext, the new vertex will have a single edge.
* If eDst == eOrg->Oprev, the old vertex will have a single edge.
*/
int tessMeshSplice(TMesh* pMesh, THalfEdge *pEdgeOrg, THalfEdge *pEdgeDst) 
{
	int bJoiningLoops = false;
	int bJoiningVertices = false;

	if (pEdgeOrg == pEdgeDst) return 1;

	if (pEdgeDst->pOrigin != pEdgeOrg->pOrigin)  
    {
		/* We are merging two disjoint vertices -- destroy eDst->Org */
		bJoiningVertices = true;
		KillVertex(pMesh, pEdgeDst->pOrigin, pEdgeOrg->pOrigin);
	}
	if (pEdgeDst->Lface != pEdgeOrg->Lface)  
    {
		/* We are connecting two disjoint loops -- destroy eDst->Lface */
		bJoiningLoops = true;
		KillFace(pMesh, pEdgeDst->Lface, pEdgeOrg->Lface);
	}

	/* Change the edge structure */
	Splice(pEdgeDst, pEdgeOrg);

	if (!bJoiningVertices)
    {
		TVertex *pNewVertex = (TVertex*)BucketAlloc(pMesh->pVertexBucket);
		if (pNewVertex == NULL) return 0;

		/* We split one vertex into two -- the new vertex is eDst->Org.
		* Make sure the old vertex points to a valid half-edge.
		*/
		MakeVertex(pNewVertex, pEdgeDst, pEdgeOrg->pOrigin);
		pEdgeOrg->pOrigin->pHalfEdge = pEdgeOrg;
	}
	if (!bJoiningLoops)  
    {
		TFace *pNewFace = (TFace*)BucketAlloc(pMesh->pFaceBucket);
		if (pNewFace == NULL) return 0;

		/* We split one loop into two -- the new loop is eDst->Lface.
		* Make sure the old face points to a valid half-edge.
		*/
		MakeFace(pNewFace, pEdgeDst, pEdgeOrg->Lface);
		pEdgeOrg->Lface->pHalfEdge = pEdgeOrg;
	}

	return 1;
}
Пример #7
0
/* tessMeshSplice( eOrg, eDst ) is the basic operation for changing the
* mesh connectivity and topology.  It changes the mesh so that
*    eOrg->Onext <- OLD( eDst->Onext )
*    eDst->Onext <- OLD( eOrg->Onext )
* where OLD(...) means the value before the meshSplice operation.
*
* This can have two effects on the vertex structure:
*  - if eOrg->Org != eDst->Org, the two vertices are merged together
*  - if eOrg->Org == eDst->Org, the origin is split into two vertices
* In both cases, eDst->Org is changed and eOrg->Org is untouched.
*
* Similarly (and independently) for the face structure,
*  - if eOrg->Lface == eDst->Lface, one loop is split into two
*  - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one
* In both cases, eDst->Lface is changed and eOrg->Lface is unaffected.
*
* Some special cases:
* If eDst == eOrg, the operation has no effect.
* If eDst == eOrg->Lnext, the new face will have a single edge.
* If eDst == eOrg->Lprev, the old face will have a single edge.
* If eDst == eOrg->Onext, the new vertex will have a single edge.
* If eDst == eOrg->Oprev, the old vertex will have a single edge.
*/
int tessMeshSplice( TESSmesh* mesh, TESShalfEdge *eOrg, TESShalfEdge *eDst )
{
    int joiningLoops = FALSE;
    int joiningVertices = FALSE;

    if( eOrg == eDst ) return 1;

    if( eDst->Org != eOrg->Org ) {
        /* We are merging two disjoint vertices -- destroy eDst->Org */
        joiningVertices = TRUE;
        KillVertex( mesh, eDst->Org, eOrg->Org );
    }
    if( eDst->Lface != eOrg->Lface ) {
        /* We are connecting two disjoint loops -- destroy eDst->Lface */
        joiningLoops = TRUE;
        KillFace( mesh, eDst->Lface, eOrg->Lface );
    }

    /* Change the edge structure */
    Splice( eDst, eOrg );

    if( ! joiningVertices ) {
        TESSvertex *newVertex = (TESSvertex*)bucketAlloc( mesh->vertexBucket );
        if (newVertex == NULL) return 0;

        /* We split one vertex into two -- the new vertex is eDst->Org.
        * Make sure the old vertex points to a valid half-edge.
        */
        MakeVertex( newVertex, eDst, eOrg->Org );
        eOrg->Org->anEdge = eOrg;
    }
    if( ! joiningLoops ) {
        TESSface *newFace = (TESSface*)bucketAlloc( mesh->faceBucket );
        if (newFace == NULL) return 0;

        /* We split one loop into two -- the new loop is eDst->Lface.
        * Make sure the old face points to a valid half-edge.
        */
        MakeFace( newFace, eDst, eOrg->Lface );
        eOrg->Lface->anEdge = eOrg;
    }

    return 1;
}