FreeWRL/FreeX3D  3.0.0
glsurfeval.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  * glsurfeval.c++
37  *
38  */
39 
40 /* Polynomial Evaluator Interface */
41 #include "gluos.h"
42 #include <stdio.h>
43 #include "glimports.h"
44 #include "glrenderer.h"
45 #include "glsurfeval.h"
46 #include "nurbsconsts.h"
47 #include "bezierPatchMesh.h"
48 
49 
50 //extern int surfcount;
51 //int surfcount=0;
52 
53 /*#define USE_INTERNAL_EVAL*/ //use internal evaluator
54 
55 /*whether do evaluation or not*/
56 /*#define NO_EVALUATION*/
57 
58 //#define USE_LOD //for LOD test, have to turn on USE_LOD in insurfeval.c++ too
59 
60 /*for statistics*/
61 //#define STATISTICS
62 #ifdef STATISTICS
63 static int STAT_num_of_triangles=0;
64 static int STAT_num_of_eval_vertices=0;
65 static int STAT_num_of_quad_strips=0;
66 #endif
67 
68 /*for output triangles*/
69 /*#define OUTPUT_TRIANGLES*/
70 
71 
72 /*#define FOR_CHRIS*/
73 #ifdef FOR_CHRIS
74 extern "C" { void evalUStripExt(int n_upper, REAL v_upper, REAL* upper_val,
75  int n_lower, REAL v_lower, REAL* lower_val);}
76 
77 extern "C" { void evalVStripExt(int n_left, REAL u_left, REAL* left_val,
78  int n_right, REAL u_right, REAL* right_val);
79  }
80 #endif
81 
82 
83 /**************begin for LOD_eval_list***********/
84 void OpenGLSurfaceEvaluator::LOD_eval_list(int level)
85 {
86  if(level == 0)
87  LOD_eval_level = 1;
88  else if(level == 1)
89  LOD_eval_level = 2;
90  else if(level == 2)
91  LOD_eval_level = 4;
92  else
93  LOD_eval_level = 8;
94 
95  inBPMListEvalEM(global_bpm);
96 }
97 
98 
99 OpenGLSurfaceEvaluator::OpenGLSurfaceEvaluator()
100 {
101  int i;
102 
103  for (i=0; i<VERTEX_CACHE_SIZE; i++) {
104  vertexCache[i] = new StoredVertex;
105  }
106  tmeshing = 0;
107  which = 0;
108  vcount = 0;
109 
110  global_uorder = 0;
111  global_vorder = 0;
112  global_uprime = -1.0;
113  global_vprime = -1.0;
114  global_vprime_BV = -1.0;
115  global_uprime_BU = -1.0;
116  global_uorder_BU = 0;
117  global_vorder_BU = 0;
118  global_uorder_BV = 0;
119  global_vorder_BV = 0;
120  global_baseData = NULL;
121 
122  global_bpm = NULL;
123  output_triangles = 0; //don't output triangles by default
124 
125  //no default callback functions
126  beginCallBackN = NULL;
127  endCallBackN = NULL;
128  vertexCallBackN = NULL;
129  normalCallBackN = NULL;
130  colorCallBackN = NULL;
131  texcoordCallBackN = NULL;
132  beginCallBackData = NULL;
133  endCallBackData = NULL;
134  vertexCallBackData = NULL;
135  normalCallBackData = NULL;
136  colorCallBackData = NULL;
137  texcoordCallBackData = NULL;
138 
139  userData = NULL;
140 
141  auto_normal_flag = 0;
142  callback_auto_normal = 0; //default of GLU_CALLBACK_AUTO_NORMAL is 0
143  vertex_flag = 0;
144  normal_flag = 0;
145  color_flag = 0;
146  texcoord_flag = 0;
147 
148  em_vertex.uprime = -1.0;
149  em_vertex.vprime = -1.0;
150  em_normal.uprime = -1.0;
151  em_normal.vprime = -1.0;
152  em_color.uprime = -1.0;
153  em_color.vprime = -1.0;
154  em_texcoord.uprime = -1.0;
155  em_texcoord.vprime = -1.0;
156 
157 #ifdef USE_LOD
158  LOD_eval_level = 1;
159 #endif
160 }
161 
162 OpenGLSurfaceEvaluator::~OpenGLSurfaceEvaluator()
163 {
164  for (int ii= 0; ii< VERTEX_CACHE_SIZE; ii++) {
165  delete vertexCache[ii];
166  vertexCache[ii]= 0;
167  }
168 }
169 
170 /*---------------------------------------------------------------------------
171  * disable - turn off a map
172  *---------------------------------------------------------------------------
173  */
174 void
175 OpenGLSurfaceEvaluator::disable(long type)
176 {
177  glDisable((GLenum) type);
178 }
179 
180 /*---------------------------------------------------------------------------
181  * enable - turn on a map
182  *---------------------------------------------------------------------------
183  */
184 void
185 OpenGLSurfaceEvaluator::enable(long type)
186 {
187  glEnable((GLenum) type);
188 }
189 
190 /*-------------------------------------------------------------------------
191  * mapgrid2f - define a lattice of points with origin and offset
192  *-------------------------------------------------------------------------
193  */
194 void
195 OpenGLSurfaceEvaluator::mapgrid2f(long nu, REAL u0, REAL u1, long nv, REAL v0, REAL v1)
196 {
197 #ifdef USE_INTERNAL_EVAL
198  inMapGrid2f((int) nu, (REAL) u0, (REAL) u1, (int) nv,
199  (REAL) v0, (REAL) v1);
200 #else
201 
202  if(output_triangles)
203  {
204  global_grid_u0 = u0;
205  global_grid_u1 = u1;
206  global_grid_nu = nu;
207  global_grid_v0 = v0;
208  global_grid_v1 = v1;
209  global_grid_nv = nv;
210  }
211 #ifdef HAVE_GL_H
212  else
213  glMapGrid2d((GLint) nu, (GLdouble) u0, (GLdouble) u1, (GLint) nv,
214  (GLdouble) v0, (GLdouble) v1);
215 #endif
216 #endif
217 }
218 
219 void
220 OpenGLSurfaceEvaluator::polymode(long style)
221 {
222 #ifdef HAVE_GL_H
223  if(! output_triangles)
224  {
225  switch(style) {
226  default:
227  case N_MESHFILL:
228 
229  glPolygonMode((GLenum) GL_FRONT_AND_BACK, (GLenum) GL_FILL);
230  break;
231  case N_MESHLINE:
232  glPolygonMode((GLenum) GL_FRONT_AND_BACK, (GLenum) GL_LINE);
233  break;
234  case N_MESHPOINT:
235  glPolygonMode((GLenum) GL_FRONT_AND_BACK, (GLenum) GL_POINT);
236  break;
237  }
238  }
239 #endif
240 }
241 
242 void
243 OpenGLSurfaceEvaluator::bgnline(void)
244 {
245  if(output_triangles)
246  bezierPatchMeshBeginStrip(global_bpm, GL_LINE_STRIP);
247 #ifdef HAVE_GL_H
248  else
249  glBegin((GLenum) GL_LINE_STRIP);
250 #endif
251 }
252 
253 void
254 OpenGLSurfaceEvaluator::endline(void)
255 {
256  if(output_triangles)
257  bezierPatchMeshEndStrip(global_bpm);
258 #ifdef HAVE_GL_H
259  else
260  glEnd();
261 #endif
262 }
263 
264 void
265 OpenGLSurfaceEvaluator::range2f(long type, REAL *from, REAL *to)
266 {
267 }
268 
269 void
270 OpenGLSurfaceEvaluator::domain2f(REAL ulo, REAL uhi, REAL vlo, REAL vhi)
271 {
272 }
273 
274 void
275 OpenGLSurfaceEvaluator::bgnclosedline(void)
276 {
277  if(output_triangles)
278  bezierPatchMeshBeginStrip(global_bpm, GL_LINE_LOOP);
279 #ifdef HAVE_GL_H
280  else
281  glBegin((GLenum) GL_LINE_LOOP);
282 #endif
283 }
284 
285 void
286 OpenGLSurfaceEvaluator::endclosedline(void)
287 {
288  if(output_triangles)
289  bezierPatchMeshEndStrip(global_bpm);
290 #ifdef HAVE_GL_H
291  else
292  glEnd();
293 #endif
294 }
295 
296 
297 
298 
299 
300 void
301 OpenGLSurfaceEvaluator::bgntmesh(void)
302 {
303 
304  tmeshing = 1;
305  which = 0;
306  vcount = 0;
307 
308  if(output_triangles)
309  bezierPatchMeshBeginStrip(global_bpm, GL_TRIANGLES);
310 #ifdef HAVE_GL_H
311  else
312  glBegin((GLenum) GL_TRIANGLES);
313 #endif
314 
315 }
316 
317 void
318 OpenGLSurfaceEvaluator::swaptmesh(void)
319 {
320  which = 1 - which;
321 
322 }
323 
324 void
325 OpenGLSurfaceEvaluator::endtmesh(void)
326 {
327  tmeshing = 0;
328 
329 
330  if(output_triangles)
331  bezierPatchMeshEndStrip(global_bpm);
332 #ifdef HAVE_GL_H
333  else
334  glEnd();
335 #endif
336 }
337 
338 void
339 OpenGLSurfaceEvaluator::bgntfan(void)
340 {
341 
342  if(output_triangles)
343  bezierPatchMeshBeginStrip(global_bpm, GL_TRIANGLE_FAN);
344 #ifdef HAVE_GL_H
345  else
346  glBegin((GLenum) GL_TRIANGLE_FAN);
347 #endif
348 
349 }
350 void
351 OpenGLSurfaceEvaluator::endtfan(void)
352 {
353  if(output_triangles)
354  bezierPatchMeshEndStrip(global_bpm);
355 #ifdef HAVE_GL_H
356  else
357  glEnd();
358 #endif
359 }
360 
361 void
362 OpenGLSurfaceEvaluator::evalUStrip(int n_upper, REAL v_upper, REAL* upper_val, int n_lower, REAL v_lower, REAL* lower_val)
363 {
364 #ifdef USE_INTERNAL_EVAL
365  inEvalUStrip(n_upper, v_upper, upper_val,
366  n_lower, v_lower, lower_val);
367 #else
368 
369 #ifdef FOR_CHRIS
370  evalUStripExt(n_upper, v_upper, upper_val,
371  n_lower, v_lower, lower_val);
372  return;
373 
374 #endif
375  int i,j,k,l;
376  REAL leftMostV[2];
377 
378  /*
379  *the algorithm works by scanning from left to right.
380  *leftMostV: the left most of the remaining verteces (on both upper and lower).
381  * it could an element of upperVerts or lowerVerts.
382  *i: upperVerts[i] is the first vertex to the right of leftMostV on upper line
383  *j: lowerVerts[j] is the first vertex to the right of leftMostV on lower line
384  */
385 
386  /*initialize i,j,and leftMostV
387  */
388  if(upper_val[0] <= lower_val[0])
389  {
390  i=1;
391  j=0;
392 
393  leftMostV[0] = upper_val[0];
394  leftMostV[1] = v_upper;
395  }
396  else
397  {
398  i=0;
399  j=1;
400 
401  leftMostV[0] = lower_val[0];
402  leftMostV[1] = v_lower;
403 
404  }
405 
406  /*the main loop.
407  *the invariance is that:
408  *at the beginning of each loop, the meaning of i,j,and leftMostV are
409  *maintained
410  */
411  while(1)
412  {
413  if(i >= n_upper) /*case1: no more in upper*/
414  {
415  if(j<n_lower-1) /*at least two vertices in lower*/
416  {
417  bgntfan();
418  coord2f(leftMostV[0], leftMostV[1]);
419 // glNormal3fv(leftMostNormal);
420 // glVertex3fv(leftMostXYZ);
421 
422  while(j<n_lower){
423  coord2f(lower_val[j], v_lower);
424 // glNormal3fv(lowerNormal[j]);
425 // glVertex3fv(lowerXYZ[j]);
426  j++;
427 
428  }
429  endtfan();
430  }
431  break; /*exit the main loop*/
432  }
433  else if(j>= n_lower) /*case2: no more in lower*/
434  {
435  if(i<n_upper-1) /*at least two vertices in upper*/
436  {
437  bgntfan();
438  coord2f(leftMostV[0], leftMostV[1]);
439 // glNormal3fv(leftMostNormal);
440 // glVertex3fv(leftMostXYZ);
441 
442  for(k=n_upper-1; k>=i; k--) /*reverse order for two-side lighting*/
443  {
444  coord2f(upper_val[k], v_upper);
445 // glNormal3fv(upperNormal[k]);
446 // glVertex3fv(upperXYZ[k]);
447  }
448 
449  endtfan();
450  }
451  break; /*exit the main loop*/
452  }
453  else /* case3: neither is empty, plus the leftMostV, there is at least one triangle to output*/
454  {
455  if(upper_val[i] <= lower_val[j])
456  {
457  bgntfan();
458  coord2f(lower_val[j], v_lower);
459 // glNormal3fv(lowerNormal[j]);
460 // glVertex3fv(lowerXYZ[j]);
461 
462  /*find the last k>=i such that
463  *upperverts[k][0] <= lowerverts[j][0]
464  */
465  k=i;
466 
467  while(k<n_upper)
468  {
469  if(upper_val[k] > lower_val[j])
470  break;
471  k++;
472 
473  }
474  k--;
475 
476 
477  for(l=k; l>=i; l--)/*the reverse is for two-side lighting*/
478  {
479  coord2f(upper_val[l], v_upper);
480 // glNormal3fv(upperNormal[l]);
481 // glVertex3fv(upperXYZ[l]);
482 
483  }
484  coord2f(leftMostV[0], leftMostV[1]);
485 // glNormal3fv(leftMostNormal);
486 // glVertex3fv(leftMostXYZ);
487 
488  endtfan();
489 
490  /*update i and leftMostV for next loop
491  */
492  i = k+1;
493 
494  leftMostV[0] = upper_val[k];
495  leftMostV[1] = v_upper;
496 // leftMostNormal = upperNormal[k];
497 // leftMostXYZ = upperXYZ[k];
498  }
499  else /*upperVerts[i][0] > lowerVerts[j][0]*/
500  {
501  bgntfan();
502  coord2f(upper_val[i], v_upper);
503 // glNormal3fv(upperNormal[i]);
504 // glVertex3fv(upperXYZ[i]);
505 
506  coord2f(leftMostV[0], leftMostV[1]);
507 // glNormal3fv(leftMostNormal);
508 // glVertex3fv(leftMostXYZ);
509 
510 
511  /*find the last k>=j such that
512  *lowerverts[k][0] < upperverts[i][0]
513  */
514  k=j;
515  while(k< n_lower)
516  {
517  if(lower_val[k] >= upper_val[i])
518  break;
519  coord2f(lower_val[k], v_lower);
520 // glNormal3fv(lowerNormal[k]);
521 // glVertex3fv(lowerXYZ[k]);
522 
523  k++;
524  }
525  endtfan();
526 
527  /*update j and leftMostV for next loop
528  */
529  j=k;
530  leftMostV[0] = lower_val[j-1];
531  leftMostV[1] = v_lower;
532 
533 // leftMostNormal = lowerNormal[j-1];
534 // leftMostXYZ = lowerXYZ[j-1];
535  }
536  }
537  }
538  //clean up
539 // free(upperXYZ);
540 // free(lowerXYZ);
541 // free(upperNormal);
542 // free(lowerNormal);
543 #endif
544 
545 }
546 
547 
548 void
549 OpenGLSurfaceEvaluator::evalVStrip(int n_left, REAL u_left, REAL* left_val, int n_right, REAL u_right, REAL* right_val)
550 {
551 #ifdef USE_INTERNAL_EVAL
552  inEvalVStrip(n_left, u_left, left_val,
553  n_right, u_right, right_val);
554 #else
555 
556 #ifdef FOR_CHRIS
557  evalVStripExt(n_left, u_left, left_val,
558  n_right, u_right, right_val);
559  return;
560 
561 #endif
562 
563  int i,j,k,l;
564  REAL botMostV[2];
565  /*
566  *the algorithm works by scanning from bot to top.
567  *botMostV: the bot most of the remaining verteces (on both left and right).
568  * it could an element of leftVerts or rightVerts.
569  *i: leftVerts[i] is the first vertex to the top of botMostV on left line
570  *j: rightVerts[j] is the first vertex to the top of botMostV on rightline
571  */
572 
573  /*initialize i,j,and botMostV
574  */
575  if(left_val[0] <= right_val[0])
576  {
577  i=1;
578  j=0;
579 
580  botMostV[0] = u_left;
581  botMostV[1] = left_val[0];
582  }
583  else
584  {
585  i=0;
586  j=1;
587 
588  botMostV[0] = u_right;
589  botMostV[1] = right_val[0];
590  }
591 
592  /*the main loop.
593  *the invariance is that:
594  *at the beginning of each loop, the meaning of i,j,and botMostV are
595  *maintained
596  */
597  while(1)
598  {
599  if(i >= n_left) /*case1: no more in left*/
600  {
601  if(j<n_right-1) /*at least two vertices in right*/
602  {
603  bgntfan();
604  coord2f(botMostV[0], botMostV[1]);
605  while(j<n_right){
606  coord2f(u_right, right_val[j]);
607 // glNormal3fv(rightNormal[j]);
608 // glVertex3fv(rightXYZ[j]);
609  j++;
610 
611  }
612  endtfan();
613  }
614  break; /*exit the main loop*/
615  }
616  else if(j>= n_right) /*case2: no more in right*/
617  {
618  if(i<n_left-1) /*at least two vertices in left*/
619  {
620  bgntfan();
621  coord2f(botMostV[0], botMostV[1]);
622 // glNormal3fv(botMostNormal);
623 // glVertex3fv(botMostXYZ);
624 
625  for(k=n_left-1; k>=i; k--) /*reverse order for two-side lighting*/
626  {
627  coord2f(u_left, left_val[k]);
628 // glNormal3fv(leftNormal[k]);
629 // glVertex3fv(leftXYZ[k]);
630  }
631 
632  endtfan();
633  }
634  break; /*exit the main loop*/
635  }
636  else /* case3: neither is empty, plus the botMostV, there is at least one triangle to output*/
637  {
638  if(left_val[i] <= right_val[j])
639  {
640  bgntfan();
641  coord2f(u_right, right_val[j]);
642 // glNormal3fv(rightNormal[j]);
643 // glVertex3fv(rightXYZ[j]);
644 
645  /*find the last k>=i such that
646  *leftverts[k][0] <= rightverts[j][0]
647  */
648  k=i;
649 
650  while(k<n_left)
651  {
652  if(left_val[k] > right_val[j])
653  break;
654  k++;
655 
656  }
657  k--;
658 
659 
660  for(l=k; l>=i; l--)/*the reverse is for two-side lighting*/
661  {
662  coord2f(u_left, left_val[l]);
663 // glNormal3fv(leftNormal[l]);
664 // glVertex3fv(leftXYZ[l]);
665 
666  }
667  coord2f(botMostV[0], botMostV[1]);
668 // glNormal3fv(botMostNormal);
669 // glVertex3fv(botMostXYZ);
670 
671  endtfan();
672 
673  /*update i and botMostV for next loop
674  */
675  i = k+1;
676 
677  botMostV[0] = u_left;
678  botMostV[1] = left_val[k];
679 // botMostNormal = leftNormal[k];
680 // botMostXYZ = leftXYZ[k];
681  }
682  else /*left_val[i] > right_val[j])*/
683  {
684  bgntfan();
685  coord2f(u_left, left_val[i]);
686 // glNormal3fv(leftNormal[i]);
687 // glVertex3fv(leftXYZ[i]);
688 
689  coord2f(botMostV[0], botMostV[1]);
690 // glNormal3fv(botMostNormal);
691 // glVertex3fv(botMostXYZ);
692 
693 
694  /*find the last k>=j such that
695  *rightverts[k][0] < leftverts[i][0]
696  */
697  k=j;
698  while(k< n_right)
699  {
700  if(right_val[k] >= left_val[i])
701  break;
702  coord2f(u_right, right_val[k]);
703 // glNormal3fv(rightNormal[k]);
704 // glVertex3fv(rightXYZ[k]);
705 
706  k++;
707  }
708  endtfan();
709 
710  /*update j and botMostV for next loop
711  */
712  j=k;
713  botMostV[0] = u_right;
714  botMostV[1] = right_val[j-1];
715 
716 // botMostNormal = rightNormal[j-1];
717 // botMostXYZ = rightXYZ[j-1];
718  }
719  }
720  }
721  //clean up
722 // free(leftXYZ);
723 // free(leftNormal);
724 // free(rightXYZ);
725 // free(rightNormal);
726 #endif
727 }
728 
729 
730 void
731 OpenGLSurfaceEvaluator::bgnqstrip(void)
732 {
733  if(output_triangles)
734  bezierPatchMeshBeginStrip(global_bpm, GL_QUAD_STRIP);
735 #ifdef HAVE_GL_H
736  else
737  glBegin((GLenum) GL_QUAD_STRIP);
738 #endif
739 
740 #ifdef STATISTICS
741  STAT_num_of_quad_strips++;
742 #endif
743 }
744 
745 void
746 OpenGLSurfaceEvaluator::endqstrip(void)
747 {
748  if(output_triangles)
749  bezierPatchMeshEndStrip(global_bpm);
750 #ifdef HAVE_GL_H
751  else
752  glEnd();
753 #endif
754 
755 }
756 
757 /*-------------------------------------------------------------------------
758  * bgnmap2f - preamble to surface definition and evaluations
759  *-------------------------------------------------------------------------
760  */
761 void
762 OpenGLSurfaceEvaluator::bgnmap2f(long)
763 {
764  if(output_triangles)
765  {
766  /*deallocate the space which may has been
767  *allocated by global_bpm previously
768  */
769  if(global_bpm != NULL) {
770  bezierPatchMeshListDelete(global_bpm);
771  global_bpm = NULL;
772  }
773 
774 
775  /*
776  auto_normal_flag = 1; //always output normal in callback mode.
777  //we could have used the following code,
778  //but Inspector doesn't have gl context
779  //before it calls tessellator.
780  //this way is temporary.
781  */
782  //NEWCALLBACK
783  //if one of the two normal callback functions are set,
784  //then set
785  if(normalCallBackN != NULL ||
786  normalCallBackData != NULL)
787  auto_normal_flag = 1;
788  else
789  auto_normal_flag = 0;
790 
791  //initialize so that no maps initially
792  vertex_flag = 0;
793  normal_flag = 0;
794  color_flag = 0;
795  texcoord_flag = 0;
796 
797  /*
798  if(glIsEnabled(GL_AUTO_NORMAL) == GL_TRUE)
799  auto_normal_flag = 1;
800  else if (callback_auto_normal == 1)
801  auto_normal_flag = 1;
802  else
803  auto_normal_flag = 0;
804  */
805 #ifdef HAVE_GL_H
806  glPushAttrib((GLbitfield) GL_EVAL_BIT);
807 #endif
808 
809  }
810 #ifdef HAVE_GL_H
811  else
812  {
813  glPushAttrib((GLbitfield) GL_EVAL_BIT);
814 
815  /*to avoid side effect, we restor the opengl state for GL_POLYGON_MODE
816  */
817  glGetIntegerv(GL_POLYGON_MODE, gl_polygon_mode);
818  }
819 #endif
820 
821 }
822 
823 /*-------------------------------------------------------------------------
824  * endmap2f - postamble to a map
825  *-------------------------------------------------------------------------
826  */
827 void
828 OpenGLSurfaceEvaluator::endmap2f(void)
829 {
830 
831  if(output_triangles)
832  {
833  //bezierPatchMeshListDelDeg(global_bpm);
834 
835  // bezierPatchMeshListEval(global_bpm);
836 
837  //surfcount++;
838  //printf("surfcount=%i\n", surfcount);
839  //if(surfcount == 8) exit(0);
840 
841  inBPMListEvalEM(global_bpm);
842 
843 
844 
845 /*
846  global_bpm = bezierPatchMeshListReverse(global_bpm);
847  {
848  float *vertex_array;
849  float *normal_array;
850  int *length_array;
851  int *type_array;
852  int num_strips;
853  bezierPatchMeshListCollect(global_bpm, &vertex_array, &normal_array, &length_array, &type_array, &num_strips);
854  drawStrips(vertex_array, normal_array, length_array, type_array, num_strips);
855  free(vertex_array);
856  free(normal_array);
857  free(length_array);
858  free(type_array);
859  }
860 */
861 
862  //bezierPatchMeshListPrint(global_bpm);
863  //bezierPatchMeshListDraw(global_bpm);
864 
865 // printf("num triangles=%i\n", bezierPatchMeshListNumTriangles(global_bpm));
866 
867 #ifdef USE_LOD
868 #else
869  bezierPatchMeshListDelete(global_bpm);
870  global_bpm = NULL;
871 #endif
872 #ifdef HAVE_GL_H
873  glPopAttrib();
874 #endif
875  }
876 #ifdef HAVE_GL_H
877 else
878  {
879 #ifndef USE_LOD
880  glPopAttrib();
881 #endif
882 
883 #ifdef STATISTICS
884  fprintf(stderr, "num_vertices=%i,num_triangles=%i,num_quads_strips=%i\n", STAT_num_of_eval_vertices,STAT_num_of_triangles,STAT_num_of_quad_strips);
885 #endif
886 
887  /*to restore the gl_polygon_mode
888  */
889 #ifndef USE_LOD
890  glPolygonMode( GL_FRONT, (GLenum) gl_polygon_mode[0]);
891  glPolygonMode( GL_BACK, (GLenum) gl_polygon_mode[1]);
892 #endif
893 }
894 #endif
895 
896 }
897 
898 /*-------------------------------------------------------------------------
899  * map2f - pass a desription of a surface map
900  *-------------------------------------------------------------------------
901  */
902 void
903 OpenGLSurfaceEvaluator::map2f(
904  long _type,
905  REAL _ulower, /* u lower domain coord */
906  REAL _uupper, /* u upper domain coord */
907  long _ustride, /* interpoint distance */
908  long _uorder, /* parametric order */
909  REAL _vlower, /* v lower domain coord */
910  REAL _vupper, /* v upper domain coord */
911  long _vstride, /* interpoint distance */
912  long _vorder, /* parametric order */
913  REAL *pts) /* control points */
914 {
915 #ifdef USE_INTERNAL_EVAL
916  inMap2f((int) _type, (REAL) _ulower, (REAL) _uupper,
917  (int) _ustride, (int) _uorder, (REAL) _vlower,
918  (REAL) _vupper, (int) _vstride, (int) _vorder,
919  (REAL *) pts);
920 #else
921 
922 
923 
924  if(output_triangles)
925  {
926  if(global_bpm == NULL)
927  global_bpm = bezierPatchMeshMake2(10,10);
928  if(
929  (global_bpm->bpatch == NULL &&
930  (_type == GL_MAP2_VERTEX_3 || _type == GL_MAP2_VERTEX_4))
931  ||
932  (global_bpm->bpatch_normal == NULL &&
933  (_type == GL_MAP2_NORMAL))
934  ||
935  (global_bpm->bpatch_color == NULL &&
936  (_type == GL_MAP2_INDEX || _type == GL_MAP2_COLOR_4))
937  ||
938  (global_bpm->bpatch_texcoord == NULL &&
939  (_type == GL_MAP2_TEXTURE_COORD_1 ||
940  _type == GL_MAP2_TEXTURE_COORD_2 ||
941  _type == GL_MAP2_TEXTURE_COORD_3 ||
942  _type == GL_MAP2_TEXTURE_COORD_4 )
943  ))
944  {
945  bezierPatchMeshPutPatch(global_bpm, (int) _type, _ulower, _uupper,(int) _ustride,(int) _uorder,_vlower, _vupper, (int) _vstride, (int) _vorder, pts);
946  }
947  else /*new surface patch (with multiple maps) starts*/
948  {
949  bezierPatchMesh *temp = bezierPatchMeshMake2(10,10);
950  bezierPatchMeshPutPatch(temp, (int) _type, _ulower, _uupper,(int) _ustride,(int) _uorder,_vlower, _vupper, (int) _vstride, (int) _vorder, pts);
951  global_bpm = bezierPatchMeshListInsert(global_bpm, temp);
952 
953  /*
954  global_bpm = bezierPatchMeshListInsert(global_bpm,
955  bezierPatchMeshMake(
956  (int) _type, _ulower, _uupper,(int) _ustride, (int) _uorder, _vlower, _vupper, (int) _vstride, (int) _vorder, pts, 10, 10));
957  */
958  }
959  }
960 #ifdef HAVE_GL_H
961  else /*not output triangles*/
962  {
963  glMap2f((GLenum) _type, (GLfloat) _ulower, (GLfloat) _uupper,
964  (GLint) _ustride, (GLint) _uorder, (GLfloat) _vlower,
965  (GLfloat) _vupper, (GLint) _vstride, (GLint) _vorder,
966  (const GLfloat *) pts);
967  }
968 #endif
969 #endif
970 }
971 
972 
973 /*-------------------------------------------------------------------------
974  * mapmesh2f - evaluate a mesh of points on lattice
975  *-------------------------------------------------------------------------
976  */
977 void
978 OpenGLSurfaceEvaluator::mapmesh2f(long style, long umin, long umax, long vmin, long vmax)
979 {
980 #ifdef NO_EVALUATION
981 return;
982 #endif
983 
984 #ifdef USE_INTERNAL_EVAL
985  inEvalMesh2((int)umin, (int)vmin, (int)umax, (int)vmax);
986 #else
987 
988 
989 
990 if(output_triangles)
991 {
992 #ifdef USE_LOD
993  bezierPatchMeshBeginStrip(global_bpm, GL_POLYGON);
994  bezierPatchMeshInsertUV(global_bpm, global_grid_u0, global_grid_v0);
995  bezierPatchMeshInsertUV(global_bpm, global_grid_u1, global_grid_v1);
996  bezierPatchMeshInsertUV(global_bpm, (REAL)global_grid_nu, (REAL)global_grid_nv);
997  bezierPatchMeshInsertUV(global_bpm, (REAL)umin, (REAL)vmin);
998  bezierPatchMeshInsertUV(global_bpm, (REAL)umax, (REAL)vmax);
999  bezierPatchMeshEndStrip(global_bpm);
1000 
1001 #else
1002 
1003  REAL du, dv;
1004  long i,j;
1005  if(global_grid_nu == 0 || global_grid_nv == 0)
1006  return; /*no points need to be output*/
1007  du = (global_grid_u1 - global_grid_u0) / (REAL)global_grid_nu;
1008  dv = (global_grid_v1 - global_grid_v0) / (REAL)global_grid_nv;
1009 
1010  if(global_grid_nu >= global_grid_nv){
1011 
1012  for(i=umin; i<umax; i++){
1013  REAL u1 = (i==global_grid_nu)? global_grid_u1:(global_grid_u0 + i*du);
1014  REAL u2 = ((i+1) == global_grid_nu)? global_grid_u1: (global_grid_u0+(i+1)*du);
1015 
1016  bgnqstrip();
1017  for(j=vmax; j>=vmin; j--){
1018  REAL v1 = (j == global_grid_nv)? global_grid_v1: (global_grid_v0 +j*dv);
1019 
1020  coord2f(u1, v1);
1021  coord2f(u2, v1);
1022  }
1023  endqstrip();
1024  }
1025  }
1026  else{
1027 
1028  for(i=vmin; i<vmax; i++){
1029  REAL v1 = (i==global_grid_nv)? global_grid_v1:(global_grid_v0 + i*dv);
1030  REAL v2 = ((i+1) == global_grid_nv)? global_grid_v1: (global_grid_v0+(i+1)*dv);
1031 
1032  bgnqstrip();
1033  for(j=umax; j>=umin; j--){
1034  REAL u1 = (j == global_grid_nu)? global_grid_u1: (global_grid_u0 +j*du);
1035  coord2f(u1, v2);
1036  coord2f(u1, v1);
1037  }
1038  endqstrip();
1039  }
1040  }
1041 #endif
1042 }
1043 #ifdef HAVE_GL_H
1044 else
1045 {
1046  switch(style) {
1047  default:
1048  case N_MESHFILL:
1049  glEvalMesh2((GLenum) GL_FILL, (GLint) umin, (GLint) umax,
1050  (GLint) vmin, (GLint) vmax);
1051  break;
1052  case N_MESHLINE:
1053  glEvalMesh2((GLenum) GL_LINE, (GLint) umin, (GLint) umax,
1054  (GLint) vmin, (GLint) vmax);
1055  break;
1056  case N_MESHPOINT:
1057  glEvalMesh2((GLenum) GL_POINT, (GLint) umin, (GLint) umax,
1058  (GLint) vmin, (GLint) vmax);
1059  break;
1060  }
1061  }
1062 #endif
1063 #endif
1064 
1065 #ifdef STATISTICS
1066  STAT_num_of_quad_strips += (umax-umin)*(vmax-vmin);
1067 #endif
1068 }
1069 
1070 /*-------------------------------------------------------------------------
1071  * evalcoord2f - evaluate a point on a surface
1072  *-------------------------------------------------------------------------
1073  */
1074 void
1075 OpenGLSurfaceEvaluator::evalcoord2f(long, REAL u, REAL v)
1076 {
1077 
1078 
1079 #ifdef NO_EVALUATION
1080 return;
1081 #endif
1082 
1083 
1084  newtmeshvert(u, v);
1085 }
1086 
1087 /*-------------------------------------------------------------------------
1088  * evalpoint2i - evaluate a grid point
1089  *-------------------------------------------------------------------------
1090  */
1091 void
1092 OpenGLSurfaceEvaluator::evalpoint2i(long u, long v)
1093 {
1094 #ifdef NO_EVALUATION
1095 return;
1096 #endif
1097 
1098  newtmeshvert(u, v);
1099 }
1100 
1101 void
1102 OpenGLSurfaceEvaluator::point2i( long u, long v )
1103 {
1104 #ifdef NO_EVALUATION
1105 return;
1106 #else
1107 
1108 #ifdef USE_INTERNAL_EVAL
1109  inEvalPoint2( (int)u, (int)v);
1110 #else
1111 
1112 
1113 if(output_triangles)
1114 {
1115 
1116  REAL du, dv;
1117  REAL fu,fv;
1118  du = (global_grid_u1 - global_grid_u0) / (REAL)global_grid_nu;
1119  dv = (global_grid_v1 - global_grid_v0) / (REAL)global_grid_nv;
1120  fu = (u==global_grid_nu)? global_grid_u1:(global_grid_u0 + u*du);
1121  fv = (v == global_grid_nv)? global_grid_v1: (global_grid_v0 +v*dv);
1122  coord2f(fu,fv);
1123 }
1124 #ifdef HAVE_GL_H
1125 else
1126  glEvalPoint2((GLint) u, (GLint) v);
1127 #endif
1128 
1129 #endif
1130 
1131 #ifdef STATISTICS
1132  STAT_num_of_eval_vertices++;
1133 #endif
1134 
1135 #endif
1136 
1137 }
1138 
1139 void
1140 OpenGLSurfaceEvaluator::coord2f( REAL u, REAL v )
1141 {
1142 #ifdef NO_EVALUATION
1143 return;
1144 #else
1145 
1146 #ifdef USE_INTERNAL_EVAL
1147  inEvalCoord2f( u, v);
1148 #else
1149 
1150 
1151 if(output_triangles)
1152  bezierPatchMeshInsertUV(global_bpm, u,v);
1153 #ifdef HAVE_GL_H
1154 else
1155  glEvalCoord2f((GLfloat) u, (GLfloat) v);
1156 #endif
1157 
1158 #endif
1159 
1160 
1161 #ifdef STATISTICS
1162  STAT_num_of_eval_vertices++;
1163 #endif
1164 
1165 #endif
1166 }
1167 
1168 void
1169 OpenGLSurfaceEvaluator::newtmeshvert( long u, long v )
1170 {
1171 #ifdef NO_EVALUATION
1172 return;
1173 #else
1174 
1175  if (tmeshing) {
1176 
1177  if (vcount == 2) {
1178  vertexCache[0]->invoke(this);
1179  vertexCache[1]->invoke(this);
1180  point2i( u, v);
1181 
1182  } else {
1183  vcount++;
1184  }
1185 
1186  vertexCache[which]->saveEvalPoint(u, v);
1187  which = 1 - which;
1188  } else {
1189  point2i( u, v);
1190  }
1191 #endif
1192 }
1193 
1194 void
1195 OpenGLSurfaceEvaluator::newtmeshvert( REAL u, REAL v )
1196 {
1197 #ifdef NO_EVALUATION
1198 return;
1199 #else
1200  if (tmeshing) {
1201 
1202 
1203  if (vcount == 2) {
1204  vertexCache[0]->invoke(this);
1205  vertexCache[1]->invoke(this);
1206  coord2f(u,v);
1207 
1208  } else {
1209  vcount++;
1210  }
1211 
1212  vertexCache[which]->saveEvalCoord(u, v);
1213  which = 1 - which;
1214  } else {
1215 
1216  coord2f( u, v);
1217  }
1218 #endif
1219 
1220 }
1221 
1222 #ifdef _WIN32
1223 void OpenGLSurfaceEvaluator::putCallBack(GLenum which, void (GLAPIENTRY *fn)() )
1224 #else
1225 void OpenGLSurfaceEvaluator::putCallBack(GLenum which, _GLUfuncptr fn )
1226 #endif
1227 {
1228  switch(which)
1229  {
1230  case GLU_NURBS_BEGIN:
1231  beginCallBackN = (void (GLAPIENTRY *) (GLenum)) fn;
1232  break;
1233  case GLU_NURBS_END:
1234  endCallBackN = (void (GLAPIENTRY *) (void)) fn;
1235  break;
1236  case GLU_NURBS_VERTEX:
1237  vertexCallBackN = (void (GLAPIENTRY *) (const GLfloat*)) fn;
1238  break;
1239  case GLU_NURBS_NORMAL:
1240  normalCallBackN = (void (GLAPIENTRY *) (const GLfloat*)) fn;
1241  break;
1242  case GLU_NURBS_COLOR:
1243  colorCallBackN = (void (GLAPIENTRY *) (const GLfloat*)) fn;
1244  break;
1245  case GLU_NURBS_TEXTURE_COORD:
1246  texcoordCallBackN = (void (GLAPIENTRY *) (const GLfloat*)) fn;
1247  break;
1248  case GLU_NURBS_BEGIN_DATA:
1249  beginCallBackData = (void (GLAPIENTRY *) (GLenum, void*)) fn;
1250  break;
1251  case GLU_NURBS_END_DATA:
1252  endCallBackData = (void (GLAPIENTRY *) (void*)) fn;
1253  break;
1254  case GLU_NURBS_VERTEX_DATA:
1255  vertexCallBackData = (void (GLAPIENTRY *) (const GLfloat*, void*)) fn;
1256  break;
1257  case GLU_NURBS_NORMAL_DATA:
1258  normalCallBackData = (void (GLAPIENTRY *) (const GLfloat*, void*)) fn;
1259  break;
1260  case GLU_NURBS_COLOR_DATA:
1261  colorCallBackData = (void (GLAPIENTRY *) (const GLfloat*, void*)) fn;
1262  break;
1263  case GLU_NURBS_TEXTURE_COORD_DATA:
1264  texcoordCallBackData = (void (GLAPIENTRY *) (const GLfloat*, void*)) fn;
1265  break;
1266 
1267  }
1268 }
1269 
1270 
1271 void
1272 OpenGLSurfaceEvaluator::beginCallBack(GLenum which, void *data)
1273 {
1274  if(beginCallBackData)
1275  beginCallBackData(which, data);
1276  else if(beginCallBackN)
1277  beginCallBackN(which);
1278 }
1279 
1280 void
1281 OpenGLSurfaceEvaluator::endCallBack(void *data)
1282 {
1283  if(endCallBackData)
1284  endCallBackData(data);
1285  else if(endCallBackN)
1286  endCallBackN();
1287 }
1288 
1289 void
1290 OpenGLSurfaceEvaluator::vertexCallBack(const GLfloat *vert, void* data)
1291 {
1292  if(vertexCallBackData)
1293  vertexCallBackData(vert, data);
1294  else if(vertexCallBackN)
1295  vertexCallBackN(vert);
1296 }
1297 
1298 
1299 void
1300 OpenGLSurfaceEvaluator::normalCallBack(const GLfloat *normal, void* data)
1301 {
1302  if(normalCallBackData)
1303  normalCallBackData(normal, data);
1304  else if(normalCallBackN)
1305  normalCallBackN(normal);
1306 }
1307 
1308 void
1309 OpenGLSurfaceEvaluator::colorCallBack(const GLfloat *color, void* data)
1310 {
1311  if(colorCallBackData)
1312  colorCallBackData(color, data);
1313  else if(colorCallBackN)
1314  colorCallBackN(color);
1315 }
1316 
1317 void
1318 OpenGLSurfaceEvaluator::texcoordCallBack(const GLfloat *texcoord, void* data)
1319 {
1320  if(texcoordCallBackData)
1321  texcoordCallBackData(texcoord, data);
1322  else if(texcoordCallBackN)
1323  texcoordCallBackN(texcoord);
1324 }
1325 
1326 
1327 
1328