ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

insurfeval.cc
Go to the documentation of this file.
00001 /*
00002 ** License Applicability. Except to the extent portions of this file are
00003 ** made subject to an alternative license as permitted in the SGI Free
00004 ** Software License B, Version 1.1 (the "License"), the contents of this
00005 ** file are subject only to the provisions of the License. You may not use
00006 ** this file except in compliance with the License. You may obtain a copy
00007 ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
00008 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
00009 ** 
00010 ** http://oss.sgi.com/projects/FreeB
00011 ** 
00012 ** Note that, as provided in the License, the Software is distributed on an
00013 ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
00014 ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
00015 ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
00016 ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
00017 ** 
00018 ** Original Code. The Original Code is: OpenGL Sample Implementation,
00019 ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
00020 ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
00021 ** Copyright in any portions created by third parties is as indicated
00022 ** elsewhere herein. All Rights Reserved.
00023 ** 
00024 ** Additional Notice Provisions: The application programming interfaces
00025 ** established by SGI in conjunction with the Original Code are The
00026 ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
00027 ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
00028 ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
00029 ** Window System(R) (Version 1.3), released October 19, 1998. This software
00030 ** was created using the OpenGL(R) version 1.2.1 Sample Implementation
00031 ** published by SGI, but has not been independently verified as being
00032 ** compliant with the OpenGL(R) version 1.2.1 Specification.
00033 **
00034 ** $Date: 2008-11-21 09:45:54 +0000 (Fri, 21 Nov 2008) $ $Revision: 1.1 $
00035 */
00036 /*
00037 ** $Header: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/glu32/libnurbs/interface/insurfeval.cc,v 1.1 2004/02/02 16:39:08 navaraf Exp $
00038 */
00039 
00040 #include "gluos.h"
00041 #include <stdlib.h>
00042 #include <stdio.h>
00043 #include <GL/gl.h>
00044 #include <math.h>
00045 #include <assert.h>
00046 
00047 #include "glsurfeval.h"
00048 
00049 //extern int surfcount;
00050 
00051 //#define CRACK_TEST
00052 
00053 #define AVOID_ZERO_NORMAL
00054 
00055 #ifdef AVOID_ZERO_NORMAL
00056 #define myabs(x)  ((x>0)? x: (-x))
00057 #define MYZERO 0.000001
00058 #define MYDELTA 0.001
00059 #endif
00060 
00061 //#define USE_LOD
00062 #ifdef USE_LOD
00063 //#define LOD_EVAL_COORD(u,v) inDoEvalCoord2EM(u,v)
00064 #define LOD_EVAL_COORD(u,v) glEvalCoord2f(u,v)
00065 
00066 static void LOD_interpolate(REAL A[2], REAL B[2], REAL C[2], int j, int k, int pow2_level,
00067                 REAL& u, REAL& v)
00068 {
00069   REAL a,a1,b,b1;
00070 
00071   a = ((REAL) j) / ((REAL) pow2_level);
00072   a1 = 1-a;
00073 
00074   if(j != 0)
00075     {
00076       b = ((REAL) k) / ((REAL)j);
00077       b1 = 1-b;
00078     }
00079   REAL x,y,z;
00080   x = a1;
00081   if(j==0)
00082     {
00083       y=0; z=0;
00084     }
00085   else{
00086     y = b1*a;
00087     z = b *a;
00088   }
00089 
00090   u = x*A[0] + y*B[0] + z*C[0];
00091   v = x*A[1] + y*B[1] + z*C[1];
00092 }
00093 
00094 void OpenGLSurfaceEvaluator::LOD_triangle(REAL A[2], REAL B[2], REAL C[2], 
00095              int level)     
00096 {
00097   int k,j;
00098   int pow2_level;
00099   /*compute 2^level*/
00100   pow2_level = 1;
00101 
00102   for(j=0; j<level; j++)
00103     pow2_level *= 2;
00104   for(j=0; j<=pow2_level-1; j++)
00105     {
00106       REAL u,v;
00107 
00108 /*      beginCallBack(GL_TRIANGLE_STRIP);*/
00109 glBegin(GL_TRIANGLE_STRIP);
00110       LOD_interpolate(A,B,C, j+1, j+1, pow2_level, u,v);
00111 #ifdef USE_LOD
00112       LOD_EVAL_COORD(u,v);
00113 //      glEvalCoord2f(u,v);
00114 #else
00115       inDoEvalCoord2EM(u,v);
00116 #endif
00117 
00118       for(k=0; k<=j; k++)
00119     {
00120       LOD_interpolate(A,B,C,j,j-k,pow2_level, u,v);
00121 #ifdef USE_LOD
00122           LOD_EVAL_COORD(u,v);
00123 //    glEvalCoord2f(u,v);
00124 #else
00125       inDoEvalCoord2EM(u,v);
00126 #endif
00127 
00128       LOD_interpolate(A,B,C,j+1,j-k,pow2_level, u,v);
00129 
00130 #ifdef USE_LOD
00131       LOD_EVAL_COORD(u,v);
00132 //    glEvalCoord2f(u,v);
00133 #else
00134       inDoEvalCoord2EM(u,v);
00135 #endif
00136     }
00137 //      endCallBack();  
00138 glEnd();
00139     }
00140 }
00141 
00142 void OpenGLSurfaceEvaluator::LOD_eval(int num_vert, REAL* verts, int type,
00143              int level
00144              )
00145 {
00146   int i,k;
00147   switch(type){
00148   case GL_TRIANGLE_STRIP:
00149   case GL_QUAD_STRIP:
00150     for(i=2, k=4; i<=num_vert-2; i+=2, k+=4)
00151       {
00152     LOD_triangle(verts+k-4, verts+k-2, verts+k,
00153              level
00154              );
00155     LOD_triangle(verts+k-2, verts+k+2, verts+k,
00156              level
00157              );
00158       }
00159     if(num_vert % 2 ==1) 
00160       {
00161     LOD_triangle(verts+2*(num_vert-3), verts+2*(num_vert-2), verts+2*(num_vert-1),
00162              level
00163              );
00164       }
00165     break;      
00166   case GL_TRIANGLE_FAN:
00167     for(i=1, k=2; i<=num_vert-2; i++, k+=2)
00168       {
00169     LOD_triangle(verts,verts+k, verts+k+2,
00170              level
00171              );
00172       }
00173     break;
00174   
00175   default:
00176     fprintf(stderr, "typy not supported in LOD_\n");
00177   }
00178 }
00179     
00180 
00181 #endif //USE_LOD
00182 
00183 //#define  GENERIC_TEST
00184 #ifdef GENERIC_TEST
00185 extern float xmin, xmax, ymin, ymax, zmin, zmax; /*bounding box*/
00186 extern int temp_signal;
00187 
00188 static void gTessVertexSphere(float u, float v, float temp_normal[3], float temp_vertex[3])
00189 {
00190   float r=2.0;
00191   float Ox = 0.5*(xmin+xmax);
00192   float Oy = 0.5*(ymin+ymax);
00193   float Oz = 0.5*(zmin+zmax);
00194   float nx = cos(v) * sin(u);
00195   float ny = sin(v) * sin(u);
00196   float nz = cos(u);
00197   float x= Ox+r * nx;
00198   float y= Oy+r * ny;
00199   float z= Oz+r * nz;
00200 
00201   temp_normal[0] = nx;
00202   temp_normal[1] = ny;
00203   temp_normal[2] =  nz;
00204   temp_vertex[0] = x;
00205   temp_vertex[1] = y;
00206   temp_vertex[2] = z;
00207 
00208 //  glNormal3f(nx,ny,nz);
00209 //  glVertex3f(x,y,z);
00210 }
00211 
00212 static void gTessVertexCyl(float u, float v, float temp_normal[3], float temp_vertex[3])
00213 {
00214    float r=2.0;
00215   float Ox = 0.5*(xmin+xmax);
00216   float Oy = 0.5*(ymin+ymax);
00217   float Oz = 0.5*(zmin+zmax);
00218   float nx = cos(v);
00219   float ny = sin(v);
00220   float nz = 0;
00221   float x= Ox+r * nx;
00222   float y= Oy+r * ny;
00223   float z= Oz - 2*u;
00224 
00225   temp_normal[0] = nx;
00226   temp_normal[1] = ny;
00227   temp_normal[2] =  nz;
00228   temp_vertex[0] = x;
00229   temp_vertex[1] = y;
00230   temp_vertex[2] = z;
00231 
00232 /*  
00233   glNormal3f(nx,ny,nz);
00234   glVertex3f(x,y,z);
00235 */
00236 }
00237 
00238 #endif //GENERIC_TEST
00239 
00240 void OpenGLSurfaceEvaluator::inBPMListEval(bezierPatchMesh* list)
00241 {
00242   bezierPatchMesh* temp;
00243   for(temp = list; temp != NULL; temp = temp->next)
00244     {
00245       inBPMEval(temp);
00246     }
00247 }
00248 
00249 void OpenGLSurfaceEvaluator::inBPMEval(bezierPatchMesh* bpm)
00250 {
00251   int i,j,k,l;
00252   float u,v;
00253 
00254   int ustride = bpm->bpatch->dimension * bpm->bpatch->vorder;
00255   int vstride = bpm->bpatch->dimension;
00256   inMap2f( 
00257       (bpm->bpatch->dimension == 3)? GL_MAP2_VERTEX_3 : GL_MAP2_VERTEX_4,
00258       bpm->bpatch->umin,
00259       bpm->bpatch->umax,
00260       ustride,
00261       bpm->bpatch->uorder,
00262       bpm->bpatch->vmin,
00263       bpm->bpatch->vmax,
00264       vstride,
00265       bpm->bpatch->vorder,
00266       bpm->bpatch->ctlpoints);
00267   
00268   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.*/
00269   assert(bpm->vertex_array);
00270   bpm->normal_array = (float*) malloc(sizeof(float)* (bpm->index_UVarray/2) * 3);
00271   assert(bpm->normal_array);
00272 #ifdef CRACK_TEST
00273 if(  global_ev_u1 ==2 &&   global_ev_u2 == 3
00274   && global_ev_v1 ==2 &&   global_ev_v2 == 3)
00275 {
00276 REAL vertex[4];
00277 REAL normal[4];
00278 #ifdef DEBUG
00279 printf("***number 1\n");
00280 #endif
00281 
00282 beginCallBack(GL_QUAD_STRIP, NULL);
00283 inEvalCoord2f(3.0, 3.0);
00284 inEvalCoord2f(2.0, 3.0);
00285 inEvalCoord2f(3.0, 2.7);
00286 inEvalCoord2f(2.0, 2.7);
00287 inEvalCoord2f(3.0, 2.0);
00288 inEvalCoord2f(2.0, 2.0);
00289 endCallBack(NULL);
00290 
00291 
00292 beginCallBack(GL_TRIANGLE_STRIP, NULL);
00293 inEvalCoord2f(2.0, 3.0);
00294 inEvalCoord2f(2.0, 2.0);
00295 inEvalCoord2f(2.0, 2.7);
00296 endCallBack(NULL);
00297 
00298 }
00299 
00300 /*
00301 if(  global_ev_u1 ==2 &&   global_ev_u2 == 3
00302   && global_ev_v1 ==1 &&   global_ev_v2 == 2)
00303 {
00304 #ifdef DEBUG
00305 printf("***number 2\n");
00306 #endif
00307 beginCallBack(GL_QUAD_STRIP);
00308 inEvalCoord2f(2.0, 2.0);
00309 inEvalCoord2f(2.0, 1.0);
00310 inEvalCoord2f(3.0, 2.0);
00311 inEvalCoord2f(3.0, 1.0);
00312 endCallBack();
00313 }
00314 */
00315 if(  global_ev_u1 ==1 &&   global_ev_u2 == 2
00316   && global_ev_v1 ==2 &&   global_ev_v2 == 3)
00317 {
00318 #ifdef DEBUG
00319 printf("***number 3\n");
00320 #endif
00321 beginCallBack(GL_QUAD_STRIP, NULL);
00322 inEvalCoord2f(2.0, 3.0);
00323 inEvalCoord2f(1.0, 3.0);
00324 inEvalCoord2f(2.0, 2.3);
00325 inEvalCoord2f(1.0, 2.3);
00326 inEvalCoord2f(2.0, 2.0);
00327 inEvalCoord2f(1.0, 2.0);
00328 endCallBack(NULL);
00329 
00330 beginCallBack(GL_TRIANGLE_STRIP, NULL);
00331 inEvalCoord2f(2.0, 2.3);
00332 inEvalCoord2f(2.0, 2.0);
00333 inEvalCoord2f(2.0, 3.0);
00334 endCallBack(NULL);
00335 
00336 }
00337 return;
00338 #endif
00339 
00340   k=0;
00341   l=0;
00342 
00343   for(i=0; i<bpm->index_length_array; i++)
00344     {
00345       beginCallBack(bpm->type_array[i], userData);
00346       for(j=0; j<bpm->length_array[i]; j++)
00347     {
00348       u = bpm->UVarray[k];
00349       v = bpm->UVarray[k+1];
00350       inDoEvalCoord2NOGE(u,v,
00351                  bpm->vertex_array+l,
00352                  bpm->normal_array+l);
00353 
00354       normalCallBack(bpm->normal_array+l, userData);
00355       vertexCallBack(bpm->vertex_array+l, userData);
00356 
00357       k += 2;
00358       l += 3;
00359     }
00360       endCallBack(userData);
00361     }
00362 }
00363 
00364 void OpenGLSurfaceEvaluator::inEvalPoint2(int i, int j)
00365 {
00366   REAL du, dv;
00367   REAL point[4];
00368   REAL normal[3];
00369   REAL u,v;
00370   du = (global_grid_u1 - global_grid_u0) / (REAL)global_grid_nu;
00371   dv = (global_grid_v1 - global_grid_v0) / (REAL)global_grid_nv;
00372   u = (i==global_grid_nu)? global_grid_u1:(global_grid_u0 + i*du);
00373   v = (j == global_grid_nv)? global_grid_v1: (global_grid_v0 +j*dv);
00374   inDoEvalCoord2(u,v,point,normal);
00375 }
00376 
00377 void OpenGLSurfaceEvaluator::inEvalCoord2f(REAL u, REAL v)
00378 {
00379 
00380   REAL point[4];
00381   REAL normal[3];
00382   inDoEvalCoord2(u,v,point, normal);
00383 }
00384 
00385 
00386 
00387 /*define a grid. store the values into the global variabls:
00388  * global_grid_*
00389  *These values will be used later by evaluating functions
00390  */
00391 void OpenGLSurfaceEvaluator::inMapGrid2f(int nu, REAL u0, REAL u1,
00392          int nv, REAL v0, REAL v1)
00393 {
00394  global_grid_u0 = u0;
00395  global_grid_u1 = u1;
00396  global_grid_nu = nu;
00397  global_grid_v0 = v0;
00398  global_grid_v1 = v1;
00399  global_grid_nv = nv;
00400 }
00401 
00402 void OpenGLSurfaceEvaluator::inEvalMesh2(int lowU, int lowV, int highU, int highV)
00403 {
00404   REAL du, dv;
00405   int i,j;
00406   REAL point[4];
00407   REAL normal[3];
00408   if(global_grid_nu == 0 || global_grid_nv == 0)
00409     return; /*no points need to be output*/
00410   du = (global_grid_u1 - global_grid_u0) / (REAL)global_grid_nu;
00411   dv = (global_grid_v1 - global_grid_v0) / (REAL)global_grid_nv;  
00412   
00413   if(global_grid_nu >= global_grid_nv){
00414     for(i=lowU; i<highU; i++){
00415       REAL u1 = (i==global_grid_nu)? global_grid_u1:(global_grid_u0 + i*du);
00416       REAL u2 = ((i+1) == global_grid_nu)? global_grid_u1: (global_grid_u0+(i+1)*du);
00417       
00418       bgnqstrip();
00419       for(j=highV; j>=lowV; j--){
00420     REAL v1 = (j == global_grid_nv)? global_grid_v1: (global_grid_v0 +j*dv);
00421     
00422     inDoEvalCoord2(u1, v1, point, normal);
00423     inDoEvalCoord2(u2, v1, point, normal);
00424       }
00425       endqstrip();
00426     }
00427   }
00428   
00429   else{
00430     for(i=lowV; i<highV; i++){
00431       REAL v1 = (i==global_grid_nv)? global_grid_v1:(global_grid_v0 + i*dv);
00432       REAL v2 = ((i+1) == global_grid_nv)? global_grid_v1: (global_grid_v0+(i+1)*dv);
00433       
00434       bgnqstrip();
00435       for(j=highU; j>=lowU; j--){
00436     REAL u1 = (j == global_grid_nu)? global_grid_u1: (global_grid_u0 +j*du);    
00437     inDoEvalCoord2(u1, v2, point, normal);
00438     inDoEvalCoord2(u1, v1, point, normal);
00439       }
00440       endqstrip();
00441     }
00442   }
00443     
00444 }
00445 
00446 void OpenGLSurfaceEvaluator::inMap2f(int k,
00447          REAL ulower,
00448          REAL uupper,
00449          int ustride,
00450          int uorder,
00451          REAL vlower,
00452          REAL vupper,
00453          int vstride,
00454          int vorder,
00455          REAL *ctlPoints)
00456 {
00457   int i,j,x;
00458   REAL *data = global_ev_ctlPoints;
00459   
00460 
00461 
00462   if(k == GL_MAP2_VERTEX_3) k=3;
00463   else if (k==GL_MAP2_VERTEX_4) k =4;
00464   else {
00465     printf("error in inMap2f, maptype=%i is wrong, k,map is not updated\n", k);
00466     return;
00467   }
00468   
00469   global_ev_k = k;
00470   global_ev_u1 = ulower;
00471   global_ev_u2 = uupper;
00472   global_ev_ustride = ustride;
00473   global_ev_uorder = uorder;
00474   global_ev_v1 = vlower;
00475   global_ev_v2 = vupper;
00476   global_ev_vstride = vstride;
00477   global_ev_vorder = vorder;
00478 
00479   /*copy the contrl points from ctlPoints to global_ev_ctlPoints*/
00480   for (i=0; i<uorder; i++) {
00481     for (j=0; j<vorder; j++) {
00482       for (x=0; x<k; x++) {
00483     data[x] = ctlPoints[x];
00484       }
00485       ctlPoints += vstride;
00486       data += k;
00487     }
00488     ctlPoints += ustride - vstride * vorder;
00489   }
00490 
00491 }
00492 
00493 
00494 /*
00495  *given a point p with homegeneous coordiante (x,y,z,w), 
00496  *let pu(x,y,z,w) be its partial derivative vector with
00497  *respect to u
00498  *and pv(x,y,z,w) be its partial derivative vector with repect to v.
00499  *This function returns the partial derivative vectors of the
00500  *inhomegensous coordinates, i.e., 
00501  * (x/w, y/w, z/w) with respect to u and v.
00502  */
00503 void OpenGLSurfaceEvaluator::inComputeFirstPartials(REAL *p, REAL *pu, REAL *pv)
00504 {
00505     pu[0] = pu[0]*p[3] - pu[3]*p[0];
00506     pu[1] = pu[1]*p[3] - pu[3]*p[1];
00507     pu[2] = pu[2]*p[3] - pu[3]*p[2];
00508 
00509     pv[0] = pv[0]*p[3] - pv[3]*p[0];
00510     pv[1] = pv[1]*p[3] - pv[3]*p[1];
00511     pv[2] = pv[2]*p[3] - pv[3]*p[2];
00512 }
00513 
00514 /*compute the cross product of pu and pv and normalize.
00515  *the normal is returned in retNormal
00516  * pu: dimension 3
00517  * pv: dimension 3
00518  * n: return normal, of dimension 3
00519  */
00520 void OpenGLSurfaceEvaluator::inComputeNormal2(REAL *pu, REAL *pv, REAL *n)
00521 {
00522   REAL mag; 
00523 
00524   n[0] = pu[1]*pv[2] - pu[2]*pv[1];
00525   n[1] = pu[2]*pv[0] - pu[0]*pv[2];
00526   n[2] = pu[0]*pv[1] - pu[1]*pv[0];  
00527 
00528   mag = sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
00529 
00530   if (mag > 0.0) {
00531      n[0] /= mag; 
00532      n[1] /= mag;
00533      n[2] /= mag;
00534   }
00535 }
00536  
00537 
00538 
00539 /*Compute point and normal
00540  *see the head of inDoDomain2WithDerivs
00541  *for the meaning of the arguments
00542  */
00543 void OpenGLSurfaceEvaluator::inDoEvalCoord2(REAL u, REAL v,
00544                REAL *retPoint, REAL *retNormal)
00545 {
00546 
00547   REAL du[4];
00548   REAL dv[4];
00549 
00550  
00551   assert(global_ev_k>=3 && global_ev_k <= 4);
00552   /*compute homegeneous point and partial derivatives*/
00553   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);
00554 
00555 #ifdef AVOID_ZERO_NORMAL
00556 
00557   if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
00558     {
00559 
00560       REAL tempdu[4];
00561       REAL tempdata[4];
00562       REAL u1 = global_ev_u1;
00563       REAL u2 = global_ev_u2;
00564       if(u-MYDELTA*(u2-u1) < u1)
00565     u = u+ MYDELTA*(u2-u1);
00566       else
00567     u = u-MYDELTA*(u2-u1);
00568       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);
00569     }
00570   if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
00571     {
00572       REAL tempdv[4];
00573       REAL tempdata[4];
00574       REAL v1 = global_ev_v1;
00575       REAL v2 = global_ev_v2;
00576       if(v-MYDELTA*(v2-v1) < v1)
00577     v = v+ MYDELTA*(v2-v1);
00578       else
00579     v = v-MYDELTA*(v2-v1);
00580       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);
00581     }
00582 #endif
00583 
00584 
00585   /*compute normal*/
00586   switch(global_ev_k){
00587   case 3:
00588     inComputeNormal2(du, dv, retNormal);
00589 
00590     break;
00591   case 4:
00592     inComputeFirstPartials(retPoint, du, dv);
00593     inComputeNormal2(du, dv, retNormal);
00594     /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
00595     retPoint[0] /= retPoint[3];
00596     retPoint[1] /= retPoint[3];
00597     retPoint[2] /= retPoint[3];
00598     break;
00599   }
00600   /*output this vertex*/
00601 /*  inMeshStreamInsert(global_ms, retPoint, retNormal);*/
00602 
00603 
00604 
00605   glNormal3fv(retNormal);
00606   glVertex3fv(retPoint);
00607 
00608 
00609 
00610 
00611   #ifdef DEBUG
00612   printf("vertex(%f,%f,%f)\n", retPoint[0],retPoint[1],retPoint[2]);
00613   #endif
00614   
00615 
00616 
00617 }
00618 
00619 /*Compute point and normal
00620  *see the head of inDoDomain2WithDerivs
00621  *for the meaning of the arguments
00622  */
00623 void OpenGLSurfaceEvaluator::inDoEvalCoord2NOGE_BU(REAL u, REAL v,
00624                REAL *retPoint, REAL *retNormal)
00625 {
00626 
00627   REAL du[4];
00628   REAL dv[4];
00629 
00630  
00631   assert(global_ev_k>=3 && global_ev_k <= 4);
00632   /*compute homegeneous point and partial derivatives*/
00633 //   inPreEvaluateBU(global_ev_k, global_ev_uorder, global_ev_vorder, (u-global_ev_u1)/(global_ev_u2-global_ev_u1), global_ev_ctlPoints);
00634   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);
00635 
00636 
00637 #ifdef AVOID_ZERO_NORMAL
00638 
00639   if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
00640     {
00641 
00642       REAL tempdu[4];
00643       REAL tempdata[4];
00644       REAL u1 = global_ev_u1;
00645       REAL u2 = global_ev_u2;
00646       if(u-MYDELTA*(u2-u1) < u1)
00647     u = u+ MYDELTA*(u2-u1);
00648       else
00649     u = u-MYDELTA*(u2-u1);
00650       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);
00651     }
00652   if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
00653     {
00654       REAL tempdv[4];
00655       REAL tempdata[4];
00656       REAL v1 = global_ev_v1;
00657       REAL v2 = global_ev_v2;
00658       if(v-MYDELTA*(v2-v1) < v1)
00659     v = v+ MYDELTA*(v2-v1);
00660       else
00661     v = v-MYDELTA*(v2-v1);
00662       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);
00663     }
00664 #endif
00665 
00666   /*compute normal*/
00667   switch(global_ev_k){
00668   case 3:
00669     inComputeNormal2(du, dv, retNormal);
00670     break;
00671   case 4:
00672     inComputeFirstPartials(retPoint, du, dv);
00673     inComputeNormal2(du, dv, retNormal);
00674     /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
00675     retPoint[0] /= retPoint[3];
00676     retPoint[1] /= retPoint[3];
00677     retPoint[2] /= retPoint[3];
00678     break;
00679   }
00680 }
00681 
00682 /*Compute point and normal
00683  *see the head of inDoDomain2WithDerivs
00684  *for the meaning of the arguments
00685  */
00686 void OpenGLSurfaceEvaluator::inDoEvalCoord2NOGE_BV(REAL u, REAL v,
00687                REAL *retPoint, REAL *retNormal)
00688 {
00689 
00690   REAL du[4];
00691   REAL dv[4];
00692 
00693  
00694   assert(global_ev_k>=3 && global_ev_k <= 4);
00695   /*compute homegeneous point and partial derivatives*/
00696 //   inPreEvaluateBV(global_ev_k, global_ev_uorder, global_ev_vorder, (v-global_ev_v1)/(global_ev_v2-global_ev_v1), global_ev_ctlPoints);
00697 
00698   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);
00699 
00700 
00701 #ifdef AVOID_ZERO_NORMAL
00702 
00703   if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
00704     {
00705 
00706       REAL tempdu[4];
00707       REAL tempdata[4];
00708       REAL u1 = global_ev_u1;
00709       REAL u2 = global_ev_u2;
00710       if(u-MYDELTA*(u2-u1) < u1)
00711     u = u+ MYDELTA*(u2-u1);
00712       else
00713     u = u-MYDELTA*(u2-u1);
00714       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);
00715     }
00716   if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
00717     {
00718       REAL tempdv[4];
00719       REAL tempdata[4];
00720       REAL v1 = global_ev_v1;
00721       REAL v2 = global_ev_v2;
00722       if(v-MYDELTA*(v2-v1) < v1)
00723     v = v+ MYDELTA*(v2-v1);
00724       else
00725     v = v-MYDELTA*(v2-v1);
00726       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);
00727     }
00728 #endif
00729 
00730   /*compute normal*/
00731   switch(global_ev_k){
00732   case 3:
00733     inComputeNormal2(du, dv, retNormal);
00734     break;
00735   case 4:
00736     inComputeFirstPartials(retPoint, du, dv);
00737     inComputeNormal2(du, dv, retNormal);
00738     /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
00739     retPoint[0] /= retPoint[3];
00740     retPoint[1] /= retPoint[3];
00741     retPoint[2] /= retPoint[3];
00742     break;
00743   }
00744 }
00745  
00746 
00747 /*Compute point and normal
00748  *see the head of inDoDomain2WithDerivs
00749  *for the meaning of the arguments
00750  */
00751 void OpenGLSurfaceEvaluator::inDoEvalCoord2NOGE(REAL u, REAL v,
00752                REAL *retPoint, REAL *retNormal)
00753 {
00754 
00755   REAL du[4];
00756   REAL dv[4];
00757 
00758  
00759   assert(global_ev_k>=3 && global_ev_k <= 4);
00760   /*compute homegeneous point and partial derivatives*/
00761   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);
00762 
00763 
00764 #ifdef AVOID_ZERO_NORMAL
00765 
00766   if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
00767     {
00768 
00769       REAL tempdu[4];
00770       REAL tempdata[4];
00771       REAL u1 = global_ev_u1;
00772       REAL u2 = global_ev_u2;
00773       if(u-MYDELTA*(u2-u1) < u1)
00774     u = u+ MYDELTA*(u2-u1);
00775       else
00776     u = u-MYDELTA*(u2-u1);
00777       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);
00778     }
00779   if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
00780     {
00781       REAL tempdv[4];
00782       REAL tempdata[4];
00783       REAL v1 = global_ev_v1;
00784       REAL v2 = global_ev_v2;
00785       if(v-MYDELTA*(v2-v1) < v1)
00786     v = v+ MYDELTA*(v2-v1);
00787       else
00788     v = v-MYDELTA*(v2-v1);
00789       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);
00790     }
00791 #endif
00792 
00793   /*compute normal*/
00794   switch(global_ev_k){
00795   case 3:
00796     inComputeNormal2(du, dv, retNormal);
00797     break;
00798   case 4:
00799     inComputeFirstPartials(retPoint, du, dv);
00800     inComputeNormal2(du, dv, retNormal);
00801     /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
00802     retPoint[0] /= retPoint[3];
00803     retPoint[1] /= retPoint[3];
00804     retPoint[2] /= retPoint[3];
00805     break;
00806   }
00807 //  glNormal3fv(retNormal);
00808 //  glVertex3fv(retPoint);
00809 }
00810  
00811 void OpenGLSurfaceEvaluator::inPreEvaluateBV(int k, int uorder, int vorder, REAL vprime, REAL *baseData)
00812 {
00813   int j,row,col;
00814   REAL p, pdv;
00815   REAL *data;
00816 
00817   if(global_vprime != vprime || global_vorder != vorder) {      
00818     inPreEvaluateWithDeriv(vorder, vprime, global_vcoeff, global_vcoeffDeriv);
00819     global_vprime = vprime;
00820     global_vorder = vorder;
00821   }
00822 
00823   for(j=0; j<k; j++){
00824     data = baseData+j;
00825     for(row=0; row<uorder; row++){
00826       p = global_vcoeff[0] * (*data);
00827       pdv = global_vcoeffDeriv[0] * (*data);
00828       data += k;
00829       for(col = 1; col < vorder; col++){
00830     p += global_vcoeff[col] *  (*data);
00831     pdv += global_vcoeffDeriv[col] * (*data);
00832     data += k;
00833       }
00834       global_BV[row][j]  = p;
00835       global_PBV[row][j]  = pdv;
00836     }
00837   }
00838 }
00839 
00840 void OpenGLSurfaceEvaluator::inPreEvaluateBU(int k, int uorder, int vorder, REAL uprime, REAL *baseData)
00841 {
00842   int j,row,col;
00843   REAL p, pdu;
00844   REAL *data;
00845 
00846   if(global_uprime != uprime || global_uorder != uorder) {      
00847     inPreEvaluateWithDeriv(uorder, uprime, global_ucoeff, global_ucoeffDeriv);
00848     global_uprime = uprime;
00849     global_uorder = uorder;
00850   }
00851 
00852   for(j=0; j<k; j++){
00853     data = baseData+j;
00854     for(col=0; col<vorder; col++){
00855       data = baseData+j + k*col;
00856       p = global_ucoeff[0] * (*data);
00857       pdu = global_ucoeffDeriv[0] * (*data);
00858       data += k*uorder;
00859       for(row = 1; row < uorder; row++){
00860     p += global_ucoeff[row] *  (*data);
00861     pdu += global_ucoeffDeriv[row] * (*data);
00862     data += k * uorder;
00863       }
00864       global_BU[col][j]  = p;
00865       global_PBU[col][j]  = pdu;
00866     }
00867   }
00868 }
00869  
00870 void OpenGLSurfaceEvaluator::inDoDomain2WithDerivsBU(int k, REAL u, REAL v,
00871                               REAL u1, REAL u2, int uorder,
00872                               REAL v1, REAL v2, int vorder,
00873                               REAL *baseData,
00874                               REAL *retPoint, REAL* retdu, REAL *retdv)
00875 {
00876   int j, col;
00877 
00878   REAL vprime;
00879 
00880 
00881   if((u2 == u1) || (v2 == v1))
00882     return;
00883 
00884   vprime = (v - v1) / (v2 - v1);
00885 
00886 
00887   if(global_vprime != vprime || global_vorder != vorder) {
00888     inPreEvaluateWithDeriv(vorder, vprime, global_vcoeff, global_vcoeffDeriv);
00889     global_vprime = vprime;
00890     global_vorder = vorder;
00891   }
00892 
00893 
00894   for(j=0; j<k; j++)
00895     {
00896       retPoint[j] = retdu[j] = retdv[j] = 0.0;
00897       for (col = 0; col < vorder; col++)  {
00898     retPoint[j] += global_BU[col][j] * global_vcoeff[col];
00899     retdu[j] += global_PBU[col][j] * global_vcoeff[col];
00900     retdv[j] += global_BU[col][j] * global_vcoeffDeriv[col];
00901       }
00902     }
00903 }    
00904    
00905 void OpenGLSurfaceEvaluator::inDoDomain2WithDerivsBV(int k, REAL u, REAL v,
00906                               REAL u1, REAL u2, int uorder,
00907                               REAL v1, REAL v2, int vorder,
00908                               REAL *baseData,
00909                               REAL *retPoint, REAL* retdu, REAL *retdv)
00910 {
00911   int j, row;
00912   REAL uprime;
00913 
00914 
00915   if((u2 == u1) || (v2 == v1))
00916     return;
00917   uprime = (u - u1) / (u2 - u1);
00918 
00919 
00920   if(global_uprime != uprime || global_uorder != uorder) {
00921     inPreEvaluateWithDeriv(uorder, uprime, global_ucoeff, global_ucoeffDeriv);
00922     global_uprime = uprime;
00923     global_uorder = uorder;
00924   }
00925 
00926 
00927   for(j=0; j<k; j++)
00928     {
00929       retPoint[j] = retdu[j] = retdv[j] = 0.0;
00930       for (row = 0; row < uorder; row++)  {
00931     retPoint[j] += global_BV[row][j] * global_ucoeff[row];
00932     retdu[j] += global_BV[row][j] * global_ucoeffDeriv[row];
00933     retdv[j] += global_PBV[row][j] * global_ucoeff[row];
00934       }
00935     }
00936 }
00937   
00938 
00939 /*
00940  *given a Bezier surface, and parameter (u,v), compute the point in the object space,
00941  *and the normal
00942  *k: the dimension of the object space: usually 2,3,or 4.
00943  *u,v: the paramter pair.
00944  *u1,u2,uorder: the Bezier polynomial of u coord is defined on [u1,u2] with order uorder.
00945  *v1,v2,vorder: the Bezier polynomial of v coord is defined on [v1,v2] with order vorder.
00946  *baseData: contrl points. arranged as: (u,v,k).
00947  *retPoint:  the computed point (one point) with dimension k.
00948  *retdu: the computed partial derivative with respect to u.
00949  *retdv: the computed partial derivative with respect to v.
00950  */
00951 void OpenGLSurfaceEvaluator::inDoDomain2WithDerivs(int k, REAL u, REAL v, 
00952                 REAL u1, REAL u2, int uorder, 
00953                 REAL v1,  REAL v2, int vorder, 
00954                 REAL *baseData,
00955                 REAL *retPoint, REAL *retdu, REAL *retdv)
00956 {
00957     int j, row, col;
00958     REAL uprime;
00959     REAL vprime;
00960     REAL p;
00961     REAL pdv;
00962     REAL *data;
00963 
00964     if((u2 == u1) || (v2 == v1))
00965     return;
00966     uprime = (u - u1) / (u2 - u1);
00967     vprime = (v - v1) / (v2 - v1);
00968     
00969     /* Compute coefficients for values and derivs */
00970 
00971     /* Use already cached values if possible */
00972     if(global_uprime != uprime || global_uorder != uorder) {
00973         inPreEvaluateWithDeriv(uorder, uprime, global_ucoeff, global_ucoeffDeriv);
00974     global_uorder = uorder;
00975     global_uprime = uprime;
00976     }
00977     if (global_vprime != vprime || 
00978       global_vorder != vorder) {
00979     inPreEvaluateWithDeriv(vorder, vprime, global_vcoeff, global_vcoeffDeriv);
00980     global_vorder = vorder;
00981     global_vprime = vprime;
00982     }
00983 
00984     for (j = 0; j < k; j++) {
00985     data=baseData+j;
00986     retPoint[j] = retdu[j] = retdv[j] = 0.0;
00987     for (row = 0; row < uorder; row++)  {
00988         /* 
00989         ** Minor optimization.
00990         ** The col == 0 part of the loop is extracted so we don't
00991         ** have to initialize p and pdv to 0.
00992         */
00993         p = global_vcoeff[0] * (*data);
00994         pdv = global_vcoeffDeriv[0] * (*data);
00995         data += k;
00996         for (col = 1; col < vorder; col++) {
00997         /* Incrementally build up p, pdv value */
00998         p += global_vcoeff[col] * (*data);
00999         pdv += global_vcoeffDeriv[col] * (*data);
01000         data += k;
01001         }
01002         /* Use p, pdv value to incrementally add up r, du, dv */
01003         retPoint[j] += global_ucoeff[row] * p;
01004         retdu[j] += global_ucoeffDeriv[row] * p;
01005         retdv[j] += global_ucoeff[row] * pdv;
01006     }
01007     }  
01008 }
01009 
01010 
01011 /*
01012  *compute the Bezier polynomials C[n,j](v) for all j at v with 
01013  *return values stored in coeff[], where 
01014  *  C[n,j](v) = (n,j) * v^j * (1-v)^(n-j),
01015  *  j=0,1,2,...,n.
01016  *order : n+1
01017  *vprime: v
01018  *coeff : coeff[j]=C[n,j](v), this array store the returned values.
01019  *The algorithm is a recursive scheme:
01020  *   C[0,0]=1;
01021  *   C[n,j](v) = (1-v)*C[n-1,j](v) + v*C[n-1,j-1](v), n>=1
01022  *This code is copied from opengl/soft/so_eval.c:PreEvaluate
01023  */
01024 void OpenGLSurfaceEvaluator::inPreEvaluate(int order, REAL vprime, REAL *coeff)
01025 {
01026   int i, j;
01027   REAL oldval, temp;
01028   REAL oneMinusvprime;
01029   
01030   /*
01031    * Minor optimization
01032    * Compute orders 1 and 2 outright, and set coeff[0], coeff[1] to
01033      * their i==1 loop values to avoid the initialization and the i==1 loop.
01034      */
01035   if (order == 1) {
01036     coeff[0] = 1.0;
01037     return;
01038   }
01039   
01040   oneMinusvprime = 1-vprime;
01041   coeff[0] = oneMinusvprime;
01042   coeff[1] = vprime;
01043   if (order == 2) return;
01044   
01045   for (i = 2; i < order; i++) {
01046     oldval = coeff[0] * vprime;
01047     coeff[0] = oneMinusvprime * coeff[0];
01048     for (j = 1; j < i; j++) {
01049       temp = oldval;
01050       oldval = coeff[j] * vprime;
01051         coeff[j] = temp + oneMinusvprime * coeff[j];
01052     }
01053     coeff[j] = oldval;
01054   }
01055 }
01056 
01057 /*
01058  *compute the Bezier polynomials C[n,j](v) and derivatives for all j at v with 
01059  *return values stored in coeff[] and coeffDeriv[].
01060  *see the head of function inPreEvaluate for the definition of C[n,j](v)
01061  *and how to compute the values. 
01062  *The algorithm to compute the derivative is:
01063  *   dC[0,0](v) = 0.
01064  *   dC[n,j](v) = n*(dC[n-1,j-1](v) - dC[n-1,j](v)).
01065  *
01066  *This code is copied from opengl/soft/so_eval.c:PreEvaluateWidthDeriv
01067  */
01068 void OpenGLSurfaceEvaluator::inPreEvaluateWithDeriv(int order, REAL vprime, 
01069     REAL *coeff, REAL *coeffDeriv)
01070 {
01071   int i, j;
01072   REAL oldval, temp;
01073   REAL oneMinusvprime;
01074   
01075   oneMinusvprime = 1-vprime;
01076   /*
01077    * Minor optimization
01078    * Compute orders 1 and 2 outright, and set coeff[0], coeff[1] to 
01079    * their i==1 loop values to avoid the initialization and the i==1 loop.
01080    */
01081   if (order == 1) {
01082     coeff[0] = 1.0;
01083     coeffDeriv[0] = 0.0;
01084     return;
01085   } else if (order == 2) {
01086     coeffDeriv[0] = -1.0;
01087     coeffDeriv[1] = 1.0;
01088     coeff[0] = oneMinusvprime;
01089     coeff[1] = vprime;
01090     return;
01091   }
01092   coeff[0] = oneMinusvprime;
01093   coeff[1] = vprime;
01094   for (i = 2; i < order - 1; i++) {
01095     oldval = coeff[0] * vprime;
01096     coeff[0] = oneMinusvprime * coeff[0];
01097     for (j = 1; j < i; j++) {
01098       temp = oldval;
01099       oldval = coeff[j] * vprime;
01100       coeff[j] = temp + oneMinusvprime * coeff[j];
01101     }
01102     coeff[j] = oldval;
01103   }
01104   coeffDeriv[0] = -coeff[0];
01105   /*
01106    ** Minor optimization:
01107    ** Would make this a "for (j=1; j<order-1; j++)" loop, but it is always
01108    ** executed at least once, so this is more efficient.
01109    */
01110   j=1;
01111   do {
01112     coeffDeriv[j] = coeff[j-1] - coeff[j];
01113     j++;
01114   } while (j < order - 1);
01115   coeffDeriv[j] = coeff[j-1];
01116   
01117   oldval = coeff[0] * vprime;
01118   coeff[0] = oneMinusvprime * coeff[0];
01119   for (j = 1; j < i; j++) {
01120     temp = oldval;
01121     oldval = coeff[j] * vprime;
01122     coeff[j] = temp + oneMinusvprime * coeff[j];
01123   }
01124   coeff[j] = oldval;
01125 }
01126 
01127 void OpenGLSurfaceEvaluator::inEvalULine(int n_points, REAL v, REAL* u_vals, 
01128     int stride, REAL ret_points[][3], REAL ret_normals[][3])
01129 {
01130   int i,k;
01131   REAL temp[4];
01132 inPreEvaluateBV_intfac(v);
01133 
01134   for(i=0,k=0; i<n_points; i++, k += stride)
01135     {
01136       inDoEvalCoord2NOGE_BV(u_vals[k],v,temp, ret_normals[i]);
01137 
01138       ret_points[i][0] = temp[0];
01139       ret_points[i][1] = temp[1];
01140       ret_points[i][2] = temp[2];
01141 
01142     }
01143 
01144 }
01145 
01146 void OpenGLSurfaceEvaluator::inEvalVLine(int n_points, REAL u, REAL* v_vals, 
01147     int stride, REAL ret_points[][3], REAL ret_normals[][3])
01148 {
01149   int i,k;
01150   REAL temp[4];
01151 inPreEvaluateBU_intfac(u);
01152   for(i=0,k=0; i<n_points; i++, k += stride)
01153     {
01154       inDoEvalCoord2NOGE_BU(u, v_vals[k], temp, ret_normals[i]);
01155       ret_points[i][0] = temp[0];
01156       ret_points[i][1] = temp[1];
01157       ret_points[i][2] = temp[2];
01158     }
01159 }
01160       
01161 
01162 /*triangulate a strip bounded by two lines which are parallel  to U-axis
01163  *upperVerts: the verteces on the upper line
01164  *lowerVertx: the verteces on the lower line
01165  *n_upper >=1
01166  *n_lower >=1
01167  */
01168 void OpenGLSurfaceEvaluator::inEvalUStrip(int n_upper, REAL v_upper, REAL* upper_val, int n_lower, REAL v_lower, REAL* lower_val)
01169 {
01170   int i,j,k,l;
01171   REAL leftMostV[2];
01172  typedef REAL REAL3[3];
01173 
01174   REAL3* upperXYZ = (REAL3*) malloc(sizeof(REAL3)*n_upper);
01175   assert(upperXYZ);
01176   REAL3* upperNormal = (REAL3*) malloc(sizeof(REAL3) * n_upper);
01177   assert(upperNormal);
01178   REAL3* lowerXYZ = (REAL3*) malloc(sizeof(REAL3)*n_lower);
01179   assert(lowerXYZ);
01180   REAL3* lowerNormal = (REAL3*) malloc(sizeof(REAL3) * n_lower);
01181   assert(lowerNormal);
01182   
01183   inEvalULine(n_upper, v_upper, upper_val,  1, upperXYZ, upperNormal);
01184   inEvalULine(n_lower, v_lower, lower_val,  1, lowerXYZ, lowerNormal);
01185 
01186 
01187 
01188   REAL* leftMostXYZ;
01189   REAL* leftMostNormal;
01190 
01191   /*
01192    *the algorithm works by scanning from left to right.
01193    *leftMostV: the left most of the remaining verteces (on both upper and lower).
01194    *           it could an element of upperVerts or lowerVerts.
01195    *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   */
01196 
01197   /*initialize i,j,and leftMostV
01198    */
01199   if(upper_val[0] <= lower_val[0])
01200     {
01201       i=1;
01202       j=0;
01203 
01204       leftMostV[0] = upper_val[0];
01205       leftMostV[1] = v_upper;
01206       leftMostXYZ = upperXYZ[0];
01207       leftMostNormal = upperNormal[0];
01208     }
01209   else
01210     {
01211       i=0;
01212       j=1;
01213 
01214       leftMostV[0] = lower_val[0];
01215       leftMostV[1] = v_lower;
01216 
01217       leftMostXYZ = lowerXYZ[0];
01218       leftMostNormal = lowerNormal[0];
01219     }
01220   
01221   /*the main loop.
01222    *the invariance is that: 
01223    *at the beginning of each loop, the meaning of i,j,and leftMostV are 
01224    *maintained
01225    */
01226   while(1)
01227     {
01228       if(i >= n_upper) /*case1: no more in upper*/
01229         {
01230           if(j<n_lower-1) /*at least two vertices in lower*/
01231             {
01232               bgntfan();
01233           glNormal3fv(leftMostNormal);
01234               glVertex3fv(leftMostXYZ);
01235 
01236               while(j<n_lower){
01237         glNormal3fv(lowerNormal[j]);
01238         glVertex3fv(lowerXYZ[j]);
01239         j++;
01240 
01241               }
01242               endtfan();
01243             }
01244           break; /*exit the main loop*/
01245         }
01246       else if(j>= n_lower) /*case2: no more in lower*/
01247         {
01248           if(i<n_upper-1) /*at least two vertices in upper*/
01249             {
01250               bgntfan();
01251           glNormal3fv(leftMostNormal);
01252           glVertex3fv(leftMostXYZ);
01253           
01254               for(k=n_upper-1; k>=i; k--) /*reverse order for two-side lighting*/
01255         {
01256           glNormal3fv(upperNormal[k]);
01257           glVertex3fv(upperXYZ[k]);
01258         }
01259 
01260               endtfan();
01261             }
01262           break; /*exit the main loop*/
01263         }
01264       else /* case3: neither is empty, plus the leftMostV, there is at least one triangle to output*/
01265         {
01266           if(upper_val[i] <= lower_val[j])
01267             {
01268           bgntfan();
01269 
01270           glNormal3fv(lowerNormal[j]);
01271           glVertex3fv(lowerXYZ[j]);
01272 
01273               /*find the last k>=i such that 
01274                *upperverts[k][0] <= lowerverts[j][0]
01275                */
01276               k=i;
01277 
01278               while(k<n_upper)
01279                 {
01280                   if(upper_val[k] > lower_val[j])
01281                     break;
01282                   k++;
01283 
01284                 }
01285               k--;
01286 
01287 
01288               for(l=k; l>=i; l--)/*the reverse is for two-side lighting*/
01289                 {
01290           glNormal3fv(upperNormal[l]);
01291           glVertex3fv(upperXYZ[l]);
01292 
01293                 }
01294           glNormal3fv(leftMostNormal);
01295           glVertex3fv(leftMostXYZ);
01296 
01297               endtfan();
01298 
01299               /*update i and leftMostV for next loop
01300                */
01301               i = k+1;
01302 
01303           leftMostV[0] = upper_val[k];
01304           leftMostV[1] = v_upper;
01305           leftMostNormal = upperNormal[k];
01306           leftMostXYZ = upperXYZ[k];
01307             }
01308           else /*upperVerts[i][0] > lowerVerts[j][0]*/
01309             {
01310           bgntfan();
01311           glNormal3fv(upperNormal[i]);
01312           glVertex3fv(upperXYZ[i]);
01313           
01314               glNormal3fv(leftMostNormal);
01315           glVertex3fv(leftMostXYZ);
01316           
01317 
01318               /*find the last k>=j such that
01319                *lowerverts[k][0] < upperverts[i][0]
01320                */
01321               k=j;
01322               while(k< n_lower)
01323                 {
01324                   if(lower_val[k] >= upper_val[i])
01325                     break;
01326           glNormal3fv(lowerNormal[k]);
01327           glVertex3fv(lowerXYZ[k]);
01328 
01329                   k++;
01330                 }
01331               endtfan();
01332 
01333               /*update j and leftMostV for next loop
01334                */
01335               j=k;
01336           leftMostV[0] = lower_val[j-1];
01337           leftMostV[1] = v_lower;
01338 
01339           leftMostNormal = lowerNormal[j-1];
01340           leftMostXYZ = lowerXYZ[j-1];
01341             }     
01342         }
01343     }
01344   //clean up 
01345   free(upperXYZ);
01346   free(lowerXYZ);
01347   free(upperNormal);
01348   free(lowerNormal);
01349 }
01350 
01351 /*triangulate a strip bounded by two lines which are parallel  to V-axis
01352  *leftVerts: the verteces on the left line
01353  *rightVertx: the verteces on the right line
01354  *n_left >=1
01355  *n_right >=1
01356  */
01357 void OpenGLSurfaceEvaluator::inEvalVStrip(int n_left, REAL u_left, REAL* left_val, int n_right, REAL u_right, REAL* right_val)
01358 {
01359   int i,j,k,l;
01360   REAL botMostV[2];
01361   typedef REAL REAL3[3];
01362 
01363   REAL3* leftXYZ = (REAL3*) malloc(sizeof(REAL3)*n_left);
01364   assert(leftXYZ);
01365   REAL3* leftNormal = (REAL3*) malloc(sizeof(REAL3) * n_left);
01366   assert(leftNormal);
01367   REAL3* rightXYZ = (REAL3*) malloc(sizeof(REAL3)*n_right);
01368   assert(rightXYZ);
01369   REAL3* rightNormal = (REAL3*) malloc(sizeof(REAL3) * n_right);
01370   assert(rightNormal);
01371   
01372   inEvalVLine(n_left, u_left, left_val,  1, leftXYZ, leftNormal);
01373   inEvalVLine(n_right, u_right, right_val,  1, rightXYZ, rightNormal);
01374 
01375 
01376 
01377   REAL* botMostXYZ;
01378   REAL* botMostNormal;
01379 
01380   /*
01381    *the algorithm works by scanning from bot to top.
01382    *botMostV: the bot most of the remaining verteces (on both left and right).
01383    *           it could an element of leftVerts or rightVerts.
01384    *i: leftVerts[i] is the first vertex to the top of botMostV on left line   
01385    *j: rightVerts[j] is the first vertex to the top of botMostV on rightline   */
01386 
01387   /*initialize i,j,and botMostV
01388    */
01389   if(left_val[0] <= right_val[0])
01390     {
01391       i=1;
01392       j=0;
01393 
01394       botMostV[0] = u_left;
01395       botMostV[1] = left_val[0];
01396       botMostXYZ = leftXYZ[0];
01397       botMostNormal = leftNormal[0];
01398     }
01399   else
01400     {
01401       i=0;
01402       j=1;
01403 
01404       botMostV[0] = u_right;
01405       botMostV[1] = right_val[0];
01406 
01407       botMostXYZ = rightXYZ[0];
01408       botMostNormal = rightNormal[0];
01409     }
01410   
01411   /*the main loop.
01412    *the invariance is that: 
01413    *at the beginning of each loop, the meaning of i,j,and botMostV are 
01414    *maintained
01415    */
01416   while(1)
01417     {
01418       if(i >= n_left) /*case1: no more in left*/
01419         {
01420           if(j<n_right-1) /*at least two vertices in right*/
01421             {
01422               bgntfan();
01423           glNormal3fv(botMostNormal);
01424               glVertex3fv(botMostXYZ);
01425 
01426               while(j<n_right){
01427         glNormal3fv(rightNormal[j]);
01428         glVertex3fv(rightXYZ[j]);
01429         j++;
01430 
01431               }
01432               endtfan();
01433             }
01434           break; /*exit the main loop*/
01435         }
01436       else if(j>= n_right) /*case2: no more in right*/
01437         {
01438           if(i<n_left-1) /*at least two vertices in left*/
01439             {
01440               bgntfan();
01441           glNormal3fv(botMostNormal);
01442           glVertex3fv(botMostXYZ);
01443           
01444               for(k=n_left-1; k>=i; k--) /*reverse order for two-side lighting*/
01445         {
01446           glNormal3fv(leftNormal[k]);
01447           glVertex3fv(leftXYZ[k]);
01448         }
01449 
01450               endtfan();
01451             }
01452           break; /*exit the main loop*/
01453         }
01454       else /* case3: neither is empty, plus the botMostV, there is at least one triangle to output*/
01455         {
01456           if(left_val[i] <= right_val[j])
01457             {
01458           bgntfan();
01459 
01460           glNormal3fv(rightNormal[j]);
01461           glVertex3fv(rightXYZ[j]);
01462 
01463               /*find the last k>=i such that 
01464                *leftverts[k][0] <= rightverts[j][0]
01465                */
01466               k=i;
01467 
01468               while(k<n_left)
01469                 {
01470                   if(left_val[k] > right_val[j])
01471                     break;
01472                   k++;
01473 
01474                 }
01475               k--;
01476 
01477 
01478               for(l=k; l>=i; l--)/*the reverse is for two-side lighting*/
01479                 {
01480           glNormal3fv(leftNormal[l]);
01481           glVertex3fv(leftXYZ[l]);
01482 
01483                 }
01484           glNormal3fv(botMostNormal);
01485           glVertex3fv(botMostXYZ);
01486 
01487               endtfan();
01488 
01489               /*update i and botMostV for next loop
01490                */
01491               i = k+1;
01492 
01493           botMostV[0] = u_left;
01494           botMostV[1] = left_val[k];
01495           botMostNormal = leftNormal[k];
01496           botMostXYZ = leftXYZ[k];
01497             }
01498           else /*left_val[i] > right_val[j])*/
01499             {
01500           bgntfan();
01501           glNormal3fv(leftNormal[i]);
01502           glVertex3fv(leftXYZ[i]);
01503           
01504               glNormal3fv(botMostNormal);
01505           glVertex3fv(botMostXYZ);
01506           
01507 
01508               /*find the last k>=j such that
01509                *rightverts[k][0] < leftverts[i][0]
01510                */
01511               k=j;
01512               while(k< n_right)
01513                 {
01514                   if(right_val[k] >= left_val[i])
01515                     break;
01516           glNormal3fv(rightNormal[k]);
01517           glVertex3fv(rightXYZ[k]);
01518 
01519                   k++;
01520                 }
01521               endtfan();
01522 
01523               /*update j and botMostV for next loop
01524                */
01525               j=k;
01526           botMostV[0] = u_right;
01527           botMostV[1] = right_val[j-1];
01528 
01529           botMostNormal = rightNormal[j-1];
01530           botMostXYZ = rightXYZ[j-1];
01531             }     
01532         }
01533     }
01534   //clean up 
01535   free(leftXYZ);
01536   free(rightXYZ);
01537   free(leftNormal);
01538   free(rightNormal);
01539 }
01540 
01541 /*-----------------------begin evalMachine-------------------*/
01542 void OpenGLSurfaceEvaluator::inMap2fEM(int which, int k,
01543          REAL ulower,
01544          REAL uupper,
01545          int ustride,
01546          int uorder,
01547          REAL vlower,
01548          REAL vupper,
01549          int vstride,
01550          int vorder,
01551          REAL *ctlPoints)
01552 {
01553   int i,j,x;
01554   surfEvalMachine *temp_em;
01555   switch(which){
01556   case 0: //vertex
01557     vertex_flag = 1;
01558     temp_em = &em_vertex;
01559     break;
01560   case 1: //normal
01561     normal_flag = 1;
01562     temp_em = &em_normal;
01563     break;
01564   case 2: //color
01565     color_flag = 1;
01566     temp_em = &em_color;
01567     break;
01568   default:
01569     texcoord_flag = 1;
01570     temp_em = &em_texcoord;
01571     break;
01572   }
01573 
01574   REAL *data = temp_em->ctlPoints;
01575   
01576   temp_em->uprime = -1;//initilized
01577   temp_em->vprime = -1;
01578 
01579   temp_em->k = k;
01580   temp_em->u1 = ulower;
01581   temp_em->u2 = uupper;
01582   temp_em->ustride = ustride;
01583   temp_em->uorder = uorder;
01584   temp_em->v1 = vlower;
01585   temp_em->v2 = vupper;
01586   temp_em->vstride = vstride;
01587   temp_em->vorder = vorder;
01588 
01589   /*copy the contrl points from ctlPoints to global_ev_ctlPoints*/
01590   for (i=0; i<uorder; i++) {
01591     for (j=0; j<vorder; j++) {
01592       for (x=0; x<k; x++) {
01593     data[x] = ctlPoints[x];
01594       }
01595       ctlPoints += vstride;
01596       data += k;
01597     }
01598     ctlPoints += ustride - vstride * vorder;
01599   }
01600 }
01601 
01602 void OpenGLSurfaceEvaluator::inDoDomain2WithDerivsEM(surfEvalMachine *em, REAL u, REAL v, 
01603                 REAL *retPoint, REAL *retdu, REAL *retdv)
01604 {
01605     int j, row, col;
01606     REAL the_uprime;
01607     REAL the_vprime;
01608     REAL p;
01609     REAL pdv;
01610     REAL *data;
01611 
01612     if((em->u2 == em->u1) || (em->v2 == em->v1))
01613     return;
01614     the_uprime = (u - em->u1) / (em->u2 - em->u1);
01615     the_vprime = (v - em->v1) / (em->v2 - em->v1);
01616     
01617     /* Compute coefficients for values and derivs */
01618 
01619     /* Use already cached values if possible */
01620     if(em->uprime != the_uprime) {
01621         inPreEvaluateWithDeriv(em->uorder, the_uprime, em->ucoeff, em->ucoeffDeriv);
01622     em->uprime = the_uprime;
01623     }
01624     if (em->vprime != the_vprime) {
01625     inPreEvaluateWithDeriv(em->vorder, the_vprime, em->vcoeff, em->vcoeffDeriv);
01626     em->vprime = the_vprime;
01627     }
01628 
01629     for (j = 0; j < em->k; j++) {
01630     data=em->ctlPoints+j;
01631     retPoint[j] = retdu[j] = retdv[j] = 0.0;
01632     for (row = 0; row < em->uorder; row++)  {
01633         /* 
01634         ** Minor optimization.
01635         ** The col == 0 part of the loop is extracted so we don't
01636         ** have to initialize p and pdv to 0.
01637         */
01638         p = em->vcoeff[0] * (*data);
01639         pdv = em->vcoeffDeriv[0] * (*data);
01640         data += em->k;
01641         for (col = 1; col < em->vorder; col++) {
01642         /* Incrementally build up p, pdv value */
01643         p += em->vcoeff[col] * (*data);
01644         pdv += em->vcoeffDeriv[col] * (*data);
01645         data += em->k;
01646         }
01647         /* Use p, pdv value to incrementally add up r, du, dv */
01648         retPoint[j] += em->ucoeff[row] * p;
01649         retdu[j] += em->ucoeffDeriv[row] * p;
01650         retdv[j] += em->ucoeff[row] * pdv;
01651     }
01652     }  
01653 }  
01654 
01655 void OpenGLSurfaceEvaluator::inDoDomain2EM(surfEvalMachine *em, REAL u, REAL v, 
01656                 REAL *retPoint)
01657 {
01658     int j, row, col;
01659     REAL the_uprime;
01660     REAL the_vprime;
01661     REAL p;
01662     REAL *data;
01663 
01664     if((em->u2 == em->u1) || (em->v2 == em->v1))
01665     return;
01666     the_uprime = (u - em->u1) / (em->u2 - em->u1);
01667     the_vprime = (v - em->v1) / (em->v2 - em->v1);
01668     
01669     /* Compute coefficients for values and derivs */
01670 
01671     /* Use already cached values if possible */
01672     if(em->uprime != the_uprime) {
01673         inPreEvaluate(em->uorder, the_uprime, em->ucoeff);
01674     em->uprime = the_uprime;
01675     }
01676     if (em->vprime != the_vprime) {
01677     inPreEvaluate(em->vorder, the_vprime, em->vcoeff);
01678     em->vprime = the_vprime;
01679     }
01680 
01681     for (j = 0; j < em->k; j++) {
01682     data=em->ctlPoints+j;
01683     retPoint[j] = 0.0;
01684     for (row = 0; row < em->uorder; row++)  {
01685         /* 
01686         ** Minor optimization.
01687         ** The col == 0 part of the loop is extracted so we don't
01688         ** have to initialize p and pdv to 0.
01689         */
01690         p = em->vcoeff[0] * (*data);
01691         data += em->k;
01692         for (col = 1; col < em->vorder; col++) {
01693         /* Incrementally build up p, pdv value */
01694         p += em->vcoeff[col] * (*data);
01695         data += em->k;
01696         }
01697         /* Use p, pdv value to incrementally add up r, du, dv */
01698         retPoint[j] += em->ucoeff[row] * p;
01699     }
01700     }  
01701 }  
01702 
01703 
01704 void OpenGLSurfaceEvaluator::inDoEvalCoord2EM(REAL u, REAL v)
01705 {
01706   REAL temp_vertex[5];
01707   REAL temp_normal[3];
01708   REAL temp_color[4];
01709   REAL temp_texcoord[4];
01710 
01711   if(texcoord_flag)
01712     {
01713       inDoDomain2EM(&em_texcoord, u,v, temp_texcoord);
01714       texcoordCallBack(temp_texcoord, userData);
01715     }
01716   if(color_flag)
01717     {
01718       inDoDomain2EM(&em_color, u,v, temp_color);
01719       colorCallBack(temp_color, userData);
01720     }
01721 
01722   if(normal_flag) //there is a normla map
01723     {
01724       inDoDomain2EM(&em_normal, u,v, temp_normal);
01725       normalCallBack(temp_normal, userData);
01726     
01727       if(vertex_flag)
01728     {
01729       inDoDomain2EM(&em_vertex, u,v,temp_vertex);
01730       if(em_vertex.k == 4)
01731         {
01732           temp_vertex[0] /= temp_vertex[3];
01733           temp_vertex[1] /= temp_vertex[3];
01734           temp_vertex[2] /= temp_vertex[3];       
01735         }
01736           temp_vertex[3]=u;
01737           temp_vertex[4]=v;   
01738       vertexCallBack(temp_vertex, userData);
01739     }
01740     }
01741   else if(auto_normal_flag) //no normal map but there is a normal callbackfunctin
01742     {
01743       REAL du[4];
01744       REAL dv[4];
01745       
01746       /*compute homegeneous point and partial derivatives*/
01747       inDoDomain2WithDerivsEM(&em_vertex, u,v,temp_vertex,du,dv);
01748 
01749       if(em_vertex.k ==4)
01750     inComputeFirstPartials(temp_vertex, du, dv);
01751 
01752 #ifdef AVOID_ZERO_NORMAL
01753       if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
01754     {
01755       
01756       REAL tempdu[4];
01757       REAL tempdata[4];
01758       REAL u1 = em_vertex.u1;
01759       REAL u2 = em_vertex.u2;
01760       if(u-MYDELTA*(u2-u1) < u1)
01761         u = u+ MYDELTA*(u2-u1);
01762       else
01763         u = u-MYDELTA*(u2-u1);
01764       inDoDomain2WithDerivsEM(&em_vertex,u,v, tempdata, tempdu, dv);
01765 
01766       if(em_vertex.k ==4)
01767         inComputeFirstPartials(temp_vertex, du, dv);      
01768     }
01769       else if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
01770     {
01771       REAL tempdv[4];
01772       REAL tempdata[4];
01773       REAL v1 = em_vertex.v1;
01774       REAL v2 = em_vertex.v2;
01775       if(v-MYDELTA*(v2-v1) < v1)
01776         v = v+ MYDELTA*(v2-v1);
01777       else
01778         v = v-MYDELTA*(v2-v1);
01779       inDoDomain2WithDerivsEM(&em_vertex,u,v, tempdata, du, tempdv);
01780 
01781       if(em_vertex.k ==4)
01782         inComputeFirstPartials(temp_vertex, du, dv);
01783     }
01784 #endif
01785 
01786       /*compute normal*/
01787       switch(em_vertex.k){
01788       case 3:
01789 
01790     inComputeNormal2(du, dv, temp_normal);
01791     break;
01792       case 4:
01793 
01794 //  inComputeFirstPartials(temp_vertex, du, dv);
01795     inComputeNormal2(du, dv, temp_normal);
01796 
01797     /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
01798     temp_vertex[0] /= temp_vertex[3];
01799     temp_vertex[1] /= temp_vertex[3];
01800     temp_vertex[2] /= temp_vertex[3];
01801     break;
01802       }
01803       normalCallBack(temp_normal, userData);
01804       temp_vertex[3] = u;
01805       temp_vertex[4] = v;
01806       vertexCallBack(temp_vertex, userData);
01807       
01808     }/*end if auto_normal*/
01809   else //no normal map, and no normal callback function
01810     {
01811       if(vertex_flag)
01812     {
01813       inDoDomain2EM(&em_vertex, u,v,temp_vertex);
01814       if(em_vertex.k == 4)
01815         {
01816           temp_vertex[0] /= temp_vertex[3];
01817           temp_vertex[1] /= temp_vertex[3];
01818           temp_vertex[2] /= temp_vertex[3];       
01819         }
01820           temp_vertex[3] = u;
01821           temp_vertex[4] = v;
01822       vertexCallBack(temp_vertex, userData);
01823     }
01824     }
01825 }
01826 
01827 
01828 void OpenGLSurfaceEvaluator::inBPMEvalEM(bezierPatchMesh* bpm)
01829 {
01830   int i,j,k;
01831   float u,v;
01832 
01833   int ustride;
01834   int vstride;
01835 
01836 #ifdef USE_LOD
01837   if(bpm->bpatch != NULL)
01838     {
01839       bezierPatch* p=bpm->bpatch;
01840       ustride = p->dimension * p->vorder;
01841       vstride = p->dimension;
01842 
01843       glMap2f( (p->dimension == 3)? GL_MAP2_VERTEX_3 : GL_MAP2_VERTEX_4,
01844           p->umin,
01845           p->umax,
01846           ustride,
01847           p->uorder,
01848           p->vmin,
01849           p->vmax,
01850           vstride,
01851           p->vorder,
01852           p->ctlpoints);
01853 
01854 
01855 /*
01856     inMap2fEM(0, p->dimension,
01857       p->umin,
01858       p->umax,
01859       ustride,
01860       p->uorder,
01861       p->vmin,
01862       p->vmax,
01863       vstride,
01864       p->vorder,
01865       p->ctlpoints);
01866 */
01867     }
01868 #else
01869 
01870   if(bpm->bpatch != NULL){
01871     bezierPatch* p = bpm->bpatch;
01872     ustride = p->dimension * p->vorder;
01873     vstride = p->dimension;
01874     inMap2fEM(0, p->dimension,
01875       p->umin,
01876       p->umax,
01877       ustride,
01878       p->uorder,
01879       p->vmin,
01880       p->vmax,
01881       vstride,
01882       p->vorder,
01883       p->ctlpoints);
01884   }
01885   if(bpm->bpatch_normal != NULL){
01886     bezierPatch* p = bpm->bpatch_normal;
01887     ustride = p->dimension * p->vorder;
01888     vstride = p->dimension;
01889     inMap2fEM(1, p->dimension,
01890       p->umin,
01891       p->umax,
01892       ustride,
01893       p->uorder,
01894       p->vmin,
01895       p->vmax,
01896       vstride,
01897       p->vorder,
01898       p->ctlpoints);
01899   }
01900   if(bpm->bpatch_color != NULL){
01901     bezierPatch* p = bpm->bpatch_color;
01902     ustride = p->dimension * p->vorder;
01903     vstride = p->dimension;
01904     inMap2fEM(2, p->dimension,
01905       p->umin,
01906       p->umax,
01907       ustride,
01908       p->uorder,
01909       p->vmin,
01910       p->vmax,
01911       vstride,
01912       p->vorder,
01913       p->ctlpoints);
01914   }
01915   if(bpm->bpatch_texcoord != NULL){
01916     bezierPatch* p = bpm->bpatch_texcoord;
01917     ustride = p->dimension * p->vorder;
01918     vstride = p->dimension;
01919     inMap2fEM(3, p->dimension,
01920       p->umin,
01921       p->umax,
01922       ustride,
01923       p->uorder,
01924       p->vmin,
01925       p->vmax,
01926       vstride,
01927       p->vorder,
01928       p->ctlpoints);
01929   }
01930 #endif
01931 
01932 
01933   k=0;
01934   for(i=0; i<bpm->index_length_array; i++)
01935     {
01936 #ifdef USE_LOD
01937       if(bpm->type_array[i] == GL_POLYGON) //a mesh
01938     {
01939       GLfloat *temp = bpm->UVarray+k;
01940       GLfloat u0 = temp[0];
01941       GLfloat v0 = temp[1];
01942       GLfloat u1 = temp[2];
01943       GLfloat v1 = temp[3];
01944       GLint nu = (GLint) ( temp[4]);
01945       GLint nv = (GLint) ( temp[5]);
01946       GLint umin = (GLint) ( temp[6]);
01947       GLint vmin = (GLint) ( temp[7]);
01948       GLint umax = (GLint) ( temp[8]);
01949       GLint vmax = (GLint) ( temp[9]);
01950 
01951       glMapGrid2f(LOD_eval_level*nu, u0, u1, LOD_eval_level*nv, v0, v1);
01952       glEvalMesh2(GL_FILL, LOD_eval_level*umin, LOD_eval_level*umax, LOD_eval_level*vmin, LOD_eval_level*vmax);
01953     }
01954       else
01955     {
01956       LOD_eval(bpm->length_array[i], bpm->UVarray+k, bpm->type_array[i],
01957            0
01958            );
01959     }
01960       k+= 2*bpm->length_array[i];       
01961     
01962 #else //undef  USE_LOD
01963 
01964 #ifdef CRACK_TEST
01965 if(  bpm->bpatch->umin == 2 &&   bpm->bpatch->umax == 3
01966   && bpm->bpatch->vmin ==2 &&    bpm->bpatch->vmax == 3)
01967 {
01968 REAL vertex[4];
01969 REAL normal[4];
01970 #ifdef DEBUG
01971 printf("***number ****1\n");
01972 #endif
01973 
01974 beginCallBack(GL_QUAD_STRIP, NULL);
01975 inDoEvalCoord2EM(3.0, 3.0);
01976 inDoEvalCoord2EM(2.0, 3.0);
01977 inDoEvalCoord2EM(3.0, 2.7);
01978 inDoEvalCoord2EM(2.0, 2.7);
01979 inDoEvalCoord2EM(3.0, 2.0);
01980 inDoEvalCoord2EM(2.0, 2.0);
01981 endCallBack(NULL);
01982 
01983 beginCallBack(GL_TRIANGLE_STRIP, NULL);
01984 inDoEvalCoord2EM(2.0, 3.0);
01985 inDoEvalCoord2EM(2.0, 2.0);
01986 inDoEvalCoord2EM(2.0, 2.7);
01987 endCallBack(NULL);
01988 
01989 }
01990 if(  bpm->bpatch->umin == 1 &&   bpm->bpatch->umax == 2
01991   && bpm->bpatch->vmin ==2 &&    bpm->bpatch->vmax == 3)
01992 {
01993 #ifdef DEBUG
01994 printf("***number 3\n");
01995 #endif
01996 beginCallBack(GL_QUAD_STRIP, NULL);
01997 inDoEvalCoord2EM(2.0, 3.0);
01998 inDoEvalCoord2EM(1.0, 3.0);
01999 inDoEvalCoord2EM(2.0, 2.3);
02000 inDoEvalCoord2EM(1.0, 2.3);
02001 inDoEvalCoord2EM(2.0, 2.0);
02002 inDoEvalCoord2EM(1.0, 2.0);
02003 endCallBack(NULL);
02004 
02005 beginCallBack(GL_TRIANGLE_STRIP, NULL);
02006 inDoEvalCoord2EM(2.0, 2.3);
02007 inDoEvalCoord2EM(2.0, 2.0);
02008 inDoEvalCoord2EM(2.0, 3.0);
02009 endCallBack(NULL);
02010 
02011 }
02012 return;
02013 #endif //CRACK_TEST
02014 
02015       beginCallBack(bpm->type_array[i], userData);
02016 
02017       for(j=0; j<bpm->length_array[i]; j++)
02018     {
02019       u = bpm->UVarray[k];
02020       v = bpm->UVarray[k+1];
02021 #ifdef USE_LOD
02022           LOD_EVAL_COORD(u,v);
02023 //    glEvalCoord2f(u,v);
02024 #else
02025 
02026 #ifdef  GENERIC_TEST
02027           float temp_normal[3];
02028           float temp_vertex[3];
02029           if(temp_signal == 0)
02030         {
02031           gTessVertexSphere(u,v, temp_normal, temp_vertex);
02032 //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]);
02033               normalCallBack(temp_normal, userData);
02034           vertexCallBack(temp_vertex, userData);
02035         }
02036           else if(temp_signal == 1)
02037         {
02038           gTessVertexCyl(u,v, temp_normal, temp_vertex);
02039 //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]);
02040               normalCallBack(temp_normal, userData);
02041           vertexCallBack(temp_vertex, userData);
02042         }
02043       else
02044 #endif //GENERIC_TEST
02045 
02046         inDoEvalCoord2EM(u,v);
02047      
02048 #endif //USE_LOD
02049 
02050       k += 2;
02051     }
02052       endCallBack(userData);
02053 
02054 #endif //USE_LOD
02055     }
02056 }
02057 
02058 void OpenGLSurfaceEvaluator::inBPMListEvalEM(bezierPatchMesh* list)
02059 {
02060   bezierPatchMesh* temp;
02061   for(temp = list; temp != NULL; temp = temp->next)
02062     {
02063       inBPMEvalEM(temp);
02064     }
02065 }
02066 

Generated on Sun May 27 2012 04:23:38 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.