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: 2003/10/15 21:11:13 $ $Revision: 1.2 $
39 * $Header: /home/krh/git/sync/mesa-cvs-repo/Mesa/src/glu/sgi/libnurbs/internals/subdivider.cc,v 1.2 2003/10/15 21:11:13 brianp Exp $
42 #include "glimports.h"
45 #include "subdivider.h"
47 #include "bezierarc.h"
49 #include "renderhints.h"
53 #include "patchlist.h"
55 #include "nurbsconsts.h"
56 #include "trimvertpool.h"
57 #include "simplemath.h"
59 #include "polyUtil.h" //for function area()
61 //#define PARTITION_TEST
63 #include "partitionY.h"
64 #include "monoTriangulation.h"
65 #include "dataTransform.h"
66 #include "monoChain.h"
71 #define OPTIMIZE_UNTRIMED_CASE
75 Subdivider::makePatchBoundary( const REAL
*from
, const REAL
*to
)
85 Arc_ptr jarc
= new(arcpool
) Arc( arc_bottom
, 0 );
86 arctessellator
.bezier( jarc
, smin
, smax
, tmin
, tmin
);
88 pjarc
= jarc
->append( pjarc
);
90 jarc
= new(arcpool
) Arc( arc_right
, 0 );
91 arctessellator
.bezier( jarc
, smax
, smax
, tmin
, tmax
);
93 pjarc
= jarc
->append( pjarc
);
95 jarc
= new(arcpool
) Arc( arc_top
, 0 );
96 arctessellator
.bezier( jarc
, smax
, smin
, tmax
, tmax
);
98 pjarc
= jarc
->append( pjarc
);
100 jarc
= new(arcpool
) Arc( arc_left
, 0 );
101 arctessellator
.bezier( jarc
, smin
, smin
, tmax
, tmin
);
103 jarc
->append( pjarc
);
105 assert( jarc
->check() != 0 );
109 /*---------------------------------------------------------------------------
110 * Subdivider - construct a subdivider
111 *---------------------------------------------------------------------------
114 Subdivider::Subdivider( Renderhints
& r
, Backend
& b
)
116 arctessellator( trimvertexpool
, pwlarcpool
),
117 arcpool( sizeof( Arc
), 1, "arcpool" ),
118 bezierarcpool( sizeof( BezierArc
), 1, "Bezarcpool" ),
119 pwlarcpool( sizeof( PwlArc
), 1, "Pwlarcpool" ),
126 Subdivider::setJumpbuffer( JumpBuffer
*j
)
131 /*---------------------------------------------------------------------------
132 * clear - reset all state after possible error condition
133 *---------------------------------------------------------------------------
137 Subdivider::clear( void )
139 trimvertexpool
.clear();
142 bezierarcpool
.clear();
145 /*---------------------------------------------------------------------------
146 * ~Subdivider - destroy a subdivider
147 *---------------------------------------------------------------------------
150 Subdivider::~Subdivider( void )
154 /*---------------------------------------------------------------------------
155 * addArc - add a bezier arc to a trim loop and to a bin
156 *---------------------------------------------------------------------------
159 Subdivider::addArc( REAL
*cpts
, Quilt
*quilt
, long _nuid
)
161 BezierArc
*bezierArc
= new(bezierarcpool
) BezierArc
;
162 Arc
*jarc
= new(arcpool
) Arc( arc_none
, _nuid
);
164 jarc
->bezierArc
= bezierArc
;
165 bezierArc
->order
= quilt
->qspec
->order
;
166 bezierArc
->stride
= quilt
->qspec
->stride
;
167 bezierArc
->mapdesc
= quilt
->mapdesc
;
168 bezierArc
->cpts
= cpts
;
169 initialbin
.addarc( jarc
);
170 pjarc
= jarc
->append( pjarc
);
173 /*---------------------------------------------------------------------------
174 * addArc - add a pwl arc to a trim loop and to a bin
175 *---------------------------------------------------------------------------
179 Subdivider::addArc( int npts
, TrimVertex
*pts
, long _nuid
)
181 Arc
*jarc
= new(arcpool
) Arc( arc_none
, _nuid
);
182 jarc
->pwlArc
= new(pwlarcpool
) PwlArc( npts
, pts
);
183 initialbin
.addarc( jarc
);
184 pjarc
= jarc
->append( pjarc
);
188 Subdivider::beginQuilts( void )
194 Subdivider::addQuilt( Quilt
*quilt
)
200 /*---------------------------------------------------------------------------
201 * drawSurfaces - main entry point for surface tessellation
202 *---------------------------------------------------------------------------
206 Subdivider::drawSurfaces( long nuid
)
212 //initialbin could be nonempty due to some errors
213 freejarcs(initialbin
);
217 for( Quilt
*q
= qlist
; q
; q
= q
->next
) {
218 if( q
->isCulled( ) == CULL_TRIVIAL_REJECT
) {
219 freejarcs( initialbin
);
226 qlist
->getRange( from
, to
, spbrkpts
, tpbrkpts
);
227 #ifdef OPTIMIZE_UNTRIMED_CASE
228 //perform optimization only when the samplng method is
229 //DOMAIN_DISTANCE and the display methdo is either
230 //fill or outline_polygon.
231 int optimize
= (is_domain_distance_sampling
&& (renderhints
.display_method
!= N_OUTLINE_PATCH
));
234 if( ! initialbin
.isnonempty() ) {
235 #ifdef OPTIMIZE_UNTRIMED_CASE
239 makeBorderTrim( from
, to
);
242 makeBorderTrim( from
, to
);
246 qlist
->findRates( spbrkpts
, tpbrkpts
, rate
);
248 if( decompose( initialbin
, min(rate
[0], rate
[1]) ) )
249 mylongjmp( jumpbuffer
, 31 );
252 backend
.bgnsurf( renderhints
.wiretris
, renderhints
.wirequads
, nuid
);
254 #ifdef PARTITION_TEST
255 if( initialbin
.isnonempty() && spbrkpts
.end
-2 == spbrkpts
.start
&&
256 tpbrkpts
.end
-2 == tpbrkpts
.start
)
258 for(int i
=spbrkpts
.start
; i
<spbrkpts
.end
-1; i
++){
259 for(int j
=tpbrkpts
.start
; j
<tpbrkpts
.end
-1; j
++){
261 pta
[0] = spbrkpts
.pts
[i
];
262 ptb
[0] = spbrkpts
.pts
[i
+1];
263 pta
[1] = tpbrkpts
.pts
[j
];
264 ptb
[1] = tpbrkpts
.pts
[j
+1];
265 qlist
->downloadAll(pta
, ptb
, backend
);
271 poly
= bin_to_DLineLoops(initialbin
);
273 poly
=poly
->deleteDegenerateLinesAllPolygons();
275 sampledLine
* retSampledLines
;
276 //printf("before MC_partition\n");
277 poly
= MC_partitionY(poly
, &retSampledLines
);
278 //printf("after MC_partition\n");
284 primStream
pStream(5000,5000);
287 for(temp
=poly
; temp
!= NULL
; temp
=temp
->getNextPolygon())
289 monoTriangulation(temp
, &pStream
);
291 slicer
.evalStream(&pStream
);
294 //need to clean up space
297 freejarcs( initialbin
);
302 printf("num_polygons=%i\n", poly->numPolygons());
303 printf("num_edges=%i\n", poly->numEdgesAllPolygons());
304 poly->writeAllPolygons("zloutputFile");
307 primStream pStream(20,20);
308 for(directedLine* tempD = poly; tempD != NULL; tempD = tempD->getNextPolygon())
309 monoTriangulation(tempD, &pStream);
314 #endif //PARTITION_TEST
317 #ifdef OPTIMIZE_UNTRIMED_CASE
318 if( (!initialbin
.isnonempty()) && optimize
)
323 for(i
=spbrkpts
.start
; i
<spbrkpts
.end
-1; i
++){
324 for(j
=tpbrkpts
.start
; j
<tpbrkpts
.end
-1; j
++){
326 pta
[0] = spbrkpts
.pts
[i
];
327 ptb
[0] = spbrkpts
.pts
[i
+1];
328 pta
[1] = tpbrkpts
.pts
[j
];
329 ptb
[1] = tpbrkpts
.pts
[j
+1];
330 qlist
->downloadAll(pta
, ptb
, backend
);
332 num_u_steps
= (int) (domain_distance_u_rate
* (ptb
[0]-pta
[0]));
333 num_v_steps
= (int) (domain_distance_v_rate
* (ptb
[1]-pta
[1]));
335 if(num_u_steps
<= 0) num_u_steps
= 1;
336 if(num_v_steps
<= 0) num_v_steps
= 1;
338 backend
.surfgrid(pta
[0], ptb
[0], num_u_steps
,
339 ptb
[1], pta
[1], num_v_steps
);
340 backend
.surfmesh(0,0,num_u_steps
,num_v_steps
);
345 /* the following is left for reference purpose, don't delete
348 Patchlist patchlist(qlist, pta, ptb);
349 patchlist.getstepsize();
351 tempSource=makePatchBoundary(pta, ptb);
353 tessellation(*tempSource, patchlist);
363 subdivideInS( initialbin
);
366 subdivideInS( initialbin
);
374 Subdivider::subdivideInS( Bin
& source
)
376 if( renderhints
.display_method
== N_OUTLINE_PARAM
) {
382 splitInS( source
, spbrkpts
.start
, spbrkpts
.end
);
387 /*---------------------------------------------------------------------------
388 * splitInS - split a patch and a bin by an isoparametric line
389 *---------------------------------------------------------------------------
393 Subdivider::splitInS( Bin
& source
, int start
, int end
)
395 if( source
.isnonempty() ) {
397 int i
= start
+ (end
- start
) / 2;
399 split( source
, left
, right
, 0, spbrkpts
.pts
[i
] );
400 splitInS( left
, start
, i
);
401 splitInS( right
, i
+1, end
);
403 if( start
== spbrkpts
.start
|| start
== spbrkpts
.end
) {
405 } else if( renderhints
.display_method
== N_OUTLINE_PARAM_S
) {
412 splitInT( source
, tpbrkpts
.start
, tpbrkpts
.end
);
418 /*---------------------------------------------------------------------------
419 * splitInT - split a patch and a bin by an isoparametric line
420 *---------------------------------------------------------------------------
424 Subdivider::splitInT( Bin
& source
, int start
, int end
)
426 if( source
.isnonempty() ) {
428 int i
= start
+ (end
- start
) / 2;
430 split( source
, left
, right
, 1, tpbrkpts
.pts
[i
] );
431 splitInT( left
, start
, i
);
432 splitInT( right
, i
+1, end
);
434 if( start
== tpbrkpts
.start
|| start
== tpbrkpts
.end
) {
436 } else if( renderhints
.display_method
== N_OUTLINE_PARAM_ST
) {
445 pta
[0] = spbrkpts
.pts
[s_index
-1];
446 pta
[1] = tpbrkpts
.pts
[t_index
-1];
448 ptb
[0] = spbrkpts
.pts
[s_index
];
449 ptb
[1] = tpbrkpts
.pts
[t_index
];
450 qlist
->downloadAll( pta
, ptb
, backend
);
452 Patchlist
patchlist( qlist
, pta
, ptb
);
454 printf("-------samplingSplit-----\n");
455 source.show("samplingSplit source");
457 samplingSplit( source
, patchlist
, renderhints
.maxsubdivisions
, 0 );
465 /*--------------------------------------------------------------------------
466 * samplingSplit - recursively subdivide patch, cull check each subpatch
467 *--------------------------------------------------------------------------
471 Subdivider::samplingSplit(
473 Patchlist
& patchlist
,
477 if( ! source
.isnonempty() ) return;
479 if( patchlist
.cullCheck() == CULL_TRIVIAL_REJECT
) {
484 patchlist
.getstepsize();
486 if( renderhints
.display_method
== N_OUTLINE_PATCH
) {
487 tessellation( source
, patchlist
);
495 tessellation( source
, patchlist
);
497 if( patchlist
.needsSamplingSubdivision() && (subdivisions
> 0) ) {
498 if( ! patchlist
.needsSubdivision( 0 ) )
500 else if( ! patchlist
.needsSubdivision( 1 ) )
506 REAL mid
= ( patchlist
.pspec
[param
].range
[0] +
507 patchlist
.pspec
[param
].range
[1] ) * 0.5;
508 split( source
, left
, right
, param
, mid
);
509 Patchlist
subpatchlist( patchlist
, param
, mid
);
510 samplingSplit( left
, subpatchlist
, subdivisions
-1, param
);
511 samplingSplit( right
, patchlist
, subdivisions
-1, param
);
515 nonSamplingSplit( source
, patchlist
, subdivisions
, param
);
522 Subdivider::nonSamplingSplit(
524 Patchlist
& patchlist
,
528 if( patchlist
.needsNonSamplingSubdivision() && (subdivisions
> 0) ) {
532 REAL mid
= ( patchlist
.pspec
[param
].range
[0] +
533 patchlist
.pspec
[param
].range
[1] ) * 0.5;
534 split( source
, left
, right
, param
, mid
);
535 Patchlist
subpatchlist( patchlist
, param
, mid
);
536 if( left
.isnonempty() )
537 if( subpatchlist
.cullCheck() == CULL_TRIVIAL_REJECT
)
540 nonSamplingSplit( left
, subpatchlist
, subdivisions
-1, param
);
541 if( right
.isnonempty() )
542 if( patchlist
.cullCheck() == CULL_TRIVIAL_REJECT
)
545 nonSamplingSplit( right
, patchlist
, subdivisions
-1, param
);
550 backend
.patch( patchlist
.pspec
[0].range
[0], patchlist
.pspec
[0].range
[1],
551 patchlist
.pspec
[1].range
[0], patchlist
.pspec
[1].range
[1] );
553 if( renderhints
.display_method
== N_OUTLINE_SUBDIV
) {
559 findIrregularS( source
);
560 monosplitInS( source
, smbrkpts
.start
, smbrkpts
.end
);
565 /*--------------------------------------------------------------------------
566 * tessellation - set tessellation of interior and boundary of patch
567 *--------------------------------------------------------------------------
571 Subdivider::tessellation( Bin
& bin
, Patchlist
&patchlist
)
573 // tessellate unsampled trim curves
574 tessellate( bin
, patchlist
.pspec
[1].sidestep
[1], patchlist
.pspec
[0].sidestep
[1],
575 patchlist
.pspec
[1].sidestep
[0], patchlist
.pspec
[0].sidestep
[0] );
577 // set interior sampling rates
578 slicer
.setstriptessellation( patchlist
.pspec
[0].stepsize
, patchlist
.pspec
[1].stepsize
);
580 //added by zl: set the order which will be used in slicer.c++
581 slicer
.set_ulinear( (patchlist
.get_uorder() == 2));
582 slicer
.set_vlinear( (patchlist
.get_vorder() == 2));
584 // set boundary sampling rates
585 stepsizes
[0] = patchlist
.pspec
[1].stepsize
;
586 stepsizes
[1] = patchlist
.pspec
[0].stepsize
;
587 stepsizes
[2] = patchlist
.pspec
[1].stepsize
;
588 stepsizes
[3] = patchlist
.pspec
[0].stepsize
;
591 /*---------------------------------------------------------------------------
592 * monosplitInS - split a patch and a bin by an isoparametric line
593 *---------------------------------------------------------------------------
597 Subdivider::monosplitInS( Bin
& source
, int start
, int end
)
599 if( source
.isnonempty() ) {
601 int i
= start
+ (end
- start
) / 2;
603 split( source
, left
, right
, 0, smbrkpts
.pts
[i
] );
604 monosplitInS( left
, start
, i
);
605 monosplitInS( right
, i
+1, end
);
607 if( renderhints
.display_method
== N_OUTLINE_SUBDIV_S
) {
613 findIrregularT( source
);
614 monosplitInT( source
, tmbrkpts
.start
, tmbrkpts
.end
);
620 /*---------------------------------------------------------------------------
621 * monosplitInT - split a patch and a bin by an isoparametric line
622 *---------------------------------------------------------------------------
626 Subdivider::monosplitInT( Bin
& source
, int start
, int end
)
628 if( source
.isnonempty() ) {
630 int i
= start
+ (end
- start
) / 2;
632 split( source
, left
, right
, 1, tmbrkpts
.pts
[i
] );
633 monosplitInT( left
, start
, i
);
634 monosplitInT( right
, i
+1, end
);
636 if( renderhints
.display_method
== N_OUTLINE_SUBDIV_ST
) {
641 printf("*******render\n");
642 source.show("source\n");
652 /*----------------------------------------------------------------------------
653 * findIrregularS - determine points of non-monotonicity is s direction
654 *----------------------------------------------------------------------------
658 Subdivider::findIrregularS( Bin
& bin
)
660 assert( bin
.firstarc()->check() != 0 );
662 smbrkpts
.grow( bin
.numarcs() );
664 for( Arc_ptr jarc
=bin
.firstarc(); jarc
; jarc
=bin
.nextarc() ) {
665 REAL
*a
= jarc
->prev
->tail();
666 REAL
*b
= jarc
->tail();
667 REAL
*c
= jarc
->head();
669 if( b
[1] == a
[1] && b
[1] == c
[1] ) continue;
672 if((b
[1]<=a
[1] && b
[1] <= c
[1]) ||
673 (b
[1]>=a
[1] && b
[1] >= c
[1]))
675 //each arc (jarc, jarc->prev, jarc->next) is a
676 //monotone arc consisting of multiple line segements.
677 //it may happen that jarc->prev and jarc->next are the same,
678 //that is, jarc->prev and jarc form a closed loop.
679 //In such case, a and c will be the same.
680 if(a
[0]==c
[0] && a
[1] == c
[1])
682 if(jarc
->pwlArc
->npts
>2)
684 c
= jarc
->pwlArc
->pts
[jarc
->pwlArc
->npts
-2].param
;
688 assert(jarc
->prev
->pwlArc
->npts
>2);
689 a
= jarc
->prev
->pwlArc
->pts
[jarc
->prev
->pwlArc
->npts
-2].param
;
701 if( b[1] <= a[1] && b[1] <= c[1] ) {
702 if( ! ccwTurn_tr( jarc->prev, jarc ) )
703 smbrkpts.add( b[0] );
704 } else if( b[1] >= a[1] && b[1] >= c[1] ) {
705 if( ! ccwTurn_tl( jarc->prev, jarc ) )
706 smbrkpts.add( b[0] );
715 /*----------------------------------------------------------------------------
716 * findIrregularT - determine points of non-monotonicity in t direction
717 * where one arc is parallel to the s axis.
718 *----------------------------------------------------------------------------
722 Subdivider::findIrregularT( Bin
& bin
)
724 assert( bin
.firstarc()->check() != 0 );
726 tmbrkpts
.grow( bin
.numarcs() );
728 for( Arc_ptr jarc
=bin
.firstarc(); jarc
; jarc
=bin
.nextarc() ) {
729 REAL
*a
= jarc
->prev
->tail();
730 REAL
*b
= jarc
->tail();
731 REAL
*c
= jarc
->head();
733 if( b
[0] == a
[0] && b
[0] == c
[0] ) continue;
735 if( b
[0] <= a
[0] && b
[0] <= c
[0] ) {
736 if( a
[1] != b
[1] && b
[1] != c
[1] ) continue;
737 if( ! ccwTurn_sr( jarc
->prev
, jarc
) )
738 tmbrkpts
.add( b
[1] );
739 } else if ( b
[0] >= a
[0] && b
[0] >= c
[0] ) {
740 if( a
[1] != b
[1] && b
[1] != c
[1] ) continue;
741 if( ! ccwTurn_sl( jarc
->prev
, jarc
) )
742 tmbrkpts
.add( b
[1] );
748 /*-----------------------------------------------------------------------------
749 * makeBorderTrim - if no user input trimming data then create
750 * a trimming curve around the boundaries of the Quilt. The curve consists of
751 * four Jordan arcs, one for each side of the Quilt, connected, of course,
753 *-----------------------------------------------------------------------------
757 Subdivider::makeBorderTrim( const REAL
*from
, const REAL
*to
)
766 Arc_ptr jarc
= new(arcpool
) Arc( arc_bottom
, 0 );
767 arctessellator
.bezier( jarc
, smin
, smax
, tmin
, tmin
);
768 initialbin
.addarc( jarc
);
769 pjarc
= jarc
->append( pjarc
);
771 jarc
= new(arcpool
) Arc( arc_right
, 0 );
772 arctessellator
.bezier( jarc
, smax
, smax
, tmin
, tmax
);
773 initialbin
.addarc( jarc
);
774 pjarc
= jarc
->append( pjarc
);
776 jarc
= new(arcpool
) Arc( arc_top
, 0 );
777 arctessellator
.bezier( jarc
, smax
, smin
, tmax
, tmax
);
778 initialbin
.addarc( jarc
);
779 pjarc
= jarc
->append( pjarc
);
781 jarc
= new(arcpool
) Arc( arc_left
, 0 );
782 arctessellator
.bezier( jarc
, smin
, smin
, tmax
, tmin
);
783 initialbin
.addarc( jarc
);
784 jarc
->append( pjarc
);
786 assert( jarc
->check() != 0 );
789 /*----------------------------------------------------------------------------
790 * render - renders all monotone regions in a bin and frees the bin
791 *----------------------------------------------------------------------------
795 Subdivider::render( Bin
& bin
)
800 slicer
.setisolines( ( renderhints
.display_method
== N_ISOLINE_S
) ? 1 : 0 );
802 slicer
.setisolines( 0 );
805 for( Arc_ptr jarc
=bin
.firstarc(); jarc
; jarc
=bin
.nextarc() ) {
806 if( jarc
->ismarked() ) {
807 assert( jarc
->check( ) != 0 );
808 Arc_ptr jarchead
= jarc
;
812 } while (jarc
!= jarchead
);
813 slicer
.slice( jarc
);
818 /*---------------------------------------------------------------------------
819 * outline - render the trimmed patch by outlining the boundary
820 *---------------------------------------------------------------------------
824 Subdivider::outline( Bin
& bin
)
827 for( Arc_ptr jarc
=bin
.firstarc(); jarc
; jarc
=bin
.nextarc() ) {
828 if( jarc
->ismarked() ) {
829 assert( jarc
->check( ) != 0 );
830 Arc_ptr jarchead
= jarc
;
832 slicer
.outline( jarc
);
835 } while (jarc
!= jarchead
);
840 /*---------------------------------------------------------------------------
841 * freejarcs - free all arcs in a bin
842 *---------------------------------------------------------------------------
846 Subdivider::freejarcs( Bin
& bin
)
848 bin
.adopt(); /* XXX - should not be necessary */
851 while( (jarc
= bin
.removearc()) != NULL
) {
852 if( jarc
->pwlArc
) jarc
->pwlArc
->deleteMe( pwlarcpool
); jarc
->pwlArc
= 0;
853 if( jarc
->bezierArc
) jarc
->bezierArc
->deleteMe( bezierarcpool
); jarc
->bezierArc
= 0;
854 jarc
->deleteMe( arcpool
);
858 /*----------------------------------------------------------------------------
859 * tessellate - tessellate all Bezier arcs in a bin
860 * 1) only accepts linear Bezier arcs as input
861 * 2) the Bezier arcs are stored in the pwlArc structure
862 * 3) only vertical or horizontal lines work
864 * 1) represent Bezier arcs in BezierArc structure
865 * (this requires a multitude of changes to the code)
866 * 2) accept high degree Bezier arcs (hard)
867 * 3) map the curve onto the surface to determine tessellation
868 * 4) work for curves of arbitrary geometry
869 *----------------------------------------------------------------------------
874 Subdivider::tessellate( Bin
& bin
, REAL rrate
, REAL trate
, REAL lrate
, REAL brate
)
876 for( Arc_ptr jarc
=bin
.firstarc(); jarc
; jarc
=bin
.nextarc() ) {
877 if( jarc
->isbezier( ) ) {
878 assert( jarc
->pwlArc
->npts
== 2 );
879 TrimVertex
*pts
= jarc
->pwlArc
->pts
;
880 REAL s1
= pts
[0].param
[0];
881 REAL t1
= pts
[0].param
[1];
882 REAL s2
= pts
[1].param
[0];
883 REAL t2
= pts
[1].param
[1];
885 jarc
->pwlArc
->deleteMe( pwlarcpool
); jarc
->pwlArc
= 0;
887 switch( jarc
->getside() ) {
890 arctessellator
.pwl_left( jarc
, s1
, t1
, t2
, lrate
);
894 arctessellator
.pwl_right( jarc
, s1
, t1
, t2
, rrate
);
898 arctessellator
.pwl_top( jarc
, t1
, s1
, s2
, trate
);
902 arctessellator
.pwl_bottom( jarc
, t1
, s1
, s2
, brate
);
908 assert( ! jarc
->isbezier() );
909 assert( jarc
->check() != 0 );