mirror of
https://github.com/reactos/reactos.git
synced 2025-01-11 16:51:06 +00:00
c424146e2c
svn path=/branches/cmake-bringup/; revision=48236
1290 lines
29 KiB
C++
1290 lines
29 KiB
C++
/*
|
|
** 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 <stdio.h>
|
|
#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; i<VERTEX_CACHE_SIZE; i++) {
|
|
vertexCache[i] = new StoredVertex;
|
|
}
|
|
tmeshing = 0;
|
|
which = 0;
|
|
vcount = 0;
|
|
|
|
global_uorder = 0;
|
|
global_vorder = 0;
|
|
global_uprime = -1.0;
|
|
global_vprime = -1.0;
|
|
global_vprime_BV = -1.0;
|
|
global_uprime_BU = -1.0;
|
|
global_uorder_BU = 0;
|
|
global_vorder_BU = 0;
|
|
global_uorder_BV = 0;
|
|
global_vorder_BV = 0;
|
|
global_baseData = NULL;
|
|
|
|
global_bpm = NULL;
|
|
output_triangles = 0; //don't output triangles by default
|
|
|
|
//no default callback functions
|
|
beginCallBackN = NULL;
|
|
endCallBackN = NULL;
|
|
vertexCallBackN = NULL;
|
|
normalCallBackN = NULL;
|
|
colorCallBackN = NULL;
|
|
texcoordCallBackN = NULL;
|
|
beginCallBackData = NULL;
|
|
endCallBackData = NULL;
|
|
vertexCallBackData = NULL;
|
|
normalCallBackData = NULL;
|
|
colorCallBackData = NULL;
|
|
texcoordCallBackData = NULL;
|
|
|
|
userData = NULL;
|
|
|
|
auto_normal_flag = 0;
|
|
callback_auto_normal = 0; //default of GLU_CALLBACK_AUTO_NORMAL is 0
|
|
vertex_flag = 0;
|
|
normal_flag = 0;
|
|
color_flag = 0;
|
|
texcoord_flag = 0;
|
|
|
|
em_vertex.uprime = -1.0;
|
|
em_vertex.vprime = -1.0;
|
|
em_normal.uprime = -1.0;
|
|
em_normal.vprime = -1.0;
|
|
em_color.uprime = -1.0;
|
|
em_color.vprime = -1.0;
|
|
em_texcoord.uprime = -1.0;
|
|
em_texcoord.vprime = -1.0;
|
|
|
|
#ifdef USE_LOD
|
|
LOD_eval_level = 1;
|
|
#endif
|
|
}
|
|
|
|
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
|
|
|
|
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
|
|
glMapGrid2d((GLint) nu, (GLdouble) u0, (GLdouble) u1, (GLint) nv,
|
|
(GLdouble) v0, (GLdouble) v1);
|
|
|
|
#endif
|
|
}
|
|
|
|
void
|
|
OpenGLSurfaceEvaluator::polymode(long style)
|
|
{
|
|
if(! output_triangles)
|
|
{
|
|
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)
|
|
{
|
|
if(output_triangles)
|
|
bezierPatchMeshBeginStrip(global_bpm, GL_LINE_STRIP);
|
|
else
|
|
glBegin((GLenum) GL_LINE_STRIP);
|
|
}
|
|
|
|
void
|
|
OpenGLSurfaceEvaluator::endline(void)
|
|
{
|
|
if(output_triangles)
|
|
bezierPatchMeshEndStrip(global_bpm);
|
|
else
|
|
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
|
|
glBegin((GLenum) GL_LINE_LOOP);
|
|
}
|
|
|
|
void
|
|
OpenGLSurfaceEvaluator::endclosedline(void)
|
|
{
|
|
if(output_triangles)
|
|
bezierPatchMeshEndStrip(global_bpm);
|
|
else
|
|
glEnd();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
OpenGLSurfaceEvaluator::bgntmesh(void)
|
|
{
|
|
|
|
tmeshing = 1;
|
|
which = 0;
|
|
vcount = 0;
|
|
|
|
if(output_triangles)
|
|
bezierPatchMeshBeginStrip(global_bpm, GL_TRIANGLES);
|
|
else
|
|
glBegin((GLenum) GL_TRIANGLES);
|
|
|
|
}
|
|
|
|
void
|
|
OpenGLSurfaceEvaluator::swaptmesh(void)
|
|
{
|
|
which = 1 - which;
|
|
|
|
}
|
|
|
|
void
|
|
OpenGLSurfaceEvaluator::endtmesh(void)
|
|
{
|
|
tmeshing = 0;
|
|
|
|
|
|
if(output_triangles)
|
|
bezierPatchMeshEndStrip(global_bpm);
|
|
else
|
|
glEnd();
|
|
}
|
|
|
|
void
|
|
OpenGLSurfaceEvaluator::bgntfan(void)
|
|
{
|
|
|
|
if(output_triangles)
|
|
bezierPatchMeshBeginStrip(global_bpm, GL_TRIANGLE_FAN);
|
|
else
|
|
glBegin((GLenum) GL_TRIANGLE_FAN);
|
|
|
|
}
|
|
void
|
|
OpenGLSurfaceEvaluator::endtfan(void)
|
|
{
|
|
if(output_triangles)
|
|
bezierPatchMeshEndStrip(global_bpm);
|
|
else
|
|
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-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
|
|
|
|
#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-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)
|
|
{
|
|
if(output_triangles)
|
|
bezierPatchMeshBeginStrip(global_bpm, GL_QUAD_STRIP);
|
|
else
|
|
glBegin((GLenum) GL_QUAD_STRIP);
|
|
|
|
#ifdef STATISTICS
|
|
STAT_num_of_quad_strips++;
|
|
#endif
|
|
}
|
|
|
|
void
|
|
OpenGLSurfaceEvaluator::endqstrip(void)
|
|
{
|
|
if(output_triangles)
|
|
bezierPatchMeshEndStrip(global_bpm);
|
|
else
|
|
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;
|
|
*/
|
|
|
|
//NEWCALLBACK: no need to worry about gl states when gling clalback
|
|
}
|
|
else
|
|
{
|
|
glPushAttrib((GLbitfield) GL_EVAL_BIT);
|
|
|
|
/*to avoid side effect, we restor the opengl state for GL_POLYGON_MODE
|
|
*/
|
|
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
|
|
|
|
}
|
|
else
|
|
{
|
|
#ifndef USE_LOD
|
|
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
|
|
glPolygonMode( GL_FRONT, (GLenum) gl_polygon_mode[0]);
|
|
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*/
|
|
{
|
|
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<umax; i++){
|
|
REAL u1 = (i==global_grid_nu)? global_grid_u1:(global_grid_u0 + i*du);
|
|
REAL u2 = ((i+1) == global_grid_nu)? global_grid_u1: (global_grid_u0+(i+1)*du);
|
|
|
|
bgnqstrip();
|
|
for(j=vmax; j>=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<vmax; i++){
|
|
REAL v1 = (i==global_grid_nv)? global_grid_v1:(global_grid_v0 + i*dv);
|
|
REAL v2 = ((i+1) == global_grid_nv)? global_grid_v1: (global_grid_v0+(i+1)*dv);
|
|
|
|
bgnqstrip();
|
|
for(j=umax; j>=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:
|
|
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 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
|
|
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
|
|
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);
|
|
}
|
|
|
|
|
|
|
|
|