/************************************************************************** * * * Copyright (C) 1991, Silicon Graphics, Inc. * * * * These coded instructions, statements, and computer programs contain * * unpublished proprietary information of Silicon Graphics, Inc., and * * are protected by Federal copyright law. They may not be disclosed * * to third parties or copied or duplicated in any form, in whole or * * in part, without the prior written consent of Silicon Graphics, Inc. * * * **************************************************************************/ /* * glsurfeval.c++ - surface evaluator * * $Revision: 1.5 $ */ /* Polynomial Evaluator Interface */ #include #include #include "glimport.h" #include "glrender.h" #include "glsurfev.h" #include "nurbscon.h" /*#define USE_INTERNAL_EVAL*/ //use internal evaluator /*whether do evaluation or not*/ /*#define NO_EVALUATION*/ /*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 OpenGLSurfaceEvaluator::OpenGLSurfaceEvaluator() { int i; for (i=0; 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 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) { glBegin((GLenum) GL_QUAD_STRIP); #ifdef STATISTICS STAT_num_of_quad_strips++; #endif } void OpenGLSurfaceEvaluator::endqstrip(void) { glEnd(); } /*------------------------------------------------------------------------- * bgnmap2f - preamble to surface definition and evaluations *------------------------------------------------------------------------- */ void OpenGLSurfaceEvaluator::bgnmap2f(long) { glPushAttrib((GLbitfield) GL_EVAL_BIT); } /*------------------------------------------------------------------------- * endmap2f - postamble to a map *------------------------------------------------------------------------- */ void OpenGLSurfaceEvaluator::endmap2f(void) { glPopAttrib(); #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 } /*------------------------------------------------------------------------- * 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 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 switch(style) { default: case N_MESHFILL: glEvalMesh2((GLenum) GL_FILL, (GLint) umin, (GLint) umax, (GLint) vmin, (GLint) vmax); break; case N_MESHLINE: glEvalMesh2((GLenum) GL_LINE, (GLint) umin, (GLint) umax, (GLint) vmin, (GLint) vmax); break; case N_MESHPOINT: 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 USE_INTERNAL_EVAL inEvalPoint2( (int)u, (int)v); #else glEvalPoint2((GLint) u, (GLint) v); #endif #ifdef STATISTICS STAT_num_of_eval_vertices++; #endif } void OpenGLSurfaceEvaluator::coord2f( REAL u, REAL v ) { #ifdef USE_INTERNAL_EVAL inEvalCoord2f( u, v); #else glEvalCoord2f((GLfloat) u, (GLfloat) v); #endif #ifdef STATISTICS STAT_num_of_eval_vertices++; #endif } void OpenGLSurfaceEvaluator::newtmeshvert( long u, long v ) { 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); } } void OpenGLSurfaceEvaluator::newtmeshvert( REAL u, REAL v ) { 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); } }