From f4092abdf94af6a99aff944d6264bc1284e8bdd4 Mon Sep 17 00:00:00 2001 From: Reinhard Tartler Date: Mon, 10 Oct 2011 17:43:39 +0200 Subject: Imported nx-X11-3.1.0-1.tar.gz Summary: Imported nx-X11-3.1.0-1.tar.gz Keywords: Imported nx-X11-3.1.0-1.tar.gz into Git repository --- .../gfx/lib/glu/libnurbs/interface/insurfeval.cc | 2023 ++++++++++++++++++++ 1 file changed, 2023 insertions(+) create mode 100644 nx-X11/extras/ogl-sample/main/gfx/lib/glu/libnurbs/interface/insurfeval.cc (limited to 'nx-X11/extras/ogl-sample/main/gfx/lib/glu/libnurbs/interface/insurfeval.cc') diff --git a/nx-X11/extras/ogl-sample/main/gfx/lib/glu/libnurbs/interface/insurfeval.cc b/nx-X11/extras/ogl-sample/main/gfx/lib/glu/libnurbs/interface/insurfeval.cc new file mode 100644 index 000000000..7908d60a0 --- /dev/null +++ b/nx-X11/extras/ogl-sample/main/gfx/lib/glu/libnurbs/interface/insurfeval.cc @@ -0,0 +1,2023 @@ +/* +** 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. +** +** $Date: 2004/04/23 18:42:55 $ $Revision: 1.2 $ +*/ +/* +** $Header: /cvs/xorg/xc/extras/ogl-sample/main/gfx/lib/glu/libnurbs/interface/insurfeval.cc,v 1.2 2004/04/23 18:42:55 eich Exp $ +*/ +/* $XFree86: xc/extras/ogl-sample/main/gfx/lib/glu/libnurbs/interface/insurfeval.cc,v 1.2tsi Exp $ */ + +#include "gluos.h" +#include +#include +#include +#include +#include + +#include "glsurfeval.h" + +//extern int surfcount; + +//#define CRACK_TEST + +#define AVOID_ZERO_NORMAL + +#ifdef AVOID_ZERO_NORMAL +#define myabs(x) ((x>0)? x: (-x)) +#define MYZERO 0.000001 +#define MYDELTA 0.001 +#endif + +//#define USE_LOD +#ifdef USE_LOD +//#define LOD_EVAL_COORD(u,v) inDoEvalCoord2EM(u,v) +#define LOD_EVAL_COORD(u,v) glEvalCoord2f(u,v) + +static void LOD_interpolate(REAL A[2], REAL B[2], REAL C[2], int j, int k, int pow2_level, + REAL& u, REAL& v) +{ + REAL a,a1,b,b1; + + a = ((REAL) j) / ((REAL) pow2_level); + a1 = 1-a; + + if(j != 0) + { + b = ((REAL) k) / ((REAL)j); + b1 = 1-b; + } + REAL x,y,z; + x = a1; + if(j==0) + { + y=0; z=0; + } + else{ + y = b1*a; + z = b *a; + } + + u = x*A[0] + y*B[0] + z*C[0]; + v = x*A[1] + y*B[1] + z*C[1]; +} + +void OpenGLSurfaceEvaluator::LOD_triangle(REAL A[2], REAL B[2], REAL C[2], + int level) +{ + int k,j; + int pow2_level; + /*compute 2^level*/ + pow2_level = 1; + + for(j=0; jnext) + { + inBPMEval(temp); + } +} + +void OpenGLSurfaceEvaluator::inBPMEval(bezierPatchMesh* bpm) +{ + int i,j,k,l; + float u,v; + + int ustride = bpm->bpatch->dimension * bpm->bpatch->vorder; + int vstride = bpm->bpatch->dimension; + inMap2f( + (bpm->bpatch->dimension == 3)? GL_MAP2_VERTEX_3 : GL_MAP2_VERTEX_4, + bpm->bpatch->umin, + bpm->bpatch->umax, + ustride, + bpm->bpatch->uorder, + bpm->bpatch->vmin, + bpm->bpatch->vmax, + vstride, + bpm->bpatch->vorder, + bpm->bpatch->ctlpoints); + + bpm->vertex_array = (float*) malloc(sizeof(float)* (bpm->index_UVarray/2) * 3+1); /*in case the origional dimenion is 4, then we need 4 space to pass to evaluator.*/ + assert(bpm->vertex_array); + bpm->normal_array = (float*) malloc(sizeof(float)* (bpm->index_UVarray/2) * 3); + assert(bpm->normal_array); +#ifdef CRACK_TEST +if( global_ev_u1 ==2 && global_ev_u2 == 3 + && global_ev_v1 ==2 && global_ev_v2 == 3) +{ +REAL vertex[4]; +REAL normal[4]; +#ifdef DEBUG +printf("***number 1\n"); +#endif + +beginCallBack(GL_QUAD_STRIP, NULL); +inEvalCoord2f(3.0, 3.0); +inEvalCoord2f(2.0, 3.0); +inEvalCoord2f(3.0, 2.7); +inEvalCoord2f(2.0, 2.7); +inEvalCoord2f(3.0, 2.0); +inEvalCoord2f(2.0, 2.0); +endCallBack(NULL); + + +beginCallBack(GL_TRIANGLE_STRIP, NULL); +inEvalCoord2f(2.0, 3.0); +inEvalCoord2f(2.0, 2.0); +inEvalCoord2f(2.0, 2.7); +endCallBack(NULL); + +} + +/* +if( global_ev_u1 ==2 && global_ev_u2 == 3 + && global_ev_v1 ==1 && global_ev_v2 == 2) +{ +#ifdef DEBUG +printf("***number 2\n"); +#endif +beginCallBack(GL_QUAD_STRIP); +inEvalCoord2f(2.0, 2.0); +inEvalCoord2f(2.0, 1.0); +inEvalCoord2f(3.0, 2.0); +inEvalCoord2f(3.0, 1.0); +endCallBack(); +} +*/ +if( global_ev_u1 ==1 && global_ev_u2 == 2 + && global_ev_v1 ==2 && global_ev_v2 == 3) +{ +#ifdef DEBUG +printf("***number 3\n"); +#endif +beginCallBack(GL_QUAD_STRIP, NULL); +inEvalCoord2f(2.0, 3.0); +inEvalCoord2f(1.0, 3.0); +inEvalCoord2f(2.0, 2.3); +inEvalCoord2f(1.0, 2.3); +inEvalCoord2f(2.0, 2.0); +inEvalCoord2f(1.0, 2.0); +endCallBack(NULL); + +beginCallBack(GL_TRIANGLE_STRIP, NULL); +inEvalCoord2f(2.0, 2.3); +inEvalCoord2f(2.0, 2.0); +inEvalCoord2f(2.0, 3.0); +endCallBack(NULL); + +} +return; +#endif + + k=0; + l=0; + + for(i=0; iindex_length_array; i++) + { + beginCallBack(bpm->type_array[i], userData); + for(j=0; jlength_array[i]; j++) + { + u = bpm->UVarray[k]; + v = bpm->UVarray[k+1]; + inDoEvalCoord2NOGE(u,v, + bpm->vertex_array+l, + bpm->normal_array+l); + + normalCallBack(bpm->normal_array+l, userData); + vertexCallBack(bpm->vertex_array+l, userData); + + k += 2; + l += 3; + } + endCallBack(userData); + } +} + +void OpenGLSurfaceEvaluator::inEvalPoint2(int i, int j) +{ + REAL du, dv; + REAL point[4]; + REAL normal[3]; + REAL u,v; + du = (global_grid_u1 - global_grid_u0) / (REAL)global_grid_nu; + dv = (global_grid_v1 - global_grid_v0) / (REAL)global_grid_nv; + u = (i==global_grid_nu)? global_grid_u1:(global_grid_u0 + i*du); + v = (j == global_grid_nv)? global_grid_v1: (global_grid_v0 +j*dv); + inDoEvalCoord2(u,v,point,normal); +} + +void OpenGLSurfaceEvaluator::inEvalCoord2f(REAL u, REAL v) +{ + + REAL point[4]; + REAL normal[3]; + inDoEvalCoord2(u,v,point, normal); +} + + + +/*define a grid. store the values into the global variabls: + * global_grid_* + *These values will be used later by evaluating functions + */ +void OpenGLSurfaceEvaluator::inMapGrid2f(int nu, REAL u0, REAL u1, + int nv, REAL v0, REAL v1) +{ + global_grid_u0 = u0; + global_grid_u1 = u1; + global_grid_nu = nu; + global_grid_v0 = v0; + global_grid_v1 = v1; + global_grid_nv = nv; +} + +void OpenGLSurfaceEvaluator::inEvalMesh2(int lowU, int lowV, int highU, int highV) +{ + REAL du, dv; + int i,j; + REAL point[4]; + REAL normal[3]; + 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=lowU; i=lowV; j--){ + REAL v1 = (j == global_grid_nv)? global_grid_v1: (global_grid_v0 +j*dv); + + inDoEvalCoord2(u1, v1, point, normal); + inDoEvalCoord2(u2, v1, point, normal); + } + endqstrip(); + } + } + + else{ + for(i=lowV; i=lowU; j--){ + REAL u1 = (j == global_grid_nu)? global_grid_u1: (global_grid_u0 +j*du); + inDoEvalCoord2(u1, v2, point, normal); + inDoEvalCoord2(u1, v1, point, normal); + } + endqstrip(); + } + } +} + +void OpenGLSurfaceEvaluator::inMap2f(int k, + REAL ulower, + REAL uupper, + int ustride, + int uorder, + REAL vlower, + REAL vupper, + int vstride, + int vorder, + REAL *ctlPoints) +{ + int i,j,x; + REAL *data = global_ev_ctlPoints; + + + + if(k == GL_MAP2_VERTEX_3) k=3; + else if (k==GL_MAP2_VERTEX_4) k =4; + else { + printf("error in inMap2f, maptype=%i is wrong, k,map is not updated\n", k); + return; + } + + global_ev_k = k; + global_ev_u1 = ulower; + global_ev_u2 = uupper; + global_ev_ustride = ustride; + global_ev_uorder = uorder; + global_ev_v1 = vlower; + global_ev_v2 = vupper; + global_ev_vstride = vstride; + global_ev_vorder = vorder; + + /*copy the contrl points from ctlPoints to global_ev_ctlPoints*/ + for (i=0; i 0.0); /*better be some threshold*/ + n[0] /= mag; + n[1] /= mag; + n[2] /= mag; + +} + + + +/*Compute point and normal + *see the head of inDoDomain2WithDerivs + *for the meaning of the arguments + */ +void OpenGLSurfaceEvaluator::inDoEvalCoord2(REAL u, REAL v, + REAL *retPoint, REAL *retNormal) +{ + + REAL du[4]; + REAL dv[4]; + + assert(global_ev_k>=3 && global_ev_k <= 4); + /*compute homegeneous point and partial derivatives*/ + inDoDomain2WithDerivs(global_ev_k, u, v, global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, retPoint, du, dv); + +#ifdef AVOID_ZERO_NORMAL + + if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO) + { + + REAL tempdu[4]; + REAL tempdata[4]; + REAL u1 = global_ev_u1; + REAL u2 = global_ev_u2; + if(u-MYDELTA*(u2-u1) < u1) + u = u+ MYDELTA*(u2-u1); + else + u = u-MYDELTA*(u2-u1); + inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, tempdu, dv); + } + if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO) + { + REAL tempdv[4]; + REAL tempdata[4]; + REAL v1 = global_ev_v1; + REAL v2 = global_ev_v2; + if(v-MYDELTA*(v2-v1) < v1) + v = v+ MYDELTA*(v2-v1); + else + v = v-MYDELTA*(v2-v1); + inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, du, tempdv); + } +#endif + + + /*compute normal*/ + switch(global_ev_k){ + case 3: + inComputeNormal2(du, dv, retNormal); + + break; + case 4: + inComputeFirstPartials(retPoint, du, dv); + inComputeNormal2(du, dv, retNormal); + /*transform the homegeneous coordinate of retPoint into inhomogenous one*/ + retPoint[0] /= retPoint[3]; + retPoint[1] /= retPoint[3]; + retPoint[2] /= retPoint[3]; + break; + } + /*output this vertex*/ +/* inMeshStreamInsert(global_ms, retPoint, retNormal);*/ + + + + glNormal3fv(retNormal); + glVertex3fv(retPoint); + + + + +#ifdef DEBUG + printf("vertex(%f,%f,%f)\n", retPoint[0],retPoint[1],retPoint[2]); +#endif +} + +/*Compute point and normal + *see the head of inDoDomain2WithDerivs + *for the meaning of the arguments + */ +void OpenGLSurfaceEvaluator::inDoEvalCoord2NOGE_BU(REAL u, REAL v, + REAL *retPoint, REAL *retNormal) +{ + + REAL du[4]; + REAL dv[4]; + + assert(global_ev_k>=3 && global_ev_k <= 4); + /*compute homegeneous point and partial derivatives*/ +// inPreEvaluateBU(global_ev_k, global_ev_uorder, global_ev_vorder, (u-global_ev_u1)/(global_ev_u2-global_ev_u1), global_ev_ctlPoints); + inDoDomain2WithDerivsBU(global_ev_k, u, v, global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, retPoint, du, dv); + + +#ifdef AVOID_ZERO_NORMAL + + if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO) + { + + REAL tempdu[4]; + REAL tempdata[4]; + REAL u1 = global_ev_u1; + REAL u2 = global_ev_u2; + if(u-MYDELTA*(u2-u1) < u1) + u = u+ MYDELTA*(u2-u1); + else + u = u-MYDELTA*(u2-u1); + inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, tempdu, dv); + } + if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO) + { + REAL tempdv[4]; + REAL tempdata[4]; + REAL v1 = global_ev_v1; + REAL v2 = global_ev_v2; + if(v-MYDELTA*(v2-v1) < v1) + v = v+ MYDELTA*(v2-v1); + else + v = v-MYDELTA*(v2-v1); + inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, du, tempdv); + } +#endif + + /*compute normal*/ + switch(global_ev_k){ + case 3: + inComputeNormal2(du, dv, retNormal); + break; + case 4: + inComputeFirstPartials(retPoint, du, dv); + inComputeNormal2(du, dv, retNormal); + /*transform the homegeneous coordinate of retPoint into inhomogenous one*/ + retPoint[0] /= retPoint[3]; + retPoint[1] /= retPoint[3]; + retPoint[2] /= retPoint[3]; + break; + } +} + +/*Compute point and normal + *see the head of inDoDomain2WithDerivs + *for the meaning of the arguments + */ +void OpenGLSurfaceEvaluator::inDoEvalCoord2NOGE_BV(REAL u, REAL v, + REAL *retPoint, REAL *retNormal) +{ + + REAL du[4]; + REAL dv[4]; + + assert(global_ev_k>=3 && global_ev_k <= 4); + /*compute homegeneous point and partial derivatives*/ +// inPreEvaluateBV(global_ev_k, global_ev_uorder, global_ev_vorder, (v-global_ev_v1)/(global_ev_v2-global_ev_v1), global_ev_ctlPoints); + + inDoDomain2WithDerivsBV(global_ev_k, u, v, global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, retPoint, du, dv); + + +#ifdef AVOID_ZERO_NORMAL + + if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO) + { + + REAL tempdu[4]; + REAL tempdata[4]; + REAL u1 = global_ev_u1; + REAL u2 = global_ev_u2; + if(u-MYDELTA*(u2-u1) < u1) + u = u+ MYDELTA*(u2-u1); + else + u = u-MYDELTA*(u2-u1); + inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, tempdu, dv); + } + if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO) + { + REAL tempdv[4]; + REAL tempdata[4]; + REAL v1 = global_ev_v1; + REAL v2 = global_ev_v2; + if(v-MYDELTA*(v2-v1) < v1) + v = v+ MYDELTA*(v2-v1); + else + v = v-MYDELTA*(v2-v1); + inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, du, tempdv); + } +#endif + + /*compute normal*/ + switch(global_ev_k){ + case 3: + inComputeNormal2(du, dv, retNormal); + break; + case 4: + inComputeFirstPartials(retPoint, du, dv); + inComputeNormal2(du, dv, retNormal); + /*transform the homegeneous coordinate of retPoint into inhomogenous one*/ + retPoint[0] /= retPoint[3]; + retPoint[1] /= retPoint[3]; + retPoint[2] /= retPoint[3]; + break; + } +} + + +/*Compute point and normal + *see the head of inDoDomain2WithDerivs + *for the meaning of the arguments + */ +void OpenGLSurfaceEvaluator::inDoEvalCoord2NOGE(REAL u, REAL v, + REAL *retPoint, REAL *retNormal) +{ + + REAL du[4]; + REAL dv[4]; + + assert(global_ev_k>=3 && global_ev_k <= 4); + /*compute homegeneous point and partial derivatives*/ + inDoDomain2WithDerivs(global_ev_k, u, v, global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, retPoint, du, dv); + + +#ifdef AVOID_ZERO_NORMAL + + if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO) + { + + REAL tempdu[4]; + REAL tempdata[4]; + REAL u1 = global_ev_u1; + REAL u2 = global_ev_u2; + if(u-MYDELTA*(u2-u1) < u1) + u = u+ MYDELTA*(u2-u1); + else + u = u-MYDELTA*(u2-u1); + inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, tempdu, dv); + } + if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO) + { + REAL tempdv[4]; + REAL tempdata[4]; + REAL v1 = global_ev_v1; + REAL v2 = global_ev_v2; + if(v-MYDELTA*(v2-v1) < v1) + v = v+ MYDELTA*(v2-v1); + else + v = v-MYDELTA*(v2-v1); + inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, du, tempdv); + } +#endif + + /*compute normal*/ + switch(global_ev_k){ + case 3: + inComputeNormal2(du, dv, retNormal); + break; + case 4: + inComputeFirstPartials(retPoint, du, dv); + inComputeNormal2(du, dv, retNormal); + /*transform the homegeneous coordinate of retPoint into inhomogenous one*/ + retPoint[0] /= retPoint[3]; + retPoint[1] /= retPoint[3]; + retPoint[2] /= retPoint[3]; + break; + } +// glNormal3fv(retNormal); +// glVertex3fv(retPoint); +} + +void OpenGLSurfaceEvaluator::inPreEvaluateBV(int k, int uorder, int vorder, REAL vprime, REAL *baseData) +{ + int j,row,col; + REAL p, pdv; + REAL *data; + + if(global_vprime != vprime || global_vorder != vorder) { + inPreEvaluateWithDeriv(vorder, vprime, global_vcoeff, global_vcoeffDeriv); + global_vprime = vprime; + global_vorder = vorder; + } + + for(j=0; j=1 + *This code is copied from opengl/soft/so_eval.c:PreEvaluate + */ +void OpenGLSurfaceEvaluator::inPreEvaluate(int order, REAL vprime, REAL *coeff) +{ + int i, j; + REAL oldval, temp; + REAL oneMinusvprime; + + /* + * Minor optimization + * Compute orders 1 and 2 outright, and set coeff[0], coeff[1] to + * their i==1 loop values to avoid the initialization and the i==1 loop. + */ + if (order == 1) { + coeff[0] = 1.0; + return; + } + + oneMinusvprime = 1-vprime; + coeff[0] = oneMinusvprime; + coeff[1] = vprime; + if (order == 2) return; + + for (i = 2; i < order; i++) { + oldval = coeff[0] * vprime; + coeff[0] = oneMinusvprime * coeff[0]; + for (j = 1; j < i; j++) { + temp = oldval; + oldval = coeff[j] * vprime; + coeff[j] = temp + oneMinusvprime * coeff[j]; + } + coeff[j] = oldval; + } +} + +/* + *compute the Bezier polynomials C[n,j](v) and derivatives for all j at v with + *return values stored in coeff[] and coeffDeriv[]. + *see the head of function inPreEvaluate for the definition of C[n,j](v) + *and how to compute the values. + *The algorithm to compute the derivative is: + * dC[0,0](v) = 0. + * dC[n,j](v) = n*(dC[n-1,j-1](v) - dC[n-1,j](v)). + * + *This code is copied from opengl/soft/so_eval.c:PreEvaluateWidthDeriv + */ +void OpenGLSurfaceEvaluator::inPreEvaluateWithDeriv(int order, REAL vprime, + REAL *coeff, REAL *coeffDeriv) +{ + int i, j; + REAL oldval, temp; + REAL oneMinusvprime; + + oneMinusvprime = 1-vprime; + /* + * Minor optimization + * Compute orders 1 and 2 outright, and set coeff[0], coeff[1] to + * their i==1 loop values to avoid the initialization and the i==1 loop. + */ + if (order == 1) { + coeff[0] = 1.0; + coeffDeriv[0] = 0.0; + return; + } else if (order == 2) { + coeffDeriv[0] = -1.0; + coeffDeriv[1] = 1.0; + coeff[0] = oneMinusvprime; + coeff[1] = vprime; + return; + } + coeff[0] = oneMinusvprime; + coeff[1] = vprime; + for (i = 2; i < order - 1; i++) { + oldval = coeff[0] * vprime; + coeff[0] = oneMinusvprime * coeff[0]; + for (j = 1; j < i; j++) { + temp = oldval; + oldval = coeff[j] * vprime; + coeff[j] = temp + oneMinusvprime * coeff[j]; + } + coeff[j] = oldval; + } + coeffDeriv[0] = -coeff[0]; + /* + ** Minor optimization: + ** Would make this a "for (j=1; j=1 + *n_lower >=1 + */ +void OpenGLSurfaceEvaluator::inEvalUStrip(int n_upper, REAL v_upper, REAL* upper_val, int n_lower, REAL v_lower, REAL* lower_val) +{ + int i,j,k,l; + typedef REAL REAL3[3]; + + REAL3* upperXYZ = (REAL3*) malloc(sizeof(REAL3)*n_upper); + assert(upperXYZ); + REAL3* upperNormal = (REAL3*) malloc(sizeof(REAL3) * n_upper); + assert(upperNormal); + REAL3* lowerXYZ = (REAL3*) malloc(sizeof(REAL3)*n_lower); + assert(lowerXYZ); + REAL3* lowerNormal = (REAL3*) malloc(sizeof(REAL3) * n_lower); + assert(lowerNormal); + + inEvalULine(n_upper, v_upper, upper_val, 1, upperXYZ, upperNormal); + inEvalULine(n_lower, v_lower, lower_val, 1, lowerXYZ, lowerNormal); + + + + REAL* leftMostXYZ; + REAL* leftMostNormal; + + /* + *the algorithm works by scanning from left to right. + */ + + if(upper_val[0] <= lower_val[0]) + { + i=1; + j=0; + + leftMostXYZ = upperXYZ[0]; + leftMostNormal = upperNormal[0]; + } + else + { + i=0; + j=1; + + leftMostXYZ = lowerXYZ[0]; + leftMostNormal = lowerNormal[0]; + } + + /*the main loop. + */ + 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*/ + { + glNormal3fv(upperNormal[k]); + glVertex3fv(upperXYZ[k]); + } + + endtfan(); + } + break; /*exit the main loop*/ + } + else /* case3: neither is empty, there is at least one triangle to output*/ + { + if(upper_val[i] <= lower_val[j]) + { + bgntfan(); + + 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*/ + { + glNormal3fv(upperNormal[l]); + glVertex3fv(upperXYZ[l]); + + } + glNormal3fv(leftMostNormal); + glVertex3fv(leftMostXYZ); + + endtfan(); + + /*update i for next loop + */ + i = k+1; + + leftMostNormal = upperNormal[k]; + leftMostXYZ = upperXYZ[k]; + } + else /*upperVerts[i][0] > lowerVerts[j][0]*/ + { + bgntfan(); + glNormal3fv(upperNormal[i]); + glVertex3fv(upperXYZ[i]); + + 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; + glNormal3fv(lowerNormal[k]); + glVertex3fv(lowerXYZ[k]); + + k++; + } + endtfan(); + + /*update j for next loop + */ + j=k; + + leftMostNormal = lowerNormal[j-1]; + leftMostXYZ = lowerXYZ[j-1]; + } + } + } + //clean up + free(upperXYZ); + free(lowerXYZ); + free(upperNormal); + free(lowerNormal); +} + +/*triangulate a strip bounded by two lines which are parallel to V-axis + *leftVerts: the verteces on the left line + *rightVertx: the verteces on the right line + *n_left >=1 + *n_right >=1 + */ +void OpenGLSurfaceEvaluator::inEvalVStrip(int n_left, REAL u_left, REAL* left_val, int n_right, REAL u_right, REAL* right_val) +{ + int i,j,k,l; + typedef REAL REAL3[3]; + + REAL3* leftXYZ = (REAL3*) malloc(sizeof(REAL3)*n_left); + assert(leftXYZ); + REAL3* leftNormal = (REAL3*) malloc(sizeof(REAL3) * n_left); + assert(leftNormal); + REAL3* rightXYZ = (REAL3*) malloc(sizeof(REAL3)*n_right); + assert(rightXYZ); + REAL3* rightNormal = (REAL3*) malloc(sizeof(REAL3) * n_right); + assert(rightNormal); + + inEvalVLine(n_left, u_left, left_val, 1, leftXYZ, leftNormal); + inEvalVLine(n_right, u_right, right_val, 1, rightXYZ, rightNormal); + + + + REAL* botMostXYZ; + REAL* botMostNormal; + + /* + *the algorithm works by scanning from bot to top. + */ + + if(left_val[0] <= right_val[0]) + { + i=1; + j=0; + + botMostXYZ = leftXYZ[0]; + botMostNormal = leftNormal[0]; + } + else + { + i=0; + j=1; + + botMostXYZ = rightXYZ[0]; + botMostNormal = rightNormal[0]; + } + + /*the main loop. + */ + 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*/ + { + glNormal3fv(leftNormal[k]); + glVertex3fv(leftXYZ[k]); + } + + endtfan(); + } + break; /*exit the main loop*/ + } + else /* case3: neither is empty, there is at least one triangle to output*/ + { + if(left_val[i] <= right_val[j]) + { + bgntfan(); + + 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*/ + { + glNormal3fv(leftNormal[l]); + glVertex3fv(leftXYZ[l]); + + } + glNormal3fv(botMostNormal); + glVertex3fv(botMostXYZ); + + endtfan(); + + /*update i for next loop + */ + i = k+1; + + botMostNormal = leftNormal[k]; + botMostXYZ = leftXYZ[k]; + } + else /*left_val[i] > right_val[j])*/ + { + bgntfan(); + glNormal3fv(leftNormal[i]); + glVertex3fv(leftXYZ[i]); + + 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; + glNormal3fv(rightNormal[k]); + glVertex3fv(rightXYZ[k]); + + k++; + } + endtfan(); + + /*update j for next loop + */ + j=k; + + botMostNormal = rightNormal[j-1]; + botMostXYZ = rightXYZ[j-1]; + } + } + } + //clean up + free(leftXYZ); + free(leftXYZ); + free(rightNormal); + free(rightNormal); +} + +/*-----------------------begin evalMachine-------------------*/ +void OpenGLSurfaceEvaluator::inMap2fEM(int which, int k, + REAL ulower, + REAL uupper, + int ustride, + int uorder, + REAL vlower, + REAL vupper, + int vstride, + int vorder, + REAL *ctlPoints) +{ + int i,j,x; + surfEvalMachine *temp_em; + switch(which){ + case 0: //vertex + vertex_flag = 1; + temp_em = &em_vertex; + break; + case 1: //normal + normal_flag = 1; + temp_em = &em_normal; + break; + case 2: //color + color_flag = 1; + temp_em = &em_color; + break; + default: + texcoord_flag = 1; + temp_em = &em_texcoord; + break; + } + + REAL *data = temp_em->ctlPoints; + + temp_em->uprime = -1;//initilized + temp_em->vprime = -1; + + temp_em->k = k; + temp_em->u1 = ulower; + temp_em->u2 = uupper; + temp_em->ustride = ustride; + temp_em->uorder = uorder; + temp_em->v1 = vlower; + temp_em->v2 = vupper; + temp_em->vstride = vstride; + temp_em->vorder = vorder; + + /*copy the contrl points from ctlPoints to global_ev_ctlPoints*/ + for (i=0; iu2 == em->u1) || (em->v2 == em->v1)) + return; + the_uprime = (u - em->u1) / (em->u2 - em->u1); + the_vprime = (v - em->v1) / (em->v2 - em->v1); + + /* Compute coefficients for values and derivs */ + + /* Use already cached values if possible */ + if(em->uprime != the_uprime) { + inPreEvaluateWithDeriv(em->uorder, the_uprime, em->ucoeff, em->ucoeffDeriv); + em->uprime = the_uprime; + } + if (em->vprime != the_vprime) { + inPreEvaluateWithDeriv(em->vorder, the_vprime, em->vcoeff, em->vcoeffDeriv); + em->vprime = the_vprime; + } + + for (j = 0; j < em->k; j++) { + data=em->ctlPoints+j; + retPoint[j] = retdu[j] = retdv[j] = 0.0; + for (row = 0; row < em->uorder; row++) { + /* + ** Minor optimization. + ** The col == 0 part of the loop is extracted so we don't + ** have to initialize p and pdv to 0. + */ + p = em->vcoeff[0] * (*data); + pdv = em->vcoeffDeriv[0] * (*data); + data += em->k; + for (col = 1; col < em->vorder; col++) { + /* Incrementally build up p, pdv value */ + p += em->vcoeff[col] * (*data); + pdv += em->vcoeffDeriv[col] * (*data); + data += em->k; + } + /* Use p, pdv value to incrementally add up r, du, dv */ + retPoint[j] += em->ucoeff[row] * p; + retdu[j] += em->ucoeffDeriv[row] * p; + retdv[j] += em->ucoeff[row] * pdv; + } + } +} + +void OpenGLSurfaceEvaluator::inDoDomain2EM(surfEvalMachine *em, REAL u, REAL v, + REAL *retPoint) +{ + int j, row, col; + REAL the_uprime; + REAL the_vprime; + REAL p; + REAL *data; + + if((em->u2 == em->u1) || (em->v2 == em->v1)) + return; + the_uprime = (u - em->u1) / (em->u2 - em->u1); + the_vprime = (v - em->v1) / (em->v2 - em->v1); + + /* Compute coefficients for values and derivs */ + + /* Use already cached values if possible */ + if(em->uprime != the_uprime) { + inPreEvaluate(em->uorder, the_uprime, em->ucoeff); + em->uprime = the_uprime; + } + if (em->vprime != the_vprime) { + inPreEvaluate(em->vorder, the_vprime, em->vcoeff); + em->vprime = the_vprime; + } + + for (j = 0; j < em->k; j++) { + data=em->ctlPoints+j; + retPoint[j] = 0.0; + for (row = 0; row < em->uorder; row++) { + /* + ** Minor optimization. + ** The col == 0 part of the loop is extracted so we don't + ** have to initialize p and pdv to 0. + */ + p = em->vcoeff[0] * (*data); + data += em->k; + for (col = 1; col < em->vorder; col++) { + /* Incrementally build up p, pdv value */ + p += em->vcoeff[col] * (*data); + data += em->k; + } + /* Use p, pdv value to incrementally add up r, du, dv */ + retPoint[j] += em->ucoeff[row] * p; + } + } +} + + +void OpenGLSurfaceEvaluator::inDoEvalCoord2EM(REAL u, REAL v) +{ + REAL temp_vertex[5]; + REAL temp_normal[3]; + REAL temp_color[4]; + REAL temp_texcoord[4]; + + if(texcoord_flag) + { + inDoDomain2EM(&em_texcoord, u,v, temp_texcoord); + texcoordCallBack(temp_texcoord, userData); + } + if(color_flag) + { + inDoDomain2EM(&em_color, u,v, temp_color); + colorCallBack(temp_color, userData); + } + + if(normal_flag) //there is a normla map + { + inDoDomain2EM(&em_normal, u,v, temp_normal); + normalCallBack(temp_normal, userData); + + if(vertex_flag) + { + inDoDomain2EM(&em_vertex, u,v,temp_vertex); + if(em_vertex.k == 4) + { + temp_vertex[0] /= temp_vertex[3]; + temp_vertex[1] /= temp_vertex[3]; + temp_vertex[2] /= temp_vertex[3]; + } + temp_vertex[3]=u; + temp_vertex[4]=v; + vertexCallBack(temp_vertex, userData); + } + } + else if(auto_normal_flag) //no normal map but there is a normal callbackfunctin + { + REAL du[4]; + REAL dv[4]; + + /*compute homegeneous point and partial derivatives*/ + inDoDomain2WithDerivsEM(&em_vertex, u,v,temp_vertex,du,dv); + + if(em_vertex.k ==4) + inComputeFirstPartials(temp_vertex, du, dv); + +#ifdef AVOID_ZERO_NORMAL + if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO) + { + + REAL tempdu[4]; + REAL tempdata[4]; + REAL u1 = em_vertex.u1; + REAL u2 = em_vertex.u2; + if(u-MYDELTA*(u2-u1) < u1) + u = u+ MYDELTA*(u2-u1); + else + u = u-MYDELTA*(u2-u1); + inDoDomain2WithDerivsEM(&em_vertex,u,v, tempdata, tempdu, dv); + + if(em_vertex.k ==4) + inComputeFirstPartials(temp_vertex, du, dv); + } + else if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO) + { + REAL tempdv[4]; + REAL tempdata[4]; + REAL v1 = em_vertex.v1; + REAL v2 = em_vertex.v2; + if(v-MYDELTA*(v2-v1) < v1) + v = v+ MYDELTA*(v2-v1); + else + v = v-MYDELTA*(v2-v1); + inDoDomain2WithDerivsEM(&em_vertex,u,v, tempdata, du, tempdv); + + if(em_vertex.k ==4) + inComputeFirstPartials(temp_vertex, du, dv); + } +#endif + + /*compute normal*/ + switch(em_vertex.k){ + case 3: + + inComputeNormal2(du, dv, temp_normal); + break; + case 4: + +// inComputeFirstPartials(temp_vertex, du, dv); + inComputeNormal2(du, dv, temp_normal); + + /*transform the homegeneous coordinate of retPoint into inhomogenous one*/ + temp_vertex[0] /= temp_vertex[3]; + temp_vertex[1] /= temp_vertex[3]; + temp_vertex[2] /= temp_vertex[3]; + break; + } + normalCallBack(temp_normal, userData); + temp_vertex[3] = u; + temp_vertex[4] = v; + vertexCallBack(temp_vertex, userData); + }/*end if auto_normal*/ + else //no normal map, and no normal callback function + { + if(vertex_flag) + { + inDoDomain2EM(&em_vertex, u,v,temp_vertex); + if(em_vertex.k == 4) + { + temp_vertex[0] /= temp_vertex[3]; + temp_vertex[1] /= temp_vertex[3]; + temp_vertex[2] /= temp_vertex[3]; + } + temp_vertex[3] = u; + temp_vertex[4] = v; + vertexCallBack(temp_vertex, userData); + } + } +} + + +void OpenGLSurfaceEvaluator::inBPMEvalEM(bezierPatchMesh* bpm) +{ + int i,j,k; + float u,v; + + int ustride; + int vstride; + +#ifdef USE_LOD + if(bpm->bpatch != NULL) + { + bezierPatch* p=bpm->bpatch; + ustride = p->dimension * p->vorder; + vstride = p->dimension; + + glMap2f( (p->dimension == 3)? GL_MAP2_VERTEX_3 : GL_MAP2_VERTEX_4, + p->umin, + p->umax, + ustride, + p->uorder, + p->vmin, + p->vmax, + vstride, + p->vorder, + p->ctlpoints); + + +/* + inMap2fEM(0, p->dimension, + p->umin, + p->umax, + ustride, + p->uorder, + p->vmin, + p->vmax, + vstride, + p->vorder, + p->ctlpoints); +*/ + } +#else + + if(bpm->bpatch != NULL){ + bezierPatch* p = bpm->bpatch; + ustride = p->dimension * p->vorder; + vstride = p->dimension; + inMap2fEM(0, p->dimension, + p->umin, + p->umax, + ustride, + p->uorder, + p->vmin, + p->vmax, + vstride, + p->vorder, + p->ctlpoints); + } + if(bpm->bpatch_normal != NULL){ + bezierPatch* p = bpm->bpatch_normal; + ustride = p->dimension * p->vorder; + vstride = p->dimension; + inMap2fEM(1, p->dimension, + p->umin, + p->umax, + ustride, + p->uorder, + p->vmin, + p->vmax, + vstride, + p->vorder, + p->ctlpoints); + } + if(bpm->bpatch_color != NULL){ + bezierPatch* p = bpm->bpatch_color; + ustride = p->dimension * p->vorder; + vstride = p->dimension; + inMap2fEM(2, p->dimension, + p->umin, + p->umax, + ustride, + p->uorder, + p->vmin, + p->vmax, + vstride, + p->vorder, + p->ctlpoints); + } + if(bpm->bpatch_texcoord != NULL){ + bezierPatch* p = bpm->bpatch_texcoord; + ustride = p->dimension * p->vorder; + vstride = p->dimension; + inMap2fEM(3, p->dimension, + p->umin, + p->umax, + ustride, + p->uorder, + p->vmin, + p->vmax, + vstride, + p->vorder, + p->ctlpoints); + } +#endif + + + k=0; + for(i=0; iindex_length_array; i++) + { +#ifdef USE_LOD + if(bpm->type_array[i] == GL_POLYGON) //a mesh + { + GLfloat *temp = bpm->UVarray+k; + GLfloat u0 = temp[0]; + GLfloat v0 = temp[1]; + GLfloat u1 = temp[2]; + GLfloat v1 = temp[3]; + GLint nu = (GLint) ( temp[4]); + GLint nv = (GLint) ( temp[5]); + GLint umin = (GLint) ( temp[6]); + GLint vmin = (GLint) ( temp[7]); + GLint umax = (GLint) ( temp[8]); + GLint vmax = (GLint) ( temp[9]); + + glMapGrid2f(LOD_eval_level*nu, u0, u1, LOD_eval_level*nv, v0, v1); + glEvalMesh2(GL_FILL, LOD_eval_level*umin, LOD_eval_level*umax, LOD_eval_level*vmin, LOD_eval_level*vmax); + } + else + { + LOD_eval(bpm->length_array[i], bpm->UVarray+k, bpm->type_array[i], + 0 + ); + } + k+= 2*bpm->length_array[i]; + +#else //undef USE_LOD + +#ifdef CRACK_TEST +if( bpm->bpatch->umin == 2 && bpm->bpatch->umax == 3 + && bpm->bpatch->vmin ==2 && bpm->bpatch->vmax == 3) +{ +REAL vertex[4]; +REAL normal[4]; +#ifdef DEBUG +printf("***number ****1\n"); +#endif + +beginCallBack(GL_QUAD_STRIP, NULL); +inDoEvalCoord2EM(3.0, 3.0); +inDoEvalCoord2EM(2.0, 3.0); +inDoEvalCoord2EM(3.0, 2.7); +inDoEvalCoord2EM(2.0, 2.7); +inDoEvalCoord2EM(3.0, 2.0); +inDoEvalCoord2EM(2.0, 2.0); +endCallBack(NULL); + +beginCallBack(GL_TRIANGLE_STRIP, NULL); +inDoEvalCoord2EM(2.0, 3.0); +inDoEvalCoord2EM(2.0, 2.0); +inDoEvalCoord2EM(2.0, 2.7); +endCallBack(NULL); + +} +if( bpm->bpatch->umin == 1 && bpm->bpatch->umax == 2 + && bpm->bpatch->vmin ==2 && bpm->bpatch->vmax == 3) +{ +#ifdef DEBUG +printf("***number 3\n"); +#endif +beginCallBack(GL_QUAD_STRIP, NULL); +inDoEvalCoord2EM(2.0, 3.0); +inDoEvalCoord2EM(1.0, 3.0); +inDoEvalCoord2EM(2.0, 2.3); +inDoEvalCoord2EM(1.0, 2.3); +inDoEvalCoord2EM(2.0, 2.0); +inDoEvalCoord2EM(1.0, 2.0); +endCallBack(NULL); + +beginCallBack(GL_TRIANGLE_STRIP, NULL); +inDoEvalCoord2EM(2.0, 2.3); +inDoEvalCoord2EM(2.0, 2.0); +inDoEvalCoord2EM(2.0, 3.0); +endCallBack(NULL); + +} +return; +#endif //CRACK_TEST + + beginCallBack(bpm->type_array[i], userData); + + for(j=0; jlength_array[i]; j++) + { + u = bpm->UVarray[k]; + v = bpm->UVarray[k+1]; +#ifdef USE_LOD + LOD_EVAL_COORD(u,v); +// glEvalCoord2f(u,v); +#else + +#ifdef GENERIC_TEST + float temp_normal[3]; + float temp_vertex[3]; + if(temp_signal == 0) + { + gTessVertexSphere(u,v, temp_normal, temp_vertex); +//printf("normal=(%f,%f,%f)\n", temp_normal[0], temp_normal[1], temp_normal[2])//printf("veretx=(%f,%f,%f)\n", temp_vertex[0], temp_vertex[1], temp_vertex[2]); + normalCallBack(temp_normal, userData); + vertexCallBack(temp_vertex, userData); + } + else if(temp_signal == 1) + { + gTessVertexCyl(u,v, temp_normal, temp_vertex); +//printf("normal=(%f,%f,%f)\n", temp_normal[0], temp_normal[1], temp_normal[2])//printf("veretx=(%f,%f,%f)\n", temp_vertex[0], temp_vertex[1], temp_vertex[2]); + normalCallBack(temp_normal, userData); + vertexCallBack(temp_vertex, userData); + } + else +#endif //GENERIC_TEST + + inDoEvalCoord2EM(u,v); + +#endif //USE_LOD + + k += 2; + } + endCallBack(userData); + +#endif //USE_LOD + } +} + +void OpenGLSurfaceEvaluator::inBPMListEvalEM(bezierPatchMesh* list) +{ + bezierPatchMesh* temp; + for(temp = list; temp != NULL; temp = temp->next) + { + inBPMEvalEM(temp); + } +} + -- cgit v1.2.3