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

📄 sweep.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 4 页
字号:
  tmp.eUp = vEvent->anEdge->Sym;  /* __GL_DICTLISTKEY */ /* __gl_dictListSearch */  regUp = (ActiveRegion *)dictKey( dictSearch( tess->dict, &tmp ));  regLo = RegionBelow( regUp );  eUp = regUp->eUp;  eLo = regLo->eUp;  /* Try merging with U or L first */  if( EdgeSign( eUp->Dst, vEvent, eUp->Org ) == 0 ) {    ConnectLeftDegenerate( tess, regUp, vEvent );    return;  }  /* Connect vEvent to rightmost processed vertex of either chain.   * e->Dst is the vertex that we will connect to vEvent.   */  reg = VertLeq( eLo->Dst, eUp->Dst ) ? regUp : regLo;  if( regUp->inside || reg->fixUpperEdge) {    if( reg == regUp ) {      eNew = __gl_meshConnect( vEvent->anEdge->Sym, eUp->Lnext );      if (eNew == NULL) longjmp(tess->env,1);    } else {      GLUhalfEdge *tempHalfEdge= __gl_meshConnect( eLo->Dnext, vEvent->anEdge);      if (tempHalfEdge == NULL) longjmp(tess->env,1);      eNew = tempHalfEdge->Sym;    }    if( reg->fixUpperEdge ) {      if ( !FixUpperEdge( reg, eNew ) ) longjmp(tess->env,1);    } else {      ComputeWinding( tess, AddRegionBelow( tess, regUp, eNew ));    }    SweepEvent( tess, vEvent );  } else {    /* The new vertex is in a region which does not belong to the polygon.     * We don''t need to connect this vertex to the rest of the mesh.     */    AddRightEdges( tess, regUp, vEvent->anEdge, vEvent->anEdge, NULL, TRUE );  }}static void SweepEvent( GLUtesselator *tess, GLUvertex *vEvent )/* * Does everything necessary when the sweep line crosses a vertex. * Updates the mesh and the edge dictionary. */{  ActiveRegion *regUp, *reg;  GLUhalfEdge *e, *eTopLeft, *eBottomLeft;  tess->event = vEvent; 	/* for access in EdgeLeq() */  DebugEvent( tess );  /* Check if this vertex is the right endpoint of an edge that is   * already in the dictionary.  In this case we don't need to waste   * time searching for the location to insert new edges.   */  e = vEvent->anEdge;  while( e->activeRegion == NULL ) {    e = e->Onext;    if( e == vEvent->anEdge ) {      /* All edges go right -- not incident to any processed edges */      ConnectLeftVertex( tess, vEvent );      return;    }  }  /* Processing consists of two phases: first we "finish" all the   * active regions where both the upper and lower edges terminate   * at vEvent (ie. vEvent is closing off these regions).   * We mark these faces "inside" or "outside" the polygon according   * to their winding number, and delete the edges from the dictionary.   * This takes care of all the left-going edges from vEvent.   */  regUp = TopLeftRegion( e->activeRegion );  if (regUp == NULL) longjmp(tess->env,1);  reg = RegionBelow( regUp );  eTopLeft = reg->eUp;  eBottomLeft = FinishLeftRegions( tess, reg, NULL );  /* Next we process all the right-going edges from vEvent.  This   * involves adding the edges to the dictionary, and creating the   * associated "active regions" which record information about the   * regions between adjacent dictionary edges.   */  if( eBottomLeft->Onext == eTopLeft ) {    /* No right-going edges -- add a temporary "fixable" edge */    ConnectRightVertex( tess, regUp, eBottomLeft );  } else {    AddRightEdges( tess, regUp, eBottomLeft->Onext, eTopLeft, eTopLeft, TRUE );  }}/* Make the sentinel coordinates big enough that they will never be * merged with real input features.  (Even with the largest possible * input contour and the maximum tolerance of 1.0, no merging will be * done with coordinates larger than 3 * GLU_TESS_MAX_COORD). */#define SENTINEL_COORD	(4 * GLU_TESS_MAX_COORD)static void AddSentinel( GLUtesselator *tess, GLdouble t )/* * We add two sentinel edges above and below all other edges, * to avoid special cases at the top and bottom. */{  GLUhalfEdge *e;  ActiveRegion *reg = (ActiveRegion *)memAlloc( sizeof( ActiveRegion ));  if (reg == NULL) longjmp(tess->env,1);  e = __gl_meshMakeEdge( tess->mesh );  if (e == NULL) longjmp(tess->env,1);  e->Org->s = SENTINEL_COORD;  e->Org->t = t;  e->Dst->s = -SENTINEL_COORD;  e->Dst->t = t;  tess->event = e->Dst; 	/* initialize it */  reg->eUp = e;  reg->windingNumber = 0;  reg->inside = FALSE;  reg->fixUpperEdge = FALSE;  reg->sentinel = TRUE;  reg->dirty = FALSE;  reg->nodeUp = dictInsert( tess->dict, reg ); /* __gl_dictListInsertBefore */  if (reg->nodeUp == NULL) longjmp(tess->env,1);}static void InitEdgeDict( GLUtesselator *tess )/* * We maintain an ordering of edge intersections with the sweep line. * This order is maintained in a dynamic dictionary. */{  /* __gl_dictListNewDict */  tess->dict = dictNewDict( tess, (int (*)(void *, DictKey, DictKey)) EdgeLeq );  if (tess->dict == NULL) longjmp(tess->env,1);  AddSentinel( tess, -SENTINEL_COORD );  AddSentinel( tess, SENTINEL_COORD );}static void DoneEdgeDict( GLUtesselator *tess ){  ActiveRegion *reg;#ifndef NDEBUG  int fixedEdges = 0;#endif  /* __GL_DICTLISTKEY */ /* __GL_DICTLISTMIN */  while( (reg = (ActiveRegion *)dictKey( dictMin( tess->dict ))) != NULL ) {    /*     * At the end of all processing, the dictionary should contain     * only the two sentinel edges, plus at most one "fixable" edge     * created by ConnectRightVertex().     */    if( ! reg->sentinel ) {      assert( reg->fixUpperEdge );      assert( ++fixedEdges == 1 );    }    assert( reg->windingNumber == 0 );    DeleteRegion( tess, reg );/*    __gl_meshDelete( reg->eUp );*/  }  dictDeleteDict( tess->dict ); /* __gl_dictListDeleteDict */}static void RemoveDegenerateEdges( GLUtesselator *tess )/* * Remove zero-length edges, and contours with fewer than 3 vertices. */{  GLUhalfEdge *e, *eNext, *eLnext;  GLUhalfEdge *eHead = &tess->mesh->eHead;  /*LINTED*/  for( e = eHead->next; e != eHead; e = eNext ) {    eNext = e->next;    eLnext = e->Lnext;    if( VertEq( e->Org, e->Dst ) && e->Lnext->Lnext != e ) {      /* Zero-length edge, contour has at least 3 edges */      SpliceMergeVertices( tess, eLnext, e );	/* deletes e->Org */      if ( !__gl_meshDelete( e ) ) longjmp(tess->env,1); /* e is a self-loop */      e = eLnext;      eLnext = e->Lnext;    }    if( eLnext->Lnext == e ) {      /* Degenerate contour (one or two edges) */      if( eLnext != e ) {	if( eLnext == eNext || eLnext == eNext->Sym ) { eNext = eNext->next; }	if ( !__gl_meshDelete( eLnext ) ) longjmp(tess->env,1);      }      if( e == eNext || e == eNext->Sym ) { eNext = eNext->next; }      if ( !__gl_meshDelete( e ) ) longjmp(tess->env,1);    }  }}static int InitPriorityQ( GLUtesselator *tess )/* * Insert all vertices into the priority queue which determines the * order in which vertices cross the sweep line. */{  PriorityQ *pq;  GLUvertex *v, *vHead;  /* __gl_pqSortNewPriorityQ */  pq = tess->pq = pqNewPriorityQ( (int (*)(PQkey, PQkey)) __gl_vertLeq );  if (pq == NULL) return 0;  vHead = &tess->mesh->vHead;  for( v = vHead->next; v != vHead; v = v->next ) {    v->pqHandle = pqInsert( pq, v ); /* __gl_pqSortInsert */    if (v->pqHandle == LONG_MAX) break;  }  if (v != vHead || !pqInit( pq ) ) { /* __gl_pqSortInit */    pqDeletePriorityQ(tess->pq);	/* __gl_pqSortDeletePriorityQ */    tess->pq = NULL;    return 0;  }  return 1;}static void DonePriorityQ( GLUtesselator *tess ){  pqDeletePriorityQ( tess->pq ); /* __gl_pqSortDeletePriorityQ */}static int RemoveDegenerateFaces( GLUmesh *mesh )/* * Delete any degenerate faces with only two edges.  WalkDirtyRegions() * will catch almost all of these, but it won't catch degenerate faces * produced by splice operations on already-processed edges. * The two places this can happen are in FinishLeftRegions(), when * we splice in a "temporary" edge produced by ConnectRightVertex(), * and in CheckForLeftSplice(), where we splice already-processed * edges to ensure that our dictionary invariants are not violated * by numerical errors. * * In both these cases it is *very* dangerous to delete the offending * edge at the time, since one of the routines further up the stack * will sometimes be keeping a pointer to that edge. */{  GLUface *f, *fNext;  GLUhalfEdge *e;  /*LINTED*/  for( f = mesh->fHead.next; f != &mesh->fHead; f = fNext ) {    fNext = f->next;    e = f->anEdge;    assert( e->Lnext != e );    if( e->Lnext->Lnext == e ) {      /* A face with only two edges */      AddWinding( e->Onext, e );      if ( !__gl_meshDelete( e ) ) return 0;    }  }  return 1;}int __gl_computeInterior( GLUtesselator *tess )/* * __gl_computeInterior( tess ) computes the planar arrangement specified * by the given contours, and further subdivides this arrangement * into regions.  Each region is marked "inside" if it belongs * to the polygon, according to the rule given by tess->windingRule. * Each interior region is guaranteed be monotone. */{  GLUvertex *v, *vNext;  tess->fatalError = FALSE;  /* Each vertex defines an event for our sweep line.  Start by inserting   * all the vertices in a priority queue.  Events are processed in   * lexicographic order, ie.   *   *	e1 < e2  iff  e1.x < e2.x || (e1.x == e2.x && e1.y < e2.y)   */  RemoveDegenerateEdges( tess );  if ( !InitPriorityQ( tess ) ) return 0; /* if error */  InitEdgeDict( tess );  /* __gl_pqSortExtractMin */  while( (v = (GLUvertex *)pqExtractMin( tess->pq )) != NULL ) {    for( ;; ) {      vNext = (GLUvertex *)pqMinimum( tess->pq ); /* __gl_pqSortMinimum */      if( vNext == NULL || ! VertEq( vNext, v )) break;      /* Merge together all vertices at exactly the same location.       * This is more efficient than processing them one at a time,       * simplifies the code (see ConnectLeftDegenerate), and is also       * important for correct handling of certain degenerate cases.       * For example, suppose there are two identical edges A and B       * that belong to different contours (so without this code they would       * be processed by separate sweep events).  Suppose another edge C       * crosses A and B from above.  When A is processed, we split it       * at its intersection point with C.  However this also splits C,       * so when we insert B we may compute a slightly different       * intersection point.  This might leave two edges with a small       * gap between them.  This kind of error is especially obvious       * when using boundary extraction (GLU_TESS_BOUNDARY_ONLY).       */      vNext = (GLUvertex *)pqExtractMin( tess->pq ); /* __gl_pqSortExtractMin*/      SpliceMergeVertices( tess, v->anEdge, vNext->anEdge );    }    SweepEvent( tess, v );  }  /* Set tess->event for debugging purposes */  /* __GL_DICTLISTKEY */ /* __GL_DICTLISTMIN */  tess->event = ((ActiveRegion *) dictKey( dictMin( tess->dict )))->eUp->Org;  DebugEvent( tess );  DoneEdgeDict( tess );  DonePriorityQ( tess );  if ( !RemoveDegenerateFaces( tess->mesh ) ) return 0;  __gl_meshCheckMesh( tess->mesh );  return 1;}

⌨️ 快捷键说明

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