2 ** License Applicability. Except to the extent portions of this file are
3 ** made subject to an alternative license as permitted in the SGI Free
4 ** Software License B, Version 1.1 (the "License"), the contents of this
5 ** file are subject only to the provisions of the License. You may not use
6 ** this file except in compliance with the License. You may obtain a copy
7 ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
8 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
10 ** http://oss.sgi.com/projects/FreeB
12 ** Note that, as provided in the License, the Software is distributed on an
13 ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
14 ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
15 ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
16 ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
18 ** Original Code. The Original Code is: OpenGL Sample Implementation,
19 ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
20 ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
21 ** Copyright in any portions created by third parties is as indicated
22 ** elsewhere herein. All Rights Reserved.
24 ** Additional Notice Provisions: The application programming interfaces
25 ** established by SGI in conjunction with the Original Code are The
26 ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
27 ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
28 ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
29 ** Window System(R) (Version 1.3), released October 19, 1998. This software
30 ** was created using the OpenGL(R) version 1.2.1 Sample Implementation
31 ** published by SGI, but has not been independently verified as being
32 ** compliant with the OpenGL(R) version 1.2.1 Specification.
34 ** $Date: 2004/05/12 15:29:36 $ $Revision: 1.3 $
37 ** $Header: /home/krh/git/sync/mesa-cvs-repo/Mesa/src/glu/sgi/libnurbs/interface/insurfeval.cc,v 1.3 2004/05/12 15:29:36 brianp Exp $
47 #include "glsurfeval.h"
49 //extern int surfcount;
53 #define AVOID_ZERO_NORMAL
55 #ifdef AVOID_ZERO_NORMAL
56 #define myabs(x) ((x>0)? x: (-x))
57 #define MYZERO 0.000001
63 //#define LOD_EVAL_COORD(u,v) inDoEvalCoord2EM(u,v)
64 #define LOD_EVAL_COORD(u,v) glEvalCoord2f(u,v)
66 static void LOD_interpolate(REAL A[2], REAL B[2], REAL C[2], int j, int k, int pow2_level,
71 a = ((REAL) j) / ((REAL) pow2_level);
76 b = ((REAL) k) / ((REAL)j);
90 u = x*A[0] + y*B[0] + z*C[0];
91 v = x*A[1] + y*B[1] + z*C[1];
94 void OpenGLSurfaceEvaluator::LOD_triangle(REAL A[2], REAL B[2], REAL C[2],
102 for(j=0; j<level; j++)
104 for(j=0; j<=pow2_level-1; j++)
108 /* beginCallBack(GL_TRIANGLE_STRIP);*/
109 glBegin(GL_TRIANGLE_STRIP);
110 LOD_interpolate(A,B,C, j+1, j+1, pow2_level, u,v);
113 // glEvalCoord2f(u,v);
115 inDoEvalCoord2EM(u,v);
120 LOD_interpolate(A,B,C,j,j-k,pow2_level, u,v);
123 // glEvalCoord2f(u,v);
125 inDoEvalCoord2EM(u,v);
128 LOD_interpolate(A,B,C,j+1,j-k,pow2_level, u,v);
132 // glEvalCoord2f(u,v);
134 inDoEvalCoord2EM(u,v);
142 void OpenGLSurfaceEvaluator::LOD_eval(int num_vert, REAL* verts, int type,
148 case GL_TRIANGLE_STRIP:
150 for(i=2, k=4; i<=num_vert-2; i+=2, k+=4)
152 LOD_triangle(verts+k-4, verts+k-2, verts+k,
155 LOD_triangle(verts+k-2, verts+k+2, verts+k,
161 LOD_triangle(verts+2*(num_vert-3), verts+2*(num_vert-2), verts+2*(num_vert-1),
166 case GL_TRIANGLE_FAN:
167 for(i=1, k=2; i<=num_vert-2; i++, k+=2)
169 LOD_triangle(verts,verts+k, verts+k+2,
176 fprintf(stderr, "typy not supported in LOD_\n");
183 //#define GENERIC_TEST
185 extern float xmin, xmax, ymin, ymax, zmin, zmax; /*bounding box*/
186 extern int temp_signal;
188 static void gTessVertexSphere(float u, float v, float temp_normal[3], float temp_vertex[3])
191 float Ox = 0.5*(xmin+xmax);
192 float Oy = 0.5*(ymin+ymax);
193 float Oz = 0.5*(zmin+zmax);
194 float nx = cos(v) * sin(u);
195 float ny = sin(v) * sin(u);
208 // glNormal3f(nx,ny,nz);
209 // glVertex3f(x,y,z);
212 static void gTessVertexCyl(float u, float v, float temp_normal[3], float temp_vertex[3])
215 float Ox = 0.5*(xmin+xmax);
216 float Oy = 0.5*(ymin+ymax);
217 float Oz = 0.5*(zmin+zmax);
233 glNormal3f(nx,ny,nz);
238 #endif //GENERIC_TEST
240 void OpenGLSurfaceEvaluator::inBPMListEval(bezierPatchMesh* list)
242 bezierPatchMesh* temp;
243 for(temp = list; temp != NULL; temp = temp->next)
249 void OpenGLSurfaceEvaluator::inBPMEval(bezierPatchMesh* bpm)
254 int ustride = bpm->bpatch->dimension * bpm->bpatch->vorder;
255 int vstride = bpm->bpatch->dimension;
257 (bpm->bpatch->dimension == 3)? GL_MAP2_VERTEX_3 : GL_MAP2_VERTEX_4,
266 bpm->bpatch->ctlpoints);
268 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.*/
269 assert(bpm->vertex_array);
270 bpm->normal_array = (float*) malloc(sizeof(float)* (bpm->index_UVarray/2) * 3);
271 assert(bpm->normal_array);
273 if( global_ev_u1 ==2 && global_ev_u2 == 3
274 && global_ev_v1 ==2 && global_ev_v2 == 3)
279 printf("***number 1\n");
282 beginCallBack(GL_QUAD_STRIP, NULL);
283 inEvalCoord2f(3.0, 3.0);
284 inEvalCoord2f(2.0, 3.0);
285 inEvalCoord2f(3.0, 2.7);
286 inEvalCoord2f(2.0, 2.7);
287 inEvalCoord2f(3.0, 2.0);
288 inEvalCoord2f(2.0, 2.0);
292 beginCallBack(GL_TRIANGLE_STRIP, NULL);
293 inEvalCoord2f(2.0, 3.0);
294 inEvalCoord2f(2.0, 2.0);
295 inEvalCoord2f(2.0, 2.7);
301 if( global_ev_u1 ==2 && global_ev_u2 == 3
302 && global_ev_v1 ==1 && global_ev_v2 == 2)
305 printf("***number 2\n");
307 beginCallBack(GL_QUAD_STRIP);
308 inEvalCoord2f(2.0, 2.0);
309 inEvalCoord2f(2.0, 1.0);
310 inEvalCoord2f(3.0, 2.0);
311 inEvalCoord2f(3.0, 1.0);
315 if( global_ev_u1 ==1 && global_ev_u2 == 2
316 && global_ev_v1 ==2 && global_ev_v2 == 3)
319 printf("***number 3\n");
321 beginCallBack(GL_QUAD_STRIP, NULL);
322 inEvalCoord2f(2.0, 3.0);
323 inEvalCoord2f(1.0, 3.0);
324 inEvalCoord2f(2.0, 2.3);
325 inEvalCoord2f(1.0, 2.3);
326 inEvalCoord2f(2.0, 2.0);
327 inEvalCoord2f(1.0, 2.0);
330 beginCallBack(GL_TRIANGLE_STRIP, NULL);
331 inEvalCoord2f(2.0, 2.3);
332 inEvalCoord2f(2.0, 2.0);
333 inEvalCoord2f(2.0, 3.0);
343 for(i=0; i<bpm->index_length_array; i++)
345 beginCallBack(bpm->type_array[i], userData);
346 for(j=0; j<bpm->length_array[i]; j++)
349 v = bpm->UVarray[k+1];
350 inDoEvalCoord2NOGE(u,v,
352 bpm->normal_array+l);
354 normalCallBack(bpm->normal_array+l, userData);
355 vertexCallBack(bpm->vertex_array+l, userData);
360 endCallBack(userData);
364 void OpenGLSurfaceEvaluator::inEvalPoint2(int i, int j)
370 du = (global_grid_u1 - global_grid_u0) / (REAL)global_grid_nu;
371 dv = (global_grid_v1 - global_grid_v0) / (REAL)global_grid_nv;
372 u = (i==global_grid_nu)? global_grid_u1:(global_grid_u0 + i*du);
373 v = (j == global_grid_nv)? global_grid_v1: (global_grid_v0 +j*dv);
374 inDoEvalCoord2(u,v,point,normal);
377 void OpenGLSurfaceEvaluator::inEvalCoord2f(REAL u, REAL v)
382 inDoEvalCoord2(u,v,point, normal);
387 /*define a grid. store the values into the global variabls:
389 *These values will be used later by evaluating functions
391 void OpenGLSurfaceEvaluator::inMapGrid2f(int nu, REAL u0, REAL u1,
392 int nv, REAL v0, REAL v1)
402 void OpenGLSurfaceEvaluator::inEvalMesh2(int lowU, int lowV, int highU, int highV)
408 if(global_grid_nu == 0 || global_grid_nv == 0)
409 return; /*no points need to be output*/
410 du = (global_grid_u1 - global_grid_u0) / (REAL)global_grid_nu;
411 dv = (global_grid_v1 - global_grid_v0) / (REAL)global_grid_nv;
413 if(global_grid_nu >= global_grid_nv){
414 for(i=lowU; i<highU; i++){
415 REAL u1 = (i==global_grid_nu)? global_grid_u1:(global_grid_u0 + i*du);
416 REAL u2 = ((i+1) == global_grid_nu)? global_grid_u1: (global_grid_u0+(i+1)*du);
419 for(j=highV; j>=lowV; j--){
420 REAL v1 = (j == global_grid_nv)? global_grid_v1: (global_grid_v0 +j*dv);
422 inDoEvalCoord2(u1, v1, point, normal);
423 inDoEvalCoord2(u2, v1, point, normal);
430 for(i=lowV; i<highV; i++){
431 REAL v1 = (i==global_grid_nv)? global_grid_v1:(global_grid_v0 + i*dv);
432 REAL v2 = ((i+1) == global_grid_nv)? global_grid_v1: (global_grid_v0+(i+1)*dv);
435 for(j=highU; j>=lowU; j--){
436 REAL u1 = (j == global_grid_nu)? global_grid_u1: (global_grid_u0 +j*du);
437 inDoEvalCoord2(u1, v2, point, normal);
438 inDoEvalCoord2(u1, v1, point, normal);
446 void OpenGLSurfaceEvaluator::inMap2f(int k,
458 REAL *data = global_ev_ctlPoints;
462 if(k == GL_MAP2_VERTEX_3) k=3;
463 else if (k==GL_MAP2_VERTEX_4) k =4;
465 printf("error in inMap2f, maptype=%i is wrong, k,map is not updated\n", k);
470 global_ev_u1 = ulower;
471 global_ev_u2 = uupper;
472 global_ev_ustride = ustride;
473 global_ev_uorder = uorder;
474 global_ev_v1 = vlower;
475 global_ev_v2 = vupper;
476 global_ev_vstride = vstride;
477 global_ev_vorder = vorder;
479 /*copy the contrl points from ctlPoints to global_ev_ctlPoints*/
480 for (i=0; i<uorder; i++) {
481 for (j=0; j<vorder; j++) {
482 for (x=0; x<k; x++) {
483 data[x] = ctlPoints[x];
485 ctlPoints += vstride;
488 ctlPoints += ustride - vstride * vorder;
495 *given a point p with homegeneous coordiante (x,y,z,w),
496 *let pu(x,y,z,w) be its partial derivative vector with
498 *and pv(x,y,z,w) be its partial derivative vector with repect to v.
499 *This function returns the partial derivative vectors of the
500 *inhomegensous coordinates, i.e.,
501 * (x/w, y/w, z/w) with respect to u and v.
503 void OpenGLSurfaceEvaluator::inComputeFirstPartials(REAL *p, REAL *pu, REAL *pv)
505 pu[0] = pu[0]*p[3] - pu[3]*p[0];
506 pu[1] = pu[1]*p[3] - pu[3]*p[1];
507 pu[2] = pu[2]*p[3] - pu[3]*p[2];
509 pv[0] = pv[0]*p[3] - pv[3]*p[0];
510 pv[1] = pv[1]*p[3] - pv[3]*p[1];
511 pv[2] = pv[2]*p[3] - pv[3]*p[2];
514 /*compute the cross product of pu and pv and normalize.
515 *the normal is returned in retNormal
518 * n: return normal, of dimension 3
520 void OpenGLSurfaceEvaluator::inComputeNormal2(REAL *pu, REAL *pv, REAL *n)
524 n[0] = pu[1]*pv[2] - pu[2]*pv[1];
525 n[1] = pu[2]*pv[0] - pu[0]*pv[2];
526 n[2] = pu[0]*pv[1] - pu[1]*pv[0];
528 mag = sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
539 /*Compute point and normal
540 *see the head of inDoDomain2WithDerivs
541 *for the meaning of the arguments
543 void OpenGLSurfaceEvaluator::inDoEvalCoord2(REAL u, REAL v,
544 REAL *retPoint, REAL *retNormal)
551 assert(global_ev_k>=3 && global_ev_k <= 4);
552 /*compute homegeneous point and partial derivatives*/
553 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);
555 #ifdef AVOID_ZERO_NORMAL
557 if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
562 REAL u1 = global_ev_u1;
563 REAL u2 = global_ev_u2;
564 if(u-MYDELTA*(u2-u1) < u1)
565 u = u+ MYDELTA*(u2-u1);
567 u = u-MYDELTA*(u2-u1);
568 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);
570 if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
574 REAL v1 = global_ev_v1;
575 REAL v2 = global_ev_v2;
576 if(v-MYDELTA*(v2-v1) < v1)
577 v = v+ MYDELTA*(v2-v1);
579 v = v-MYDELTA*(v2-v1);
580 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);
588 inComputeNormal2(du, dv, retNormal);
592 inComputeFirstPartials(retPoint, du, dv);
593 inComputeNormal2(du, dv, retNormal);
594 /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
595 retPoint[0] /= retPoint[3];
596 retPoint[1] /= retPoint[3];
597 retPoint[2] /= retPoint[3];
600 /*output this vertex*/
601 /* inMeshStreamInsert(global_ms, retPoint, retNormal);*/
605 glNormal3fv(retNormal);
606 glVertex3fv(retPoint);
612 printf("vertex(%f,%f,%f)\n", retPoint[0],retPoint[1],retPoint[2]);
619 /*Compute point and normal
620 *see the head of inDoDomain2WithDerivs
621 *for the meaning of the arguments
623 void OpenGLSurfaceEvaluator::inDoEvalCoord2NOGE_BU(REAL u, REAL v,
624 REAL *retPoint, REAL *retNormal)
631 assert(global_ev_k>=3 && global_ev_k <= 4);
632 /*compute homegeneous point and partial derivatives*/
633 // inPreEvaluateBU(global_ev_k, global_ev_uorder, global_ev_vorder, (u-global_ev_u1)/(global_ev_u2-global_ev_u1), global_ev_ctlPoints);
634 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);
637 #ifdef AVOID_ZERO_NORMAL
639 if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
644 REAL u1 = global_ev_u1;
645 REAL u2 = global_ev_u2;
646 if(u-MYDELTA*(u2-u1) < u1)
647 u = u+ MYDELTA*(u2-u1);
649 u = u-MYDELTA*(u2-u1);
650 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);
652 if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
656 REAL v1 = global_ev_v1;
657 REAL v2 = global_ev_v2;
658 if(v-MYDELTA*(v2-v1) < v1)
659 v = v+ MYDELTA*(v2-v1);
661 v = v-MYDELTA*(v2-v1);
662 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);
669 inComputeNormal2(du, dv, retNormal);
672 inComputeFirstPartials(retPoint, du, dv);
673 inComputeNormal2(du, dv, retNormal);
674 /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
675 retPoint[0] /= retPoint[3];
676 retPoint[1] /= retPoint[3];
677 retPoint[2] /= retPoint[3];
682 /*Compute point and normal
683 *see the head of inDoDomain2WithDerivs
684 *for the meaning of the arguments
686 void OpenGLSurfaceEvaluator::inDoEvalCoord2NOGE_BV(REAL u, REAL v,
687 REAL *retPoint, REAL *retNormal)
694 assert(global_ev_k>=3 && global_ev_k <= 4);
695 /*compute homegeneous point and partial derivatives*/
696 // inPreEvaluateBV(global_ev_k, global_ev_uorder, global_ev_vorder, (v-global_ev_v1)/(global_ev_v2-global_ev_v1), global_ev_ctlPoints);
698 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);
701 #ifdef AVOID_ZERO_NORMAL
703 if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
708 REAL u1 = global_ev_u1;
709 REAL u2 = global_ev_u2;
710 if(u-MYDELTA*(u2-u1) < u1)
711 u = u+ MYDELTA*(u2-u1);
713 u = u-MYDELTA*(u2-u1);
714 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);
716 if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
720 REAL v1 = global_ev_v1;
721 REAL v2 = global_ev_v2;
722 if(v-MYDELTA*(v2-v1) < v1)
723 v = v+ MYDELTA*(v2-v1);
725 v = v-MYDELTA*(v2-v1);
726 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);
733 inComputeNormal2(du, dv, retNormal);
736 inComputeFirstPartials(retPoint, du, dv);
737 inComputeNormal2(du, dv, retNormal);
738 /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
739 retPoint[0] /= retPoint[3];
740 retPoint[1] /= retPoint[3];
741 retPoint[2] /= retPoint[3];
747 /*Compute point and normal
748 *see the head of inDoDomain2WithDerivs
749 *for the meaning of the arguments
751 void OpenGLSurfaceEvaluator::inDoEvalCoord2NOGE(REAL u, REAL v,
752 REAL *retPoint, REAL *retNormal)
759 assert(global_ev_k>=3 && global_ev_k <= 4);
760 /*compute homegeneous point and partial derivatives*/
761 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);
764 #ifdef AVOID_ZERO_NORMAL
766 if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
771 REAL u1 = global_ev_u1;
772 REAL u2 = global_ev_u2;
773 if(u-MYDELTA*(u2-u1) < u1)
774 u = u+ MYDELTA*(u2-u1);
776 u = u-MYDELTA*(u2-u1);
777 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);
779 if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
783 REAL v1 = global_ev_v1;
784 REAL v2 = global_ev_v2;
785 if(v-MYDELTA*(v2-v1) < v1)
786 v = v+ MYDELTA*(v2-v1);
788 v = v-MYDELTA*(v2-v1);
789 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);
796 inComputeNormal2(du, dv, retNormal);
799 inComputeFirstPartials(retPoint, du, dv);
800 inComputeNormal2(du, dv, retNormal);
801 /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
802 retPoint[0] /= retPoint[3];
803 retPoint[1] /= retPoint[3];
804 retPoint[2] /= retPoint[3];
807 // glNormal3fv(retNormal);
808 // glVertex3fv(retPoint);
811 void OpenGLSurfaceEvaluator::inPreEvaluateBV(int k, int uorder, int vorder, REAL vprime, REAL *baseData)
817 if(global_vprime != vprime || global_vorder != vorder) {
818 inPreEvaluateWithDeriv(vorder, vprime, global_vcoeff, global_vcoeffDeriv);
819 global_vprime = vprime;
820 global_vorder = vorder;
825 for(row=0; row<uorder; row++){
826 p = global_vcoeff[0] * (*data);
827 pdv = global_vcoeffDeriv[0] * (*data);
829 for(col = 1; col < vorder; col++){
830 p += global_vcoeff[col] * (*data);
831 pdv += global_vcoeffDeriv[col] * (*data);
834 global_BV[row][j] = p;
835 global_PBV[row][j] = pdv;
840 void OpenGLSurfaceEvaluator::inPreEvaluateBU(int k, int uorder, int vorder, REAL uprime, REAL *baseData)
846 if(global_uprime != uprime || global_uorder != uorder) {
847 inPreEvaluateWithDeriv(uorder, uprime, global_ucoeff, global_ucoeffDeriv);
848 global_uprime = uprime;
849 global_uorder = uorder;
854 for(col=0; col<vorder; col++){
855 data = baseData+j + k*col;
856 p = global_ucoeff[0] * (*data);
857 pdu = global_ucoeffDeriv[0] * (*data);
859 for(row = 1; row < uorder; row++){
860 p += global_ucoeff[row] * (*data);
861 pdu += global_ucoeffDeriv[row] * (*data);
864 global_BU[col][j] = p;
865 global_PBU[col][j] = pdu;
870 void OpenGLSurfaceEvaluator::inDoDomain2WithDerivsBU(int k, REAL u, REAL v,
871 REAL u1, REAL u2, int uorder,
872 REAL v1, REAL v2, int vorder,
874 REAL *retPoint, REAL* retdu, REAL *retdv)
881 if((u2 == u1) || (v2 == v1))
884 vprime = (v - v1) / (v2 - v1);
887 if(global_vprime != vprime || global_vorder != vorder) {
888 inPreEvaluateWithDeriv(vorder, vprime, global_vcoeff, global_vcoeffDeriv);
889 global_vprime = vprime;
890 global_vorder = vorder;
896 retPoint[j] = retdu[j] = retdv[j] = 0.0;
897 for (col = 0; col < vorder; col++) {
898 retPoint[j] += global_BU[col][j] * global_vcoeff[col];
899 retdu[j] += global_PBU[col][j] * global_vcoeff[col];
900 retdv[j] += global_BU[col][j] * global_vcoeffDeriv[col];
905 void OpenGLSurfaceEvaluator::inDoDomain2WithDerivsBV(int k, REAL u, REAL v,
906 REAL u1, REAL u2, int uorder,
907 REAL v1, REAL v2, int vorder,
909 REAL *retPoint, REAL* retdu, REAL *retdv)
915 if((u2 == u1) || (v2 == v1))
917 uprime = (u - u1) / (u2 - u1);
920 if(global_uprime != uprime || global_uorder != uorder) {
921 inPreEvaluateWithDeriv(uorder, uprime, global_ucoeff, global_ucoeffDeriv);
922 global_uprime = uprime;
923 global_uorder = uorder;
929 retPoint[j] = retdu[j] = retdv[j] = 0.0;
930 for (row = 0; row < uorder; row++) {
931 retPoint[j] += global_BV[row][j] * global_ucoeff[row];
932 retdu[j] += global_BV[row][j] * global_ucoeffDeriv[row];
933 retdv[j] += global_PBV[row][j] * global_ucoeff[row];
940 *given a Bezier surface, and parameter (u,v), compute the point in the object space,
942 *k: the dimension of the object space: usually 2,3,or 4.
943 *u,v: the paramter pair.
944 *u1,u2,uorder: the Bezier polynomial of u coord is defined on [u1,u2] with order uorder.
945 *v1,v2,vorder: the Bezier polynomial of v coord is defined on [v1,v2] with order vorder.
946 *baseData: contrl points. arranged as: (u,v,k).
947 *retPoint: the computed point (one point) with dimension k.
948 *retdu: the computed partial derivative with respect to u.
949 *retdv: the computed partial derivative with respect to v.
951 void OpenGLSurfaceEvaluator::inDoDomain2WithDerivs(int k, REAL u, REAL v,
952 REAL u1, REAL u2, int uorder,
953 REAL v1, REAL v2, int vorder,
955 REAL *retPoint, REAL *retdu, REAL *retdv)
964 if((u2 == u1) || (v2 == v1))
966 uprime = (u - u1) / (u2 - u1);
967 vprime = (v - v1) / (v2 - v1);
969 /* Compute coefficients for values and derivs */
971 /* Use already cached values if possible */
972 if(global_uprime != uprime || global_uorder != uorder) {
973 inPreEvaluateWithDeriv(uorder, uprime, global_ucoeff, global_ucoeffDeriv);
974 global_uorder = uorder;
975 global_uprime = uprime;
977 if (global_vprime != vprime ||
978 global_vorder != vorder) {
979 inPreEvaluateWithDeriv(vorder, vprime, global_vcoeff, global_vcoeffDeriv);
980 global_vorder = vorder;
981 global_vprime = vprime;
984 for (j = 0; j < k; j++) {
986 retPoint[j] = retdu[j] = retdv[j] = 0.0;
987 for (row = 0; row < uorder; row++) {
989 ** Minor optimization.
990 ** The col == 0 part of the loop is extracted so we don't
991 ** have to initialize p and pdv to 0.
993 p = global_vcoeff[0] * (*data);
994 pdv = global_vcoeffDeriv[0] * (*data);
996 for (col = 1; col < vorder; col++) {
997 /* Incrementally build up p, pdv value */
998 p += global_vcoeff[col] * (*data);
999 pdv += global_vcoeffDeriv[col] * (*data);
1002 /* Use p, pdv value to incrementally add up r, du, dv */
1003 retPoint[j] += global_ucoeff[row] * p;
1004 retdu[j] += global_ucoeffDeriv[row] * p;
1005 retdv[j] += global_ucoeff[row] * pdv;
1012 *compute the Bezier polynomials C[n,j](v) for all j at v with
1013 *return values stored in coeff[], where
1014 * C[n,j](v) = (n,j) * v^j * (1-v)^(n-j),
1018 *coeff : coeff[j]=C[n,j](v), this array store the returned values.
1019 *The algorithm is a recursive scheme:
1021 * C[n,j](v) = (1-v)*C[n-1,j](v) + v*C[n-1,j-1](v), n>=1
1022 *This code is copied from opengl/soft/so_eval.c:PreEvaluate
1024 void OpenGLSurfaceEvaluator::inPreEvaluate(int order, REAL vprime, REAL *coeff)
1028 REAL oneMinusvprime;
1031 * Minor optimization
1032 * Compute orders 1 and 2 outright, and set coeff[0], coeff[1] to
1033 * their i==1 loop values to avoid the initialization and the i==1 loop.
1040 oneMinusvprime = 1-vprime;
1041 coeff[0] = oneMinusvprime;
1043 if (order == 2) return;
1045 for (i = 2; i < order; i++) {
1046 oldval = coeff[0] * vprime;
1047 coeff[0] = oneMinusvprime * coeff[0];
1048 for (j = 1; j < i; j++) {
1050 oldval = coeff[j] * vprime;
1051 coeff[j] = temp + oneMinusvprime * coeff[j];
1058 *compute the Bezier polynomials C[n,j](v) and derivatives for all j at v with
1059 *return values stored in coeff[] and coeffDeriv[].
1060 *see the head of function inPreEvaluate for the definition of C[n,j](v)
1061 *and how to compute the values.
1062 *The algorithm to compute the derivative is:
1064 * dC[n,j](v) = n*(dC[n-1,j-1](v) - dC[n-1,j](v)).
1066 *This code is copied from opengl/soft/so_eval.c:PreEvaluateWidthDeriv
1068 void OpenGLSurfaceEvaluator::inPreEvaluateWithDeriv(int order, REAL vprime,
1069 REAL *coeff, REAL *coeffDeriv)
1073 REAL oneMinusvprime;
1075 oneMinusvprime = 1-vprime;
1077 * Minor optimization
1078 * Compute orders 1 and 2 outright, and set coeff[0], coeff[1] to
1079 * their i==1 loop values to avoid the initialization and the i==1 loop.
1083 coeffDeriv[0] = 0.0;
1085 } else if (order == 2) {
1086 coeffDeriv[0] = -1.0;
1087 coeffDeriv[1] = 1.0;
1088 coeff[0] = oneMinusvprime;
1092 coeff[0] = oneMinusvprime;
1094 for (i = 2; i < order - 1; i++) {
1095 oldval = coeff[0] * vprime;
1096 coeff[0] = oneMinusvprime * coeff[0];
1097 for (j = 1; j < i; j++) {
1099 oldval = coeff[j] * vprime;
1100 coeff[j] = temp + oneMinusvprime * coeff[j];
1104 coeffDeriv[0] = -coeff[0];
1106 ** Minor optimization:
1107 ** Would make this a "for (j=1; j<order-1; j++)" loop, but it is always
1108 ** executed at least once, so this is more efficient.
1112 coeffDeriv[j] = coeff[j-1] - coeff[j];
1114 } while (j < order - 1);
1115 coeffDeriv[j] = coeff[j-1];
1117 oldval = coeff[0] * vprime;
1118 coeff[0] = oneMinusvprime * coeff[0];
1119 for (j = 1; j < i; j++) {
1121 oldval = coeff[j] * vprime;
1122 coeff[j] = temp + oneMinusvprime * coeff[j];
1127 void OpenGLSurfaceEvaluator::inEvalULine(int n_points, REAL v, REAL* u_vals,
1128 int stride, REAL ret_points[][3], REAL ret_normals[][3])
1132 inPreEvaluateBV_intfac(v);
1134 for(i=0,k=0; i<n_points; i++, k += stride)
1136 inDoEvalCoord2NOGE_BV(u_vals[k],v,temp, ret_normals[i]);
1138 ret_points[i][0] = temp[0];
1139 ret_points[i][1] = temp[1];
1140 ret_points[i][2] = temp[2];
1146 void OpenGLSurfaceEvaluator::inEvalVLine(int n_points, REAL u, REAL* v_vals,
1147 int stride, REAL ret_points[][3], REAL ret_normals[][3])
1151 inPreEvaluateBU_intfac(u);
1152 for(i=0,k=0; i<n_points; i++, k += stride)
1154 inDoEvalCoord2NOGE_BU(u, v_vals[k], temp, ret_normals[i]);
1155 ret_points[i][0] = temp[0];
1156 ret_points[i][1] = temp[1];
1157 ret_points[i][2] = temp[2];
1162 /*triangulate a strip bounded by two lines which are parallel to U-axis
1163 *upperVerts: the verteces on the upper line
1164 *lowerVertx: the verteces on the lower line
1168 void OpenGLSurfaceEvaluator::inEvalUStrip(int n_upper, REAL v_upper, REAL* upper_val, int n_lower, REAL v_lower, REAL* lower_val)
1172 typedef REAL REAL3[3];
1174 REAL3* upperXYZ = (REAL3*) malloc(sizeof(REAL3)*n_upper);
1176 REAL3* upperNormal = (REAL3*) malloc(sizeof(REAL3) * n_upper);
1177 assert(upperNormal);
1178 REAL3* lowerXYZ = (REAL3*) malloc(sizeof(REAL3)*n_lower);
1180 REAL3* lowerNormal = (REAL3*) malloc(sizeof(REAL3) * n_lower);
1181 assert(lowerNormal);
1183 inEvalULine(n_upper, v_upper, upper_val, 1, upperXYZ, upperNormal);
1184 inEvalULine(n_lower, v_lower, lower_val, 1, lowerXYZ, lowerNormal);
1189 REAL* leftMostNormal;
1192 *the algorithm works by scanning from left to right.
1193 *leftMostV: the left most of the remaining verteces (on both upper and lower).
1194 * it could an element of upperVerts or lowerVerts.
1195 *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 */
1197 /*initialize i,j,and leftMostV
1199 if(upper_val[0] <= lower_val[0])
1204 leftMostV[0] = upper_val[0];
1205 leftMostV[1] = v_upper;
1206 leftMostXYZ = upperXYZ[0];
1207 leftMostNormal = upperNormal[0];
1214 leftMostV[0] = lower_val[0];
1215 leftMostV[1] = v_lower;
1217 leftMostXYZ = lowerXYZ[0];
1218 leftMostNormal = lowerNormal[0];
1222 *the invariance is that:
1223 *at the beginning of each loop, the meaning of i,j,and leftMostV are
1228 if(i >= n_upper) /*case1: no more in upper*/
1230 if(j<n_lower-1) /*at least two vertices in lower*/
1233 glNormal3fv(leftMostNormal);
1234 glVertex3fv(leftMostXYZ);
1237 glNormal3fv(lowerNormal[j]);
1238 glVertex3fv(lowerXYZ[j]);
1244 break; /*exit the main loop*/
1246 else if(j>= n_lower) /*case2: no more in lower*/
1248 if(i<n_upper-1) /*at least two vertices in upper*/
1251 glNormal3fv(leftMostNormal);
1252 glVertex3fv(leftMostXYZ);
1254 for(k=n_upper-1; k>=i; k--) /*reverse order for two-side lighting*/
1256 glNormal3fv(upperNormal[k]);
1257 glVertex3fv(upperXYZ[k]);
1262 break; /*exit the main loop*/
1264 else /* case3: neither is empty, plus the leftMostV, there is at least one triangle to output*/
1266 if(upper_val[i] <= lower_val[j])
1270 glNormal3fv(lowerNormal[j]);
1271 glVertex3fv(lowerXYZ[j]);
1273 /*find the last k>=i such that
1274 *upperverts[k][0] <= lowerverts[j][0]
1280 if(upper_val[k] > lower_val[j])
1288 for(l=k; l>=i; l--)/*the reverse is for two-side lighting*/
1290 glNormal3fv(upperNormal[l]);
1291 glVertex3fv(upperXYZ[l]);
1294 glNormal3fv(leftMostNormal);
1295 glVertex3fv(leftMostXYZ);
1299 /*update i and leftMostV for next loop
1303 leftMostV[0] = upper_val[k];
1304 leftMostV[1] = v_upper;
1305 leftMostNormal = upperNormal[k];
1306 leftMostXYZ = upperXYZ[k];
1308 else /*upperVerts[i][0] > lowerVerts[j][0]*/
1311 glNormal3fv(upperNormal[i]);
1312 glVertex3fv(upperXYZ[i]);
1314 glNormal3fv(leftMostNormal);
1315 glVertex3fv(leftMostXYZ);
1318 /*find the last k>=j such that
1319 *lowerverts[k][0] < upperverts[i][0]
1324 if(lower_val[k] >= upper_val[i])
1326 glNormal3fv(lowerNormal[k]);
1327 glVertex3fv(lowerXYZ[k]);
1333 /*update j and leftMostV for next loop
1336 leftMostV[0] = lower_val[j-1];
1337 leftMostV[1] = v_lower;
1339 leftMostNormal = lowerNormal[j-1];
1340 leftMostXYZ = lowerXYZ[j-1];
1351 /*triangulate a strip bounded by two lines which are parallel to V-axis
1352 *leftVerts: the verteces on the left line
1353 *rightVertx: the verteces on the right line
1357 void OpenGLSurfaceEvaluator::inEvalVStrip(int n_left, REAL u_left, REAL* left_val, int n_right, REAL u_right, REAL* right_val)
1361 typedef REAL REAL3[3];
1363 REAL3* leftXYZ = (REAL3*) malloc(sizeof(REAL3)*n_left);
1365 REAL3* leftNormal = (REAL3*) malloc(sizeof(REAL3) * n_left);
1367 REAL3* rightXYZ = (REAL3*) malloc(sizeof(REAL3)*n_right);
1369 REAL3* rightNormal = (REAL3*) malloc(sizeof(REAL3) * n_right);
1370 assert(rightNormal);
1372 inEvalVLine(n_left, u_left, left_val, 1, leftXYZ, leftNormal);
1373 inEvalVLine(n_right, u_right, right_val, 1, rightXYZ, rightNormal);
1378 REAL* botMostNormal;
1381 *the algorithm works by scanning from bot to top.
1382 *botMostV: the bot most of the remaining verteces (on both left and right).
1383 * it could an element of leftVerts or rightVerts.
1384 *i: leftVerts[i] is the first vertex to the top of botMostV on left line
1385 *j: rightVerts[j] is the first vertex to the top of botMostV on rightline */
1387 /*initialize i,j,and botMostV
1389 if(left_val[0] <= right_val[0])
1394 botMostV[0] = u_left;
1395 botMostV[1] = left_val[0];
1396 botMostXYZ = leftXYZ[0];
1397 botMostNormal = leftNormal[0];
1404 botMostV[0] = u_right;
1405 botMostV[1] = right_val[0];
1407 botMostXYZ = rightXYZ[0];
1408 botMostNormal = rightNormal[0];
1412 *the invariance is that:
1413 *at the beginning of each loop, the meaning of i,j,and botMostV are
1418 if(i >= n_left) /*case1: no more in left*/
1420 if(j<n_right-1) /*at least two vertices in right*/
1423 glNormal3fv(botMostNormal);
1424 glVertex3fv(botMostXYZ);
1427 glNormal3fv(rightNormal[j]);
1428 glVertex3fv(rightXYZ[j]);
1434 break; /*exit the main loop*/
1436 else if(j>= n_right) /*case2: no more in right*/
1438 if(i<n_left-1) /*at least two vertices in left*/
1441 glNormal3fv(botMostNormal);
1442 glVertex3fv(botMostXYZ);
1444 for(k=n_left-1; k>=i; k--) /*reverse order for two-side lighting*/
1446 glNormal3fv(leftNormal[k]);
1447 glVertex3fv(leftXYZ[k]);
1452 break; /*exit the main loop*/
1454 else /* case3: neither is empty, plus the botMostV, there is at least one triangle to output*/
1456 if(left_val[i] <= right_val[j])
1460 glNormal3fv(rightNormal[j]);
1461 glVertex3fv(rightXYZ[j]);
1463 /*find the last k>=i such that
1464 *leftverts[k][0] <= rightverts[j][0]
1470 if(left_val[k] > right_val[j])
1478 for(l=k; l>=i; l--)/*the reverse is for two-side lighting*/
1480 glNormal3fv(leftNormal[l]);
1481 glVertex3fv(leftXYZ[l]);
1484 glNormal3fv(botMostNormal);
1485 glVertex3fv(botMostXYZ);
1489 /*update i and botMostV for next loop
1493 botMostV[0] = u_left;
1494 botMostV[1] = left_val[k];
1495 botMostNormal = leftNormal[k];
1496 botMostXYZ = leftXYZ[k];
1498 else /*left_val[i] > right_val[j])*/
1501 glNormal3fv(leftNormal[i]);
1502 glVertex3fv(leftXYZ[i]);
1504 glNormal3fv(botMostNormal);
1505 glVertex3fv(botMostXYZ);
1508 /*find the last k>=j such that
1509 *rightverts[k][0] < leftverts[i][0]
1514 if(right_val[k] >= left_val[i])
1516 glNormal3fv(rightNormal[k]);
1517 glVertex3fv(rightXYZ[k]);
1523 /*update j and botMostV for next loop
1526 botMostV[0] = u_right;
1527 botMostV[1] = right_val[j-1];
1529 botMostNormal = rightNormal[j-1];
1530 botMostXYZ = rightXYZ[j-1];
1541 /*-----------------------begin evalMachine-------------------*/
1542 void OpenGLSurfaceEvaluator::inMap2fEM(int which, int k,
1554 surfEvalMachine *temp_em;
1558 temp_em = &em_vertex;
1562 temp_em = &em_normal;
1566 temp_em = &em_color;
1570 temp_em = &em_texcoord;
1574 REAL *data = temp_em->ctlPoints;
1576 temp_em->uprime = -1;//initilized
1577 temp_em->vprime = -1;
1580 temp_em->u1 = ulower;
1581 temp_em->u2 = uupper;
1582 temp_em->ustride = ustride;
1583 temp_em->uorder = uorder;
1584 temp_em->v1 = vlower;
1585 temp_em->v2 = vupper;
1586 temp_em->vstride = vstride;
1587 temp_em->vorder = vorder;
1589 /*copy the contrl points from ctlPoints to global_ev_ctlPoints*/
1590 for (i=0; i<uorder; i++) {
1591 for (j=0; j<vorder; j++) {
1592 for (x=0; x<k; x++) {
1593 data[x] = ctlPoints[x];
1595 ctlPoints += vstride;
1598 ctlPoints += ustride - vstride * vorder;
1602 void OpenGLSurfaceEvaluator::inDoDomain2WithDerivsEM(surfEvalMachine *em, REAL u, REAL v,
1603 REAL *retPoint, REAL *retdu, REAL *retdv)
1612 if((em->u2 == em->u1) || (em->v2 == em->v1))
1614 the_uprime = (u - em->u1) / (em->u2 - em->u1);
1615 the_vprime = (v - em->v1) / (em->v2 - em->v1);
1617 /* Compute coefficients for values and derivs */
1619 /* Use already cached values if possible */
1620 if(em->uprime != the_uprime) {
1621 inPreEvaluateWithDeriv(em->uorder, the_uprime, em->ucoeff, em->ucoeffDeriv);
1622 em->uprime = the_uprime;
1624 if (em->vprime != the_vprime) {
1625 inPreEvaluateWithDeriv(em->vorder, the_vprime, em->vcoeff, em->vcoeffDeriv);
1626 em->vprime = the_vprime;
1629 for (j = 0; j < em->k; j++) {
1630 data=em->ctlPoints+j;
1631 retPoint[j] = retdu[j] = retdv[j] = 0.0;
1632 for (row = 0; row < em->uorder; row++) {
1634 ** Minor optimization.
1635 ** The col == 0 part of the loop is extracted so we don't
1636 ** have to initialize p and pdv to 0.
1638 p = em->vcoeff[0] * (*data);
1639 pdv = em->vcoeffDeriv[0] * (*data);
1641 for (col = 1; col < em->vorder; col++) {
1642 /* Incrementally build up p, pdv value */
1643 p += em->vcoeff[col] * (*data);
1644 pdv += em->vcoeffDeriv[col] * (*data);
1647 /* Use p, pdv value to incrementally add up r, du, dv */
1648 retPoint[j] += em->ucoeff[row] * p;
1649 retdu[j] += em->ucoeffDeriv[row] * p;
1650 retdv[j] += em->ucoeff[row] * pdv;
1655 void OpenGLSurfaceEvaluator::inDoDomain2EM(surfEvalMachine *em, REAL u, REAL v,
1664 if((em->u2 == em->u1) || (em->v2 == em->v1))
1666 the_uprime = (u - em->u1) / (em->u2 - em->u1);
1667 the_vprime = (v - em->v1) / (em->v2 - em->v1);
1669 /* Compute coefficients for values and derivs */
1671 /* Use already cached values if possible */
1672 if(em->uprime != the_uprime) {
1673 inPreEvaluate(em->uorder, the_uprime, em->ucoeff);
1674 em->uprime = the_uprime;
1676 if (em->vprime != the_vprime) {
1677 inPreEvaluate(em->vorder, the_vprime, em->vcoeff);
1678 em->vprime = the_vprime;
1681 for (j = 0; j < em->k; j++) {
1682 data=em->ctlPoints+j;
1684 for (row = 0; row < em->uorder; row++) {
1686 ** Minor optimization.
1687 ** The col == 0 part of the loop is extracted so we don't
1688 ** have to initialize p and pdv to 0.
1690 p = em->vcoeff[0] * (*data);
1692 for (col = 1; col < em->vorder; col++) {
1693 /* Incrementally build up p, pdv value */
1694 p += em->vcoeff[col] * (*data);
1697 /* Use p, pdv value to incrementally add up r, du, dv */
1698 retPoint[j] += em->ucoeff[row] * p;
1704 void OpenGLSurfaceEvaluator::inDoEvalCoord2EM(REAL u, REAL v)
1706 REAL temp_vertex[5];
1707 REAL temp_normal[3];
1709 REAL temp_texcoord[4];
1713 inDoDomain2EM(&em_texcoord, u,v, temp_texcoord);
1714 texcoordCallBack(temp_texcoord, userData);
1718 inDoDomain2EM(&em_color, u,v, temp_color);
1719 colorCallBack(temp_color, userData);
1722 if(normal_flag) //there is a normla map
1724 inDoDomain2EM(&em_normal, u,v, temp_normal);
1725 normalCallBack(temp_normal, userData);
1729 inDoDomain2EM(&em_vertex, u,v,temp_vertex);
1730 if(em_vertex.k == 4)
1732 temp_vertex[0] /= temp_vertex[3];
1733 temp_vertex[1] /= temp_vertex[3];
1734 temp_vertex[2] /= temp_vertex[3];
1738 vertexCallBack(temp_vertex, userData);
1741 else if(auto_normal_flag) //no normal map but there is a normal callbackfunctin
1746 /*compute homegeneous point and partial derivatives*/
1747 inDoDomain2WithDerivsEM(&em_vertex, u,v,temp_vertex,du,dv);
1750 inComputeFirstPartials(temp_vertex, du, dv);
1752 #ifdef AVOID_ZERO_NORMAL
1753 if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
1758 REAL u1 = em_vertex.u1;
1759 REAL u2 = em_vertex.u2;
1760 if(u-MYDELTA*(u2-u1) < u1)
1761 u = u+ MYDELTA*(u2-u1);
1763 u = u-MYDELTA*(u2-u1);
1764 inDoDomain2WithDerivsEM(&em_vertex,u,v, tempdata, tempdu, dv);
1767 inComputeFirstPartials(temp_vertex, du, dv);
1769 else if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
1773 REAL v1 = em_vertex.v1;
1774 REAL v2 = em_vertex.v2;
1775 if(v-MYDELTA*(v2-v1) < v1)
1776 v = v+ MYDELTA*(v2-v1);
1778 v = v-MYDELTA*(v2-v1);
1779 inDoDomain2WithDerivsEM(&em_vertex,u,v, tempdata, du, tempdv);
1782 inComputeFirstPartials(temp_vertex, du, dv);
1787 switch(em_vertex.k){
1790 inComputeNormal2(du, dv, temp_normal);
1794 // inComputeFirstPartials(temp_vertex, du, dv);
1795 inComputeNormal2(du, dv, temp_normal);
1797 /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
1798 temp_vertex[0] /= temp_vertex[3];
1799 temp_vertex[1] /= temp_vertex[3];
1800 temp_vertex[2] /= temp_vertex[3];
1803 normalCallBack(temp_normal, userData);
1806 vertexCallBack(temp_vertex, userData);
1808 }/*end if auto_normal*/
1809 else //no normal map, and no normal callback function
1813 inDoDomain2EM(&em_vertex, u,v,temp_vertex);
1814 if(em_vertex.k == 4)
1816 temp_vertex[0] /= temp_vertex[3];
1817 temp_vertex[1] /= temp_vertex[3];
1818 temp_vertex[2] /= temp_vertex[3];
1822 vertexCallBack(temp_vertex, userData);
1828 void OpenGLSurfaceEvaluator::inBPMEvalEM(bezierPatchMesh* bpm)
1837 if(bpm->bpatch != NULL)
1839 bezierPatch* p=bpm->bpatch;
1840 ustride = p->dimension * p->vorder;
1841 vstride = p->dimension;
1843 glMap2f( (p->dimension == 3)? GL_MAP2_VERTEX_3 : GL_MAP2_VERTEX_4,
1856 inMap2fEM(0, p->dimension,
1870 if(bpm->bpatch != NULL){
1871 bezierPatch* p = bpm->bpatch;
1872 ustride = p->dimension * p->vorder;
1873 vstride = p->dimension;
1874 inMap2fEM(0, p->dimension,
1885 if(bpm->bpatch_normal != NULL){
1886 bezierPatch* p = bpm->bpatch_normal;
1887 ustride = p->dimension * p->vorder;
1888 vstride = p->dimension;
1889 inMap2fEM(1, p->dimension,
1900 if(bpm->bpatch_color != NULL){
1901 bezierPatch* p = bpm->bpatch_color;
1902 ustride = p->dimension * p->vorder;
1903 vstride = p->dimension;
1904 inMap2fEM(2, p->dimension,
1915 if(bpm->bpatch_texcoord != NULL){
1916 bezierPatch* p = bpm->bpatch_texcoord;
1917 ustride = p->dimension * p->vorder;
1918 vstride = p->dimension;
1919 inMap2fEM(3, p->dimension,
1934 for(i=0; i<bpm->index_length_array; i++)
1937 if(bpm->type_array[i] == GL_POLYGON) //a mesh
1939 GLfloat *temp = bpm->UVarray+k;
1940 GLfloat u0 = temp[0];
1941 GLfloat v0 = temp[1];
1942 GLfloat u1 = temp[2];
1943 GLfloat v1 = temp[3];
1944 GLint nu = (GLint) ( temp[4]);
1945 GLint nv = (GLint) ( temp[5]);
1946 GLint umin = (GLint) ( temp[6]);
1947 GLint vmin = (GLint) ( temp[7]);
1948 GLint umax = (GLint) ( temp[8]);
1949 GLint vmax = (GLint) ( temp[9]);
1951 glMapGrid2f(LOD_eval_level*nu, u0, u1, LOD_eval_level*nv, v0, v1);
1952 glEvalMesh2(GL_FILL, LOD_eval_level*umin, LOD_eval_level*umax, LOD_eval_level*vmin, LOD_eval_level*vmax);
1956 LOD_eval(bpm->length_array[i], bpm->UVarray+k, bpm->type_array[i],
1960 k+= 2*bpm->length_array[i];
1962 #else //undef USE_LOD
1965 if( bpm->bpatch->umin == 2 && bpm->bpatch->umax == 3
1966 && bpm->bpatch->vmin ==2 && bpm->bpatch->vmax == 3)
1971 printf("***number ****1\n");
1974 beginCallBack(GL_QUAD_STRIP, NULL);
1975 inDoEvalCoord2EM(3.0, 3.0);
1976 inDoEvalCoord2EM(2.0, 3.0);
1977 inDoEvalCoord2EM(3.0, 2.7);
1978 inDoEvalCoord2EM(2.0, 2.7);
1979 inDoEvalCoord2EM(3.0, 2.0);
1980 inDoEvalCoord2EM(2.0, 2.0);
1983 beginCallBack(GL_TRIANGLE_STRIP, NULL);
1984 inDoEvalCoord2EM(2.0, 3.0);
1985 inDoEvalCoord2EM(2.0, 2.0);
1986 inDoEvalCoord2EM(2.0, 2.7);
1990 if( bpm->bpatch->umin == 1 && bpm->bpatch->umax == 2
1991 && bpm->bpatch->vmin ==2 && bpm->bpatch->vmax == 3)
1994 printf("***number 3\n");
1996 beginCallBack(GL_QUAD_STRIP, NULL);
1997 inDoEvalCoord2EM(2.0, 3.0);
1998 inDoEvalCoord2EM(1.0, 3.0);
1999 inDoEvalCoord2EM(2.0, 2.3);
2000 inDoEvalCoord2EM(1.0, 2.3);
2001 inDoEvalCoord2EM(2.0, 2.0);
2002 inDoEvalCoord2EM(1.0, 2.0);
2005 beginCallBack(GL_TRIANGLE_STRIP, NULL);
2006 inDoEvalCoord2EM(2.0, 2.3);
2007 inDoEvalCoord2EM(2.0, 2.0);
2008 inDoEvalCoord2EM(2.0, 3.0);
2015 beginCallBack(bpm->type_array[i], userData);
2017 for(j=0; j<bpm->length_array[i]; j++)
2019 u = bpm->UVarray[k];
2020 v = bpm->UVarray[k+1];
2022 LOD_EVAL_COORD(u,v);
2023 // glEvalCoord2f(u,v);
2027 float temp_normal[3];
2028 float temp_vertex[3];
2029 if(temp_signal == 0)
2031 gTessVertexSphere(u,v, temp_normal, temp_vertex);
2032 //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]);
2033 normalCallBack(temp_normal, userData);
2034 vertexCallBack(temp_vertex, userData);
2036 else if(temp_signal == 1)
2038 gTessVertexCyl(u,v, temp_normal, temp_vertex);
2039 //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]);
2040 normalCallBack(temp_normal, userData);
2041 vertexCallBack(temp_vertex, userData);
2044 #endif //GENERIC_TEST
2046 inDoEvalCoord2EM(u,v);
2052 endCallBack(userData);
2058 void OpenGLSurfaceEvaluator::inBPMListEvalEM(bezierPatchMesh* list)
2060 bezierPatchMesh* temp;
2061 for(temp = list; temp != NULL; temp = temp->next)