Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentess.c
Go to the documentation of this file.
00001 /* 00002 ** License Applicability. Except to the extent portions of this file are 00003 ** made subject to an alternative license as permitted in the SGI Free 00004 ** Software License B, Version 1.1 (the "License"), the contents of this 00005 ** file are subject only to the provisions of the License. You may not use 00006 ** this file except in compliance with the License. You may obtain a copy 00007 ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 00008 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: 00009 ** 00010 ** http://oss.sgi.com/projects/FreeB 00011 ** 00012 ** Note that, as provided in the License, the Software is distributed on an 00013 ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS 00014 ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND 00015 ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A 00016 ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. 00017 ** 00018 ** Original Code. The Original Code is: OpenGL Sample Implementation, 00019 ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, 00020 ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. 00021 ** Copyright in any portions created by third parties is as indicated 00022 ** elsewhere herein. All Rights Reserved. 00023 ** 00024 ** Additional Notice Provisions: The application programming interfaces 00025 ** established by SGI in conjunction with the Original Code are The 00026 ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released 00027 ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version 00028 ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X 00029 ** Window System(R) (Version 1.3), released October 19, 1998. This software 00030 ** was created using the OpenGL(R) version 1.2.1 Sample Implementation 00031 ** published by SGI, but has not been independently verified as being 00032 ** compliant with the OpenGL(R) version 1.2.1 Specification. 00033 ** 00034 */ 00035 /* 00036 ** Author: Eric Veach, July 1994. 00037 ** 00038 */ 00039 00040 #include "gluos.h" 00041 #include <stddef.h> 00042 #include <assert.h> 00043 #include <setjmp.h> 00044 #include "memalloc.h" 00045 #include "tess.h" 00046 #include "mesh.h" 00047 #include "normal.h" 00048 #include "sweep.h" 00049 #include "tessmono.h" 00050 #include "render.h" 00051 00052 #define GLU_TESS_DEFAULT_TOLERANCE 0.0 00053 #define GLU_TESS_MESH 100112 /* void (*)(GLUmesh *mesh) */ 00054 00055 #define TRUE 1 00056 #define FALSE 0 00057 00058 /*ARGSUSED*/ static void GLAPIENTRY noBegin( GLenum type ) {} 00059 /*ARGSUSED*/ static void GLAPIENTRY noEdgeFlag( GLboolean boundaryEdge ) {} 00060 /*ARGSUSED*/ static void GLAPIENTRY noVertex( void *data ) {} 00061 /*ARGSUSED*/ static void GLAPIENTRY noEnd( void ) {} 00062 /*ARGSUSED*/ static void GLAPIENTRY noError( GLenum errnum ) {} 00063 /*ARGSUSED*/ static void GLAPIENTRY noCombine( GLdouble coords[3], void *data[4], 00064 GLfloat weight[4], void **dataOut ) {} 00065 /*ARGSUSED*/ static void GLAPIENTRY noMesh( GLUmesh *mesh ) {} 00066 00067 00068 /*ARGSUSED*/ void GLAPIENTRY __gl_noBeginData( GLenum type, 00069 void *polygonData ) {} 00070 /*ARGSUSED*/ void GLAPIENTRY __gl_noEdgeFlagData( GLboolean boundaryEdge, 00071 void *polygonData ) {} 00072 /*ARGSUSED*/ void GLAPIENTRY __gl_noVertexData( void *data, 00073 void *polygonData ) {} 00074 /*ARGSUSED*/ void GLAPIENTRY __gl_noEndData( void *polygonData ) {} 00075 /*ARGSUSED*/ void GLAPIENTRY __gl_noErrorData( GLenum errnum, 00076 void *polygonData ) {} 00077 /*ARGSUSED*/ void GLAPIENTRY __gl_noCombineData( GLdouble coords[3], 00078 void *data[4], 00079 GLfloat weight[4], 00080 void **outData, 00081 void *polygonData ) {} 00082 00083 /* Half-edges are allocated in pairs (see mesh.c) */ 00084 typedef struct { GLUhalfEdge e, eSym; } EdgePair; 00085 00086 #undef MAX 00087 #define MAX(a,b) ((a) > (b) ? (a) : (b)) 00088 #define MAX_FAST_ALLOC (MAX(sizeof(EdgePair), \ 00089 MAX(sizeof(GLUvertex),sizeof(GLUface)))) 00090 00091 00092 GLUtesselator * GLAPIENTRY 00093 gluNewTess( void ) 00094 { 00095 GLUtesselator *tess; 00096 00097 /* Only initialize fields which can be changed by the api. Other fields 00098 * are initialized where they are used. 00099 */ 00100 00101 if (memInit( MAX_FAST_ALLOC ) == 0) { 00102 return 0; /* out of memory */ 00103 } 00104 tess = (GLUtesselator *)memAlloc( sizeof( GLUtesselator )); 00105 if (tess == NULL) { 00106 return 0; /* out of memory */ 00107 } 00108 00109 tess->state = T_DORMANT; 00110 00111 tess->normal[0] = 0; 00112 tess->normal[1] = 0; 00113 tess->normal[2] = 0; 00114 00115 tess->relTolerance = GLU_TESS_DEFAULT_TOLERANCE; 00116 tess->windingRule = GLU_TESS_WINDING_ODD; 00117 tess->flagBoundary = FALSE; 00118 tess->boundaryOnly = FALSE; 00119 00120 tess->callBegin = &noBegin; 00121 tess->callEdgeFlag = &noEdgeFlag; 00122 tess->callVertex = &noVertex; 00123 tess->callEnd = &noEnd; 00124 00125 tess->callError = &noError; 00126 tess->callCombine = &noCombine; 00127 tess->callMesh = &noMesh; 00128 00129 tess->callBeginData= &__gl_noBeginData; 00130 tess->callEdgeFlagData= &__gl_noEdgeFlagData; 00131 tess->callVertexData= &__gl_noVertexData; 00132 tess->callEndData= &__gl_noEndData; 00133 tess->callErrorData= &__gl_noErrorData; 00134 tess->callCombineData= &__gl_noCombineData; 00135 00136 tess->polygonData= NULL; 00137 00138 return tess; 00139 } 00140 00141 static void MakeDormant( GLUtesselator *tess ) 00142 { 00143 /* Return the tessellator to its original dormant state. */ 00144 00145 if( tess->mesh != NULL ) { 00146 __gl_meshDeleteMesh( tess->mesh ); 00147 } 00148 tess->state = T_DORMANT; 00149 tess->lastEdge = NULL; 00150 tess->mesh = NULL; 00151 } 00152 00153 #define RequireState( tess, s ) if( tess->state != s ) GotoState(tess,s) 00154 00155 static void GotoState( GLUtesselator *tess, enum TessState newState ) 00156 { 00157 while( tess->state != newState ) { 00158 /* We change the current state one level at a time, to get to 00159 * the desired state. 00160 */ 00161 if( tess->state < newState ) { 00162 switch( tess->state ) { 00163 case T_DORMANT: 00164 CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_BEGIN_POLYGON ); 00165 gluTessBeginPolygon( tess, NULL ); 00166 break; 00167 case T_IN_POLYGON: 00168 CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_BEGIN_CONTOUR ); 00169 gluTessBeginContour( tess ); 00170 break; 00171 default: 00172 ; 00173 } 00174 } else { 00175 switch( tess->state ) { 00176 case T_IN_CONTOUR: 00177 CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_END_CONTOUR ); 00178 gluTessEndContour( tess ); 00179 break; 00180 case T_IN_POLYGON: 00181 CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_END_POLYGON ); 00182 /* gluTessEndPolygon( tess ) is too much work! */ 00183 MakeDormant( tess ); 00184 break; 00185 default: 00186 ; 00187 } 00188 } 00189 } 00190 } 00191 00192 00193 void GLAPIENTRY 00194 gluDeleteTess( GLUtesselator *tess ) 00195 { 00196 RequireState( tess, T_DORMANT ); 00197 memFree( tess ); 00198 } 00199 00200 00201 void GLAPIENTRY 00202 gluTessProperty( GLUtesselator *tess, GLenum which, GLdouble value ) 00203 { 00204 GLenum windingRule; 00205 00206 switch( which ) { 00207 case GLU_TESS_TOLERANCE: 00208 if( value < 0.0 || value > 1.0 ) break; 00209 tess->relTolerance = value; 00210 return; 00211 00212 case GLU_TESS_WINDING_RULE: 00213 windingRule = (GLenum) value; 00214 if( windingRule != value ) break; /* not an integer */ 00215 00216 switch( windingRule ) { 00217 case GLU_TESS_WINDING_ODD: 00218 case GLU_TESS_WINDING_NONZERO: 00219 case GLU_TESS_WINDING_POSITIVE: 00220 case GLU_TESS_WINDING_NEGATIVE: 00221 case GLU_TESS_WINDING_ABS_GEQ_TWO: 00222 tess->windingRule = windingRule; 00223 return; 00224 default: 00225 break; 00226 } 00227 00228 case GLU_TESS_BOUNDARY_ONLY: 00229 tess->boundaryOnly = (value != 0); 00230 return; 00231 00232 default: 00233 CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_ENUM ); 00234 return; 00235 } 00236 CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_VALUE ); 00237 } 00238 00239 /* Returns tessellator property */ 00240 void GLAPIENTRY 00241 gluGetTessProperty( GLUtesselator *tess, GLenum which, GLdouble *value ) 00242 { 00243 switch (which) { 00244 case GLU_TESS_TOLERANCE: 00245 /* tolerance should be in range [0..1] */ 00246 assert(0.0 <= tess->relTolerance && tess->relTolerance <= 1.0); 00247 *value= tess->relTolerance; 00248 break; 00249 case GLU_TESS_WINDING_RULE: 00250 assert(tess->windingRule == GLU_TESS_WINDING_ODD || 00251 tess->windingRule == GLU_TESS_WINDING_NONZERO || 00252 tess->windingRule == GLU_TESS_WINDING_POSITIVE || 00253 tess->windingRule == GLU_TESS_WINDING_NEGATIVE || 00254 tess->windingRule == GLU_TESS_WINDING_ABS_GEQ_TWO); 00255 *value= tess->windingRule; 00256 break; 00257 case GLU_TESS_BOUNDARY_ONLY: 00258 assert(tess->boundaryOnly == TRUE || tess->boundaryOnly == FALSE); 00259 *value= tess->boundaryOnly; 00260 break; 00261 default: 00262 *value= 0.0; 00263 CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_ENUM ); 00264 break; 00265 } 00266 } /* gluGetTessProperty() */ 00267 00268 void GLAPIENTRY 00269 gluTessNormal( GLUtesselator *tess, GLdouble x, GLdouble y, GLdouble z ) 00270 { 00271 tess->normal[0] = x; 00272 tess->normal[1] = y; 00273 tess->normal[2] = z; 00274 } 00275 00276 void GLAPIENTRY 00277 gluTessCallback( GLUtesselator *tess, GLenum which, _GLUfuncptr fn) 00278 { 00279 switch( which ) { 00280 case GLU_TESS_BEGIN: 00281 tess->callBegin = (fn == NULL) ? &noBegin : (void (GLAPIENTRY *)(GLenum)) fn; 00282 return; 00283 case GLU_TESS_BEGIN_DATA: 00284 tess->callBeginData = (fn == NULL) ? 00285 &__gl_noBeginData : (void (GLAPIENTRY *)(GLenum, void *)) fn; 00286 return; 00287 case GLU_TESS_EDGE_FLAG: 00288 tess->callEdgeFlag = (fn == NULL) ? &noEdgeFlag : 00289 (void (GLAPIENTRY *)(GLboolean)) fn; 00290 /* If the client wants boundary edges to be flagged, 00291 * we render everything as separate triangles (no strips or fans). 00292 */ 00293 tess->flagBoundary = (fn != NULL); 00294 return; 00295 case GLU_TESS_EDGE_FLAG_DATA: 00296 tess->callEdgeFlagData= (fn == NULL) ? 00297 &__gl_noEdgeFlagData : (void (GLAPIENTRY *)(GLboolean, void *)) fn; 00298 /* If the client wants boundary edges to be flagged, 00299 * we render everything as separate triangles (no strips or fans). 00300 */ 00301 tess->flagBoundary = (fn != NULL); 00302 return; 00303 case GLU_TESS_VERTEX: 00304 tess->callVertex = (fn == NULL) ? &noVertex : 00305 (void (GLAPIENTRY *)(void *)) fn; 00306 return; 00307 case GLU_TESS_VERTEX_DATA: 00308 tess->callVertexData = (fn == NULL) ? 00309 &__gl_noVertexData : (void (GLAPIENTRY *)(void *, void *)) fn; 00310 return; 00311 case GLU_TESS_END: 00312 tess->callEnd = (fn == NULL) ? &noEnd : (void (GLAPIENTRY *)(void)) fn; 00313 return; 00314 case GLU_TESS_END_DATA: 00315 tess->callEndData = (fn == NULL) ? &__gl_noEndData : 00316 (void (GLAPIENTRY *)(void *)) fn; 00317 return; 00318 case GLU_TESS_ERROR: 00319 tess->callError = (fn == NULL) ? &noError : (void (GLAPIENTRY *)(GLenum)) fn; 00320 return; 00321 case GLU_TESS_ERROR_DATA: 00322 tess->callErrorData = (fn == NULL) ? 00323 &__gl_noErrorData : (void (GLAPIENTRY *)(GLenum, void *)) fn; 00324 return; 00325 case GLU_TESS_COMBINE: 00326 tess->callCombine = (fn == NULL) ? &noCombine : 00327 (void (GLAPIENTRY *)(GLdouble [3],void *[4], GLfloat [4], void ** )) fn; 00328 return; 00329 case GLU_TESS_COMBINE_DATA: 00330 tess->callCombineData = (fn == NULL) ? &__gl_noCombineData : 00331 (void (GLAPIENTRY *)(GLdouble [3], 00332 void *[4], 00333 GLfloat [4], 00334 void **, 00335 void *)) fn; 00336 return; 00337 case GLU_TESS_MESH: 00338 tess->callMesh = (fn == NULL) ? &noMesh : (void (GLAPIENTRY *)(GLUmesh *)) fn; 00339 return; 00340 default: 00341 CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_ENUM ); 00342 return; 00343 } 00344 } 00345 00346 static int AddVertex( GLUtesselator *tess, GLdouble coords[3], void *data ) 00347 { 00348 GLUhalfEdge *e; 00349 00350 e = tess->lastEdge; 00351 if( e == NULL ) { 00352 /* Make a self-loop (one vertex, one edge). */ 00353 00354 e = __gl_meshMakeEdge( tess->mesh ); 00355 if (e == NULL) return 0; 00356 if ( !__gl_meshSplice( e, e->Sym ) ) return 0; 00357 } else { 00358 /* Create a new vertex and edge which immediately follow e 00359 * in the ordering around the left face. 00360 */ 00361 if (__gl_meshSplitEdge( e ) == NULL) return 0; 00362 e = e->Lnext; 00363 } 00364 00365 /* The new vertex is now e->Org. */ 00366 e->Org->data = data; 00367 e->Org->coords[0] = coords[0]; 00368 e->Org->coords[1] = coords[1]; 00369 e->Org->coords[2] = coords[2]; 00370 00371 /* The winding of an edge says how the winding number changes as we 00372 * cross from the edge''s right face to its left face. We add the 00373 * vertices in such an order that a CCW contour will add +1 to 00374 * the winding number of the region inside the contour. 00375 */ 00376 e->winding = 1; 00377 e->Sym->winding = -1; 00378 00379 tess->lastEdge = e; 00380 00381 return 1; 00382 } 00383 00384 00385 static void CacheVertex( GLUtesselator *tess, GLdouble coords[3], void *data ) 00386 { 00387 CachedVertex *v = &tess->cache[tess->cacheCount]; 00388 00389 v->data = data; 00390 v->coords[0] = coords[0]; 00391 v->coords[1] = coords[1]; 00392 v->coords[2] = coords[2]; 00393 ++tess->cacheCount; 00394 } 00395 00396 00397 static int EmptyCache( GLUtesselator *tess ) 00398 { 00399 CachedVertex *v = tess->cache; 00400 CachedVertex *vLast; 00401 00402 tess->mesh = __gl_meshNewMesh(); 00403 if (tess->mesh == NULL) return 0; 00404 00405 for( vLast = v + tess->cacheCount; v < vLast; ++v ) { 00406 if ( !AddVertex( tess, v->coords, v->data ) ) return 0; 00407 } 00408 tess->cacheCount = 0; 00409 tess->emptyCache = FALSE; 00410 00411 return 1; 00412 } 00413 00414 00415 void GLAPIENTRY 00416 gluTessVertex( GLUtesselator *tess, GLdouble coords[3], void *data ) 00417 { 00418 int i, tooLarge = FALSE; 00419 GLdouble x, clamped[3]; 00420 00421 RequireState( tess, T_IN_CONTOUR ); 00422 00423 if( tess->emptyCache ) { 00424 if ( !EmptyCache( tess ) ) { 00425 CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY ); 00426 return; 00427 } 00428 tess->lastEdge = NULL; 00429 } 00430 for( i = 0; i < 3; ++i ) { 00431 x = coords[i]; 00432 if( x < - GLU_TESS_MAX_COORD ) { 00433 x = - GLU_TESS_MAX_COORD; 00434 tooLarge = TRUE; 00435 } 00436 if( x > GLU_TESS_MAX_COORD ) { 00437 x = GLU_TESS_MAX_COORD; 00438 tooLarge = TRUE; 00439 } 00440 clamped[i] = x; 00441 } 00442 if( tooLarge ) { 00443 CALL_ERROR_OR_ERROR_DATA( GLU_TESS_COORD_TOO_LARGE ); 00444 } 00445 00446 if( tess->mesh == NULL ) { 00447 if( tess->cacheCount < TESS_MAX_CACHE ) { 00448 CacheVertex( tess, clamped, data ); 00449 return; 00450 } 00451 if ( !EmptyCache( tess ) ) { 00452 CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY ); 00453 return; 00454 } 00455 } 00456 if ( !AddVertex( tess, clamped, data ) ) { 00457 CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY ); 00458 } 00459 } 00460 00461 00462 void GLAPIENTRY 00463 gluTessBeginPolygon( GLUtesselator *tess, void *data ) 00464 { 00465 RequireState( tess, T_DORMANT ); 00466 00467 tess->state = T_IN_POLYGON; 00468 tess->cacheCount = 0; 00469 tess->emptyCache = FALSE; 00470 tess->mesh = NULL; 00471 00472 tess->polygonData= data; 00473 } 00474 00475 00476 void GLAPIENTRY 00477 gluTessBeginContour( GLUtesselator *tess ) 00478 { 00479 RequireState( tess, T_IN_POLYGON ); 00480 00481 tess->state = T_IN_CONTOUR; 00482 tess->lastEdge = NULL; 00483 if( tess->cacheCount > 0 ) { 00484 /* Just set a flag so we don't get confused by empty contours 00485 * -- these can be generated accidentally with the obsolete 00486 * NextContour() interface. 00487 */ 00488 tess->emptyCache = TRUE; 00489 } 00490 } 00491 00492 00493 void GLAPIENTRY 00494 gluTessEndContour( GLUtesselator *tess ) 00495 { 00496 RequireState( tess, T_IN_CONTOUR ); 00497 tess->state = T_IN_POLYGON; 00498 } 00499 00500 void GLAPIENTRY 00501 gluTessEndPolygon( GLUtesselator *tess ) 00502 { 00503 GLUmesh *mesh; 00504 00505 if (setjmp(tess->env) != 0) { 00506 /* come back here if out of memory */ 00507 CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY ); 00508 return; 00509 } 00510 00511 RequireState( tess, T_IN_POLYGON ); 00512 tess->state = T_DORMANT; 00513 00514 if( tess->mesh == NULL ) { 00515 if( ! tess->flagBoundary && tess->callMesh == &noMesh ) { 00516 00517 /* Try some special code to make the easy cases go quickly 00518 * (eg. convex polygons). This code does NOT handle multiple contours, 00519 * intersections, edge flags, and of course it does not generate 00520 * an explicit mesh either. 00521 */ 00522 if( __gl_renderCache( tess )) { 00523 tess->polygonData= NULL; 00524 return; 00525 } 00526 } 00527 if ( !EmptyCache( tess ) ) longjmp(tess->env,1); /* could've used a label*/ 00528 } 00529 00530 /* Determine the polygon normal and project vertices onto the plane 00531 * of the polygon. 00532 */ 00533 __gl_projectPolygon( tess ); 00534 00535 /* __gl_computeInterior( tess ) computes the planar arrangement specified 00536 * by the given contours, and further subdivides this arrangement 00537 * into regions. Each region is marked "inside" if it belongs 00538 * to the polygon, according to the rule given by tess->windingRule. 00539 * Each interior region is guaranteed be monotone. 00540 */ 00541 if ( !__gl_computeInterior( tess ) ) { 00542 longjmp(tess->env,1); /* could've used a label */ 00543 } 00544 00545 mesh = tess->mesh; 00546 if( ! tess->fatalError ) { 00547 int rc = 1; 00548 00549 /* If the user wants only the boundary contours, we throw away all edges 00550 * except those which separate the interior from the exterior. 00551 * Otherwise we tessellate all the regions marked "inside". 00552 */ 00553 if( tess->boundaryOnly ) { 00554 rc = __gl_meshSetWindingNumber( mesh, 1, TRUE ); 00555 } else { 00556 rc = __gl_meshTessellateInterior( mesh ); 00557 } 00558 if (rc == 0) longjmp(tess->env,1); /* could've used a label */ 00559 00560 __gl_meshCheckMesh( mesh ); 00561 00562 if( tess->callBegin != &noBegin || tess->callEnd != &noEnd 00563 || tess->callVertex != &noVertex || tess->callEdgeFlag != &noEdgeFlag 00564 || tess->callBeginData != &__gl_noBeginData 00565 || tess->callEndData != &__gl_noEndData 00566 || tess->callVertexData != &__gl_noVertexData 00567 || tess->callEdgeFlagData != &__gl_noEdgeFlagData ) 00568 { 00569 if( tess->boundaryOnly ) { 00570 __gl_renderBoundary( tess, mesh ); /* output boundary contours */ 00571 } else { 00572 __gl_renderMesh( tess, mesh ); /* output strips and fans */ 00573 } 00574 } 00575 if( tess->callMesh != &noMesh ) { 00576 00577 /* Throw away the exterior faces, so that all faces are interior. 00578 * This way the user doesn't have to check the "inside" flag, 00579 * and we don't need to even reveal its existence. It also leaves 00580 * the freedom for an implementation to not generate the exterior 00581 * faces in the first place. 00582 */ 00583 __gl_meshDiscardExterior( mesh ); 00584 (*tess->callMesh)( mesh ); /* user wants the mesh itself */ 00585 tess->mesh = NULL; 00586 tess->polygonData= NULL; 00587 return; 00588 } 00589 } 00590 __gl_meshDeleteMesh( mesh ); 00591 tess->polygonData= NULL; 00592 tess->mesh = NULL; 00593 } 00594 00595 00596 /*XXXblythe unused function*/ 00597 #if 0 00598 void GLAPIENTRY 00599 gluDeleteMesh( GLUmesh *mesh ) 00600 { 00601 __gl_meshDeleteMesh( mesh ); 00602 } 00603 #endif 00604 00605 00606 00607 /*******************************************************/ 00608 00609 /* Obsolete calls -- for backward compatibility */ 00610 00611 void GLAPIENTRY 00612 gluBeginPolygon( GLUtesselator *tess ) 00613 { 00614 gluTessBeginPolygon( tess, NULL ); 00615 gluTessBeginContour( tess ); 00616 } 00617 00618 00619 /*ARGSUSED*/ 00620 void GLAPIENTRY 00621 gluNextContour( GLUtesselator *tess, GLenum type ) 00622 { 00623 gluTessEndContour( tess ); 00624 gluTessBeginContour( tess ); 00625 } 00626 00627 00628 void GLAPIENTRY 00629 gluEndPolygon( GLUtesselator *tess ) 00630 { 00631 gluTessEndContour( tess ); 00632 gluTessEndPolygon( tess ); 00633 } Generated on Fri May 25 2012 04:21:58 for ReactOS by
1.7.6.1
|