Home | History | Annotate | Line # | Download | only in internals
      1 /*
      2 ** License Applicability. Except to the extent portions of this file are
      3 ** made subject to an alternative license as permitted in the SGI Free
      4 ** Software License B, Version 1.1 (the "License"), the contents of this
      5 ** file are subject only to the provisions of the License. You may not use
      6 ** this file except in compliance with the License. You may obtain a copy
      7 ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
      8 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
      9 **
     10 ** http://oss.sgi.com/projects/FreeB
     11 **
     12 ** Note that, as provided in the License, the Software is distributed on an
     13 ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
     14 ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
     15 ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
     16 ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
     17 **
     18 ** Original Code. The Original Code is: OpenGL Sample Implementation,
     19 ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
     20 ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
     21 ** Copyright in any portions created by third parties is as indicated
     22 ** elsewhere herein. All Rights Reserved.
     23 **
     24 ** Additional Notice Provisions: The application programming interfaces
     25 ** established by SGI in conjunction with the Original Code are The
     26 ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
     27 ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
     28 ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
     29 ** Window System(R) (Version 1.3), released October 19, 1998. This software
     30 ** was created using the OpenGL(R) version 1.2.1 Sample Implementation
     31 ** published by SGI, but has not been independently verified as being
     32 ** compliant with the OpenGL(R) version 1.2.1 Specification.
     33 */
     34 
     35 /*
     36  * nurbsinterfac.c++
     37  *
     38  */
     39 
     40 #include "glimports.h"
     41 #include "mystdio.h"
     42 #include "nurbsconsts.h"
     43 #include "nurbstess.h"
     44 #include "bufpool.h"
     45 #include "quilt.h"
     46 #include "displaylist.h"
     47 #include "knotvector.h"
     48 #include "mapdesc.h"
     49 
     50 #define THREAD( work, arg, cleanup ) \
     51 	if( dl ) {\
     52 	    arg->save = 1;\
     53 	    dl->append( (PFVS)&NurbsTessellator::work, (void *) arg, (PFVS)&NurbsTessellator::cleanup );\
     54  	} else {\
     55 	    arg->save = 0;\
     56 	    work( arg );\
     57 	}
     58 
     59 #define THREAD2( work ) \
     60 	if( dl ) {\
     61 	    dl->append( (PFVS)&NurbsTessellator::work, 0, 0 );\
     62  	} else {\
     63 	    work( );\
     64 	}
     65 
     66 NurbsTessellator::NurbsTessellator( BasicCurveEvaluator &c, BasicSurfaceEvaluator& e)
     67 	: maplist( backend ),
     68 	  backend( c, e ),
     69           subdivider( renderhints, backend ),
     70 	  o_pwlcurvePool( sizeof( O_pwlcurve ), 32, "o_pwlcurvePool" ),
     71 	  o_nurbscurvePool( sizeof( O_nurbscurve ), 32, "o_nurbscurvePool"),
     72 	  o_curvePool( sizeof( O_curve ), 32,  "o_curvePool" ),
     73 	  o_trimPool( sizeof( O_trim ), 32,  "o_trimPool" ),
     74 	  o_surfacePool( sizeof( O_surface ), 1, "o_surfacePool" ),
     75 	  o_nurbssurfacePool( sizeof( O_nurbssurface ), 4, "o_nurbssurfacePool" ),
     76 	  propertyPool( sizeof( Property ), 32, "propertyPool" ),
     77           quiltPool( sizeof( Quilt  ), 32, "quiltPool" )
     78 {
     79     dl		= 0;
     80     inSurface	= 0;
     81     inCurve	= 0;
     82     inTrim	= 0;
     83     playBack	= 0;
     84     jumpbuffer  = newJumpbuffer();
     85     subdivider.setJumpbuffer( jumpbuffer );
     86 }
     87 
     88 NurbsTessellator::~NurbsTessellator( void )
     89 {
     90     if( inTrim ) {
     91 	do_nurbserror( 12 );
     92 	endtrim();
     93     }
     94 
     95     if( inSurface ) {
     96         *nextNurbssurface = 0;
     97         do_freeall();
     98     }
     99 
    100     if (jumpbuffer) {
    101         deleteJumpbuffer(jumpbuffer);
    102 	jumpbuffer= 0;
    103     }
    104 }
    105 
    106 /*-----------------------------------------------------------------------------
    107  * bgnsurface - allocate and initialize an o_surface structure
    108  *
    109  * Client: GL user
    110  *-----------------------------------------------------------------------------
    111  */
    112 void
    113 NurbsTessellator::bgnsurface( long nuid )
    114 {
    115     O_surface *o_surface = new(o_surfacePool) O_surface;
    116     o_surface->nuid = nuid;
    117     THREAD( do_bgnsurface, o_surface, do_freebgnsurface );
    118 }
    119 
    120 /*-----------------------------------------------------------------------------
    121  * bgncurve - allocate an initialize an o_curve structure
    122  *
    123  * Client: GL user
    124  *-----------------------------------------------------------------------------
    125  */
    126 void
    127 NurbsTessellator::bgncurve( long nuid )
    128 {
    129     O_curve *o_curve = new(o_curvePool) O_curve;
    130     o_curve->nuid = nuid;
    131     THREAD( do_bgncurve, o_curve, do_freebgncurve );
    132 }
    133 /*-----------------------------------------------------------------------------
    134  * endcurve -
    135  *
    136  * Client:
    137  *-----------------------------------------------------------------------------
    138  */
    139 
    140 void
    141 NurbsTessellator::endcurve( void )
    142 {
    143     THREAD2( do_endcurve );
    144 }
    145 
    146 /*-----------------------------------------------------------------------------
    147  * endsurface - user level end of surface call
    148  *
    149  * Client: GL user
    150  *-----------------------------------------------------------------------------
    151  */
    152 void
    153 NurbsTessellator::endsurface( void )
    154 {
    155     THREAD2( do_endsurface );
    156 }
    157 
    158 
    159 /*-----------------------------------------------------------------------------
    160  * bgntrim - allocate and initialize a new trim loop structure (o_trim )
    161  *
    162  * Client: GL user
    163  *-----------------------------------------------------------------------------
    164  */
    165 void
    166 NurbsTessellator::bgntrim( void )
    167 {
    168     O_trim *o_trim = new(o_trimPool) O_trim;
    169     THREAD( do_bgntrim, o_trim, do_freebgntrim );
    170 }
    171 
    172 /*-----------------------------------------------------------------------------
    173  * endtrim -
    174  *
    175  * Client: GL user
    176  *-----------------------------------------------------------------------------
    177  */
    178 void
    179 NurbsTessellator::endtrim( void )
    180 {
    181     THREAD2( do_endtrim );
    182 }
    183 
    184 
    185 /*-----------------------------------------------------------------------------
    186  * pwlcurve -
    187  *
    188  *      count        - number of points on curve
    189  *      array        - array of points on curve
    190  *      byte_stride  - distance between points in bytes
    191  *      type         - valid data flag
    192  *
    193  * Client: Gl user
    194  *-----------------------------------------------------------------------------
    195  */
    196 void
    197 NurbsTessellator::pwlcurve( long count, INREAL array[], long byte_stride, long type )
    198 {
    199     Mapdesc *mapdesc = maplist.locate( type );
    200 
    201     if( mapdesc == 0 ) {
    202 	do_nurbserror( 35 );
    203 	isDataValid = 0;
    204 	return;
    205     }
    206 
    207     if ( (type != N_P2D) && (type != N_P2DR) ) {
    208 	do_nurbserror( 22 );
    209 	isDataValid = 0;
    210 	return;
    211     }
    212     if( count < 0 ) {
    213 	do_nurbserror( 33 );
    214 	isDataValid = 0;
    215 	return;
    216     }
    217     if( byte_stride < 0 ) {
    218 	do_nurbserror( 34 );
    219 	isDataValid = 0;
    220 	return;
    221     }
    222 
    223 #ifdef NOTDEF
    224     if( mapdesc->isRational() ) {
    225 	INREAL *p = array;
    226 	INREAL x = p[0]; INREAL y = p[1]; INREAL w = p[2];
    227 	p = (INREAL *) (((char *) p) + byte_stride);
    228 	for( long i = 1; i != count; i++ ) {
    229 	    if( p[0] == x && p[1] == y && p[2] == w ) break;
    230 	    x = p[0]; y = p[1]; w = p[2];
    231 	    p = (INREAL *) (((char *) p) + byte_stride);
    232 	}
    233 	if( i != count ) {
    234 	    do_nurbserror( 37 );
    235 	    _glu_dprintf( "point %d (%f,%f)\n", i, x, y );
    236 	    isDataValid = 0;
    237 	    return;
    238 	}
    239     } else {
    240 	INREAL *p = array;
    241 	INREAL x = p[0]; INREAL y = p[1];
    242 	p = (INREAL *) (((char *) p) + byte_stride);
    243 	for( long i = 1; i != count; i++ ) {
    244 	    if( p[0] == x && p[1] == y ) break;
    245 	    x = p[0]; y = p[1];
    246 	    p = (INREAL *) (((char *) p) + byte_stride);
    247 	}
    248 	if( i != count ) {
    249 	    do_nurbserror( 37 );
    250 	    _glu_dprintf( "point %d (%f,%f)\n", i, x, y );
    251 	    isDataValid = 0;
    252 	    return;
    253 	}
    254     }
    255 #endif
    256 
    257     O_pwlcurve	*o_pwlcurve = new(o_pwlcurvePool) O_pwlcurve( type, count, array, byte_stride, extTrimVertexPool.get((int)count) );
    258     THREAD( do_pwlcurve, o_pwlcurve, do_freepwlcurve );
    259 }
    260 
    261 
    262 /*-----------------------------------------------------------------------------
    263  * nurbscurve -
    264  *
    265  * Client: GL user
    266  *-----------------------------------------------------------------------------
    267  */
    268 void
    269 NurbsTessellator::nurbscurve(
    270     long nknots, 		/* number of p knots */
    271     INREAL knot[], 		/* nondecreasing knot values in p */
    272     long byte_stride,		/* distance in bytes between control points */
    273     INREAL ctlarray[], 		/* pointer to first control point */
    274     long order,			/* order of spline */
    275     long type )			/* description of range space */
    276 {
    277 
    278     Mapdesc *mapdesc = maplist.locate( type );
    279 
    280     if( mapdesc == 0 ) {
    281 	do_nurbserror( 35 );
    282 	isDataValid = 0;
    283 	return;
    284     }
    285 
    286     if( ctlarray == 0 ) {
    287 	do_nurbserror( 36 );
    288 	isDataValid = 0;
    289 	return;
    290     }
    291 
    292     if( byte_stride < 0 ) {
    293 	do_nurbserror( 34 );
    294 	isDataValid = 0;
    295 	return;
    296     }
    297 
    298     Knotvector knots;
    299 
    300     knots.init( nknots, byte_stride, order, knot );
    301     if( do_check_knots( &knots, "curve" ) ) return;
    302 
    303     O_nurbscurve *o_nurbscurve = new(o_nurbscurvePool) O_nurbscurve(type);
    304     o_nurbscurve->bezier_curves = new(quiltPool) Quilt(mapdesc);
    305     o_nurbscurve->bezier_curves->toBezier( knots,ctlarray, mapdesc->getNcoords() );
    306 
    307     THREAD( do_nurbscurve, o_nurbscurve, do_freenurbscurve );
    308 }
    309 
    310 
    311 /*-----------------------------------------------------------------------------
    312  * nurbssurface -
    313  *
    314  * Client: User routine
    315  *-----------------------------------------------------------------------------
    316  */
    317 void
    318 NurbsTessellator::nurbssurface(
    319     long sknot_count,		/* number of s knots */
    320     INREAL sknot[],		/* nondecreasing knot values in s */
    321     long tknot_count, 		/* number of t knots */
    322     INREAL tknot[],		/* nondecreasing knot values in t */
    323     long s_byte_stride,		/* s step size in memory bytes */
    324     long t_byte_stride,		/* t step size in memory bytes */
    325     INREAL ctlarray[],		/* pointer to first control point */
    326     long sorder,		/* order of the spline in s parameter */
    327     long torder,		/* order of the spline in t parameter */
    328     long type)			/* description of range space */
    329 {
    330     Mapdesc *mapdesc = maplist.locate( type );
    331 
    332     if( mapdesc == 0 ) {
    333 	do_nurbserror( 35 );
    334 	isDataValid = 0;
    335 	return;
    336     }
    337 
    338     if( s_byte_stride < 0 ) {
    339 	do_nurbserror( 34 );
    340 	isDataValid = 0;
    341 	return;
    342     }
    343 
    344     if( t_byte_stride < 0 ) {
    345 	do_nurbserror( 34 );
    346 	isDataValid = 0;
    347 	return;
    348     }
    349 
    350     Knotvector sknotvector, tknotvector;
    351 
    352     sknotvector.init( sknot_count, s_byte_stride, sorder, sknot );
    353     if( do_check_knots( &sknotvector, "surface" ) ) return;
    354 
    355     tknotvector.init( tknot_count, t_byte_stride, torder, tknot );
    356     if( do_check_knots( &tknotvector, "surface" ) ) return;
    357 
    358     O_nurbssurface *o_nurbssurface = new(o_nurbssurfacePool) O_nurbssurface(type);
    359     o_nurbssurface->bezier_patches = new(quiltPool) Quilt(mapdesc);
    360 
    361     o_nurbssurface->bezier_patches->toBezier( sknotvector, tknotvector,
    362 	ctlarray, mapdesc->getNcoords() );
    363     THREAD( do_nurbssurface, o_nurbssurface, do_freenurbssurface );
    364 }
    365 
    366 
    367 /*-----------------------------------------------------------------------------
    368  * setnurbsproperty -
    369  *
    370  *-----------------------------------------------------------------------------
    371  */
    372 void
    373 NurbsTessellator::setnurbsproperty( long tag, INREAL value )
    374 {
    375     if( ! renderhints.isProperty( tag ) ) {
    376 	do_nurbserror( 26 );
    377     } else {
    378 	Property *prop = new(propertyPool) Property( tag, value );
    379 	THREAD( do_setnurbsproperty, prop, do_freenurbsproperty );
    380     }
    381 }
    382 
    383 /*-----------------------------------------------------------------------------
    384  * setnurbsproperty -
    385  *
    386  *-----------------------------------------------------------------------------
    387  */
    388 void
    389 NurbsTessellator::setnurbsproperty( long type, long tag, INREAL value )
    390 {
    391     Mapdesc *mapdesc = maplist.locate( type );
    392 
    393     if( mapdesc == 0 ) {
    394 	do_nurbserror( 35 );
    395 	return;
    396     }
    397 
    398     if( ! mapdesc->isProperty( tag ) ) {
    399 	do_nurbserror( 26 );
    400 	return;
    401     }
    402 
    403     Property *prop = new(propertyPool) Property( type, tag, value );
    404     THREAD( do_setnurbsproperty2, prop, do_freenurbsproperty );
    405 }
    406 
    407 
    408 /*-----------------------------------------------------------------------------
    409  * getnurbsproperty -
    410  *
    411  *-----------------------------------------------------------------------------
    412  */
    413 
    414 void
    415 NurbsTessellator::getnurbsproperty( long tag, INREAL *value )
    416 {
    417     if( renderhints.isProperty( tag ) ) {
    418 	*value = renderhints.getProperty( tag );
    419     } else {
    420 	do_nurbserror( 26 );
    421     }
    422 }
    423 
    424 /*-----------------------------------------------------------------------------
    425  * getnurbsproperty -
    426  *
    427  *-----------------------------------------------------------------------------
    428  */
    429 
    430 void
    431 NurbsTessellator::getnurbsproperty( long type, long tag, INREAL *value )
    432 {
    433     Mapdesc *mapdesc = maplist.locate( type );
    434 
    435     if( mapdesc == 0 )
    436 	do_nurbserror( 35 );
    437 
    438     if( mapdesc->isProperty( tag  ) ) {
    439 	*value = mapdesc->getProperty( tag );
    440     } else {
    441 	do_nurbserror( 26 );
    442     }
    443 }
    444 
    445 /*--------------------------------------------------------------------------
    446  * setnurbsproperty - accept a user supplied matrix as culling or sampling mat
    447  *--------------------------------------------------------------------------
    448  */
    449 
    450 void
    451 NurbsTessellator::setnurbsproperty( long type, long purpose, INREAL *mat )
    452 {
    453     // XXX - cannot be put in display list
    454     Mapdesc *mapdesc = maplist.locate( type );
    455 
    456     if( mapdesc == 0 ) {
    457 	do_nurbserror( 35 );
    458 	isDataValid = 0;
    459     } else if( purpose == N_BBOXSIZE ) {
    460 	mapdesc->setBboxsize( mat );
    461     } else {
    462 #ifndef NDEBUG
    463         _glu_dprintf( "ERRORRORRORR!!!\n");
    464 #endif
    465     }
    466 }
    467 
    468 /*--------------------------------------------------------------------------
    469  * setnurbsproperty - accept a user supplied matrix as culling or sampling mat
    470  *--------------------------------------------------------------------------
    471  */
    472 
    473 void
    474 NurbsTessellator::setnurbsproperty( long type, long purpose, INREAL *mat,
    475     long rstride, long cstride )
    476 {
    477     // XXX - cannot be put in display list
    478     Mapdesc *mapdesc = maplist.locate( type );
    479 
    480     if( mapdesc == 0 ) {
    481 	do_nurbserror( 35 );
    482 	isDataValid = 0;
    483     } else if( purpose == N_CULLINGMATRIX ) {
    484 	mapdesc->setCmat( mat, rstride, cstride );
    485     } else if( purpose == N_SAMPLINGMATRIX ) {
    486 	mapdesc->setSmat( mat, rstride, cstride );
    487     } else if( purpose == N_BBOXMATRIX ) {
    488 	mapdesc->setBmat( mat, rstride, cstride );
    489     } else {
    490 #ifndef NDEBUG
    491         _glu_dprintf( "ERRORRORRORR!!!\n");
    492 #endif
    493     }
    494 }
    495 
    496 void
    497 NurbsTessellator::redefineMaps( void )
    498 {
    499     maplist.initialize();
    500 }
    501 
    502 void
    503 NurbsTessellator::defineMap( long type, long rational, long ncoords )
    504 {
    505     maplist.define( type, (int) rational, (int) ncoords );
    506 }
    507 
    508 void
    509 NurbsTessellator::discardRecording( void *_dl )
    510 {
    511     delete (DisplayList *) _dl;
    512 }
    513 
    514 void *
    515 NurbsTessellator::beginRecording( void )
    516 {
    517     dl = new DisplayList( this );
    518     return (void *) dl;
    519 }
    520 
    521 void
    522 NurbsTessellator::endRecording( void )
    523 {
    524     dl->endList();
    525     dl = 0;
    526 }
    527 
    528 void
    529 NurbsTessellator::playRecording( void *_dl )
    530 {
    531     playBack = 1;
    532     bgnrender();
    533     ((DisplayList *)_dl)->play();
    534     endrender();
    535     playBack = 0;
    536 }
    537 
    538