Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

467 lines
18 KiB

  1. /**************************************************************************
  2. * *
  3. * Copyright (C) 1992, Silicon Graphics, Inc. *
  4. * *
  5. * These coded instructions, statements, and computer programs contain *
  6. * unpublished proprietary information of Silicon Graphics, Inc., and *
  7. * are protected by ederal copyright law. They may not be disclosed *
  8. * to third parties or copied or duplicated in any form, in whole or *
  9. * in part, without the prior written consent of Silicon Graphics, Inc. *
  10. * *
  11. **************************************************************************/
  12. /*
  13. * patch.c++ - $Revision: 1.4 $
  14. * Derrick Burns - 1992
  15. */
  16. #include "glimport.h"
  17. #include "mystdio.h"
  18. #include "myassert.h"
  19. #include "mymath.h"
  20. #include "mystring.h"
  21. #include "patch.h"
  22. #include "mapdesc.h"
  23. #include "quilt.h"
  24. #include "nurbscon.h"
  25. #include "simplema.h" //for abs function in ::singleStep();
  26. /*--------------------------------------------------------------------------
  27. * Patch - copy patch from quilt and transform control points
  28. *--------------------------------------------------------------------------
  29. */
  30. Patch::Patch( Quilt_ptr geo, REAL *pta, REAL *ptb, Patch *n )
  31. {
  32. /* pspec[i].range is uninit here */
  33. mapdesc = geo->mapdesc;
  34. cullval = mapdesc->isCulling() ? CULL_ACCEPT : CULL_TRIVIAL_ACCEPT;
  35. notInBbox = mapdesc->isBboxSubdividing() ? 1 : 0;
  36. needsSampling = mapdesc->isRangeSampling() ? 1 : 0;
  37. pspec[0].order = geo->qspec[0].order;
  38. pspec[1].order = geo->qspec[1].order;
  39. pspec[0].stride = pspec[1].order * MAXCOORDS;
  40. pspec[1].stride = MAXCOORDS;
  41. /* transform control points to sampling and culling spaces */
  42. REAL *ps = geo->cpts;
  43. geo->select( pta, ptb );
  44. ps += geo->qspec[0].offset;
  45. ps += geo->qspec[1].offset;
  46. ps += geo->qspec[0].index * geo->qspec[0].order * geo->qspec[0].stride;
  47. ps += geo->qspec[1].index * geo->qspec[1].order * geo->qspec[1].stride;
  48. if( needsSampling ) {
  49. mapdesc->xformSampling( ps, geo->qspec[0].order, geo->qspec[0].stride,
  50. geo->qspec[1].order, geo->qspec[1].stride,
  51. spts, pspec[0].stride, pspec[1].stride );
  52. }
  53. if( cullval == CULL_ACCEPT ) {
  54. mapdesc->xformCulling( ps, geo->qspec[0].order, geo->qspec[0].stride,
  55. geo->qspec[1].order, geo->qspec[1].stride,
  56. cpts, pspec[0].stride, pspec[1].stride );
  57. }
  58. if( notInBbox ) {
  59. mapdesc->xformBounding( ps, geo->qspec[0].order, geo->qspec[0].stride,
  60. geo->qspec[1].order, geo->qspec[1].stride,
  61. bpts, pspec[0].stride, pspec[1].stride );
  62. }
  63. /* set scale range */
  64. pspec[0].range[0] = geo->qspec[0].breakpoints[geo->qspec[0].index];
  65. pspec[0].range[1] = geo->qspec[0].breakpoints[geo->qspec[0].index+1];
  66. pspec[0].range[2] = pspec[0].range[1] - pspec[0].range[0];
  67. pspec[1].range[0] = geo->qspec[1].breakpoints[geo->qspec[1].index];
  68. pspec[1].range[1] = geo->qspec[1].breakpoints[geo->qspec[1].index+1];
  69. pspec[1].range[2] = pspec[1].range[1] - pspec[1].range[0];
  70. // may need to subdivide to match range of sub-patch
  71. if( pspec[0].range[0] != pta[0] ) {
  72. assert( pspec[0].range[0] < pta[0] );
  73. Patch lower( *this, 0, pta[0], 0 );
  74. *this = lower;
  75. }
  76. if( pspec[0].range[1] != ptb[0] ) {
  77. assert( pspec[0].range[1] > ptb[0] );
  78. Patch upper( *this, 0, ptb[0], 0 );
  79. }
  80. if( pspec[1].range[0] != pta[1] ) {
  81. assert( pspec[1].range[0] < pta[1] );
  82. Patch lower( *this, 1, pta[1], 0 );
  83. *this = lower;
  84. }
  85. if( pspec[1].range[1] != ptb[1] ) {
  86. assert( pspec[1].range[1] > ptb[1] );
  87. Patch upper( *this, 1, ptb[1], 0 );
  88. }
  89. checkBboxConstraint();
  90. next = n;
  91. }
  92. /*--------------------------------------------------------------------------
  93. * Patch - subdivide a patch along an isoparametric line
  94. *--------------------------------------------------------------------------
  95. */
  96. Patch::Patch( Patch& upper, int param, REAL value, Patch *n )
  97. {
  98. Patch& lower = *this;
  99. lower.cullval = upper.cullval;
  100. lower.mapdesc = upper.mapdesc;
  101. lower.notInBbox = upper.notInBbox;
  102. lower.needsSampling = upper.needsSampling;
  103. lower.pspec[0].order = upper.pspec[0].order;
  104. lower.pspec[1].order = upper.pspec[1].order;
  105. lower.pspec[0].stride = upper.pspec[0].stride;
  106. lower.pspec[1].stride = upper.pspec[1].stride;
  107. lower.next = n;
  108. /* reset scale range */
  109. switch( param ) {
  110. case 0: {
  111. REAL d = (value-upper.pspec[0].range[0]) / upper.pspec[0].range[2];
  112. if( needsSampling )
  113. mapdesc->subdivide( upper.spts, lower.spts, d, pspec[1].order,
  114. pspec[1].stride, pspec[0].order, pspec[0].stride );
  115. if( cullval == CULL_ACCEPT )
  116. mapdesc->subdivide( upper.cpts, lower.cpts, d, pspec[1].order,
  117. pspec[1].stride, pspec[0].order, pspec[0].stride );
  118. if( notInBbox )
  119. mapdesc->subdivide( upper.bpts, lower.bpts, d, pspec[1].order,
  120. pspec[1].stride, pspec[0].order, pspec[0].stride );
  121. lower.pspec[0].range[0] = upper.pspec[0].range[0];
  122. lower.pspec[0].range[1] = value;
  123. lower.pspec[0].range[2] = value - upper.pspec[0].range[0];
  124. upper.pspec[0].range[0] = value;
  125. upper.pspec[0].range[2] = upper.pspec[0].range[1] - value;
  126. lower.pspec[1].range[0] = upper.pspec[1].range[0];
  127. lower.pspec[1].range[1] = upper.pspec[1].range[1];
  128. lower.pspec[1].range[2] = upper.pspec[1].range[2];
  129. break;
  130. }
  131. case 1: {
  132. REAL d = (value-upper.pspec[1].range[0]) / upper.pspec[1].range[2];
  133. if( needsSampling )
  134. mapdesc->subdivide( upper.spts, lower.spts, d, pspec[0].order,
  135. pspec[0].stride, pspec[1].order, pspec[1].stride );
  136. if( cullval == CULL_ACCEPT )
  137. mapdesc->subdivide( upper.cpts, lower.cpts, d, pspec[0].order,
  138. pspec[0].stride, pspec[1].order, pspec[1].stride );
  139. if( notInBbox )
  140. mapdesc->subdivide( upper.bpts, lower.bpts, d, pspec[0].order,
  141. pspec[0].stride, pspec[1].order, pspec[1].stride );
  142. lower.pspec[0].range[0] = upper.pspec[0].range[0];
  143. lower.pspec[0].range[1] = upper.pspec[0].range[1];
  144. lower.pspec[0].range[2] = upper.pspec[0].range[2];
  145. lower.pspec[1].range[0] = upper.pspec[1].range[0];
  146. lower.pspec[1].range[1] = value;
  147. lower.pspec[1].range[2] = value - upper.pspec[1].range[0];
  148. upper.pspec[1].range[0] = value;
  149. upper.pspec[1].range[2] = upper.pspec[1].range[1] - value;
  150. break;
  151. }
  152. }
  153. // inherit bounding box
  154. if( mapdesc->isBboxSubdividing() && ! notInBbox )
  155. memcpy( lower.bb, upper.bb, sizeof( bb ) );
  156. lower.checkBboxConstraint();
  157. upper.checkBboxConstraint();
  158. }
  159. /*--------------------------------------------------------------------------
  160. * clamp - clamp the sampling rate to a given maximum
  161. *--------------------------------------------------------------------------
  162. */
  163. void
  164. Patch::clamp( void )
  165. {
  166. if( mapdesc->clampfactor != N_NOCLAMPING ) {
  167. pspec[0].clamp( mapdesc->clampfactor );
  168. pspec[1].clamp( mapdesc->clampfactor );
  169. }
  170. }
  171. void
  172. Patchspec::clamp( REAL clampfactor )
  173. {
  174. if( sidestep[0] < minstepsize )
  175. sidestep[0] = clampfactor * minstepsize;
  176. if( sidestep[1] < minstepsize )
  177. sidestep[1] = clampfactor * minstepsize;
  178. if( stepsize < minstepsize )
  179. stepsize = clampfactor * minstepsize;
  180. }
  181. void
  182. Patch::checkBboxConstraint( void )
  183. {
  184. if( notInBbox &&
  185. mapdesc->bboxTooBig( bpts, pspec[0].stride, pspec[1].stride,
  186. pspec[0].order, pspec[1].order, bb ) != 1 ) {
  187. notInBbox = 0;
  188. }
  189. }
  190. void
  191. Patch::bbox( void )
  192. {
  193. if( mapdesc->isBboxSubdividing() )
  194. mapdesc->surfbbox( bb );
  195. }
  196. /*--------------------------------------------------------------------------
  197. * getstepsize - compute the sampling density across the patch
  198. * and determine if patch needs to be subdivided
  199. *--------------------------------------------------------------------------
  200. */
  201. void
  202. Patch::getstepsize( void )
  203. {
  204. pspec[0].minstepsize = pspec[1].minstepsize = 0;
  205. pspec[0].needsSubdivision = pspec[1].needsSubdivision = 0;
  206. if( mapdesc->isConstantSampling() ) {
  207. // fixed number of samples per patch in each direction
  208. // maxsrate is number of s samples per patch
  209. // maxtrate is number of t samples per patch
  210. pspec[0].getstepsize( mapdesc->maxsrate );
  211. pspec[1].getstepsize( mapdesc->maxtrate );
  212. } else if( mapdesc->isDomainSampling() ) {
  213. // maxsrate is number of s samples per unit s length of domain
  214. // maxtrate is number of t samples per unit t length of domain
  215. pspec[0].getstepsize( mapdesc->maxsrate * pspec[0].range[2] );
  216. pspec[1].getstepsize( mapdesc->maxtrate * pspec[1].range[2] );
  217. } else if( ! needsSampling ) {
  218. pspec[0].singleStep();
  219. pspec[1].singleStep();
  220. } else {
  221. // upper bound on path length between sample points
  222. REAL tmp[MAXORDER][MAXORDER][MAXCOORDS];
  223. const int trstride = sizeof(tmp[0]) / sizeof(REAL);
  224. const int tcstride = sizeof(tmp[0][0]) / sizeof(REAL);
  225. assert( pspec[0].order <= MAXORDER );
  226. /* points have been transformed, therefore they are homogeneous */
  227. int val = mapdesc->project( spts, pspec[0].stride, pspec[1].stride,
  228. &tmp[0][0][0], trstride, tcstride,
  229. pspec[0].order, pspec[1].order );
  230. if( val == 0 ) {
  231. // control points cross infinity, therefore partials are undefined
  232. pspec[0].getstepsize( mapdesc->maxsrate );
  233. pspec[1].getstepsize( mapdesc->maxtrate );
  234. } else {
  235. REAL t1 = mapdesc->getProperty( N_PIXEL_TOLERANCE );
  236. REAL t2 = mapdesc->getProperty( N_ERROR_TOLERANCE );
  237. pspec[0].minstepsize = ( mapdesc->maxsrate > 0.0 ) ?
  238. (pspec[0].range[2] / mapdesc->maxsrate) : 0.0;
  239. pspec[1].minstepsize = ( mapdesc->maxtrate > 0.0 ) ?
  240. (pspec[1].range[2] / mapdesc->maxtrate) : 0.0;
  241. if( mapdesc->isParametricDistanceSampling() ) {
  242. // t2 is upper bound on the distance between surface and tessellant
  243. REAL ssv[2], ttv[2];
  244. 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 );
  245. 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 );
  246. 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 );
  247. if( ss != 0.0 && tt != 0.0 ) {
  248. /* printf( "ssv[0] %g ssv[1] %g ttv[0] %g ttv[1] %g\n",
  249. ssv[0], ssv[1], ttv[0], ttv[1] ); */
  250. REAL ttq = ::sqrtf( (float) ss );
  251. REAL ssq = ::sqrtf( (float) tt );
  252. REAL ds = ::sqrtf( 4 * t2 * ttq / ( ss * ttq + st * ssq ) );
  253. REAL dt = ::sqrtf( 4 * t2 * ssq / ( tt * ssq + st * ttq ) );
  254. pspec[0].stepsize = ( ds < pspec[0].range[2] ) ? ds : pspec[0].range[2];
  255. REAL scutoff = 2.0 * t2 / ( pspec[0].range[2] * pspec[0].range[2]);
  256. pspec[0].sidestep[0] = (ssv[0] > scutoff) ? ::sqrtf( 2.0 * t2 / ssv[0] ) : pspec[0].range[2];
  257. pspec[0].sidestep[1] = (ssv[1] > scutoff) ? ::sqrtf( 2.0 * t2 / ssv[1] ) : pspec[0].range[2];
  258. pspec[1].stepsize = ( dt < pspec[1].range[2] ) ? dt : pspec[1].range[2];
  259. REAL tcutoff = 2.0 * t2 / ( pspec[1].range[2] * pspec[1].range[2]);
  260. pspec[1].sidestep[0] = (ttv[0] > tcutoff) ? ::sqrtf( 2.0 * t2 / ttv[0] ) : pspec[1].range[2];
  261. pspec[1].sidestep[1] = (ttv[1] > tcutoff) ? ::sqrtf( 2.0 * t2 / ttv[1] ) : pspec[1].range[2];
  262. } else if( ss != 0.0 ) {
  263. REAL x = pspec[1].range[2] * st;
  264. REAL ds = ( ::sqrtf( x * x + 8.0 * t2 * ss ) - x ) / ss;
  265. pspec[0].stepsize = ( ds < pspec[0].range[2] ) ? ds : pspec[0].range[2];
  266. REAL scutoff = 2.0 * t2 / ( pspec[0].range[2] * pspec[0].range[2]);
  267. pspec[0].sidestep[0] = (ssv[0] > scutoff) ? ::sqrtf( 2.0 * t2 / ssv[0] ) : pspec[0].range[2];
  268. pspec[0].sidestep[1] = (ssv[1] > scutoff) ? ::sqrtf( 2.0 * t2 / ssv[1] ) : pspec[0].range[2];
  269. pspec[1].singleStep();
  270. } else if( tt != 0.0 ) {
  271. REAL x = pspec[0].range[2] * st;
  272. REAL dt = ( ::sqrtf( x * x + 8.0 * t2 * tt ) - x ) / tt;
  273. pspec[0].singleStep();
  274. REAL tcutoff = 2.0 * t2 / ( pspec[1].range[2] * pspec[1].range[2]);
  275. pspec[1].stepsize = ( dt < pspec[1].range[2] ) ? dt : pspec[1].range[2];
  276. pspec[1].sidestep[0] = (ttv[0] > tcutoff) ? ::sqrtf( 2.0 * t2 / ttv[0] ) : pspec[1].range[2];
  277. pspec[1].sidestep[1] = (ttv[1] > tcutoff) ? ::sqrtf( 2.0 * t2 / ttv[1] ) : pspec[1].range[2];
  278. } else {
  279. if( 4.0 * t2 > st * pspec[0].range[2] * pspec[1].range[2] ) {
  280. pspec[0].singleStep();
  281. pspec[1].singleStep();
  282. } else {
  283. REAL area = 4.0 * t2 / st;
  284. REAL ds = ::sqrtf( area * pspec[0].range[2] / pspec[1].range[2] );
  285. REAL dt = ::sqrtf( area * pspec[1].range[2] / pspec[0].range[2] );
  286. pspec[0].stepsize = ( ds < pspec[0].range[2] ) ? ds : pspec[0].range[2];
  287. pspec[0].sidestep[0] = pspec[0].range[2];
  288. pspec[0].sidestep[1] = pspec[0].range[2];
  289. pspec[1].stepsize = ( dt < pspec[1].range[2] ) ? dt : pspec[1].range[2];
  290. pspec[1].sidestep[0] = pspec[1].range[2];
  291. pspec[1].sidestep[1] = pspec[1].range[2];
  292. }
  293. }
  294. } else if( mapdesc->isPathLengthSampling() ) {
  295. // t1 is upper bound on path length
  296. REAL msv[2], mtv[2];
  297. 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 );
  298. 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 );
  299. if( ms != 0.0 ) {
  300. if( mt != 0.0 ) {
  301. /* REAL d = t1 / ( ms * ms + mt * mt );*/
  302. /* REAL ds = mt * d;*/
  303. REAL ds = t1 / (2.0*ms);
  304. /* REAL dt = ms * d;*/
  305. REAL dt = t1 / (2.0*mt);
  306. pspec[0].stepsize = ( ds < pspec[0].range[2] ) ? ds : pspec[0].range[2];
  307. pspec[0].sidestep[0] = ( msv[0] * pspec[0].range[2] > t1 ) ? (t1 / msv[0]) : pspec[0].range[2];
  308. pspec[0].sidestep[1] = ( msv[1] * pspec[0].range[2] > t1 ) ? (t1 / msv[1]) : pspec[0].range[2];
  309. pspec[1].stepsize = ( dt < pspec[1].range[2] ) ? dt : pspec[1].range[2];
  310. pspec[1].sidestep[0] = ( mtv[0] * pspec[1].range[2] > t1 ) ? (t1 / mtv[0]) : pspec[1].range[2];
  311. pspec[1].sidestep[1] = ( mtv[1] * pspec[1].range[2] > t1 ) ? (t1 / mtv[1]) : pspec[1].range[2];
  312. } else {
  313. pspec[0].stepsize = ( t1 < ms * pspec[0].range[2] ) ? (t1 / ms) : pspec[0].range[2];
  314. pspec[0].sidestep[0] = ( msv[0] * pspec[0].range[2] > t1 ) ? (t1 / msv[0]) : pspec[0].range[2];
  315. pspec[0].sidestep[1] = ( msv[1] * pspec[0].range[2] > t1 ) ? (t1 / msv[1]) : pspec[0].range[2];
  316. pspec[1].singleStep();
  317. }
  318. } else {
  319. if( mt != 0.0 ) {
  320. pspec[0].singleStep();
  321. pspec[1].stepsize = ( t1 < mt * pspec[1].range[2] ) ? (t1 / mt) : pspec[1].range[2];
  322. pspec[1].sidestep[0] = ( mtv[0] * pspec[1].range[2] > t1 ) ? (t1 / mtv[0]) : pspec[1].range[2];
  323. pspec[1].sidestep[1] = ( mtv[1] * pspec[1].range[2] > t1 ) ? (t1 / mtv[1]) : pspec[1].range[2];
  324. } else {
  325. pspec[0].singleStep();
  326. pspec[1].singleStep();
  327. }
  328. }
  329. } else if( mapdesc->isSurfaceAreaSampling() ) {
  330. // t is the square root of area
  331. /*
  332. REAL msv[2], mtv[2];
  333. 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 );
  334. 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 );
  335. if( ms != 0.0 && mt != 0.0 ) {
  336. REAL d = 1.0 / (ms * mt);
  337. t *= M_SQRT2;
  338. REAL ds = t * ::sqrtf( d * pspec[0].range[2] / pspec[1].range[2] );
  339. REAL dt = t * ::sqrtf( d * pspec[1].range[2] / pspec[0].range[2] );
  340. pspec[0].stepsize = ( ds < pspec[0].range[2] ) ? ds : pspec[0].range[2];
  341. pspec[0].sidestep[0] = ( msv[0] * pspec[0].range[2] > t ) ? (t / msv[0]) : pspec[0].range[2];
  342. pspec[0].sidestep[1] = ( msv[1] * pspec[0].range[2] > t ) ? (t / msv[1]) : pspec[0].range[2];
  343. pspec[1].stepsize = ( dt < pspec[1].range[2] ) ? dt : pspec[1].range[2];
  344. pspec[1].sidestep[0] = ( mtv[0] * pspec[1].range[2] > t ) ? (t / mtv[0]) : pspec[1].range[2];
  345. pspec[1].sidestep[1] = ( mtv[1] * pspec[1].range[2] > t ) ? (t / mtv[1]) : pspec[1].range[2];
  346. } else {
  347. pspec[0].singleStep();
  348. pspec[1].singleStep();
  349. }
  350. */
  351. } else {
  352. pspec[0].singleStep();
  353. pspec[1].singleStep();
  354. }
  355. }
  356. }
  357. dprintf( "sidesteps %g %g %g %g, stepsize %g %g\n",
  358. pspec[0].sidestep[0], pspec[0].sidestep[1],
  359. pspec[1].sidestep[0], pspec[1].sidestep[1],
  360. pspec[0].stepsize, pspec[1].stepsize );
  361. if( mapdesc->minsavings != N_NOSAVINGSSUBDIVISION ) {
  362. REAL savings = 1./(pspec[0].stepsize * pspec[1].stepsize) ;
  363. savings-= (2./( pspec[0].sidestep[0] + pspec[0].sidestep[1] )) *
  364. (2./( pspec[1].sidestep[0] + pspec[1].sidestep[1] ));
  365. savings *= pspec[0].range[2] * pspec[1].range[2];
  366. if( savings > mapdesc->minsavings ) {
  367. pspec[0].needsSubdivision = pspec[1].needsSubdivision = 1;
  368. }
  369. }
  370. if( pspec[0].stepsize < pspec[0].minstepsize ) pspec[0].needsSubdivision = 1;
  371. if( pspec[1].stepsize < pspec[1].minstepsize ) pspec[1].needsSubdivision = 1;
  372. needsSampling = (needsSampling ? needsSamplingSubdivision() : 0);
  373. }
  374. void
  375. Patchspec::singleStep()
  376. {
  377. stepsize = sidestep[0] = sidestep[1] = abs(range[2]);
  378. }
  379. void
  380. Patchspec::getstepsize( REAL max ) // max is number of samples for entire patch
  381. {
  382. stepsize = ( max >= 1.0 ) ? range[2] / max : range[2];
  383. if (stepsize < 0.0) {
  384. stepsize = -stepsize;
  385. }
  386. sidestep[0] = sidestep[1] = minstepsize = stepsize;
  387. }
  388. int
  389. Patch::needsSamplingSubdivision( void )
  390. {
  391. return (pspec[0].needsSubdivision || pspec[1].needsSubdivision) ? 1 : 0;
  392. }
  393. int
  394. Patch::needsNonSamplingSubdivision( void )
  395. {
  396. return notInBbox;
  397. }
  398. int
  399. Patch::needsSubdivision( int param )
  400. {
  401. return pspec[param].needsSubdivision;
  402. }
  403. int
  404. Patch::cullCheck( void )
  405. {
  406. if( cullval == CULL_ACCEPT )
  407. cullval = mapdesc->cullCheck( cpts, pspec[0].order, pspec[0].stride,
  408. pspec[1].order, pspec[1].stride );
  409. return cullval;
  410. }