1 /* 2 ** License Applicability. Except to the extent portions of this file are 3 ** made subject to an alternative license as permitted in the SGI Free 4 ** Software License B, Version 1.1 (the "License"), the contents of this 5 ** file are subject only to the provisions of the License. You may not use 6 ** this file except in compliance with the License. You may obtain a copy 7 ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 8 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: 9 ** 10 ** http://oss.sgi.com/projects/FreeB 11 ** 12 ** Note that, as provided in the License, the Software is distributed on an 13 ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS 14 ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND 15 ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A 16 ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. 17 ** 18 ** Original Code. The Original Code is: OpenGL Sample Implementation, 19 ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, 20 ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. 21 ** Copyright in any portions created by third parties is as indicated 22 ** elsewhere herein. All Rights Reserved. 23 ** 24 ** Additional Notice Provisions: The application programming interfaces 25 ** established by SGI in conjunction with the Original Code are The 26 ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released 27 ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version 28 ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X 29 ** Window System(R) (Version 1.3), released October 19, 1998. This software 30 ** was created using the OpenGL(R) version 1.2.1 Sample Implementation 31 ** published by SGI, but has not been independently verified as being 32 ** compliant with the OpenGL(R) version 1.2.1 Specification. 33 */ 34 35 /* 36 * patch.c++ 37 * 38 */ 39 40 //#include <stdio.h> 41 //#include "glimports.h" 42 //#include "mystdio.h" 43 //#include "myassert.h" 44 #include "mymath.h" 45 //#include "mystring.h" 46 #include "patch.h" 47 #include "mapdesc.h" 48 #include "quilt.h" 49 //#include "nurbsconsts.h" 50 #include "simplemath.h" //for glu_abs function in ::singleStep(); 51 52 53 /*-------------------------------------------------------------------------- 54 * Patch - copy patch from quilt and transform control points 55 *-------------------------------------------------------------------------- 56 */ 57 58 Patch::Patch( Quilt_ptr geo, REAL *pta, REAL *ptb, Patch *n ) 59 { 60 /* pspec[i].range is uninit here */ 61 mapdesc = geo->mapdesc; 62 cullval = mapdesc->isCulling() ? CULL_ACCEPT : CULL_TRIVIAL_ACCEPT; 63 notInBbox = mapdesc->isBboxSubdividing() ? 1 : 0; 64 needsSampling = mapdesc->isRangeSampling() ? 1 : 0; 65 pspec[0].order = geo->qspec[0].order; 66 pspec[1].order = geo->qspec[1].order; 67 pspec[0].stride = pspec[1].order * MAXCOORDS; 68 pspec[1].stride = MAXCOORDS; 69 70 /* transform control points to sampling and culling spaces */ 71 REAL *ps = geo->cpts; 72 geo->select( pta, ptb ); 73 ps += geo->qspec[0].offset; 74 ps += geo->qspec[1].offset; 75 ps += geo->qspec[0].index * geo->qspec[0].order * geo->qspec[0].stride; 76 ps += geo->qspec[1].index * geo->qspec[1].order * geo->qspec[1].stride; 77 78 if( needsSampling ) { 79 mapdesc->xformSampling( ps, geo->qspec[0].order, geo->qspec[0].stride, 80 geo->qspec[1].order, geo->qspec[1].stride, 81 spts, pspec[0].stride, pspec[1].stride ); 82 } 83 84 if( cullval == CULL_ACCEPT ) { 85 mapdesc->xformCulling( ps, geo->qspec[0].order, geo->qspec[0].stride, 86 geo->qspec[1].order, geo->qspec[1].stride, 87 cpts, pspec[0].stride, pspec[1].stride ); 88 } 89 90 if( notInBbox ) { 91 mapdesc->xformBounding( ps, geo->qspec[0].order, geo->qspec[0].stride, 92 geo->qspec[1].order, geo->qspec[1].stride, 93 bpts, pspec[0].stride, pspec[1].stride ); 94 } 95 96 /* set scale range */ 97 pspec[0].range[0] = geo->qspec[0].breakpoints[geo->qspec[0].index]; 98 pspec[0].range[1] = geo->qspec[0].breakpoints[geo->qspec[0].index+1]; 99 pspec[0].range[2] = pspec[0].range[1] - pspec[0].range[0]; 100 101 pspec[1].range[0] = geo->qspec[1].breakpoints[geo->qspec[1].index]; 102 pspec[1].range[1] = geo->qspec[1].breakpoints[geo->qspec[1].index+1]; 103 pspec[1].range[2] = pspec[1].range[1] - pspec[1].range[0]; 104 105 // may need to subdivide to match range of sub-patch 106 if( pspec[0].range[0] != pta[0] ) { 107 assert( pspec[0].range[0] < pta[0] ); 108 Patch lower( *this, 0, pta[0], 0 ); 109 *this = lower; 110 } 111 112 if( pspec[0].range[1] != ptb[0] ) { 113 assert( pspec[0].range[1] > ptb[0] ); 114 Patch upper( *this, 0, ptb[0], 0 ); 115 } 116 117 if( pspec[1].range[0] != pta[1] ) { 118 assert( pspec[1].range[0] < pta[1] ); 119 Patch lower( *this, 1, pta[1], 0 ); 120 *this = lower; 121 } 122 123 if( pspec[1].range[1] != ptb[1] ) { 124 assert( pspec[1].range[1] > ptb[1] ); 125 Patch upper( *this, 1, ptb[1], 0 ); 126 } 127 checkBboxConstraint(); 128 next = n; 129 } 130 131 /*-------------------------------------------------------------------------- 132 * Patch - subdivide a patch along an isoparametric line 133 *-------------------------------------------------------------------------- 134 */ 135 136 Patch::Patch( Patch& upper, int param, REAL value, Patch *n ) 137 { 138 Patch& lower = *this; 139 140 lower.cullval = upper.cullval; 141 lower.mapdesc = upper.mapdesc; 142 lower.notInBbox = upper.notInBbox; 143 lower.needsSampling = upper.needsSampling; 144 lower.pspec[0].order = upper.pspec[0].order; 145 lower.pspec[1].order = upper.pspec[1].order; 146 lower.pspec[0].stride = upper.pspec[0].stride; 147 lower.pspec[1].stride = upper.pspec[1].stride; 148 lower.next = n; 149 150 /* reset scale range */ 151 switch( param ) { 152 case 0: { 153 REAL d = (value-upper.pspec[0].range[0]) / upper.pspec[0].range[2]; 154 if( needsSampling ) 155 mapdesc->subdivide( upper.spts, lower.spts, d, pspec[1].order, 156 pspec[1].stride, pspec[0].order, pspec[0].stride ); 157 158 if( cullval == CULL_ACCEPT ) 159 mapdesc->subdivide( upper.cpts, lower.cpts, d, pspec[1].order, 160 pspec[1].stride, pspec[0].order, pspec[0].stride ); 161 162 if( notInBbox ) 163 mapdesc->subdivide( upper.bpts, lower.bpts, d, pspec[1].order, 164 pspec[1].stride, pspec[0].order, pspec[0].stride ); 165 166 lower.pspec[0].range[0] = upper.pspec[0].range[0]; 167 lower.pspec[0].range[1] = value; 168 lower.pspec[0].range[2] = value - upper.pspec[0].range[0]; 169 upper.pspec[0].range[0] = value; 170 upper.pspec[0].range[2] = upper.pspec[0].range[1] - value; 171 172 lower.pspec[1].range[0] = upper.pspec[1].range[0]; 173 lower.pspec[1].range[1] = upper.pspec[1].range[1]; 174 lower.pspec[1].range[2] = upper.pspec[1].range[2]; 175 break; 176 } 177 case 1: { 178 REAL d = (value-upper.pspec[1].range[0]) / upper.pspec[1].range[2]; 179 if( needsSampling ) 180 mapdesc->subdivide( upper.spts, lower.spts, d, pspec[0].order, 181 pspec[0].stride, pspec[1].order, pspec[1].stride ); 182 if( cullval == CULL_ACCEPT ) 183 mapdesc->subdivide( upper.cpts, lower.cpts, d, pspec[0].order, 184 pspec[0].stride, pspec[1].order, pspec[1].stride ); 185 if( notInBbox ) 186 mapdesc->subdivide( upper.bpts, lower.bpts, d, pspec[0].order, 187 pspec[0].stride, pspec[1].order, pspec[1].stride ); 188 lower.pspec[0].range[0] = upper.pspec[0].range[0]; 189 lower.pspec[0].range[1] = upper.pspec[0].range[1]; 190 lower.pspec[0].range[2] = upper.pspec[0].range[2]; 191 192 lower.pspec[1].range[0] = upper.pspec[1].range[0]; 193 lower.pspec[1].range[1] = value; 194 lower.pspec[1].range[2] = value - upper.pspec[1].range[0]; 195 upper.pspec[1].range[0] = value; 196 upper.pspec[1].range[2] = upper.pspec[1].range[1] - value; 197 break; 198 } 199 } 200 201 // inherit bounding box 202 if( mapdesc->isBboxSubdividing() && ! notInBbox ) 203 memcpy( lower.bb, upper.bb, sizeof( bb ) ); 204 205 lower.checkBboxConstraint(); 206 upper.checkBboxConstraint(); 207 } 208 209 /*-------------------------------------------------------------------------- 210 * clamp - clamp the sampling rate to a given maximum 211 *-------------------------------------------------------------------------- 212 */ 213 214 void 215 Patch::clamp( void ) 216 { 217 if( mapdesc->clampfactor != N_NOCLAMPING ) { 218 pspec[0].clamp( mapdesc->clampfactor ); 219 pspec[1].clamp( mapdesc->clampfactor ); 220 } 221 } 222 223 void 224 Patchspec::clamp( REAL clampfactor ) 225 { 226 if( sidestep[0] < minstepsize ) 227 sidestep[0] = clampfactor * minstepsize; 228 if( sidestep[1] < minstepsize ) 229 sidestep[1] = clampfactor * minstepsize; 230 if( stepsize < minstepsize ) 231 stepsize = clampfactor * minstepsize; 232 } 233 234 void 235 Patch::checkBboxConstraint( void ) 236 { 237 if( notInBbox && 238 mapdesc->bboxTooBig( bpts, pspec[0].stride, pspec[1].stride, 239 pspec[0].order, pspec[1].order, bb ) != 1 ) { 240 notInBbox = 0; 241 } 242 } 243 244 void 245 Patch::bbox( void ) 246 { 247 if( mapdesc->isBboxSubdividing() ) 248 mapdesc->surfbbox( bb ); 249 } 250 251 /*-------------------------------------------------------------------------- 252 * getstepsize - compute the sampling density across the patch 253 * and determine if patch needs to be subdivided 254 *-------------------------------------------------------------------------- 255 */ 256 257 void 258 Patch::getstepsize( void ) 259 { 260 pspec[0].minstepsize = pspec[1].minstepsize = 0; 261 pspec[0].needsSubdivision = pspec[1].needsSubdivision = 0; 262 263 if( mapdesc->isConstantSampling() ) { 264 // fixed number of samples per patch in each direction 265 // maxsrate is number of s samples per patch 266 // maxtrate is number of t samples per patch 267 pspec[0].getstepsize( mapdesc->maxsrate ); 268 pspec[1].getstepsize( mapdesc->maxtrate ); 269 270 } else if( mapdesc->isDomainSampling() ) { 271 // maxsrate is number of s samples per unit s length of domain 272 // maxtrate is number of t samples per unit t length of domain 273 pspec[0].getstepsize( mapdesc->maxsrate * pspec[0].range[2] ); 274 pspec[1].getstepsize( mapdesc->maxtrate * pspec[1].range[2] ); 275 276 } else if( ! needsSampling ) { 277 pspec[0].singleStep(); 278 pspec[1].singleStep(); 279 } else { 280 // upper bound on path length between sample points 281 REAL tmp[MAXORDER][MAXORDER][MAXCOORDS]; 282 const int trstride = sizeof(tmp[0]) / sizeof(REAL); 283 const int tcstride = sizeof(tmp[0][0]) / sizeof(REAL); 284 285 assert( pspec[0].order <= MAXORDER ); 286 287 /* points have been transformed, therefore they are homogeneous */ 288 289 int val = mapdesc->project( spts, pspec[0].stride, pspec[1].stride, 290 &tmp[0][0][0], trstride, tcstride, 291 pspec[0].order, pspec[1].order ); 292 if( val == 0 ) { 293 // control points cross infinity, therefore partials are undefined 294 pspec[0].getstepsize( mapdesc->maxsrate ); 295 pspec[1].getstepsize( mapdesc->maxtrate ); 296 } else { 297 REAL t1 = mapdesc->getProperty( N_PIXEL_TOLERANCE ); 298 // REAL t2 = mapdesc->getProperty( N_ERROR_TOLERANCE ); 299 pspec[0].minstepsize = ( mapdesc->maxsrate > 0.0 ) ? 300 (pspec[0].range[2] / mapdesc->maxsrate) : 0.0; 301 pspec[1].minstepsize = ( mapdesc->maxtrate > 0.0 ) ? 302 (pspec[1].range[2] / mapdesc->maxtrate) : 0.0; 303 if( mapdesc->isParametricDistanceSampling() || 304 mapdesc->isObjectSpaceParaSampling() ) { 305 306 REAL t2; 307 t2 = mapdesc->getProperty( N_ERROR_TOLERANCE ); 308 309 // t2 is upper bound on the distance between surface and tessellant 310 REAL ssv[2], ttv[2]; 311 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 ); 312 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 ); 313 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 ); 314 //make sure that ss st and tt are nonnegative: 315 if(ss <0) ss = -ss; 316 if(st <0) st = -st; 317 if(tt <0) tt = -tt; 318 319 if( ss != 0.0 && tt != 0.0 ) { 320 /* printf( "ssv[0] %g ssv[1] %g ttv[0] %g ttv[1] %g\n", 321 ssv[0], ssv[1], ttv[0], ttv[1] ); */ 322 REAL ttq = sqrtf( (float) ss ); 323 REAL ssq = sqrtf( (float) tt ); 324 REAL ds = sqrtf( 4 * t2 * ttq / ( ss * ttq + st * ssq ) ); 325 REAL dt = sqrtf( 4 * t2 * ssq / ( tt * ssq + st * ttq ) ); 326 pspec[0].stepsize = ( ds < pspec[0].range[2] ) ? ds : pspec[0].range[2]; 327 REAL scutoff = 2.0 * t2 / ( pspec[0].range[2] * pspec[0].range[2]); 328 pspec[0].sidestep[0] = (ssv[0] > scutoff) ? sqrtf( 2.0 * t2 / ssv[0] ) : pspec[0].range[2]; 329 pspec[0].sidestep[1] = (ssv[1] > scutoff) ? sqrtf( 2.0 * t2 / ssv[1] ) : pspec[0].range[2]; 330 331 pspec[1].stepsize = ( dt < pspec[1].range[2] ) ? dt : pspec[1].range[2]; 332 REAL tcutoff = 2.0 * t2 / ( pspec[1].range[2] * pspec[1].range[2]); 333 pspec[1].sidestep[0] = (ttv[0] > tcutoff) ? sqrtf( 2.0 * t2 / ttv[0] ) : pspec[1].range[2]; 334 pspec[1].sidestep[1] = (ttv[1] > tcutoff) ? sqrtf( 2.0 * t2 / ttv[1] ) : pspec[1].range[2]; 335 } else if( ss != 0.0 ) { 336 REAL x = pspec[1].range[2] * st; 337 REAL ds = ( sqrtf( x * x + 8.0 * t2 * ss ) - x ) / ss; 338 pspec[0].stepsize = ( ds < pspec[0].range[2] ) ? ds : pspec[0].range[2]; 339 REAL scutoff = 2.0 * t2 / ( pspec[0].range[2] * pspec[0].range[2]); 340 pspec[0].sidestep[0] = (ssv[0] > scutoff) ? sqrtf( 2.0 * t2 / ssv[0] ) : pspec[0].range[2]; 341 pspec[0].sidestep[1] = (ssv[1] > scutoff) ? sqrtf( 2.0 * t2 / ssv[1] ) : pspec[0].range[2]; 342 pspec[1].singleStep(); 343 } else if( tt != 0.0 ) { 344 REAL x = pspec[0].range[2] * st; 345 REAL dt = ( sqrtf( x * x + 8.0 * t2 * tt ) - x ) / tt; 346 pspec[0].singleStep(); 347 REAL tcutoff = 2.0 * t2 / ( pspec[1].range[2] * pspec[1].range[2]); 348 pspec[1].stepsize = ( dt < pspec[1].range[2] ) ? dt : pspec[1].range[2]; 349 pspec[1].sidestep[0] = (ttv[0] > tcutoff) ? sqrtf( 2.0 * t2 / ttv[0] ) : pspec[1].range[2]; 350 pspec[1].sidestep[1] = (ttv[1] > tcutoff) ? sqrtf( 2.0 * t2 / ttv[1] ) : pspec[1].range[2]; 351 } else { 352 if( 4.0 * t2 > st * pspec[0].range[2] * pspec[1].range[2] ) { 353 pspec[0].singleStep(); 354 pspec[1].singleStep(); 355 } else { 356 REAL area = 4.0 * t2 / st; 357 REAL ds = sqrtf( area * pspec[0].range[2] / pspec[1].range[2] ); 358 REAL dt = sqrtf( area * pspec[1].range[2] / pspec[0].range[2] ); 359 pspec[0].stepsize = ( ds < pspec[0].range[2] ) ? ds : pspec[0].range[2]; 360 pspec[0].sidestep[0] = pspec[0].range[2]; 361 pspec[0].sidestep[1] = pspec[0].range[2]; 362 363 pspec[1].stepsize = ( dt < pspec[1].range[2] ) ? dt : pspec[1].range[2]; 364 pspec[1].sidestep[0] = pspec[1].range[2]; 365 pspec[1].sidestep[1] = pspec[1].range[2]; 366 } 367 } 368 } else if( mapdesc->isPathLengthSampling() || 369 mapdesc->isObjectSpacePathSampling()) { 370 // t1 is upper bound on path length 371 REAL msv[2], mtv[2]; 372 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 ); 373 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 ); 374 REAL side_scale = 1.0; 375 376 if( ms != 0.0 ) { 377 if( mt != 0.0 ) { 378 /* REAL d = t1 / ( ms * ms + mt * mt );*/ 379 /* REAL ds = mt * d;*/ 380 REAL ds = t1 / (2.0*ms); 381 /* REAL dt = ms * d;*/ 382 REAL dt = t1 / (2.0*mt); 383 pspec[0].stepsize = ( ds < pspec[0].range[2] ) ? ds : pspec[0].range[2]; 384 pspec[0].sidestep[0] = ( msv[0] * pspec[0].range[2] > t1 ) ? (side_scale* t1 / msv[0]) : pspec[0].range[2]; 385 pspec[0].sidestep[1] = ( msv[1] * pspec[0].range[2] > t1 ) ? (side_scale* t1 / msv[1]) : pspec[0].range[2]; 386 387 pspec[1].stepsize = ( dt < pspec[1].range[2] ) ? dt : pspec[1].range[2]; 388 pspec[1].sidestep[0] = ( mtv[0] * pspec[1].range[2] > t1 ) ? (side_scale*t1 / mtv[0]) : pspec[1].range[2]; 389 pspec[1].sidestep[1] = ( mtv[1] * pspec[1].range[2] > t1 ) ? (side_scale*t1 / mtv[1]) : pspec[1].range[2]; 390 } else { 391 pspec[0].stepsize = ( t1 < ms * pspec[0].range[2] ) ? (t1 / ms) : pspec[0].range[2]; 392 pspec[0].sidestep[0] = ( msv[0] * pspec[0].range[2] > t1 ) ? (t1 / msv[0]) : pspec[0].range[2]; 393 pspec[0].sidestep[1] = ( msv[1] * pspec[0].range[2] > t1 ) ? (t1 / msv[1]) : pspec[0].range[2]; 394 395 pspec[1].singleStep(); 396 } 397 } else { 398 if( mt != 0.0 ) { 399 pspec[0].singleStep(); 400 401 pspec[1].stepsize = ( t1 < mt * pspec[1].range[2] ) ? (t1 / mt) : pspec[1].range[2]; 402 pspec[1].sidestep[0] = ( mtv[0] * pspec[1].range[2] > t1 ) ? (t1 / mtv[0]) : pspec[1].range[2]; 403 pspec[1].sidestep[1] = ( mtv[1] * pspec[1].range[2] > t1 ) ? (t1 / mtv[1]) : pspec[1].range[2]; 404 } else { 405 pspec[0].singleStep(); 406 pspec[1].singleStep(); 407 } 408 } 409 } else if( mapdesc->isSurfaceAreaSampling() ) { 410 // t is the square root of area 411 /* 412 REAL msv[2], mtv[2]; 413 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 ); 414 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 ); 415 if( ms != 0.0 && mt != 0.0 ) { 416 REAL d = 1.0 / (ms * mt); 417 t *= M_SQRT2; 418 REAL ds = t * sqrtf( d * pspec[0].range[2] / pspec[1].range[2] ); 419 REAL dt = t * sqrtf( d * pspec[1].range[2] / pspec[0].range[2] ); 420 pspec[0].stepsize = ( ds < pspec[0].range[2] ) ? ds : pspec[0].range[2]; 421 pspec[0].sidestep[0] = ( msv[0] * pspec[0].range[2] > t ) ? (t / msv[0]) : pspec[0].range[2]; 422 pspec[0].sidestep[1] = ( msv[1] * pspec[0].range[2] > t ) ? (t / msv[1]) : pspec[0].range[2]; 423 424 pspec[1].stepsize = ( dt < pspec[1].range[2] ) ? dt : pspec[1].range[2]; 425 pspec[1].sidestep[0] = ( mtv[0] * pspec[1].range[2] > t ) ? (t / mtv[0]) : pspec[1].range[2]; 426 pspec[1].sidestep[1] = ( mtv[1] * pspec[1].range[2] > t ) ? (t / mtv[1]) : pspec[1].range[2]; 427 } else { 428 pspec[0].singleStep(); 429 pspec[1].singleStep(); 430 } 431 */ 432 } else { 433 pspec[0].singleStep(); 434 pspec[1].singleStep(); 435 } 436 } 437 } 438 439 #ifdef DEBUG 440 _glu_dprintf( "sidesteps %g %g %g %g, stepsize %g %g\n", 441 pspec[0].sidestep[0], pspec[0].sidestep[1], 442 pspec[1].sidestep[0], pspec[1].sidestep[1], 443 pspec[0].stepsize, pspec[1].stepsize ); 444 #endif 445 446 if( mapdesc->minsavings != N_NOSAVINGSSUBDIVISION ) { 447 REAL savings = 1./(pspec[0].stepsize * pspec[1].stepsize) ; 448 savings-= (2./( pspec[0].sidestep[0] + pspec[0].sidestep[1] )) * 449 (2./( pspec[1].sidestep[0] + pspec[1].sidestep[1] )); 450 451 savings *= pspec[0].range[2] * pspec[1].range[2]; 452 if( savings > mapdesc->minsavings ) { 453 pspec[0].needsSubdivision = pspec[1].needsSubdivision = 1; 454 } 455 } 456 457 if( pspec[0].stepsize < pspec[0].minstepsize ) pspec[0].needsSubdivision = 1; 458 if( pspec[1].stepsize < pspec[1].minstepsize ) pspec[1].needsSubdivision = 1; 459 needsSampling = (needsSampling ? needsSamplingSubdivision() : 0); 460 } 461 462 void 463 Patchspec::singleStep() 464 { 465 stepsize = sidestep[0] = sidestep[1] = glu_abs(range[2]); 466 } 467 468 void 469 Patchspec::getstepsize( REAL max ) // max is number of samples for entire patch 470 { 471 stepsize = ( max >= 1.0 ) ? range[2] / max : range[2]; 472 if (stepsize < 0.0) { 473 stepsize = -stepsize; 474 } 475 sidestep[0] = sidestep[1] = minstepsize = stepsize; 476 } 477 478 int 479 Patch::needsSamplingSubdivision( void ) 480 { 481 return (pspec[0].needsSubdivision || pspec[1].needsSubdivision) ? 1 : 0; 482 } 483 484 int 485 Patch::needsNonSamplingSubdivision( void ) 486 { 487 return notInBbox; 488 } 489 490 int 491 Patch::needsSubdivision( int param ) 492 { 493 return pspec[param].needsSubdivision; 494 } 495 496 int 497 Patch::cullCheck( void ) 498 { 499 if( cullval == CULL_ACCEPT ) 500 cullval = mapdesc->cullCheck( cpts, pspec[0].order, pspec[0].stride, 501 pspec[1].order, pspec[1].stride ); 502 return cullval; 503 } 504 505