⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sweep.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 4 页
字号:
	  && EdgeSign( dstUp, tess->event, &isect ) >= 0)      || (! VertEq( dstLo, tess->event )	  && EdgeSign( dstLo, tess->event, &isect ) <= 0 ))  {    /* Very unusual -- the new upper or lower edge would pass on the     * wrong side of the sweep event, or through it.  This can happen     * due to very small numerical errors in the intersection calculation.     */    if( dstLo == tess->event ) {      /* Splice dstLo into eUp, and process the new region(s) */      if (__gl_meshSplitEdge( eUp->Sym ) == NULL) longjmp(tess->env,1);      if ( !__gl_meshSplice( eLo->Sym, eUp ) ) longjmp(tess->env,1);      regUp = TopLeftRegion( regUp );      if (regUp == NULL) longjmp(tess->env,1);      eUp = RegionBelow(regUp)->eUp;      FinishLeftRegions( tess, RegionBelow(regUp), regLo );      AddRightEdges( tess, regUp, eUp->Oprev, eUp, eUp, TRUE );      return TRUE;    }    if( dstUp == tess->event ) {      /* Splice dstUp into eLo, and process the new region(s) */      if (__gl_meshSplitEdge( eLo->Sym ) == NULL) longjmp(tess->env,1);      if ( !__gl_meshSplice( eUp->Lnext, eLo->Oprev ) ) longjmp(tess->env,1);      regLo = regUp;      regUp = TopRightRegion( regUp );      e = RegionBelow(regUp)->eUp->Rprev;      regLo->eUp = eLo->Oprev;      eLo = FinishLeftRegions( tess, regLo, NULL );      AddRightEdges( tess, regUp, eLo->Onext, eUp->Rprev, e, TRUE );      return TRUE;    }    /* Special case: called from ConnectRightVertex.  If either     * edge passes on the wrong side of tess->event, split it     * (and wait for ConnectRightVertex to splice it appropriately).     */    if( EdgeSign( dstUp, tess->event, &isect ) >= 0 ) {      RegionAbove(regUp)->dirty = regUp->dirty = TRUE;      if (__gl_meshSplitEdge( eUp->Sym ) == NULL) longjmp(tess->env,1);      eUp->Org->s = tess->event->s;      eUp->Org->t = tess->event->t;    }    if( EdgeSign( dstLo, tess->event, &isect ) <= 0 ) {      regUp->dirty = regLo->dirty = TRUE;      if (__gl_meshSplitEdge( eLo->Sym ) == NULL) longjmp(tess->env,1);      eLo->Org->s = tess->event->s;      eLo->Org->t = tess->event->t;    }    /* leave the rest for ConnectRightVertex */    return FALSE;  }  /* General case -- split both edges, splice into new vertex.   * When we do the splice operation, the order of the arguments is   * arbitrary as far as correctness goes.  However, when the operation   * creates a new face, the work done is proportional to the size of   * the new face.  We expect the faces in the processed part of   * the mesh (ie. eUp->Lface) to be smaller than the faces in the   * unprocessed original contours (which will be eLo->Oprev->Lface).   */  if (__gl_meshSplitEdge( eUp->Sym ) == NULL) longjmp(tess->env,1);  if (__gl_meshSplitEdge( eLo->Sym ) == NULL) longjmp(tess->env,1);  if ( !__gl_meshSplice( eLo->Oprev, eUp ) ) longjmp(tess->env,1);  eUp->Org->s = isect.s;  eUp->Org->t = isect.t;  eUp->Org->pqHandle = pqInsert( tess->pq, eUp->Org ); /* __gl_pqSortInsert */  if (eUp->Org->pqHandle == LONG_MAX) {     pqDeletePriorityQ(tess->pq);	/* __gl_pqSortDeletePriorityQ */     tess->pq = NULL;     longjmp(tess->env,1);  }  GetIntersectData( tess, eUp->Org, orgUp, dstUp, orgLo, dstLo );  RegionAbove(regUp)->dirty = regUp->dirty = regLo->dirty = TRUE;  return FALSE;}static void WalkDirtyRegions( GLUtesselator *tess, ActiveRegion *regUp )/* * When the upper or lower edge of any region changes, the region is * marked "dirty".  This routine walks through all the dirty regions * and makes sure that the dictionary invariants are satisfied * (see the comments at the beginning of this file).  Of course * new dirty regions can be created as we make changes to restore * the invariants. */{  ActiveRegion *regLo = RegionBelow(regUp);  GLUhalfEdge *eUp, *eLo;  for( ;; ) {    /* Find the lowest dirty region (we walk from the bottom up). */    while( regLo->dirty ) {      regUp = regLo;      regLo = RegionBelow(regLo);    }    if( ! regUp->dirty ) {      regLo = regUp;      regUp = RegionAbove( regUp );      if( regUp == NULL || ! regUp->dirty ) {	/* We've walked all the dirty regions */	return;      }    }    regUp->dirty = FALSE;    eUp = regUp->eUp;    eLo = regLo->eUp;    if( eUp->Dst != eLo->Dst ) {      /* Check that the edge ordering is obeyed at the Dst vertices. */      if( CheckForLeftSplice( tess, regUp )) {	/* If the upper or lower edge was marked fixUpperEdge, then	 * we no longer need it (since these edges are needed only for	 * vertices which otherwise have no right-going edges).	 */	if( regLo->fixUpperEdge ) {	  DeleteRegion( tess, regLo );	  if ( !__gl_meshDelete( eLo ) ) longjmp(tess->env,1);	  regLo = RegionBelow( regUp );	  eLo = regLo->eUp;	} else if( regUp->fixUpperEdge ) {	  DeleteRegion( tess, regUp );	  if ( !__gl_meshDelete( eUp ) ) longjmp(tess->env,1);	  regUp = RegionAbove( regLo );	  eUp = regUp->eUp;	}      }    }    if( eUp->Org != eLo->Org ) {      if(    eUp->Dst != eLo->Dst	  && ! regUp->fixUpperEdge && ! regLo->fixUpperEdge	  && (eUp->Dst == tess->event || eLo->Dst == tess->event) )      {	/* When all else fails in CheckForIntersect(), it uses tess->event	 * as the intersection location.  To make this possible, it requires	 * that tess->event lie between the upper and lower edges, and also	 * that neither of these is marked fixUpperEdge (since in the worst	 * case it might splice one of these edges into tess->event, and	 * violate the invariant that fixable edges are the only right-going	 * edge from their associated vertex).	 */	if( CheckForIntersect( tess, regUp )) {	  /* WalkDirtyRegions() was called recursively; we're done */	  return;	}      } else {	/* Even though we can't use CheckForIntersect(), the Org vertices	 * may violate the dictionary edge ordering.  Check and correct this.	 */	(void) CheckForRightSplice( tess, regUp );      }    }    if( eUp->Org == eLo->Org && eUp->Dst == eLo->Dst ) {      /* A degenerate loop consisting of only two edges -- delete it. */      AddWinding( eLo, eUp );      DeleteRegion( tess, regUp );      if ( !__gl_meshDelete( eUp ) ) longjmp(tess->env,1);      regUp = RegionAbove( regLo );    }  }}static void ConnectRightVertex( GLUtesselator *tess, ActiveRegion *regUp,				GLUhalfEdge *eBottomLeft )/* * Purpose: connect a "right" vertex vEvent (one where all edges go left) * to the unprocessed portion of the mesh.  Since there are no right-going * edges, two regions (one above vEvent and one below) are being merged * into one.  "regUp" is the upper of these two regions. * * There are two reasons for doing this (adding a right-going edge): *  - if the two regions being merged are "inside", we must add an edge *    to keep them separated (the combined region would not be monotone). *  - in any case, we must leave some record of vEvent in the dictionary, *    so that we can merge vEvent with features that we have not seen yet. *    For example, maybe there is a vertical edge which passes just to *    the right of vEvent; we would like to splice vEvent into this edge. * * However, we don't want to connect vEvent to just any vertex.  We don''t * want the new edge to cross any other edges; otherwise we will create * intersection vertices even when the input data had no self-intersections. * (This is a bad thing; if the user's input data has no intersections, * we don't want to generate any false intersections ourselves.) * * Our eventual goal is to connect vEvent to the leftmost unprocessed * vertex of the combined region (the union of regUp and regLo). * But because of unseen vertices with all right-going edges, and also * new vertices which may be created by edge intersections, we don''t * know where that leftmost unprocessed vertex is.  In the meantime, we * connect vEvent to the closest vertex of either chain, and mark the region * as "fixUpperEdge".  This flag says to delete and reconnect this edge * to the next processed vertex on the boundary of the combined region. * Quite possibly the vertex we connected to will turn out to be the * closest one, in which case we won''t need to make any changes. */{  GLUhalfEdge *eNew;  GLUhalfEdge *eTopLeft = eBottomLeft->Onext;  ActiveRegion *regLo = RegionBelow(regUp);  GLUhalfEdge *eUp = regUp->eUp;  GLUhalfEdge *eLo = regLo->eUp;  int degenerate = FALSE;  if( eUp->Dst != eLo->Dst ) {    (void) CheckForIntersect( tess, regUp );  }  /* Possible new degeneracies: upper or lower edge of regUp may pass   * through vEvent, or may coincide with new intersection vertex   */  if( VertEq( eUp->Org, tess->event )) {    if ( !__gl_meshSplice( eTopLeft->Oprev, eUp ) ) longjmp(tess->env,1);    regUp = TopLeftRegion( regUp );    if (regUp == NULL) longjmp(tess->env,1);    eTopLeft = RegionBelow( regUp )->eUp;    FinishLeftRegions( tess, RegionBelow(regUp), regLo );    degenerate = TRUE;  }  if( VertEq( eLo->Org, tess->event )) {    if ( !__gl_meshSplice( eBottomLeft, eLo->Oprev ) ) longjmp(tess->env,1);    eBottomLeft = FinishLeftRegions( tess, regLo, NULL );    degenerate = TRUE;  }  if( degenerate ) {    AddRightEdges( tess, regUp, eBottomLeft->Onext, eTopLeft, eTopLeft, TRUE );    return;  }  /* Non-degenerate situation -- need to add a temporary, fixable edge.   * Connect to the closer of eLo->Org, eUp->Org.   */  if( VertLeq( eLo->Org, eUp->Org )) {    eNew = eLo->Oprev;  } else {    eNew = eUp;  }  eNew = __gl_meshConnect( eBottomLeft->Lprev, eNew );  if (eNew == NULL) longjmp(tess->env,1);  /* Prevent cleanup, otherwise eNew might disappear before we've even   * had a chance to mark it as a temporary edge.   */  AddRightEdges( tess, regUp, eNew, eNew->Onext, eNew->Onext, FALSE );  eNew->Sym->activeRegion->fixUpperEdge = TRUE;  WalkDirtyRegions( tess, regUp );}/* Because vertices at exactly the same location are merged together * before we process the sweep event, some degenerate cases can't occur. * However if someone eventually makes the modifications required to * merge features which are close together, the cases below marked * TOLERANCE_NONZERO will be useful.  They were debugged before the * code to merge identical vertices in the main loop was added. */#define TOLERANCE_NONZERO	FALSEstatic void ConnectLeftDegenerate( GLUtesselator *tess,				   ActiveRegion *regUp, GLUvertex *vEvent )/* * The event vertex lies exacty on an already-processed edge or vertex. * Adding the new vertex involves splicing it into the already-processed * part of the mesh. */{  GLUhalfEdge *e, *eTopLeft, *eTopRight, *eLast;  ActiveRegion *reg;  e = regUp->eUp;  if( VertEq( e->Org, vEvent )) {    /* e->Org is an unprocessed vertex - just combine them, and wait     * for e->Org to be pulled from the queue     */    assert( TOLERANCE_NONZERO );    SpliceMergeVertices( tess, e, vEvent->anEdge );    return;  }  if( ! VertEq( e->Dst, vEvent )) {    /* General case -- splice vEvent into edge e which passes through it */    if (__gl_meshSplitEdge( e->Sym ) == NULL) longjmp(tess->env,1);    if( regUp->fixUpperEdge ) {      /* This edge was fixable -- delete unused portion of original edge */      if ( !__gl_meshDelete( e->Onext ) ) longjmp(tess->env,1);      regUp->fixUpperEdge = FALSE;    }    if ( !__gl_meshSplice( vEvent->anEdge, e ) ) longjmp(tess->env,1);    SweepEvent( tess, vEvent ); /* recurse */    return;  }  /* vEvent coincides with e->Dst, which has already been processed.   * Splice in the additional right-going edges.   */  assert( TOLERANCE_NONZERO );  regUp = TopRightRegion( regUp );  reg = RegionBelow( regUp );  eTopRight = reg->eUp->Sym;  eTopLeft = eLast = eTopRight->Onext;  if( reg->fixUpperEdge ) {    /* Here e->Dst has only a single fixable edge going right.     * We can delete it since now we have some real right-going edges.     */    assert( eTopLeft != eTopRight );   /* there are some left edges too */    DeleteRegion( tess, reg );    if ( !__gl_meshDelete( eTopRight ) ) longjmp(tess->env,1);    eTopRight = eTopLeft->Oprev;  }  if ( !__gl_meshSplice( vEvent->anEdge, eTopRight ) ) longjmp(tess->env,1);  if( ! EdgeGoesLeft( eTopLeft )) {    /* e->Dst had no left-going edges -- indicate this to AddRightEdges() */    eTopLeft = NULL;  }  AddRightEdges( tess, regUp, eTopRight->Onext, eLast, eTopLeft, TRUE );}static void ConnectLeftVertex( GLUtesselator *tess, GLUvertex *vEvent )/* * Purpose: connect a "left" vertex (one where both edges go right) * to the processed portion of the mesh.  Let R be the active region * containing vEvent, and let U and L be the upper and lower edge * chains of R.  There are two possibilities: * * - the normal case: split R into two regions, by connecting vEvent to *   the rightmost vertex of U or L lying to the left of the sweep line * * - the degenerate case: if vEvent is close enough to U or L, we *   merge vEvent into that edge chain.  The subcases are: *	- merging with the rightmost vertex of U or L *	- merging with the active edge of U or L *	- merging with an already-processed portion of U or L */{  ActiveRegion *regUp, *regLo, *reg;  GLUhalfEdge *eUp, *eLo, *eNew;  ActiveRegion tmp;  /* assert( vEvent->anEdge->Onext->Onext == vEvent->anEdge ); */  /* Get a pointer to the active region containing vEvent */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -