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 66NurbsTessellator::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 88NurbsTessellator::~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 */ 112void 113NurbsTessellator::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 */ 126void 127NurbsTessellator::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 140void 141NurbsTessellator::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 */ 152void 153NurbsTessellator::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 */ 165void 166NurbsTessellator::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 */ 178void 179NurbsTessellator::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 */ 196void 197NurbsTessellator::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 */ 268void 269NurbsTessellator::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 */ 317void 318NurbsTessellator::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 */ 372void 373NurbsTessellator::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 */ 388void 389NurbsTessellator::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 414void 415NurbsTessellator::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 430void 431NurbsTessellator::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 450void 451NurbsTessellator::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 473void 474NurbsTessellator::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 496void 497NurbsTessellator::redefineMaps( void ) 498{ 499 maplist.initialize(); 500} 501 502void 503NurbsTessellator::defineMap( long type, long rational, long ncoords ) 504{ 505 maplist.define( type, (int) rational, (int) ncoords ); 506} 507 508void 509NurbsTessellator::discardRecording( void *_dl ) 510{ 511 delete (DisplayList *) _dl; 512} 513 514void * 515NurbsTessellator::beginRecording( void ) 516{ 517 dl = new DisplayList( this ); 518 return (void *) dl; 519} 520 521void 522NurbsTessellator::endRecording( void ) 523{ 524 dl->endList(); 525 dl = 0; 526} 527 528void 529NurbsTessellator::playRecording( void *_dl ) 530{ 531 playBack = 1; 532 bgnrender(); 533 ((DisplayList *)_dl)->play(); 534 endrender(); 535 playBack = 0; 536} 537 538