mirror of
https://github.com/reactos/reactos.git
synced 2025-01-12 09:07:54 +00:00
c424146e2c
svn path=/branches/cmake-bringup/; revision=48236
912 lines
25 KiB
C++
912 lines
25 KiB
C++
/*
|
|
** License Applicability. Except to the extent portions of this file are
|
|
** made subject to an alternative license as permitted in the SGI Free
|
|
** Software License B, Version 1.1 (the "License"), the contents of this
|
|
** file are subject only to the provisions of the License. You may not use
|
|
** this file except in compliance with the License. You may obtain a copy
|
|
** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
|
|
** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
|
|
**
|
|
** http://oss.sgi.com/projects/FreeB
|
|
**
|
|
** Note that, as provided in the License, the Software is distributed on an
|
|
** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
|
|
** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
|
|
** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
|
|
** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
|
|
**
|
|
** Original Code. The Original Code is: OpenGL Sample Implementation,
|
|
** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
|
|
** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
|
|
** Copyright in any portions created by third parties is as indicated
|
|
** elsewhere herein. All Rights Reserved.
|
|
**
|
|
** Additional Notice Provisions: The application programming interfaces
|
|
** established by SGI in conjunction with the Original Code are The
|
|
** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
|
|
** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
|
|
** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
|
|
** Window System(R) (Version 1.3), released October 19, 1998. This software
|
|
** was created using the OpenGL(R) version 1.2.1 Sample Implementation
|
|
** published by SGI, but has not been independently verified as being
|
|
** compliant with the OpenGL(R) version 1.2.1 Specification.
|
|
*/
|
|
|
|
/*
|
|
* subdivider.cxx
|
|
*
|
|
*/
|
|
|
|
#include "glimports.h"
|
|
#include "myassert.h"
|
|
#include "mystdio.h"
|
|
#include "subdivider.h"
|
|
#include "arc.h"
|
|
#include "bezierarc.h"
|
|
#include "bin.h"
|
|
#include "renderhints.h"
|
|
#include "backend.h"
|
|
#include "mapdesc.h"
|
|
#include "quilt.h"
|
|
#include "patchlist.h"
|
|
#include "patch.h"
|
|
#include "nurbsconsts.h"
|
|
#include "trimvertpool.h"
|
|
#include "simplemath.h"
|
|
|
|
#include "polyUtil.h" //for function area()
|
|
|
|
//#define PARTITION_TEST
|
|
#ifdef PARTITION_TEST
|
|
#include "partitionY.h"
|
|
#include "monoTriangulation.h"
|
|
#include "dataTransform.h"
|
|
#include "monoChain.h"
|
|
|
|
#endif
|
|
|
|
|
|
#define OPTIMIZE_UNTRIMED_CASE
|
|
|
|
|
|
Bin*
|
|
Subdivider::makePatchBoundary( const REAL *from, const REAL *to )
|
|
{
|
|
Bin* ret = new Bin();
|
|
REAL smin = from[0];
|
|
REAL smax = to[0];
|
|
REAL tmin = from[1];
|
|
REAL tmax = to[1];
|
|
|
|
pjarc = 0;
|
|
|
|
Arc_ptr jarc = new(arcpool) Arc( arc_bottom, 0 );
|
|
arctessellator.bezier( jarc, smin, smax, tmin, tmin );
|
|
ret->addarc( jarc );
|
|
pjarc = jarc->append( pjarc );
|
|
|
|
jarc = new(arcpool) Arc( arc_right, 0 );
|
|
arctessellator.bezier( jarc, smax, smax, tmin, tmax );
|
|
ret->addarc( jarc );
|
|
pjarc = jarc->append( pjarc );
|
|
|
|
jarc = new(arcpool) Arc( arc_top, 0 );
|
|
arctessellator.bezier( jarc, smax, smin, tmax, tmax );
|
|
ret->addarc( jarc );
|
|
pjarc = jarc->append( pjarc );
|
|
|
|
jarc = new(arcpool) Arc( arc_left, 0 );
|
|
arctessellator.bezier( jarc, smin, smin, tmax, tmin );
|
|
ret->addarc( jarc );
|
|
jarc->append( pjarc );
|
|
|
|
assert( jarc->check() != 0 );
|
|
return ret;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* Subdivider - construct a subdivider
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
|
|
Subdivider::Subdivider( Renderhints& r, Backend& b )
|
|
: slicer( b ),
|
|
arctessellator( trimvertexpool, pwlarcpool ),
|
|
arcpool( sizeof( Arc), 1, "arcpool" ),
|
|
bezierarcpool( sizeof( BezierArc ), 1, "Bezarcpool" ),
|
|
pwlarcpool( sizeof( PwlArc ), 1, "Pwlarcpool" ),
|
|
renderhints( r ),
|
|
backend( b )
|
|
{
|
|
}
|
|
|
|
void
|
|
Subdivider::setJumpbuffer( JumpBuffer *j )
|
|
{
|
|
jumpbuffer = j;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* clear - reset all state after possible error condition
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
Subdivider::clear( void )
|
|
{
|
|
trimvertexpool.clear();
|
|
arcpool.clear();
|
|
pwlarcpool.clear();
|
|
bezierarcpool.clear();
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* ~Subdivider - destroy a subdivider
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
|
|
Subdivider::~Subdivider( void )
|
|
{
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* addArc - add a bezier arc to a trim loop and to a bin
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
Subdivider::addArc( REAL *cpts, Quilt *quilt, long _nuid )
|
|
{
|
|
BezierArc *bezierArc = new(bezierarcpool) BezierArc;
|
|
Arc *jarc = new(arcpool) Arc( arc_none, _nuid );
|
|
jarc->pwlArc = 0;
|
|
jarc->bezierArc = bezierArc;
|
|
bezierArc->order = quilt->qspec->order;
|
|
bezierArc->stride = quilt->qspec->stride;
|
|
bezierArc->mapdesc = quilt->mapdesc;
|
|
bezierArc->cpts = cpts;
|
|
initialbin.addarc( jarc );
|
|
pjarc = jarc->append( pjarc );
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* addArc - add a pwl arc to a trim loop and to a bin
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
Subdivider::addArc( int npts, TrimVertex *pts, long _nuid )
|
|
{
|
|
Arc *jarc = new(arcpool) Arc( arc_none, _nuid );
|
|
jarc->pwlArc = new(pwlarcpool) PwlArc( npts, pts );
|
|
initialbin.addarc( jarc );
|
|
pjarc = jarc->append( pjarc );
|
|
}
|
|
|
|
void
|
|
Subdivider::beginQuilts( void )
|
|
{
|
|
qlist = 0;
|
|
}
|
|
|
|
void
|
|
Subdivider::addQuilt( Quilt *quilt )
|
|
{
|
|
quilt->next = qlist;
|
|
qlist = quilt;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* drawSurfaces - main entry point for surface tessellation
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
Subdivider::drawSurfaces( long nuid )
|
|
{
|
|
renderhints.init( );
|
|
|
|
if (qlist == NULL)
|
|
{
|
|
//initialbin could be nonempty due to some errors
|
|
freejarcs(initialbin);
|
|
return;
|
|
}
|
|
|
|
for( Quilt *q = qlist; q; q = q->next ) {
|
|
if( q->isCulled( ) == CULL_TRIVIAL_REJECT ) {
|
|
freejarcs( initialbin );
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
REAL from[2], to[2];
|
|
qlist->getRange( from, to, spbrkpts, tpbrkpts );
|
|
#ifdef OPTIMIZE_UNTRIMED_CASE
|
|
//perform optimization only when the samplng method is
|
|
//DOMAIN_DISTANCE and the display methdo is either
|
|
//fill or outline_polygon.
|
|
int optimize = (is_domain_distance_sampling && (renderhints.display_method != N_OUTLINE_PATCH));
|
|
#endif
|
|
|
|
if( ! initialbin.isnonempty() ) {
|
|
#ifdef OPTIMIZE_UNTRIMED_CASE
|
|
if(! optimize )
|
|
{
|
|
|
|
makeBorderTrim( from, to );
|
|
}
|
|
#else
|
|
makeBorderTrim( from, to );
|
|
#endif
|
|
} else {
|
|
REAL rate[2];
|
|
qlist->findRates( spbrkpts, tpbrkpts, rate );
|
|
|
|
if( decompose( initialbin, min(rate[0], rate[1]) ) )
|
|
mylongjmp( jumpbuffer, 31 );
|
|
}
|
|
|
|
backend.bgnsurf( renderhints.wiretris, renderhints.wirequads, nuid );
|
|
|
|
#ifdef PARTITION_TEST
|
|
if( initialbin.isnonempty() && spbrkpts.end-2 == spbrkpts.start &&
|
|
tpbrkpts.end-2 == tpbrkpts.start)
|
|
{
|
|
for(int i=spbrkpts.start; i<spbrkpts.end-1; i++){
|
|
for(int j=tpbrkpts.start; j<tpbrkpts.end-1; j++){
|
|
Real pta[2], ptb[2];
|
|
pta[0] = spbrkpts.pts[i];
|
|
ptb[0] = spbrkpts.pts[i+1];
|
|
pta[1] = tpbrkpts.pts[j];
|
|
ptb[1] = tpbrkpts.pts[j+1];
|
|
qlist->downloadAll(pta, ptb, backend);
|
|
|
|
directedLine *poly;
|
|
|
|
{
|
|
|
|
poly = bin_to_DLineLoops(initialbin);
|
|
|
|
poly=poly->deleteDegenerateLinesAllPolygons();
|
|
|
|
sampledLine* retSampledLines;
|
|
//printf("before MC_partition\n");
|
|
poly = MC_partitionY(poly, &retSampledLines);
|
|
//printf("after MC_partition\n");
|
|
|
|
}
|
|
|
|
|
|
{
|
|
primStream pStream(5000,5000);
|
|
directedLine* temp;
|
|
|
|
for(temp=poly; temp != NULL; temp=temp->getNextPolygon())
|
|
|
|
monoTriangulation(temp, &pStream);
|
|
|
|
slicer.evalStream(&pStream);
|
|
|
|
}
|
|
//need to clean up space
|
|
}
|
|
}
|
|
freejarcs( initialbin );
|
|
backend.endsurf();
|
|
return;
|
|
|
|
/*
|
|
printf("num_polygons=%i\n", poly->numPolygons());
|
|
printf("num_edges=%i\n", poly->numEdgesAllPolygons());
|
|
poly->writeAllPolygons("zloutputFile");
|
|
return;
|
|
{
|
|
primStream pStream(20,20);
|
|
for(directedLine* tempD = poly; tempD != NULL; tempD = tempD->getNextPolygon())
|
|
monoTriangulation(tempD, &pStream);
|
|
}
|
|
return;
|
|
*/
|
|
}
|
|
#endif //PARTITION_TEST
|
|
|
|
|
|
#ifdef OPTIMIZE_UNTRIMED_CASE
|
|
if( (!initialbin.isnonempty()) && optimize )
|
|
{
|
|
int i,j;
|
|
int num_u_steps;
|
|
int num_v_steps;
|
|
for(i=spbrkpts.start; i<spbrkpts.end-1; i++){
|
|
for(j=tpbrkpts.start; j<tpbrkpts.end-1; j++){
|
|
Real pta[2], ptb[2];
|
|
pta[0] = spbrkpts.pts[i];
|
|
ptb[0] = spbrkpts.pts[i+1];
|
|
pta[1] = tpbrkpts.pts[j];
|
|
ptb[1] = tpbrkpts.pts[j+1];
|
|
qlist->downloadAll(pta, ptb, backend);
|
|
|
|
num_u_steps = (int) (domain_distance_u_rate * (ptb[0]-pta[0]));
|
|
num_v_steps = (int) (domain_distance_v_rate * (ptb[1]-pta[1]));
|
|
|
|
if(num_u_steps <= 0) num_u_steps = 1;
|
|
if(num_v_steps <= 0) num_v_steps = 1;
|
|
|
|
backend.surfgrid(pta[0], ptb[0], num_u_steps,
|
|
ptb[1], pta[1], num_v_steps);
|
|
backend.surfmesh(0,0,num_u_steps,num_v_steps);
|
|
|
|
|
|
|
|
continue;
|
|
/* the following is left for reference purpose, don't delete
|
|
{
|
|
Bin* tempSource;
|
|
Patchlist patchlist(qlist, pta, ptb);
|
|
patchlist.getstepsize();
|
|
|
|
tempSource=makePatchBoundary(pta, ptb);
|
|
|
|
tessellation(*tempSource, patchlist);
|
|
|
|
render(*tempSource);
|
|
delete tempSource;
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
}
|
|
else
|
|
subdivideInS( initialbin );
|
|
#else
|
|
|
|
subdivideInS( initialbin );
|
|
#endif
|
|
|
|
backend.endsurf();
|
|
|
|
}
|
|
|
|
void
|
|
Subdivider::subdivideInS( Bin& source )
|
|
{
|
|
if( renderhints.display_method == N_OUTLINE_PARAM ) {
|
|
outline( source );
|
|
freejarcs( source );
|
|
} else {
|
|
setArcTypeBezier();
|
|
setNonDegenerate();
|
|
splitInS( source, spbrkpts.start, spbrkpts.end );
|
|
}
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* splitInS - split a patch and a bin by an isoparametric line
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
Subdivider::splitInS( Bin& source, int start, int end )
|
|
{
|
|
if( source.isnonempty() ) {
|
|
if( start != end ) {
|
|
int i = start + (end - start) / 2;
|
|
Bin left, right;
|
|
split( source, left, right, 0, spbrkpts.pts[i] );
|
|
splitInS( left, start, i );
|
|
splitInS( right, i+1, end );
|
|
} else {
|
|
if( start == spbrkpts.start || start == spbrkpts.end ) {
|
|
freejarcs( source );
|
|
} else if( renderhints.display_method == N_OUTLINE_PARAM_S ) {
|
|
outline( source );
|
|
freejarcs( source );
|
|
} else {
|
|
setArcTypeBezier();
|
|
setNonDegenerate();
|
|
s_index = start;
|
|
splitInT( source, tpbrkpts.start, tpbrkpts.end );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* splitInT - split a patch and a bin by an isoparametric line
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
Subdivider::splitInT( Bin& source, int start, int end )
|
|
{
|
|
if( source.isnonempty() ) {
|
|
if( start != end ) {
|
|
int i = start + (end - start) / 2;
|
|
Bin left, right;
|
|
split( source, left, right, 1, tpbrkpts.pts[i] );
|
|
splitInT( left, start, i );
|
|
splitInT( right, i+1, end );
|
|
} else {
|
|
if( start == tpbrkpts.start || start == tpbrkpts.end ) {
|
|
freejarcs( source );
|
|
} else if( renderhints.display_method == N_OUTLINE_PARAM_ST ) {
|
|
outline( source );
|
|
freejarcs( source );
|
|
} else {
|
|
t_index = start;
|
|
setArcTypeBezier();
|
|
setDegenerate();
|
|
|
|
REAL pta[2], ptb[2];
|
|
pta[0] = spbrkpts.pts[s_index-1];
|
|
pta[1] = tpbrkpts.pts[t_index-1];
|
|
|
|
ptb[0] = spbrkpts.pts[s_index];
|
|
ptb[1] = tpbrkpts.pts[t_index];
|
|
qlist->downloadAll( pta, ptb, backend );
|
|
|
|
Patchlist patchlist( qlist, pta, ptb );
|
|
/*
|
|
printf("-------samplingSplit-----\n");
|
|
source.show("samplingSplit source");
|
|
*/
|
|
samplingSplit( source, patchlist, renderhints.maxsubdivisions, 0 );
|
|
setNonDegenerate();
|
|
setArcTypeBezier();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* samplingSplit - recursively subdivide patch, cull check each subpatch
|
|
*--------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
Subdivider::samplingSplit(
|
|
Bin& source,
|
|
Patchlist& patchlist,
|
|
int subdivisions,
|
|
int param )
|
|
{
|
|
if( ! source.isnonempty() ) return;
|
|
|
|
if( patchlist.cullCheck() == CULL_TRIVIAL_REJECT ) {
|
|
freejarcs( source );
|
|
return;
|
|
}
|
|
|
|
patchlist.getstepsize();
|
|
|
|
if( renderhints.display_method == N_OUTLINE_PATCH ) {
|
|
tessellation( source, patchlist );
|
|
outline( source );
|
|
freejarcs( source );
|
|
return;
|
|
}
|
|
|
|
//patchlist.clamp();
|
|
|
|
tessellation( source, patchlist );
|
|
|
|
if( patchlist.needsSamplingSubdivision() && (subdivisions > 0) ) {
|
|
if( ! patchlist.needsSubdivision( 0 ) )
|
|
param = 1;
|
|
else if( ! patchlist.needsSubdivision( 1 ) )
|
|
param = 0;
|
|
else
|
|
param = 1 - param;
|
|
|
|
Bin left, right;
|
|
REAL mid = ( patchlist.pspec[param].range[0] +
|
|
patchlist.pspec[param].range[1] ) * 0.5;
|
|
split( source, left, right, param, mid );
|
|
Patchlist subpatchlist( patchlist, param, mid );
|
|
samplingSplit( left, subpatchlist, subdivisions-1, param );
|
|
samplingSplit( right, patchlist, subdivisions-1, param );
|
|
} else {
|
|
setArcTypePwl();
|
|
setDegenerate();
|
|
nonSamplingSplit( source, patchlist, subdivisions, param );
|
|
setDegenerate();
|
|
setArcTypeBezier();
|
|
}
|
|
}
|
|
|
|
void
|
|
Subdivider::nonSamplingSplit(
|
|
Bin& source,
|
|
Patchlist& patchlist,
|
|
int subdivisions,
|
|
int param )
|
|
{
|
|
if( patchlist.needsNonSamplingSubdivision() && (subdivisions > 0) ) {
|
|
param = 1 - param;
|
|
|
|
Bin left, right;
|
|
REAL mid = ( patchlist.pspec[param].range[0] +
|
|
patchlist.pspec[param].range[1] ) * 0.5;
|
|
split( source, left, right, param, mid );
|
|
Patchlist subpatchlist( patchlist, param, mid );
|
|
if( left.isnonempty() ) {
|
|
if( subpatchlist.cullCheck() == CULL_TRIVIAL_REJECT )
|
|
freejarcs( left );
|
|
else
|
|
nonSamplingSplit( left, subpatchlist, subdivisions-1, param );
|
|
}
|
|
if( right.isnonempty() ) {
|
|
if( patchlist.cullCheck() == CULL_TRIVIAL_REJECT )
|
|
freejarcs( right );
|
|
else
|
|
nonSamplingSplit( right, patchlist, subdivisions-1, param );
|
|
}
|
|
|
|
} else {
|
|
// make bbox calls
|
|
patchlist.bbox();
|
|
backend.patch( patchlist.pspec[0].range[0], patchlist.pspec[0].range[1],
|
|
patchlist.pspec[1].range[0], patchlist.pspec[1].range[1] );
|
|
|
|
if( renderhints.display_method == N_OUTLINE_SUBDIV ) {
|
|
outline( source );
|
|
freejarcs( source );
|
|
} else {
|
|
setArcTypePwl();
|
|
setDegenerate();
|
|
findIrregularS( source );
|
|
monosplitInS( source, smbrkpts.start, smbrkpts.end );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* tessellation - set tessellation of interior and boundary of patch
|
|
*--------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
Subdivider::tessellation( Bin& bin, Patchlist &patchlist )
|
|
{
|
|
// tessellate unsampled trim curves
|
|
tessellate( bin, patchlist.pspec[1].sidestep[1], patchlist.pspec[0].sidestep[1],
|
|
patchlist.pspec[1].sidestep[0], patchlist.pspec[0].sidestep[0] );
|
|
|
|
// set interior sampling rates
|
|
slicer.setstriptessellation( patchlist.pspec[0].stepsize, patchlist.pspec[1].stepsize );
|
|
|
|
//added by zl: set the order which will be used in slicer.c++
|
|
slicer.set_ulinear( (patchlist.get_uorder() == 2));
|
|
slicer.set_vlinear( (patchlist.get_vorder() == 2));
|
|
|
|
// set boundary sampling rates
|
|
stepsizes[0] = patchlist.pspec[1].stepsize;
|
|
stepsizes[1] = patchlist.pspec[0].stepsize;
|
|
stepsizes[2] = patchlist.pspec[1].stepsize;
|
|
stepsizes[3] = patchlist.pspec[0].stepsize;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* monosplitInS - split a patch and a bin by an isoparametric line
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
Subdivider::monosplitInS( Bin& source, int start, int end )
|
|
{
|
|
if( source.isnonempty() ) {
|
|
if( start != end ) {
|
|
int i = start + (end - start) / 2;
|
|
Bin left, right;
|
|
split( source, left, right, 0, smbrkpts.pts[i] );
|
|
monosplitInS( left, start, i );
|
|
monosplitInS( right, i+1, end );
|
|
} else {
|
|
if( renderhints.display_method == N_OUTLINE_SUBDIV_S ) {
|
|
outline( source );
|
|
freejarcs( source );
|
|
} else {
|
|
setArcTypePwl();
|
|
setDegenerate();
|
|
findIrregularT( source );
|
|
monosplitInT( source, tmbrkpts.start, tmbrkpts.end );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* monosplitInT - split a patch and a bin by an isoparametric line
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
Subdivider::monosplitInT( Bin& source, int start, int end )
|
|
{
|
|
if( source.isnonempty() ) {
|
|
if( start != end ) {
|
|
int i = start + (end - start) / 2;
|
|
Bin left, right;
|
|
split( source, left, right, 1, tmbrkpts.pts[i] );
|
|
monosplitInT( left, start, i );
|
|
monosplitInT( right, i+1, end );
|
|
} else {
|
|
if( renderhints.display_method == N_OUTLINE_SUBDIV_ST ) {
|
|
outline( source );
|
|
freejarcs( source );
|
|
} else {
|
|
/*
|
|
printf("*******render\n");
|
|
source.show("source\n");
|
|
*/
|
|
render( source );
|
|
freejarcs( source );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* findIrregularS - determine points of non-monotonicity is s direction
|
|
*----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
Subdivider::findIrregularS( Bin& bin )
|
|
{
|
|
assert( bin.firstarc()->check() != 0 );
|
|
|
|
smbrkpts.grow( bin.numarcs() );
|
|
|
|
for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
|
|
REAL *a = jarc->prev->tail();
|
|
REAL *b = jarc->tail();
|
|
REAL *c = jarc->head();
|
|
|
|
if( b[1] == a[1] && b[1] == c[1] ) continue;
|
|
|
|
//corrected code
|
|
if((b[1]<=a[1] && b[1] <= c[1]) ||
|
|
(b[1]>=a[1] && b[1] >= c[1]))
|
|
{
|
|
//each arc (jarc, jarc->prev, jarc->next) is a
|
|
//monotone arc consisting of multiple line segements.
|
|
//it may happen that jarc->prev and jarc->next are the same,
|
|
//that is, jarc->prev and jarc form a closed loop.
|
|
//In such case, a and c will be the same.
|
|
if(a[0]==c[0] && a[1] == c[1])
|
|
{
|
|
if(jarc->pwlArc->npts >2)
|
|
{
|
|
c = jarc->pwlArc->pts[jarc->pwlArc->npts-2].param;
|
|
}
|
|
else
|
|
{
|
|
assert(jarc->prev->pwlArc->npts>2);
|
|
a = jarc->prev->pwlArc->pts[jarc->prev->pwlArc->npts-2].param;
|
|
}
|
|
|
|
}
|
|
if(area(a,b,c) < 0)
|
|
{
|
|
smbrkpts.add(b[0]);
|
|
}
|
|
|
|
}
|
|
|
|
/* old code,
|
|
if( b[1] <= a[1] && b[1] <= c[1] ) {
|
|
if( ! ccwTurn_tr( jarc->prev, jarc ) )
|
|
smbrkpts.add( b[0] );
|
|
} else if( b[1] >= a[1] && b[1] >= c[1] ) {
|
|
if( ! ccwTurn_tl( jarc->prev, jarc ) )
|
|
smbrkpts.add( b[0] );
|
|
}
|
|
*/
|
|
|
|
}
|
|
|
|
smbrkpts.filter();
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* findIrregularT - determine points of non-monotonicity in t direction
|
|
* where one arc is parallel to the s axis.
|
|
*----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
Subdivider::findIrregularT( Bin& bin )
|
|
{
|
|
assert( bin.firstarc()->check() != 0 );
|
|
|
|
tmbrkpts.grow( bin.numarcs() );
|
|
|
|
for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
|
|
REAL *a = jarc->prev->tail();
|
|
REAL *b = jarc->tail();
|
|
REAL *c = jarc->head();
|
|
|
|
if( b[0] == a[0] && b[0] == c[0] ) continue;
|
|
|
|
if( b[0] <= a[0] && b[0] <= c[0] ) {
|
|
if( a[1] != b[1] && b[1] != c[1] ) continue;
|
|
if( ! ccwTurn_sr( jarc->prev, jarc ) )
|
|
tmbrkpts.add( b[1] );
|
|
} else if ( b[0] >= a[0] && b[0] >= c[0] ) {
|
|
if( a[1] != b[1] && b[1] != c[1] ) continue;
|
|
if( ! ccwTurn_sl( jarc->prev, jarc ) )
|
|
tmbrkpts.add( b[1] );
|
|
}
|
|
}
|
|
tmbrkpts.filter( );
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* makeBorderTrim - if no user input trimming data then create
|
|
* a trimming curve around the boundaries of the Quilt. The curve consists of
|
|
* four Jordan arcs, one for each side of the Quilt, connected, of course,
|
|
* head to tail.
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
Subdivider::makeBorderTrim( const REAL *from, const REAL *to )
|
|
{
|
|
REAL smin = from[0];
|
|
REAL smax = to[0];
|
|
REAL tmin = from[1];
|
|
REAL tmax = to[1];
|
|
|
|
pjarc = 0;
|
|
|
|
Arc_ptr jarc = new(arcpool) Arc( arc_bottom, 0 );
|
|
arctessellator.bezier( jarc, smin, smax, tmin, tmin );
|
|
initialbin.addarc( jarc );
|
|
pjarc = jarc->append( pjarc );
|
|
|
|
jarc = new(arcpool) Arc( arc_right, 0 );
|
|
arctessellator.bezier( jarc, smax, smax, tmin, tmax );
|
|
initialbin.addarc( jarc );
|
|
pjarc = jarc->append( pjarc );
|
|
|
|
jarc = new(arcpool) Arc( arc_top, 0 );
|
|
arctessellator.bezier( jarc, smax, smin, tmax, tmax );
|
|
initialbin.addarc( jarc );
|
|
pjarc = jarc->append( pjarc );
|
|
|
|
jarc = new(arcpool) Arc( arc_left, 0 );
|
|
arctessellator.bezier( jarc, smin, smin, tmax, tmin );
|
|
initialbin.addarc( jarc );
|
|
jarc->append( pjarc );
|
|
|
|
assert( jarc->check() != 0 );
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* render - renders all monotone regions in a bin and frees the bin
|
|
*----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
Subdivider::render( Bin& bin )
|
|
{
|
|
bin.markall();
|
|
|
|
#ifdef N_ISOLINE_S
|
|
slicer.setisolines( ( renderhints.display_method == N_ISOLINE_S ) ? 1 : 0 );
|
|
#else
|
|
slicer.setisolines( 0 );
|
|
#endif
|
|
|
|
for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
|
|
if( jarc->ismarked() ) {
|
|
assert( jarc->check( ) != 0 );
|
|
Arc_ptr jarchead = jarc;
|
|
do {
|
|
jarc->clearmark();
|
|
jarc = jarc->next;
|
|
} while (jarc != jarchead);
|
|
slicer.slice( jarc );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* outline - render the trimmed patch by outlining the boundary
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
Subdivider::outline( Bin& bin )
|
|
{
|
|
bin.markall();
|
|
for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
|
|
if( jarc->ismarked() ) {
|
|
assert( jarc->check( ) != 0 );
|
|
Arc_ptr jarchead = jarc;
|
|
do {
|
|
slicer.outline( jarc );
|
|
jarc->clearmark();
|
|
jarc = jarc->prev;
|
|
} while (jarc != jarchead);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* freejarcs - free all arcs in a bin
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
Subdivider::freejarcs( Bin& bin )
|
|
{
|
|
bin.adopt(); /* XXX - should not be necessary */
|
|
|
|
Arc_ptr jarc;
|
|
while( (jarc = bin.removearc()) != NULL ) {
|
|
if( jarc->pwlArc ) jarc->pwlArc->deleteMe( pwlarcpool ); jarc->pwlArc = 0;
|
|
if( jarc->bezierArc) jarc->bezierArc->deleteMe( bezierarcpool ); jarc->bezierArc = 0;
|
|
jarc->deleteMe( arcpool );
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* tessellate - tessellate all Bezier arcs in a bin
|
|
* 1) only accepts linear Bezier arcs as input
|
|
* 2) the Bezier arcs are stored in the pwlArc structure
|
|
* 3) only vertical or horizontal lines work
|
|
* -- should
|
|
* 1) represent Bezier arcs in BezierArc structure
|
|
* (this requires a multitude of changes to the code)
|
|
* 2) accept high degree Bezier arcs (hard)
|
|
* 3) map the curve onto the surface to determine tessellation
|
|
* 4) work for curves of arbitrary geometry
|
|
*----------------------------------------------------------------------------
|
|
*/
|
|
|
|
|
|
void
|
|
Subdivider::tessellate( Bin& bin, REAL rrate, REAL trate, REAL lrate, REAL brate )
|
|
{
|
|
for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
|
|
if( jarc->isbezier( ) ) {
|
|
assert( jarc->pwlArc->npts == 2 );
|
|
TrimVertex *pts = jarc->pwlArc->pts;
|
|
REAL s1 = pts[0].param[0];
|
|
REAL t1 = pts[0].param[1];
|
|
REAL s2 = pts[1].param[0];
|
|
REAL t2 = pts[1].param[1];
|
|
|
|
jarc->pwlArc->deleteMe( pwlarcpool ); jarc->pwlArc = 0;
|
|
|
|
switch( jarc->getside() ) {
|
|
case arc_left:
|
|
assert( s1 == s2 );
|
|
arctessellator.pwl_left( jarc, s1, t1, t2, lrate );
|
|
break;
|
|
case arc_right:
|
|
assert( s1 == s2 );
|
|
arctessellator.pwl_right( jarc, s1, t1, t2, rrate );
|
|
break;
|
|
case arc_top:
|
|
assert( t1 == t2 );
|
|
arctessellator.pwl_top( jarc, t1, s1, s2, trate );
|
|
break;
|
|
case arc_bottom:
|
|
assert( t1 == t2 );
|
|
arctessellator.pwl_bottom( jarc, t1, s1, s2, brate );
|
|
break;
|
|
case arc_none:
|
|
(void) abort();
|
|
break;
|
|
}
|
|
assert( ! jarc->isbezier() );
|
|
assert( jarc->check() != 0 );
|
|
}
|
|
}
|
|
}
|