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
63static int STAT_num_of_triangles=0;
64static int STAT_num_of_eval_vertices=0;
65static 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
74extern "C"  {  void                evalUStripExt(int n_upper, REAL v_upper, REAL* upper_val,
75				   int n_lower, REAL v_lower, REAL* lower_val);}
76
77extern "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***********/
84void 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
99OpenGLSurfaceEvaluator::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
162OpenGLSurfaceEvaluator::~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 */
174void
175OpenGLSurfaceEvaluator::disable(long type)
176{
177    glDisable((GLenum) type);
178}
179
180/*---------------------------------------------------------------------------
181 * enable - turn on a map
182 *---------------------------------------------------------------------------
183 */
184void
185OpenGLSurfaceEvaluator::enable(long type)
186{
187    glEnable((GLenum) type);
188}
189
190/*-------------------------------------------------------------------------
191 * mapgrid2f - define a lattice of points with origin and offset
192 *-------------------------------------------------------------------------
193 */
194void
195OpenGLSurfaceEvaluator::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
218void
219OpenGLSurfaceEvaluator::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
239void
240OpenGLSurfaceEvaluator::bgnline(void)
241{
242  if(output_triangles)
243    bezierPatchMeshBeginStrip(global_bpm, GL_LINE_STRIP);
244  else
245    glBegin((GLenum) GL_LINE_STRIP);
246}
247
248void
249OpenGLSurfaceEvaluator::endline(void)
250{
251  if(output_triangles)
252    bezierPatchMeshEndStrip(global_bpm);
253  else
254    glEnd();
255}
256
257void
258OpenGLSurfaceEvaluator::range2f(long type, REAL *from, REAL *to)
259{
260}
261
262void
263OpenGLSurfaceEvaluator::domain2f(REAL ulo, REAL uhi, REAL vlo, REAL vhi)
264{
265}
266
267void
268OpenGLSurfaceEvaluator::bgnclosedline(void)
269{
270  if(output_triangles)
271    bezierPatchMeshBeginStrip(global_bpm, GL_LINE_LOOP);
272  else
273    glBegin((GLenum) GL_LINE_LOOP);
274}
275
276void
277OpenGLSurfaceEvaluator::endclosedline(void)
278{
279  if(output_triangles)
280    bezierPatchMeshEndStrip(global_bpm);
281  else
282    glEnd();
283}
284
285
286
287
288
289void
290OpenGLSurfaceEvaluator::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
304void
305OpenGLSurfaceEvaluator::swaptmesh(void)
306{
307    which = 1 - which;
308
309}
310
311void
312OpenGLSurfaceEvaluator::endtmesh(void)
313{
314    tmeshing = 0;
315
316
317    if(output_triangles)
318      bezierPatchMeshEndStrip(global_bpm);
319    else
320      glEnd();
321}
322
323void
324OpenGLSurfaceEvaluator::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}
333void
334OpenGLSurfaceEvaluator::endtfan(void)
335{
336  if(output_triangles)
337	bezierPatchMeshEndStrip(global_bpm);
338  else
339    glEnd();
340}
341
342void
343OpenGLSurfaceEvaluator::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
529void
530OpenGLSurfaceEvaluator::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
711void
712OpenGLSurfaceEvaluator::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
724void
725OpenGLSurfaceEvaluator::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 */
738void
739OpenGLSurfaceEvaluator::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 */
800void
801OpenGLSurfaceEvaluator::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  }
847else
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 */
871void
872OpenGLSurfaceEvaluator::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 */
945void
946OpenGLSurfaceEvaluator::mapmesh2f(long style, long umin, long umax, long vmin, long vmax)
947{
948#ifdef NO_EVALUATION
949return;
950#endif
951
952#ifdef USE_INTERNAL_EVAL
953    inEvalMesh2((int)umin, (int)vmin, (int)umax, (int)vmax);
954#else
955
956
957
958if(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}
1011else
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 */
1041void
1042OpenGLSurfaceEvaluator::evalcoord2f(long, REAL u, REAL v)
1043{
1044
1045
1046#ifdef NO_EVALUATION
1047return;
1048#endif
1049
1050
1051    newtmeshvert(u, v);
1052}
1053
1054/*-------------------------------------------------------------------------
1055 * evalpoint2i - evaluate a grid point
1056 *-------------------------------------------------------------------------
1057 */
1058void
1059OpenGLSurfaceEvaluator::evalpoint2i(long u, long v)
1060{
1061#ifdef NO_EVALUATION
1062return;
1063#endif
1064
1065    newtmeshvert(u, v);
1066}
1067
1068void
1069OpenGLSurfaceEvaluator::point2i( long u, long v )
1070{
1071#ifdef NO_EVALUATION
1072return;
1073#else
1074
1075#ifdef USE_INTERNAL_EVAL
1076    inEvalPoint2( (int)u,  (int)v);
1077#else
1078
1079
1080if(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}
1091else
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
1105void
1106OpenGLSurfaceEvaluator::coord2f( REAL u, REAL v )
1107{
1108#ifdef NO_EVALUATION
1109return;
1110#else
1111
1112#ifdef USE_INTERNAL_EVAL
1113    inEvalCoord2f( u, v);
1114#else
1115
1116
1117if(output_triangles)
1118    bezierPatchMeshInsertUV(global_bpm, u,v);
1119else
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
1133void
1134OpenGLSurfaceEvaluator::newtmeshvert( long u, long v )
1135{
1136#ifdef NO_EVALUATION
1137return;
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
1159void
1160OpenGLSurfaceEvaluator::newtmeshvert( REAL u, REAL v )
1161{
1162#ifdef NO_EVALUATION
1163return;
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
1188void OpenGLSurfaceEvaluator::putCallBack(GLenum which, void (GLAPIENTRY *fn)() )
1189#else
1190void 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
1236void
1237OpenGLSurfaceEvaluator::beginCallBack(GLenum which, void *data)
1238{
1239  if(beginCallBackData)
1240    beginCallBackData(which, data);
1241  else if(beginCallBackN)
1242    beginCallBackN(which);
1243}
1244
1245void
1246OpenGLSurfaceEvaluator::endCallBack(void *data)
1247{
1248  if(endCallBackData)
1249    endCallBackData(data);
1250  else if(endCallBackN)
1251    endCallBackN();
1252}
1253
1254void
1255OpenGLSurfaceEvaluator::vertexCallBack(const GLfloat *vert, void* data)
1256{
1257  if(vertexCallBackData)
1258    vertexCallBackData(vert, data);
1259  else if(vertexCallBackN)
1260    vertexCallBackN(vert);
1261}
1262
1263
1264void
1265OpenGLSurfaceEvaluator::normalCallBack(const GLfloat *normal, void* data)
1266{
1267  if(normalCallBackData)
1268    normalCallBackData(normal, data);
1269  else if(normalCallBackN)
1270    normalCallBackN(normal);
1271}
1272
1273void
1274OpenGLSurfaceEvaluator::colorCallBack(const GLfloat *color, void* data)
1275{
1276  if(colorCallBackData)
1277    colorCallBackData(color, data);
1278  else if(colorCallBackN)
1279    colorCallBackN(color);
1280}
1281
1282void
1283OpenGLSurfaceEvaluator::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