1 /*
2 ** License Applicability. Except to the extent portions of this file are
3 ** made subject to an alternative license as permitted in the SGI Free
4 ** Software License B, Version 1.1 (the "License"), the contents of this
5 ** file are subject only to the provisions of the License. You may not use
6 ** this file except in compliance with the License. You may obtain a copy
7 ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
8 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
9 **
10 ** http://oss.sgi.com/projects/FreeB
11 **
12 ** Note that, as provided in the License, the Software is distributed on an
13 ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
14 ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
15 ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
16 ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
17 **
18 ** Original Code. The Original Code is: OpenGL Sample Implementation,
19 ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
20 ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
21 ** Copyright in any portions created by third parties is as indicated
22 ** elsewhere herein. All Rights Reserved.
23 **
24 ** Additional Notice Provisions: The application programming interfaces
25 ** established by SGI in conjunction with the Original Code are The
26 ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
27 ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
28 ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
29 ** Window System(R) (Version 1.3), released October 19, 1998. This software
30 ** was created using the OpenGL(R) version 1.2.1 Sample Implementation
31 ** published by SGI, but has not been independently verified as being
32 ** compliant with the OpenGL(R) version 1.2.1 Specification.
33 **
34 */
35 /*
36 */
37
38 #include "gluos.h"
39 //#include <stdlib.h>
40 //#include <stdio.h>
41 //#include <GL/gl.h>
42 #include <math.h>
43 #include <assert.h>
44
45 #include "glsurfeval.h"
46
47 //extern int surfcount;
48
49 //#define CRACK_TEST
50
51 #define AVOID_ZERO_NORMAL
52
53 #ifdef AVOID_ZERO_NORMAL
54 #define myabs(x) ((x>0)? x: (-x))
55 #define MYZERO 0.000001
56 #define MYDELTA 0.001
57 #endif
58
59 //#define USE_LOD
60 #ifdef USE_LOD
61 //#define LOD_EVAL_COORD(u,v) inDoEvalCoord2EM(u,v)
62 #define LOD_EVAL_COORD(u,v) glEvalCoord2f(u,v)
63
LOD_interpolate(REAL A[2],REAL B[2],REAL C[2],int j,int k,int pow2_level,REAL & u,REAL & v)64 static void LOD_interpolate(REAL A[2], REAL B[2], REAL C[2], int j, int k, int pow2_level,
65 REAL& u, REAL& v)
66 {
67 REAL a,a1,b,b1;
68
69 a = ((REAL) j) / ((REAL) pow2_level);
70 a1 = 1-a;
71
72 if(j != 0)
73 {
74 b = ((REAL) k) / ((REAL)j);
75 b1 = 1-b;
76 }
77 REAL x,y,z;
78 x = a1;
79 if(j==0)
80 {
81 y=0; z=0;
82 }
83 else{
84 y = b1*a;
85 z = b *a;
86 }
87
88 u = x*A[0] + y*B[0] + z*C[0];
89 v = x*A[1] + y*B[1] + z*C[1];
90 }
91
LOD_triangle(REAL A[2],REAL B[2],REAL C[2],int level)92 void OpenGLSurfaceEvaluator::LOD_triangle(REAL A[2], REAL B[2], REAL C[2],
93 int level)
94 {
95 int k,j;
96 int pow2_level;
97 /*compute 2^level*/
98 pow2_level = 1;
99
100 for(j=0; j<level; j++)
101 pow2_level *= 2;
102 for(j=0; j<=pow2_level-1; j++)
103 {
104 REAL u,v;
105
106 /* beginCallBack(GL_TRIANGLE_STRIP);*/
107 glBegin(GL_TRIANGLE_STRIP);
108 LOD_interpolate(A,B,C, j+1, j+1, pow2_level, u,v);
109 #ifdef USE_LOD
110 LOD_EVAL_COORD(u,v);
111 // glEvalCoord2f(u,v);
112 #else
113 inDoEvalCoord2EM(u,v);
114 #endif
115
116 for(k=0; k<=j; k++)
117 {
118 LOD_interpolate(A,B,C,j,j-k,pow2_level, u,v);
119 #ifdef USE_LOD
120 LOD_EVAL_COORD(u,v);
121 // glEvalCoord2f(u,v);
122 #else
123 inDoEvalCoord2EM(u,v);
124 #endif
125
126 LOD_interpolate(A,B,C,j+1,j-k,pow2_level, u,v);
127
128 #ifdef USE_LOD
129 LOD_EVAL_COORD(u,v);
130 // glEvalCoord2f(u,v);
131 #else
132 inDoEvalCoord2EM(u,v);
133 #endif
134 }
135 // endCallBack();
136 glEnd();
137 }
138 }
139
LOD_eval(int num_vert,REAL * verts,int type,int level)140 void OpenGLSurfaceEvaluator::LOD_eval(int num_vert, REAL* verts, int type,
141 int level
142 )
143 {
144 int i,k;
145 switch(type){
146 case GL_TRIANGLE_STRIP:
147 case GL_QUAD_STRIP:
148 for(i=2, k=4; i<=num_vert-2; i+=2, k+=4)
149 {
150 LOD_triangle(verts+k-4, verts+k-2, verts+k,
151 level
152 );
153 LOD_triangle(verts+k-2, verts+k+2, verts+k,
154 level
155 );
156 }
157 if(num_vert % 2 ==1)
158 {
159 LOD_triangle(verts+2*(num_vert-3), verts+2*(num_vert-2), verts+2*(num_vert-1),
160 level
161 );
162 }
163 break;
164 case GL_TRIANGLE_FAN:
165 for(i=1, k=2; i<=num_vert-2; i++, k+=2)
166 {
167 LOD_triangle(verts,verts+k, verts+k+2,
168 level
169 );
170 }
171 break;
172
173 default:
174 fprintf(stderr, "typy not supported in LOD_\n");
175 }
176 }
177
178
179 #endif //USE_LOD
180
181 //#define GENERIC_TEST
182 #ifdef GENERIC_TEST
183 extern float xmin, xmax, ymin, ymax, zmin, zmax; /*bounding box*/
184 extern int temp_signal;
185
gTessVertexSphere(float u,float v,float temp_normal[3],float temp_vertex[3])186 static void gTessVertexSphere(float u, float v, float temp_normal[3], float temp_vertex[3])
187 {
188 float r=2.0;
189 float Ox = 0.5*(xmin+xmax);
190 float Oy = 0.5*(ymin+ymax);
191 float Oz = 0.5*(zmin+zmax);
192 float nx = cos(v) * sin(u);
193 float ny = sin(v) * sin(u);
194 float nz = cos(u);
195 float x= Ox+r * nx;
196 float y= Oy+r * ny;
197 float z= Oz+r * nz;
198
199 temp_normal[0] = nx;
200 temp_normal[1] = ny;
201 temp_normal[2] = nz;
202 temp_vertex[0] = x;
203 temp_vertex[1] = y;
204 temp_vertex[2] = z;
205
206 // glNormal3f(nx,ny,nz);
207 // glVertex3f(x,y,z);
208 }
209
gTessVertexCyl(float u,float v,float temp_normal[3],float temp_vertex[3])210 static void gTessVertexCyl(float u, float v, float temp_normal[3], float temp_vertex[3])
211 {
212 float r=2.0;
213 float Ox = 0.5*(xmin+xmax);
214 float Oy = 0.5*(ymin+ymax);
215 float Oz = 0.5*(zmin+zmax);
216 float nx = cos(v);
217 float ny = sin(v);
218 float nz = 0;
219 float x= Ox+r * nx;
220 float y= Oy+r * ny;
221 float z= Oz - 2*u;
222
223 temp_normal[0] = nx;
224 temp_normal[1] = ny;
225 temp_normal[2] = nz;
226 temp_vertex[0] = x;
227 temp_vertex[1] = y;
228 temp_vertex[2] = z;
229
230 /*
231 glNormal3f(nx,ny,nz);
232 glVertex3f(x,y,z);
233 */
234 }
235
236 #endif //GENERIC_TEST
237
inBPMListEval(bezierPatchMesh * list)238 void OpenGLSurfaceEvaluator::inBPMListEval(bezierPatchMesh* list)
239 {
240 bezierPatchMesh* temp;
241 for(temp = list; temp != NULL; temp = temp->next)
242 {
243 inBPMEval(temp);
244 }
245 }
246
inBPMEval(bezierPatchMesh * bpm)247 void OpenGLSurfaceEvaluator::inBPMEval(bezierPatchMesh* bpm)
248 {
249 int i,j,k,l;
250 float u,v;
251
252 int ustride = bpm->bpatch->dimension * bpm->bpatch->vorder;
253 int vstride = bpm->bpatch->dimension;
254 inMap2f(
255 (bpm->bpatch->dimension == 3)? GL_MAP2_VERTEX_3 : GL_MAP2_VERTEX_4,
256 bpm->bpatch->umin,
257 bpm->bpatch->umax,
258 ustride,
259 bpm->bpatch->uorder,
260 bpm->bpatch->vmin,
261 bpm->bpatch->vmax,
262 vstride,
263 bpm->bpatch->vorder,
264 bpm->bpatch->ctlpoints);
265
266 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.*/
267 assert(bpm->vertex_array);
268 bpm->normal_array = (float*) malloc(sizeof(float)* (bpm->index_UVarray/2) * 3);
269 assert(bpm->normal_array);
270 #ifdef CRACK_TEST
271 if( global_ev_u1 ==2 && global_ev_u2 == 3
272 && global_ev_v1 ==2 && global_ev_v2 == 3)
273 {
274 REAL vertex[4];
275 REAL normal[4];
276 #ifdef DEBUG
277 printf("***number 1\n");
278 #endif
279
280 beginCallBack(GL_QUAD_STRIP, NULL);
281 inEvalCoord2f(3.0, 3.0);
282 inEvalCoord2f(2.0, 3.0);
283 inEvalCoord2f(3.0, 2.7);
284 inEvalCoord2f(2.0, 2.7);
285 inEvalCoord2f(3.0, 2.0);
286 inEvalCoord2f(2.0, 2.0);
287 endCallBack(NULL);
288
289
290 beginCallBack(GL_TRIANGLE_STRIP, NULL);
291 inEvalCoord2f(2.0, 3.0);
292 inEvalCoord2f(2.0, 2.0);
293 inEvalCoord2f(2.0, 2.7);
294 endCallBack(NULL);
295
296 }
297
298 /*
299 if( global_ev_u1 ==2 && global_ev_u2 == 3
300 && global_ev_v1 ==1 && global_ev_v2 == 2)
301 {
302 #ifdef DEBUG
303 printf("***number 2\n");
304 #endif
305 beginCallBack(GL_QUAD_STRIP);
306 inEvalCoord2f(2.0, 2.0);
307 inEvalCoord2f(2.0, 1.0);
308 inEvalCoord2f(3.0, 2.0);
309 inEvalCoord2f(3.0, 1.0);
310 endCallBack();
311 }
312 */
313 if( global_ev_u1 ==1 && global_ev_u2 == 2
314 && global_ev_v1 ==2 && global_ev_v2 == 3)
315 {
316 #ifdef DEBUG
317 printf("***number 3\n");
318 #endif
319 beginCallBack(GL_QUAD_STRIP, NULL);
320 inEvalCoord2f(2.0, 3.0);
321 inEvalCoord2f(1.0, 3.0);
322 inEvalCoord2f(2.0, 2.3);
323 inEvalCoord2f(1.0, 2.3);
324 inEvalCoord2f(2.0, 2.0);
325 inEvalCoord2f(1.0, 2.0);
326 endCallBack(NULL);
327
328 beginCallBack(GL_TRIANGLE_STRIP, NULL);
329 inEvalCoord2f(2.0, 2.3);
330 inEvalCoord2f(2.0, 2.0);
331 inEvalCoord2f(2.0, 3.0);
332 endCallBack(NULL);
333
334 }
335 return;
336 #endif
337
338 k=0;
339 l=0;
340
341 for(i=0; i<bpm->index_length_array; i++)
342 {
343 beginCallBack(bpm->type_array[i], userData);
344 for(j=0; j<bpm->length_array[i]; j++)
345 {
346 u = bpm->UVarray[k];
347 v = bpm->UVarray[k+1];
348 inDoEvalCoord2NOGE(u,v,
349 bpm->vertex_array+l,
350 bpm->normal_array+l);
351
352 normalCallBack(bpm->normal_array+l, userData);
353 vertexCallBack(bpm->vertex_array+l, userData);
354
355 k += 2;
356 l += 3;
357 }
358 endCallBack(userData);
359 }
360 }
361
inEvalPoint2(int i,int j)362 void OpenGLSurfaceEvaluator::inEvalPoint2(int i, int j)
363 {
364 REAL du, dv;
365 REAL point[4];
366 REAL normal[3];
367 REAL u,v;
368 du = (global_grid_u1 - global_grid_u0) / (REAL)global_grid_nu;
369 dv = (global_grid_v1 - global_grid_v0) / (REAL)global_grid_nv;
370 u = (i==global_grid_nu)? global_grid_u1:(global_grid_u0 + i*du);
371 v = (j == global_grid_nv)? global_grid_v1: (global_grid_v0 +j*dv);
372 inDoEvalCoord2(u,v,point,normal);
373 }
374
inEvalCoord2f(REAL u,REAL v)375 void OpenGLSurfaceEvaluator::inEvalCoord2f(REAL u, REAL v)
376 {
377
378 REAL point[4];
379 REAL normal[3];
380 inDoEvalCoord2(u,v,point, normal);
381 }
382
383
384
385 /*define a grid. store the values into the global variabls:
386 * global_grid_*
387 *These values will be used later by evaluating functions
388 */
inMapGrid2f(int nu,REAL u0,REAL u1,int nv,REAL v0,REAL v1)389 void OpenGLSurfaceEvaluator::inMapGrid2f(int nu, REAL u0, REAL u1,
390 int nv, REAL v0, REAL v1)
391 {
392 global_grid_u0 = u0;
393 global_grid_u1 = u1;
394 global_grid_nu = nu;
395 global_grid_v0 = v0;
396 global_grid_v1 = v1;
397 global_grid_nv = nv;
398 }
399
inEvalMesh2(int lowU,int lowV,int highU,int highV)400 void OpenGLSurfaceEvaluator::inEvalMesh2(int lowU, int lowV, int highU, int highV)
401 {
402 REAL du, dv;
403 int i,j;
404 REAL point[4];
405 REAL normal[3];
406 if(global_grid_nu == 0 || global_grid_nv == 0)
407 return; /*no points need to be output*/
408 du = (global_grid_u1 - global_grid_u0) / (REAL)global_grid_nu;
409 dv = (global_grid_v1 - global_grid_v0) / (REAL)global_grid_nv;
410
411 if(global_grid_nu >= global_grid_nv){
412 for(i=lowU; i<highU; i++){
413 REAL u1 = (i==global_grid_nu)? global_grid_u1:(global_grid_u0 + i*du);
414 REAL u2 = ((i+1) == global_grid_nu)? global_grid_u1: (global_grid_u0+(i+1)*du);
415
416 bgnqstrip();
417 for(j=highV; j>=lowV; j--){
418 REAL v1 = (j == global_grid_nv)? global_grid_v1: (global_grid_v0 +j*dv);
419
420 inDoEvalCoord2(u1, v1, point, normal);
421 inDoEvalCoord2(u2, v1, point, normal);
422 }
423 endqstrip();
424 }
425 }
426
427 else{
428 for(i=lowV; i<highV; i++){
429 REAL v1 = (i==global_grid_nv)? global_grid_v1:(global_grid_v0 + i*dv);
430 REAL v2 = ((i+1) == global_grid_nv)? global_grid_v1: (global_grid_v0+(i+1)*dv);
431
432 bgnqstrip();
433 for(j=highU; j>=lowU; j--){
434 REAL u1 = (j == global_grid_nu)? global_grid_u1: (global_grid_u0 +j*du);
435 inDoEvalCoord2(u1, v2, point, normal);
436 inDoEvalCoord2(u1, v1, point, normal);
437 }
438 endqstrip();
439 }
440 }
441
442 }
443
inMap2f(int k,REAL ulower,REAL uupper,int ustride,int uorder,REAL vlower,REAL vupper,int vstride,int vorder,REAL * ctlPoints)444 void OpenGLSurfaceEvaluator::inMap2f(int k,
445 REAL ulower,
446 REAL uupper,
447 int ustride,
448 int uorder,
449 REAL vlower,
450 REAL vupper,
451 int vstride,
452 int vorder,
453 REAL *ctlPoints)
454 {
455 int i,j,x;
456 REAL *data = global_ev_ctlPoints;
457
458
459
460 if(k == GL_MAP2_VERTEX_3) k=3;
461 else if (k==GL_MAP2_VERTEX_4) k =4;
462 else {
463 printf("error in inMap2f, maptype=%i is wrong, k,map is not updated\n", k);
464 return;
465 }
466
467 global_ev_k = k;
468 global_ev_u1 = ulower;
469 global_ev_u2 = uupper;
470 global_ev_ustride = ustride;
471 global_ev_uorder = uorder;
472 global_ev_v1 = vlower;
473 global_ev_v2 = vupper;
474 global_ev_vstride = vstride;
475 global_ev_vorder = vorder;
476
477 /*copy the contrl points from ctlPoints to global_ev_ctlPoints*/
478 for (i=0; i<uorder; i++) {
479 for (j=0; j<vorder; j++) {
480 for (x=0; x<k; x++) {
481 data[x] = ctlPoints[x];
482 }
483 ctlPoints += vstride;
484 data += k;
485 }
486 ctlPoints += ustride - vstride * vorder;
487 }
488
489 }
490
491
492 /*
493 *given a point p with homegeneous coordiante (x,y,z,w),
494 *let pu(x,y,z,w) be its partial derivative vector with
495 *respect to u
496 *and pv(x,y,z,w) be its partial derivative vector with repect to v.
497 *This function returns the partial derivative vectors of the
498 *inhomegensous coordinates, i.e.,
499 * (x/w, y/w, z/w) with respect to u and v.
500 */
inComputeFirstPartials(REAL * p,REAL * pu,REAL * pv)501 void OpenGLSurfaceEvaluator::inComputeFirstPartials(REAL *p, REAL *pu, REAL *pv)
502 {
503 pu[0] = pu[0]*p[3] - pu[3]*p[0];
504 pu[1] = pu[1]*p[3] - pu[3]*p[1];
505 pu[2] = pu[2]*p[3] - pu[3]*p[2];
506
507 pv[0] = pv[0]*p[3] - pv[3]*p[0];
508 pv[1] = pv[1]*p[3] - pv[3]*p[1];
509 pv[2] = pv[2]*p[3] - pv[3]*p[2];
510 }
511
512 /*compute the cross product of pu and pv and normalize.
513 *the normal is returned in retNormal
514 * pu: dimension 3
515 * pv: dimension 3
516 * n: return normal, of dimension 3
517 */
inComputeNormal2(REAL * pu,REAL * pv,REAL * n)518 void OpenGLSurfaceEvaluator::inComputeNormal2(REAL *pu, REAL *pv, REAL *n)
519 {
520 REAL mag;
521
522 n[0] = pu[1]*pv[2] - pu[2]*pv[1];
523 n[1] = pu[2]*pv[0] - pu[0]*pv[2];
524 n[2] = pu[0]*pv[1] - pu[1]*pv[0];
525
526 mag = sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
527
528 if (mag > 0.0) {
529 n[0] /= mag;
530 n[1] /= mag;
531 n[2] /= mag;
532 }
533 }
534
535
536
537 /*Compute point and normal
538 *see the head of inDoDomain2WithDerivs
539 *for the meaning of the arguments
540 */
inDoEvalCoord2(REAL u,REAL v,REAL * retPoint,REAL * retNormal)541 void OpenGLSurfaceEvaluator::inDoEvalCoord2(REAL u, REAL v,
542 REAL *retPoint, REAL *retNormal)
543 {
544
545 REAL du[4];
546 REAL dv[4];
547
548
549 assert(global_ev_k>=3 && global_ev_k <= 4);
550 /*compute homegeneous point and partial derivatives*/
551 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);
552
553 #ifdef AVOID_ZERO_NORMAL
554
555 if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
556 {
557
558 REAL tempdu[4];
559 REAL tempdata[4];
560 REAL u1 = global_ev_u1;
561 REAL u2 = global_ev_u2;
562 if(u-MYDELTA*(u2-u1) < u1)
563 u = u+ MYDELTA*(u2-u1);
564 else
565 u = u-MYDELTA*(u2-u1);
566 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);
567 }
568 if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
569 {
570 REAL tempdv[4];
571 REAL tempdata[4];
572 REAL v1 = global_ev_v1;
573 REAL v2 = global_ev_v2;
574 if(v-MYDELTA*(v2-v1) < v1)
575 v = v+ MYDELTA*(v2-v1);
576 else
577 v = v-MYDELTA*(v2-v1);
578 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);
579 }
580 #endif
581
582
583 /*compute normal*/
584 switch(global_ev_k){
585 case 3:
586 inComputeNormal2(du, dv, retNormal);
587
588 break;
589 case 4:
590 inComputeFirstPartials(retPoint, du, dv);
591 inComputeNormal2(du, dv, retNormal);
592 /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
593 retPoint[0] /= retPoint[3];
594 retPoint[1] /= retPoint[3];
595 retPoint[2] /= retPoint[3];
596 break;
597 }
598 /*output this vertex*/
599 /* inMeshStreamInsert(global_ms, retPoint, retNormal);*/
600
601
602
603 glNormal3fv(retNormal);
604 glVertex3fv(retPoint);
605
606
607
608
609 #ifdef DEBUG
610 printf("vertex(%f,%f,%f)\n", retPoint[0],retPoint[1],retPoint[2]);
611 #endif
612
613
614
615 }
616
617 /*Compute point and normal
618 *see the head of inDoDomain2WithDerivs
619 *for the meaning of the arguments
620 */
inDoEvalCoord2NOGE_BU(REAL u,REAL v,REAL * retPoint,REAL * retNormal)621 void OpenGLSurfaceEvaluator::inDoEvalCoord2NOGE_BU(REAL u, REAL v,
622 REAL *retPoint, REAL *retNormal)
623 {
624
625 REAL du[4];
626 REAL dv[4];
627
628
629 assert(global_ev_k>=3 && global_ev_k <= 4);
630 /*compute homegeneous point and partial derivatives*/
631 // inPreEvaluateBU(global_ev_k, global_ev_uorder, global_ev_vorder, (u-global_ev_u1)/(global_ev_u2-global_ev_u1), global_ev_ctlPoints);
632 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);
633
634
635 #ifdef AVOID_ZERO_NORMAL
636
637 if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
638 {
639
640 REAL tempdu[4];
641 REAL tempdata[4];
642 REAL u1 = global_ev_u1;
643 REAL u2 = global_ev_u2;
644 if(u-MYDELTA*(u2-u1) < u1)
645 u = u+ MYDELTA*(u2-u1);
646 else
647 u = u-MYDELTA*(u2-u1);
648 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);
649 }
650 if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
651 {
652 REAL tempdv[4];
653 REAL tempdata[4];
654 REAL v1 = global_ev_v1;
655 REAL v2 = global_ev_v2;
656 if(v-MYDELTA*(v2-v1) < v1)
657 v = v+ MYDELTA*(v2-v1);
658 else
659 v = v-MYDELTA*(v2-v1);
660 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);
661 }
662 #endif
663
664 /*compute normal*/
665 switch(global_ev_k){
666 case 3:
667 inComputeNormal2(du, dv, retNormal);
668 break;
669 case 4:
670 inComputeFirstPartials(retPoint, du, dv);
671 inComputeNormal2(du, dv, retNormal);
672 /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
673 retPoint[0] /= retPoint[3];
674 retPoint[1] /= retPoint[3];
675 retPoint[2] /= retPoint[3];
676 break;
677 }
678 }
679
680 /*Compute point and normal
681 *see the head of inDoDomain2WithDerivs
682 *for the meaning of the arguments
683 */
inDoEvalCoord2NOGE_BV(REAL u,REAL v,REAL * retPoint,REAL * retNormal)684 void OpenGLSurfaceEvaluator::inDoEvalCoord2NOGE_BV(REAL u, REAL v,
685 REAL *retPoint, REAL *retNormal)
686 {
687
688 REAL du[4];
689 REAL dv[4];
690
691
692 assert(global_ev_k>=3 && global_ev_k <= 4);
693 /*compute homegeneous point and partial derivatives*/
694 // inPreEvaluateBV(global_ev_k, global_ev_uorder, global_ev_vorder, (v-global_ev_v1)/(global_ev_v2-global_ev_v1), global_ev_ctlPoints);
695
696 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);
697
698
699 #ifdef AVOID_ZERO_NORMAL
700
701 if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
702 {
703
704 REAL tempdu[4];
705 REAL tempdata[4];
706 REAL u1 = global_ev_u1;
707 REAL u2 = global_ev_u2;
708 if(u-MYDELTA*(u2-u1) < u1)
709 u = u+ MYDELTA*(u2-u1);
710 else
711 u = u-MYDELTA*(u2-u1);
712 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);
713 }
714 if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
715 {
716 REAL tempdv[4];
717 REAL tempdata[4];
718 REAL v1 = global_ev_v1;
719 REAL v2 = global_ev_v2;
720 if(v-MYDELTA*(v2-v1) < v1)
721 v = v+ MYDELTA*(v2-v1);
722 else
723 v = v-MYDELTA*(v2-v1);
724 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);
725 }
726 #endif
727
728 /*compute normal*/
729 switch(global_ev_k){
730 case 3:
731 inComputeNormal2(du, dv, retNormal);
732 break;
733 case 4:
734 inComputeFirstPartials(retPoint, du, dv);
735 inComputeNormal2(du, dv, retNormal);
736 /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
737 retPoint[0] /= retPoint[3];
738 retPoint[1] /= retPoint[3];
739 retPoint[2] /= retPoint[3];
740 break;
741 }
742 }
743
744
745 /*Compute point and normal
746 *see the head of inDoDomain2WithDerivs
747 *for the meaning of the arguments
748 */
inDoEvalCoord2NOGE(REAL u,REAL v,REAL * retPoint,REAL * retNormal)749 void OpenGLSurfaceEvaluator::inDoEvalCoord2NOGE(REAL u, REAL v,
750 REAL *retPoint, REAL *retNormal)
751 {
752
753 REAL du[4];
754 REAL dv[4];
755
756
757 assert(global_ev_k>=3 && global_ev_k <= 4);
758 /*compute homegeneous point and partial derivatives*/
759 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);
760
761
762 #ifdef AVOID_ZERO_NORMAL
763
764 if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
765 {
766
767 REAL tempdu[4];
768 REAL tempdata[4];
769 REAL u1 = global_ev_u1;
770 REAL u2 = global_ev_u2;
771 if(u-MYDELTA*(u2-u1) < u1)
772 u = u+ MYDELTA*(u2-u1);
773 else
774 u = u-MYDELTA*(u2-u1);
775 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);
776 }
777 if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
778 {
779 REAL tempdv[4];
780 REAL tempdata[4];
781 REAL v1 = global_ev_v1;
782 REAL v2 = global_ev_v2;
783 if(v-MYDELTA*(v2-v1) < v1)
784 v = v+ MYDELTA*(v2-v1);
785 else
786 v = v-MYDELTA*(v2-v1);
787 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);
788 }
789 #endif
790
791 /*compute normal*/
792 switch(global_ev_k){
793 case 3:
794 inComputeNormal2(du, dv, retNormal);
795 break;
796 case 4:
797 inComputeFirstPartials(retPoint, du, dv);
798 inComputeNormal2(du, dv, retNormal);
799 /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
800 retPoint[0] /= retPoint[3];
801 retPoint[1] /= retPoint[3];
802 retPoint[2] /= retPoint[3];
803 break;
804 }
805 // glNormal3fv(retNormal);
806 // glVertex3fv(retPoint);
807 }
808
inPreEvaluateBV(int k,int uorder,int vorder,REAL vprime,REAL * baseData)809 void OpenGLSurfaceEvaluator::inPreEvaluateBV(int k, int uorder, int vorder, REAL vprime, REAL *baseData)
810 {
811 int j,row,col;
812 REAL p, pdv;
813 REAL *data;
814
815 if(global_vprime != vprime || global_vorder != vorder) {
816 inPreEvaluateWithDeriv(vorder, vprime, global_vcoeff, global_vcoeffDeriv);
817 global_vprime = vprime;
818 global_vorder = vorder;
819 }
820
821 for(j=0; j<k; j++){
822 data = baseData+j;
823 for(row=0; row<uorder; row++){
824 p = global_vcoeff[0] * (*data);
825 pdv = global_vcoeffDeriv[0] * (*data);
826 data += k;
827 for(col = 1; col < vorder; col++){
828 p += global_vcoeff[col] * (*data);
829 pdv += global_vcoeffDeriv[col] * (*data);
830 data += k;
831 }
832 global_BV[row][j] = p;
833 global_PBV[row][j] = pdv;
834 }
835 }
836 }
837
inPreEvaluateBU(int k,int uorder,int vorder,REAL uprime,REAL * baseData)838 void OpenGLSurfaceEvaluator::inPreEvaluateBU(int k, int uorder, int vorder, REAL uprime, REAL *baseData)
839 {
840 int j,row,col;
841 REAL p, pdu;
842 REAL *data;
843
844 if(global_uprime != uprime || global_uorder != uorder) {
845 inPreEvaluateWithDeriv(uorder, uprime, global_ucoeff, global_ucoeffDeriv);
846 global_uprime = uprime;
847 global_uorder = uorder;
848 }
849
850 for(j=0; j<k; j++){
851 data = baseData+j;
852 for(col=0; col<vorder; col++){
853 data = baseData+j + k*col;
854 p = global_ucoeff[0] * (*data);
855 pdu = global_ucoeffDeriv[0] * (*data);
856 data += k*uorder;
857 for(row = 1; row < uorder; row++){
858 p += global_ucoeff[row] * (*data);
859 pdu += global_ucoeffDeriv[row] * (*data);
860 data += k * uorder;
861 }
862 global_BU[col][j] = p;
863 global_PBU[col][j] = pdu;
864 }
865 }
866 }
867
inDoDomain2WithDerivsBU(int k,REAL u,REAL v,REAL u1,REAL u2,int uorder,REAL v1,REAL v2,int vorder,REAL * baseData,REAL * retPoint,REAL * retdu,REAL * retdv)868 void OpenGLSurfaceEvaluator::inDoDomain2WithDerivsBU(int k, REAL u, REAL v,
869 REAL u1, REAL u2, int uorder,
870 REAL v1, REAL v2, int vorder,
871 REAL *baseData,
872 REAL *retPoint, REAL* retdu, REAL *retdv)
873 {
874 int j, col;
875
876 REAL vprime;
877
878
879 if((u2 == u1) || (v2 == v1))
880 return;
881
882 vprime = (v - v1) / (v2 - v1);
883
884
885 if(global_vprime != vprime || global_vorder != vorder) {
886 inPreEvaluateWithDeriv(vorder, vprime, global_vcoeff, global_vcoeffDeriv);
887 global_vprime = vprime;
888 global_vorder = vorder;
889 }
890
891
892 for(j=0; j<k; j++)
893 {
894 retPoint[j] = retdu[j] = retdv[j] = 0.0;
895 for (col = 0; col < vorder; col++) {
896 retPoint[j] += global_BU[col][j] * global_vcoeff[col];
897 retdu[j] += global_PBU[col][j] * global_vcoeff[col];
898 retdv[j] += global_BU[col][j] * global_vcoeffDeriv[col];
899 }
900 }
901 }
902
inDoDomain2WithDerivsBV(int k,REAL u,REAL v,REAL u1,REAL u2,int uorder,REAL v1,REAL v2,int vorder,REAL * baseData,REAL * retPoint,REAL * retdu,REAL * retdv)903 void OpenGLSurfaceEvaluator::inDoDomain2WithDerivsBV(int k, REAL u, REAL v,
904 REAL u1, REAL u2, int uorder,
905 REAL v1, REAL v2, int vorder,
906 REAL *baseData,
907 REAL *retPoint, REAL* retdu, REAL *retdv)
908 {
909 int j, row;
910 REAL uprime;
911
912
913 if((u2 == u1) || (v2 == v1))
914 return;
915 uprime = (u - u1) / (u2 - u1);
916
917
918 if(global_uprime != uprime || global_uorder != uorder) {
919 inPreEvaluateWithDeriv(uorder, uprime, global_ucoeff, global_ucoeffDeriv);
920 global_uprime = uprime;
921 global_uorder = uorder;
922 }
923
924
925 for(j=0; j<k; j++)
926 {
927 retPoint[j] = retdu[j] = retdv[j] = 0.0;
928 for (row = 0; row < uorder; row++) {
929 retPoint[j] += global_BV[row][j] * global_ucoeff[row];
930 retdu[j] += global_BV[row][j] * global_ucoeffDeriv[row];
931 retdv[j] += global_PBV[row][j] * global_ucoeff[row];
932 }
933 }
934 }
935
936
937 /*
938 *given a Bezier surface, and parameter (u,v), compute the point in the object space,
939 *and the normal
940 *k: the dimension of the object space: usually 2,3,or 4.
941 *u,v: the paramter pair.
942 *u1,u2,uorder: the Bezier polynomial of u coord is defined on [u1,u2] with order uorder.
943 *v1,v2,vorder: the Bezier polynomial of v coord is defined on [v1,v2] with order vorder.
944 *baseData: contrl points. arranged as: (u,v,k).
945 *retPoint: the computed point (one point) with dimension k.
946 *retdu: the computed partial derivative with respect to u.
947 *retdv: the computed partial derivative with respect to v.
948 */
inDoDomain2WithDerivs(int k,REAL u,REAL v,REAL u1,REAL u2,int uorder,REAL v1,REAL v2,int vorder,REAL * baseData,REAL * retPoint,REAL * retdu,REAL * retdv)949 void OpenGLSurfaceEvaluator::inDoDomain2WithDerivs(int k, REAL u, REAL v,
950 REAL u1, REAL u2, int uorder,
951 REAL v1, REAL v2, int vorder,
952 REAL *baseData,
953 REAL *retPoint, REAL *retdu, REAL *retdv)
954 {
955 int j, row, col;
956 REAL uprime;
957 REAL vprime;
958 REAL p;
959 REAL pdv;
960 REAL *data;
961
962 if((u2 == u1) || (v2 == v1))
963 return;
964 uprime = (u - u1) / (u2 - u1);
965 vprime = (v - v1) / (v2 - v1);
966
967 /* Compute coefficients for values and derivs */
968
969 /* Use already cached values if possible */
970 if(global_uprime != uprime || global_uorder != uorder) {
971 inPreEvaluateWithDeriv(uorder, uprime, global_ucoeff, global_ucoeffDeriv);
972 global_uorder = uorder;
973 global_uprime = uprime;
974 }
975 if (global_vprime != vprime ||
976 global_vorder != vorder) {
977 inPreEvaluateWithDeriv(vorder, vprime, global_vcoeff, global_vcoeffDeriv);
978 global_vorder = vorder;
979 global_vprime = vprime;
980 }
981
982 for (j = 0; j < k; j++) {
983 data=baseData+j;
984 retPoint[j] = retdu[j] = retdv[j] = 0.0;
985 for (row = 0; row < uorder; row++) {
986 /*
987 ** Minor optimization.
988 ** The col == 0 part of the loop is extracted so we don't
989 ** have to initialize p and pdv to 0.
990 */
991 p = global_vcoeff[0] * (*data);
992 pdv = global_vcoeffDeriv[0] * (*data);
993 data += k;
994 for (col = 1; col < vorder; col++) {
995 /* Incrementally build up p, pdv value */
996 p += global_vcoeff[col] * (*data);
997 pdv += global_vcoeffDeriv[col] * (*data);
998 data += k;
999 }
1000 /* Use p, pdv value to incrementally add up r, du, dv */
1001 retPoint[j] += global_ucoeff[row] * p;
1002 retdu[j] += global_ucoeffDeriv[row] * p;
1003 retdv[j] += global_ucoeff[row] * pdv;
1004 }
1005 }
1006 }
1007
1008
1009 /*
1010 *compute the Bezier polynomials C[n,j](v) for all j at v with
1011 *return values stored in coeff[], where
1012 * C[n,j](v) = (n,j) * v^j * (1-v)^(n-j),
1013 * j=0,1,2,...,n.
1014 *order : n+1
1015 *vprime: v
1016 *coeff : coeff[j]=C[n,j](v), this array store the returned values.
1017 *The algorithm is a recursive scheme:
1018 * C[0,0]=1;
1019 * C[n,j](v) = (1-v)*C[n-1,j](v) + v*C[n-1,j-1](v), n>=1
1020 *This code is copied from opengl/soft/so_eval.c:PreEvaluate
1021 */
inPreEvaluate(int order,REAL vprime,REAL * coeff)1022 void OpenGLSurfaceEvaluator::inPreEvaluate(int order, REAL vprime, REAL *coeff)
1023 {
1024 int i, j;
1025 REAL oldval, temp;
1026 REAL oneMinusvprime;
1027
1028 /*
1029 * Minor optimization
1030 * Compute orders 1 and 2 outright, and set coeff[0], coeff[1] to
1031 * their i==1 loop values to avoid the initialization and the i==1 loop.
1032 */
1033 if (order == 1) {
1034 coeff[0] = 1.0;
1035 return;
1036 }
1037
1038 oneMinusvprime = 1-vprime;
1039 coeff[0] = oneMinusvprime;
1040 coeff[1] = vprime;
1041 if (order == 2) return;
1042
1043 for (i = 2; i < order; i++) {
1044 oldval = coeff[0] * vprime;
1045 coeff[0] = oneMinusvprime * coeff[0];
1046 for (j = 1; j < i; j++) {
1047 temp = oldval;
1048 oldval = coeff[j] * vprime;
1049 coeff[j] = temp + oneMinusvprime * coeff[j];
1050 }
1051 coeff[j] = oldval;
1052 }
1053 }
1054
1055 /*
1056 *compute the Bezier polynomials C[n,j](v) and derivatives for all j at v with
1057 *return values stored in coeff[] and coeffDeriv[].
1058 *see the head of function inPreEvaluate for the definition of C[n,j](v)
1059 *and how to compute the values.
1060 *The algorithm to compute the derivative is:
1061 * dC[0,0](v) = 0.
1062 * dC[n,j](v) = n*(dC[n-1,j-1](v) - dC[n-1,j](v)).
1063 *
1064 *This code is copied from opengl/soft/so_eval.c:PreEvaluateWidthDeriv
1065 */
inPreEvaluateWithDeriv(int order,REAL vprime,REAL * coeff,REAL * coeffDeriv)1066 void OpenGLSurfaceEvaluator::inPreEvaluateWithDeriv(int order, REAL vprime,
1067 REAL *coeff, REAL *coeffDeriv)
1068 {
1069 int i, j;
1070 REAL oldval, temp;
1071 REAL oneMinusvprime;
1072
1073 oneMinusvprime = 1-vprime;
1074 /*
1075 * Minor optimization
1076 * Compute orders 1 and 2 outright, and set coeff[0], coeff[1] to
1077 * their i==1 loop values to avoid the initialization and the i==1 loop.
1078 */
1079 if (order == 1) {
1080 coeff[0] = 1.0;
1081 coeffDeriv[0] = 0.0;
1082 return;
1083 } else if (order == 2) {
1084 coeffDeriv[0] = -1.0;
1085 coeffDeriv[1] = 1.0;
1086 coeff[0] = oneMinusvprime;
1087 coeff[1] = vprime;
1088 return;
1089 }
1090 coeff[0] = oneMinusvprime;
1091 coeff[1] = vprime;
1092 for (i = 2; i < order - 1; i++) {
1093 oldval = coeff[0] * vprime;
1094 coeff[0] = oneMinusvprime * coeff[0];
1095 for (j = 1; j < i; j++) {
1096 temp = oldval;
1097 oldval = coeff[j] * vprime;
1098 coeff[j] = temp + oneMinusvprime * coeff[j];
1099 }
1100 coeff[j] = oldval;
1101 }
1102 coeffDeriv[0] = -coeff[0];
1103 /*
1104 ** Minor optimization:
1105 ** Would make this a "for (j=1; j<order-1; j++)" loop, but it is always
1106 ** executed at least once, so this is more efficient.
1107 */
1108 j=1;
1109 do {
1110 coeffDeriv[j] = coeff[j-1] - coeff[j];
1111 j++;
1112 } while (j < order - 1);
1113 coeffDeriv[j] = coeff[j-1];
1114
1115 oldval = coeff[0] * vprime;
1116 coeff[0] = oneMinusvprime * coeff[0];
1117 for (j = 1; j < i; j++) {
1118 temp = oldval;
1119 oldval = coeff[j] * vprime;
1120 coeff[j] = temp + oneMinusvprime * coeff[j];
1121 }
1122 coeff[j] = oldval;
1123 }
1124
inEvalULine(int n_points,REAL v,REAL * u_vals,int stride,REAL ret_points[][3],REAL ret_normals[][3])1125 void OpenGLSurfaceEvaluator::inEvalULine(int n_points, REAL v, REAL* u_vals,
1126 int stride, REAL ret_points[][3], REAL ret_normals[][3])
1127 {
1128 int i,k;
1129 REAL temp[4];
1130 inPreEvaluateBV_intfac(v);
1131
1132 for(i=0,k=0; i<n_points; i++, k += stride)
1133 {
1134 inDoEvalCoord2NOGE_BV(u_vals[k],v,temp, ret_normals[i]);
1135
1136 ret_points[i][0] = temp[0];
1137 ret_points[i][1] = temp[1];
1138 ret_points[i][2] = temp[2];
1139
1140 }
1141
1142 }
1143
inEvalVLine(int n_points,REAL u,REAL * v_vals,int stride,REAL ret_points[][3],REAL ret_normals[][3])1144 void OpenGLSurfaceEvaluator::inEvalVLine(int n_points, REAL u, REAL* v_vals,
1145 int stride, REAL ret_points[][3], REAL ret_normals[][3])
1146 {
1147 int i,k;
1148 REAL temp[4];
1149 inPreEvaluateBU_intfac(u);
1150 for(i=0,k=0; i<n_points; i++, k += stride)
1151 {
1152 inDoEvalCoord2NOGE_BU(u, v_vals[k], temp, ret_normals[i]);
1153 ret_points[i][0] = temp[0];
1154 ret_points[i][1] = temp[1];
1155 ret_points[i][2] = temp[2];
1156 }
1157 }
1158
1159
1160 /*triangulate a strip bounded by two lines which are parallel to U-axis
1161 *upperVerts: the verteces on the upper line
1162 *lowerVertx: the verteces on the lower line
1163 *n_upper >=1
1164 *n_lower >=1
1165 */
inEvalUStrip(int n_upper,REAL v_upper,REAL * upper_val,int n_lower,REAL v_lower,REAL * lower_val)1166 void OpenGLSurfaceEvaluator::inEvalUStrip(int n_upper, REAL v_upper, REAL* upper_val, int n_lower, REAL v_lower, REAL* lower_val)
1167 {
1168 int i,j,k,l;
1169 REAL leftMostV[2];
1170 typedef REAL REAL3[3];
1171
1172 REAL3* upperXYZ = (REAL3*) malloc(sizeof(REAL3)*n_upper);
1173 assert(upperXYZ);
1174 REAL3* upperNormal = (REAL3*) malloc(sizeof(REAL3) * n_upper);
1175 assert(upperNormal);
1176 REAL3* lowerXYZ = (REAL3*) malloc(sizeof(REAL3)*n_lower);
1177 assert(lowerXYZ);
1178 REAL3* lowerNormal = (REAL3*) malloc(sizeof(REAL3) * n_lower);
1179 assert(lowerNormal);
1180
1181 inEvalULine(n_upper, v_upper, upper_val, 1, upperXYZ, upperNormal);
1182 inEvalULine(n_lower, v_lower, lower_val, 1, lowerXYZ, lowerNormal);
1183
1184
1185
1186 REAL* leftMostXYZ;
1187 REAL* leftMostNormal;
1188
1189 /*
1190 *the algorithm works by scanning from left to right.
1191 *leftMostV: the left most of the remaining verteces (on both upper and lower).
1192 * it could an element of upperVerts or lowerVerts.
1193 *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 */
1194
1195 /*initialize i,j,and leftMostV
1196 */
1197 if(upper_val[0] <= lower_val[0])
1198 {
1199 i=1;
1200 j=0;
1201
1202 leftMostV[0] = upper_val[0];
1203 leftMostV[1] = v_upper;
1204 leftMostXYZ = upperXYZ[0];
1205 leftMostNormal = upperNormal[0];
1206 }
1207 else
1208 {
1209 i=0;
1210 j=1;
1211
1212 leftMostV[0] = lower_val[0];
1213 leftMostV[1] = v_lower;
1214
1215 leftMostXYZ = lowerXYZ[0];
1216 leftMostNormal = lowerNormal[0];
1217 }
1218
1219 /*the main loop.
1220 *the invariance is that:
1221 *at the beginning of each loop, the meaning of i,j,and leftMostV are
1222 *maintained
1223 */
1224 while(1)
1225 {
1226 if(i >= n_upper) /*case1: no more in upper*/
1227 {
1228 if(j<n_lower-1) /*at least two vertices in lower*/
1229 {
1230 bgntfan();
1231 glNormal3fv(leftMostNormal);
1232 glVertex3fv(leftMostXYZ);
1233
1234 while(j<n_lower){
1235 glNormal3fv(lowerNormal[j]);
1236 glVertex3fv(lowerXYZ[j]);
1237 j++;
1238
1239 }
1240 endtfan();
1241 }
1242 break; /*exit the main loop*/
1243 }
1244 else if(j>= n_lower) /*case2: no more in lower*/
1245 {
1246 if(i<n_upper-1) /*at least two vertices in upper*/
1247 {
1248 bgntfan();
1249 glNormal3fv(leftMostNormal);
1250 glVertex3fv(leftMostXYZ);
1251
1252 for(k=n_upper-1; k>=i; k--) /*reverse order for two-side lighting*/
1253 {
1254 glNormal3fv(upperNormal[k]);
1255 glVertex3fv(upperXYZ[k]);
1256 }
1257
1258 endtfan();
1259 }
1260 break; /*exit the main loop*/
1261 }
1262 else /* case3: neither is empty, plus the leftMostV, there is at least one triangle to output*/
1263 {
1264 if(upper_val[i] <= lower_val[j])
1265 {
1266 bgntfan();
1267
1268 glNormal3fv(lowerNormal[j]);
1269 glVertex3fv(lowerXYZ[j]);
1270
1271 /*find the last k>=i such that
1272 *upperverts[k][0] <= lowerverts[j][0]
1273 */
1274 k=i;
1275
1276 while(k<n_upper)
1277 {
1278 if(upper_val[k] > lower_val[j])
1279 break;
1280 k++;
1281
1282 }
1283 k--;
1284
1285
1286 for(l=k; l>=i; l--)/*the reverse is for two-side lighting*/
1287 {
1288 glNormal3fv(upperNormal[l]);
1289 glVertex3fv(upperXYZ[l]);
1290
1291 }
1292 glNormal3fv(leftMostNormal);
1293 glVertex3fv(leftMostXYZ);
1294
1295 endtfan();
1296
1297 /*update i and leftMostV for next loop
1298 */
1299 i = k+1;
1300
1301 leftMostV[0] = upper_val[k];
1302 leftMostV[1] = v_upper;
1303 leftMostNormal = upperNormal[k];
1304 leftMostXYZ = upperXYZ[k];
1305 }
1306 else /*upperVerts[i][0] > lowerVerts[j][0]*/
1307 {
1308 bgntfan();
1309 glNormal3fv(upperNormal[i]);
1310 glVertex3fv(upperXYZ[i]);
1311
1312 glNormal3fv(leftMostNormal);
1313 glVertex3fv(leftMostXYZ);
1314
1315
1316 /*find the last k>=j such that
1317 *lowerverts[k][0] < upperverts[i][0]
1318 */
1319 k=j;
1320 while(k< n_lower)
1321 {
1322 if(lower_val[k] >= upper_val[i])
1323 break;
1324 glNormal3fv(lowerNormal[k]);
1325 glVertex3fv(lowerXYZ[k]);
1326
1327 k++;
1328 }
1329 endtfan();
1330
1331 /*update j and leftMostV for next loop
1332 */
1333 j=k;
1334 leftMostV[0] = lower_val[j-1];
1335 leftMostV[1] = v_lower;
1336
1337 leftMostNormal = lowerNormal[j-1];
1338 leftMostXYZ = lowerXYZ[j-1];
1339 }
1340 }
1341 }
1342 //clean up
1343 free(upperXYZ);
1344 free(lowerXYZ);
1345 free(upperNormal);
1346 free(lowerNormal);
1347 }
1348
1349 /*triangulate a strip bounded by two lines which are parallel to V-axis
1350 *leftVerts: the verteces on the left line
1351 *rightVertx: the verteces on the right line
1352 *n_left >=1
1353 *n_right >=1
1354 */
inEvalVStrip(int n_left,REAL u_left,REAL * left_val,int n_right,REAL u_right,REAL * right_val)1355 void OpenGLSurfaceEvaluator::inEvalVStrip(int n_left, REAL u_left, REAL* left_val, int n_right, REAL u_right, REAL* right_val)
1356 {
1357 int i,j,k,l;
1358 REAL botMostV[2];
1359 typedef REAL REAL3[3];
1360
1361 REAL3* leftXYZ = (REAL3*) malloc(sizeof(REAL3)*n_left);
1362 assert(leftXYZ);
1363 REAL3* leftNormal = (REAL3*) malloc(sizeof(REAL3) * n_left);
1364 assert(leftNormal);
1365 REAL3* rightXYZ = (REAL3*) malloc(sizeof(REAL3)*n_right);
1366 assert(rightXYZ);
1367 REAL3* rightNormal = (REAL3*) malloc(sizeof(REAL3) * n_right);
1368 assert(rightNormal);
1369
1370 inEvalVLine(n_left, u_left, left_val, 1, leftXYZ, leftNormal);
1371 inEvalVLine(n_right, u_right, right_val, 1, rightXYZ, rightNormal);
1372
1373
1374
1375 REAL* botMostXYZ;
1376 REAL* botMostNormal;
1377
1378 /*
1379 *the algorithm works by scanning from bot to top.
1380 *botMostV: the bot most of the remaining verteces (on both left and right).
1381 * it could an element of leftVerts or rightVerts.
1382 *i: leftVerts[i] is the first vertex to the top of botMostV on left line
1383 *j: rightVerts[j] is the first vertex to the top of botMostV on rightline */
1384
1385 /*initialize i,j,and botMostV
1386 */
1387 if(left_val[0] <= right_val[0])
1388 {
1389 i=1;
1390 j=0;
1391
1392 botMostV[0] = u_left;
1393 botMostV[1] = left_val[0];
1394 botMostXYZ = leftXYZ[0];
1395 botMostNormal = leftNormal[0];
1396 }
1397 else
1398 {
1399 i=0;
1400 j=1;
1401
1402 botMostV[0] = u_right;
1403 botMostV[1] = right_val[0];
1404
1405 botMostXYZ = rightXYZ[0];
1406 botMostNormal = rightNormal[0];
1407 }
1408
1409 /*the main loop.
1410 *the invariance is that:
1411 *at the beginning of each loop, the meaning of i,j,and botMostV are
1412 *maintained
1413 */
1414 while(1)
1415 {
1416 if(i >= n_left) /*case1: no more in left*/
1417 {
1418 if(j<n_right-1) /*at least two vertices in right*/
1419 {
1420 bgntfan();
1421 glNormal3fv(botMostNormal);
1422 glVertex3fv(botMostXYZ);
1423
1424 while(j<n_right){
1425 glNormal3fv(rightNormal[j]);
1426 glVertex3fv(rightXYZ[j]);
1427 j++;
1428
1429 }
1430 endtfan();
1431 }
1432 break; /*exit the main loop*/
1433 }
1434 else if(j>= n_right) /*case2: no more in right*/
1435 {
1436 if(i<n_left-1) /*at least two vertices in left*/
1437 {
1438 bgntfan();
1439 glNormal3fv(botMostNormal);
1440 glVertex3fv(botMostXYZ);
1441
1442 for(k=n_left-1; k>=i; k--) /*reverse order for two-side lighting*/
1443 {
1444 glNormal3fv(leftNormal[k]);
1445 glVertex3fv(leftXYZ[k]);
1446 }
1447
1448 endtfan();
1449 }
1450 break; /*exit the main loop*/
1451 }
1452 else /* case3: neither is empty, plus the botMostV, there is at least one triangle to output*/
1453 {
1454 if(left_val[i] <= right_val[j])
1455 {
1456 bgntfan();
1457
1458 glNormal3fv(rightNormal[j]);
1459 glVertex3fv(rightXYZ[j]);
1460
1461 /*find the last k>=i such that
1462 *leftverts[k][0] <= rightverts[j][0]
1463 */
1464 k=i;
1465
1466 while(k<n_left)
1467 {
1468 if(left_val[k] > right_val[j])
1469 break;
1470 k++;
1471
1472 }
1473 k--;
1474
1475
1476 for(l=k; l>=i; l--)/*the reverse is for two-side lighting*/
1477 {
1478 glNormal3fv(leftNormal[l]);
1479 glVertex3fv(leftXYZ[l]);
1480
1481 }
1482 glNormal3fv(botMostNormal);
1483 glVertex3fv(botMostXYZ);
1484
1485 endtfan();
1486
1487 /*update i and botMostV for next loop
1488 */
1489 i = k+1;
1490
1491 botMostV[0] = u_left;
1492 botMostV[1] = left_val[k];
1493 botMostNormal = leftNormal[k];
1494 botMostXYZ = leftXYZ[k];
1495 }
1496 else /*left_val[i] > right_val[j])*/
1497 {
1498 bgntfan();
1499 glNormal3fv(leftNormal[i]);
1500 glVertex3fv(leftXYZ[i]);
1501
1502 glNormal3fv(botMostNormal);
1503 glVertex3fv(botMostXYZ);
1504
1505
1506 /*find the last k>=j such that
1507 *rightverts[k][0] < leftverts[i][0]
1508 */
1509 k=j;
1510 while(k< n_right)
1511 {
1512 if(right_val[k] >= left_val[i])
1513 break;
1514 glNormal3fv(rightNormal[k]);
1515 glVertex3fv(rightXYZ[k]);
1516
1517 k++;
1518 }
1519 endtfan();
1520
1521 /*update j and botMostV for next loop
1522 */
1523 j=k;
1524 botMostV[0] = u_right;
1525 botMostV[1] = right_val[j-1];
1526
1527 botMostNormal = rightNormal[j-1];
1528 botMostXYZ = rightXYZ[j-1];
1529 }
1530 }
1531 }
1532 //clean up
1533 free(leftXYZ);
1534 free(rightXYZ);
1535 free(leftNormal);
1536 free(rightNormal);
1537 }
1538
1539 /*-----------------------begin evalMachine-------------------*/
inMap2fEM(int which,int k,REAL ulower,REAL uupper,int ustride,int uorder,REAL vlower,REAL vupper,int vstride,int vorder,REAL * ctlPoints)1540 void OpenGLSurfaceEvaluator::inMap2fEM(int which, int k,
1541 REAL ulower,
1542 REAL uupper,
1543 int ustride,
1544 int uorder,
1545 REAL vlower,
1546 REAL vupper,
1547 int vstride,
1548 int vorder,
1549 REAL *ctlPoints)
1550 {
1551 int i,j,x;
1552 surfEvalMachine *temp_em;
1553 switch(which){
1554 case 0: //vertex
1555 vertex_flag = 1;
1556 temp_em = &em_vertex;
1557 break;
1558 case 1: //normal
1559 normal_flag = 1;
1560 temp_em = &em_normal;
1561 break;
1562 case 2: //color
1563 color_flag = 1;
1564 temp_em = &em_color;
1565 break;
1566 default:
1567 texcoord_flag = 1;
1568 temp_em = &em_texcoord;
1569 break;
1570 }
1571
1572 REAL *data = temp_em->ctlPoints;
1573
1574 temp_em->uprime = -1;//initilized
1575 temp_em->vprime = -1;
1576
1577 temp_em->k = k;
1578 temp_em->u1 = ulower;
1579 temp_em->u2 = uupper;
1580 temp_em->ustride = ustride;
1581 temp_em->uorder = uorder;
1582 temp_em->v1 = vlower;
1583 temp_em->v2 = vupper;
1584 temp_em->vstride = vstride;
1585 temp_em->vorder = vorder;
1586
1587 /*copy the contrl points from ctlPoints to global_ev_ctlPoints*/
1588 for (i=0; i<uorder; i++) {
1589 for (j=0; j<vorder; j++) {
1590 for (x=0; x<k; x++) {
1591 data[x] = ctlPoints[x];
1592 }
1593 ctlPoints += vstride;
1594 data += k;
1595 }
1596 ctlPoints += ustride - vstride * vorder;
1597 }
1598 }
1599
inDoDomain2WithDerivsEM(surfEvalMachine * em,REAL u,REAL v,REAL * retPoint,REAL * retdu,REAL * retdv)1600 void OpenGLSurfaceEvaluator::inDoDomain2WithDerivsEM(surfEvalMachine *em, REAL u, REAL v,
1601 REAL *retPoint, REAL *retdu, REAL *retdv)
1602 {
1603 int j, row, col;
1604 REAL the_uprime;
1605 REAL the_vprime;
1606 REAL p;
1607 REAL pdv;
1608 REAL *data;
1609
1610 if((em->u2 == em->u1) || (em->v2 == em->v1))
1611 return;
1612 the_uprime = (u - em->u1) / (em->u2 - em->u1);
1613 the_vprime = (v - em->v1) / (em->v2 - em->v1);
1614
1615 /* Compute coefficients for values and derivs */
1616
1617 /* Use already cached values if possible */
1618 if(em->uprime != the_uprime) {
1619 inPreEvaluateWithDeriv(em->uorder, the_uprime, em->ucoeff, em->ucoeffDeriv);
1620 em->uprime = the_uprime;
1621 }
1622 if (em->vprime != the_vprime) {
1623 inPreEvaluateWithDeriv(em->vorder, the_vprime, em->vcoeff, em->vcoeffDeriv);
1624 em->vprime = the_vprime;
1625 }
1626
1627 for (j = 0; j < em->k; j++) {
1628 data=em->ctlPoints+j;
1629 retPoint[j] = retdu[j] = retdv[j] = 0.0;
1630 for (row = 0; row < em->uorder; row++) {
1631 /*
1632 ** Minor optimization.
1633 ** The col == 0 part of the loop is extracted so we don't
1634 ** have to initialize p and pdv to 0.
1635 */
1636 p = em->vcoeff[0] * (*data);
1637 pdv = em->vcoeffDeriv[0] * (*data);
1638 data += em->k;
1639 for (col = 1; col < em->vorder; col++) {
1640 /* Incrementally build up p, pdv value */
1641 p += em->vcoeff[col] * (*data);
1642 pdv += em->vcoeffDeriv[col] * (*data);
1643 data += em->k;
1644 }
1645 /* Use p, pdv value to incrementally add up r, du, dv */
1646 retPoint[j] += em->ucoeff[row] * p;
1647 retdu[j] += em->ucoeffDeriv[row] * p;
1648 retdv[j] += em->ucoeff[row] * pdv;
1649 }
1650 }
1651 }
1652
inDoDomain2EM(surfEvalMachine * em,REAL u,REAL v,REAL * retPoint)1653 void OpenGLSurfaceEvaluator::inDoDomain2EM(surfEvalMachine *em, REAL u, REAL v,
1654 REAL *retPoint)
1655 {
1656 int j, row, col;
1657 REAL the_uprime;
1658 REAL the_vprime;
1659 REAL p;
1660 REAL *data;
1661
1662 if((em->u2 == em->u1) || (em->v2 == em->v1))
1663 return;
1664 the_uprime = (u - em->u1) / (em->u2 - em->u1);
1665 the_vprime = (v - em->v1) / (em->v2 - em->v1);
1666
1667 /* Compute coefficients for values and derivs */
1668
1669 /* Use already cached values if possible */
1670 if(em->uprime != the_uprime) {
1671 inPreEvaluate(em->uorder, the_uprime, em->ucoeff);
1672 em->uprime = the_uprime;
1673 }
1674 if (em->vprime != the_vprime) {
1675 inPreEvaluate(em->vorder, the_vprime, em->vcoeff);
1676 em->vprime = the_vprime;
1677 }
1678
1679 for (j = 0; j < em->k; j++) {
1680 data=em->ctlPoints+j;
1681 retPoint[j] = 0.0;
1682 for (row = 0; row < em->uorder; row++) {
1683 /*
1684 ** Minor optimization.
1685 ** The col == 0 part of the loop is extracted so we don't
1686 ** have to initialize p and pdv to 0.
1687 */
1688 p = em->vcoeff[0] * (*data);
1689 data += em->k;
1690 for (col = 1; col < em->vorder; col++) {
1691 /* Incrementally build up p, pdv value */
1692 p += em->vcoeff[col] * (*data);
1693 data += em->k;
1694 }
1695 /* Use p, pdv value to incrementally add up r, du, dv */
1696 retPoint[j] += em->ucoeff[row] * p;
1697 }
1698 }
1699 }
1700
1701
inDoEvalCoord2EM(REAL u,REAL v)1702 void OpenGLSurfaceEvaluator::inDoEvalCoord2EM(REAL u, REAL v)
1703 {
1704 REAL temp_vertex[5];
1705 REAL temp_normal[3];
1706 REAL temp_color[4];
1707 REAL temp_texcoord[4];
1708
1709 if(texcoord_flag)
1710 {
1711 inDoDomain2EM(&em_texcoord, u,v, temp_texcoord);
1712 texcoordCallBack(temp_texcoord, userData);
1713 }
1714 if(color_flag)
1715 {
1716 inDoDomain2EM(&em_color, u,v, temp_color);
1717 colorCallBack(temp_color, userData);
1718 }
1719
1720 if(normal_flag) //there is a normla map
1721 {
1722 inDoDomain2EM(&em_normal, u,v, temp_normal);
1723 normalCallBack(temp_normal, userData);
1724
1725 if(vertex_flag)
1726 {
1727 inDoDomain2EM(&em_vertex, u,v,temp_vertex);
1728 if(em_vertex.k == 4)
1729 {
1730 temp_vertex[0] /= temp_vertex[3];
1731 temp_vertex[1] /= temp_vertex[3];
1732 temp_vertex[2] /= temp_vertex[3];
1733 }
1734 temp_vertex[3]=u;
1735 temp_vertex[4]=v;
1736 vertexCallBack(temp_vertex, userData);
1737 }
1738 }
1739 else if(auto_normal_flag) //no normal map but there is a normal callbackfunctin
1740 {
1741 REAL du[4];
1742 REAL dv[4];
1743
1744 /*compute homegeneous point and partial derivatives*/
1745 inDoDomain2WithDerivsEM(&em_vertex, u,v,temp_vertex,du,dv);
1746
1747 if(em_vertex.k ==4)
1748 inComputeFirstPartials(temp_vertex, du, dv);
1749
1750 #ifdef AVOID_ZERO_NORMAL
1751 if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
1752 {
1753
1754 REAL tempdu[4];
1755 REAL tempdata[4];
1756 REAL u1 = em_vertex.u1;
1757 REAL u2 = em_vertex.u2;
1758 if(u-MYDELTA*(u2-u1) < u1)
1759 u = u+ MYDELTA*(u2-u1);
1760 else
1761 u = u-MYDELTA*(u2-u1);
1762 inDoDomain2WithDerivsEM(&em_vertex,u,v, tempdata, tempdu, dv);
1763
1764 if(em_vertex.k ==4)
1765 inComputeFirstPartials(temp_vertex, du, dv);
1766 }
1767 else if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
1768 {
1769 REAL tempdv[4];
1770 REAL tempdata[4];
1771 REAL v1 = em_vertex.v1;
1772 REAL v2 = em_vertex.v2;
1773 if(v-MYDELTA*(v2-v1) < v1)
1774 v = v+ MYDELTA*(v2-v1);
1775 else
1776 v = v-MYDELTA*(v2-v1);
1777 inDoDomain2WithDerivsEM(&em_vertex,u,v, tempdata, du, tempdv);
1778
1779 if(em_vertex.k ==4)
1780 inComputeFirstPartials(temp_vertex, du, dv);
1781 }
1782 #endif
1783
1784 /*compute normal*/
1785 switch(em_vertex.k){
1786 case 3:
1787
1788 inComputeNormal2(du, dv, temp_normal);
1789 break;
1790 case 4:
1791
1792 // inComputeFirstPartials(temp_vertex, du, dv);
1793 inComputeNormal2(du, dv, temp_normal);
1794
1795 /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
1796 temp_vertex[0] /= temp_vertex[3];
1797 temp_vertex[1] /= temp_vertex[3];
1798 temp_vertex[2] /= temp_vertex[3];
1799 break;
1800 }
1801 normalCallBack(temp_normal, userData);
1802 temp_vertex[3] = u;
1803 temp_vertex[4] = v;
1804 vertexCallBack(temp_vertex, userData);
1805
1806 }/*end if auto_normal*/
1807 else //no normal map, and no normal callback function
1808 {
1809 if(vertex_flag)
1810 {
1811 inDoDomain2EM(&em_vertex, u,v,temp_vertex);
1812 if(em_vertex.k == 4)
1813 {
1814 temp_vertex[0] /= temp_vertex[3];
1815 temp_vertex[1] /= temp_vertex[3];
1816 temp_vertex[2] /= temp_vertex[3];
1817 }
1818 temp_vertex[3] = u;
1819 temp_vertex[4] = v;
1820 vertexCallBack(temp_vertex, userData);
1821 }
1822 }
1823 }
1824
1825
inBPMEvalEM(bezierPatchMesh * bpm)1826 void OpenGLSurfaceEvaluator::inBPMEvalEM(bezierPatchMesh* bpm)
1827 {
1828 int i,j,k;
1829 float u,v;
1830
1831 int ustride;
1832 int vstride;
1833
1834 #ifdef USE_LOD
1835 if(bpm->bpatch != NULL)
1836 {
1837 bezierPatch* p=bpm->bpatch;
1838 ustride = p->dimension * p->vorder;
1839 vstride = p->dimension;
1840
1841 glMap2f( (p->dimension == 3)? GL_MAP2_VERTEX_3 : GL_MAP2_VERTEX_4,
1842 p->umin,
1843 p->umax,
1844 ustride,
1845 p->uorder,
1846 p->vmin,
1847 p->vmax,
1848 vstride,
1849 p->vorder,
1850 p->ctlpoints);
1851
1852
1853 /*
1854 inMap2fEM(0, p->dimension,
1855 p->umin,
1856 p->umax,
1857 ustride,
1858 p->uorder,
1859 p->vmin,
1860 p->vmax,
1861 vstride,
1862 p->vorder,
1863 p->ctlpoints);
1864 */
1865 }
1866 #else
1867
1868 if(bpm->bpatch != NULL){
1869 bezierPatch* p = bpm->bpatch;
1870 ustride = p->dimension * p->vorder;
1871 vstride = p->dimension;
1872 inMap2fEM(0, p->dimension,
1873 p->umin,
1874 p->umax,
1875 ustride,
1876 p->uorder,
1877 p->vmin,
1878 p->vmax,
1879 vstride,
1880 p->vorder,
1881 p->ctlpoints);
1882 }
1883 if(bpm->bpatch_normal != NULL){
1884 bezierPatch* p = bpm->bpatch_normal;
1885 ustride = p->dimension * p->vorder;
1886 vstride = p->dimension;
1887 inMap2fEM(1, p->dimension,
1888 p->umin,
1889 p->umax,
1890 ustride,
1891 p->uorder,
1892 p->vmin,
1893 p->vmax,
1894 vstride,
1895 p->vorder,
1896 p->ctlpoints);
1897 }
1898 if(bpm->bpatch_color != NULL){
1899 bezierPatch* p = bpm->bpatch_color;
1900 ustride = p->dimension * p->vorder;
1901 vstride = p->dimension;
1902 inMap2fEM(2, p->dimension,
1903 p->umin,
1904 p->umax,
1905 ustride,
1906 p->uorder,
1907 p->vmin,
1908 p->vmax,
1909 vstride,
1910 p->vorder,
1911 p->ctlpoints);
1912 }
1913 if(bpm->bpatch_texcoord != NULL){
1914 bezierPatch* p = bpm->bpatch_texcoord;
1915 ustride = p->dimension * p->vorder;
1916 vstride = p->dimension;
1917 inMap2fEM(3, p->dimension,
1918 p->umin,
1919 p->umax,
1920 ustride,
1921 p->uorder,
1922 p->vmin,
1923 p->vmax,
1924 vstride,
1925 p->vorder,
1926 p->ctlpoints);
1927 }
1928 #endif
1929
1930
1931 k=0;
1932 for(i=0; i<bpm->index_length_array; i++)
1933 {
1934 #ifdef USE_LOD
1935 if(bpm->type_array[i] == GL_POLYGON) //a mesh
1936 {
1937 GLfloat *temp = bpm->UVarray+k;
1938 GLfloat u0 = temp[0];
1939 GLfloat v0 = temp[1];
1940 GLfloat u1 = temp[2];
1941 GLfloat v1 = temp[3];
1942 GLint nu = (GLint) ( temp[4]);
1943 GLint nv = (GLint) ( temp[5]);
1944 GLint umin = (GLint) ( temp[6]);
1945 GLint vmin = (GLint) ( temp[7]);
1946 GLint umax = (GLint) ( temp[8]);
1947 GLint vmax = (GLint) ( temp[9]);
1948
1949 glMapGrid2f(LOD_eval_level*nu, u0, u1, LOD_eval_level*nv, v0, v1);
1950 glEvalMesh2(GL_FILL, LOD_eval_level*umin, LOD_eval_level*umax, LOD_eval_level*vmin, LOD_eval_level*vmax);
1951 }
1952 else
1953 {
1954 LOD_eval(bpm->length_array[i], bpm->UVarray+k, bpm->type_array[i],
1955 0
1956 );
1957 }
1958 k+= 2*bpm->length_array[i];
1959
1960 #else //undef USE_LOD
1961
1962 #ifdef CRACK_TEST
1963 if( bpm->bpatch->umin == 2 && bpm->bpatch->umax == 3
1964 && bpm->bpatch->vmin ==2 && bpm->bpatch->vmax == 3)
1965 {
1966 REAL vertex[4];
1967 REAL normal[4];
1968 #ifdef DEBUG
1969 printf("***number ****1\n");
1970 #endif
1971
1972 beginCallBack(GL_QUAD_STRIP, NULL);
1973 inDoEvalCoord2EM(3.0, 3.0);
1974 inDoEvalCoord2EM(2.0, 3.0);
1975 inDoEvalCoord2EM(3.0, 2.7);
1976 inDoEvalCoord2EM(2.0, 2.7);
1977 inDoEvalCoord2EM(3.0, 2.0);
1978 inDoEvalCoord2EM(2.0, 2.0);
1979 endCallBack(NULL);
1980
1981 beginCallBack(GL_TRIANGLE_STRIP, NULL);
1982 inDoEvalCoord2EM(2.0, 3.0);
1983 inDoEvalCoord2EM(2.0, 2.0);
1984 inDoEvalCoord2EM(2.0, 2.7);
1985 endCallBack(NULL);
1986
1987 }
1988 if( bpm->bpatch->umin == 1 && bpm->bpatch->umax == 2
1989 && bpm->bpatch->vmin ==2 && bpm->bpatch->vmax == 3)
1990 {
1991 #ifdef DEBUG
1992 printf("***number 3\n");
1993 #endif
1994 beginCallBack(GL_QUAD_STRIP, NULL);
1995 inDoEvalCoord2EM(2.0, 3.0);
1996 inDoEvalCoord2EM(1.0, 3.0);
1997 inDoEvalCoord2EM(2.0, 2.3);
1998 inDoEvalCoord2EM(1.0, 2.3);
1999 inDoEvalCoord2EM(2.0, 2.0);
2000 inDoEvalCoord2EM(1.0, 2.0);
2001 endCallBack(NULL);
2002
2003 beginCallBack(GL_TRIANGLE_STRIP, NULL);
2004 inDoEvalCoord2EM(2.0, 2.3);
2005 inDoEvalCoord2EM(2.0, 2.0);
2006 inDoEvalCoord2EM(2.0, 3.0);
2007 endCallBack(NULL);
2008
2009 }
2010 return;
2011 #endif //CRACK_TEST
2012
2013 beginCallBack(bpm->type_array[i], userData);
2014
2015 for(j=0; j<bpm->length_array[i]; j++)
2016 {
2017 u = bpm->UVarray[k];
2018 v = bpm->UVarray[k+1];
2019 #ifdef USE_LOD
2020 LOD_EVAL_COORD(u,v);
2021 // glEvalCoord2f(u,v);
2022 #else
2023
2024 #ifdef GENERIC_TEST
2025 float temp_normal[3];
2026 float temp_vertex[3];
2027 if(temp_signal == 0)
2028 {
2029 gTessVertexSphere(u,v, temp_normal, temp_vertex);
2030 //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]);
2031 normalCallBack(temp_normal, userData);
2032 vertexCallBack(temp_vertex, userData);
2033 }
2034 else if(temp_signal == 1)
2035 {
2036 gTessVertexCyl(u,v, temp_normal, temp_vertex);
2037 //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]);
2038 normalCallBack(temp_normal, userData);
2039 vertexCallBack(temp_vertex, userData);
2040 }
2041 else
2042 #endif //GENERIC_TEST
2043
2044 inDoEvalCoord2EM(u,v);
2045
2046 #endif //USE_LOD
2047
2048 k += 2;
2049 }
2050 endCallBack(userData);
2051
2052 #endif //USE_LOD
2053 }
2054 }
2055
inBPMListEvalEM(bezierPatchMesh * list)2056 void OpenGLSurfaceEvaluator::inBPMListEvalEM(bezierPatchMesh* list)
2057 {
2058 bezierPatchMesh* temp;
2059 for(temp = list; temp != NULL; temp = temp->next)
2060 {
2061 inBPMEvalEM(temp);
2062 }
2063 }
2064
2065