Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygeninsurfeval.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
1.7.6.1
|