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 * nurbstess.c++ 37 * 38 */ 39 40 //#include "glimports.h" 41 //#include "myassert.h" 42 //#include "mysetjmp.h" 43 //#include "mystdio.h" 44 //#include "nurbsconsts.h" 45 #include "nurbstess.h" 46 //#include "bufpool.h" 47 #include "quilt.h" 48 #include "knotvector.h" 49 #include "mapdesc.h" 50 //#include "maplist.h" 51 52 void 53 NurbsTessellator::set_domain_distance_u_rate(REAL u_rate) 54 { 55 subdivider.set_domain_distance_u_rate(u_rate); 56 } 57 58 void 59 NurbsTessellator::set_domain_distance_v_rate(REAL v_rate) 60 { 61 subdivider.set_domain_distance_v_rate(v_rate); 62 } 63 64 void 65 NurbsTessellator::set_is_domain_distance_sampling(int flag) 66 { 67 subdivider.set_is_domain_distance_sampling(flag); 68 } 69 70 void 71 NurbsTessellator::resetObjects( void ) 72 { 73 subdivider.clear(); 74 } 75 76 void 77 NurbsTessellator::makeobj( int ) 78 { 79 #ifndef NDEBUG 80 _glu_dprintf( "makeobj\n" ); 81 #endif 82 } 83 84 void 85 NurbsTessellator::closeobj( void ) 86 { 87 #ifndef NDEBUG 88 _glu_dprintf( "closeobj\n" ); 89 #endif 90 } 91 92 void 93 NurbsTessellator::bgnrender( void ) 94 { 95 #ifndef NDEBUG 96 _glu_dprintf( "bgnrender\n" ); 97 #endif 98 } 99 100 void 101 NurbsTessellator::endrender( void ) 102 { 103 #ifndef NDEBUG 104 _glu_dprintf( "endrender\n" ); 105 #endif 106 } 107 108 /*----------------------------------------------------------------------------- 109 * do_freebgnsurface - free o_surface structure 110 * 111 * Client: do_freeall(), bgnsurface() 112 *----------------------------------------------------------------------------- 113 */ 114 void 115 NurbsTessellator::do_freebgnsurface( O_surface *o_surface ) 116 { 117 o_surface->deleteMe( o_surfacePool ); 118 } 119 120 121 /*----------------------------------------------------------------------------- 122 * do_bgnsurface - begin the display of a surface 123 * 124 * Client: bgnsurface() 125 *----------------------------------------------------------------------------- 126 */ 127 void 128 NurbsTessellator::do_bgnsurface( O_surface *o_surface ) 129 { 130 if( inSurface ) { 131 do_nurbserror( 27 ); 132 endsurface(); 133 } 134 inSurface = 1; 135 136 if( ! playBack ) bgnrender(); 137 138 isTrimModified = 0; 139 isSurfaceModified = 0; 140 isDataValid = 1; 141 numTrims = 0; 142 currentSurface = o_surface; 143 nextTrim = &( currentSurface->o_trim ); 144 nextNurbssurface = &( currentSurface->o_nurbssurface ); 145 } 146 147 /*----------------------------------------------------------------------------- 148 * do_bgncurve - begin the display of a curve 149 * 150 * Client: bgncurve() 151 *----------------------------------------------------------------------------- 152 */ 153 void 154 NurbsTessellator::do_bgncurve( O_curve *o_curve ) 155 { 156 if ( inCurve ) { 157 do_nurbserror( 6 ); 158 endcurve(); 159 } 160 161 inCurve = 1; 162 currentCurve = o_curve; 163 currentCurve->curvetype = ct_none; 164 165 if( inTrim ) { 166 if( *nextCurve != o_curve ) { 167 isCurveModified = 1; 168 *nextCurve = o_curve; 169 } 170 } else { 171 if( ! playBack ) bgnrender(); 172 isDataValid = 1; 173 } 174 nextCurve = &(o_curve->next); 175 nextPwlcurve = &(o_curve->curve.o_pwlcurve); 176 nextNurbscurve = &(o_curve->curve.o_nurbscurve); 177 } 178 179 /*----------------------------------------------------------------------------- 180 * do_endcurve - 181 * 182 * Client: endcurve() 183 *----------------------------------------------------------------------------- 184 */ 185 186 void 187 NurbsTessellator::do_endcurve( void ) 188 { 189 if( ! inCurve ) { 190 do_nurbserror( 7 ); 191 return; 192 } 193 inCurve = 0; 194 195 *nextCurve = 0; 196 if (currentCurve->curvetype == ct_nurbscurve) 197 *nextNurbscurve = 0; 198 else 199 *nextPwlcurve = 0; 200 201 if ( ! inTrim ) { 202 if( ! isDataValid ) { 203 do_freecurveall( currentCurve ); 204 return; 205 } 206 207 int errval; 208 errval = ::mysetjmp( jumpbuffer ); 209 if( errval == 0 ) { 210 if( currentCurve->curvetype == ct_nurbscurve ) { 211 subdivider.beginQuilts(); 212 for( O_nurbscurve *n = currentCurve->curve.o_nurbscurve; n != 0; n = n->next ) 213 subdivider.addQuilt( n->bezier_curves ); 214 subdivider.endQuilts(); 215 subdivider.drawCurves(); 216 if( ! playBack ) endrender(); 217 } else { 218 /* XXX */ 219 if( ! playBack ) endrender(); 220 /*do_draw_pwlcurve( currentCurve->curve.o_pwlcurve ) */; 221 do_nurbserror( 9 ); 222 } 223 } else { 224 if( ! playBack ) endrender(); 225 do_nurbserror( errval ); 226 } 227 do_freecurveall( currentCurve ); 228 resetObjects(); 229 } 230 } 231 232 /*----------------------------------------------------------------------------- 233 * do_endsurface - mark end of surface, display surface, free immediate data 234 * 235 * Client: 236 *----------------------------------------------------------------------------- 237 */ 238 void 239 NurbsTessellator::do_endsurface( void ) 240 { 241 if( inTrim ) { 242 do_nurbserror( 12 ); 243 endtrim(); 244 } 245 246 if( ! inSurface ) { 247 do_nurbserror( 13 ); 248 return; 249 } 250 inSurface = 0; 251 252 *nextNurbssurface = 0; 253 254 if( ! isDataValid ) { 255 do_freeall( ); 256 return; 257 } 258 259 if( *nextTrim != 0 ) { 260 isTrimModified = 1; 261 *nextTrim = 0; 262 } 263 264 int errval; 265 266 errval = ::mysetjmp( jumpbuffer ); 267 if( errval == 0 ) { 268 if( numTrims > 0 ) { 269 270 subdivider.beginTrims(); 271 for( O_trim *trim = currentSurface->o_trim; trim; trim = trim->next ) { 272 subdivider.beginLoop(); 273 for( O_curve *curve = trim->o_curve; curve; curve = curve->next ) { 274 curve->used = 0; 275 assert( curve->curvetype != ct_none ); 276 if (curve->curvetype == ct_pwlcurve) { 277 O_pwlcurve *c = curve->curve.o_pwlcurve; 278 subdivider.addArc( c->npts, c->pts, curve->nuid ); 279 } else { 280 Quilt *quilt = curve->curve.o_nurbscurve->bezier_curves; 281 Quiltspec *qspec = quilt->qspec; 282 REAL *cpts = quilt->cpts + qspec->offset; 283 REAL *cptsend = cpts + (qspec->width * qspec->order * qspec->stride); 284 for( ; cpts != cptsend; cpts += qspec->order*qspec->stride ) 285 subdivider.addArc( cpts, quilt, curve->nuid ); 286 } 287 } 288 subdivider.endLoop(); 289 } 290 subdivider.endTrims(); 291 } 292 293 subdivider.beginQuilts(); 294 for( O_nurbssurface *n = currentSurface->o_nurbssurface; n; n = n->next ) 295 subdivider.addQuilt( n->bezier_patches ); 296 subdivider.endQuilts(); 297 subdivider.drawSurfaces( currentSurface->nuid ); 298 if( ! playBack ) endrender(); 299 } else { 300 if( ! playBack ) endrender(); 301 do_nurbserror( errval ); 302 } 303 304 do_freeall( ); 305 resetObjects(); 306 } 307 308 /*----------------------------------------------------------------------------- 309 * do_freeall - free all data allocated in immediate mode 310 * 311 * Client: 312 *----------------------------------------------------------------------------- 313 */ 314 void 315 NurbsTessellator::do_freeall( void ) 316 { 317 for( O_trim *o_trim = currentSurface->o_trim; o_trim; ) { 318 O_trim *next_o_trim = o_trim->next; 319 for( O_curve *curve = o_trim->o_curve; curve; ) { 320 O_curve *next_o_curve = curve->next; 321 do_freecurveall( curve ); 322 curve = next_o_curve; 323 } 324 if( o_trim->save == 0 ) do_freebgntrim( o_trim ); 325 o_trim = next_o_trim; 326 } 327 328 O_nurbssurface *nurbss, *next_nurbss; 329 for( nurbss= currentSurface->o_nurbssurface; nurbss; nurbss = next_nurbss) { 330 next_nurbss = nurbss->next; 331 if( nurbss->save == 0 ) 332 do_freenurbssurface( nurbss ); 333 else 334 nurbss->used = 0; 335 } 336 337 if( currentSurface->save == 0 ) do_freebgnsurface( currentSurface ); 338 } 339 340 void 341 NurbsTessellator::do_freecurveall( O_curve *curve ) 342 { 343 assert( curve->curvetype != ct_none ); 344 345 if( curve->curvetype == ct_nurbscurve ) { 346 O_nurbscurve *ncurve, *next_ncurve; 347 for( ncurve=curve->curve.o_nurbscurve; ncurve; ncurve=next_ncurve ) { 348 next_ncurve = ncurve->next; 349 if( ncurve->save == 0 ) 350 do_freenurbscurve( ncurve ); 351 else 352 ncurve->used = 0; 353 } 354 } else { 355 O_pwlcurve *pcurve, *next_pcurve; 356 for( pcurve=curve->curve.o_pwlcurve; pcurve; pcurve=next_pcurve ) { 357 next_pcurve = pcurve->next; 358 if( pcurve->save == 0 ) 359 do_freepwlcurve( pcurve ); 360 else 361 pcurve->used = 0; 362 } 363 } 364 if( curve->save == 0 ) 365 do_freebgncurve( curve ); 366 } 367 368 369 /*----------------------------------------------------------------------------- 370 * do_freebgntrim - free the space allocated for a trim loop 371 * 372 * Client: 373 *----------------------------------------------------------------------------- 374 */ 375 void 376 NurbsTessellator::do_freebgntrim( O_trim *o_trim ) 377 { 378 o_trim->deleteMe( o_trimPool ); 379 } 380 381 382 /*----------------------------------------------------------------------------- 383 * do_bgntrim - link in a trim loop to the current trimmed surface description 384 * 385 * Client: bgntrim() 386 *----------------------------------------------------------------------------- 387 */ 388 void 389 NurbsTessellator::do_bgntrim( O_trim *o_trim ) 390 { 391 392 if( ! inSurface ) { 393 do_nurbserror( 15 ); 394 bgnsurface( 0 ); 395 inSurface = 2; 396 } 397 398 if( inTrim ) { 399 do_nurbserror( 16 ); 400 endtrim(); 401 } 402 inTrim = 1; 403 404 if( *nextTrim != o_trim ) { 405 isTrimModified = 1; 406 *nextTrim = o_trim; 407 } 408 409 currentTrim = o_trim; 410 nextTrim = &(o_trim->next); 411 nextCurve = &(o_trim->o_curve); 412 } 413 414 415 /*----------------------------------------------------------------------------- 416 * do_endtrim - mark the end of the current trim loop 417 * 418 * Client: endtrim() 419 *----------------------------------------------------------------------------- 420 */ 421 void 422 NurbsTessellator::do_endtrim( void ) 423 { 424 if( ! inTrim ) { 425 do_nurbserror( 17 ); 426 return; 427 } 428 inTrim = 0; 429 430 if( currentTrim->o_curve == 0 ) { 431 do_nurbserror( 18 ); 432 isDataValid = 0; 433 } 434 435 numTrims++; 436 437 if( *nextCurve != 0 ) { 438 isTrimModified = 1; 439 *nextCurve = 0; 440 } 441 } 442 443 /*----------------------------------------------------------------------------- 444 * do_freepwlcurve - 445 * 446 * Client: 447 *----------------------------------------------------------------------------- 448 */ 449 void 450 NurbsTessellator::do_freepwlcurve( O_pwlcurve *o_pwlcurve ) 451 { 452 o_pwlcurve->deleteMe( o_pwlcurvePool ); 453 } 454 455 void 456 NurbsTessellator::do_freebgncurve( O_curve *o_curve ) 457 { 458 o_curve->deleteMe( o_curvePool ); 459 } 460 461 /*----------------------------------------------------------------------------- 462 * do_pwlcurve - link in pwl trim loop to the current surface description 463 * 464 * Client: pwlcurve() 465 *----------------------------------------------------------------------------- 466 */ 467 void 468 NurbsTessellator::do_pwlcurve( O_pwlcurve *o_pwlcurve ) 469 { 470 if( ! inTrim ) { 471 do_nurbserror( 19 ); 472 if( o_pwlcurve->save == 0 ) 473 do_freepwlcurve(o_pwlcurve ); 474 return; 475 } 476 477 if( ! inCurve ) { 478 bgncurve( 0 ); 479 inCurve = 2; 480 } 481 482 if( o_pwlcurve->used ) { 483 do_nurbserror( 20 ); 484 isDataValid = 0; 485 return; 486 } else 487 o_pwlcurve->used = 1; 488 489 if( currentCurve->curvetype == ct_none ) { 490 currentCurve->curvetype = ct_pwlcurve; 491 } else if( currentCurve->curvetype != ct_pwlcurve ) { 492 do_nurbserror( 21 ); 493 isDataValid = 0; 494 return; 495 } 496 497 if( *nextPwlcurve != o_pwlcurve ) { 498 isCurveModified = 1; 499 *nextPwlcurve = o_pwlcurve; 500 } 501 nextPwlcurve = &(o_pwlcurve->next); 502 503 if( o_pwlcurve->owner != currentCurve ) { 504 isCurveModified = 1; 505 o_pwlcurve->owner = currentCurve; 506 } 507 508 if( inCurve == 2 ) 509 endcurve(); 510 } 511 512 513 /*----------------------------------------------------------------------------- 514 * do_freenurbscurve - 515 * 516 * Client: 517 *----------------------------------------------------------------------------- 518 */ 519 void 520 NurbsTessellator::do_freenurbscurve( O_nurbscurve *o_nurbscurve ) 521 { 522 o_nurbscurve->bezier_curves->deleteMe( quiltPool ); 523 o_nurbscurve->deleteMe( o_nurbscurvePool ); 524 } 525 526 527 /*----------------------------------------------------------------------------- 528 * do_nurbscurve - 529 * 530 * Client: nurbscurve() 531 *----------------------------------------------------------------------------- 532 */ 533 void 534 NurbsTessellator::do_nurbscurve( O_nurbscurve *o_nurbscurve ) 535 { 536 if ( ! inCurve ) { 537 bgncurve( 0 ); 538 inCurve = 2; 539 } 540 541 if( o_nurbscurve->used ) { 542 /* error - curve was already called in current surface */ 543 do_nurbserror( 23 ); 544 isDataValid = 0; 545 return; 546 } else 547 o_nurbscurve->used = 1; 548 549 if( currentCurve->curvetype == ct_none ) { 550 currentCurve->curvetype = ct_nurbscurve; 551 } else if( currentCurve->curvetype != ct_nurbscurve ) { 552 do_nurbserror( 24 ); 553 isDataValid = 0; 554 return; 555 } 556 557 if( *nextNurbscurve != o_nurbscurve ) { 558 isCurveModified = 1; 559 *nextNurbscurve = o_nurbscurve; 560 } 561 562 nextNurbscurve = &(o_nurbscurve->next); 563 564 if( o_nurbscurve->owner != currentCurve ) { 565 isCurveModified = 1; 566 o_nurbscurve->owner = currentCurve; 567 } 568 569 if( o_nurbscurve->owner == 0 ) 570 isCurveModified = 1; 571 572 if( inCurve == 2 ) 573 endcurve(); 574 } 575 576 577 /*----------------------------------------------------------------------------- 578 * do_freenurbssurface - 579 * 580 * Client: 581 *----------------------------------------------------------------------------- 582 */ 583 584 void 585 NurbsTessellator::do_freenurbssurface( O_nurbssurface *o_nurbssurface ) 586 { 587 o_nurbssurface->bezier_patches->deleteMe( quiltPool ); 588 o_nurbssurface->deleteMe( o_nurbssurfacePool ); 589 } 590 591 /*----------------------------------------------------------------------------- 592 * do_nurbssurface - 593 * 594 * Client: nurbssurface() 595 *----------------------------------------------------------------------------- 596 */ 597 void 598 NurbsTessellator::do_nurbssurface( O_nurbssurface *o_nurbssurface ) 599 { 600 if( ! inSurface ) { 601 bgnsurface( 0 ); 602 inSurface = 2; 603 } 604 605 if( o_nurbssurface->used ) { 606 /* error - surface was already called in current block */ 607 do_nurbserror( 25 ); 608 isDataValid = 0; 609 return; 610 } else 611 o_nurbssurface->used = 1; 612 613 if( *nextNurbssurface != o_nurbssurface ) { 614 isSurfaceModified = 1; 615 *nextNurbssurface = o_nurbssurface; 616 } 617 618 if( o_nurbssurface->owner != currentSurface ) { 619 isSurfaceModified = 1; 620 o_nurbssurface->owner = currentSurface; 621 } 622 nextNurbssurface = &(o_nurbssurface->next); 623 624 if( inSurface == 2 ) 625 endsurface(); 626 } 627 628 629 /*----------------------------------------------------------------------------- 630 * do_freenurbsproperty 631 * 632 *----------------------------------------------------------------------------- 633 */ 634 635 void 636 NurbsTessellator::do_freenurbsproperty( Property *prop ) 637 { 638 prop->deleteMe( propertyPool ); 639 } 640 641 642 /*----------------------------------------------------------------------------- 643 * do_setnurbsproperty - 644 * 645 *----------------------------------------------------------------------------- 646 */ 647 648 void 649 NurbsTessellator::do_setnurbsproperty( Property *prop ) 650 { 651 renderhints.setProperty( prop->tag, prop->value ); 652 if( prop->save == 0 ) 653 do_freenurbsproperty( prop ); 654 } 655 656 void 657 NurbsTessellator::do_setnurbsproperty2( Property *prop ) 658 { 659 Mapdesc *mapdesc = maplist.find( prop->type ); 660 661 mapdesc->setProperty( prop->tag, prop->value ); 662 if( prop->save == 0 ) 663 do_freenurbsproperty( prop ); 664 } 665 666 void 667 NurbsTessellator::errorHandler( int ) 668 { 669 } 670 671 void 672 NurbsTessellator::do_nurbserror( int msg ) 673 { 674 errorHandler( msg ); 675 } 676 677 int 678 NurbsTessellator::do_check_knots( Knotvector *knots, const char *msg ) 679 { 680 int status = knots->validate(); 681 if( status ) { 682 do_nurbserror( status ); 683 if( renderhints.errorchecking != N_NOMSG ) knots->show( msg ); 684 } 685 return status; 686 } 687 688 689 690 691 692