blob: 520bd419ea23fd0ba49cdbc551f34e9598cbfd16 [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.
*/
/*
* nurbsinterfac.c++
*
*/
#include "glimports.h"
#include "mystdio.h"
#include "nurbsconsts.h"
#include "nurbstess.h"
#include "bufpool.h"
#include "quilt.h"
#include "displaylist.h"
#include "knotvector.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)
: maplist( backend ),
backend( c, e ),
subdivider( renderhints, 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 );
_glu_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 );
_glu_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
_glu_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
_glu_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;
}