blob: ca5bf36b36335511965d2202328a02b8cd83bd7c [file] [log] [blame]
/*
** 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.
*/
/*
* coveandtiler.c++
*
*/
#include "glimports.h"
#include "myassert.h"
#include "mystdio.h"
#include "coveandtiler.h"
#include "gridvertex.h"
#include "gridtrimvertex.h"
#include "uarray.h"
#include "backend.h"
const int CoveAndTiler::MAXSTRIPSIZE = 1000;
CoveAndTiler::CoveAndTiler( Backend& b )
: backend( b )
{ }
CoveAndTiler::~CoveAndTiler( void )
{ }
inline void
CoveAndTiler::output( GridVertex &gv )
{
backend.tmeshvert( &gv );
}
inline void
CoveAndTiler::output( TrimVertex *tv )
{
backend.tmeshvert( tv );
}
inline void
CoveAndTiler::output( GridTrimVertex& g )
{
backend.tmeshvert( &g );
}
void
CoveAndTiler::coveAndTile( void )
{
long ustart = (top.ustart >= bot.ustart) ? top.ustart : bot.ustart;
long uend = (top.uend <= bot.uend) ? top.uend : bot.uend;
if( ustart <= uend ) {
tile( bot.vindex, ustart, uend );
if( top.ustart >= bot.ustart )
coveUpperLeft();
else
coveLowerLeft();
if( top.uend <= bot.uend )
coveUpperRight();
else
coveLowerRight();
} else {
TrimVertex blv, tlv, *bl, *tl;
GridTrimVertex bllv, tllv;
TrimVertex *lf = left.first();
TrimVertex *ll = left.last();
if( lf->param[0] >= ll->param[0] ) {
blv.param[0] = lf->param[0];
blv.param[1] = ll->param[1];
blv.nuid = 0; // XXX
assert( blv.param[1] == bot.vval );
bl = &blv;
tl = lf;
tllv.set( lf );
if( ll->param[0] > uarray.uarray[top.ustart-1] ) {
bllv.set( ll );
assert( ll->param[0] <= uarray.uarray[bot.ustart] );
} else {
bllv.set( top.ustart-1, bot.vindex );
}
coveUpperLeftNoGrid( bl );
} else {
tlv.param[0] = ll->param[0];
tlv.param[1] = lf->param[1];
tlv.nuid = 0; // XXX
assert( tlv.param[1] == top.vval );
tl = &tlv;
bl = ll;
bllv.set( ll );
if( lf->param[0] > uarray.uarray[bot.ustart-1] ) {
assert( lf->param[0] <= uarray.uarray[bot.ustart] );
tllv.set( lf );
} else {
tllv.set( bot.ustart-1, top.vindex );
}
coveLowerLeftNoGrid( tl );
}
TrimVertex brv, trv, *br, *tr;
GridTrimVertex brrv, trrv;
TrimVertex *rf = right.first();
TrimVertex *rl = right.last();
if( rf->param[0] <= rl->param[0] ) {
brv.param[0] = rf->param[0];
brv.param[1] = rl->param[1];
brv.nuid = 0; // XXX
assert( brv.param[1] == bot.vval );
br = &brv;
tr = rf;
trrv.set( rf );
if( rl->param[0] < uarray.uarray[top.uend+1] ) {
assert( rl->param[0] >= uarray.uarray[top.uend] );
brrv.set( rl );
} else {
brrv.set( top.uend+1, bot.vindex );
}
coveUpperRightNoGrid( br );
} else {
trv.param[0] = rl->param[0];
trv.param[1] = rf->param[1];
trv.nuid = 0; // XXX
assert( trv.param[1] == top.vval );
tr = &trv;
br = rl;
brrv.set( rl );
if( rf->param[0] < uarray.uarray[bot.uend+1] ) {
assert( rf->param[0] >= uarray.uarray[bot.uend] );
trrv.set( rf );
} else {
trrv.set( bot.uend+1, top.vindex );
}
coveLowerRightNoGrid( tr );
}
backend.bgntmesh( "doit" );
output(trrv);
output(tllv);
output( tr );
output( tl );
output( br );
output( bl );
output(brrv);
output(bllv);
backend.endtmesh();
}
}
void
CoveAndTiler::tile( long vindex, long ustart, long uend )
{
long numsteps = uend - ustart;
if( numsteps == 0 ) return;
if( numsteps > MAXSTRIPSIZE ) {
long umid = ustart + (uend - ustart) / 2;
tile( vindex, ustart, umid );
tile( vindex, umid, uend );
} else {
backend.surfmesh( ustart, vindex-1, numsteps, 1 );
}
}
void
CoveAndTiler::coveUpperRight( void )
{
GridVertex tgv( top.uend, top.vindex );
GridVertex gv( top.uend, bot.vindex );
right.first();
backend.bgntmesh( "coveUpperRight" );
output( right.next() );
output( tgv );
backend.swaptmesh();
output( gv );
coveUR();
backend.endtmesh();
}
void
CoveAndTiler::coveUpperRightNoGrid( TrimVertex* br )
{
backend.bgntmesh( "coveUpperRight" );
output( right.first() );
output( right.next() );
backend.swaptmesh();
output( br );
coveUR();
backend.endtmesh();
}
void
CoveAndTiler::coveUR( )
{
GridVertex gv( top.uend, bot.vindex );
TrimVertex *vert = right.next();
if( vert == NULL ) return;
assert( vert->param[0] >= uarray.uarray[gv.gparam[0]] );
if( gv.nextu() >= bot.uend ) {
for( ; vert; vert = right.next() ) {
output( vert );
backend.swaptmesh();
}
} else while( 1 ) {
if( vert->param[0] < uarray.uarray[gv.gparam[0]] ) {
output( vert );
backend.swaptmesh();
vert = right.next();
if( vert == NULL ) break;
} else {
backend.swaptmesh();
output( gv );
if( gv.nextu() == bot.uend ) {
for( ; vert; vert = right.next() ) {
output( vert );
backend.swaptmesh();
}
break;
}
}
}
}
void
CoveAndTiler::coveUpperLeft( void )
{
GridVertex tgv( top.ustart, top.vindex );
GridVertex gv( top.ustart, bot.vindex );
left.first();
backend.bgntmesh( "coveUpperLeft" );
output( tgv );
output( left.next() );
output( gv );
backend.swaptmesh();
coveUL();
backend.endtmesh();
}
void
CoveAndTiler::coveUpperLeftNoGrid( TrimVertex* bl )
{
backend.bgntmesh( "coveUpperLeftNoGrid" );
output( left.first() );
output( left.next() );
output( bl );
backend.swaptmesh();
coveUL();
backend.endtmesh();
}
void
CoveAndTiler::coveUL()
{
GridVertex gv( top.ustart, bot.vindex );
TrimVertex *vert = left.next();
if( vert == NULL ) return;
assert( vert->param[0] <= uarray.uarray[gv.gparam[0]] );
if( gv.prevu() <= bot.ustart ) {
for( ; vert; vert = left.next() ) {
backend.swaptmesh();
output( vert );
}
} else while( 1 ) {
if( vert->param[0] > uarray.uarray[gv.gparam[0]] ) {
backend.swaptmesh();
output( vert );
vert = left.next();
if( vert == NULL ) break;
} else {
output( gv );
backend.swaptmesh();
if( gv.prevu() == bot.ustart ) {
for( ; vert; vert = left.next() ) {
backend.swaptmesh();
output( vert );
}
break;
}
}
}
}
void
CoveAndTiler::coveLowerLeft( void )
{
GridVertex bgv( bot.ustart, bot.vindex );
GridVertex gv( bot.ustart, top.vindex );
left.last();
backend.bgntmesh( "coveLowerLeft" );
output( left.prev() );
output( bgv );
backend.swaptmesh();
output( gv );
coveLL();
backend.endtmesh();
}
void
CoveAndTiler::coveLowerLeftNoGrid( TrimVertex* tl )
{
backend.bgntmesh( "coveLowerLeft" );
output( left.last() );
output( left.prev() );
backend.swaptmesh();
output( tl );
coveLL( );
backend.endtmesh();
}
void
CoveAndTiler::coveLL()
{
GridVertex gv( bot.ustart, top.vindex );
TrimVertex *vert = left.prev();
if( vert == NULL ) return;
assert( vert->param[0] <= uarray.uarray[gv.gparam[0]] );
if( gv.prevu() <= top.ustart ) {
for( ; vert; vert = left.prev() ) {
output( vert );
backend.swaptmesh();
}
} else while( 1 ) {
if( vert->param[0] > uarray.uarray[gv.gparam[0]] ){
output( vert );
backend.swaptmesh();
vert = left.prev();
if( vert == NULL ) break;
} else {
backend.swaptmesh();
output( gv );
if( gv.prevu() == top.ustart ) {
for( ; vert; vert = left.prev() ) {
output( vert );
backend.swaptmesh();
}
break;
}
}
}
}
void
CoveAndTiler::coveLowerRight( void )
{
GridVertex bgv( bot.uend, bot.vindex );
GridVertex gv( bot.uend, top.vindex );
right.last();
backend.bgntmesh( "coveLowerRight" );
output( bgv );
output( right.prev() );
output( gv );
backend.swaptmesh();
coveLR();
backend.endtmesh( );
}
void
CoveAndTiler::coveLowerRightNoGrid( TrimVertex* tr )
{
backend.bgntmesh( "coveLowerRIght" );
output( right.last() );
output( right.prev() );
output( tr );
backend.swaptmesh();
coveLR();
backend.endtmesh();
}
void
CoveAndTiler::coveLR( )
{
GridVertex gv( bot.uend, top.vindex );
TrimVertex *vert = right.prev();
if( vert == NULL ) return;
assert( vert->param[0] >= uarray.uarray[gv.gparam[0]] );
if( gv.nextu() >= top.uend ) {
for( ; vert; vert = right.prev() ) {
backend.swaptmesh();
output( vert );
}
} else while( 1 ) {
if( vert->param[0] < uarray.uarray[gv.gparam[0]] ) {
backend.swaptmesh();
output( vert );
vert = right.prev();
if( vert == NULL ) break;
} else {
output( gv );
backend.swaptmesh();
if( gv.nextu() == top.uend ) {
for( ; vert; vert = right.prev() ) {
backend.swaptmesh();
output( vert );
}
break;
}
}
}
}