FreeWRL/FreeX3D  3.0.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 
65 static 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 
93 void 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);*/
108 glBegin(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();
137 glEnd();
138  }
139 }
140 
141 void 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
184 extern float xmin, xmax, ymin, ymax, zmin, zmax; /*bounding box*/
185 extern int temp_signal;
186 
187 static 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 
211 static 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 
239 void OpenGLSurfaceEvaluator::inBPMListEval(bezierPatchMesh* list)
240 {
241  bezierPatchMesh* temp;
242  for(temp = list; temp != NULL; temp = temp->next)
243  {
244  inBPMEval(temp);
245  }
246 }
247 
248 void 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
272 if( global_ev_u1 ==2 && global_ev_u2 == 3
273  && global_ev_v1 ==2 && global_ev_v2 == 3)
274 {
275 REAL vertex[4];
276 REAL normal[4];
277 #ifdef DEBUG
278 printf("***number 1\n");
279 #endif
280 
281 beginCallBack(GL_QUAD_STRIP, NULL);
282 inEvalCoord2f(3.0, 3.0);
283 inEvalCoord2f(2.0, 3.0);
284 inEvalCoord2f(3.0, 2.7);
285 inEvalCoord2f(2.0, 2.7);
286 inEvalCoord2f(3.0, 2.0);
287 inEvalCoord2f(2.0, 2.0);
288 endCallBack(NULL);
289 
290 
291 beginCallBack(GL_TRIANGLE_STRIP, NULL);
292 inEvalCoord2f(2.0, 3.0);
293 inEvalCoord2f(2.0, 2.0);
294 inEvalCoord2f(2.0, 2.7);
295 endCallBack(NULL);
296 
297 }
298 
299 /*
300 if( global_ev_u1 ==2 && global_ev_u2 == 3
301  && global_ev_v1 ==1 && global_ev_v2 == 2)
302 {
303 #ifdef DEBUG
304 printf("***number 2\n");
305 #endif
306 beginCallBack(GL_QUAD_STRIP);
307 inEvalCoord2f(2.0, 2.0);
308 inEvalCoord2f(2.0, 1.0);
309 inEvalCoord2f(3.0, 2.0);
310 inEvalCoord2f(3.0, 1.0);
311 endCallBack();
312 }
313 */
314 if( global_ev_u1 ==1 && global_ev_u2 == 2
315  && global_ev_v1 ==2 && global_ev_v2 == 3)
316 {
317 #ifdef DEBUG
318 printf("***number 3\n");
319 #endif
320 beginCallBack(GL_QUAD_STRIP, NULL);
321 inEvalCoord2f(2.0, 3.0);
322 inEvalCoord2f(1.0, 3.0);
323 inEvalCoord2f(2.0, 2.3);
324 inEvalCoord2f(1.0, 2.3);
325 inEvalCoord2f(2.0, 2.0);
326 inEvalCoord2f(1.0, 2.0);
327 endCallBack(NULL);
328 
329 beginCallBack(GL_TRIANGLE_STRIP, NULL);
330 inEvalCoord2f(2.0, 2.3);
331 inEvalCoord2f(2.0, 2.0);
332 inEvalCoord2f(2.0, 3.0);
333 endCallBack(NULL);
334 
335 }
336 return;
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 
363 void 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 
376 void 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  */
390 void 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 
401 void 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 
445 void 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  */
502 void 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  */
519 void 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  */
542 void 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  */
622 void 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  */
685 void 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  */
750 void 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 
810 void 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 
839 void 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 
869 void 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 
904 void 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  */
950 void 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  */
1023 void 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  */
1067 void 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 
1126 void 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];
1131 inPreEvaluateBV_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 
1145 void 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];
1150 inPreEvaluateBU_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  */
1167 void 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  */
1367 void 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-------------------*/
1562 void 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 
1622 void 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 
1675 void 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 
1724 void 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 
1848 void 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
1985 if( bpm->bpatch->umin == 2 && bpm->bpatch->umax == 3
1986  && bpm->bpatch->vmin ==2 && bpm->bpatch->vmax == 3)
1987 {
1988 REAL vertex[4];
1989 REAL normal[4];
1990 #ifdef DEBUG
1991 printf("***number ****1\n");
1992 #endif
1993 
1994 beginCallBack(GL_QUAD_STRIP, NULL);
1995 inDoEvalCoord2EM(3.0, 3.0);
1996 inDoEvalCoord2EM(2.0, 3.0);
1997 inDoEvalCoord2EM(3.0, 2.7);
1998 inDoEvalCoord2EM(2.0, 2.7);
1999 inDoEvalCoord2EM(3.0, 2.0);
2000 inDoEvalCoord2EM(2.0, 2.0);
2001 endCallBack(NULL);
2002 
2003 beginCallBack(GL_TRIANGLE_STRIP, NULL);
2004 inDoEvalCoord2EM(2.0, 3.0);
2005 inDoEvalCoord2EM(2.0, 2.0);
2006 inDoEvalCoord2EM(2.0, 2.7);
2007 endCallBack(NULL);
2008 
2009 }
2010 if( bpm->bpatch->umin == 1 && bpm->bpatch->umax == 2
2011  && bpm->bpatch->vmin ==2 && bpm->bpatch->vmax == 3)
2012 {
2013 #ifdef DEBUG
2014 printf("***number 3\n");
2015 #endif
2016 beginCallBack(GL_QUAD_STRIP, NULL);
2017 inDoEvalCoord2EM(2.0, 3.0);
2018 inDoEvalCoord2EM(1.0, 3.0);
2019 inDoEvalCoord2EM(2.0, 2.3);
2020 inDoEvalCoord2EM(1.0, 2.3);
2021 inDoEvalCoord2EM(2.0, 2.0);
2022 inDoEvalCoord2EM(1.0, 2.0);
2023 endCallBack(NULL);
2024 
2025 beginCallBack(GL_TRIANGLE_STRIP, NULL);
2026 inDoEvalCoord2EM(2.0, 2.3);
2027 inDoEvalCoord2EM(2.0, 2.0);
2028 inDoEvalCoord2EM(2.0, 3.0);
2029 endCallBack(NULL);
2030 
2031 }
2032 return;
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 
2078 void OpenGLSurfaceEvaluator::inBPMListEvalEM(bezierPatchMesh* list)
2079 {
2080  bezierPatchMesh* temp;
2081  for(temp = list; temp != NULL; temp = temp->next)
2082  {
2083  inBPMEvalEM(temp);
2084  }
2085 }
2086