767 lines
17 KiB
C++
767 lines
17 KiB
C++
/**************************************************************************
|
|
* *
|
|
* 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 <glos.h>
|
|
#include <GL/gl.h>
|
|
#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<VERTEX_CACHE_SIZE; i++) {
|
|
vertexCache[i] = new StoredVertex;
|
|
}
|
|
tmeshing = 0;
|
|
which = 0;
|
|
vcount = 0;
|
|
|
|
|
|
}
|
|
|
|
OpenGLSurfaceEvaluator::~OpenGLSurfaceEvaluator()
|
|
{
|
|
for (int ii= 0; ii< VERTEX_CACHE_SIZE; ii++) {
|
|
delete vertexCache[ii];
|
|
vertexCache[ii]= 0;
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* disable - turn off a map
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
OpenGLSurfaceEvaluator::disable(long type)
|
|
{
|
|
glDisable((GLenum) type);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* enable - turn on a map
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
OpenGLSurfaceEvaluator::enable(long type)
|
|
{
|
|
glEnable((GLenum) type);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* 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
|
|
|
|
glMapGrid2d((GLint) nu, (GLdouble) u0, (GLdouble) u1, (GLint) nv,
|
|
(GLdouble) v0, (GLdouble) v1);
|
|
#endif
|
|
}
|
|
|
|
void
|
|
OpenGLSurfaceEvaluator::polymode(long style)
|
|
{
|
|
switch(style) {
|
|
default:
|
|
case N_MESHFILL:
|
|
|
|
glPolygonMode((GLenum) GL_FRONT_AND_BACK, (GLenum) GL_FILL);
|
|
break;
|
|
case N_MESHLINE:
|
|
glPolygonMode((GLenum) GL_FRONT_AND_BACK, (GLenum) GL_LINE);
|
|
break;
|
|
case N_MESHPOINT:
|
|
glPolygonMode((GLenum) GL_FRONT_AND_BACK, (GLenum) GL_POINT);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
OpenGLSurfaceEvaluator::bgnline(void)
|
|
{
|
|
glBegin((GLenum) GL_LINE_STRIP);
|
|
}
|
|
|
|
void
|
|
OpenGLSurfaceEvaluator::endline(void)
|
|
{
|
|
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)
|
|
{
|
|
glBegin((GLenum) GL_LINE_LOOP);
|
|
}
|
|
|
|
void
|
|
OpenGLSurfaceEvaluator::endclosedline(void)
|
|
{
|
|
glEnd();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
OpenGLSurfaceEvaluator::bgntmesh(void)
|
|
{
|
|
|
|
tmeshing = 1;
|
|
which = 0;
|
|
vcount = 0;
|
|
|
|
glBegin((GLenum) GL_TRIANGLES);
|
|
|
|
}
|
|
|
|
void
|
|
OpenGLSurfaceEvaluator::swaptmesh(void)
|
|
{
|
|
which = 1 - which;
|
|
|
|
}
|
|
|
|
void
|
|
OpenGLSurfaceEvaluator::endtmesh(void)
|
|
{
|
|
tmeshing = 0;
|
|
|
|
glEnd();
|
|
}
|
|
|
|
void
|
|
OpenGLSurfaceEvaluator::bgntfan(void)
|
|
{
|
|
glBegin((GLenum) GL_TRIANGLE_FAN);
|
|
}
|
|
void
|
|
OpenGLSurfaceEvaluator::endtfan(void)
|
|
{
|
|
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
|
|
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-1) /*at least two vertices in lower*/
|
|
{
|
|
bgntfan();
|
|
coord2f(leftMostV[0], leftMostV[1]);
|
|
// glNormal3fv(leftMostNormal);
|
|
// glVertex3fv(leftMostXYZ);
|
|
|
|
while(j<n_lower){
|
|
coord2f(lower_val[j], v_lower);
|
|
// glNormal3fv(lowerNormal[j]);
|
|
// glVertex3fv(lowerXYZ[j]);
|
|
j++;
|
|
|
|
}
|
|
endtfan();
|
|
}
|
|
break; /*exit the main loop*/
|
|
}
|
|
else if(j>= n_lower) /*case2: no more in lower*/
|
|
{
|
|
if(i<n_upper-1) /*at least two vertices in upper*/
|
|
{
|
|
bgntfan();
|
|
coord2f(leftMostV[0], leftMostV[1]);
|
|
// glNormal3fv(leftMostNormal);
|
|
// glVertex3fv(leftMostXYZ);
|
|
|
|
for(k=n_upper-1; k>=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<n_upper)
|
|
{
|
|
if(upper_val[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-1) /*at least two vertices in right*/
|
|
{
|
|
bgntfan();
|
|
coord2f(botMostV[0], botMostV[1]);
|
|
while(j<n_right){
|
|
coord2f(u_right, right_val[j]);
|
|
// glNormal3fv(rightNormal[j]);
|
|
// glVertex3fv(rightXYZ[j]);
|
|
j++;
|
|
|
|
}
|
|
endtfan();
|
|
}
|
|
break; /*exit the main loop*/
|
|
}
|
|
else if(j>= n_right) /*case2: no more in right*/
|
|
{
|
|
if(i<n_left-1) /*at least two vertices in left*/
|
|
{
|
|
bgntfan();
|
|
coord2f(botMostV[0], botMostV[1]);
|
|
// glNormal3fv(botMostNormal);
|
|
// glVertex3fv(botMostXYZ);
|
|
|
|
for(k=n_left-1; k>=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<n_left)
|
|
{
|
|
if(left_val[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);
|
|
}
|
|
}
|