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