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$ $Revision: 1.1 $
37 ** $Header: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/glu32/libnurbs/interface/insurfeval.cc,v 1.1 2004/02/02 16:39:08 navaraf 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
)