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.
38 * $Date$ $Revision: 1.1 $
39 * $Header: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/glu32/libnurbs/internals/patch.cc,v 1.1 2004/02/02 16:39:12 navaraf Exp $
43 #include "glimports.h"
51 #include "nurbsconsts.h"
52 #include "simplemath.h" //for glu_abs function in ::singleStep();
55 /*--------------------------------------------------------------------------
56 * Patch - copy patch from quilt and transform control points
57 *--------------------------------------------------------------------------
60 Patch::Patch( Quilt_ptr geo
, REAL
*pta
, REAL
*ptb
, Patch
*n
)
62 /* pspec[i].range is uninit here */
63 mapdesc
= geo
->mapdesc
;
64 cullval
= mapdesc
->isCulling() ? CULL_ACCEPT
: CULL_TRIVIAL_ACCEPT
;
65 notInBbox
= mapdesc
->isBboxSubdividing() ? 1 : 0;
66 needsSampling
= mapdesc
->isRangeSampling() ? 1 : 0;
67 pspec
[0].order
= geo
->qspec
[0].order
;
68 pspec
[1].order
= geo
->qspec
[1].order
;
69 pspec
[0].stride
= pspec
[1].order
* MAXCOORDS
;
70 pspec
[1].stride
= MAXCOORDS
;
72 /* transform control points to sampling and culling spaces */
74 geo
->select( pta
, ptb
);
75 ps
+= geo
->qspec
[0].offset
;
76 ps
+= geo
->qspec
[1].offset
;
77 ps
+= geo
->qspec
[0].index
* geo
->qspec
[0].order
* geo
->qspec
[0].stride
;
78 ps
+= geo
->qspec
[1].index
* geo
->qspec
[1].order
* geo
->qspec
[1].stride
;
81 mapdesc
->xformSampling( ps
, geo
->qspec
[0].order
, geo
->qspec
[0].stride
,
82 geo
->qspec
[1].order
, geo
->qspec
[1].stride
,
83 spts
, pspec
[0].stride
, pspec
[1].stride
);
86 if( cullval
== CULL_ACCEPT
) {
87 mapdesc
->xformCulling( ps
, geo
->qspec
[0].order
, geo
->qspec
[0].stride
,
88 geo
->qspec
[1].order
, geo
->qspec
[1].stride
,
89 cpts
, pspec
[0].stride
, pspec
[1].stride
);
93 mapdesc
->xformBounding( ps
, geo
->qspec
[0].order
, geo
->qspec
[0].stride
,
94 geo
->qspec
[1].order
, geo
->qspec
[1].stride
,
95 bpts
, pspec
[0].stride
, pspec
[1].stride
);
99 pspec
[0].range
[0] = geo
->qspec
[0].breakpoints
[geo
->qspec
[0].index
];
100 pspec
[0].range
[1] = geo
->qspec
[0].breakpoints
[geo
->qspec
[0].index
+1];
101 pspec
[0].range
[2] = pspec
[0].range
[1] - pspec
[0].range
[0];
103 pspec
[1].range
[0] = geo
->qspec
[1].breakpoints
[geo
->qspec
[1].index
];
104 pspec
[1].range
[1] = geo
->qspec
[1].breakpoints
[geo
->qspec
[1].index
+1];
105 pspec
[1].range
[2] = pspec
[1].range
[1] - pspec
[1].range
[0];
107 // may need to subdivide to match range of sub-patch
108 if( pspec
[0].range
[0] != pta
[0] ) {
109 assert( pspec
[0].range
[0] < pta
[0] );
110 Patch
lower( *this, 0, pta
[0], 0 );
114 if( pspec
[0].range
[1] != ptb
[0] ) {
115 assert( pspec
[0].range
[1] > ptb
[0] );
116 Patch
upper( *this, 0, ptb
[0], 0 );
119 if( pspec
[1].range
[0] != pta
[1] ) {
120 assert( pspec
[1].range
[0] < pta
[1] );
121 Patch
lower( *this, 1, pta
[1], 0 );
125 if( pspec
[1].range
[1] != ptb
[1] ) {
126 assert( pspec
[1].range
[1] > ptb
[1] );
127 Patch
upper( *this, 1, ptb
[1], 0 );
129 checkBboxConstraint();
133 /*--------------------------------------------------------------------------
134 * Patch - subdivide a patch along an isoparametric line
135 *--------------------------------------------------------------------------
138 Patch::Patch( Patch
& upper
, int param
, REAL value
, Patch
*n
)
140 Patch
& lower
= *this;
142 lower
.cullval
= upper
.cullval
;
143 lower
.mapdesc
= upper
.mapdesc
;
144 lower
.notInBbox
= upper
.notInBbox
;
145 lower
.needsSampling
= upper
.needsSampling
;
146 lower
.pspec
[0].order
= upper
.pspec
[0].order
;
147 lower
.pspec
[1].order
= upper
.pspec
[1].order
;
148 lower
.pspec
[0].stride
= upper
.pspec
[0].stride
;
149 lower
.pspec
[1].stride
= upper
.pspec
[1].stride
;
152 /* reset scale range */
155 REAL d
= (value
-upper
.pspec
[0].range
[0]) / upper
.pspec
[0].range
[2];
157 mapdesc
->subdivide( upper
.spts
, lower
.spts
, d
, pspec
[1].order
,
158 pspec
[1].stride
, pspec
[0].order
, pspec
[0].stride
);
160 if( cullval
== CULL_ACCEPT
)
161 mapdesc
->subdivide( upper
.cpts
, lower
.cpts
, d
, pspec
[1].order
,
162 pspec
[1].stride
, pspec
[0].order
, pspec
[0].stride
);
165 mapdesc
->subdivide( upper
.bpts
, lower
.bpts
, d
, pspec
[1].order
,
166 pspec
[1].stride
, pspec
[0].order
, pspec
[0].stride
);
168 lower
.pspec
[0].range
[0] = upper
.pspec
[0].range
[0];
169 lower
.pspec
[0].range
[1] = value
;
170 lower
.pspec
[0].range
[2] = value
- upper
.pspec
[0].range
[0];
171 upper
.pspec
[0].range
[0] = value
;
172 upper
.pspec
[0].range
[2] = upper
.pspec
[0].range
[1] - value
;
174 lower
.pspec
[1].range
[0] = upper
.pspec
[1].range
[0];
175 lower
.pspec
[1].range
[1] = upper
.pspec
[1].range
[1];
176 lower
.pspec
[1].range
[2] = upper
.pspec
[1].range
[2];
180 REAL d
= (value
-upper
.pspec
[1].range
[0]) / upper
.pspec
[1].range
[2];
182 mapdesc
->subdivide( upper
.spts
, lower
.spts
, d
, pspec
[0].order
,
183 pspec
[0].stride
, pspec
[1].order
, pspec
[1].stride
);
184 if( cullval
== CULL_ACCEPT
)
185 mapdesc
->subdivide( upper
.cpts
, lower
.cpts
, d
, pspec
[0].order
,
186 pspec
[0].stride
, pspec
[1].order
, pspec
[1].stride
);
188 mapdesc
->subdivide( upper
.bpts
, lower
.bpts
, d
, pspec
[0].order
,
189 pspec
[0].stride
, pspec
[1].order
, pspec
[1].stride
);
190 lower
.pspec
[0].range
[0] = upper
.pspec
[0].range
[0];
191 lower
.pspec
[0].range
[1] = upper
.pspec
[0].range
[1];
192 lower
.pspec
[0].range
[2] = upper
.pspec
[0].range
[2];
194 lower
.pspec
[1].range
[0] = upper
.pspec
[1].range
[0];
195 lower
.pspec
[1].range
[1] = value
;
196 lower
.pspec
[1].range
[2] = value
- upper
.pspec
[1].range
[0];
197 upper
.pspec
[1].range
[0] = value
;
198 upper
.pspec
[1].range
[2] = upper
.pspec
[1].range
[1] - value
;
203 // inherit bounding box
204 if( mapdesc
->isBboxSubdividing() && ! notInBbox
)
205 memcpy( lower
.bb
, upper
.bb
, sizeof( bb
) );
207 lower
.checkBboxConstraint();
208 upper
.checkBboxConstraint();
211 /*--------------------------------------------------------------------------
212 * clamp - clamp the sampling rate to a given maximum
213 *--------------------------------------------------------------------------
219 if( mapdesc
->clampfactor
!= N_NOCLAMPING
) {
220 pspec
[0].clamp( mapdesc
->clampfactor
);
221 pspec
[1].clamp( mapdesc
->clampfactor
);
226 Patchspec::clamp( REAL clampfactor
)
228 if( sidestep
[0] < minstepsize
)
229 sidestep
[0] = clampfactor
* minstepsize
;
230 if( sidestep
[1] < minstepsize
)
231 sidestep
[1] = clampfactor
* minstepsize
;
232 if( stepsize
< minstepsize
)
233 stepsize
= clampfactor
* minstepsize
;
237 Patch::checkBboxConstraint( void )
240 mapdesc
->bboxTooBig( bpts
, pspec
[0].stride
, pspec
[1].stride
,
241 pspec
[0].order
, pspec
[1].order
, bb
) != 1 ) {
249 if( mapdesc
->isBboxSubdividing() )
250 mapdesc
->surfbbox( bb
);
253 /*--------------------------------------------------------------------------
254 * getstepsize - compute the sampling density across the patch
255 * and determine if patch needs to be subdivided
256 *--------------------------------------------------------------------------
260 Patch::getstepsize( void )
262 pspec
[0].minstepsize
= pspec
[1].minstepsize
= 0;
263 pspec
[0].needsSubdivision
= pspec
[1].needsSubdivision
= 0;
265 if( mapdesc
->isConstantSampling() ) {
266 // fixed number of samples per patch in each direction
267 // maxsrate is number of s samples per patch
268 // maxtrate is number of t samples per patch
269 pspec
[0].getstepsize( mapdesc
->maxsrate
);
270 pspec
[1].getstepsize( mapdesc
->maxtrate
);
272 } else if( mapdesc
->isDomainSampling() ) {
273 // maxsrate is number of s samples per unit s length of domain
274 // maxtrate is number of t samples per unit t length of domain
275 pspec
[0].getstepsize( mapdesc
->maxsrate
* pspec
[0].range
[2] );
276 pspec
[1].getstepsize( mapdesc
->maxtrate
* pspec
[1].range
[2] );
278 } else if( ! needsSampling
) {
279 pspec
[0].singleStep();
280 pspec
[1].singleStep();
282 // upper bound on path length between sample points
283 REAL tmp
[MAXORDER
][MAXORDER
][MAXCOORDS
];
284 const int trstride
= sizeof(tmp
[0]) / sizeof(REAL
);
285 const int tcstride
= sizeof(tmp
[0][0]) / sizeof(REAL
);
287 assert( pspec
[0].order
<= MAXORDER
);
289 /* points have been transformed, therefore they are homogeneous */
291 int val
= mapdesc
->project( spts
, pspec
[0].stride
, pspec
[1].stride
,
292 &tmp
[0][0][0], trstride
, tcstride
,
293 pspec
[0].order
, pspec
[1].order
);
295 // control points cross infinity, therefore partials are undefined
296 pspec
[0].getstepsize( mapdesc
->maxsrate
);
297 pspec
[1].getstepsize( mapdesc
->maxtrate
);
299 REAL t1
= mapdesc
->getProperty( N_PIXEL_TOLERANCE
);
300 // REAL t2 = mapdesc->getProperty( N_ERROR_TOLERANCE );
301 pspec
[0].minstepsize
= ( mapdesc
->maxsrate
> 0.0 ) ?
302 (pspec
[0].range
[2] / mapdesc
->maxsrate
) : 0.0;
303 pspec
[1].minstepsize
= ( mapdesc
->maxtrate
> 0.0 ) ?
304 (pspec
[1].range
[2] / mapdesc
->maxtrate
) : 0.0;
305 if( mapdesc
->isParametricDistanceSampling() ||
306 mapdesc
->isObjectSpaceParaSampling() ) {
309 t2
= mapdesc
->getProperty( N_ERROR_TOLERANCE
);
311 // t2 is upper bound on the distance between surface and tessellant
313 REAL ss
= mapdesc
->calcPartialVelocity( ssv
, &tmp
[0][0][0], trstride
, tcstride
, pspec
[0].order
, pspec
[1].order
, 2, 0, pspec
[0].range
[2], pspec
[1].range
[2], 0 );
314 REAL st
= mapdesc
->calcPartialVelocity( 0, &tmp
[0][0][0], trstride
, tcstride
, pspec
[0].order
, pspec
[1].order
, 1, 1, pspec
[0].range
[2], pspec
[1].range
[2], -1 );
315 REAL tt
= mapdesc
->calcPartialVelocity( ttv
, &tmp
[0][0][0], trstride
, tcstride
, pspec
[0].order
, pspec
[1].order
, 0, 2, pspec
[0].range
[2], pspec
[1].range
[2], 1 );
316 //make sure that ss st and tt are nonnegative:
321 if( ss
!= 0.0 && tt
!= 0.0 ) {
322 /* printf( "ssv[0] %g ssv[1] %g ttv[0] %g ttv[1] %g\n",
323 ssv[0], ssv[1], ttv[0], ttv[1] ); */
324 REAL ttq
= sqrtf( (float) ss
);
325 REAL ssq
= sqrtf( (float) tt
);
326 REAL ds
= sqrtf( 4 * t2
* ttq
/ ( ss
* ttq
+ st
* ssq
) );
327 REAL dt
= sqrtf( 4 * t2
* ssq
/ ( tt
* ssq
+ st
* ttq
) );
328 pspec
[0].stepsize
= ( ds
< pspec
[0].range
[2] ) ? ds
: pspec
[0].range
[2];
329 REAL scutoff
= 2.0 * t2
/ ( pspec
[0].range
[2] * pspec
[0].range
[2]);
330 pspec
[0].sidestep
[0] = (ssv
[0] > scutoff
) ? sqrtf( 2.0 * t2
/ ssv
[0] ) : pspec
[0].range
[2];
331 pspec
[0].sidestep
[1] = (ssv
[1] > scutoff
) ? sqrtf( 2.0 * t2
/ ssv
[1] ) : pspec
[0].range
[2];
333 pspec
[1].stepsize
= ( dt
< pspec
[1].range
[2] ) ? dt
: pspec
[1].range
[2];
334 REAL tcutoff
= 2.0 * t2
/ ( pspec
[1].range
[2] * pspec
[1].range
[2]);
335 pspec
[1].sidestep
[0] = (ttv
[0] > tcutoff
) ? sqrtf( 2.0 * t2
/ ttv
[0] ) : pspec
[1].range
[2];
336 pspec
[1].sidestep
[1] = (ttv
[1] > tcutoff
) ? sqrtf( 2.0 * t2
/ ttv
[1] ) : pspec
[1].range
[2];
337 } else if( ss
!= 0.0 ) {
338 REAL x
= pspec
[1].range
[2] * st
;
339 REAL ds
= ( sqrtf( x
* x
+ 8.0 * t2
* ss
) - x
) / ss
;
340 pspec
[0].stepsize
= ( ds
< pspec
[0].range
[2] ) ? ds
: pspec
[0].range
[2];
341 REAL scutoff
= 2.0 * t2
/ ( pspec
[0].range
[2] * pspec
[0].range
[2]);
342 pspec
[0].sidestep
[0] = (ssv
[0] > scutoff
) ? sqrtf( 2.0 * t2
/ ssv
[0] ) : pspec
[0].range
[2];
343 pspec
[0].sidestep
[1] = (ssv
[1] > scutoff
) ? sqrtf( 2.0 * t2
/ ssv
[1] ) : pspec
[0].range
[2];
344 pspec
[1].singleStep();
345 } else if( tt
!= 0.0 ) {
346 REAL x
= pspec
[0].range
[2] * st
;
347 REAL dt
= ( sqrtf( x
* x
+ 8.0 * t2
* tt
) - x
) / tt
;
348 pspec
[0].singleStep();
349 REAL tcutoff
= 2.0 * t2
/ ( pspec
[1].range
[2] * pspec
[1].range
[2]);
350 pspec
[1].stepsize
= ( dt
< pspec
[1].range
[2] ) ? dt
: pspec
[1].range
[2];
351 pspec
[1].sidestep
[0] = (ttv
[0] > tcutoff
) ? sqrtf( 2.0 * t2
/ ttv
[0] ) : pspec
[1].range
[2];
352 pspec
[1].sidestep
[1] = (ttv
[1] > tcutoff
) ? sqrtf( 2.0 * t2
/ ttv
[1] ) : pspec
[1].range
[2];
354 if( 4.0 * t2
> st
* pspec
[0].range
[2] * pspec
[1].range
[2] ) {
355 pspec
[0].singleStep();
356 pspec
[1].singleStep();
358 REAL area
= 4.0 * t2
/ st
;
359 REAL ds
= sqrtf( area
* pspec
[0].range
[2] / pspec
[1].range
[2] );
360 REAL dt
= sqrtf( area
* pspec
[1].range
[2] / pspec
[0].range
[2] );
361 pspec
[0].stepsize
= ( ds
< pspec
[0].range
[2] ) ? ds
: pspec
[0].range
[2];
362 pspec
[0].sidestep
[0] = pspec
[0].range
[2];
363 pspec
[0].sidestep
[1] = pspec
[0].range
[2];
365 pspec
[1].stepsize
= ( dt
< pspec
[1].range
[2] ) ? dt
: pspec
[1].range
[2];
366 pspec
[1].sidestep
[0] = pspec
[1].range
[2];
367 pspec
[1].sidestep
[1] = pspec
[1].range
[2];
370 } else if( mapdesc
->isPathLengthSampling() ||
371 mapdesc
->isObjectSpacePathSampling()) {
372 // t1 is upper bound on path length
374 REAL ms
= mapdesc
->calcPartialVelocity( msv
, &tmp
[0][0][0], trstride
, tcstride
, pspec
[0].order
, pspec
[1].order
, 1, 0, pspec
[0].range
[2], pspec
[1].range
[2], 0 );
375 REAL mt
= mapdesc
->calcPartialVelocity( mtv
, &tmp
[0][0][0], trstride
, tcstride
, pspec
[0].order
, pspec
[1].order
, 0, 1, pspec
[0].range
[2], pspec
[1].range
[2], 1 );
376 REAL side_scale
= 1.0;
380 /* REAL d = t1 / ( ms * ms + mt * mt );*/
381 /* REAL ds = mt * d;*/
382 REAL ds
= t1
/ (2.0*ms
);
383 /* REAL dt = ms * d;*/
384 REAL dt
= t1
/ (2.0*mt
);
385 pspec
[0].stepsize
= ( ds
< pspec
[0].range
[2] ) ? ds
: pspec
[0].range
[2];
386 pspec
[0].sidestep
[0] = ( msv
[0] * pspec
[0].range
[2] > t1
) ? (side_scale
* t1
/ msv
[0]) : pspec
[0].range
[2];
387 pspec
[0].sidestep
[1] = ( msv
[1] * pspec
[0].range
[2] > t1
) ? (side_scale
* t1
/ msv
[1]) : pspec
[0].range
[2];
389 pspec
[1].stepsize
= ( dt
< pspec
[1].range
[2] ) ? dt
: pspec
[1].range
[2];
390 pspec
[1].sidestep
[0] = ( mtv
[0] * pspec
[1].range
[2] > t1
) ? (side_scale
*t1
/ mtv
[0]) : pspec
[1].range
[2];
391 pspec
[1].sidestep
[1] = ( mtv
[1] * pspec
[1].range
[2] > t1
) ? (side_scale
*t1
/ mtv
[1]) : pspec
[1].range
[2];
393 pspec
[0].stepsize
= ( t1
< ms
* pspec
[0].range
[2] ) ? (t1
/ ms
) : pspec
[0].range
[2];
394 pspec
[0].sidestep
[0] = ( msv
[0] * pspec
[0].range
[2] > t1
) ? (t1
/ msv
[0]) : pspec
[0].range
[2];
395 pspec
[0].sidestep
[1] = ( msv
[1] * pspec
[0].range
[2] > t1
) ? (t1
/ msv
[1]) : pspec
[0].range
[2];
397 pspec
[1].singleStep();
401 pspec
[0].singleStep();
403 pspec
[1].stepsize
= ( t1
< mt
* pspec
[1].range
[2] ) ? (t1
/ mt
) : pspec
[1].range
[2];
404 pspec
[1].sidestep
[0] = ( mtv
[0] * pspec
[1].range
[2] > t1
) ? (t1
/ mtv
[0]) : pspec
[1].range
[2];
405 pspec
[1].sidestep
[1] = ( mtv
[1] * pspec
[1].range
[2] > t1
) ? (t1
/ mtv
[1]) : pspec
[1].range
[2];
407 pspec
[0].singleStep();
408 pspec
[1].singleStep();
411 } else if( mapdesc
->isSurfaceAreaSampling() ) {
412 // t is the square root of area
415 REAL ms = mapdesc->calcPartialVelocity( msv, &tmp[0][0][0], trstride, tcstride, pspec[0].order, pspec[1].order, 1, 0, pspec[0].range[2], pspec[1].range[2], 0 );
416 REAL mt = mapdesc->calcPartialVelocity( mtv, &tmp[0][0][0], trstride, tcstride, pspec[0].order, pspec[1].order, 0, 1, pspec[0].range[2], pspec[1].range[2], 1 );
417 if( ms != 0.0 && mt != 0.0 ) {
418 REAL d = 1.0 / (ms * mt);
420 REAL ds = t * sqrtf( d * pspec[0].range[2] / pspec[1].range[2] );
421 REAL dt = t * sqrtf( d * pspec[1].range[2] / pspec[0].range[2] );
422 pspec[0].stepsize = ( ds < pspec[0].range[2] ) ? ds : pspec[0].range[2];
423 pspec[0].sidestep[0] = ( msv[0] * pspec[0].range[2] > t ) ? (t / msv[0]) : pspec[0].range[2];
424 pspec[0].sidestep[1] = ( msv[1] * pspec[0].range[2] > t ) ? (t / msv[1]) : pspec[0].range[2];
426 pspec[1].stepsize = ( dt < pspec[1].range[2] ) ? dt : pspec[1].range[2];
427 pspec[1].sidestep[0] = ( mtv[0] * pspec[1].range[2] > t ) ? (t / mtv[0]) : pspec[1].range[2];
428 pspec[1].sidestep[1] = ( mtv[1] * pspec[1].range[2] > t ) ? (t / mtv[1]) : pspec[1].range[2];
430 pspec[0].singleStep();
431 pspec[1].singleStep();
435 pspec
[0].singleStep();
436 pspec
[1].singleStep();
442 dprintf( "sidesteps %g %g %g %g, stepsize %g %g\n",
443 pspec
[0].sidestep
[0], pspec
[0].sidestep
[1],
444 pspec
[1].sidestep
[0], pspec
[1].sidestep
[1],
445 pspec
[0].stepsize
, pspec
[1].stepsize
);
448 if( mapdesc
->minsavings
!= N_NOSAVINGSSUBDIVISION
) {
449 REAL savings
= 1./(pspec
[0].stepsize
* pspec
[1].stepsize
) ;
450 savings
-= (2./( pspec
[0].sidestep
[0] + pspec
[0].sidestep
[1] )) *
451 (2./( pspec
[1].sidestep
[0] + pspec
[1].sidestep
[1] ));
453 savings
*= pspec
[0].range
[2] * pspec
[1].range
[2];
454 if( savings
> mapdesc
->minsavings
) {
455 pspec
[0].needsSubdivision
= pspec
[1].needsSubdivision
= 1;
459 if( pspec
[0].stepsize
< pspec
[0].minstepsize
) pspec
[0].needsSubdivision
= 1;
460 if( pspec
[1].stepsize
< pspec
[1].minstepsize
) pspec
[1].needsSubdivision
= 1;
461 needsSampling
= (needsSampling
? needsSamplingSubdivision() : 0);
465 Patchspec::singleStep()
467 stepsize
= sidestep
[0] = sidestep
[1] = glu_abs(range
[2]);
471 Patchspec::getstepsize( REAL max
) // max is number of samples for entire patch
473 stepsize
= ( max
>= 1.0 ) ? range
[2] / max
: range
[2];
474 if (stepsize
< 0.0) {
475 stepsize
= -stepsize
;
477 sidestep
[0] = sidestep
[1] = minstepsize
= stepsize
;
481 Patch::needsSamplingSubdivision( void )
483 return (pspec
[0].needsSubdivision
|| pspec
[1].needsSubdivision
) ? 1 : 0;
487 Patch::needsNonSamplingSubdivision( void )
493 Patch::needsSubdivision( int param
)
495 return pspec
[param
].needsSubdivision
;
499 Patch::cullCheck( void )
501 if( cullval
== CULL_ACCEPT
)
502 cullval
= mapdesc
->cullCheck( cpts
, pspec
[0].order
, pspec
[0].stride
,
503 pspec
[1].order
, pspec
[1].stride
);