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.
515 lines
14 KiB
515 lines
14 KiB
/**************************************************************************
|
|
* *
|
|
* Copyright (C) 1992, Silicon Graphics, Inc. *
|
|
* *
|
|
* These coded instructions, statements, and computer programs contain *
|
|
* unpublished proprietary information of Silicon Graphics, Inc., and *
|
|
* are protected by Federal copyright law. They may not be disclosed *
|
|
* to third parties or copied or duplicated in any form, in whole or *
|
|
* in part, without the prior written consent of Silicon Graphics, Inc. *
|
|
* *
|
|
**************************************************************************/
|
|
|
|
/*
|
|
* nurbsinterfac.c++ - $Revision: 1.2 $
|
|
* Derrick Burns - 1991
|
|
*/
|
|
|
|
#include "glimport.h"
|
|
#include "mystdio.h"
|
|
#include "nurbscon.h"
|
|
#include "nurbstes.h"
|
|
#include "bufpool.h"
|
|
#include "quilt.h"
|
|
#include "displayl.h"
|
|
#include "knotvect.h"
|
|
#include "mapdesc.h"
|
|
|
|
#define THREAD( work, arg, cleanup ) \
|
|
if( dl ) {\
|
|
arg->save = 1;\
|
|
dl->append( (PFVS)&NurbsTessellator::work, (void *) arg, (PFVS)&NurbsTessellator::cleanup );\
|
|
} else {\
|
|
arg->save = 0;\
|
|
work( arg );\
|
|
}
|
|
|
|
#define THREAD2( work ) \
|
|
if( dl ) {\
|
|
dl->append( (PFVS)&NurbsTessellator::work, 0, 0 );\
|
|
} else {\
|
|
work( );\
|
|
}
|
|
|
|
NurbsTessellator::NurbsTessellator( BasicCurveEvaluator &c, BasicSurfaceEvaluator& e)
|
|
: subdivider( renderhints, backend ),
|
|
backend( c, e ),
|
|
maplist( backend ),
|
|
o_pwlcurvePool( sizeof( O_pwlcurve ), 32, "o_pwlcurvePool" ),
|
|
o_nurbscurvePool( sizeof( O_nurbscurve ), 32, "o_nurbscurvePool"),
|
|
o_curvePool( sizeof( O_curve ), 32, "o_curvePool" ),
|
|
o_trimPool( sizeof( O_trim ), 32, "o_trimPool" ),
|
|
o_surfacePool( sizeof( O_surface ), 1, "o_surfacePool" ),
|
|
o_nurbssurfacePool( sizeof( O_nurbssurface ), 4, "o_nurbssurfacePool" ),
|
|
propertyPool( sizeof( Property ), 32, "propertyPool" ),
|
|
quiltPool( sizeof( Quilt ), 32, "quiltPool" )
|
|
{
|
|
dl = 0;
|
|
inSurface = 0;
|
|
inCurve = 0;
|
|
inTrim = 0;
|
|
playBack = 0;
|
|
jumpbuffer = newJumpbuffer();
|
|
subdivider.setJumpbuffer( jumpbuffer );
|
|
}
|
|
|
|
NurbsTessellator::~NurbsTessellator( void )
|
|
{
|
|
if( inTrim ) {
|
|
do_nurbserror( 12 );
|
|
endtrim();
|
|
}
|
|
|
|
if( inSurface ) {
|
|
*nextNurbssurface = 0;
|
|
do_freeall();
|
|
}
|
|
|
|
if (jumpbuffer) {
|
|
deleteJumpbuffer(jumpbuffer);
|
|
jumpbuffer= 0;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* bgnsurface - allocate and initialize an o_surface structure
|
|
*
|
|
* Client: GL user
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
NurbsTessellator::bgnsurface( long nuid )
|
|
{
|
|
O_surface *o_surface = new(o_surfacePool) O_surface;
|
|
o_surface->nuid = nuid;
|
|
THREAD( do_bgnsurface, o_surface, do_freebgnsurface );
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* bgncurve - allocate an initialize an o_curve structure
|
|
*
|
|
* Client: GL user
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
NurbsTessellator::bgncurve( long nuid )
|
|
{
|
|
O_curve *o_curve = new(o_curvePool) O_curve;
|
|
o_curve->nuid = nuid;
|
|
THREAD( do_bgncurve, o_curve, do_freebgncurve );
|
|
}
|
|
/*-----------------------------------------------------------------------------
|
|
* endcurve -
|
|
*
|
|
* Client:
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
NurbsTessellator::endcurve( void )
|
|
{
|
|
THREAD2( do_endcurve );
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* endsurface - user level end of surface call
|
|
*
|
|
* Client: GL user
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
NurbsTessellator::endsurface( void )
|
|
{
|
|
THREAD2( do_endsurface );
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* bgntrim - allocate and initialize a new trim loop structure (o_trim )
|
|
*
|
|
* Client: GL user
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
NurbsTessellator::bgntrim( void )
|
|
{
|
|
O_trim *o_trim = new(o_trimPool) O_trim;
|
|
THREAD( do_bgntrim, o_trim, do_freebgntrim );
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* endtrim -
|
|
*
|
|
* Client: GL user
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
NurbsTessellator::endtrim( void )
|
|
{
|
|
THREAD2( do_endtrim );
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* pwlcurve -
|
|
*
|
|
* count - number of points on curve
|
|
* array - array of points on curve
|
|
* byte_stride - distance between points in bytes
|
|
* type - valid data flag
|
|
*
|
|
* Client: Gl user
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
NurbsTessellator::pwlcurve( long count, INREAL array[], long byte_stride, long type )
|
|
{
|
|
Mapdesc *mapdesc = maplist.locate( type );
|
|
|
|
if( mapdesc == 0 ) {
|
|
do_nurbserror( 35 );
|
|
isDataValid = 0;
|
|
return;
|
|
}
|
|
|
|
if ( (type != N_P2D) && (type != N_P2DR) ) {
|
|
do_nurbserror( 22 );
|
|
isDataValid = 0;
|
|
return;
|
|
}
|
|
if( count < 0 ) {
|
|
do_nurbserror( 33 );
|
|
isDataValid = 0;
|
|
return;
|
|
}
|
|
if( byte_stride < 0 ) {
|
|
do_nurbserror( 34 );
|
|
isDataValid = 0;
|
|
return;
|
|
}
|
|
|
|
#ifdef NOTDEF
|
|
if( mapdesc->isRational() ) {
|
|
INREAL *p = array;
|
|
INREAL x = p[0]; INREAL y = p[1]; INREAL w = p[2];
|
|
p = (INREAL *) (((char *) p) + byte_stride);
|
|
for( long i = 1; i != count; i++ ) {
|
|
if( p[0] == x && p[1] == y && p[2] == w ) break;
|
|
x = p[0]; y = p[1]; w = p[2];
|
|
p = (INREAL *) (((char *) p) + byte_stride);
|
|
}
|
|
if( i != count ) {
|
|
do_nurbserror( 37 );
|
|
dprintf( "point %d (%f,%f)\n", i, x, y );
|
|
isDataValid = 0;
|
|
return;
|
|
}
|
|
} else {
|
|
INREAL *p = array;
|
|
INREAL x = p[0]; INREAL y = p[1];
|
|
p = (INREAL *) (((char *) p) + byte_stride);
|
|
for( long i = 1; i != count; i++ ) {
|
|
if( p[0] == x && p[1] == y ) break;
|
|
x = p[0]; y = p[1];
|
|
p = (INREAL *) (((char *) p) + byte_stride);
|
|
}
|
|
if( i != count ) {
|
|
do_nurbserror( 37 );
|
|
dprintf( "point %d (%f,%f)\n", i, x, y );
|
|
isDataValid = 0;
|
|
return;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
O_pwlcurve *o_pwlcurve = new(o_pwlcurvePool) O_pwlcurve( type, count, array, byte_stride, extTrimVertexPool.get((int)count) );
|
|
THREAD( do_pwlcurve, o_pwlcurve, do_freepwlcurve );
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* nurbscurve -
|
|
*
|
|
* Client: GL user
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
NurbsTessellator::nurbscurve(
|
|
long nknots, /* number of p knots */
|
|
INREAL knot[], /* nondecreasing knot values in p */
|
|
long byte_stride, /* distance in bytes between control points */
|
|
INREAL ctlarray[], /* pointer to first control point */
|
|
long order, /* order of spline */
|
|
long type ) /* description of range space */
|
|
{
|
|
|
|
Mapdesc *mapdesc = maplist.locate( type );
|
|
|
|
if( mapdesc == 0 ) {
|
|
do_nurbserror( 35 );
|
|
isDataValid = 0;
|
|
return;
|
|
}
|
|
|
|
if( ctlarray == 0 ) {
|
|
do_nurbserror( 36 );
|
|
isDataValid = 0;
|
|
return;
|
|
}
|
|
|
|
if( byte_stride < 0 ) {
|
|
do_nurbserror( 34 );
|
|
isDataValid = 0;
|
|
return;
|
|
}
|
|
|
|
Knotvector knots;
|
|
|
|
knots.init( nknots, byte_stride, order, knot );
|
|
if( do_check_knots( &knots, "curve" ) ) return;
|
|
|
|
O_nurbscurve *o_nurbscurve = new(o_nurbscurvePool) O_nurbscurve(type);
|
|
o_nurbscurve->bezier_curves = new(quiltPool) Quilt(mapdesc);
|
|
o_nurbscurve->bezier_curves->toBezier( knots,ctlarray, mapdesc->getNcoords() );
|
|
|
|
THREAD( do_nurbscurve, o_nurbscurve, do_freenurbscurve );
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* nurbssurface -
|
|
*
|
|
* Client: User routine
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
NurbsTessellator::nurbssurface(
|
|
long sknot_count, /* number of s knots */
|
|
INREAL sknot[], /* nondecreasing knot values in s */
|
|
long tknot_count, /* number of t knots */
|
|
INREAL tknot[], /* nondecreasing knot values in t */
|
|
long s_byte_stride, /* s step size in memory bytes */
|
|
long t_byte_stride, /* t step size in memory bytes */
|
|
INREAL ctlarray[], /* pointer to first control point */
|
|
long sorder, /* order of the spline in s parameter */
|
|
long torder, /* order of the spline in t parameter */
|
|
long type) /* description of range space */
|
|
{
|
|
Mapdesc *mapdesc = maplist.locate( type );
|
|
|
|
if( mapdesc == 0 ) {
|
|
do_nurbserror( 35 );
|
|
isDataValid = 0;
|
|
return;
|
|
}
|
|
|
|
if( s_byte_stride < 0 ) {
|
|
do_nurbserror( 34 );
|
|
isDataValid = 0;
|
|
return;
|
|
}
|
|
|
|
if( t_byte_stride < 0 ) {
|
|
do_nurbserror( 34 );
|
|
isDataValid = 0;
|
|
return;
|
|
}
|
|
|
|
Knotvector sknotvector, tknotvector;
|
|
|
|
sknotvector.init( sknot_count, s_byte_stride, sorder, sknot );
|
|
if( do_check_knots( &sknotvector, "surface" ) ) return;
|
|
|
|
tknotvector.init( tknot_count, t_byte_stride, torder, tknot );
|
|
if( do_check_knots( &tknotvector, "surface" ) ) return;
|
|
|
|
O_nurbssurface *o_nurbssurface = new(o_nurbssurfacePool) O_nurbssurface(type);
|
|
o_nurbssurface->bezier_patches = new(quiltPool) Quilt(mapdesc);
|
|
|
|
o_nurbssurface->bezier_patches->toBezier( sknotvector, tknotvector,
|
|
ctlarray, mapdesc->getNcoords() );
|
|
THREAD( do_nurbssurface, o_nurbssurface, do_freenurbssurface );
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* setnurbsproperty -
|
|
*
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
NurbsTessellator::setnurbsproperty( long tag, INREAL value )
|
|
{
|
|
if( ! renderhints.isProperty( tag ) ) {
|
|
do_nurbserror( 26 );
|
|
} else {
|
|
Property *prop = new(propertyPool) Property( tag, value );
|
|
THREAD( do_setnurbsproperty, prop, do_freenurbsproperty );
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* setnurbsproperty -
|
|
*
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
NurbsTessellator::setnurbsproperty( long type, long tag, INREAL value )
|
|
{
|
|
Mapdesc *mapdesc = maplist.locate( type );
|
|
|
|
if( mapdesc == 0 ) {
|
|
do_nurbserror( 35 );
|
|
return;
|
|
}
|
|
|
|
if( ! mapdesc->isProperty( tag ) ) {
|
|
do_nurbserror( 26 );
|
|
return;
|
|
}
|
|
|
|
Property *prop = new(propertyPool) Property( type, tag, value );
|
|
THREAD( do_setnurbsproperty2, prop, do_freenurbsproperty );
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* getnurbsproperty -
|
|
*
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
NurbsTessellator::getnurbsproperty( long tag, INREAL *value )
|
|
{
|
|
if( renderhints.isProperty( tag ) ) {
|
|
*value = renderhints.getProperty( tag );
|
|
} else {
|
|
do_nurbserror( 26 );
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* getnurbsproperty -
|
|
*
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
NurbsTessellator::getnurbsproperty( long type, long tag, INREAL *value )
|
|
{
|
|
Mapdesc *mapdesc = maplist.locate( type );
|
|
|
|
if( mapdesc == 0 )
|
|
do_nurbserror( 35 );
|
|
|
|
if( mapdesc->isProperty( tag ) ) {
|
|
*value = mapdesc->getProperty( tag );
|
|
} else {
|
|
do_nurbserror( 26 );
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* setnurbsproperty - accept a user supplied matrix as culling or sampling mat
|
|
*--------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
NurbsTessellator::setnurbsproperty( long type, long purpose, INREAL *mat )
|
|
{
|
|
// XXX - cannot be put in display list
|
|
Mapdesc *mapdesc = maplist.locate( type );
|
|
|
|
if( mapdesc == 0 ) {
|
|
do_nurbserror( 35 );
|
|
isDataValid = 0;
|
|
} else if( purpose == N_BBOXSIZE ) {
|
|
mapdesc->setBboxsize( mat );
|
|
} else {
|
|
#ifndef NDEBUG
|
|
dprintf( "ERRORRORRORR!!!\n");
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* setnurbsproperty - accept a user supplied matrix as culling or sampling mat
|
|
*--------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
NurbsTessellator::setnurbsproperty( long type, long purpose, INREAL *mat,
|
|
long rstride, long cstride )
|
|
{
|
|
// XXX - cannot be put in display list
|
|
Mapdesc *mapdesc = maplist.locate( type );
|
|
|
|
if( mapdesc == 0 ) {
|
|
do_nurbserror( 35 );
|
|
isDataValid = 0;
|
|
} else if( purpose == N_CULLINGMATRIX ) {
|
|
mapdesc->setCmat( mat, rstride, cstride );
|
|
} else if( purpose == N_SAMPLINGMATRIX ) {
|
|
mapdesc->setSmat( mat, rstride, cstride );
|
|
} else if( purpose == N_BBOXMATRIX ) {
|
|
mapdesc->setBmat( mat, rstride, cstride );
|
|
} else {
|
|
#ifndef NDEBUG
|
|
dprintf( "ERRORRORRORR!!!\n");
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void
|
|
NurbsTessellator::redefineMaps( void )
|
|
{
|
|
maplist.initialize();
|
|
}
|
|
|
|
void
|
|
NurbsTessellator::defineMap( long type, long rational, long ncoords )
|
|
{
|
|
maplist.define( type, (int) rational, (int) ncoords );
|
|
}
|
|
|
|
void
|
|
NurbsTessellator::discardRecording( void *_dl )
|
|
{
|
|
delete (DisplayList *) _dl;
|
|
}
|
|
|
|
void *
|
|
NurbsTessellator::beginRecording( void )
|
|
{
|
|
dl = new DisplayList( this );
|
|
return (void *) dl;
|
|
}
|
|
|
|
void
|
|
NurbsTessellator::endRecording( void )
|
|
{
|
|
dl->endList();
|
|
dl = 0;
|
|
}
|
|
|
|
void
|
|
NurbsTessellator::playRecording( void *_dl )
|
|
{
|
|
playBack = 1;
|
|
bgnrender();
|
|
((DisplayList *)_dl)->play();
|
|
endrender();
|
|
playBack = 0;
|
|
}
|
|
|