FreeWRL / FreeX3D 4.3.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
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#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
219void
220OpenGLSurfaceEvaluator::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
242void
243OpenGLSurfaceEvaluator::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
253void
254OpenGLSurfaceEvaluator::endline(void)
255{
256 if(output_triangles)
257 bezierPatchMeshEndStrip(global_bpm);
258#ifdef HAVE_GL_H
259 else
260 glEnd();
261#endif
262}
263
264void
265OpenGLSurfaceEvaluator::range2f(long type, REAL *from, REAL *to)
266{
267}
268
269void
270OpenGLSurfaceEvaluator::domain2f(REAL ulo, REAL uhi, REAL vlo, REAL vhi)
271{
272}
273
274void
275OpenGLSurfaceEvaluator::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
285void
286OpenGLSurfaceEvaluator::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
300void
301OpenGLSurfaceEvaluator::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
317void
318OpenGLSurfaceEvaluator::swaptmesh(void)
319{
320 which = 1 - which;
321
322}
323
324void
325OpenGLSurfaceEvaluator::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
338void
339OpenGLSurfaceEvaluator::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}
350void
351OpenGLSurfaceEvaluator::endtfan(void)
352{
353 if(output_triangles)
354 bezierPatchMeshEndStrip(global_bpm);
355#ifdef HAVE_GL_H
356 else
357 glEnd();
358#endif
359}
360
361void
362OpenGLSurfaceEvaluator::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
548void
549OpenGLSurfaceEvaluator::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
730void
731OpenGLSurfaceEvaluator::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
745void
746OpenGLSurfaceEvaluator::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 */
761void
762OpenGLSurfaceEvaluator::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 */
827void
828OpenGLSurfaceEvaluator::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
877else
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 */
902void
903OpenGLSurfaceEvaluator::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 */
977void
978OpenGLSurfaceEvaluator::mapmesh2f(long style, long umin, long umax, long vmin, long vmax)
979{
980#ifdef NO_EVALUATION
981return;
982#endif
983
984#ifdef USE_INTERNAL_EVAL
985 inEvalMesh2((int)umin, (int)vmin, (int)umax, (int)vmax);
986#else
987
988
989
990if(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
1044else
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 */
1074void
1075OpenGLSurfaceEvaluator::evalcoord2f(long, REAL u, REAL v)
1076{
1077
1078
1079#ifdef NO_EVALUATION
1080return;
1081#endif
1082
1083
1084 newtmeshvert(u, v);
1085}
1086
1087/*-------------------------------------------------------------------------
1088 * evalpoint2i - evaluate a grid point
1089 *-------------------------------------------------------------------------
1090 */
1091void
1092OpenGLSurfaceEvaluator::evalpoint2i(long u, long v)
1093{
1094#ifdef NO_EVALUATION
1095return;
1096#endif
1097
1098 newtmeshvert(u, v);
1099}
1100
1101void
1102OpenGLSurfaceEvaluator::point2i( long u, long v )
1103{
1104#ifdef NO_EVALUATION
1105return;
1106#else
1107
1108#ifdef USE_INTERNAL_EVAL
1109 inEvalPoint2( (int)u, (int)v);
1110#else
1111
1112
1113if(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
1125else
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
1139void
1140OpenGLSurfaceEvaluator::coord2f( REAL u, REAL v )
1141{
1142#ifdef NO_EVALUATION
1143return;
1144#else
1145
1146#ifdef USE_INTERNAL_EVAL
1147 inEvalCoord2f( u, v);
1148#else
1149
1150
1151if(output_triangles)
1152 bezierPatchMeshInsertUV(global_bpm, u,v);
1153#ifdef HAVE_GL_H
1154else
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
1168void
1169OpenGLSurfaceEvaluator::newtmeshvert( long u, long v )
1170{
1171#ifdef NO_EVALUATION
1172return;
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
1194void
1195OpenGLSurfaceEvaluator::newtmeshvert( REAL u, REAL v )
1196{
1197#ifdef NO_EVALUATION
1198return;
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
1223void OpenGLSurfaceEvaluator::putCallBack(GLenum which, void (GLAPIENTRY *fn)() )
1224#else
1225void 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
1271void
1272OpenGLSurfaceEvaluator::beginCallBack(GLenum which, void *data)
1273{
1274 if(beginCallBackData)
1275 beginCallBackData(which, data);
1276 else if(beginCallBackN)
1277 beginCallBackN(which);
1278}
1279
1280void
1281OpenGLSurfaceEvaluator::endCallBack(void *data)
1282{
1283 if(endCallBackData)
1284 endCallBackData(data);
1285 else if(endCallBackN)
1286 endCallBackN();
1287}
1288
1289void
1290OpenGLSurfaceEvaluator::vertexCallBack(const GLfloat *vert, void* data)
1291{
1292 if(vertexCallBackData)
1293 vertexCallBackData(vert, data);
1294 else if(vertexCallBackN)
1295 vertexCallBackN(vert);
1296}
1297
1298
1299void
1300OpenGLSurfaceEvaluator::normalCallBack(const GLfloat *normal, void* data)
1301{
1302 if(normalCallBackData)
1303 normalCallBackData(normal, data);
1304 else if(normalCallBackN)
1305 normalCallBackN(normal);
1306}
1307
1308void
1309OpenGLSurfaceEvaluator::colorCallBack(const GLfloat *color, void* data)
1310{
1311 if(colorCallBackData)
1312 colorCallBackData(color, data);
1313 else if(colorCallBackN)
1314 colorCallBackN(color);
1315}
1316
1317void
1318OpenGLSurfaceEvaluator::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