40 #include "glimports.h"
43 #include "subdivider.h"
45 #include "bezierarc.h"
47 #include "renderhints.h"
51 #include "patchlist.h"
53 #include "nurbsconsts.h"
54 #include "trimvertpool.h"
55 #include "simplemath.h"
61 #include "partitionY.h"
62 #include "monoTriangulation.h"
63 #include "dataTransform.h"
64 #include "monoChain.h"
69 #define OPTIMIZE_UNTRIMED_CASE
73 Subdivider::makePatchBoundary(
const REAL *from,
const REAL *to )
83 Arc_ptr jarc =
new(arcpool)
Arc( arc_bottom, 0 );
84 arctessellator.bezier( jarc, smin, smax, tmin, tmin );
86 pjarc = jarc->append( pjarc );
88 jarc =
new(arcpool)
Arc( arc_right, 0 );
89 arctessellator.bezier( jarc, smax, smax, tmin, tmax );
91 pjarc = jarc->append( pjarc );
93 jarc =
new(arcpool)
Arc( arc_top, 0 );
94 arctessellator.bezier( jarc, smax, smin, tmax, tmax );
96 pjarc = jarc->append( pjarc );
98 jarc =
new(arcpool)
Arc( arc_left, 0 );
99 arctessellator.bezier( jarc, smin, smin, tmax, tmin );
101 jarc->append( pjarc );
103 assert( jarc->check() != 0 );
114 arctessellator( trimvertexpool, pwlarcpool ),
115 arcpool( sizeof(
Arc), 1,
"arcpool" ),
116 bezierarcpool( sizeof(
BezierArc ), 1,
"Bezarcpool" ),
117 pwlarcpool( sizeof(
PwlArc ), 1,
"Pwlarcpool" ),
124 Subdivider::setJumpbuffer( JumpBuffer *j )
135 Subdivider::clear(
void )
137 trimvertexpool.clear();
140 bezierarcpool.clear();
148 Subdivider::~Subdivider(
void )
157 Subdivider::addArc( REAL *cpts,
Quilt *quilt,
long _nuid )
160 Arc *jarc =
new(arcpool)
Arc( arc_none, _nuid );
162 jarc->bezierArc = bezierArc;
163 bezierArc->order = quilt->qspec->order;
164 bezierArc->stride = quilt->qspec->stride;
165 bezierArc->mapdesc = quilt->mapdesc;
166 bezierArc->cpts = cpts;
167 initialbin.addarc( jarc );
168 pjarc = jarc->append( pjarc );
177 Subdivider::addArc(
int npts,
TrimVertex *pts,
long _nuid )
179 Arc *jarc =
new(arcpool)
Arc( arc_none, _nuid );
180 jarc->pwlArc =
new(pwlarcpool)
PwlArc( npts, pts );
181 initialbin.addarc( jarc );
182 pjarc = jarc->append( pjarc );
186 Subdivider::beginQuilts(
void )
192 Subdivider::addQuilt(
Quilt *quilt )
204 Subdivider::drawSurfaces(
long nuid )
211 freejarcs(initialbin);
215 for(
Quilt *q = qlist; q; q = q->next ) {
216 if( q->isCulled( ) == CULL_TRIVIAL_REJECT ) {
217 freejarcs( initialbin );
224 qlist->getRange( from, to, spbrkpts, tpbrkpts );
225 #ifdef OPTIMIZE_UNTRIMED_CASE
229 int optimize = (is_domain_distance_sampling && (renderhints.display_method != N_OUTLINE_PATCH));
232 if( ! initialbin.isnonempty() ) {
233 #ifdef OPTIMIZE_UNTRIMED_CASE
237 makeBorderTrim( from, to );
240 makeBorderTrim( from, to );
244 qlist->findRates( spbrkpts, tpbrkpts, rate );
246 if( decompose( initialbin, min(rate[0], rate[1]) ) )
247 mylongjmp( jumpbuffer, 31 );
250 backend.bgnsurf( renderhints.wiretris, renderhints.wirequads, nuid );
252 #ifdef PARTITION_TEST
253 if( initialbin.isnonempty() && spbrkpts.end-2 == spbrkpts.start &&
254 tpbrkpts.end-2 == tpbrkpts.start)
256 for(
int i=spbrkpts.start; i<spbrkpts.end-1; i++){
257 for(
int j=tpbrkpts.start; j<tpbrkpts.end-1; j++){
259 pta[0] = spbrkpts.pts[i];
260 ptb[0] = spbrkpts.pts[i+1];
261 pta[1] = tpbrkpts.pts[j];
262 ptb[1] = tpbrkpts.pts[j+1];
263 qlist->downloadAll(pta, ptb, backend);
269 poly = bin_to_DLineLoops(initialbin);
271 poly=poly->deleteDegenerateLinesAllPolygons();
275 poly = MC_partitionY(poly, &retSampledLines);
285 for(temp=poly; temp != NULL; temp=temp->getNextPolygon())
287 monoTriangulation(temp, &pStream);
289 slicer.evalStream(&pStream);
295 freejarcs( initialbin );
312 #endif //PARTITION_TEST
315 #ifdef OPTIMIZE_UNTRIMED_CASE
316 if( (!initialbin.isnonempty()) && optimize )
321 for(i=spbrkpts.start; i<spbrkpts.end-1; i++){
322 for(j=tpbrkpts.start; j<tpbrkpts.end-1; j++){
324 pta[0] = spbrkpts.pts[i];
325 ptb[0] = spbrkpts.pts[i+1];
326 pta[1] = tpbrkpts.pts[j];
327 ptb[1] = tpbrkpts.pts[j+1];
328 qlist->downloadAll(pta, ptb, backend);
330 num_u_steps = (int) (domain_distance_u_rate * (ptb[0]-pta[0]));
331 num_v_steps = (int) (domain_distance_v_rate * (ptb[1]-pta[1]));
333 if(num_u_steps <= 0) num_u_steps = 1;
334 if(num_v_steps <= 0) num_v_steps = 1;
336 backend.surfgrid(pta[0], ptb[0], num_u_steps,
337 ptb[1], pta[1], num_v_steps);
338 backend.surfmesh(0,0,num_u_steps,num_v_steps);
361 subdivideInS( initialbin );
364 subdivideInS( initialbin );
372 Subdivider::subdivideInS(
Bin& source )
374 if( renderhints.display_method == N_OUTLINE_PARAM ) {
380 splitInS( source, spbrkpts.start, spbrkpts.end );
391 Subdivider::splitInS(
Bin& source,
int start,
int end )
393 if( source.isnonempty() ) {
395 int i = start + (end - start) / 2;
397 split( source, left, right, 0, spbrkpts.pts[i] );
398 splitInS( left, start, i );
399 splitInS( right, i+1, end );
401 if( start == spbrkpts.start || start == spbrkpts.end ) {
403 }
else if( renderhints.display_method == N_OUTLINE_PARAM_S ) {
410 splitInT( source, tpbrkpts.start, tpbrkpts.end );
422 Subdivider::splitInT(
Bin& source,
int start,
int end )
424 if( source.isnonempty() ) {
426 int i = start + (end - start) / 2;
428 split( source, left, right, 1, tpbrkpts.pts[i] );
429 splitInT( left, start, i );
430 splitInT( right, i+1, end );
432 if( start == tpbrkpts.start || start == tpbrkpts.end ) {
434 }
else if( renderhints.display_method == N_OUTLINE_PARAM_ST ) {
443 pta[0] = spbrkpts.pts[s_index-1];
444 pta[1] = tpbrkpts.pts[t_index-1];
446 ptb[0] = spbrkpts.pts[s_index];
447 ptb[1] = tpbrkpts.pts[t_index];
448 qlist->downloadAll( pta, ptb, backend );
455 samplingSplit( source, patchlist, renderhints.maxsubdivisions, 0 );
469 Subdivider::samplingSplit(
475 if( ! source.isnonempty() )
return;
477 if( patchlist.cullCheck() == CULL_TRIVIAL_REJECT ) {
482 patchlist.getstepsize();
484 if( renderhints.display_method == N_OUTLINE_PATCH ) {
485 tessellation( source, patchlist );
493 tessellation( source, patchlist );
495 if( patchlist.needsSamplingSubdivision() && (subdivisions > 0) ) {
496 if( ! patchlist.needsSubdivision( 0 ) )
498 else if( ! patchlist.needsSubdivision( 1 ) )
504 REAL mid = ( patchlist.pspec[param].range[0] +
505 patchlist.pspec[param].range[1] ) * 0.5;
506 split( source, left, right, param, mid );
507 Patchlist subpatchlist( patchlist, param, mid );
508 samplingSplit( left, subpatchlist, subdivisions-1, param );
509 samplingSplit( right, patchlist, subdivisions-1, param );
513 nonSamplingSplit( source, patchlist, subdivisions, param );
520 Subdivider::nonSamplingSplit(
526 if( patchlist.needsNonSamplingSubdivision() && (subdivisions > 0) ) {
530 REAL mid = ( patchlist.pspec[param].range[0] +
531 patchlist.pspec[param].range[1] ) * 0.5;
532 split( source, left, right, param, mid );
533 Patchlist subpatchlist( patchlist, param, mid );
534 if( left.isnonempty() )
535 if( subpatchlist.cullCheck() == CULL_TRIVIAL_REJECT )
538 nonSamplingSplit( left, subpatchlist, subdivisions-1, param );
539 if( right.isnonempty() )
540 if( patchlist.cullCheck() == CULL_TRIVIAL_REJECT )
543 nonSamplingSplit( right, patchlist, subdivisions-1, param );
548 backend.patch( patchlist.pspec[0].range[0], patchlist.pspec[0].range[1],
549 patchlist.pspec[1].range[0], patchlist.pspec[1].range[1] );
551 if( renderhints.display_method == N_OUTLINE_SUBDIV ) {
557 findIrregularS( source );
558 monosplitInS( source, smbrkpts.start, smbrkpts.end );
569 Subdivider::tessellation(
Bin& bin,
Patchlist &patchlist )
572 tessellate( bin, patchlist.pspec[1].sidestep[1], patchlist.pspec[0].sidestep[1],
573 patchlist.pspec[1].sidestep[0], patchlist.pspec[0].sidestep[0] );
576 slicer.setstriptessellation( patchlist.pspec[0].stepsize, patchlist.pspec[1].stepsize );
579 slicer.set_ulinear( (patchlist.get_uorder() == 2));
580 slicer.set_vlinear( (patchlist.get_vorder() == 2));
583 stepsizes[0] = patchlist.pspec[1].stepsize;
584 stepsizes[1] = patchlist.pspec[0].stepsize;
585 stepsizes[2] = patchlist.pspec[1].stepsize;
586 stepsizes[3] = patchlist.pspec[0].stepsize;
595 Subdivider::monosplitInS(
Bin& source,
int start,
int end )
597 if( source.isnonempty() ) {
599 int i = start + (end - start) / 2;
601 split( source, left, right, 0, smbrkpts.pts[i] );
602 monosplitInS( left, start, i );
603 monosplitInS( right, i+1, end );
605 if( renderhints.display_method == N_OUTLINE_SUBDIV_S ) {
611 findIrregularT( source );
612 monosplitInT( source, tmbrkpts.start, tmbrkpts.end );
624 Subdivider::monosplitInT(
Bin& source,
int start,
int end )
626 if( source.isnonempty() ) {
628 int i = start + (end - start) / 2;
630 split( source, left, right, 1, tmbrkpts.pts[i] );
631 monosplitInT( left, start, i );
632 monosplitInT( right, i+1, end );
634 if( renderhints.display_method == N_OUTLINE_SUBDIV_ST ) {
656 Subdivider::findIrregularS(
Bin& bin )
658 assert( bin.firstarc()->check() != 0 );
660 smbrkpts.grow( bin.numarcs() );
662 for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
663 REAL *a = jarc->prev->tail();
664 REAL *b = jarc->tail();
665 REAL *c = jarc->head();
667 if( b[1] == a[1] && b[1] == c[1] )
continue;
670 if((b[1]<=a[1] && b[1] <= c[1]) ||
671 (b[1]>=a[1] && b[1] >= c[1]))
678 if(a[0]==c[0] && a[1] == c[1])
680 if(jarc->pwlArc->npts >2)
682 c = jarc->pwlArc->pts[jarc->pwlArc->npts-2].param;
686 assert(jarc->prev->pwlArc->npts>2);
687 a = jarc->prev->pwlArc->pts[jarc->prev->pwlArc->npts-2].param;
720 Subdivider::findIrregularT(
Bin& bin )
722 assert( bin.firstarc()->check() != 0 );
724 tmbrkpts.grow( bin.numarcs() );
726 for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
727 REAL *a = jarc->prev->tail();
728 REAL *b = jarc->tail();
729 REAL *c = jarc->head();
731 if( b[0] == a[0] && b[0] == c[0] )
continue;
733 if( b[0] <= a[0] && b[0] <= c[0] ) {
734 if( a[1] != b[1] && b[1] != c[1] )
continue;
735 if( ! ccwTurn_sr( jarc->prev, jarc ) )
736 tmbrkpts.add( b[1] );
737 }
else if ( b[0] >= a[0] && b[0] >= c[0] ) {
738 if( a[1] != b[1] && b[1] != c[1] )
continue;
739 if( ! ccwTurn_sl( jarc->prev, jarc ) )
740 tmbrkpts.add( b[1] );
755 Subdivider::makeBorderTrim(
const REAL *from,
const REAL *to )
764 Arc_ptr jarc =
new(arcpool)
Arc( arc_bottom, 0 );
765 arctessellator.bezier( jarc, smin, smax, tmin, tmin );
766 initialbin.addarc( jarc );
767 pjarc = jarc->append( pjarc );
769 jarc =
new(arcpool)
Arc( arc_right, 0 );
770 arctessellator.bezier( jarc, smax, smax, tmin, tmax );
771 initialbin.addarc( jarc );
772 pjarc = jarc->append( pjarc );
774 jarc =
new(arcpool)
Arc( arc_top, 0 );
775 arctessellator.bezier( jarc, smax, smin, tmax, tmax );
776 initialbin.addarc( jarc );
777 pjarc = jarc->append( pjarc );
779 jarc =
new(arcpool)
Arc( arc_left, 0 );
780 arctessellator.bezier( jarc, smin, smin, tmax, tmin );
781 initialbin.addarc( jarc );
782 jarc->append( pjarc );
784 assert( jarc->check() != 0 );
793 Subdivider::render(
Bin& bin )
798 slicer.setisolines( ( renderhints.display_method == N_ISOLINE_S ) ? 1 : 0 );
800 slicer.setisolines( 0 );
803 for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
804 if( jarc->ismarked() ) {
805 assert( jarc->check( ) != 0 );
806 Arc_ptr jarchead = jarc;
810 }
while (jarc != jarchead);
811 slicer.slice( jarc );
822 Subdivider::outline(
Bin& bin )
825 for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
826 if( jarc->ismarked() ) {
827 assert( jarc->check( ) != 0 );
828 Arc_ptr jarchead = jarc;
830 slicer.outline( jarc );
833 }
while (jarc != jarchead);
844 Subdivider::freejarcs(
Bin& bin )
849 while( (jarc = bin.removearc()) != NULL ) {
850 if( jarc->pwlArc ) jarc->pwlArc->deleteMe( pwlarcpool ); jarc->pwlArc = 0;
851 if( jarc->bezierArc) jarc->bezierArc->deleteMe( bezierarcpool ); jarc->bezierArc = 0;
852 jarc->deleteMe( arcpool );
872 Subdivider::tessellate(
Bin& bin, REAL rrate, REAL trate, REAL lrate, REAL brate )
874 for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
875 if( jarc->isbezier( ) ) {
876 assert( jarc->pwlArc->npts == 2 );
878 REAL s1 = pts[0].param[0];
879 REAL t1 = pts[0].param[1];
880 REAL s2 = pts[1].param[0];
881 REAL t2 = pts[1].param[1];
883 jarc->pwlArc->deleteMe( pwlarcpool ); jarc->pwlArc = 0;
885 switch( jarc->getside() ) {
888 arctessellator.pwl_left( jarc, s1, t1, t2, lrate );
892 arctessellator.pwl_right( jarc, s1, t1, t2, rrate );
896 arctessellator.pwl_top( jarc, t1, s1, s2, trate );
900 arctessellator.pwl_bottom( jarc, t1, s1, s2, brate );
906 assert( ! jarc->isbezier() );
907 assert( jarc->check() != 0 );