/* ** License Applicability. Except to the extent portions of this file are ** made subject to an alternative license as permitted in the SGI Free ** Software License B, Version 1.1 (the "License"), the contents of this ** file are subject only to the provisions of the License. You may not use ** this file except in compliance with the License. You may obtain a copy ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: ** ** http://oss.sgi.com/projects/FreeB ** ** Note that, as provided in the License, the Software is distributed on an ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. ** ** Original Code. The Original Code is: OpenGL Sample Implementation, ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. ** Copyright in any portions created by third parties is as indicated ** elsewhere herein. All Rights Reserved. ** ** Additional Notice Provisions: The application programming interfaces ** established by SGI in conjunction with the Original Code are The ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X ** Window System(R) (Version 1.3), released October 19, 1998. This software ** was created using the OpenGL(R) version 1.2.1 Sample Implementation ** published by SGI, but has not been independently verified as being ** compliant with the OpenGL(R) version 1.2.1 Specification. */ /* * glsurfeval.c++ * */ /* Polynomial Evaluator Interface */ #include "gluos.h" #include #include "glimports.h" #include "glrenderer.h" #include "glsurfeval.h" #include "nurbsconsts.h" #include "bezierPatchMesh.h" //extern int surfcount; //int surfcount=0; /*#define USE_INTERNAL_EVAL*/ //use internal evaluator /*whether do evaluation or not*/ /*#define NO_EVALUATION*/ //#define USE_LOD //for LOD test, have to turn on USE_LOD in insurfeval.c++ too /*for statistics*/ //#define STATISTICS #ifdef STATISTICS static int STAT_num_of_triangles=0; static int STAT_num_of_eval_vertices=0; static int STAT_num_of_quad_strips=0; #endif /*for output triangles*/ /*#define OUTPUT_TRIANGLES*/ /*#define FOR_CHRIS*/ #ifdef FOR_CHRIS extern "C" { void evalUStripExt(int n_upper, REAL v_upper, REAL* upper_val, int n_lower, REAL v_lower, REAL* lower_val);} extern "C" { void evalVStripExt(int n_left, REAL u_left, REAL* left_val, int n_right, REAL u_right, REAL* right_val); } #endif /**************begin for LOD_eval_list***********/ void OpenGLSurfaceEvaluator::LOD_eval_list(int level) { if(level == 0) LOD_eval_level = 1; else if(level == 1) LOD_eval_level = 2; else if(level == 2) LOD_eval_level = 4; else LOD_eval_level = 8; inBPMListEvalEM(global_bpm); } OpenGLSurfaceEvaluator::OpenGLSurfaceEvaluator() { int i; for (i=0; iSetState((GLenum) type, GL_FALSE); } /*--------------------------------------------------------------------------- * enable - turn on a map *--------------------------------------------------------------------------- */ void OpenGLSurfaceEvaluator::enable(long type) { m_Self->SetState((GLenum) type, GL_TRUE); } /*------------------------------------------------------------------------- * mapgrid2f - define a lattice of points with origin and offset *------------------------------------------------------------------------- */ void OpenGLSurfaceEvaluator::mapgrid2f(long nu, REAL u0, REAL u1, long nv, REAL v0, REAL v1) { #ifdef USE_INTERNAL_EVAL inMapGrid2f((int) nu, (REAL) u0, (REAL) u1, (int) nv, (REAL) v0, (REAL) v1); #else if(output_triangles) { global_grid_u0 = u0; global_grid_u1 = u1; global_grid_nu = nu; global_grid_v0 = v0; global_grid_v1 = v1; global_grid_nv = nv; } else m_Self->GLMapGrid2f((GLint) nu, (GLfloat) u0, (GLfloat) u1, (GLint) nv, (GLfloat) v0, (GLfloat) v1); #endif } void OpenGLSurfaceEvaluator::polymode(long style) { if(! output_triangles) { switch(style) { default: case N_MESHFILL: m_Self->GLPolygonMode((GLenum) GL_FRONT_AND_BACK, (GLenum) GL_FILL); break; case N_MESHLINE: m_Self->GLPolygonMode((GLenum) GL_FRONT_AND_BACK, (GLenum) GL_LINE); break; case N_MESHPOINT: m_Self->GLPolygonMode((GLenum) GL_FRONT_AND_BACK, (GLenum) GL_POINT); break; } } } void OpenGLSurfaceEvaluator::bgnline(void) { if(output_triangles) bezierPatchMeshBeginStrip(global_bpm, GL_LINE_STRIP); else m_Self->GLBegin((GLenum) GL_LINE_STRIP); } void OpenGLSurfaceEvaluator::endline(void) { if(output_triangles) bezierPatchMeshEndStrip(global_bpm); else m_Self->GLEnd(); } void OpenGLSurfaceEvaluator::range2f(long type, REAL *from, REAL *to) { } void OpenGLSurfaceEvaluator::domain2f(REAL ulo, REAL uhi, REAL vlo, REAL vhi) { } void OpenGLSurfaceEvaluator::bgnclosedline(void) { if(output_triangles) bezierPatchMeshBeginStrip(global_bpm, GL_LINE_LOOP); else m_Self->GLBegin((GLenum) GL_LINE_LOOP); } void OpenGLSurfaceEvaluator::endclosedline(void) { if(output_triangles) bezierPatchMeshEndStrip(global_bpm); else m_Self->GLEnd(); } void OpenGLSurfaceEvaluator::bgntmesh(void) { tmeshing = 1; which = 0; vcount = 0; if(output_triangles) bezierPatchMeshBeginStrip(global_bpm, GL_TRIANGLES); else m_Self->GLBegin((GLenum) GL_TRIANGLES); } void OpenGLSurfaceEvaluator::swaptmesh(void) { which = 1 - which; } void OpenGLSurfaceEvaluator::endtmesh(void) { tmeshing = 0; if(output_triangles) bezierPatchMeshEndStrip(global_bpm); else m_Self->GLEnd(); } void OpenGLSurfaceEvaluator::bgntfan(void) { if(output_triangles) bezierPatchMeshBeginStrip(global_bpm, GL_TRIANGLE_FAN); else m_Self->GLBegin((GLenum) GL_TRIANGLE_FAN); } void OpenGLSurfaceEvaluator::endtfan(void) { if(output_triangles) bezierPatchMeshEndStrip(global_bpm); else m_Self->GLEnd(); } void OpenGLSurfaceEvaluator::evalUStrip(int n_upper, REAL v_upper, REAL* upper_val, int n_lower, REAL v_lower, REAL* lower_val) { #ifdef USE_INTERNAL_EVAL inEvalUStrip(n_upper, v_upper, upper_val, n_lower, v_lower, lower_val); #else #ifdef FOR_CHRIS evalUStripExt(n_upper, v_upper, upper_val, n_lower, v_lower, lower_val); return; #endif int i,j,k,l; REAL leftMostV[2]; /* *the algorithm works by scanning from left to right. *leftMostV: the left most of the remaining verteces (on both upper and lower). * it could an element of upperVerts or lowerVerts. *i: upperVerts[i] is the first vertex to the right of leftMostV on upper line *j: lowerVerts[j] is the first vertex to the right of leftMostV on lower line */ /*initialize i,j,and leftMostV */ if(upper_val[0] <= lower_val[0]) { i=1; j=0; leftMostV[0] = upper_val[0]; leftMostV[1] = v_upper; } else { i=0; j=1; leftMostV[0] = lower_val[0]; leftMostV[1] = v_lower; } /*the main loop. *the invariance is that: *at the beginning of each loop, the meaning of i,j,and leftMostV are *maintained */ while(1) { if(i >= n_upper) /*case1: no more in upper*/ { if(j= n_lower) /*case2: no more in lower*/ { if(i=i; k--) /*reverse order for two-side lighting*/ { coord2f(upper_val[k], v_upper); // glNormal3fv(upperNormal[k]); // glVertex3fv(upperXYZ[k]); } endtfan(); } break; /*exit the main loop*/ } else /* case3: neither is empty, plus the leftMostV, there is at least one triangle to output*/ { if(upper_val[i] <= lower_val[j]) { bgntfan(); coord2f(lower_val[j], v_lower); // glNormal3fv(lowerNormal[j]); // glVertex3fv(lowerXYZ[j]); /*find the last k>=i such that *upperverts[k][0] <= lowerverts[j][0] */ k=i; while(k lower_val[j]) break; k++; } k--; for(l=k; l>=i; l--)/*the reverse is for two-side lighting*/ { coord2f(upper_val[l], v_upper); // glNormal3fv(upperNormal[l]); // glVertex3fv(upperXYZ[l]); } coord2f(leftMostV[0], leftMostV[1]); // glNormal3fv(leftMostNormal); // glVertex3fv(leftMostXYZ); endtfan(); /*update i and leftMostV for next loop */ i = k+1; leftMostV[0] = upper_val[k]; leftMostV[1] = v_upper; // leftMostNormal = upperNormal[k]; // leftMostXYZ = upperXYZ[k]; } else /*upperVerts[i][0] > lowerVerts[j][0]*/ { bgntfan(); coord2f(upper_val[i], v_upper); // glNormal3fv(upperNormal[i]); // glVertex3fv(upperXYZ[i]); coord2f(leftMostV[0], leftMostV[1]); // glNormal3fv(leftMostNormal); // glVertex3fv(leftMostXYZ); /*find the last k>=j such that *lowerverts[k][0] < upperverts[i][0] */ k=j; while(k< n_lower) { if(lower_val[k] >= upper_val[i]) break; coord2f(lower_val[k], v_lower); // glNormal3fv(lowerNormal[k]); // glVertex3fv(lowerXYZ[k]); k++; } endtfan(); /*update j and leftMostV for next loop */ j=k; leftMostV[0] = lower_val[j-1]; leftMostV[1] = v_lower; // leftMostNormal = lowerNormal[j-1]; // leftMostXYZ = lowerXYZ[j-1]; } } } //clean up // free(upperXYZ); // free(lowerXYZ); // free(upperNormal); // free(lowerNormal); #endif } void OpenGLSurfaceEvaluator::evalVStrip(int n_left, REAL u_left, REAL* left_val, int n_right, REAL u_right, REAL* right_val) { #ifdef USE_INTERNAL_EVAL inEvalVStrip(n_left, u_left, left_val, n_right, u_right, right_val); #else #ifdef FOR_CHRIS evalVStripExt(n_left, u_left, left_val, n_right, u_right, right_val); return; #endif int i,j,k,l; REAL botMostV[2]; /* *the algorithm works by scanning from bot to top. *botMostV: the bot most of the remaining verteces (on both left and right). * it could an element of leftVerts or rightVerts. *i: leftVerts[i] is the first vertex to the top of botMostV on left line *j: rightVerts[j] is the first vertex to the top of botMostV on rightline */ /*initialize i,j,and botMostV */ if(left_val[0] <= right_val[0]) { i=1; j=0; botMostV[0] = u_left; botMostV[1] = left_val[0]; } else { i=0; j=1; botMostV[0] = u_right; botMostV[1] = right_val[0]; } /*the main loop. *the invariance is that: *at the beginning of each loop, the meaning of i,j,and botMostV are *maintained */ while(1) { if(i >= n_left) /*case1: no more in left*/ { if(j= n_right) /*case2: no more in right*/ { if(i=i; k--) /*reverse order for two-side lighting*/ { coord2f(u_left, left_val[k]); // glNormal3fv(leftNormal[k]); // glVertex3fv(leftXYZ[k]); } endtfan(); } break; /*exit the main loop*/ } else /* case3: neither is empty, plus the botMostV, there is at least one triangle to output*/ { if(left_val[i] <= right_val[j]) { bgntfan(); coord2f(u_right, right_val[j]); // glNormal3fv(rightNormal[j]); // glVertex3fv(rightXYZ[j]); /*find the last k>=i such that *leftverts[k][0] <= rightverts[j][0] */ k=i; while(k right_val[j]) break; k++; } k--; for(l=k; l>=i; l--)/*the reverse is for two-side lighting*/ { coord2f(u_left, left_val[l]); // glNormal3fv(leftNormal[l]); // glVertex3fv(leftXYZ[l]); } coord2f(botMostV[0], botMostV[1]); // glNormal3fv(botMostNormal); // glVertex3fv(botMostXYZ); endtfan(); /*update i and botMostV for next loop */ i = k+1; botMostV[0] = u_left; botMostV[1] = left_val[k]; // botMostNormal = leftNormal[k]; // botMostXYZ = leftXYZ[k]; } else /*left_val[i] > right_val[j])*/ { bgntfan(); coord2f(u_left, left_val[i]); // glNormal3fv(leftNormal[i]); // glVertex3fv(leftXYZ[i]); coord2f(botMostV[0], botMostV[1]); // glNormal3fv(botMostNormal); // glVertex3fv(botMostXYZ); /*find the last k>=j such that *rightverts[k][0] < leftverts[i][0] */ k=j; while(k< n_right) { if(right_val[k] >= left_val[i]) break; coord2f(u_right, right_val[k]); // glNormal3fv(rightNormal[k]); // glVertex3fv(rightXYZ[k]); k++; } endtfan(); /*update j and botMostV for next loop */ j=k; botMostV[0] = u_right; botMostV[1] = right_val[j-1]; // botMostNormal = rightNormal[j-1]; // botMostXYZ = rightXYZ[j-1]; } } } //clean up // free(leftXYZ); // free(leftNormal); // free(rightXYZ); // free(rightNormal); #endif } void OpenGLSurfaceEvaluator::bgnqstrip(void) { if(output_triangles) bezierPatchMeshBeginStrip(global_bpm, GL_QUAD_STRIP); else m_Self->GLBegin((GLenum) GL_QUAD_STRIP); #ifdef STATISTICS STAT_num_of_quad_strips++; #endif } void OpenGLSurfaceEvaluator::endqstrip(void) { if(output_triangles) bezierPatchMeshEndStrip(global_bpm); else m_Self->GLEnd(); } /*------------------------------------------------------------------------- * bgnmap2f - preamble to surface definition and evaluations *------------------------------------------------------------------------- */ void OpenGLSurfaceEvaluator::bgnmap2f(long) { if(output_triangles) { /*deallocate the space which may has been *allocated by global_bpm previously */ if(global_bpm != NULL) { bezierPatchMeshListDelete(global_bpm); global_bpm = NULL; } /* auto_normal_flag = 1; //always output normal in callback mode. //we could have used the following code, //but Inspector doesn't have gl context //before it calls tessellator. //this way is temporary. */ //NEWCALLBACK //if one of the two normal callback functions are set, //then set if(normalCallBackN != NULL || normalCallBackData != NULL) auto_normal_flag = 1; else auto_normal_flag = 0; //initialize so that no maps initially vertex_flag = 0; normal_flag = 0; color_flag = 0; texcoord_flag = 0; /* if(glIsEnabled(GL_AUTO_NORMAL) == GL_TRUE) auto_normal_flag = 1; else if (callback_auto_normal == 1) auto_normal_flag = 1; else auto_normal_flag = 0; */ m_Self->GLPushAttrib((GLbitfield) GL_EVAL_BIT); } else { m_Self->GLPushAttrib((GLbitfield) GL_EVAL_BIT); /*to avoid side effect, we restor the opengl state for GL_POLYGON_MODE */ m_Self->GLGetIntegerv(GL_POLYGON_MODE, gl_polygon_mode); } } /*------------------------------------------------------------------------- * endmap2f - postamble to a map *------------------------------------------------------------------------- */ void OpenGLSurfaceEvaluator::endmap2f(void) { if(output_triangles) { //bezierPatchMeshListDelDeg(global_bpm); // bezierPatchMeshListEval(global_bpm); //surfcount++; //printf("surfcount=%i\n", surfcount); //if(surfcount == 8) exit(0); inBPMListEvalEM(global_bpm); /* global_bpm = bezierPatchMeshListReverse(global_bpm); { float *vertex_array; float *normal_array; int *length_array; int *type_array; int num_strips; bezierPatchMeshListCollect(global_bpm, &vertex_array, &normal_array, &length_array, &type_array, &num_strips); drawStrips(vertex_array, normal_array, length_array, type_array, num_strips); free(vertex_array); free(normal_array); free(length_array); free(type_array); } */ //bezierPatchMeshListPrint(global_bpm); //bezierPatchMeshListDraw(global_bpm); // printf("num triangles=%i\n", bezierPatchMeshListNumTriangles(global_bpm)); #ifdef USE_LOD #else bezierPatchMeshListDelete(global_bpm); global_bpm = NULL; #endif m_Self->GLPopAttrib(); } else { #ifndef USE_LOD m_Self->GLPopAttrib(); #endif #ifdef STATISTICS fprintf(stderr, "num_vertices=%i,num_triangles=%i,num_quads_strips=%i\n", STAT_num_of_eval_vertices,STAT_num_of_triangles,STAT_num_of_quad_strips); #endif /*to restore the gl_polygon_mode */ #ifndef USE_LOD m_Self->GLPolygonMode( GL_FRONT, (GLenum) gl_polygon_mode[0]); m_Self->GLPolygonMode( GL_BACK, (GLenum) gl_polygon_mode[1]); #endif } } /*------------------------------------------------------------------------- * map2f - pass a desription of a surface map *------------------------------------------------------------------------- */ void OpenGLSurfaceEvaluator::map2f( long _type, REAL _ulower, /* u lower domain coord */ REAL _uupper, /* u upper domain coord */ long _ustride, /* interpoint distance */ long _uorder, /* parametric order */ REAL _vlower, /* v lower domain coord */ REAL _vupper, /* v upper domain coord */ long _vstride, /* interpoint distance */ long _vorder, /* parametric order */ REAL *pts) /* control points */ { #ifdef USE_INTERNAL_EVAL inMap2f((int) _type, (REAL) _ulower, (REAL) _uupper, (int) _ustride, (int) _uorder, (REAL) _vlower, (REAL) _vupper, (int) _vstride, (int) _vorder, (REAL *) pts); #else if(output_triangles) { if(global_bpm == NULL) global_bpm = bezierPatchMeshMake2(10,10); if( (global_bpm->bpatch == NULL && (_type == GL_MAP2_VERTEX_3 || _type == GL_MAP2_VERTEX_4)) || (global_bpm->bpatch_normal == NULL && (_type == GL_MAP2_NORMAL)) || (global_bpm->bpatch_color == NULL && (_type == GL_MAP2_INDEX || _type == GL_MAP2_COLOR_4)) || (global_bpm->bpatch_texcoord == NULL && (_type == GL_MAP2_TEXTURE_COORD_1 || _type == GL_MAP2_TEXTURE_COORD_2 || _type == GL_MAP2_TEXTURE_COORD_3 || _type == GL_MAP2_TEXTURE_COORD_4 ) )) { bezierPatchMeshPutPatch(global_bpm, (int) _type, _ulower, _uupper,(int) _ustride,(int) _uorder,_vlower, _vupper, (int) _vstride, (int) _vorder, pts); } else /*new surface patch (with multiple maps) starts*/ { bezierPatchMesh *temp = bezierPatchMeshMake2(10,10); bezierPatchMeshPutPatch(temp, (int) _type, _ulower, _uupper,(int) _ustride,(int) _uorder,_vlower, _vupper, (int) _vstride, (int) _vorder, pts); global_bpm = bezierPatchMeshListInsert(global_bpm, temp); /* global_bpm = bezierPatchMeshListInsert(global_bpm, bezierPatchMeshMake( (int) _type, _ulower, _uupper,(int) _ustride, (int) _uorder, _vlower, _vupper, (int) _vstride, (int) _vorder, pts, 10, 10)); */ } } else /*not output triangles*/ { m_Self->GLMap2f((GLenum) _type, (GLfloat) _ulower, (GLfloat) _uupper, (GLint) _ustride, (GLint) _uorder, (GLfloat) _vlower, (GLfloat) _vupper, (GLint) _vstride, (GLint) _vorder, (const GLfloat *) pts); } #endif } /*------------------------------------------------------------------------- * mapmesh2f - evaluate a mesh of points on lattice *------------------------------------------------------------------------- */ void OpenGLSurfaceEvaluator::mapmesh2f(long style, long umin, long umax, long vmin, long vmax) { #ifdef NO_EVALUATION return; #endif #ifdef USE_INTERNAL_EVAL inEvalMesh2((int)umin, (int)vmin, (int)umax, (int)vmax); #else if(output_triangles) { #ifdef USE_LOD bezierPatchMeshBeginStrip(global_bpm, GL_POLYGON); bezierPatchMeshInsertUV(global_bpm, global_grid_u0, global_grid_v0); bezierPatchMeshInsertUV(global_bpm, global_grid_u1, global_grid_v1); bezierPatchMeshInsertUV(global_bpm, (REAL)global_grid_nu, (REAL)global_grid_nv); bezierPatchMeshInsertUV(global_bpm, (REAL)umin, (REAL)vmin); bezierPatchMeshInsertUV(global_bpm, (REAL)umax, (REAL)vmax); bezierPatchMeshEndStrip(global_bpm); #else REAL du, dv; long i,j; if(global_grid_nu == 0 || global_grid_nv == 0) return; /*no points need to be output*/ du = (global_grid_u1 - global_grid_u0) / (REAL)global_grid_nu; dv = (global_grid_v1 - global_grid_v0) / (REAL)global_grid_nv; if(global_grid_nu >= global_grid_nv){ for(i=umin; i=vmin; j--){ REAL v1 = (j == global_grid_nv)? global_grid_v1: (global_grid_v0 +j*dv); coord2f(u1, v1); coord2f(u2, v1); } endqstrip(); } } else{ for(i=vmin; i=umin; j--){ REAL u1 = (j == global_grid_nu)? global_grid_u1: (global_grid_u0 +j*du); coord2f(u1, v2); coord2f(u1, v1); } endqstrip(); } } #endif } else { switch(style) { default: case N_MESHFILL: m_Self->GLEvalMesh2((GLenum) GL_FILL, (GLint) umin, (GLint) umax, (GLint) vmin, (GLint) vmax); break; case N_MESHLINE: m_Self->GLEvalMesh2((GLenum) GL_LINE, (GLint) umin, (GLint) umax, (GLint) vmin, (GLint) vmax); break; case N_MESHPOINT: m_Self->GLEvalMesh2((GLenum) GL_POINT, (GLint) umin, (GLint) umax, (GLint) vmin, (GLint) vmax); break; } } #endif #ifdef STATISTICS STAT_num_of_quad_strips += (umax-umin)*(vmax-vmin); #endif } /*------------------------------------------------------------------------- * evalcoord2f - evaluate a point on a surface *------------------------------------------------------------------------- */ void OpenGLSurfaceEvaluator::evalcoord2f(long, REAL u, REAL v) { #ifdef NO_EVALUATION return; #endif newtmeshvert(u, v); } /*------------------------------------------------------------------------- * evalpoint2i - evaluate a grid point *------------------------------------------------------------------------- */ void OpenGLSurfaceEvaluator::evalpoint2i(long u, long v) { #ifdef NO_EVALUATION return; #endif newtmeshvert(u, v); } void OpenGLSurfaceEvaluator::point2i( long u, long v ) { #ifdef NO_EVALUATION return; #else #ifdef USE_INTERNAL_EVAL inEvalPoint2( (int)u, (int)v); #else if(output_triangles) { REAL du, dv; REAL fu,fv; du = (global_grid_u1 - global_grid_u0) / (REAL)global_grid_nu; dv = (global_grid_v1 - global_grid_v0) / (REAL)global_grid_nv; fu = (u==global_grid_nu)? global_grid_u1:(global_grid_u0 + u*du); fv = (v == global_grid_nv)? global_grid_v1: (global_grid_v0 +v*dv); coord2f(fu,fv); } else m_Self->GLEvalPoint2((GLint) u, (GLint) v); #endif #ifdef STATISTICS STAT_num_of_eval_vertices++; #endif #endif } void OpenGLSurfaceEvaluator::coord2f( REAL u, REAL v ) { #ifdef NO_EVALUATION return; #else #ifdef USE_INTERNAL_EVAL inEvalCoord2f( u, v); #else if(output_triangles) bezierPatchMeshInsertUV(global_bpm, u,v); else m_Self->GLEvalCoord2f((GLfloat) u, (GLfloat) v); #endif #ifdef STATISTICS STAT_num_of_eval_vertices++; #endif #endif } void OpenGLSurfaceEvaluator::newtmeshvert( long u, long v ) { #ifdef NO_EVALUATION return; #else if (tmeshing) { if (vcount == 2) { vertexCache[0]->invoke(this); vertexCache[1]->invoke(this); point2i( u, v); } else { vcount++; } vertexCache[which]->saveEvalPoint(u, v); which = 1 - which; } else { point2i( u, v); } #endif } void OpenGLSurfaceEvaluator::newtmeshvert( REAL u, REAL v ) { #ifdef NO_EVALUATION return; #else if (tmeshing) { if (vcount == 2) { vertexCache[0]->invoke(this); vertexCache[1]->invoke(this); coord2f(u,v); } else { vcount++; } vertexCache[which]->saveEvalCoord(u, v); which = 1 - which; } else { coord2f( u, v); } #endif } void OpenGLSurfaceEvaluator::putCallBack(GLenum which, _GLUfuncptr fn ) { switch(which) { case GLU_NURBS_BEGIN: beginCallBackN = (void (GLAPIENTRY *) (GLenum)) fn; break; case GLU_NURBS_END: endCallBackN = (void (GLAPIENTRY *) (void)) fn; break; case GLU_NURBS_VERTEX: vertexCallBackN = (void (GLAPIENTRY *) (const GLfloat*)) fn; break; case GLU_NURBS_NORMAL: normalCallBackN = (void (GLAPIENTRY *) (const GLfloat*)) fn; break; case GLU_NURBS_COLOR: colorCallBackN = (void (GLAPIENTRY *) (const GLfloat*)) fn; break; case GLU_NURBS_TEXTURE_COORD: texcoordCallBackN = (void (GLAPIENTRY *) (const GLfloat*)) fn; break; case GLU_NURBS_BEGIN_DATA: beginCallBackData = (void (GLAPIENTRY *) (GLenum, void*)) fn; break; case GLU_NURBS_END_DATA: endCallBackData = (void (GLAPIENTRY *) (void*)) fn; break; case GLU_NURBS_VERTEX_DATA: vertexCallBackData = (void (GLAPIENTRY *) (const GLfloat*, void*)) fn; break; case GLU_NURBS_NORMAL_DATA: normalCallBackData = (void (GLAPIENTRY *) (const GLfloat*, void*)) fn; break; case GLU_NURBS_COLOR_DATA: colorCallBackData = (void (GLAPIENTRY *) (const GLfloat*, void*)) fn; break; case GLU_NURBS_TEXTURE_COORD_DATA: texcoordCallBackData = (void (GLAPIENTRY *) (const GLfloat*, void*)) fn; break; } } void OpenGLSurfaceEvaluator::beginCallBack(GLenum which, void *data) { if(beginCallBackData) beginCallBackData(which, data); else if(beginCallBackN) beginCallBackN(which); } void OpenGLSurfaceEvaluator::endCallBack(void *data) { if(endCallBackData) endCallBackData(data); else if(endCallBackN) endCallBackN(); } void OpenGLSurfaceEvaluator::vertexCallBack(const GLfloat *vert, void* data) { if(vertexCallBackData) vertexCallBackData(vert, data); else if(vertexCallBackN) vertexCallBackN(vert); } void OpenGLSurfaceEvaluator::normalCallBack(const GLfloat *normal, void* data) { if(normalCallBackData) normalCallBackData(normal, data); else if(normalCallBackN) normalCallBackN(normal); } void OpenGLSurfaceEvaluator::colorCallBack(const GLfloat *color, void* data) { if(colorCallBackData) colorCallBackData(color, data); else if(colorCallBackN) colorCallBackN(color); } void OpenGLSurfaceEvaluator::texcoordCallBack(const GLfloat *texcoord, void* data) { if(texcoordCallBackData) texcoordCallBackData(texcoord, data); else if(texcoordCallBackN) texcoordCallBackN(texcoord); }