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