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