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.

659 lines
19 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 Federal 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. * subdivider.c++ - $Revision: 1.3 $
  14. * Derrick Burns - 1991
  15. */
  16. #include "glimport.h"
  17. #include "myassert.h"
  18. #include "mystdio.h"
  19. #include "subdivid.h"
  20. #include "arc.h"
  21. #include "bezierar.h"
  22. #include "bin.h"
  23. #include "renderhi.h"
  24. #include "backend.h"
  25. #include "mapdesc.h"
  26. #include "quilt.h"
  27. #include "patchlis.h"
  28. #include "patch.h"
  29. #include "nurbscon.h"
  30. #include "trimpool.h"
  31. #include "simplema.h"
  32. /*---------------------------------------------------------------------------
  33. * Subdivider - construct a subdivider
  34. *---------------------------------------------------------------------------
  35. */
  36. Subdivider::Subdivider( Renderhints& r, Backend& b )
  37. : arcpool( sizeof( Arc), 1, "arcpool" ),
  38. bezierarcpool( sizeof( BezierArc ), 1, "Bezarcpool" ),
  39. pwlarcpool( sizeof( PwlArc ), 1, "Pwlarcpool" ),
  40. renderhints( r ),
  41. arctessellator( trimvertexpool, pwlarcpool ),
  42. backend( b ),
  43. slicer( b )
  44. {
  45. }
  46. void
  47. Subdivider::setJumpbuffer( JumpBuffer *j )
  48. {
  49. jumpbuffer = j;
  50. }
  51. /*---------------------------------------------------------------------------
  52. * clear - reset all state after possible error condition
  53. *---------------------------------------------------------------------------
  54. */
  55. void
  56. Subdivider::clear( void )
  57. {
  58. trimvertexpool.clear();
  59. arcpool.clear();
  60. pwlarcpool.clear();
  61. bezierarcpool.clear();
  62. }
  63. /*---------------------------------------------------------------------------
  64. * ~Subdivider - destroy a subdivider
  65. *---------------------------------------------------------------------------
  66. */
  67. Subdivider::~Subdivider( void )
  68. {
  69. }
  70. /*---------------------------------------------------------------------------
  71. * addArc - add a bezier arc to a trim loop and to a bin
  72. *---------------------------------------------------------------------------
  73. */
  74. void
  75. Subdivider::addArc( REAL *cpts, Quilt *quilt, long _nuid )
  76. {
  77. BezierArc *bezierArc = new(bezierarcpool) BezierArc;
  78. Arc *jarc = new(arcpool) Arc( arc_none, _nuid );
  79. jarc->pwlArc = 0;
  80. jarc->bezierArc = bezierArc;
  81. bezierArc->order = quilt->qspec->order;
  82. bezierArc->stride = quilt->qspec->stride;
  83. bezierArc->mapdesc = quilt->mapdesc;
  84. bezierArc->cpts = cpts;
  85. initialbin.addarc( jarc );
  86. pjarc = jarc->append( pjarc );
  87. }
  88. /*---------------------------------------------------------------------------
  89. * addArc - add a pwl arc to a trim loop and to a bin
  90. *---------------------------------------------------------------------------
  91. */
  92. void
  93. Subdivider::addArc( int npts, TrimVertex *pts, long _nuid )
  94. {
  95. Arc *jarc = new(arcpool) Arc( arc_none, _nuid );
  96. jarc->pwlArc = new(pwlarcpool) PwlArc( npts, pts );
  97. initialbin.addarc( jarc );
  98. pjarc = jarc->append( pjarc );
  99. }
  100. void
  101. Subdivider::beginQuilts( void )
  102. {
  103. qlist = 0;
  104. }
  105. void
  106. Subdivider::addQuilt( Quilt *quilt )
  107. {
  108. quilt->next = qlist;
  109. qlist = quilt;
  110. }
  111. /*---------------------------------------------------------------------------
  112. * drawSurfaces - main entry point for surface tessellation
  113. *---------------------------------------------------------------------------
  114. */
  115. void
  116. Subdivider::drawSurfaces( long nuid )
  117. {
  118. renderhints.init( );
  119. if (qlist == NULL) return;
  120. for( Quilt *q = qlist; q; q = q->next ) {
  121. if( q->isCulled( ) == CULL_TRIVIAL_REJECT ) {
  122. freejarcs( initialbin );
  123. return;
  124. }
  125. }
  126. REAL from[2], to[2];
  127. qlist->getRange( from, to, spbrkpts, tpbrkpts );
  128. if( ! initialbin.isnonempty() ) {
  129. makeBorderTrim( from, to );
  130. } else {
  131. REAL rate[2];
  132. qlist->findRates( spbrkpts, tpbrkpts, rate );
  133. if( decompose( initialbin, min(rate[0], rate[1]) ) )
  134. mylongjmp( jumpbuffer, 31 );
  135. }
  136. backend.bgnsurf( renderhints.wiretris, renderhints.wirequads, nuid );
  137. subdivideInS( initialbin );
  138. backend.endsurf();
  139. }
  140. void
  141. Subdivider::subdivideInS( Bin& source )
  142. {
  143. if( renderhints.display_method == N_OUTLINE_PARAM ) {
  144. outline( source );
  145. freejarcs( source );
  146. } else {
  147. setArcTypeBezier();
  148. setNonDegenerate();
  149. splitInS( source, spbrkpts.start, spbrkpts.end );
  150. }
  151. }
  152. /*---------------------------------------------------------------------------
  153. * splitInS - split a patch and a bin by an isoparametric line
  154. *---------------------------------------------------------------------------
  155. */
  156. void
  157. Subdivider::splitInS( Bin& source, int start, int end )
  158. {
  159. if( source.isnonempty() ) {
  160. if( start != end ) {
  161. int i = start + (end - start) / 2;
  162. Bin left, right;
  163. split( source, left, right, 0, spbrkpts.pts[i] );
  164. splitInS( left, start, i );
  165. splitInS( right, i+1, end );
  166. } else {
  167. if( start == spbrkpts.start || start == spbrkpts.end ) {
  168. freejarcs( source );
  169. } else if( renderhints.display_method == N_OUTLINE_PARAM_S ) {
  170. outline( source );
  171. freejarcs( source );
  172. } else {
  173. setArcTypeBezier();
  174. setNonDegenerate();
  175. s_index = start;
  176. splitInT( source, tpbrkpts.start, tpbrkpts.end );
  177. }
  178. }
  179. }
  180. }
  181. /*---------------------------------------------------------------------------
  182. * splitInT - split a patch and a bin by an isoparametric line
  183. *---------------------------------------------------------------------------
  184. */
  185. void
  186. Subdivider::splitInT( Bin& source, int start, int end )
  187. {
  188. if( source.isnonempty() ) {
  189. if( start != end ) {
  190. int i = start + (end - start) / 2;
  191. Bin left, right;
  192. split( source, left, right, 1, tpbrkpts.pts[i] );
  193. splitInT( left, start, i );
  194. splitInT( right, i+1, end );
  195. } else {
  196. if( start == tpbrkpts.start || start == tpbrkpts.end ) {
  197. freejarcs( source );
  198. } else if( renderhints.display_method == N_OUTLINE_PARAM_ST ) {
  199. outline( source );
  200. freejarcs( source );
  201. } else {
  202. t_index = start;
  203. setArcTypeBezier();
  204. setDegenerate();
  205. REAL pta[2], ptb[2];
  206. pta[0] = spbrkpts.pts[s_index-1];
  207. pta[1] = tpbrkpts.pts[t_index-1];
  208. ptb[0] = spbrkpts.pts[s_index];
  209. ptb[1] = tpbrkpts.pts[t_index];
  210. qlist->downloadAll( pta, ptb, backend );
  211. Patchlist patchlist( qlist, pta, ptb );
  212. samplingSplit( source, patchlist, renderhints.maxsubdivisions, 0 );
  213. setNonDegenerate();
  214. setArcTypeBezier();
  215. }
  216. }
  217. }
  218. }
  219. /*--------------------------------------------------------------------------
  220. * samplingSplit - recursively subdivide patch, cull check each subpatch
  221. *--------------------------------------------------------------------------
  222. */
  223. void
  224. Subdivider::samplingSplit(
  225. Bin& source,
  226. Patchlist& patchlist,
  227. int subdivisions,
  228. int param )
  229. {
  230. if( ! source.isnonempty() ) return;
  231. if( patchlist.cullCheck() == CULL_TRIVIAL_REJECT ) {
  232. freejarcs( source );
  233. return;
  234. }
  235. patchlist.getstepsize();
  236. if( renderhints.display_method == N_OUTLINE_PATCH ) {
  237. tessellation( source, patchlist );
  238. outline( source );
  239. freejarcs( source );
  240. return;
  241. }
  242. //patchlist.clamp();
  243. tessellation( source, patchlist );
  244. if( patchlist.needsSamplingSubdivision() && (subdivisions > 0) ) {
  245. if( ! patchlist.needsSubdivision( 0 ) )
  246. param = 1;
  247. else if( ! patchlist.needsSubdivision( 1 ) )
  248. param = 0;
  249. else
  250. param = 1 - param;
  251. Bin left, right;
  252. REAL mid = ( patchlist.pspec[param].range[0] +
  253. patchlist.pspec[param].range[1] ) * 0.5;
  254. split( source, left, right, param, mid );
  255. Patchlist subpatchlist( patchlist, param, mid );
  256. samplingSplit( left, subpatchlist, subdivisions-1, param );
  257. samplingSplit( right, patchlist, subdivisions-1, param );
  258. } else {
  259. setArcTypePwl();
  260. setDegenerate();
  261. nonSamplingSplit( source, patchlist, subdivisions, param );
  262. setDegenerate();
  263. setArcTypeBezier();
  264. }
  265. }
  266. void
  267. Subdivider::nonSamplingSplit(
  268. Bin& source,
  269. Patchlist& patchlist,
  270. int subdivisions,
  271. int param )
  272. {
  273. if( patchlist.needsNonSamplingSubdivision() && (subdivisions > 0) ) {
  274. param = 1 - param;
  275. Bin left, right;
  276. REAL mid = ( patchlist.pspec[param].range[0] +
  277. patchlist.pspec[param].range[1] ) * 0.5;
  278. split( source, left, right, param, mid );
  279. Patchlist subpatchlist( patchlist, param, mid );
  280. if( left.isnonempty() )
  281. if( subpatchlist.cullCheck() == CULL_TRIVIAL_REJECT )
  282. freejarcs( left );
  283. else
  284. nonSamplingSplit( left, subpatchlist, subdivisions-1, param );
  285. if( right.isnonempty() )
  286. if( patchlist.cullCheck() == CULL_TRIVIAL_REJECT )
  287. freejarcs( right );
  288. else
  289. nonSamplingSplit( right, patchlist, subdivisions-1, param );
  290. } else {
  291. // make bbox calls
  292. patchlist.bbox();
  293. backend.patch( patchlist.pspec[0].range[0], patchlist.pspec[0].range[1],
  294. patchlist.pspec[1].range[0], patchlist.pspec[1].range[1] );
  295. if( renderhints.display_method == N_OUTLINE_SUBDIV ) {
  296. outline( source );
  297. freejarcs( source );
  298. } else {
  299. setArcTypePwl();
  300. setDegenerate();
  301. findIrregularS( source );
  302. monosplitInS( source, smbrkpts.start, smbrkpts.end );
  303. }
  304. }
  305. }
  306. /*--------------------------------------------------------------------------
  307. * tessellation - set tessellation of interior and boundary of patch
  308. *--------------------------------------------------------------------------
  309. */
  310. void
  311. Subdivider::tessellation( Bin& bin, Patchlist &patchlist )
  312. {
  313. // tessellate unsampled trim curves
  314. tessellate( bin, patchlist.pspec[1].sidestep[1], patchlist.pspec[0].sidestep[1],
  315. patchlist.pspec[1].sidestep[0], patchlist.pspec[0].sidestep[0] );
  316. // set interior sampling rates
  317. slicer.setstriptessellation( patchlist.pspec[0].stepsize, patchlist.pspec[1].stepsize );
  318. // set boundary sampling rates
  319. stepsizes[0] = patchlist.pspec[1].stepsize;
  320. stepsizes[1] = patchlist.pspec[0].stepsize;
  321. stepsizes[2] = patchlist.pspec[1].stepsize;
  322. stepsizes[3] = patchlist.pspec[0].stepsize;
  323. }
  324. /*---------------------------------------------------------------------------
  325. * monosplitInS - split a patch and a bin by an isoparametric line
  326. *---------------------------------------------------------------------------
  327. */
  328. void
  329. Subdivider::monosplitInS( Bin& source, int start, int end )
  330. {
  331. if( source.isnonempty() ) {
  332. if( start != end ) {
  333. int i = start + (end - start) / 2;
  334. Bin left, right;
  335. split( source, left, right, 0, smbrkpts.pts[i] );
  336. monosplitInS( left, start, i );
  337. monosplitInS( right, i+1, end );
  338. } else {
  339. if( renderhints.display_method == N_OUTLINE_SUBDIV_S ) {
  340. outline( source );
  341. freejarcs( source );
  342. } else {
  343. setArcTypePwl();
  344. setDegenerate();
  345. findIrregularT( source );
  346. monosplitInT( source, tmbrkpts.start, tmbrkpts.end );
  347. }
  348. }
  349. }
  350. }
  351. /*---------------------------------------------------------------------------
  352. * monosplitInT - split a patch and a bin by an isoparametric line
  353. *---------------------------------------------------------------------------
  354. */
  355. void
  356. Subdivider::monosplitInT( Bin& source, int start, int end )
  357. {
  358. if( source.isnonempty() ) {
  359. if( start != end ) {
  360. int i = start + (end - start) / 2;
  361. Bin left, right;
  362. split( source, left, right, 1, tmbrkpts.pts[i] );
  363. monosplitInT( left, start, i );
  364. monosplitInT( right, i+1, end );
  365. } else {
  366. if( renderhints.display_method == N_OUTLINE_SUBDIV_ST ) {
  367. outline( source );
  368. freejarcs( source );
  369. } else {
  370. render( source );
  371. freejarcs( source );
  372. }
  373. }
  374. }
  375. }
  376. /*----------------------------------------------------------------------------
  377. * findIrregularS - determine points of non-monotonicity is s direction
  378. *----------------------------------------------------------------------------
  379. */
  380. void
  381. Subdivider::findIrregularS( Bin& bin )
  382. {
  383. assert( bin.firstarc()->check() != 0 );
  384. smbrkpts.grow( bin.numarcs() );
  385. for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
  386. REAL *a = jarc->prev->tail();
  387. REAL *b = jarc->tail();
  388. REAL *c = jarc->head();
  389. if( b[1] == a[1] && b[1] == c[1] ) continue;
  390. if( b[1] <= a[1] && b[1] <= c[1] ) {
  391. if( ! ccwTurn_tr( jarc->prev, jarc ) )
  392. smbrkpts.add( b[0] );
  393. } else if( b[1] >= a[1] && b[1] >= c[1] ) {
  394. if( ! ccwTurn_tl( jarc->prev, jarc ) )
  395. smbrkpts.add( b[0] );
  396. }
  397. }
  398. smbrkpts.filter();
  399. }
  400. /*----------------------------------------------------------------------------
  401. * findIrregularT - determine points of non-monotonicity in t direction
  402. * where one arc is parallel to the s axis.
  403. *----------------------------------------------------------------------------
  404. */
  405. void
  406. Subdivider::findIrregularT( Bin& bin )
  407. {
  408. assert( bin.firstarc()->check() != 0 );
  409. tmbrkpts.grow( bin.numarcs() );
  410. for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
  411. REAL *a = jarc->prev->tail();
  412. REAL *b = jarc->tail();
  413. REAL *c = jarc->head();
  414. if( b[0] == a[0] && b[0] == c[0] ) continue;
  415. if( b[0] <= a[0] && b[0] <= c[0] ) {
  416. if( a[1] != b[1] && b[1] != c[1] ) continue;
  417. if( ! ccwTurn_sr( jarc->prev, jarc ) )
  418. tmbrkpts.add( b[1] );
  419. } else if ( b[0] >= a[0] && b[0] >= c[0] ) {
  420. if( a[1] != b[1] && b[1] != c[1] ) continue;
  421. if( ! ccwTurn_sl( jarc->prev, jarc ) )
  422. tmbrkpts.add( b[1] );
  423. }
  424. }
  425. tmbrkpts.filter( );
  426. }
  427. /*-----------------------------------------------------------------------------
  428. * makeBorderTrim - if no user input trimming data then create
  429. * a trimming curve around the boundaries of the Quilt. The curve consists of
  430. * four Jordan arcs, one for each side of the Quilt, connected, of course,
  431. * head to tail.
  432. *-----------------------------------------------------------------------------
  433. */
  434. void
  435. Subdivider::makeBorderTrim( const REAL *from, const REAL *to )
  436. {
  437. REAL smin = from[0];
  438. REAL smax = to[0];
  439. REAL tmin = from[1];
  440. REAL tmax = to[1];
  441. pjarc = 0;
  442. Arc_ptr jarc = new(arcpool) Arc( arc_bottom, 0 );
  443. arctessellator.bezier( jarc, smin, smax, tmin, tmin );
  444. initialbin.addarc( jarc );
  445. pjarc = jarc->append( pjarc );
  446. jarc = new(arcpool) Arc( arc_right, 0 );
  447. arctessellator.bezier( jarc, smax, smax, tmin, tmax );
  448. initialbin.addarc( jarc );
  449. pjarc = jarc->append( pjarc );
  450. jarc = new(arcpool) Arc( arc_top, 0 );
  451. arctessellator.bezier( jarc, smax, smin, tmax, tmax );
  452. initialbin.addarc( jarc );
  453. pjarc = jarc->append( pjarc );
  454. jarc = new(arcpool) Arc( arc_left, 0 );
  455. arctessellator.bezier( jarc, smin, smin, tmax, tmin );
  456. initialbin.addarc( jarc );
  457. jarc->append( pjarc );
  458. assert( jarc->check() != 0 );
  459. }
  460. /*----------------------------------------------------------------------------
  461. * render - renders all monotone regions in a bin and frees the bin
  462. *----------------------------------------------------------------------------
  463. */
  464. void
  465. Subdivider::render( Bin& bin )
  466. {
  467. bin.markall();
  468. #ifdef N_ISOLINE_S
  469. slicer.setisolines( ( renderhints.display_method == N_ISOLINE_S ) ? 1 : 0 );
  470. #else
  471. slicer.setisolines( 0 );
  472. #endif
  473. for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
  474. if( jarc->ismarked() ) {
  475. assert( jarc->check( ) != 0 );
  476. Arc_ptr jarchead = jarc;
  477. do {
  478. jarc->clearmark();
  479. jarc = jarc->next;
  480. } while (jarc != jarchead);
  481. slicer.slice( jarc );
  482. }
  483. }
  484. }
  485. /*---------------------------------------------------------------------------
  486. * outline - render the trimmed patch by outlining the boundary
  487. *---------------------------------------------------------------------------
  488. */
  489. void
  490. Subdivider::outline( Bin& bin )
  491. {
  492. bin.markall();
  493. for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
  494. if( jarc->ismarked() ) {
  495. assert( jarc->check( ) != 0 );
  496. Arc_ptr jarchead = jarc;
  497. do {
  498. slicer.outline( jarc );
  499. jarc->clearmark();
  500. jarc = jarc->prev;
  501. } while (jarc != jarchead);
  502. }
  503. }
  504. }
  505. /*---------------------------------------------------------------------------
  506. * freejarcs - free all arcs in a bin
  507. *---------------------------------------------------------------------------
  508. */
  509. void
  510. Subdivider::freejarcs( Bin& bin )
  511. {
  512. bin.adopt(); /* XXX - should not be necessary */
  513. Arc_ptr jarc;
  514. while( jarc = bin.removearc() ) {
  515. if( jarc->pwlArc ) jarc->pwlArc->deleteMe( pwlarcpool ); jarc->pwlArc = 0;
  516. if( jarc->bezierArc) jarc->bezierArc->deleteMe( bezierarcpool ); jarc->bezierArc = 0;
  517. jarc->deleteMe( arcpool );
  518. }
  519. }
  520. /*----------------------------------------------------------------------------
  521. * tessellate - tessellate all Bezier arcs in a bin
  522. * 1) only accepts linear Bezier arcs as input
  523. * 2) the Bezier arcs are stored in the pwlArc structure
  524. * 3) only vertical or horizontal lines work
  525. * -- should
  526. * 1) represent Bezier arcs in BezierArc structure
  527. * (this requires a multitude of changes to the code)
  528. * 2) accept high degree Bezier arcs (hard)
  529. * 3) map the curve onto the surface to determine tessellation
  530. * 4) work for curves of arbitrary geometry
  531. *----------------------------------------------------------------------------
  532. */
  533. void
  534. Subdivider::tessellate( Bin& bin, REAL rrate, REAL trate, REAL lrate, REAL brate )
  535. {
  536. for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
  537. if( jarc->isbezier( ) ) {
  538. assert( jarc->pwlArc->npts == 2 );
  539. TrimVertex *pts = jarc->pwlArc->pts;
  540. REAL s1 = pts[0].param[0];
  541. REAL t1 = pts[0].param[1];
  542. REAL s2 = pts[1].param[0];
  543. REAL t2 = pts[1].param[1];
  544. jarc->pwlArc->deleteMe( pwlarcpool ); jarc->pwlArc = 0;
  545. switch( jarc->getside() ) {
  546. case arc_left:
  547. assert( s1 == s2 );
  548. arctessellator.pwl_left( jarc, s1, t1, t2, lrate );
  549. break;
  550. case arc_right:
  551. assert( s1 == s2 );
  552. arctessellator.pwl_right( jarc, s1, t1, t2, rrate );
  553. break;
  554. case arc_top:
  555. assert( t1 == t2 );
  556. arctessellator.pwl_top( jarc, t1, s1, s2, trate );
  557. break;
  558. case arc_bottom:
  559. assert( t1 == t2 );
  560. arctessellator.pwl_bottom( jarc, t1, s1, s2, brate );
  561. break;
  562. case arc_none:
  563. #ifndef NT
  564. (void) abort();
  565. #endif
  566. break;
  567. }
  568. assert( ! jarc->isbezier() );
  569. assert( jarc->check() != 0 );
  570. }
  571. }
  572. }