1*c2c66affSColin Finck /*
2*c2c66affSColin Finck ** License Applicability. Except to the extent portions of this file are
3*c2c66affSColin Finck ** made subject to an alternative license as permitted in the SGI Free
4*c2c66affSColin Finck ** Software License B, Version 1.1 (the "License"), the contents of this
5*c2c66affSColin Finck ** file are subject only to the provisions of the License. You may not use
6*c2c66affSColin Finck ** this file except in compliance with the License. You may obtain a copy
7*c2c66affSColin Finck ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
8*c2c66affSColin Finck ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
9*c2c66affSColin Finck **
10*c2c66affSColin Finck ** http://oss.sgi.com/projects/FreeB
11*c2c66affSColin Finck **
12*c2c66affSColin Finck ** Note that, as provided in the License, the Software is distributed on an
13*c2c66affSColin Finck ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
14*c2c66affSColin Finck ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
15*c2c66affSColin Finck ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
16*c2c66affSColin Finck ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
17*c2c66affSColin Finck **
18*c2c66affSColin Finck ** Original Code. The Original Code is: OpenGL Sample Implementation,
19*c2c66affSColin Finck ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
20*c2c66affSColin Finck ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
21*c2c66affSColin Finck ** Copyright in any portions created by third parties is as indicated
22*c2c66affSColin Finck ** elsewhere herein. All Rights Reserved.
23*c2c66affSColin Finck **
24*c2c66affSColin Finck ** Additional Notice Provisions: The application programming interfaces
25*c2c66affSColin Finck ** established by SGI in conjunction with the Original Code are The
26*c2c66affSColin Finck ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
27*c2c66affSColin Finck ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
28*c2c66affSColin Finck ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
29*c2c66affSColin Finck ** Window System(R) (Version 1.3), released October 19, 1998. This software
30*c2c66affSColin Finck ** was created using the OpenGL(R) version 1.2.1 Sample Implementation
31*c2c66affSColin Finck ** published by SGI, but has not been independently verified as being
32*c2c66affSColin Finck ** compliant with the OpenGL(R) version 1.2.1 Specification.
33*c2c66affSColin Finck **
34*c2c66affSColin Finck */
35*c2c66affSColin Finck /*
36*c2c66affSColin Finck */
37*c2c66affSColin Finck 
38*c2c66affSColin Finck #include "gluos.h"
39*c2c66affSColin Finck //#include <stdlib.h>
40*c2c66affSColin Finck //#include <stdio.h>
41*c2c66affSColin Finck //#include <GL/gl.h>
42*c2c66affSColin Finck #include <math.h>
43*c2c66affSColin Finck #include <assert.h>
44*c2c66affSColin Finck 
45*c2c66affSColin Finck #include "glsurfeval.h"
46*c2c66affSColin Finck 
47*c2c66affSColin Finck //extern int surfcount;
48*c2c66affSColin Finck 
49*c2c66affSColin Finck //#define CRACK_TEST
50*c2c66affSColin Finck 
51*c2c66affSColin Finck #define AVOID_ZERO_NORMAL
52*c2c66affSColin Finck 
53*c2c66affSColin Finck #ifdef AVOID_ZERO_NORMAL
54*c2c66affSColin Finck #define myabs(x)  ((x>0)? x: (-x))
55*c2c66affSColin Finck #define MYZERO 0.000001
56*c2c66affSColin Finck #define MYDELTA 0.001
57*c2c66affSColin Finck #endif
58*c2c66affSColin Finck 
59*c2c66affSColin Finck //#define USE_LOD
60*c2c66affSColin Finck #ifdef USE_LOD
61*c2c66affSColin Finck //#define LOD_EVAL_COORD(u,v) inDoEvalCoord2EM(u,v)
62*c2c66affSColin Finck #define LOD_EVAL_COORD(u,v) glEvalCoord2f(u,v)
63*c2c66affSColin Finck 
LOD_interpolate(REAL A[2],REAL B[2],REAL C[2],int j,int k,int pow2_level,REAL & u,REAL & v)64*c2c66affSColin Finck static void LOD_interpolate(REAL A[2], REAL B[2], REAL C[2], int j, int k, int pow2_level,
65*c2c66affSColin Finck 			    REAL& u, REAL& v)
66*c2c66affSColin Finck {
67*c2c66affSColin Finck   REAL a,a1,b,b1;
68*c2c66affSColin Finck 
69*c2c66affSColin Finck   a = ((REAL) j) / ((REAL) pow2_level);
70*c2c66affSColin Finck   a1 = 1-a;
71*c2c66affSColin Finck 
72*c2c66affSColin Finck   if(j != 0)
73*c2c66affSColin Finck     {
74*c2c66affSColin Finck       b = ((REAL) k) / ((REAL)j);
75*c2c66affSColin Finck       b1 = 1-b;
76*c2c66affSColin Finck     }
77*c2c66affSColin Finck   REAL x,y,z;
78*c2c66affSColin Finck   x = a1;
79*c2c66affSColin Finck   if(j==0)
80*c2c66affSColin Finck     {
81*c2c66affSColin Finck       y=0; z=0;
82*c2c66affSColin Finck     }
83*c2c66affSColin Finck   else{
84*c2c66affSColin Finck     y = b1*a;
85*c2c66affSColin Finck     z = b *a;
86*c2c66affSColin Finck   }
87*c2c66affSColin Finck 
88*c2c66affSColin Finck   u = x*A[0] + y*B[0] + z*C[0];
89*c2c66affSColin Finck   v = x*A[1] + y*B[1] + z*C[1];
90*c2c66affSColin Finck }
91*c2c66affSColin Finck 
LOD_triangle(REAL A[2],REAL B[2],REAL C[2],int level)92*c2c66affSColin Finck void OpenGLSurfaceEvaluator::LOD_triangle(REAL A[2], REAL B[2], REAL C[2],
93*c2c66affSColin Finck 			 int level)
94*c2c66affSColin Finck {
95*c2c66affSColin Finck   int k,j;
96*c2c66affSColin Finck   int pow2_level;
97*c2c66affSColin Finck   /*compute 2^level*/
98*c2c66affSColin Finck   pow2_level = 1;
99*c2c66affSColin Finck 
100*c2c66affSColin Finck   for(j=0; j<level; j++)
101*c2c66affSColin Finck     pow2_level *= 2;
102*c2c66affSColin Finck   for(j=0; j<=pow2_level-1; j++)
103*c2c66affSColin Finck     {
104*c2c66affSColin Finck       REAL u,v;
105*c2c66affSColin Finck 
106*c2c66affSColin Finck /*      beginCallBack(GL_TRIANGLE_STRIP);*/
107*c2c66affSColin Finck glBegin(GL_TRIANGLE_STRIP);
108*c2c66affSColin Finck       LOD_interpolate(A,B,C, j+1, j+1, pow2_level, u,v);
109*c2c66affSColin Finck #ifdef USE_LOD
110*c2c66affSColin Finck       LOD_EVAL_COORD(u,v);
111*c2c66affSColin Finck //      glEvalCoord2f(u,v);
112*c2c66affSColin Finck #else
113*c2c66affSColin Finck       inDoEvalCoord2EM(u,v);
114*c2c66affSColin Finck #endif
115*c2c66affSColin Finck 
116*c2c66affSColin Finck       for(k=0; k<=j; k++)
117*c2c66affSColin Finck 	{
118*c2c66affSColin Finck 	  LOD_interpolate(A,B,C,j,j-k,pow2_level, u,v);
119*c2c66affSColin Finck #ifdef USE_LOD
120*c2c66affSColin Finck           LOD_EVAL_COORD(u,v);
121*c2c66affSColin Finck //	  glEvalCoord2f(u,v);
122*c2c66affSColin Finck #else
123*c2c66affSColin Finck 	  inDoEvalCoord2EM(u,v);
124*c2c66affSColin Finck #endif
125*c2c66affSColin Finck 
126*c2c66affSColin Finck 	  LOD_interpolate(A,B,C,j+1,j-k,pow2_level, u,v);
127*c2c66affSColin Finck 
128*c2c66affSColin Finck #ifdef USE_LOD
129*c2c66affSColin Finck 	  LOD_EVAL_COORD(u,v);
130*c2c66affSColin Finck //	  glEvalCoord2f(u,v);
131*c2c66affSColin Finck #else
132*c2c66affSColin Finck 	  inDoEvalCoord2EM(u,v);
133*c2c66affSColin Finck #endif
134*c2c66affSColin Finck 	}
135*c2c66affSColin Finck //      endCallBack();
136*c2c66affSColin Finck glEnd();
137*c2c66affSColin Finck     }
138*c2c66affSColin Finck }
139*c2c66affSColin Finck 
LOD_eval(int num_vert,REAL * verts,int type,int level)140*c2c66affSColin Finck void OpenGLSurfaceEvaluator::LOD_eval(int num_vert, REAL* verts, int type,
141*c2c66affSColin Finck 		     int level
142*c2c66affSColin Finck 		     )
143*c2c66affSColin Finck {
144*c2c66affSColin Finck   int i,k;
145*c2c66affSColin Finck   switch(type){
146*c2c66affSColin Finck   case GL_TRIANGLE_STRIP:
147*c2c66affSColin Finck   case GL_QUAD_STRIP:
148*c2c66affSColin Finck     for(i=2, k=4; i<=num_vert-2; i+=2, k+=4)
149*c2c66affSColin Finck       {
150*c2c66affSColin Finck 	LOD_triangle(verts+k-4, verts+k-2, verts+k,
151*c2c66affSColin Finck 		     level
152*c2c66affSColin Finck 		     );
153*c2c66affSColin Finck 	LOD_triangle(verts+k-2, verts+k+2, verts+k,
154*c2c66affSColin Finck 		     level
155*c2c66affSColin Finck 		     );
156*c2c66affSColin Finck       }
157*c2c66affSColin Finck     if(num_vert % 2 ==1)
158*c2c66affSColin Finck       {
159*c2c66affSColin Finck 	LOD_triangle(verts+2*(num_vert-3), verts+2*(num_vert-2), verts+2*(num_vert-1),
160*c2c66affSColin Finck 		     level
161*c2c66affSColin Finck 		     );
162*c2c66affSColin Finck       }
163*c2c66affSColin Finck     break;
164*c2c66affSColin Finck   case GL_TRIANGLE_FAN:
165*c2c66affSColin Finck     for(i=1, k=2; i<=num_vert-2; i++, k+=2)
166*c2c66affSColin Finck       {
167*c2c66affSColin Finck 	LOD_triangle(verts,verts+k, verts+k+2,
168*c2c66affSColin Finck 		     level
169*c2c66affSColin Finck 		     );
170*c2c66affSColin Finck       }
171*c2c66affSColin Finck     break;
172*c2c66affSColin Finck 
173*c2c66affSColin Finck   default:
174*c2c66affSColin Finck     fprintf(stderr, "typy not supported in LOD_\n");
175*c2c66affSColin Finck   }
176*c2c66affSColin Finck }
177*c2c66affSColin Finck 
178*c2c66affSColin Finck 
179*c2c66affSColin Finck #endif //USE_LOD
180*c2c66affSColin Finck 
181*c2c66affSColin Finck //#define  GENERIC_TEST
182*c2c66affSColin Finck #ifdef GENERIC_TEST
183*c2c66affSColin Finck extern float xmin, xmax, ymin, ymax, zmin, zmax; /*bounding box*/
184*c2c66affSColin Finck extern int temp_signal;
185*c2c66affSColin Finck 
gTessVertexSphere(float u,float v,float temp_normal[3],float temp_vertex[3])186*c2c66affSColin Finck static void gTessVertexSphere(float u, float v, float temp_normal[3], float temp_vertex[3])
187*c2c66affSColin Finck {
188*c2c66affSColin Finck   float r=2.0;
189*c2c66affSColin Finck   float Ox = 0.5*(xmin+xmax);
190*c2c66affSColin Finck   float Oy = 0.5*(ymin+ymax);
191*c2c66affSColin Finck   float Oz = 0.5*(zmin+zmax);
192*c2c66affSColin Finck   float nx = cos(v) * sin(u);
193*c2c66affSColin Finck   float ny = sin(v) * sin(u);
194*c2c66affSColin Finck   float nz = cos(u);
195*c2c66affSColin Finck   float x= Ox+r * nx;
196*c2c66affSColin Finck   float y= Oy+r * ny;
197*c2c66affSColin Finck   float z= Oz+r * nz;
198*c2c66affSColin Finck 
199*c2c66affSColin Finck   temp_normal[0] = nx;
200*c2c66affSColin Finck   temp_normal[1] = ny;
201*c2c66affSColin Finck   temp_normal[2] =  nz;
202*c2c66affSColin Finck   temp_vertex[0] = x;
203*c2c66affSColin Finck   temp_vertex[1] = y;
204*c2c66affSColin Finck   temp_vertex[2] = z;
205*c2c66affSColin Finck 
206*c2c66affSColin Finck //  glNormal3f(nx,ny,nz);
207*c2c66affSColin Finck //  glVertex3f(x,y,z);
208*c2c66affSColin Finck }
209*c2c66affSColin Finck 
gTessVertexCyl(float u,float v,float temp_normal[3],float temp_vertex[3])210*c2c66affSColin Finck static void gTessVertexCyl(float u, float v, float temp_normal[3], float temp_vertex[3])
211*c2c66affSColin Finck {
212*c2c66affSColin Finck    float r=2.0;
213*c2c66affSColin Finck   float Ox = 0.5*(xmin+xmax);
214*c2c66affSColin Finck   float Oy = 0.5*(ymin+ymax);
215*c2c66affSColin Finck   float Oz = 0.5*(zmin+zmax);
216*c2c66affSColin Finck   float nx = cos(v);
217*c2c66affSColin Finck   float ny = sin(v);
218*c2c66affSColin Finck   float nz = 0;
219*c2c66affSColin Finck   float x= Ox+r * nx;
220*c2c66affSColin Finck   float y= Oy+r * ny;
221*c2c66affSColin Finck   float z= Oz - 2*u;
222*c2c66affSColin Finck 
223*c2c66affSColin Finck   temp_normal[0] = nx;
224*c2c66affSColin Finck   temp_normal[1] = ny;
225*c2c66affSColin Finck   temp_normal[2] =  nz;
226*c2c66affSColin Finck   temp_vertex[0] = x;
227*c2c66affSColin Finck   temp_vertex[1] = y;
228*c2c66affSColin Finck   temp_vertex[2] = z;
229*c2c66affSColin Finck 
230*c2c66affSColin Finck /*
231*c2c66affSColin Finck   glNormal3f(nx,ny,nz);
232*c2c66affSColin Finck   glVertex3f(x,y,z);
233*c2c66affSColin Finck */
234*c2c66affSColin Finck }
235*c2c66affSColin Finck 
236*c2c66affSColin Finck #endif //GENERIC_TEST
237*c2c66affSColin Finck 
inBPMListEval(bezierPatchMesh * list)238*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inBPMListEval(bezierPatchMesh* list)
239*c2c66affSColin Finck {
240*c2c66affSColin Finck   bezierPatchMesh* temp;
241*c2c66affSColin Finck   for(temp = list; temp != NULL; temp = temp->next)
242*c2c66affSColin Finck     {
243*c2c66affSColin Finck       inBPMEval(temp);
244*c2c66affSColin Finck     }
245*c2c66affSColin Finck }
246*c2c66affSColin Finck 
inBPMEval(bezierPatchMesh * bpm)247*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inBPMEval(bezierPatchMesh* bpm)
248*c2c66affSColin Finck {
249*c2c66affSColin Finck   int i,j,k,l;
250*c2c66affSColin Finck   float u,v;
251*c2c66affSColin Finck 
252*c2c66affSColin Finck   int ustride = bpm->bpatch->dimension * bpm->bpatch->vorder;
253*c2c66affSColin Finck   int vstride = bpm->bpatch->dimension;
254*c2c66affSColin Finck   inMap2f(
255*c2c66affSColin Finck 	  (bpm->bpatch->dimension == 3)? GL_MAP2_VERTEX_3 : GL_MAP2_VERTEX_4,
256*c2c66affSColin Finck 	  bpm->bpatch->umin,
257*c2c66affSColin Finck 	  bpm->bpatch->umax,
258*c2c66affSColin Finck 	  ustride,
259*c2c66affSColin Finck 	  bpm->bpatch->uorder,
260*c2c66affSColin Finck 	  bpm->bpatch->vmin,
261*c2c66affSColin Finck 	  bpm->bpatch->vmax,
262*c2c66affSColin Finck 	  vstride,
263*c2c66affSColin Finck 	  bpm->bpatch->vorder,
264*c2c66affSColin Finck 	  bpm->bpatch->ctlpoints);
265*c2c66affSColin Finck 
266*c2c66affSColin Finck   bpm->vertex_array = (float*) malloc(sizeof(float)* (bpm->index_UVarray/2) * 3+1); /*in case the origional dimenion is 4, then we need 4 space to pass to evaluator.*/
267*c2c66affSColin Finck   assert(bpm->vertex_array);
268*c2c66affSColin Finck   bpm->normal_array = (float*) malloc(sizeof(float)* (bpm->index_UVarray/2) * 3);
269*c2c66affSColin Finck   assert(bpm->normal_array);
270*c2c66affSColin Finck #ifdef CRACK_TEST
271*c2c66affSColin Finck if(  global_ev_u1 ==2 &&   global_ev_u2 == 3
272*c2c66affSColin Finck   && global_ev_v1 ==2 &&   global_ev_v2 == 3)
273*c2c66affSColin Finck {
274*c2c66affSColin Finck REAL vertex[4];
275*c2c66affSColin Finck REAL normal[4];
276*c2c66affSColin Finck #ifdef DEBUG
277*c2c66affSColin Finck printf("***number 1\n");
278*c2c66affSColin Finck #endif
279*c2c66affSColin Finck 
280*c2c66affSColin Finck beginCallBack(GL_QUAD_STRIP, NULL);
281*c2c66affSColin Finck inEvalCoord2f(3.0, 3.0);
282*c2c66affSColin Finck inEvalCoord2f(2.0, 3.0);
283*c2c66affSColin Finck inEvalCoord2f(3.0, 2.7);
284*c2c66affSColin Finck inEvalCoord2f(2.0, 2.7);
285*c2c66affSColin Finck inEvalCoord2f(3.0, 2.0);
286*c2c66affSColin Finck inEvalCoord2f(2.0, 2.0);
287*c2c66affSColin Finck endCallBack(NULL);
288*c2c66affSColin Finck 
289*c2c66affSColin Finck 
290*c2c66affSColin Finck beginCallBack(GL_TRIANGLE_STRIP, NULL);
291*c2c66affSColin Finck inEvalCoord2f(2.0, 3.0);
292*c2c66affSColin Finck inEvalCoord2f(2.0, 2.0);
293*c2c66affSColin Finck inEvalCoord2f(2.0, 2.7);
294*c2c66affSColin Finck endCallBack(NULL);
295*c2c66affSColin Finck 
296*c2c66affSColin Finck }
297*c2c66affSColin Finck 
298*c2c66affSColin Finck /*
299*c2c66affSColin Finck if(  global_ev_u1 ==2 &&   global_ev_u2 == 3
300*c2c66affSColin Finck   && global_ev_v1 ==1 &&   global_ev_v2 == 2)
301*c2c66affSColin Finck {
302*c2c66affSColin Finck #ifdef DEBUG
303*c2c66affSColin Finck printf("***number 2\n");
304*c2c66affSColin Finck #endif
305*c2c66affSColin Finck beginCallBack(GL_QUAD_STRIP);
306*c2c66affSColin Finck inEvalCoord2f(2.0, 2.0);
307*c2c66affSColin Finck inEvalCoord2f(2.0, 1.0);
308*c2c66affSColin Finck inEvalCoord2f(3.0, 2.0);
309*c2c66affSColin Finck inEvalCoord2f(3.0, 1.0);
310*c2c66affSColin Finck endCallBack();
311*c2c66affSColin Finck }
312*c2c66affSColin Finck */
313*c2c66affSColin Finck if(  global_ev_u1 ==1 &&   global_ev_u2 == 2
314*c2c66affSColin Finck   && global_ev_v1 ==2 &&   global_ev_v2 == 3)
315*c2c66affSColin Finck {
316*c2c66affSColin Finck #ifdef DEBUG
317*c2c66affSColin Finck printf("***number 3\n");
318*c2c66affSColin Finck #endif
319*c2c66affSColin Finck beginCallBack(GL_QUAD_STRIP, NULL);
320*c2c66affSColin Finck inEvalCoord2f(2.0, 3.0);
321*c2c66affSColin Finck inEvalCoord2f(1.0, 3.0);
322*c2c66affSColin Finck inEvalCoord2f(2.0, 2.3);
323*c2c66affSColin Finck inEvalCoord2f(1.0, 2.3);
324*c2c66affSColin Finck inEvalCoord2f(2.0, 2.0);
325*c2c66affSColin Finck inEvalCoord2f(1.0, 2.0);
326*c2c66affSColin Finck endCallBack(NULL);
327*c2c66affSColin Finck 
328*c2c66affSColin Finck beginCallBack(GL_TRIANGLE_STRIP, NULL);
329*c2c66affSColin Finck inEvalCoord2f(2.0, 2.3);
330*c2c66affSColin Finck inEvalCoord2f(2.0, 2.0);
331*c2c66affSColin Finck inEvalCoord2f(2.0, 3.0);
332*c2c66affSColin Finck endCallBack(NULL);
333*c2c66affSColin Finck 
334*c2c66affSColin Finck }
335*c2c66affSColin Finck return;
336*c2c66affSColin Finck #endif
337*c2c66affSColin Finck 
338*c2c66affSColin Finck   k=0;
339*c2c66affSColin Finck   l=0;
340*c2c66affSColin Finck 
341*c2c66affSColin Finck   for(i=0; i<bpm->index_length_array; i++)
342*c2c66affSColin Finck     {
343*c2c66affSColin Finck       beginCallBack(bpm->type_array[i], userData);
344*c2c66affSColin Finck       for(j=0; j<bpm->length_array[i]; j++)
345*c2c66affSColin Finck 	{
346*c2c66affSColin Finck 	  u = bpm->UVarray[k];
347*c2c66affSColin Finck 	  v = bpm->UVarray[k+1];
348*c2c66affSColin Finck 	  inDoEvalCoord2NOGE(u,v,
349*c2c66affSColin Finck 			     bpm->vertex_array+l,
350*c2c66affSColin Finck 			     bpm->normal_array+l);
351*c2c66affSColin Finck 
352*c2c66affSColin Finck 	  normalCallBack(bpm->normal_array+l, userData);
353*c2c66affSColin Finck 	  vertexCallBack(bpm->vertex_array+l, userData);
354*c2c66affSColin Finck 
355*c2c66affSColin Finck 	  k += 2;
356*c2c66affSColin Finck 	  l += 3;
357*c2c66affSColin Finck 	}
358*c2c66affSColin Finck       endCallBack(userData);
359*c2c66affSColin Finck     }
360*c2c66affSColin Finck }
361*c2c66affSColin Finck 
inEvalPoint2(int i,int j)362*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inEvalPoint2(int i, int j)
363*c2c66affSColin Finck {
364*c2c66affSColin Finck   REAL du, dv;
365*c2c66affSColin Finck   REAL point[4];
366*c2c66affSColin Finck   REAL normal[3];
367*c2c66affSColin Finck   REAL u,v;
368*c2c66affSColin Finck   du = (global_grid_u1 - global_grid_u0) / (REAL)global_grid_nu;
369*c2c66affSColin Finck   dv = (global_grid_v1 - global_grid_v0) / (REAL)global_grid_nv;
370*c2c66affSColin Finck   u = (i==global_grid_nu)? global_grid_u1:(global_grid_u0 + i*du);
371*c2c66affSColin Finck   v = (j == global_grid_nv)? global_grid_v1: (global_grid_v0 +j*dv);
372*c2c66affSColin Finck   inDoEvalCoord2(u,v,point,normal);
373*c2c66affSColin Finck }
374*c2c66affSColin Finck 
inEvalCoord2f(REAL u,REAL v)375*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inEvalCoord2f(REAL u, REAL v)
376*c2c66affSColin Finck {
377*c2c66affSColin Finck 
378*c2c66affSColin Finck   REAL point[4];
379*c2c66affSColin Finck   REAL normal[3];
380*c2c66affSColin Finck   inDoEvalCoord2(u,v,point, normal);
381*c2c66affSColin Finck }
382*c2c66affSColin Finck 
383*c2c66affSColin Finck 
384*c2c66affSColin Finck 
385*c2c66affSColin Finck /*define a grid. store the values into the global variabls:
386*c2c66affSColin Finck  * global_grid_*
387*c2c66affSColin Finck  *These values will be used later by evaluating functions
388*c2c66affSColin Finck  */
inMapGrid2f(int nu,REAL u0,REAL u1,int nv,REAL v0,REAL v1)389*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inMapGrid2f(int nu, REAL u0, REAL u1,
390*c2c66affSColin Finck 		 int nv, REAL v0, REAL v1)
391*c2c66affSColin Finck {
392*c2c66affSColin Finck  global_grid_u0 = u0;
393*c2c66affSColin Finck  global_grid_u1 = u1;
394*c2c66affSColin Finck  global_grid_nu = nu;
395*c2c66affSColin Finck  global_grid_v0 = v0;
396*c2c66affSColin Finck  global_grid_v1 = v1;
397*c2c66affSColin Finck  global_grid_nv = nv;
398*c2c66affSColin Finck }
399*c2c66affSColin Finck 
inEvalMesh2(int lowU,int lowV,int highU,int highV)400*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inEvalMesh2(int lowU, int lowV, int highU, int highV)
401*c2c66affSColin Finck {
402*c2c66affSColin Finck   REAL du, dv;
403*c2c66affSColin Finck   int i,j;
404*c2c66affSColin Finck   REAL point[4];
405*c2c66affSColin Finck   REAL normal[3];
406*c2c66affSColin Finck   if(global_grid_nu == 0 || global_grid_nv == 0)
407*c2c66affSColin Finck     return; /*no points need to be output*/
408*c2c66affSColin Finck   du = (global_grid_u1 - global_grid_u0) / (REAL)global_grid_nu;
409*c2c66affSColin Finck   dv = (global_grid_v1 - global_grid_v0) / (REAL)global_grid_nv;
410*c2c66affSColin Finck 
411*c2c66affSColin Finck   if(global_grid_nu >= global_grid_nv){
412*c2c66affSColin Finck     for(i=lowU; i<highU; i++){
413*c2c66affSColin Finck       REAL u1 = (i==global_grid_nu)? global_grid_u1:(global_grid_u0 + i*du);
414*c2c66affSColin Finck       REAL u2 = ((i+1) == global_grid_nu)? global_grid_u1: (global_grid_u0+(i+1)*du);
415*c2c66affSColin Finck 
416*c2c66affSColin Finck       bgnqstrip();
417*c2c66affSColin Finck       for(j=highV; j>=lowV; j--){
418*c2c66affSColin Finck 	REAL v1 = (j == global_grid_nv)? global_grid_v1: (global_grid_v0 +j*dv);
419*c2c66affSColin Finck 
420*c2c66affSColin Finck 	inDoEvalCoord2(u1, v1, point, normal);
421*c2c66affSColin Finck 	inDoEvalCoord2(u2, v1, point, normal);
422*c2c66affSColin Finck       }
423*c2c66affSColin Finck       endqstrip();
424*c2c66affSColin Finck     }
425*c2c66affSColin Finck   }
426*c2c66affSColin Finck 
427*c2c66affSColin Finck   else{
428*c2c66affSColin Finck     for(i=lowV; i<highV; i++){
429*c2c66affSColin Finck       REAL v1 = (i==global_grid_nv)? global_grid_v1:(global_grid_v0 + i*dv);
430*c2c66affSColin Finck       REAL v2 = ((i+1) == global_grid_nv)? global_grid_v1: (global_grid_v0+(i+1)*dv);
431*c2c66affSColin Finck 
432*c2c66affSColin Finck       bgnqstrip();
433*c2c66affSColin Finck       for(j=highU; j>=lowU; j--){
434*c2c66affSColin Finck 	REAL u1 = (j == global_grid_nu)? global_grid_u1: (global_grid_u0 +j*du);
435*c2c66affSColin Finck 	inDoEvalCoord2(u1, v2, point, normal);
436*c2c66affSColin Finck 	inDoEvalCoord2(u1, v1, point, normal);
437*c2c66affSColin Finck       }
438*c2c66affSColin Finck       endqstrip();
439*c2c66affSColin Finck     }
440*c2c66affSColin Finck   }
441*c2c66affSColin Finck 
442*c2c66affSColin Finck }
443*c2c66affSColin Finck 
inMap2f(int k,REAL ulower,REAL uupper,int ustride,int uorder,REAL vlower,REAL vupper,int vstride,int vorder,REAL * ctlPoints)444*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inMap2f(int k,
445*c2c66affSColin Finck 	     REAL ulower,
446*c2c66affSColin Finck 	     REAL uupper,
447*c2c66affSColin Finck 	     int ustride,
448*c2c66affSColin Finck 	     int uorder,
449*c2c66affSColin Finck 	     REAL vlower,
450*c2c66affSColin Finck 	     REAL vupper,
451*c2c66affSColin Finck 	     int vstride,
452*c2c66affSColin Finck 	     int vorder,
453*c2c66affSColin Finck 	     REAL *ctlPoints)
454*c2c66affSColin Finck {
455*c2c66affSColin Finck   int i,j,x;
456*c2c66affSColin Finck   REAL *data = global_ev_ctlPoints;
457*c2c66affSColin Finck 
458*c2c66affSColin Finck 
459*c2c66affSColin Finck 
460*c2c66affSColin Finck   if(k == GL_MAP2_VERTEX_3) k=3;
461*c2c66affSColin Finck   else if (k==GL_MAP2_VERTEX_4) k =4;
462*c2c66affSColin Finck   else {
463*c2c66affSColin Finck     printf("error in inMap2f, maptype=%i is wrong, k,map is not updated\n", k);
464*c2c66affSColin Finck     return;
465*c2c66affSColin Finck   }
466*c2c66affSColin Finck 
467*c2c66affSColin Finck   global_ev_k = k;
468*c2c66affSColin Finck   global_ev_u1 = ulower;
469*c2c66affSColin Finck   global_ev_u2 = uupper;
470*c2c66affSColin Finck   global_ev_ustride = ustride;
471*c2c66affSColin Finck   global_ev_uorder = uorder;
472*c2c66affSColin Finck   global_ev_v1 = vlower;
473*c2c66affSColin Finck   global_ev_v2 = vupper;
474*c2c66affSColin Finck   global_ev_vstride = vstride;
475*c2c66affSColin Finck   global_ev_vorder = vorder;
476*c2c66affSColin Finck 
477*c2c66affSColin Finck   /*copy the contrl points from ctlPoints to global_ev_ctlPoints*/
478*c2c66affSColin Finck   for (i=0; i<uorder; i++) {
479*c2c66affSColin Finck     for (j=0; j<vorder; j++) {
480*c2c66affSColin Finck       for (x=0; x<k; x++) {
481*c2c66affSColin Finck 	data[x] = ctlPoints[x];
482*c2c66affSColin Finck       }
483*c2c66affSColin Finck       ctlPoints += vstride;
484*c2c66affSColin Finck       data += k;
485*c2c66affSColin Finck     }
486*c2c66affSColin Finck     ctlPoints += ustride - vstride * vorder;
487*c2c66affSColin Finck   }
488*c2c66affSColin Finck 
489*c2c66affSColin Finck }
490*c2c66affSColin Finck 
491*c2c66affSColin Finck 
492*c2c66affSColin Finck /*
493*c2c66affSColin Finck  *given a point p with homegeneous coordiante (x,y,z,w),
494*c2c66affSColin Finck  *let pu(x,y,z,w) be its partial derivative vector with
495*c2c66affSColin Finck  *respect to u
496*c2c66affSColin Finck  *and pv(x,y,z,w) be its partial derivative vector with repect to v.
497*c2c66affSColin Finck  *This function returns the partial derivative vectors of the
498*c2c66affSColin Finck  *inhomegensous coordinates, i.e.,
499*c2c66affSColin Finck  * (x/w, y/w, z/w) with respect to u and v.
500*c2c66affSColin Finck  */
inComputeFirstPartials(REAL * p,REAL * pu,REAL * pv)501*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inComputeFirstPartials(REAL *p, REAL *pu, REAL *pv)
502*c2c66affSColin Finck {
503*c2c66affSColin Finck     pu[0] = pu[0]*p[3] - pu[3]*p[0];
504*c2c66affSColin Finck     pu[1] = pu[1]*p[3] - pu[3]*p[1];
505*c2c66affSColin Finck     pu[2] = pu[2]*p[3] - pu[3]*p[2];
506*c2c66affSColin Finck 
507*c2c66affSColin Finck     pv[0] = pv[0]*p[3] - pv[3]*p[0];
508*c2c66affSColin Finck     pv[1] = pv[1]*p[3] - pv[3]*p[1];
509*c2c66affSColin Finck     pv[2] = pv[2]*p[3] - pv[3]*p[2];
510*c2c66affSColin Finck }
511*c2c66affSColin Finck 
512*c2c66affSColin Finck /*compute the cross product of pu and pv and normalize.
513*c2c66affSColin Finck  *the normal is returned in retNormal
514*c2c66affSColin Finck  * pu: dimension 3
515*c2c66affSColin Finck  * pv: dimension 3
516*c2c66affSColin Finck  * n: return normal, of dimension 3
517*c2c66affSColin Finck  */
inComputeNormal2(REAL * pu,REAL * pv,REAL * n)518*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inComputeNormal2(REAL *pu, REAL *pv, REAL *n)
519*c2c66affSColin Finck {
520*c2c66affSColin Finck   REAL mag;
521*c2c66affSColin Finck 
522*c2c66affSColin Finck   n[0] = pu[1]*pv[2] - pu[2]*pv[1];
523*c2c66affSColin Finck   n[1] = pu[2]*pv[0] - pu[0]*pv[2];
524*c2c66affSColin Finck   n[2] = pu[0]*pv[1] - pu[1]*pv[0];
525*c2c66affSColin Finck 
526*c2c66affSColin Finck   mag = sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
527*c2c66affSColin Finck 
528*c2c66affSColin Finck   if (mag > 0.0) {
529*c2c66affSColin Finck      n[0] /= mag;
530*c2c66affSColin Finck      n[1] /= mag;
531*c2c66affSColin Finck      n[2] /= mag;
532*c2c66affSColin Finck   }
533*c2c66affSColin Finck }
534*c2c66affSColin Finck 
535*c2c66affSColin Finck 
536*c2c66affSColin Finck 
537*c2c66affSColin Finck /*Compute point and normal
538*c2c66affSColin Finck  *see the head of inDoDomain2WithDerivs
539*c2c66affSColin Finck  *for the meaning of the arguments
540*c2c66affSColin Finck  */
inDoEvalCoord2(REAL u,REAL v,REAL * retPoint,REAL * retNormal)541*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inDoEvalCoord2(REAL u, REAL v,
542*c2c66affSColin Finck 			   REAL *retPoint, REAL *retNormal)
543*c2c66affSColin Finck {
544*c2c66affSColin Finck 
545*c2c66affSColin Finck   REAL du[4];
546*c2c66affSColin Finck   REAL dv[4];
547*c2c66affSColin Finck 
548*c2c66affSColin Finck 
549*c2c66affSColin Finck   assert(global_ev_k>=3 && global_ev_k <= 4);
550*c2c66affSColin Finck   /*compute homegeneous point and partial derivatives*/
551*c2c66affSColin Finck   inDoDomain2WithDerivs(global_ev_k, u, v, global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, retPoint, du, dv);
552*c2c66affSColin Finck 
553*c2c66affSColin Finck #ifdef AVOID_ZERO_NORMAL
554*c2c66affSColin Finck 
555*c2c66affSColin Finck   if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
556*c2c66affSColin Finck     {
557*c2c66affSColin Finck 
558*c2c66affSColin Finck       REAL tempdu[4];
559*c2c66affSColin Finck       REAL tempdata[4];
560*c2c66affSColin Finck       REAL u1 = global_ev_u1;
561*c2c66affSColin Finck       REAL u2 = global_ev_u2;
562*c2c66affSColin Finck       if(u-MYDELTA*(u2-u1) < u1)
563*c2c66affSColin Finck 	u = u+ MYDELTA*(u2-u1);
564*c2c66affSColin Finck       else
565*c2c66affSColin Finck 	u = u-MYDELTA*(u2-u1);
566*c2c66affSColin Finck       inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, tempdu, dv);
567*c2c66affSColin Finck     }
568*c2c66affSColin Finck   if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
569*c2c66affSColin Finck     {
570*c2c66affSColin Finck       REAL tempdv[4];
571*c2c66affSColin Finck       REAL tempdata[4];
572*c2c66affSColin Finck       REAL v1 = global_ev_v1;
573*c2c66affSColin Finck       REAL v2 = global_ev_v2;
574*c2c66affSColin Finck       if(v-MYDELTA*(v2-v1) < v1)
575*c2c66affSColin Finck 	v = v+ MYDELTA*(v2-v1);
576*c2c66affSColin Finck       else
577*c2c66affSColin Finck 	v = v-MYDELTA*(v2-v1);
578*c2c66affSColin Finck       inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, du, tempdv);
579*c2c66affSColin Finck     }
580*c2c66affSColin Finck #endif
581*c2c66affSColin Finck 
582*c2c66affSColin Finck 
583*c2c66affSColin Finck   /*compute normal*/
584*c2c66affSColin Finck   switch(global_ev_k){
585*c2c66affSColin Finck   case 3:
586*c2c66affSColin Finck     inComputeNormal2(du, dv, retNormal);
587*c2c66affSColin Finck 
588*c2c66affSColin Finck     break;
589*c2c66affSColin Finck   case 4:
590*c2c66affSColin Finck     inComputeFirstPartials(retPoint, du, dv);
591*c2c66affSColin Finck     inComputeNormal2(du, dv, retNormal);
592*c2c66affSColin Finck     /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
593*c2c66affSColin Finck     retPoint[0] /= retPoint[3];
594*c2c66affSColin Finck     retPoint[1] /= retPoint[3];
595*c2c66affSColin Finck     retPoint[2] /= retPoint[3];
596*c2c66affSColin Finck     break;
597*c2c66affSColin Finck   }
598*c2c66affSColin Finck   /*output this vertex*/
599*c2c66affSColin Finck /*  inMeshStreamInsert(global_ms, retPoint, retNormal);*/
600*c2c66affSColin Finck 
601*c2c66affSColin Finck 
602*c2c66affSColin Finck 
603*c2c66affSColin Finck   glNormal3fv(retNormal);
604*c2c66affSColin Finck   glVertex3fv(retPoint);
605*c2c66affSColin Finck 
606*c2c66affSColin Finck 
607*c2c66affSColin Finck 
608*c2c66affSColin Finck 
609*c2c66affSColin Finck   #ifdef DEBUG
610*c2c66affSColin Finck   printf("vertex(%f,%f,%f)\n", retPoint[0],retPoint[1],retPoint[2]);
611*c2c66affSColin Finck   #endif
612*c2c66affSColin Finck 
613*c2c66affSColin Finck 
614*c2c66affSColin Finck 
615*c2c66affSColin Finck }
616*c2c66affSColin Finck 
617*c2c66affSColin Finck /*Compute point and normal
618*c2c66affSColin Finck  *see the head of inDoDomain2WithDerivs
619*c2c66affSColin Finck  *for the meaning of the arguments
620*c2c66affSColin Finck  */
inDoEvalCoord2NOGE_BU(REAL u,REAL v,REAL * retPoint,REAL * retNormal)621*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inDoEvalCoord2NOGE_BU(REAL u, REAL v,
622*c2c66affSColin Finck 			   REAL *retPoint, REAL *retNormal)
623*c2c66affSColin Finck {
624*c2c66affSColin Finck 
625*c2c66affSColin Finck   REAL du[4];
626*c2c66affSColin Finck   REAL dv[4];
627*c2c66affSColin Finck 
628*c2c66affSColin Finck 
629*c2c66affSColin Finck   assert(global_ev_k>=3 && global_ev_k <= 4);
630*c2c66affSColin Finck   /*compute homegeneous point and partial derivatives*/
631*c2c66affSColin Finck //   inPreEvaluateBU(global_ev_k, global_ev_uorder, global_ev_vorder, (u-global_ev_u1)/(global_ev_u2-global_ev_u1), global_ev_ctlPoints);
632*c2c66affSColin Finck   inDoDomain2WithDerivsBU(global_ev_k, u, v, global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, retPoint, du, dv);
633*c2c66affSColin Finck 
634*c2c66affSColin Finck 
635*c2c66affSColin Finck #ifdef AVOID_ZERO_NORMAL
636*c2c66affSColin Finck 
637*c2c66affSColin Finck   if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
638*c2c66affSColin Finck     {
639*c2c66affSColin Finck 
640*c2c66affSColin Finck       REAL tempdu[4];
641*c2c66affSColin Finck       REAL tempdata[4];
642*c2c66affSColin Finck       REAL u1 = global_ev_u1;
643*c2c66affSColin Finck       REAL u2 = global_ev_u2;
644*c2c66affSColin Finck       if(u-MYDELTA*(u2-u1) < u1)
645*c2c66affSColin Finck 	u = u+ MYDELTA*(u2-u1);
646*c2c66affSColin Finck       else
647*c2c66affSColin Finck 	u = u-MYDELTA*(u2-u1);
648*c2c66affSColin Finck       inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, tempdu, dv);
649*c2c66affSColin Finck     }
650*c2c66affSColin Finck   if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
651*c2c66affSColin Finck     {
652*c2c66affSColin Finck       REAL tempdv[4];
653*c2c66affSColin Finck       REAL tempdata[4];
654*c2c66affSColin Finck       REAL v1 = global_ev_v1;
655*c2c66affSColin Finck       REAL v2 = global_ev_v2;
656*c2c66affSColin Finck       if(v-MYDELTA*(v2-v1) < v1)
657*c2c66affSColin Finck 	v = v+ MYDELTA*(v2-v1);
658*c2c66affSColin Finck       else
659*c2c66affSColin Finck 	v = v-MYDELTA*(v2-v1);
660*c2c66affSColin Finck       inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, du, tempdv);
661*c2c66affSColin Finck     }
662*c2c66affSColin Finck #endif
663*c2c66affSColin Finck 
664*c2c66affSColin Finck   /*compute normal*/
665*c2c66affSColin Finck   switch(global_ev_k){
666*c2c66affSColin Finck   case 3:
667*c2c66affSColin Finck     inComputeNormal2(du, dv, retNormal);
668*c2c66affSColin Finck     break;
669*c2c66affSColin Finck   case 4:
670*c2c66affSColin Finck     inComputeFirstPartials(retPoint, du, dv);
671*c2c66affSColin Finck     inComputeNormal2(du, dv, retNormal);
672*c2c66affSColin Finck     /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
673*c2c66affSColin Finck     retPoint[0] /= retPoint[3];
674*c2c66affSColin Finck     retPoint[1] /= retPoint[3];
675*c2c66affSColin Finck     retPoint[2] /= retPoint[3];
676*c2c66affSColin Finck     break;
677*c2c66affSColin Finck   }
678*c2c66affSColin Finck }
679*c2c66affSColin Finck 
680*c2c66affSColin Finck /*Compute point and normal
681*c2c66affSColin Finck  *see the head of inDoDomain2WithDerivs
682*c2c66affSColin Finck  *for the meaning of the arguments
683*c2c66affSColin Finck  */
inDoEvalCoord2NOGE_BV(REAL u,REAL v,REAL * retPoint,REAL * retNormal)684*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inDoEvalCoord2NOGE_BV(REAL u, REAL v,
685*c2c66affSColin Finck 			   REAL *retPoint, REAL *retNormal)
686*c2c66affSColin Finck {
687*c2c66affSColin Finck 
688*c2c66affSColin Finck   REAL du[4];
689*c2c66affSColin Finck   REAL dv[4];
690*c2c66affSColin Finck 
691*c2c66affSColin Finck 
692*c2c66affSColin Finck   assert(global_ev_k>=3 && global_ev_k <= 4);
693*c2c66affSColin Finck   /*compute homegeneous point and partial derivatives*/
694*c2c66affSColin Finck //   inPreEvaluateBV(global_ev_k, global_ev_uorder, global_ev_vorder, (v-global_ev_v1)/(global_ev_v2-global_ev_v1), global_ev_ctlPoints);
695*c2c66affSColin Finck 
696*c2c66affSColin Finck   inDoDomain2WithDerivsBV(global_ev_k, u, v, global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, retPoint, du, dv);
697*c2c66affSColin Finck 
698*c2c66affSColin Finck 
699*c2c66affSColin Finck #ifdef AVOID_ZERO_NORMAL
700*c2c66affSColin Finck 
701*c2c66affSColin Finck   if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
702*c2c66affSColin Finck     {
703*c2c66affSColin Finck 
704*c2c66affSColin Finck       REAL tempdu[4];
705*c2c66affSColin Finck       REAL tempdata[4];
706*c2c66affSColin Finck       REAL u1 = global_ev_u1;
707*c2c66affSColin Finck       REAL u2 = global_ev_u2;
708*c2c66affSColin Finck       if(u-MYDELTA*(u2-u1) < u1)
709*c2c66affSColin Finck 	u = u+ MYDELTA*(u2-u1);
710*c2c66affSColin Finck       else
711*c2c66affSColin Finck 	u = u-MYDELTA*(u2-u1);
712*c2c66affSColin Finck       inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, tempdu, dv);
713*c2c66affSColin Finck     }
714*c2c66affSColin Finck   if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
715*c2c66affSColin Finck     {
716*c2c66affSColin Finck       REAL tempdv[4];
717*c2c66affSColin Finck       REAL tempdata[4];
718*c2c66affSColin Finck       REAL v1 = global_ev_v1;
719*c2c66affSColin Finck       REAL v2 = global_ev_v2;
720*c2c66affSColin Finck       if(v-MYDELTA*(v2-v1) < v1)
721*c2c66affSColin Finck 	v = v+ MYDELTA*(v2-v1);
722*c2c66affSColin Finck       else
723*c2c66affSColin Finck 	v = v-MYDELTA*(v2-v1);
724*c2c66affSColin Finck       inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, du, tempdv);
725*c2c66affSColin Finck     }
726*c2c66affSColin Finck #endif
727*c2c66affSColin Finck 
728*c2c66affSColin Finck   /*compute normal*/
729*c2c66affSColin Finck   switch(global_ev_k){
730*c2c66affSColin Finck   case 3:
731*c2c66affSColin Finck     inComputeNormal2(du, dv, retNormal);
732*c2c66affSColin Finck     break;
733*c2c66affSColin Finck   case 4:
734*c2c66affSColin Finck     inComputeFirstPartials(retPoint, du, dv);
735*c2c66affSColin Finck     inComputeNormal2(du, dv, retNormal);
736*c2c66affSColin Finck     /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
737*c2c66affSColin Finck     retPoint[0] /= retPoint[3];
738*c2c66affSColin Finck     retPoint[1] /= retPoint[3];
739*c2c66affSColin Finck     retPoint[2] /= retPoint[3];
740*c2c66affSColin Finck     break;
741*c2c66affSColin Finck   }
742*c2c66affSColin Finck }
743*c2c66affSColin Finck 
744*c2c66affSColin Finck 
745*c2c66affSColin Finck /*Compute point and normal
746*c2c66affSColin Finck  *see the head of inDoDomain2WithDerivs
747*c2c66affSColin Finck  *for the meaning of the arguments
748*c2c66affSColin Finck  */
inDoEvalCoord2NOGE(REAL u,REAL v,REAL * retPoint,REAL * retNormal)749*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inDoEvalCoord2NOGE(REAL u, REAL v,
750*c2c66affSColin Finck 			   REAL *retPoint, REAL *retNormal)
751*c2c66affSColin Finck {
752*c2c66affSColin Finck 
753*c2c66affSColin Finck   REAL du[4];
754*c2c66affSColin Finck   REAL dv[4];
755*c2c66affSColin Finck 
756*c2c66affSColin Finck 
757*c2c66affSColin Finck   assert(global_ev_k>=3 && global_ev_k <= 4);
758*c2c66affSColin Finck   /*compute homegeneous point and partial derivatives*/
759*c2c66affSColin Finck   inDoDomain2WithDerivs(global_ev_k, u, v, global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, retPoint, du, dv);
760*c2c66affSColin Finck 
761*c2c66affSColin Finck 
762*c2c66affSColin Finck #ifdef AVOID_ZERO_NORMAL
763*c2c66affSColin Finck 
764*c2c66affSColin Finck   if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
765*c2c66affSColin Finck     {
766*c2c66affSColin Finck 
767*c2c66affSColin Finck       REAL tempdu[4];
768*c2c66affSColin Finck       REAL tempdata[4];
769*c2c66affSColin Finck       REAL u1 = global_ev_u1;
770*c2c66affSColin Finck       REAL u2 = global_ev_u2;
771*c2c66affSColin Finck       if(u-MYDELTA*(u2-u1) < u1)
772*c2c66affSColin Finck 	u = u+ MYDELTA*(u2-u1);
773*c2c66affSColin Finck       else
774*c2c66affSColin Finck 	u = u-MYDELTA*(u2-u1);
775*c2c66affSColin Finck       inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, tempdu, dv);
776*c2c66affSColin Finck     }
777*c2c66affSColin Finck   if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
778*c2c66affSColin Finck     {
779*c2c66affSColin Finck       REAL tempdv[4];
780*c2c66affSColin Finck       REAL tempdata[4];
781*c2c66affSColin Finck       REAL v1 = global_ev_v1;
782*c2c66affSColin Finck       REAL v2 = global_ev_v2;
783*c2c66affSColin Finck       if(v-MYDELTA*(v2-v1) < v1)
784*c2c66affSColin Finck 	v = v+ MYDELTA*(v2-v1);
785*c2c66affSColin Finck       else
786*c2c66affSColin Finck 	v = v-MYDELTA*(v2-v1);
787*c2c66affSColin Finck       inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, du, tempdv);
788*c2c66affSColin Finck     }
789*c2c66affSColin Finck #endif
790*c2c66affSColin Finck 
791*c2c66affSColin Finck   /*compute normal*/
792*c2c66affSColin Finck   switch(global_ev_k){
793*c2c66affSColin Finck   case 3:
794*c2c66affSColin Finck     inComputeNormal2(du, dv, retNormal);
795*c2c66affSColin Finck     break;
796*c2c66affSColin Finck   case 4:
797*c2c66affSColin Finck     inComputeFirstPartials(retPoint, du, dv);
798*c2c66affSColin Finck     inComputeNormal2(du, dv, retNormal);
799*c2c66affSColin Finck     /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
800*c2c66affSColin Finck     retPoint[0] /= retPoint[3];
801*c2c66affSColin Finck     retPoint[1] /= retPoint[3];
802*c2c66affSColin Finck     retPoint[2] /= retPoint[3];
803*c2c66affSColin Finck     break;
804*c2c66affSColin Finck   }
805*c2c66affSColin Finck //  glNormal3fv(retNormal);
806*c2c66affSColin Finck //  glVertex3fv(retPoint);
807*c2c66affSColin Finck }
808*c2c66affSColin Finck 
inPreEvaluateBV(int k,int uorder,int vorder,REAL vprime,REAL * baseData)809*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inPreEvaluateBV(int k, int uorder, int vorder, REAL vprime, REAL *baseData)
810*c2c66affSColin Finck {
811*c2c66affSColin Finck   int j,row,col;
812*c2c66affSColin Finck   REAL p, pdv;
813*c2c66affSColin Finck   REAL *data;
814*c2c66affSColin Finck 
815*c2c66affSColin Finck   if(global_vprime != vprime || global_vorder != vorder) {
816*c2c66affSColin Finck     inPreEvaluateWithDeriv(vorder, vprime, global_vcoeff, global_vcoeffDeriv);
817*c2c66affSColin Finck     global_vprime = vprime;
818*c2c66affSColin Finck     global_vorder = vorder;
819*c2c66affSColin Finck   }
820*c2c66affSColin Finck 
821*c2c66affSColin Finck   for(j=0; j<k; j++){
822*c2c66affSColin Finck     data = baseData+j;
823*c2c66affSColin Finck     for(row=0; row<uorder; row++){
824*c2c66affSColin Finck       p = global_vcoeff[0] * (*data);
825*c2c66affSColin Finck       pdv = global_vcoeffDeriv[0] * (*data);
826*c2c66affSColin Finck       data += k;
827*c2c66affSColin Finck       for(col = 1; col < vorder; col++){
828*c2c66affSColin Finck 	p += global_vcoeff[col] *  (*data);
829*c2c66affSColin Finck 	pdv += global_vcoeffDeriv[col] * (*data);
830*c2c66affSColin Finck 	data += k;
831*c2c66affSColin Finck       }
832*c2c66affSColin Finck       global_BV[row][j]  = p;
833*c2c66affSColin Finck       global_PBV[row][j]  = pdv;
834*c2c66affSColin Finck     }
835*c2c66affSColin Finck   }
836*c2c66affSColin Finck }
837*c2c66affSColin Finck 
inPreEvaluateBU(int k,int uorder,int vorder,REAL uprime,REAL * baseData)838*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inPreEvaluateBU(int k, int uorder, int vorder, REAL uprime, REAL *baseData)
839*c2c66affSColin Finck {
840*c2c66affSColin Finck   int j,row,col;
841*c2c66affSColin Finck   REAL p, pdu;
842*c2c66affSColin Finck   REAL *data;
843*c2c66affSColin Finck 
844*c2c66affSColin Finck   if(global_uprime != uprime || global_uorder != uorder) {
845*c2c66affSColin Finck     inPreEvaluateWithDeriv(uorder, uprime, global_ucoeff, global_ucoeffDeriv);
846*c2c66affSColin Finck     global_uprime = uprime;
847*c2c66affSColin Finck     global_uorder = uorder;
848*c2c66affSColin Finck   }
849*c2c66affSColin Finck 
850*c2c66affSColin Finck   for(j=0; j<k; j++){
851*c2c66affSColin Finck     data = baseData+j;
852*c2c66affSColin Finck     for(col=0; col<vorder; col++){
853*c2c66affSColin Finck       data = baseData+j + k*col;
854*c2c66affSColin Finck       p = global_ucoeff[0] * (*data);
855*c2c66affSColin Finck       pdu = global_ucoeffDeriv[0] * (*data);
856*c2c66affSColin Finck       data += k*uorder;
857*c2c66affSColin Finck       for(row = 1; row < uorder; row++){
858*c2c66affSColin Finck 	p += global_ucoeff[row] *  (*data);
859*c2c66affSColin Finck 	pdu += global_ucoeffDeriv[row] * (*data);
860*c2c66affSColin Finck 	data += k * uorder;
861*c2c66affSColin Finck       }
862*c2c66affSColin Finck       global_BU[col][j]  = p;
863*c2c66affSColin Finck       global_PBU[col][j]  = pdu;
864*c2c66affSColin Finck     }
865*c2c66affSColin Finck   }
866*c2c66affSColin Finck }
867*c2c66affSColin Finck 
inDoDomain2WithDerivsBU(int k,REAL u,REAL v,REAL u1,REAL u2,int uorder,REAL v1,REAL v2,int vorder,REAL * baseData,REAL * retPoint,REAL * retdu,REAL * retdv)868*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inDoDomain2WithDerivsBU(int k, REAL u, REAL v,
869*c2c66affSColin Finck 						      REAL u1, REAL u2, int uorder,
870*c2c66affSColin Finck 						      REAL v1, REAL v2, int vorder,
871*c2c66affSColin Finck 						      REAL *baseData,
872*c2c66affSColin Finck 						      REAL *retPoint, REAL* retdu, REAL *retdv)
873*c2c66affSColin Finck {
874*c2c66affSColin Finck   int j, col;
875*c2c66affSColin Finck 
876*c2c66affSColin Finck   REAL vprime;
877*c2c66affSColin Finck 
878*c2c66affSColin Finck 
879*c2c66affSColin Finck   if((u2 == u1) || (v2 == v1))
880*c2c66affSColin Finck     return;
881*c2c66affSColin Finck 
882*c2c66affSColin Finck   vprime = (v - v1) / (v2 - v1);
883*c2c66affSColin Finck 
884*c2c66affSColin Finck 
885*c2c66affSColin Finck   if(global_vprime != vprime || global_vorder != vorder) {
886*c2c66affSColin Finck     inPreEvaluateWithDeriv(vorder, vprime, global_vcoeff, global_vcoeffDeriv);
887*c2c66affSColin Finck     global_vprime = vprime;
888*c2c66affSColin Finck     global_vorder = vorder;
889*c2c66affSColin Finck   }
890*c2c66affSColin Finck 
891*c2c66affSColin Finck 
892*c2c66affSColin Finck   for(j=0; j<k; j++)
893*c2c66affSColin Finck     {
894*c2c66affSColin Finck       retPoint[j] = retdu[j] = retdv[j] = 0.0;
895*c2c66affSColin Finck       for (col = 0; col < vorder; col++)  {
896*c2c66affSColin Finck 	retPoint[j] += global_BU[col][j] * global_vcoeff[col];
897*c2c66affSColin Finck 	retdu[j] += global_PBU[col][j] * global_vcoeff[col];
898*c2c66affSColin Finck 	retdv[j] += global_BU[col][j] * global_vcoeffDeriv[col];
899*c2c66affSColin Finck       }
900*c2c66affSColin Finck     }
901*c2c66affSColin Finck }
902*c2c66affSColin Finck 
inDoDomain2WithDerivsBV(int k,REAL u,REAL v,REAL u1,REAL u2,int uorder,REAL v1,REAL v2,int vorder,REAL * baseData,REAL * retPoint,REAL * retdu,REAL * retdv)903*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inDoDomain2WithDerivsBV(int k, REAL u, REAL v,
904*c2c66affSColin Finck 						      REAL u1, REAL u2, int uorder,
905*c2c66affSColin Finck 						      REAL v1, REAL v2, int vorder,
906*c2c66affSColin Finck 						      REAL *baseData,
907*c2c66affSColin Finck 						      REAL *retPoint, REAL* retdu, REAL *retdv)
908*c2c66affSColin Finck {
909*c2c66affSColin Finck   int j, row;
910*c2c66affSColin Finck   REAL uprime;
911*c2c66affSColin Finck 
912*c2c66affSColin Finck 
913*c2c66affSColin Finck   if((u2 == u1) || (v2 == v1))
914*c2c66affSColin Finck     return;
915*c2c66affSColin Finck   uprime = (u - u1) / (u2 - u1);
916*c2c66affSColin Finck 
917*c2c66affSColin Finck 
918*c2c66affSColin Finck   if(global_uprime != uprime || global_uorder != uorder) {
919*c2c66affSColin Finck     inPreEvaluateWithDeriv(uorder, uprime, global_ucoeff, global_ucoeffDeriv);
920*c2c66affSColin Finck     global_uprime = uprime;
921*c2c66affSColin Finck     global_uorder = uorder;
922*c2c66affSColin Finck   }
923*c2c66affSColin Finck 
924*c2c66affSColin Finck 
925*c2c66affSColin Finck   for(j=0; j<k; j++)
926*c2c66affSColin Finck     {
927*c2c66affSColin Finck       retPoint[j] = retdu[j] = retdv[j] = 0.0;
928*c2c66affSColin Finck       for (row = 0; row < uorder; row++)  {
929*c2c66affSColin Finck 	retPoint[j] += global_BV[row][j] * global_ucoeff[row];
930*c2c66affSColin Finck 	retdu[j] += global_BV[row][j] * global_ucoeffDeriv[row];
931*c2c66affSColin Finck 	retdv[j] += global_PBV[row][j] * global_ucoeff[row];
932*c2c66affSColin Finck       }
933*c2c66affSColin Finck     }
934*c2c66affSColin Finck }
935*c2c66affSColin Finck 
936*c2c66affSColin Finck 
937*c2c66affSColin Finck /*
938*c2c66affSColin Finck  *given a Bezier surface, and parameter (u,v), compute the point in the object space,
939*c2c66affSColin Finck  *and the normal
940*c2c66affSColin Finck  *k: the dimension of the object space: usually 2,3,or 4.
941*c2c66affSColin Finck  *u,v: the paramter pair.
942*c2c66affSColin Finck  *u1,u2,uorder: the Bezier polynomial of u coord is defined on [u1,u2] with order uorder.
943*c2c66affSColin Finck  *v1,v2,vorder: the Bezier polynomial of v coord is defined on [v1,v2] with order vorder.
944*c2c66affSColin Finck  *baseData: contrl points. arranged as: (u,v,k).
945*c2c66affSColin Finck  *retPoint:  the computed point (one point) with dimension k.
946*c2c66affSColin Finck  *retdu: the computed partial derivative with respect to u.
947*c2c66affSColin Finck  *retdv: the computed partial derivative with respect to v.
948*c2c66affSColin Finck  */
inDoDomain2WithDerivs(int k,REAL u,REAL v,REAL u1,REAL u2,int uorder,REAL v1,REAL v2,int vorder,REAL * baseData,REAL * retPoint,REAL * retdu,REAL * retdv)949*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inDoDomain2WithDerivs(int k, REAL u, REAL v,
950*c2c66affSColin Finck 				REAL u1, REAL u2, int uorder,
951*c2c66affSColin Finck 				REAL v1,  REAL v2, int vorder,
952*c2c66affSColin Finck 				REAL *baseData,
953*c2c66affSColin Finck 				REAL *retPoint, REAL *retdu, REAL *retdv)
954*c2c66affSColin Finck {
955*c2c66affSColin Finck     int j, row, col;
956*c2c66affSColin Finck     REAL uprime;
957*c2c66affSColin Finck     REAL vprime;
958*c2c66affSColin Finck     REAL p;
959*c2c66affSColin Finck     REAL pdv;
960*c2c66affSColin Finck     REAL *data;
961*c2c66affSColin Finck 
962*c2c66affSColin Finck     if((u2 == u1) || (v2 == v1))
963*c2c66affSColin Finck 	return;
964*c2c66affSColin Finck     uprime = (u - u1) / (u2 - u1);
965*c2c66affSColin Finck     vprime = (v - v1) / (v2 - v1);
966*c2c66affSColin Finck 
967*c2c66affSColin Finck     /* Compute coefficients for values and derivs */
968*c2c66affSColin Finck 
969*c2c66affSColin Finck     /* Use already cached values if possible */
970*c2c66affSColin Finck     if(global_uprime != uprime || global_uorder != uorder) {
971*c2c66affSColin Finck         inPreEvaluateWithDeriv(uorder, uprime, global_ucoeff, global_ucoeffDeriv);
972*c2c66affSColin Finck 	global_uorder = uorder;
973*c2c66affSColin Finck 	global_uprime = uprime;
974*c2c66affSColin Finck     }
975*c2c66affSColin Finck     if (global_vprime != vprime ||
976*c2c66affSColin Finck 	  global_vorder != vorder) {
977*c2c66affSColin Finck 	inPreEvaluateWithDeriv(vorder, vprime, global_vcoeff, global_vcoeffDeriv);
978*c2c66affSColin Finck 	global_vorder = vorder;
979*c2c66affSColin Finck 	global_vprime = vprime;
980*c2c66affSColin Finck     }
981*c2c66affSColin Finck 
982*c2c66affSColin Finck     for (j = 0; j < k; j++) {
983*c2c66affSColin Finck 	data=baseData+j;
984*c2c66affSColin Finck 	retPoint[j] = retdu[j] = retdv[j] = 0.0;
985*c2c66affSColin Finck 	for (row = 0; row < uorder; row++)  {
986*c2c66affSColin Finck 	    /*
987*c2c66affSColin Finck 	    ** Minor optimization.
988*c2c66affSColin Finck 	    ** The col == 0 part of the loop is extracted so we don't
989*c2c66affSColin Finck 	    ** have to initialize p and pdv to 0.
990*c2c66affSColin Finck 	    */
991*c2c66affSColin Finck 	    p = global_vcoeff[0] * (*data);
992*c2c66affSColin Finck 	    pdv = global_vcoeffDeriv[0] * (*data);
993*c2c66affSColin Finck 	    data += k;
994*c2c66affSColin Finck 	    for (col = 1; col < vorder; col++) {
995*c2c66affSColin Finck 		/* Incrementally build up p, pdv value */
996*c2c66affSColin Finck 		p += global_vcoeff[col] * (*data);
997*c2c66affSColin Finck 		pdv += global_vcoeffDeriv[col] * (*data);
998*c2c66affSColin Finck 		data += k;
999*c2c66affSColin Finck 	    }
1000*c2c66affSColin Finck 	    /* Use p, pdv value to incrementally add up r, du, dv */
1001*c2c66affSColin Finck 	    retPoint[j] += global_ucoeff[row] * p;
1002*c2c66affSColin Finck 	    retdu[j] += global_ucoeffDeriv[row] * p;
1003*c2c66affSColin Finck 	    retdv[j] += global_ucoeff[row] * pdv;
1004*c2c66affSColin Finck 	}
1005*c2c66affSColin Finck     }
1006*c2c66affSColin Finck }
1007*c2c66affSColin Finck 
1008*c2c66affSColin Finck 
1009*c2c66affSColin Finck /*
1010*c2c66affSColin Finck  *compute the Bezier polynomials C[n,j](v) for all j at v with
1011*c2c66affSColin Finck  *return values stored in coeff[], where
1012*c2c66affSColin Finck  *  C[n,j](v) = (n,j) * v^j * (1-v)^(n-j),
1013*c2c66affSColin Finck  *  j=0,1,2,...,n.
1014*c2c66affSColin Finck  *order : n+1
1015*c2c66affSColin Finck  *vprime: v
1016*c2c66affSColin Finck  *coeff : coeff[j]=C[n,j](v), this array store the returned values.
1017*c2c66affSColin Finck  *The algorithm is a recursive scheme:
1018*c2c66affSColin Finck  *   C[0,0]=1;
1019*c2c66affSColin Finck  *   C[n,j](v) = (1-v)*C[n-1,j](v) + v*C[n-1,j-1](v), n>=1
1020*c2c66affSColin Finck  *This code is copied from opengl/soft/so_eval.c:PreEvaluate
1021*c2c66affSColin Finck  */
inPreEvaluate(int order,REAL vprime,REAL * coeff)1022*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inPreEvaluate(int order, REAL vprime, REAL *coeff)
1023*c2c66affSColin Finck {
1024*c2c66affSColin Finck   int i, j;
1025*c2c66affSColin Finck   REAL oldval, temp;
1026*c2c66affSColin Finck   REAL oneMinusvprime;
1027*c2c66affSColin Finck 
1028*c2c66affSColin Finck   /*
1029*c2c66affSColin Finck    * Minor optimization
1030*c2c66affSColin Finck    * Compute orders 1 and 2 outright, and set coeff[0], coeff[1] to
1031*c2c66affSColin Finck      * their i==1 loop values to avoid the initialization and the i==1 loop.
1032*c2c66affSColin Finck      */
1033*c2c66affSColin Finck   if (order == 1) {
1034*c2c66affSColin Finck     coeff[0] = 1.0;
1035*c2c66affSColin Finck     return;
1036*c2c66affSColin Finck   }
1037*c2c66affSColin Finck 
1038*c2c66affSColin Finck   oneMinusvprime = 1-vprime;
1039*c2c66affSColin Finck   coeff[0] = oneMinusvprime;
1040*c2c66affSColin Finck   coeff[1] = vprime;
1041*c2c66affSColin Finck   if (order == 2) return;
1042*c2c66affSColin Finck 
1043*c2c66affSColin Finck   for (i = 2; i < order; i++) {
1044*c2c66affSColin Finck     oldval = coeff[0] * vprime;
1045*c2c66affSColin Finck     coeff[0] = oneMinusvprime * coeff[0];
1046*c2c66affSColin Finck     for (j = 1; j < i; j++) {
1047*c2c66affSColin Finck       temp = oldval;
1048*c2c66affSColin Finck       oldval = coeff[j] * vprime;
1049*c2c66affSColin Finck 	    coeff[j] = temp + oneMinusvprime * coeff[j];
1050*c2c66affSColin Finck     }
1051*c2c66affSColin Finck     coeff[j] = oldval;
1052*c2c66affSColin Finck   }
1053*c2c66affSColin Finck }
1054*c2c66affSColin Finck 
1055*c2c66affSColin Finck /*
1056*c2c66affSColin Finck  *compute the Bezier polynomials C[n,j](v) and derivatives for all j at v with
1057*c2c66affSColin Finck  *return values stored in coeff[] and coeffDeriv[].
1058*c2c66affSColin Finck  *see the head of function inPreEvaluate for the definition of C[n,j](v)
1059*c2c66affSColin Finck  *and how to compute the values.
1060*c2c66affSColin Finck  *The algorithm to compute the derivative is:
1061*c2c66affSColin Finck  *   dC[0,0](v) = 0.
1062*c2c66affSColin Finck  *   dC[n,j](v) = n*(dC[n-1,j-1](v) - dC[n-1,j](v)).
1063*c2c66affSColin Finck  *
1064*c2c66affSColin Finck  *This code is copied from opengl/soft/so_eval.c:PreEvaluateWidthDeriv
1065*c2c66affSColin Finck  */
inPreEvaluateWithDeriv(int order,REAL vprime,REAL * coeff,REAL * coeffDeriv)1066*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inPreEvaluateWithDeriv(int order, REAL vprime,
1067*c2c66affSColin Finck     REAL *coeff, REAL *coeffDeriv)
1068*c2c66affSColin Finck {
1069*c2c66affSColin Finck   int i, j;
1070*c2c66affSColin Finck   REAL oldval, temp;
1071*c2c66affSColin Finck   REAL oneMinusvprime;
1072*c2c66affSColin Finck 
1073*c2c66affSColin Finck   oneMinusvprime = 1-vprime;
1074*c2c66affSColin Finck   /*
1075*c2c66affSColin Finck    * Minor optimization
1076*c2c66affSColin Finck    * Compute orders 1 and 2 outright, and set coeff[0], coeff[1] to
1077*c2c66affSColin Finck    * their i==1 loop values to avoid the initialization and the i==1 loop.
1078*c2c66affSColin Finck    */
1079*c2c66affSColin Finck   if (order == 1) {
1080*c2c66affSColin Finck     coeff[0] = 1.0;
1081*c2c66affSColin Finck     coeffDeriv[0] = 0.0;
1082*c2c66affSColin Finck     return;
1083*c2c66affSColin Finck   } else if (order == 2) {
1084*c2c66affSColin Finck     coeffDeriv[0] = -1.0;
1085*c2c66affSColin Finck     coeffDeriv[1] = 1.0;
1086*c2c66affSColin Finck     coeff[0] = oneMinusvprime;
1087*c2c66affSColin Finck     coeff[1] = vprime;
1088*c2c66affSColin Finck     return;
1089*c2c66affSColin Finck   }
1090*c2c66affSColin Finck   coeff[0] = oneMinusvprime;
1091*c2c66affSColin Finck   coeff[1] = vprime;
1092*c2c66affSColin Finck   for (i = 2; i < order - 1; i++) {
1093*c2c66affSColin Finck     oldval = coeff[0] * vprime;
1094*c2c66affSColin Finck     coeff[0] = oneMinusvprime * coeff[0];
1095*c2c66affSColin Finck     for (j = 1; j < i; j++) {
1096*c2c66affSColin Finck       temp = oldval;
1097*c2c66affSColin Finck       oldval = coeff[j] * vprime;
1098*c2c66affSColin Finck       coeff[j] = temp + oneMinusvprime * coeff[j];
1099*c2c66affSColin Finck     }
1100*c2c66affSColin Finck     coeff[j] = oldval;
1101*c2c66affSColin Finck   }
1102*c2c66affSColin Finck   coeffDeriv[0] = -coeff[0];
1103*c2c66affSColin Finck   /*
1104*c2c66affSColin Finck    ** Minor optimization:
1105*c2c66affSColin Finck    ** Would make this a "for (j=1; j<order-1; j++)" loop, but it is always
1106*c2c66affSColin Finck    ** executed at least once, so this is more efficient.
1107*c2c66affSColin Finck    */
1108*c2c66affSColin Finck   j=1;
1109*c2c66affSColin Finck   do {
1110*c2c66affSColin Finck     coeffDeriv[j] = coeff[j-1] - coeff[j];
1111*c2c66affSColin Finck     j++;
1112*c2c66affSColin Finck   } while (j < order - 1);
1113*c2c66affSColin Finck   coeffDeriv[j] = coeff[j-1];
1114*c2c66affSColin Finck 
1115*c2c66affSColin Finck   oldval = coeff[0] * vprime;
1116*c2c66affSColin Finck   coeff[0] = oneMinusvprime * coeff[0];
1117*c2c66affSColin Finck   for (j = 1; j < i; j++) {
1118*c2c66affSColin Finck     temp = oldval;
1119*c2c66affSColin Finck     oldval = coeff[j] * vprime;
1120*c2c66affSColin Finck     coeff[j] = temp + oneMinusvprime * coeff[j];
1121*c2c66affSColin Finck   }
1122*c2c66affSColin Finck   coeff[j] = oldval;
1123*c2c66affSColin Finck }
1124*c2c66affSColin Finck 
inEvalULine(int n_points,REAL v,REAL * u_vals,int stride,REAL ret_points[][3],REAL ret_normals[][3])1125*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inEvalULine(int n_points, REAL v, REAL* u_vals,
1126*c2c66affSColin Finck 	int stride, REAL ret_points[][3], REAL ret_normals[][3])
1127*c2c66affSColin Finck {
1128*c2c66affSColin Finck   int i,k;
1129*c2c66affSColin Finck   REAL temp[4];
1130*c2c66affSColin Finck inPreEvaluateBV_intfac(v);
1131*c2c66affSColin Finck 
1132*c2c66affSColin Finck   for(i=0,k=0; i<n_points; i++, k += stride)
1133*c2c66affSColin Finck     {
1134*c2c66affSColin Finck       inDoEvalCoord2NOGE_BV(u_vals[k],v,temp, ret_normals[i]);
1135*c2c66affSColin Finck 
1136*c2c66affSColin Finck       ret_points[i][0] = temp[0];
1137*c2c66affSColin Finck       ret_points[i][1] = temp[1];
1138*c2c66affSColin Finck       ret_points[i][2] = temp[2];
1139*c2c66affSColin Finck 
1140*c2c66affSColin Finck     }
1141*c2c66affSColin Finck 
1142*c2c66affSColin Finck }
1143*c2c66affSColin Finck 
inEvalVLine(int n_points,REAL u,REAL * v_vals,int stride,REAL ret_points[][3],REAL ret_normals[][3])1144*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inEvalVLine(int n_points, REAL u, REAL* v_vals,
1145*c2c66affSColin Finck 	int stride, REAL ret_points[][3], REAL ret_normals[][3])
1146*c2c66affSColin Finck {
1147*c2c66affSColin Finck   int i,k;
1148*c2c66affSColin Finck   REAL temp[4];
1149*c2c66affSColin Finck inPreEvaluateBU_intfac(u);
1150*c2c66affSColin Finck   for(i=0,k=0; i<n_points; i++, k += stride)
1151*c2c66affSColin Finck     {
1152*c2c66affSColin Finck       inDoEvalCoord2NOGE_BU(u, v_vals[k], temp, ret_normals[i]);
1153*c2c66affSColin Finck       ret_points[i][0] = temp[0];
1154*c2c66affSColin Finck       ret_points[i][1] = temp[1];
1155*c2c66affSColin Finck       ret_points[i][2] = temp[2];
1156*c2c66affSColin Finck     }
1157*c2c66affSColin Finck }
1158*c2c66affSColin Finck 
1159*c2c66affSColin Finck 
1160*c2c66affSColin Finck /*triangulate a strip bounded by two lines which are parallel  to U-axis
1161*c2c66affSColin Finck  *upperVerts: the verteces on the upper line
1162*c2c66affSColin Finck  *lowerVertx: the verteces on the lower line
1163*c2c66affSColin Finck  *n_upper >=1
1164*c2c66affSColin Finck  *n_lower >=1
1165*c2c66affSColin Finck  */
inEvalUStrip(int n_upper,REAL v_upper,REAL * upper_val,int n_lower,REAL v_lower,REAL * lower_val)1166*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inEvalUStrip(int n_upper, REAL v_upper, REAL* upper_val, int n_lower, REAL v_lower, REAL* lower_val)
1167*c2c66affSColin Finck {
1168*c2c66affSColin Finck   int i,j,k,l;
1169*c2c66affSColin Finck   REAL leftMostV[2];
1170*c2c66affSColin Finck  typedef REAL REAL3[3];
1171*c2c66affSColin Finck 
1172*c2c66affSColin Finck   REAL3* upperXYZ = (REAL3*) malloc(sizeof(REAL3)*n_upper);
1173*c2c66affSColin Finck   assert(upperXYZ);
1174*c2c66affSColin Finck   REAL3* upperNormal = (REAL3*) malloc(sizeof(REAL3) * n_upper);
1175*c2c66affSColin Finck   assert(upperNormal);
1176*c2c66affSColin Finck   REAL3* lowerXYZ = (REAL3*) malloc(sizeof(REAL3)*n_lower);
1177*c2c66affSColin Finck   assert(lowerXYZ);
1178*c2c66affSColin Finck   REAL3* lowerNormal = (REAL3*) malloc(sizeof(REAL3) * n_lower);
1179*c2c66affSColin Finck   assert(lowerNormal);
1180*c2c66affSColin Finck 
1181*c2c66affSColin Finck   inEvalULine(n_upper, v_upper, upper_val,  1, upperXYZ, upperNormal);
1182*c2c66affSColin Finck   inEvalULine(n_lower, v_lower, lower_val,  1, lowerXYZ, lowerNormal);
1183*c2c66affSColin Finck 
1184*c2c66affSColin Finck 
1185*c2c66affSColin Finck 
1186*c2c66affSColin Finck   REAL* leftMostXYZ;
1187*c2c66affSColin Finck   REAL* leftMostNormal;
1188*c2c66affSColin Finck 
1189*c2c66affSColin Finck   /*
1190*c2c66affSColin Finck    *the algorithm works by scanning from left to right.
1191*c2c66affSColin Finck    *leftMostV: the left most of the remaining verteces (on both upper and lower).
1192*c2c66affSColin Finck    *           it could an element of upperVerts or lowerVerts.
1193*c2c66affSColin Finck    *i: upperVerts[i] is the first vertex to the right of leftMostV on upper line   *j: lowerVerts[j] is the first vertex to the right of leftMostV on lower line   */
1194*c2c66affSColin Finck 
1195*c2c66affSColin Finck   /*initialize i,j,and leftMostV
1196*c2c66affSColin Finck    */
1197*c2c66affSColin Finck   if(upper_val[0] <= lower_val[0])
1198*c2c66affSColin Finck     {
1199*c2c66affSColin Finck       i=1;
1200*c2c66affSColin Finck       j=0;
1201*c2c66affSColin Finck 
1202*c2c66affSColin Finck       leftMostV[0] = upper_val[0];
1203*c2c66affSColin Finck       leftMostV[1] = v_upper;
1204*c2c66affSColin Finck       leftMostXYZ = upperXYZ[0];
1205*c2c66affSColin Finck       leftMostNormal = upperNormal[0];
1206*c2c66affSColin Finck     }
1207*c2c66affSColin Finck   else
1208*c2c66affSColin Finck     {
1209*c2c66affSColin Finck       i=0;
1210*c2c66affSColin Finck       j=1;
1211*c2c66affSColin Finck 
1212*c2c66affSColin Finck       leftMostV[0] = lower_val[0];
1213*c2c66affSColin Finck       leftMostV[1] = v_lower;
1214*c2c66affSColin Finck 
1215*c2c66affSColin Finck       leftMostXYZ = lowerXYZ[0];
1216*c2c66affSColin Finck       leftMostNormal = lowerNormal[0];
1217*c2c66affSColin Finck     }
1218*c2c66affSColin Finck 
1219*c2c66affSColin Finck   /*the main loop.
1220*c2c66affSColin Finck    *the invariance is that:
1221*c2c66affSColin Finck    *at the beginning of each loop, the meaning of i,j,and leftMostV are
1222*c2c66affSColin Finck    *maintained
1223*c2c66affSColin Finck    */
1224*c2c66affSColin Finck   while(1)
1225*c2c66affSColin Finck     {
1226*c2c66affSColin Finck       if(i >= n_upper) /*case1: no more in upper*/
1227*c2c66affSColin Finck         {
1228*c2c66affSColin Finck           if(j<n_lower-1) /*at least two vertices in lower*/
1229*c2c66affSColin Finck             {
1230*c2c66affSColin Finck               bgntfan();
1231*c2c66affSColin Finck 	      glNormal3fv(leftMostNormal);
1232*c2c66affSColin Finck               glVertex3fv(leftMostXYZ);
1233*c2c66affSColin Finck 
1234*c2c66affSColin Finck               while(j<n_lower){
1235*c2c66affSColin Finck 		glNormal3fv(lowerNormal[j]);
1236*c2c66affSColin Finck 		glVertex3fv(lowerXYZ[j]);
1237*c2c66affSColin Finck 		j++;
1238*c2c66affSColin Finck 
1239*c2c66affSColin Finck               }
1240*c2c66affSColin Finck               endtfan();
1241*c2c66affSColin Finck             }
1242*c2c66affSColin Finck           break; /*exit the main loop*/
1243*c2c66affSColin Finck         }
1244*c2c66affSColin Finck       else if(j>= n_lower) /*case2: no more in lower*/
1245*c2c66affSColin Finck         {
1246*c2c66affSColin Finck           if(i<n_upper-1) /*at least two vertices in upper*/
1247*c2c66affSColin Finck             {
1248*c2c66affSColin Finck               bgntfan();
1249*c2c66affSColin Finck 	      glNormal3fv(leftMostNormal);
1250*c2c66affSColin Finck 	      glVertex3fv(leftMostXYZ);
1251*c2c66affSColin Finck 
1252*c2c66affSColin Finck               for(k=n_upper-1; k>=i; k--) /*reverse order for two-side lighting*/
1253*c2c66affSColin Finck 		{
1254*c2c66affSColin Finck 		  glNormal3fv(upperNormal[k]);
1255*c2c66affSColin Finck 		  glVertex3fv(upperXYZ[k]);
1256*c2c66affSColin Finck 		}
1257*c2c66affSColin Finck 
1258*c2c66affSColin Finck               endtfan();
1259*c2c66affSColin Finck             }
1260*c2c66affSColin Finck           break; /*exit the main loop*/
1261*c2c66affSColin Finck         }
1262*c2c66affSColin Finck       else /* case3: neither is empty, plus the leftMostV, there is at least one triangle to output*/
1263*c2c66affSColin Finck         {
1264*c2c66affSColin Finck           if(upper_val[i] <= lower_val[j])
1265*c2c66affSColin Finck             {
1266*c2c66affSColin Finck 	      bgntfan();
1267*c2c66affSColin Finck 
1268*c2c66affSColin Finck 	      glNormal3fv(lowerNormal[j]);
1269*c2c66affSColin Finck 	      glVertex3fv(lowerXYZ[j]);
1270*c2c66affSColin Finck 
1271*c2c66affSColin Finck               /*find the last k>=i such that
1272*c2c66affSColin Finck                *upperverts[k][0] <= lowerverts[j][0]
1273*c2c66affSColin Finck                */
1274*c2c66affSColin Finck               k=i;
1275*c2c66affSColin Finck 
1276*c2c66affSColin Finck               while(k<n_upper)
1277*c2c66affSColin Finck                 {
1278*c2c66affSColin Finck                   if(upper_val[k] > lower_val[j])
1279*c2c66affSColin Finck                     break;
1280*c2c66affSColin Finck                   k++;
1281*c2c66affSColin Finck 
1282*c2c66affSColin Finck                 }
1283*c2c66affSColin Finck               k--;
1284*c2c66affSColin Finck 
1285*c2c66affSColin Finck 
1286*c2c66affSColin Finck               for(l=k; l>=i; l--)/*the reverse is for two-side lighting*/
1287*c2c66affSColin Finck                 {
1288*c2c66affSColin Finck 		  glNormal3fv(upperNormal[l]);
1289*c2c66affSColin Finck 		  glVertex3fv(upperXYZ[l]);
1290*c2c66affSColin Finck 
1291*c2c66affSColin Finck                 }
1292*c2c66affSColin Finck 	      glNormal3fv(leftMostNormal);
1293*c2c66affSColin Finck 	      glVertex3fv(leftMostXYZ);
1294*c2c66affSColin Finck 
1295*c2c66affSColin Finck               endtfan();
1296*c2c66affSColin Finck 
1297*c2c66affSColin Finck               /*update i and leftMostV for next loop
1298*c2c66affSColin Finck                */
1299*c2c66affSColin Finck               i = k+1;
1300*c2c66affSColin Finck 
1301*c2c66affSColin Finck 	      leftMostV[0] = upper_val[k];
1302*c2c66affSColin Finck 	      leftMostV[1] = v_upper;
1303*c2c66affSColin Finck 	      leftMostNormal = upperNormal[k];
1304*c2c66affSColin Finck 	      leftMostXYZ = upperXYZ[k];
1305*c2c66affSColin Finck             }
1306*c2c66affSColin Finck           else /*upperVerts[i][0] > lowerVerts[j][0]*/
1307*c2c66affSColin Finck             {
1308*c2c66affSColin Finck 	      bgntfan();
1309*c2c66affSColin Finck 	      glNormal3fv(upperNormal[i]);
1310*c2c66affSColin Finck 	      glVertex3fv(upperXYZ[i]);
1311*c2c66affSColin Finck 
1312*c2c66affSColin Finck               glNormal3fv(leftMostNormal);
1313*c2c66affSColin Finck 	      glVertex3fv(leftMostXYZ);
1314*c2c66affSColin Finck 
1315*c2c66affSColin Finck 
1316*c2c66affSColin Finck               /*find the last k>=j such that
1317*c2c66affSColin Finck                *lowerverts[k][0] < upperverts[i][0]
1318*c2c66affSColin Finck                */
1319*c2c66affSColin Finck               k=j;
1320*c2c66affSColin Finck               while(k< n_lower)
1321*c2c66affSColin Finck                 {
1322*c2c66affSColin Finck                   if(lower_val[k] >= upper_val[i])
1323*c2c66affSColin Finck                     break;
1324*c2c66affSColin Finck 		  glNormal3fv(lowerNormal[k]);
1325*c2c66affSColin Finck 		  glVertex3fv(lowerXYZ[k]);
1326*c2c66affSColin Finck 
1327*c2c66affSColin Finck                   k++;
1328*c2c66affSColin Finck                 }
1329*c2c66affSColin Finck               endtfan();
1330*c2c66affSColin Finck 
1331*c2c66affSColin Finck               /*update j and leftMostV for next loop
1332*c2c66affSColin Finck                */
1333*c2c66affSColin Finck               j=k;
1334*c2c66affSColin Finck 	      leftMostV[0] = lower_val[j-1];
1335*c2c66affSColin Finck 	      leftMostV[1] = v_lower;
1336*c2c66affSColin Finck 
1337*c2c66affSColin Finck 	      leftMostNormal = lowerNormal[j-1];
1338*c2c66affSColin Finck 	      leftMostXYZ = lowerXYZ[j-1];
1339*c2c66affSColin Finck             }
1340*c2c66affSColin Finck         }
1341*c2c66affSColin Finck     }
1342*c2c66affSColin Finck   //clean up
1343*c2c66affSColin Finck   free(upperXYZ);
1344*c2c66affSColin Finck   free(lowerXYZ);
1345*c2c66affSColin Finck   free(upperNormal);
1346*c2c66affSColin Finck   free(lowerNormal);
1347*c2c66affSColin Finck }
1348*c2c66affSColin Finck 
1349*c2c66affSColin Finck /*triangulate a strip bounded by two lines which are parallel  to V-axis
1350*c2c66affSColin Finck  *leftVerts: the verteces on the left line
1351*c2c66affSColin Finck  *rightVertx: the verteces on the right line
1352*c2c66affSColin Finck  *n_left >=1
1353*c2c66affSColin Finck  *n_right >=1
1354*c2c66affSColin Finck  */
inEvalVStrip(int n_left,REAL u_left,REAL * left_val,int n_right,REAL u_right,REAL * right_val)1355*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inEvalVStrip(int n_left, REAL u_left, REAL* left_val, int n_right, REAL u_right, REAL* right_val)
1356*c2c66affSColin Finck {
1357*c2c66affSColin Finck   int i,j,k,l;
1358*c2c66affSColin Finck   REAL botMostV[2];
1359*c2c66affSColin Finck   typedef REAL REAL3[3];
1360*c2c66affSColin Finck 
1361*c2c66affSColin Finck   REAL3* leftXYZ = (REAL3*) malloc(sizeof(REAL3)*n_left);
1362*c2c66affSColin Finck   assert(leftXYZ);
1363*c2c66affSColin Finck   REAL3* leftNormal = (REAL3*) malloc(sizeof(REAL3) * n_left);
1364*c2c66affSColin Finck   assert(leftNormal);
1365*c2c66affSColin Finck   REAL3* rightXYZ = (REAL3*) malloc(sizeof(REAL3)*n_right);
1366*c2c66affSColin Finck   assert(rightXYZ);
1367*c2c66affSColin Finck   REAL3* rightNormal = (REAL3*) malloc(sizeof(REAL3) * n_right);
1368*c2c66affSColin Finck   assert(rightNormal);
1369*c2c66affSColin Finck 
1370*c2c66affSColin Finck   inEvalVLine(n_left, u_left, left_val,  1, leftXYZ, leftNormal);
1371*c2c66affSColin Finck   inEvalVLine(n_right, u_right, right_val,  1, rightXYZ, rightNormal);
1372*c2c66affSColin Finck 
1373*c2c66affSColin Finck 
1374*c2c66affSColin Finck 
1375*c2c66affSColin Finck   REAL* botMostXYZ;
1376*c2c66affSColin Finck   REAL* botMostNormal;
1377*c2c66affSColin Finck 
1378*c2c66affSColin Finck   /*
1379*c2c66affSColin Finck    *the algorithm works by scanning from bot to top.
1380*c2c66affSColin Finck    *botMostV: the bot most of the remaining verteces (on both left and right).
1381*c2c66affSColin Finck    *           it could an element of leftVerts or rightVerts.
1382*c2c66affSColin Finck    *i: leftVerts[i] is the first vertex to the top of botMostV on left line
1383*c2c66affSColin Finck    *j: rightVerts[j] is the first vertex to the top of botMostV on rightline   */
1384*c2c66affSColin Finck 
1385*c2c66affSColin Finck   /*initialize i,j,and botMostV
1386*c2c66affSColin Finck    */
1387*c2c66affSColin Finck   if(left_val[0] <= right_val[0])
1388*c2c66affSColin Finck     {
1389*c2c66affSColin Finck       i=1;
1390*c2c66affSColin Finck       j=0;
1391*c2c66affSColin Finck 
1392*c2c66affSColin Finck       botMostV[0] = u_left;
1393*c2c66affSColin Finck       botMostV[1] = left_val[0];
1394*c2c66affSColin Finck       botMostXYZ = leftXYZ[0];
1395*c2c66affSColin Finck       botMostNormal = leftNormal[0];
1396*c2c66affSColin Finck     }
1397*c2c66affSColin Finck   else
1398*c2c66affSColin Finck     {
1399*c2c66affSColin Finck       i=0;
1400*c2c66affSColin Finck       j=1;
1401*c2c66affSColin Finck 
1402*c2c66affSColin Finck       botMostV[0] = u_right;
1403*c2c66affSColin Finck       botMostV[1] = right_val[0];
1404*c2c66affSColin Finck 
1405*c2c66affSColin Finck       botMostXYZ = rightXYZ[0];
1406*c2c66affSColin Finck       botMostNormal = rightNormal[0];
1407*c2c66affSColin Finck     }
1408*c2c66affSColin Finck 
1409*c2c66affSColin Finck   /*the main loop.
1410*c2c66affSColin Finck    *the invariance is that:
1411*c2c66affSColin Finck    *at the beginning of each loop, the meaning of i,j,and botMostV are
1412*c2c66affSColin Finck    *maintained
1413*c2c66affSColin Finck    */
1414*c2c66affSColin Finck   while(1)
1415*c2c66affSColin Finck     {
1416*c2c66affSColin Finck       if(i >= n_left) /*case1: no more in left*/
1417*c2c66affSColin Finck         {
1418*c2c66affSColin Finck           if(j<n_right-1) /*at least two vertices in right*/
1419*c2c66affSColin Finck             {
1420*c2c66affSColin Finck               bgntfan();
1421*c2c66affSColin Finck 	      glNormal3fv(botMostNormal);
1422*c2c66affSColin Finck               glVertex3fv(botMostXYZ);
1423*c2c66affSColin Finck 
1424*c2c66affSColin Finck               while(j<n_right){
1425*c2c66affSColin Finck 		glNormal3fv(rightNormal[j]);
1426*c2c66affSColin Finck 		glVertex3fv(rightXYZ[j]);
1427*c2c66affSColin Finck 		j++;
1428*c2c66affSColin Finck 
1429*c2c66affSColin Finck               }
1430*c2c66affSColin Finck               endtfan();
1431*c2c66affSColin Finck             }
1432*c2c66affSColin Finck           break; /*exit the main loop*/
1433*c2c66affSColin Finck         }
1434*c2c66affSColin Finck       else if(j>= n_right) /*case2: no more in right*/
1435*c2c66affSColin Finck         {
1436*c2c66affSColin Finck           if(i<n_left-1) /*at least two vertices in left*/
1437*c2c66affSColin Finck             {
1438*c2c66affSColin Finck               bgntfan();
1439*c2c66affSColin Finck 	      glNormal3fv(botMostNormal);
1440*c2c66affSColin Finck 	      glVertex3fv(botMostXYZ);
1441*c2c66affSColin Finck 
1442*c2c66affSColin Finck               for(k=n_left-1; k>=i; k--) /*reverse order for two-side lighting*/
1443*c2c66affSColin Finck 		{
1444*c2c66affSColin Finck 		  glNormal3fv(leftNormal[k]);
1445*c2c66affSColin Finck 		  glVertex3fv(leftXYZ[k]);
1446*c2c66affSColin Finck 		}
1447*c2c66affSColin Finck 
1448*c2c66affSColin Finck               endtfan();
1449*c2c66affSColin Finck             }
1450*c2c66affSColin Finck           break; /*exit the main loop*/
1451*c2c66affSColin Finck         }
1452*c2c66affSColin Finck       else /* case3: neither is empty, plus the botMostV, there is at least one triangle to output*/
1453*c2c66affSColin Finck         {
1454*c2c66affSColin Finck           if(left_val[i] <= right_val[j])
1455*c2c66affSColin Finck             {
1456*c2c66affSColin Finck 	      bgntfan();
1457*c2c66affSColin Finck 
1458*c2c66affSColin Finck 	      glNormal3fv(rightNormal[j]);
1459*c2c66affSColin Finck 	      glVertex3fv(rightXYZ[j]);
1460*c2c66affSColin Finck 
1461*c2c66affSColin Finck               /*find the last k>=i such that
1462*c2c66affSColin Finck                *leftverts[k][0] <= rightverts[j][0]
1463*c2c66affSColin Finck                */
1464*c2c66affSColin Finck               k=i;
1465*c2c66affSColin Finck 
1466*c2c66affSColin Finck               while(k<n_left)
1467*c2c66affSColin Finck                 {
1468*c2c66affSColin Finck                   if(left_val[k] > right_val[j])
1469*c2c66affSColin Finck                     break;
1470*c2c66affSColin Finck                   k++;
1471*c2c66affSColin Finck 
1472*c2c66affSColin Finck                 }
1473*c2c66affSColin Finck               k--;
1474*c2c66affSColin Finck 
1475*c2c66affSColin Finck 
1476*c2c66affSColin Finck               for(l=k; l>=i; l--)/*the reverse is for two-side lighting*/
1477*c2c66affSColin Finck                 {
1478*c2c66affSColin Finck 		  glNormal3fv(leftNormal[l]);
1479*c2c66affSColin Finck 		  glVertex3fv(leftXYZ[l]);
1480*c2c66affSColin Finck 
1481*c2c66affSColin Finck                 }
1482*c2c66affSColin Finck 	      glNormal3fv(botMostNormal);
1483*c2c66affSColin Finck 	      glVertex3fv(botMostXYZ);
1484*c2c66affSColin Finck 
1485*c2c66affSColin Finck               endtfan();
1486*c2c66affSColin Finck 
1487*c2c66affSColin Finck               /*update i and botMostV for next loop
1488*c2c66affSColin Finck                */
1489*c2c66affSColin Finck               i = k+1;
1490*c2c66affSColin Finck 
1491*c2c66affSColin Finck 	      botMostV[0] = u_left;
1492*c2c66affSColin Finck 	      botMostV[1] = left_val[k];
1493*c2c66affSColin Finck 	      botMostNormal = leftNormal[k];
1494*c2c66affSColin Finck 	      botMostXYZ = leftXYZ[k];
1495*c2c66affSColin Finck             }
1496*c2c66affSColin Finck           else /*left_val[i] > right_val[j])*/
1497*c2c66affSColin Finck             {
1498*c2c66affSColin Finck 	      bgntfan();
1499*c2c66affSColin Finck 	      glNormal3fv(leftNormal[i]);
1500*c2c66affSColin Finck 	      glVertex3fv(leftXYZ[i]);
1501*c2c66affSColin Finck 
1502*c2c66affSColin Finck               glNormal3fv(botMostNormal);
1503*c2c66affSColin Finck 	      glVertex3fv(botMostXYZ);
1504*c2c66affSColin Finck 
1505*c2c66affSColin Finck 
1506*c2c66affSColin Finck               /*find the last k>=j such that
1507*c2c66affSColin Finck                *rightverts[k][0] < leftverts[i][0]
1508*c2c66affSColin Finck                */
1509*c2c66affSColin Finck               k=j;
1510*c2c66affSColin Finck               while(k< n_right)
1511*c2c66affSColin Finck                 {
1512*c2c66affSColin Finck                   if(right_val[k] >= left_val[i])
1513*c2c66affSColin Finck                     break;
1514*c2c66affSColin Finck 		  glNormal3fv(rightNormal[k]);
1515*c2c66affSColin Finck 		  glVertex3fv(rightXYZ[k]);
1516*c2c66affSColin Finck 
1517*c2c66affSColin Finck                   k++;
1518*c2c66affSColin Finck                 }
1519*c2c66affSColin Finck               endtfan();
1520*c2c66affSColin Finck 
1521*c2c66affSColin Finck               /*update j and botMostV for next loop
1522*c2c66affSColin Finck                */
1523*c2c66affSColin Finck               j=k;
1524*c2c66affSColin Finck 	      botMostV[0] = u_right;
1525*c2c66affSColin Finck 	      botMostV[1] = right_val[j-1];
1526*c2c66affSColin Finck 
1527*c2c66affSColin Finck 	      botMostNormal = rightNormal[j-1];
1528*c2c66affSColin Finck 	      botMostXYZ = rightXYZ[j-1];
1529*c2c66affSColin Finck             }
1530*c2c66affSColin Finck         }
1531*c2c66affSColin Finck     }
1532*c2c66affSColin Finck   //clean up
1533*c2c66affSColin Finck   free(leftXYZ);
1534*c2c66affSColin Finck   free(rightXYZ);
1535*c2c66affSColin Finck   free(leftNormal);
1536*c2c66affSColin Finck   free(rightNormal);
1537*c2c66affSColin Finck }
1538*c2c66affSColin Finck 
1539*c2c66affSColin Finck /*-----------------------begin evalMachine-------------------*/
inMap2fEM(int which,int k,REAL ulower,REAL uupper,int ustride,int uorder,REAL vlower,REAL vupper,int vstride,int vorder,REAL * ctlPoints)1540*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inMap2fEM(int which, int k,
1541*c2c66affSColin Finck 	     REAL ulower,
1542*c2c66affSColin Finck 	     REAL uupper,
1543*c2c66affSColin Finck 	     int ustride,
1544*c2c66affSColin Finck 	     int uorder,
1545*c2c66affSColin Finck 	     REAL vlower,
1546*c2c66affSColin Finck 	     REAL vupper,
1547*c2c66affSColin Finck 	     int vstride,
1548*c2c66affSColin Finck 	     int vorder,
1549*c2c66affSColin Finck 	     REAL *ctlPoints)
1550*c2c66affSColin Finck {
1551*c2c66affSColin Finck   int i,j,x;
1552*c2c66affSColin Finck   surfEvalMachine *temp_em;
1553*c2c66affSColin Finck   switch(which){
1554*c2c66affSColin Finck   case 0: //vertex
1555*c2c66affSColin Finck     vertex_flag = 1;
1556*c2c66affSColin Finck     temp_em = &em_vertex;
1557*c2c66affSColin Finck     break;
1558*c2c66affSColin Finck   case 1: //normal
1559*c2c66affSColin Finck     normal_flag = 1;
1560*c2c66affSColin Finck     temp_em = &em_normal;
1561*c2c66affSColin Finck     break;
1562*c2c66affSColin Finck   case 2: //color
1563*c2c66affSColin Finck     color_flag = 1;
1564*c2c66affSColin Finck     temp_em = &em_color;
1565*c2c66affSColin Finck     break;
1566*c2c66affSColin Finck   default:
1567*c2c66affSColin Finck     texcoord_flag = 1;
1568*c2c66affSColin Finck     temp_em = &em_texcoord;
1569*c2c66affSColin Finck     break;
1570*c2c66affSColin Finck   }
1571*c2c66affSColin Finck 
1572*c2c66affSColin Finck   REAL *data = temp_em->ctlPoints;
1573*c2c66affSColin Finck 
1574*c2c66affSColin Finck   temp_em->uprime = -1;//initilized
1575*c2c66affSColin Finck   temp_em->vprime = -1;
1576*c2c66affSColin Finck 
1577*c2c66affSColin Finck   temp_em->k = k;
1578*c2c66affSColin Finck   temp_em->u1 = ulower;
1579*c2c66affSColin Finck   temp_em->u2 = uupper;
1580*c2c66affSColin Finck   temp_em->ustride = ustride;
1581*c2c66affSColin Finck   temp_em->uorder = uorder;
1582*c2c66affSColin Finck   temp_em->v1 = vlower;
1583*c2c66affSColin Finck   temp_em->v2 = vupper;
1584*c2c66affSColin Finck   temp_em->vstride = vstride;
1585*c2c66affSColin Finck   temp_em->vorder = vorder;
1586*c2c66affSColin Finck 
1587*c2c66affSColin Finck   /*copy the contrl points from ctlPoints to global_ev_ctlPoints*/
1588*c2c66affSColin Finck   for (i=0; i<uorder; i++) {
1589*c2c66affSColin Finck     for (j=0; j<vorder; j++) {
1590*c2c66affSColin Finck       for (x=0; x<k; x++) {
1591*c2c66affSColin Finck 	data[x] = ctlPoints[x];
1592*c2c66affSColin Finck       }
1593*c2c66affSColin Finck       ctlPoints += vstride;
1594*c2c66affSColin Finck       data += k;
1595*c2c66affSColin Finck     }
1596*c2c66affSColin Finck     ctlPoints += ustride - vstride * vorder;
1597*c2c66affSColin Finck   }
1598*c2c66affSColin Finck }
1599*c2c66affSColin Finck 
inDoDomain2WithDerivsEM(surfEvalMachine * em,REAL u,REAL v,REAL * retPoint,REAL * retdu,REAL * retdv)1600*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inDoDomain2WithDerivsEM(surfEvalMachine *em, REAL u, REAL v,
1601*c2c66affSColin Finck 				REAL *retPoint, REAL *retdu, REAL *retdv)
1602*c2c66affSColin Finck {
1603*c2c66affSColin Finck     int j, row, col;
1604*c2c66affSColin Finck     REAL the_uprime;
1605*c2c66affSColin Finck     REAL the_vprime;
1606*c2c66affSColin Finck     REAL p;
1607*c2c66affSColin Finck     REAL pdv;
1608*c2c66affSColin Finck     REAL *data;
1609*c2c66affSColin Finck 
1610*c2c66affSColin Finck     if((em->u2 == em->u1) || (em->v2 == em->v1))
1611*c2c66affSColin Finck 	return;
1612*c2c66affSColin Finck     the_uprime = (u - em->u1) / (em->u2 - em->u1);
1613*c2c66affSColin Finck     the_vprime = (v - em->v1) / (em->v2 - em->v1);
1614*c2c66affSColin Finck 
1615*c2c66affSColin Finck     /* Compute coefficients for values and derivs */
1616*c2c66affSColin Finck 
1617*c2c66affSColin Finck     /* Use already cached values if possible */
1618*c2c66affSColin Finck     if(em->uprime != the_uprime) {
1619*c2c66affSColin Finck         inPreEvaluateWithDeriv(em->uorder, the_uprime, em->ucoeff, em->ucoeffDeriv);
1620*c2c66affSColin Finck 	em->uprime = the_uprime;
1621*c2c66affSColin Finck     }
1622*c2c66affSColin Finck     if (em->vprime != the_vprime) {
1623*c2c66affSColin Finck 	inPreEvaluateWithDeriv(em->vorder, the_vprime, em->vcoeff, em->vcoeffDeriv);
1624*c2c66affSColin Finck 	em->vprime = the_vprime;
1625*c2c66affSColin Finck     }
1626*c2c66affSColin Finck 
1627*c2c66affSColin Finck     for (j = 0; j < em->k; j++) {
1628*c2c66affSColin Finck 	data=em->ctlPoints+j;
1629*c2c66affSColin Finck 	retPoint[j] = retdu[j] = retdv[j] = 0.0;
1630*c2c66affSColin Finck 	for (row = 0; row < em->uorder; row++)  {
1631*c2c66affSColin Finck 	    /*
1632*c2c66affSColin Finck 	    ** Minor optimization.
1633*c2c66affSColin Finck 	    ** The col == 0 part of the loop is extracted so we don't
1634*c2c66affSColin Finck 	    ** have to initialize p and pdv to 0.
1635*c2c66affSColin Finck 	    */
1636*c2c66affSColin Finck 	    p = em->vcoeff[0] * (*data);
1637*c2c66affSColin Finck 	    pdv = em->vcoeffDeriv[0] * (*data);
1638*c2c66affSColin Finck 	    data += em->k;
1639*c2c66affSColin Finck 	    for (col = 1; col < em->vorder; col++) {
1640*c2c66affSColin Finck 		/* Incrementally build up p, pdv value */
1641*c2c66affSColin Finck 		p += em->vcoeff[col] * (*data);
1642*c2c66affSColin Finck 		pdv += em->vcoeffDeriv[col] * (*data);
1643*c2c66affSColin Finck 		data += em->k;
1644*c2c66affSColin Finck 	    }
1645*c2c66affSColin Finck 	    /* Use p, pdv value to incrementally add up r, du, dv */
1646*c2c66affSColin Finck 	    retPoint[j] += em->ucoeff[row] * p;
1647*c2c66affSColin Finck 	    retdu[j] += em->ucoeffDeriv[row] * p;
1648*c2c66affSColin Finck 	    retdv[j] += em->ucoeff[row] * pdv;
1649*c2c66affSColin Finck 	}
1650*c2c66affSColin Finck     }
1651*c2c66affSColin Finck }
1652*c2c66affSColin Finck 
inDoDomain2EM(surfEvalMachine * em,REAL u,REAL v,REAL * retPoint)1653*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inDoDomain2EM(surfEvalMachine *em, REAL u, REAL v,
1654*c2c66affSColin Finck 				REAL *retPoint)
1655*c2c66affSColin Finck {
1656*c2c66affSColin Finck     int j, row, col;
1657*c2c66affSColin Finck     REAL the_uprime;
1658*c2c66affSColin Finck     REAL the_vprime;
1659*c2c66affSColin Finck     REAL p;
1660*c2c66affSColin Finck     REAL *data;
1661*c2c66affSColin Finck 
1662*c2c66affSColin Finck     if((em->u2 == em->u1) || (em->v2 == em->v1))
1663*c2c66affSColin Finck 	return;
1664*c2c66affSColin Finck     the_uprime = (u - em->u1) / (em->u2 - em->u1);
1665*c2c66affSColin Finck     the_vprime = (v - em->v1) / (em->v2 - em->v1);
1666*c2c66affSColin Finck 
1667*c2c66affSColin Finck     /* Compute coefficients for values and derivs */
1668*c2c66affSColin Finck 
1669*c2c66affSColin Finck     /* Use already cached values if possible */
1670*c2c66affSColin Finck     if(em->uprime != the_uprime) {
1671*c2c66affSColin Finck         inPreEvaluate(em->uorder, the_uprime, em->ucoeff);
1672*c2c66affSColin Finck 	em->uprime = the_uprime;
1673*c2c66affSColin Finck     }
1674*c2c66affSColin Finck     if (em->vprime != the_vprime) {
1675*c2c66affSColin Finck 	inPreEvaluate(em->vorder, the_vprime, em->vcoeff);
1676*c2c66affSColin Finck 	em->vprime = the_vprime;
1677*c2c66affSColin Finck     }
1678*c2c66affSColin Finck 
1679*c2c66affSColin Finck     for (j = 0; j < em->k; j++) {
1680*c2c66affSColin Finck 	data=em->ctlPoints+j;
1681*c2c66affSColin Finck 	retPoint[j] = 0.0;
1682*c2c66affSColin Finck 	for (row = 0; row < em->uorder; row++)  {
1683*c2c66affSColin Finck 	    /*
1684*c2c66affSColin Finck 	    ** Minor optimization.
1685*c2c66affSColin Finck 	    ** The col == 0 part of the loop is extracted so we don't
1686*c2c66affSColin Finck 	    ** have to initialize p and pdv to 0.
1687*c2c66affSColin Finck 	    */
1688*c2c66affSColin Finck 	    p = em->vcoeff[0] * (*data);
1689*c2c66affSColin Finck 	    data += em->k;
1690*c2c66affSColin Finck 	    for (col = 1; col < em->vorder; col++) {
1691*c2c66affSColin Finck 		/* Incrementally build up p, pdv value */
1692*c2c66affSColin Finck 		p += em->vcoeff[col] * (*data);
1693*c2c66affSColin Finck 		data += em->k;
1694*c2c66affSColin Finck 	    }
1695*c2c66affSColin Finck 	    /* Use p, pdv value to incrementally add up r, du, dv */
1696*c2c66affSColin Finck 	    retPoint[j] += em->ucoeff[row] * p;
1697*c2c66affSColin Finck 	}
1698*c2c66affSColin Finck     }
1699*c2c66affSColin Finck }
1700*c2c66affSColin Finck 
1701*c2c66affSColin Finck 
inDoEvalCoord2EM(REAL u,REAL v)1702*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inDoEvalCoord2EM(REAL u, REAL v)
1703*c2c66affSColin Finck {
1704*c2c66affSColin Finck   REAL temp_vertex[5];
1705*c2c66affSColin Finck   REAL temp_normal[3];
1706*c2c66affSColin Finck   REAL temp_color[4];
1707*c2c66affSColin Finck   REAL temp_texcoord[4];
1708*c2c66affSColin Finck 
1709*c2c66affSColin Finck   if(texcoord_flag)
1710*c2c66affSColin Finck     {
1711*c2c66affSColin Finck       inDoDomain2EM(&em_texcoord, u,v, temp_texcoord);
1712*c2c66affSColin Finck       texcoordCallBack(temp_texcoord, userData);
1713*c2c66affSColin Finck     }
1714*c2c66affSColin Finck   if(color_flag)
1715*c2c66affSColin Finck     {
1716*c2c66affSColin Finck       inDoDomain2EM(&em_color, u,v, temp_color);
1717*c2c66affSColin Finck       colorCallBack(temp_color, userData);
1718*c2c66affSColin Finck     }
1719*c2c66affSColin Finck 
1720*c2c66affSColin Finck   if(normal_flag) //there is a normla map
1721*c2c66affSColin Finck     {
1722*c2c66affSColin Finck       inDoDomain2EM(&em_normal, u,v, temp_normal);
1723*c2c66affSColin Finck       normalCallBack(temp_normal, userData);
1724*c2c66affSColin Finck 
1725*c2c66affSColin Finck       if(vertex_flag)
1726*c2c66affSColin Finck 	{
1727*c2c66affSColin Finck 	  inDoDomain2EM(&em_vertex, u,v,temp_vertex);
1728*c2c66affSColin Finck 	  if(em_vertex.k == 4)
1729*c2c66affSColin Finck 	    {
1730*c2c66affSColin Finck 	      temp_vertex[0] /= temp_vertex[3];
1731*c2c66affSColin Finck 	      temp_vertex[1] /= temp_vertex[3];
1732*c2c66affSColin Finck 	      temp_vertex[2] /= temp_vertex[3];
1733*c2c66affSColin Finck 	    }
1734*c2c66affSColin Finck           temp_vertex[3]=u;
1735*c2c66affSColin Finck           temp_vertex[4]=v;
1736*c2c66affSColin Finck 	  vertexCallBack(temp_vertex, userData);
1737*c2c66affSColin Finck 	}
1738*c2c66affSColin Finck     }
1739*c2c66affSColin Finck   else if(auto_normal_flag) //no normal map but there is a normal callbackfunctin
1740*c2c66affSColin Finck     {
1741*c2c66affSColin Finck       REAL du[4];
1742*c2c66affSColin Finck       REAL dv[4];
1743*c2c66affSColin Finck 
1744*c2c66affSColin Finck       /*compute homegeneous point and partial derivatives*/
1745*c2c66affSColin Finck       inDoDomain2WithDerivsEM(&em_vertex, u,v,temp_vertex,du,dv);
1746*c2c66affSColin Finck 
1747*c2c66affSColin Finck       if(em_vertex.k ==4)
1748*c2c66affSColin Finck 	inComputeFirstPartials(temp_vertex, du, dv);
1749*c2c66affSColin Finck 
1750*c2c66affSColin Finck #ifdef AVOID_ZERO_NORMAL
1751*c2c66affSColin Finck       if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
1752*c2c66affSColin Finck 	{
1753*c2c66affSColin Finck 
1754*c2c66affSColin Finck 	  REAL tempdu[4];
1755*c2c66affSColin Finck 	  REAL tempdata[4];
1756*c2c66affSColin Finck 	  REAL u1 = em_vertex.u1;
1757*c2c66affSColin Finck 	  REAL u2 = em_vertex.u2;
1758*c2c66affSColin Finck 	  if(u-MYDELTA*(u2-u1) < u1)
1759*c2c66affSColin Finck 	    u = u+ MYDELTA*(u2-u1);
1760*c2c66affSColin Finck 	  else
1761*c2c66affSColin Finck 	    u = u-MYDELTA*(u2-u1);
1762*c2c66affSColin Finck 	  inDoDomain2WithDerivsEM(&em_vertex,u,v, tempdata, tempdu, dv);
1763*c2c66affSColin Finck 
1764*c2c66affSColin Finck 	  if(em_vertex.k ==4)
1765*c2c66affSColin Finck 	    inComputeFirstPartials(temp_vertex, du, dv);
1766*c2c66affSColin Finck 	}
1767*c2c66affSColin Finck       else if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
1768*c2c66affSColin Finck 	{
1769*c2c66affSColin Finck 	  REAL tempdv[4];
1770*c2c66affSColin Finck 	  REAL tempdata[4];
1771*c2c66affSColin Finck 	  REAL v1 = em_vertex.v1;
1772*c2c66affSColin Finck 	  REAL v2 = em_vertex.v2;
1773*c2c66affSColin Finck 	  if(v-MYDELTA*(v2-v1) < v1)
1774*c2c66affSColin Finck 	    v = v+ MYDELTA*(v2-v1);
1775*c2c66affSColin Finck 	  else
1776*c2c66affSColin Finck 	    v = v-MYDELTA*(v2-v1);
1777*c2c66affSColin Finck 	  inDoDomain2WithDerivsEM(&em_vertex,u,v, tempdata, du, tempdv);
1778*c2c66affSColin Finck 
1779*c2c66affSColin Finck 	  if(em_vertex.k ==4)
1780*c2c66affSColin Finck 	    inComputeFirstPartials(temp_vertex, du, dv);
1781*c2c66affSColin Finck 	}
1782*c2c66affSColin Finck #endif
1783*c2c66affSColin Finck 
1784*c2c66affSColin Finck       /*compute normal*/
1785*c2c66affSColin Finck       switch(em_vertex.k){
1786*c2c66affSColin Finck       case 3:
1787*c2c66affSColin Finck 
1788*c2c66affSColin Finck 	inComputeNormal2(du, dv, temp_normal);
1789*c2c66affSColin Finck 	break;
1790*c2c66affSColin Finck       case 4:
1791*c2c66affSColin Finck 
1792*c2c66affSColin Finck //	inComputeFirstPartials(temp_vertex, du, dv);
1793*c2c66affSColin Finck 	inComputeNormal2(du, dv, temp_normal);
1794*c2c66affSColin Finck 
1795*c2c66affSColin Finck 	/*transform the homegeneous coordinate of retPoint into inhomogenous one*/
1796*c2c66affSColin Finck 	temp_vertex[0] /= temp_vertex[3];
1797*c2c66affSColin Finck 	temp_vertex[1] /= temp_vertex[3];
1798*c2c66affSColin Finck 	temp_vertex[2] /= temp_vertex[3];
1799*c2c66affSColin Finck 	break;
1800*c2c66affSColin Finck       }
1801*c2c66affSColin Finck       normalCallBack(temp_normal, userData);
1802*c2c66affSColin Finck       temp_vertex[3] = u;
1803*c2c66affSColin Finck       temp_vertex[4] = v;
1804*c2c66affSColin Finck       vertexCallBack(temp_vertex, userData);
1805*c2c66affSColin Finck 
1806*c2c66affSColin Finck     }/*end if auto_normal*/
1807*c2c66affSColin Finck   else //no normal map, and no normal callback function
1808*c2c66affSColin Finck     {
1809*c2c66affSColin Finck       if(vertex_flag)
1810*c2c66affSColin Finck 	{
1811*c2c66affSColin Finck 	  inDoDomain2EM(&em_vertex, u,v,temp_vertex);
1812*c2c66affSColin Finck 	  if(em_vertex.k == 4)
1813*c2c66affSColin Finck 	    {
1814*c2c66affSColin Finck 	      temp_vertex[0] /= temp_vertex[3];
1815*c2c66affSColin Finck 	      temp_vertex[1] /= temp_vertex[3];
1816*c2c66affSColin Finck 	      temp_vertex[2] /= temp_vertex[3];
1817*c2c66affSColin Finck 	    }
1818*c2c66affSColin Finck           temp_vertex[3] = u;
1819*c2c66affSColin Finck           temp_vertex[4] = v;
1820*c2c66affSColin Finck 	  vertexCallBack(temp_vertex, userData);
1821*c2c66affSColin Finck 	}
1822*c2c66affSColin Finck     }
1823*c2c66affSColin Finck }
1824*c2c66affSColin Finck 
1825*c2c66affSColin Finck 
inBPMEvalEM(bezierPatchMesh * bpm)1826*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inBPMEvalEM(bezierPatchMesh* bpm)
1827*c2c66affSColin Finck {
1828*c2c66affSColin Finck   int i,j,k;
1829*c2c66affSColin Finck   float u,v;
1830*c2c66affSColin Finck 
1831*c2c66affSColin Finck   int ustride;
1832*c2c66affSColin Finck   int vstride;
1833*c2c66affSColin Finck 
1834*c2c66affSColin Finck #ifdef USE_LOD
1835*c2c66affSColin Finck   if(bpm->bpatch != NULL)
1836*c2c66affSColin Finck     {
1837*c2c66affSColin Finck       bezierPatch* p=bpm->bpatch;
1838*c2c66affSColin Finck       ustride = p->dimension * p->vorder;
1839*c2c66affSColin Finck       vstride = p->dimension;
1840*c2c66affSColin Finck 
1841*c2c66affSColin Finck       glMap2f( (p->dimension == 3)? GL_MAP2_VERTEX_3 : GL_MAP2_VERTEX_4,
1842*c2c66affSColin Finck 	      p->umin,
1843*c2c66affSColin Finck 	      p->umax,
1844*c2c66affSColin Finck 	      ustride,
1845*c2c66affSColin Finck 	      p->uorder,
1846*c2c66affSColin Finck 	      p->vmin,
1847*c2c66affSColin Finck 	      p->vmax,
1848*c2c66affSColin Finck 	      vstride,
1849*c2c66affSColin Finck 	      p->vorder,
1850*c2c66affSColin Finck 	      p->ctlpoints);
1851*c2c66affSColin Finck 
1852*c2c66affSColin Finck 
1853*c2c66affSColin Finck /*
1854*c2c66affSColin Finck     inMap2fEM(0, p->dimension,
1855*c2c66affSColin Finck 	  p->umin,
1856*c2c66affSColin Finck 	  p->umax,
1857*c2c66affSColin Finck 	  ustride,
1858*c2c66affSColin Finck 	  p->uorder,
1859*c2c66affSColin Finck 	  p->vmin,
1860*c2c66affSColin Finck 	  p->vmax,
1861*c2c66affSColin Finck 	  vstride,
1862*c2c66affSColin Finck 	  p->vorder,
1863*c2c66affSColin Finck 	  p->ctlpoints);
1864*c2c66affSColin Finck */
1865*c2c66affSColin Finck     }
1866*c2c66affSColin Finck #else
1867*c2c66affSColin Finck 
1868*c2c66affSColin Finck   if(bpm->bpatch != NULL){
1869*c2c66affSColin Finck     bezierPatch* p = bpm->bpatch;
1870*c2c66affSColin Finck     ustride = p->dimension * p->vorder;
1871*c2c66affSColin Finck     vstride = p->dimension;
1872*c2c66affSColin Finck     inMap2fEM(0, p->dimension,
1873*c2c66affSColin Finck 	  p->umin,
1874*c2c66affSColin Finck 	  p->umax,
1875*c2c66affSColin Finck 	  ustride,
1876*c2c66affSColin Finck 	  p->uorder,
1877*c2c66affSColin Finck 	  p->vmin,
1878*c2c66affSColin Finck 	  p->vmax,
1879*c2c66affSColin Finck 	  vstride,
1880*c2c66affSColin Finck 	  p->vorder,
1881*c2c66affSColin Finck 	  p->ctlpoints);
1882*c2c66affSColin Finck   }
1883*c2c66affSColin Finck   if(bpm->bpatch_normal != NULL){
1884*c2c66affSColin Finck     bezierPatch* p = bpm->bpatch_normal;
1885*c2c66affSColin Finck     ustride = p->dimension * p->vorder;
1886*c2c66affSColin Finck     vstride = p->dimension;
1887*c2c66affSColin Finck     inMap2fEM(1, p->dimension,
1888*c2c66affSColin Finck 	  p->umin,
1889*c2c66affSColin Finck 	  p->umax,
1890*c2c66affSColin Finck 	  ustride,
1891*c2c66affSColin Finck 	  p->uorder,
1892*c2c66affSColin Finck 	  p->vmin,
1893*c2c66affSColin Finck 	  p->vmax,
1894*c2c66affSColin Finck 	  vstride,
1895*c2c66affSColin Finck 	  p->vorder,
1896*c2c66affSColin Finck 	  p->ctlpoints);
1897*c2c66affSColin Finck   }
1898*c2c66affSColin Finck   if(bpm->bpatch_color != NULL){
1899*c2c66affSColin Finck     bezierPatch* p = bpm->bpatch_color;
1900*c2c66affSColin Finck     ustride = p->dimension * p->vorder;
1901*c2c66affSColin Finck     vstride = p->dimension;
1902*c2c66affSColin Finck     inMap2fEM(2, p->dimension,
1903*c2c66affSColin Finck 	  p->umin,
1904*c2c66affSColin Finck 	  p->umax,
1905*c2c66affSColin Finck 	  ustride,
1906*c2c66affSColin Finck 	  p->uorder,
1907*c2c66affSColin Finck 	  p->vmin,
1908*c2c66affSColin Finck 	  p->vmax,
1909*c2c66affSColin Finck 	  vstride,
1910*c2c66affSColin Finck 	  p->vorder,
1911*c2c66affSColin Finck 	  p->ctlpoints);
1912*c2c66affSColin Finck   }
1913*c2c66affSColin Finck   if(bpm->bpatch_texcoord != NULL){
1914*c2c66affSColin Finck     bezierPatch* p = bpm->bpatch_texcoord;
1915*c2c66affSColin Finck     ustride = p->dimension * p->vorder;
1916*c2c66affSColin Finck     vstride = p->dimension;
1917*c2c66affSColin Finck     inMap2fEM(3, p->dimension,
1918*c2c66affSColin Finck 	  p->umin,
1919*c2c66affSColin Finck 	  p->umax,
1920*c2c66affSColin Finck 	  ustride,
1921*c2c66affSColin Finck 	  p->uorder,
1922*c2c66affSColin Finck 	  p->vmin,
1923*c2c66affSColin Finck 	  p->vmax,
1924*c2c66affSColin Finck 	  vstride,
1925*c2c66affSColin Finck 	  p->vorder,
1926*c2c66affSColin Finck 	  p->ctlpoints);
1927*c2c66affSColin Finck   }
1928*c2c66affSColin Finck #endif
1929*c2c66affSColin Finck 
1930*c2c66affSColin Finck 
1931*c2c66affSColin Finck   k=0;
1932*c2c66affSColin Finck   for(i=0; i<bpm->index_length_array; i++)
1933*c2c66affSColin Finck     {
1934*c2c66affSColin Finck #ifdef USE_LOD
1935*c2c66affSColin Finck       if(bpm->type_array[i] == GL_POLYGON) //a mesh
1936*c2c66affSColin Finck 	{
1937*c2c66affSColin Finck 	  GLfloat *temp = bpm->UVarray+k;
1938*c2c66affSColin Finck 	  GLfloat u0 = temp[0];
1939*c2c66affSColin Finck 	  GLfloat v0 = temp[1];
1940*c2c66affSColin Finck 	  GLfloat u1 = temp[2];
1941*c2c66affSColin Finck 	  GLfloat v1 = temp[3];
1942*c2c66affSColin Finck 	  GLint nu = (GLint) ( temp[4]);
1943*c2c66affSColin Finck 	  GLint nv = (GLint) ( temp[5]);
1944*c2c66affSColin Finck 	  GLint umin = (GLint) ( temp[6]);
1945*c2c66affSColin Finck 	  GLint vmin = (GLint) ( temp[7]);
1946*c2c66affSColin Finck 	  GLint umax = (GLint) ( temp[8]);
1947*c2c66affSColin Finck 	  GLint vmax = (GLint) ( temp[9]);
1948*c2c66affSColin Finck 
1949*c2c66affSColin Finck 	  glMapGrid2f(LOD_eval_level*nu, u0, u1, LOD_eval_level*nv, v0, v1);
1950*c2c66affSColin Finck 	  glEvalMesh2(GL_FILL, LOD_eval_level*umin, LOD_eval_level*umax, LOD_eval_level*vmin, LOD_eval_level*vmax);
1951*c2c66affSColin Finck 	}
1952*c2c66affSColin Finck       else
1953*c2c66affSColin Finck 	{
1954*c2c66affSColin Finck 	  LOD_eval(bpm->length_array[i], bpm->UVarray+k, bpm->type_array[i],
1955*c2c66affSColin Finck 		   0
1956*c2c66affSColin Finck 		   );
1957*c2c66affSColin Finck 	}
1958*c2c66affSColin Finck 	  k+= 2*bpm->length_array[i];
1959*c2c66affSColin Finck 
1960*c2c66affSColin Finck #else //undef  USE_LOD
1961*c2c66affSColin Finck 
1962*c2c66affSColin Finck #ifdef CRACK_TEST
1963*c2c66affSColin Finck if(  bpm->bpatch->umin == 2 &&   bpm->bpatch->umax == 3
1964*c2c66affSColin Finck   && bpm->bpatch->vmin ==2 &&    bpm->bpatch->vmax == 3)
1965*c2c66affSColin Finck {
1966*c2c66affSColin Finck REAL vertex[4];
1967*c2c66affSColin Finck REAL normal[4];
1968*c2c66affSColin Finck #ifdef DEBUG
1969*c2c66affSColin Finck printf("***number ****1\n");
1970*c2c66affSColin Finck #endif
1971*c2c66affSColin Finck 
1972*c2c66affSColin Finck beginCallBack(GL_QUAD_STRIP, NULL);
1973*c2c66affSColin Finck inDoEvalCoord2EM(3.0, 3.0);
1974*c2c66affSColin Finck inDoEvalCoord2EM(2.0, 3.0);
1975*c2c66affSColin Finck inDoEvalCoord2EM(3.0, 2.7);
1976*c2c66affSColin Finck inDoEvalCoord2EM(2.0, 2.7);
1977*c2c66affSColin Finck inDoEvalCoord2EM(3.0, 2.0);
1978*c2c66affSColin Finck inDoEvalCoord2EM(2.0, 2.0);
1979*c2c66affSColin Finck endCallBack(NULL);
1980*c2c66affSColin Finck 
1981*c2c66affSColin Finck beginCallBack(GL_TRIANGLE_STRIP, NULL);
1982*c2c66affSColin Finck inDoEvalCoord2EM(2.0, 3.0);
1983*c2c66affSColin Finck inDoEvalCoord2EM(2.0, 2.0);
1984*c2c66affSColin Finck inDoEvalCoord2EM(2.0, 2.7);
1985*c2c66affSColin Finck endCallBack(NULL);
1986*c2c66affSColin Finck 
1987*c2c66affSColin Finck }
1988*c2c66affSColin Finck if(  bpm->bpatch->umin == 1 &&   bpm->bpatch->umax == 2
1989*c2c66affSColin Finck   && bpm->bpatch->vmin ==2 &&    bpm->bpatch->vmax == 3)
1990*c2c66affSColin Finck {
1991*c2c66affSColin Finck #ifdef DEBUG
1992*c2c66affSColin Finck printf("***number 3\n");
1993*c2c66affSColin Finck #endif
1994*c2c66affSColin Finck beginCallBack(GL_QUAD_STRIP, NULL);
1995*c2c66affSColin Finck inDoEvalCoord2EM(2.0, 3.0);
1996*c2c66affSColin Finck inDoEvalCoord2EM(1.0, 3.0);
1997*c2c66affSColin Finck inDoEvalCoord2EM(2.0, 2.3);
1998*c2c66affSColin Finck inDoEvalCoord2EM(1.0, 2.3);
1999*c2c66affSColin Finck inDoEvalCoord2EM(2.0, 2.0);
2000*c2c66affSColin Finck inDoEvalCoord2EM(1.0, 2.0);
2001*c2c66affSColin Finck endCallBack(NULL);
2002*c2c66affSColin Finck 
2003*c2c66affSColin Finck beginCallBack(GL_TRIANGLE_STRIP, NULL);
2004*c2c66affSColin Finck inDoEvalCoord2EM(2.0, 2.3);
2005*c2c66affSColin Finck inDoEvalCoord2EM(2.0, 2.0);
2006*c2c66affSColin Finck inDoEvalCoord2EM(2.0, 3.0);
2007*c2c66affSColin Finck endCallBack(NULL);
2008*c2c66affSColin Finck 
2009*c2c66affSColin Finck }
2010*c2c66affSColin Finck return;
2011*c2c66affSColin Finck #endif //CRACK_TEST
2012*c2c66affSColin Finck 
2013*c2c66affSColin Finck       beginCallBack(bpm->type_array[i], userData);
2014*c2c66affSColin Finck 
2015*c2c66affSColin Finck       for(j=0; j<bpm->length_array[i]; j++)
2016*c2c66affSColin Finck 	{
2017*c2c66affSColin Finck 	  u = bpm->UVarray[k];
2018*c2c66affSColin Finck 	  v = bpm->UVarray[k+1];
2019*c2c66affSColin Finck #ifdef USE_LOD
2020*c2c66affSColin Finck           LOD_EVAL_COORD(u,v);
2021*c2c66affSColin Finck //	  glEvalCoord2f(u,v);
2022*c2c66affSColin Finck #else
2023*c2c66affSColin Finck 
2024*c2c66affSColin Finck #ifdef  GENERIC_TEST
2025*c2c66affSColin Finck           float temp_normal[3];
2026*c2c66affSColin Finck           float temp_vertex[3];
2027*c2c66affSColin Finck           if(temp_signal == 0)
2028*c2c66affSColin Finck 	    {
2029*c2c66affSColin Finck 	      gTessVertexSphere(u,v, temp_normal, temp_vertex);
2030*c2c66affSColin Finck //printf("normal=(%f,%f,%f)\n", temp_normal[0], temp_normal[1], temp_normal[2])//printf("veretx=(%f,%f,%f)\n", temp_vertex[0], temp_vertex[1], temp_vertex[2]);
2031*c2c66affSColin Finck               normalCallBack(temp_normal, userData);
2032*c2c66affSColin Finck 	      vertexCallBack(temp_vertex, userData);
2033*c2c66affSColin Finck 	    }
2034*c2c66affSColin Finck           else if(temp_signal == 1)
2035*c2c66affSColin Finck 	    {
2036*c2c66affSColin Finck 	      gTessVertexCyl(u,v, temp_normal, temp_vertex);
2037*c2c66affSColin Finck //printf("normal=(%f,%f,%f)\n", temp_normal[0], temp_normal[1], temp_normal[2])//printf("veretx=(%f,%f,%f)\n", temp_vertex[0], temp_vertex[1], temp_vertex[2]);
2038*c2c66affSColin Finck               normalCallBack(temp_normal, userData);
2039*c2c66affSColin Finck 	      vertexCallBack(temp_vertex, userData);
2040*c2c66affSColin Finck 	    }
2041*c2c66affSColin Finck 	  else
2042*c2c66affSColin Finck #endif //GENERIC_TEST
2043*c2c66affSColin Finck 
2044*c2c66affSColin Finck 	    inDoEvalCoord2EM(u,v);
2045*c2c66affSColin Finck 
2046*c2c66affSColin Finck #endif //USE_LOD
2047*c2c66affSColin Finck 
2048*c2c66affSColin Finck 	  k += 2;
2049*c2c66affSColin Finck 	}
2050*c2c66affSColin Finck       endCallBack(userData);
2051*c2c66affSColin Finck 
2052*c2c66affSColin Finck #endif //USE_LOD
2053*c2c66affSColin Finck     }
2054*c2c66affSColin Finck }
2055*c2c66affSColin Finck 
inBPMListEvalEM(bezierPatchMesh * list)2056*c2c66affSColin Finck void OpenGLSurfaceEvaluator::inBPMListEvalEM(bezierPatchMesh* list)
2057*c2c66affSColin Finck {
2058*c2c66affSColin Finck   bezierPatchMesh* temp;
2059*c2c66affSColin Finck   for(temp = list; temp != NULL; temp = temp->next)
2060*c2c66affSColin Finck     {
2061*c2c66affSColin Finck       inBPMEvalEM(temp);
2062*c2c66affSColin Finck     }
2063*c2c66affSColin Finck }
2064*c2c66affSColin Finck 
2065