| /* |
| ** 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; |
| } |
| |