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