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

📄 tess.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 2 页
字号:
  case GLU_TESS_ERROR_DATA:    tess->callErrorData = (fn == NULL) ?	&__gl_noErrorData : (void (GLAPIENTRY *)(GLenum, void *)) fn;    return;  case GLU_TESS_COMBINE:    tess->callCombine = (fn == NULL) ? &noCombine :	(void (GLAPIENTRY *)(GLdouble [3],void *[4], GLfloat [4], void ** )) fn;    return;  case GLU_TESS_COMBINE_DATA:    tess->callCombineData = (fn == NULL) ? &__gl_noCombineData :					   (void (GLAPIENTRY *)(GLdouble [3],						     void *[4],						     GLfloat [4],						     void **,						     void *)) fn;    return;  case GLU_TESS_MESH:    tess->callMesh = (fn == NULL) ? &noMesh : (void (GLAPIENTRY *)(GLUmesh *)) fn;    return;  default:    CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_ENUM );    return;  }}static int AddVertex( GLUtesselator *tess, GLdouble coords[3], void *data ){  GLUhalfEdge *e;  e = tess->lastEdge;  if( e == NULL ) {    /* Make a self-loop (one vertex, one edge). */    e = __gl_meshMakeEdge( tess->mesh );    if (e == NULL) return 0;    if ( !__gl_meshSplice( e, e->Sym ) ) return 0;  } else {    /* Create a new vertex and edge which immediately follow e     * in the ordering around the left face.     */    if (__gl_meshSplitEdge( e ) == NULL) return 0;    e = e->Lnext;  }  /* The new vertex is now e->Org. */  e->Org->data = data;  e->Org->coords[0] = coords[0];  e->Org->coords[1] = coords[1];  e->Org->coords[2] = coords[2];  /* The winding of an edge says how the winding number changes as we   * cross from the edge''s right face to its left face.  We add the   * vertices in such an order that a CCW contour will add +1 to   * the winding number of the region inside the contour.   */  e->winding = 1;  e->Sym->winding = -1;  tess->lastEdge = e;  return 1;}static void CacheVertex( GLUtesselator *tess, GLdouble coords[3], void *data ){  CachedVertex *v = &tess->cache[tess->cacheCount];  v->data = data;  v->coords[0] = coords[0];  v->coords[1] = coords[1];  v->coords[2] = coords[2];  ++tess->cacheCount;}static int EmptyCache( GLUtesselator *tess ){  CachedVertex *v = tess->cache;  CachedVertex *vLast;  tess->mesh = __gl_meshNewMesh();  if (tess->mesh == NULL) return 0;  for( vLast = v + tess->cacheCount; v < vLast; ++v ) {    if ( !AddVertex( tess, v->coords, v->data ) ) return 0;  }  tess->cacheCount = 0;  tess->emptyCache = FALSE;  return 1;}void GLAPIENTRYgluTessVertex( GLUtesselator *tess, GLdouble coords[3], void *data ){  int i, tooLarge = FALSE;  GLdouble x, clamped[3];  RequireState( tess, T_IN_CONTOUR );  if( tess->emptyCache ) {    if ( !EmptyCache( tess ) ) {       CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY );       return;    }    tess->lastEdge = NULL;  }  for( i = 0; i < 3; ++i ) {    x = coords[i];    if( x < - GLU_TESS_MAX_COORD ) {      x = - GLU_TESS_MAX_COORD;      tooLarge = TRUE;    }    if( x > GLU_TESS_MAX_COORD ) {      x = GLU_TESS_MAX_COORD;      tooLarge = TRUE;    }    clamped[i] = x;  }  if( tooLarge ) {    CALL_ERROR_OR_ERROR_DATA( GLU_TESS_COORD_TOO_LARGE );  }  if( tess->mesh == NULL ) {    if( tess->cacheCount < TESS_MAX_CACHE ) {      CacheVertex( tess, clamped, data );      return;    }    if ( !EmptyCache( tess ) ) {       CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY );       return;    }  }  if ( !AddVertex( tess, clamped, data ) ) {       CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY );  }}void GLAPIENTRYgluTessBeginPolygon( GLUtesselator *tess, void *data ){  RequireState( tess, T_DORMANT );  tess->state = T_IN_POLYGON;  tess->cacheCount = 0;  tess->emptyCache = FALSE;  tess->mesh = NULL;  tess->polygonData= data;}void GLAPIENTRYgluTessBeginContour( GLUtesselator *tess ){  RequireState( tess, T_IN_POLYGON );  tess->state = T_IN_CONTOUR;  tess->lastEdge = NULL;  if( tess->cacheCount > 0 ) {    /* Just set a flag so we don't get confused by empty contours     * -- these can be generated accidentally with the obsolete     * NextContour() interface.     */    tess->emptyCache = TRUE;  }}void GLAPIENTRYgluTessEndContour( GLUtesselator *tess ){  RequireState( tess, T_IN_CONTOUR );  tess->state = T_IN_POLYGON;}void GLAPIENTRYgluTessEndPolygon( GLUtesselator *tess ){  GLUmesh *mesh;  if (setjmp(tess->env) != 0) {      /* come back here if out of memory */     CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY );     return;  }  RequireState( tess, T_IN_POLYGON );  tess->state = T_DORMANT;  if( tess->mesh == NULL ) {    if( ! tess->flagBoundary && tess->callMesh == &noMesh ) {      /* Try some special code to make the easy cases go quickly       * (eg. convex polygons).  This code does NOT handle multiple contours,       * intersections, edge flags, and of course it does not generate       * an explicit mesh either.       */      if( __gl_renderCache( tess )) {	tess->polygonData= NULL;	return;      }    }    if ( !EmptyCache( tess ) ) longjmp(tess->env,1); /* could've used a label*/  }  /* Determine the polygon normal and project vertices onto the plane   * of the polygon.   */  __gl_projectPolygon( 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.   */  if ( !__gl_computeInterior( tess ) ) {     longjmp(tess->env,1);	/* could've used a label */  }  mesh = tess->mesh;  if( ! tess->fatalError ) {    int rc = 1;    /* If the user wants only the boundary contours, we throw away all edges     * except those which separate the interior from the exterior.     * Otherwise we tessellate all the regions marked "inside".     */    if( tess->boundaryOnly ) {      rc = __gl_meshSetWindingNumber( mesh, 1, TRUE );    } else {      rc = __gl_meshTessellateInterior( mesh );    }    if (rc == 0) longjmp(tess->env,1);	/* could've used a label */    __gl_meshCheckMesh( mesh );    if( tess->callBegin != &noBegin || tess->callEnd != &noEnd       || tess->callVertex != &noVertex || tess->callEdgeFlag != &noEdgeFlag       || tess->callBeginData != &__gl_noBeginData       || tess->callEndData != &__gl_noEndData       || tess->callVertexData != &__gl_noVertexData       || tess->callEdgeFlagData != &__gl_noEdgeFlagData )    {      if( tess->boundaryOnly ) {	__gl_renderBoundary( tess, mesh );  /* output boundary contours */      } else {	__gl_renderMesh( tess, mesh );	   /* output strips and fans */      }    }    if( tess->callMesh != &noMesh ) {      /* Throw away the exterior faces, so that all faces are interior.       * This way the user doesn't have to check the "inside" flag,       * and we don't need to even reveal its existence.  It also leaves       * the freedom for an implementation to not generate the exterior       * faces in the first place.       */      __gl_meshDiscardExterior( mesh );      (*tess->callMesh)( mesh );		/* user wants the mesh itself */      tess->mesh = NULL;      tess->polygonData= NULL;      return;    }  }  __gl_meshDeleteMesh( mesh );  tess->polygonData= NULL;  tess->mesh = NULL;}/*XXXblythe unused function*/#if 0void GLAPIENTRYgluDeleteMesh( GLUmesh *mesh ){  __gl_meshDeleteMesh( mesh );}#endif/*******************************************************//* Obsolete calls -- for backward compatibility */void GLAPIENTRYgluBeginPolygon( GLUtesselator *tess ){  gluTessBeginPolygon( tess, NULL );  gluTessBeginContour( tess );}/*ARGSUSED*/void GLAPIENTRYgluNextContour( GLUtesselator *tess, GLenum type ){  gluTessEndContour( tess );  gluTessBeginContour( tess );}void GLAPIENTRYgluEndPolygon( GLUtesselator *tess ){  gluTessEndContour( tess );  gluTessEndPolygon( tess );}

⌨️ 快捷键说明

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