aselib.c (20423B)
1 /* 2 =========================================================================== 3 Copyright (C) 1999-2005 Id Software, Inc. 4 5 This file is part of Quake III Arena source code. 6 7 Quake III Arena source code is free software; you can redistribute it 8 and/or modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 2 of the License, 10 or (at your option) any later version. 11 12 Quake III Arena source code is distributed in the hope that it will be 13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with Foobar; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 =========================================================================== 21 */ 22 23 #include "aselib.h" 24 25 #include <assert.h> 26 #include <stdio.h> 27 #include <stdlib.h> 28 29 #define MAX_ASE_MATERIALS 32 30 #define MAX_ASE_OBJECTS 64 31 #define MAX_ASE_ANIMATIONS 32 32 #define MAX_ASE_ANIMATION_FRAMES 512 33 34 #define VERBOSE( x ) { if ( ase.verbose ) { printf x ; } } 35 36 typedef struct 37 { 38 float x, y, z; 39 float nx, ny, nz; 40 float s, t; 41 } aseVertex_t; 42 43 typedef struct 44 { 45 float s, t; 46 } aseTVertex_t; 47 48 typedef int aseFace_t[3]; 49 50 typedef struct 51 { 52 int numFaces; 53 int numVertexes; 54 int numTVertexes; 55 56 int timeValue; 57 58 aseVertex_t *vertexes; 59 aseTVertex_t *tvertexes; 60 aseFace_t *faces, *tfaces; 61 62 int currentFace, currentVertex; 63 } aseMesh_t; 64 65 typedef struct 66 { 67 int numFrames; 68 aseMesh_t frames[MAX_ASE_ANIMATION_FRAMES]; 69 70 int currentFrame; 71 } aseMeshAnimation_t; 72 73 typedef struct 74 { 75 char name[128]; 76 } aseMaterial_t; 77 78 /* 79 ** contains the animate sequence of a single surface 80 ** using a single material 81 */ 82 typedef struct 83 { 84 char name[128]; 85 86 int materialRef; 87 int numAnimations; 88 89 aseMeshAnimation_t anim; 90 91 } aseGeomObject_t; 92 93 typedef struct 94 { 95 int numMaterials; 96 aseMaterial_t materials[MAX_ASE_MATERIALS]; 97 aseGeomObject_t objects[MAX_ASE_OBJECTS]; 98 99 char *buffer; 100 char *curpos; 101 int len; 102 103 int currentObject; 104 qboolean verbose; 105 qboolean grabAnims; 106 107 } ase_t; 108 109 static char s_token[1024]; 110 static ase_t ase; 111 112 static void ASE_Process( void ); 113 static void ASE_FreeGeomObject( int ndx ); 114 115 /* 116 ** ASE_Load 117 */ 118 void ASE_Load( const char *filename, qboolean verbose, qboolean grabAnims ) 119 { 120 FILE *fp = fopen( filename, "rb" ); 121 122 if ( !fp ) 123 Error( "File not found '%s'", filename ); 124 125 memset( &ase, 0, sizeof( ase ) ); 126 127 ase.verbose = verbose; 128 ase.grabAnims = grabAnims; 129 ase.len = Q_filelength( fp ); 130 131 ase.curpos = ase.buffer = malloc( ase.len ); 132 133 printf( "Processing '%s'\n", filename ); 134 135 if ( fread( ase.buffer, ase.len, 1, fp ) != 1 ) 136 { 137 fclose( fp ); 138 Error( "fread() != -1 for '%s'", filename ); 139 } 140 141 fclose( fp ); 142 143 ASE_Process(); 144 } 145 146 /* 147 ** ASE_Free 148 */ 149 void ASE_Free( void ) 150 { 151 int i; 152 153 for ( i = 0; i < ase.currentObject; i++ ) 154 { 155 ASE_FreeGeomObject( i ); 156 } 157 } 158 159 /* 160 ** ASE_GetNumSurfaces 161 */ 162 int ASE_GetNumSurfaces( void ) 163 { 164 return ase.currentObject; 165 } 166 167 /* 168 ** ASE_GetSurfaceName 169 */ 170 const char *ASE_GetSurfaceName( int which ) 171 { 172 aseGeomObject_t *pObject = &ase.objects[which]; 173 174 if ( !pObject->anim.numFrames ) 175 return 0; 176 177 return pObject->name; 178 } 179 180 /* 181 ** ASE_GetSurfaceAnimation 182 ** 183 ** Returns an animation (sequence of polysets) 184 */ 185 polyset_t *ASE_GetSurfaceAnimation( int which, int *pNumFrames, int skipFrameStart, int skipFrameEnd, int maxFrames ) 186 { 187 aseGeomObject_t *pObject = &ase.objects[which]; 188 polyset_t *psets; 189 int numFramesInAnimation; 190 int numFramesToKeep; 191 int i, f; 192 193 if ( !pObject->anim.numFrames ) 194 return 0; 195 196 if ( pObject->anim.numFrames > maxFrames && maxFrames != -1 ) 197 { 198 numFramesInAnimation = maxFrames; 199 } 200 else 201 { 202 numFramesInAnimation = pObject->anim.numFrames; 203 if ( maxFrames != -1 ) 204 printf( "WARNING: ASE_GetSurfaceAnimation maxFrames > numFramesInAnimation\n" ); 205 } 206 207 if ( skipFrameEnd != -1 ) 208 numFramesToKeep = numFramesInAnimation - ( skipFrameEnd - skipFrameStart + 1 ); 209 else 210 numFramesToKeep = numFramesInAnimation; 211 212 *pNumFrames = numFramesToKeep; 213 214 psets = calloc( sizeof( polyset_t ) * numFramesToKeep, 1 ); 215 216 for ( f = 0, i = 0; i < numFramesInAnimation; i++ ) 217 { 218 int t; 219 aseMesh_t *pMesh = &pObject->anim.frames[i]; 220 221 if ( skipFrameStart != -1 ) 222 { 223 if ( i >= skipFrameStart && i <= skipFrameEnd ) 224 continue; 225 } 226 227 strcpy( psets[f].name, pObject->name ); 228 strcpy( psets[f].materialname, ase.materials[pObject->materialRef].name ); 229 230 psets[f].triangles = calloc( sizeof( triangle_t ) * pObject->anim.frames[i].numFaces, 1 ); 231 psets[f].numtriangles = pObject->anim.frames[i].numFaces; 232 233 for ( t = 0; t < pObject->anim.frames[i].numFaces; t++ ) 234 { 235 int k; 236 237 for ( k = 0; k < 3; k++ ) 238 { 239 psets[f].triangles[t].verts[k][0] = pMesh->vertexes[pMesh->faces[t][k]].x; 240 psets[f].triangles[t].verts[k][1] = pMesh->vertexes[pMesh->faces[t][k]].y; 241 psets[f].triangles[t].verts[k][2] = pMesh->vertexes[pMesh->faces[t][k]].z; 242 243 if ( pMesh->tvertexes && pMesh->tfaces ) 244 { 245 psets[f].triangles[t].texcoords[k][0] = pMesh->tvertexes[pMesh->tfaces[t][k]].s; 246 psets[f].triangles[t].texcoords[k][1] = pMesh->tvertexes[pMesh->tfaces[t][k]].t; 247 } 248 249 } 250 } 251 252 f++; 253 } 254 255 return psets; 256 } 257 258 static void ASE_FreeGeomObject( int ndx ) 259 { 260 aseGeomObject_t *pObject; 261 int i; 262 263 pObject = &ase.objects[ndx]; 264 265 for ( i = 0; i < pObject->anim.numFrames; i++ ) 266 { 267 if ( pObject->anim.frames[i].vertexes ) 268 { 269 free( pObject->anim.frames[i].vertexes ); 270 } 271 if ( pObject->anim.frames[i].tvertexes ) 272 { 273 free( pObject->anim.frames[i].tvertexes ); 274 } 275 if ( pObject->anim.frames[i].faces ) 276 { 277 free( pObject->anim.frames[i].faces ); 278 } 279 if ( pObject->anim.frames[i].tfaces ) 280 { 281 free( pObject->anim.frames[i].tfaces ); 282 } 283 } 284 285 memset( pObject, 0, sizeof( *pObject ) ); 286 } 287 288 static aseMesh_t *ASE_GetCurrentMesh( void ) 289 { 290 aseGeomObject_t *pObject; 291 292 if ( ase.currentObject >= MAX_ASE_OBJECTS ) 293 { 294 Error( "Too many GEOMOBJECTs" ); 295 return 0; // never called 296 } 297 298 pObject = &ase.objects[ase.currentObject]; 299 300 if ( pObject->anim.currentFrame >= MAX_ASE_ANIMATION_FRAMES ) 301 { 302 Error( "Too many MESHes" ); 303 return 0; 304 } 305 306 return &pObject->anim.frames[pObject->anim.currentFrame]; 307 } 308 309 static int CharIsTokenDelimiter( int ch ) 310 { 311 if ( ch <= 32 ) 312 return 1; 313 return 0; 314 } 315 316 static int ASE_GetToken( qboolean restOfLine ) 317 { 318 int i = 0; 319 320 if ( ase.buffer == 0 ) 321 return 0; 322 323 if ( ( ase.curpos - ase.buffer ) == ase.len ) 324 return 0; 325 326 // skip over crap 327 while ( ( ( ase.curpos - ase.buffer ) < ase.len ) && 328 ( *ase.curpos <= 32 ) ) 329 { 330 ase.curpos++; 331 } 332 333 while ( ( ase.curpos - ase.buffer ) < ase.len ) 334 { 335 s_token[i] = *ase.curpos; 336 337 ase.curpos++; 338 i++; 339 340 if ( ( CharIsTokenDelimiter( s_token[i-1] ) && !restOfLine ) || 341 ( ( s_token[i-1] == '\n' ) || ( s_token[i-1] == '\r' ) ) ) 342 { 343 s_token[i-1] = 0; 344 break; 345 } 346 } 347 348 s_token[i] = 0; 349 350 return 1; 351 } 352 353 static void ASE_ParseBracedBlock( void (*parser)( const char *token ) ) 354 { 355 int indent = 0; 356 357 while ( ASE_GetToken( qfalse ) ) 358 { 359 if ( !strcmp( s_token, "{" ) ) 360 { 361 indent++; 362 } 363 else if ( !strcmp( s_token, "}" ) ) 364 { 365 --indent; 366 if ( indent == 0 ) 367 break; 368 else if ( indent < 0 ) 369 Error( "Unexpected '}'" ); 370 } 371 else 372 { 373 if ( parser ) 374 parser( s_token ); 375 } 376 } 377 } 378 379 static void ASE_SkipEnclosingBraces( void ) 380 { 381 int indent = 0; 382 383 while ( ASE_GetToken( qfalse ) ) 384 { 385 if ( !strcmp( s_token, "{" ) ) 386 { 387 indent++; 388 } 389 else if ( !strcmp( s_token, "}" ) ) 390 { 391 indent--; 392 if ( indent == 0 ) 393 break; 394 else if ( indent < 0 ) 395 Error( "Unexpected '}'" ); 396 } 397 } 398 } 399 400 static void ASE_SkipRestOfLine( void ) 401 { 402 ASE_GetToken( qtrue ); 403 } 404 405 static void ASE_KeyMAP_DIFFUSE( const char *token ) 406 { 407 char buffer[1024], buff1[1024], buff2[1024]; 408 char *buf1, *buf2; 409 int i = 0, count; 410 411 if ( !strcmp( token, "*BITMAP" ) ) 412 { 413 ASE_GetToken( qfalse ); 414 415 strcpy( buffer, s_token + 1 ); 416 if ( strchr( buffer, '"' ) ) 417 *strchr( buffer, '"' ) = 0; 418 419 while ( buffer[i] ) 420 { 421 if ( buffer[i] == '\\' ) 422 buffer[i] = '/'; 423 i++; 424 } 425 426 buf1 = buffer; 427 buf2 = gamedir; 428 // need to compare win32 volumes to potential unix junk 429 // 430 if ( (gamedir[1] == ':' && (buffer[0] == '/' && buffer[1] == '/')) || 431 (buffer[1] == ':' && (gamedir[0] == '/' && gamedir[1] == '/')) ) { 432 if (buffer[1] == ':') { 433 buf1 = buffer + 2; 434 buf2 = gamedir + 2; 435 } else { 436 buf1 = gamedir + 2; 437 buf2 = buffer +2; 438 } 439 count = 0; 440 while (*buf2 && count < 2) { 441 if (*buf2 == '/') { 442 count++; 443 } 444 buf2++; 445 } 446 } 447 strcpy(buff1, buf1); 448 strlwr(buff1); 449 strcpy(buff2, buf2); 450 strlwr(buff2); 451 if ( strstr( buff2, buff1 + 2 ) ) 452 { 453 strcpy( ase.materials[ase.numMaterials].name, strstr( buff2, buff1 + 2 ) + strlen( buff1 ) - 2 ); 454 } 455 else 456 { 457 sprintf( ase.materials[ase.numMaterials].name, "(not converted: '%s')", buffer ); 458 printf( "WARNING: illegal material name '%s'\n", buffer ); 459 } 460 } 461 else 462 { 463 } 464 } 465 466 static void ASE_KeyMATERIAL( const char *token ) 467 { 468 if ( !strcmp( token, "*MAP_DIFFUSE" ) ) 469 { 470 ASE_ParseBracedBlock( ASE_KeyMAP_DIFFUSE ); 471 } 472 else 473 { 474 } 475 } 476 477 static void ASE_KeyMATERIAL_LIST( const char *token ) 478 { 479 if ( !strcmp( token, "*MATERIAL_COUNT" ) ) 480 { 481 ASE_GetToken( qfalse ); 482 VERBOSE( ( "..num materials: %s\n", s_token ) ); 483 if ( atoi( s_token ) > MAX_ASE_MATERIALS ) 484 { 485 Error( "Too many materials!" ); 486 } 487 ase.numMaterials = 0; 488 } 489 else if ( !strcmp( token, "*MATERIAL" ) ) 490 { 491 VERBOSE( ( "..material %d ", ase.numMaterials ) ); 492 ASE_ParseBracedBlock( ASE_KeyMATERIAL ); 493 ase.numMaterials++; 494 } 495 } 496 497 static void ASE_KeyMESH_VERTEX_LIST( const char *token ) 498 { 499 aseMesh_t *pMesh = ASE_GetCurrentMesh(); 500 501 if ( !strcmp( token, "*MESH_VERTEX" ) ) 502 { 503 ASE_GetToken( qfalse ); // skip number 504 505 ASE_GetToken( qfalse ); 506 pMesh->vertexes[pMesh->currentVertex].y = atof( s_token ); 507 508 ASE_GetToken( qfalse ); 509 pMesh->vertexes[pMesh->currentVertex].x = -atof( s_token ); 510 511 ASE_GetToken( qfalse ); 512 pMesh->vertexes[pMesh->currentVertex].z = atof( s_token ); 513 514 pMesh->currentVertex++; 515 516 if ( pMesh->currentVertex > pMesh->numVertexes ) 517 { 518 Error( "pMesh->currentVertex >= pMesh->numVertexes" ); 519 } 520 } 521 else 522 { 523 Error( "Unknown token '%s' while parsing MESH_VERTEX_LIST", token ); 524 } 525 } 526 527 static void ASE_KeyMESH_FACE_LIST( const char *token ) 528 { 529 aseMesh_t *pMesh = ASE_GetCurrentMesh(); 530 531 if ( !strcmp( token, "*MESH_FACE" ) ) 532 { 533 ASE_GetToken( qfalse ); // skip face number 534 535 ASE_GetToken( qfalse ); // skip label 536 ASE_GetToken( qfalse ); // first vertex 537 pMesh->faces[pMesh->currentFace][0] = atoi( s_token ); 538 539 ASE_GetToken( qfalse ); // skip label 540 ASE_GetToken( qfalse ); // second vertex 541 pMesh->faces[pMesh->currentFace][2] = atoi( s_token ); 542 543 ASE_GetToken( qfalse ); // skip label 544 ASE_GetToken( qfalse ); // third vertex 545 pMesh->faces[pMesh->currentFace][1] = atoi( s_token ); 546 547 ASE_GetToken( qtrue ); 548 549 /* 550 if ( ( p = strstr( s_token, "*MESH_MTLID" ) ) != 0 ) 551 { 552 p += strlen( "*MESH_MTLID" ) + 1; 553 mtlID = atoi( p ); 554 } 555 else 556 { 557 Error( "No *MESH_MTLID found for face!" ); 558 } 559 */ 560 561 pMesh->currentFace++; 562 } 563 else 564 { 565 Error( "Unknown token '%s' while parsing MESH_FACE_LIST", token ); 566 } 567 } 568 569 static void ASE_KeyTFACE_LIST( const char *token ) 570 { 571 aseMesh_t *pMesh = ASE_GetCurrentMesh(); 572 573 if ( !strcmp( token, "*MESH_TFACE" ) ) 574 { 575 int a, b, c; 576 577 ASE_GetToken( qfalse ); 578 579 ASE_GetToken( qfalse ); 580 a = atoi( s_token ); 581 ASE_GetToken( qfalse ); 582 c = atoi( s_token ); 583 ASE_GetToken( qfalse ); 584 b = atoi( s_token ); 585 586 pMesh->tfaces[pMesh->currentFace][0] = a; 587 pMesh->tfaces[pMesh->currentFace][1] = b; 588 pMesh->tfaces[pMesh->currentFace][2] = c; 589 590 pMesh->currentFace++; 591 } 592 else 593 { 594 Error( "Unknown token '%s' in MESH_TFACE", token ); 595 } 596 } 597 598 static void ASE_KeyMESH_TVERTLIST( const char *token ) 599 { 600 aseMesh_t *pMesh = ASE_GetCurrentMesh(); 601 602 if ( !strcmp( token, "*MESH_TVERT" ) ) 603 { 604 char u[80], v[80], w[80]; 605 606 ASE_GetToken( qfalse ); 607 608 ASE_GetToken( qfalse ); 609 strcpy( u, s_token ); 610 611 ASE_GetToken( qfalse ); 612 strcpy( v, s_token ); 613 614 ASE_GetToken( qfalse ); 615 strcpy( w, s_token ); 616 617 pMesh->tvertexes[pMesh->currentVertex].s = atof( u ); 618 pMesh->tvertexes[pMesh->currentVertex].t = 1.0f - atof( v ); 619 620 pMesh->currentVertex++; 621 622 if ( pMesh->currentVertex > pMesh->numTVertexes ) 623 { 624 Error( "pMesh->currentVertex > pMesh->numTVertexes" ); 625 } 626 } 627 else 628 { 629 Error( "Unknown token '%s' while parsing MESH_TVERTLIST" ); 630 } 631 } 632 633 static void ASE_KeyMESH( const char *token ) 634 { 635 aseMesh_t *pMesh = ASE_GetCurrentMesh(); 636 637 if ( !strcmp( token, "*TIMEVALUE" ) ) 638 { 639 ASE_GetToken( qfalse ); 640 641 pMesh->timeValue = atoi( s_token ); 642 VERBOSE( ( ".....timevalue: %d\n", pMesh->timeValue ) ); 643 } 644 else if ( !strcmp( token, "*MESH_NUMVERTEX" ) ) 645 { 646 ASE_GetToken( qfalse ); 647 648 pMesh->numVertexes = atoi( s_token ); 649 VERBOSE( ( ".....TIMEVALUE: %d\n", pMesh->timeValue ) ); 650 VERBOSE( ( ".....num vertexes: %d\n", pMesh->numVertexes ) ); 651 } 652 else if ( !strcmp( token, "*MESH_NUMFACES" ) ) 653 { 654 ASE_GetToken( qfalse ); 655 656 pMesh->numFaces = atoi( s_token ); 657 VERBOSE( ( ".....num faces: %d\n", pMesh->numFaces ) ); 658 } 659 else if ( !strcmp( token, "*MESH_NUMTVFACES" ) ) 660 { 661 ASE_GetToken( qfalse ); 662 663 if ( atoi( s_token ) != pMesh->numFaces ) 664 { 665 Error( "MESH_NUMTVFACES != MESH_NUMFACES" ); 666 } 667 } 668 else if ( !strcmp( token, "*MESH_NUMTVERTEX" ) ) 669 { 670 ASE_GetToken( qfalse ); 671 672 pMesh->numTVertexes = atoi( s_token ); 673 VERBOSE( ( ".....num tvertexes: %d\n", pMesh->numTVertexes ) ); 674 } 675 else if ( !strcmp( token, "*MESH_VERTEX_LIST" ) ) 676 { 677 pMesh->vertexes = calloc( sizeof( aseVertex_t ) * pMesh->numVertexes, 1 ); 678 pMesh->currentVertex = 0; 679 VERBOSE( ( ".....parsing MESH_VERTEX_LIST\n" ) ); 680 ASE_ParseBracedBlock( ASE_KeyMESH_VERTEX_LIST ); 681 } 682 else if ( !strcmp( token, "*MESH_TVERTLIST" ) ) 683 { 684 pMesh->currentVertex = 0; 685 pMesh->tvertexes = calloc( sizeof( aseTVertex_t ) * pMesh->numTVertexes, 1 ); 686 VERBOSE( ( ".....parsing MESH_TVERTLIST\n" ) ); 687 ASE_ParseBracedBlock( ASE_KeyMESH_TVERTLIST ); 688 } 689 else if ( !strcmp( token, "*MESH_FACE_LIST" ) ) 690 { 691 pMesh->faces = calloc( sizeof( aseFace_t ) * pMesh->numFaces, 1 ); 692 pMesh->currentFace = 0; 693 VERBOSE( ( ".....parsing MESH_FACE_LIST\n" ) ); 694 ASE_ParseBracedBlock( ASE_KeyMESH_FACE_LIST ); 695 } 696 else if ( !strcmp( token, "*MESH_TFACELIST" ) ) 697 { 698 pMesh->tfaces = calloc( sizeof( aseFace_t ) * pMesh->numFaces, 1 ); 699 pMesh->currentFace = 0; 700 VERBOSE( ( ".....parsing MESH_TFACE_LIST\n" ) ); 701 ASE_ParseBracedBlock( ASE_KeyTFACE_LIST ); 702 } 703 else if ( !strcmp( token, "*MESH_NORMALS" ) ) 704 { 705 ASE_ParseBracedBlock( 0 ); 706 } 707 } 708 709 static void ASE_KeyMESH_ANIMATION( const char *token ) 710 { 711 aseMesh_t *pMesh = ASE_GetCurrentMesh(); 712 713 // loads a single animation frame 714 if ( !strcmp( token, "*MESH" ) ) 715 { 716 VERBOSE( ( "...found MESH\n" ) ); 717 assert( pMesh->faces == 0 ); 718 assert( pMesh->vertexes == 0 ); 719 assert( pMesh->tvertexes == 0 ); 720 memset( pMesh, 0, sizeof( *pMesh ) ); 721 722 ASE_ParseBracedBlock( ASE_KeyMESH ); 723 724 if ( ++ase.objects[ase.currentObject].anim.currentFrame == MAX_ASE_ANIMATION_FRAMES ) 725 { 726 Error( "Too many animation frames" ); 727 } 728 } 729 else 730 { 731 Error( "Unknown token '%s' while parsing MESH_ANIMATION", token ); 732 } 733 } 734 735 static void ASE_KeyGEOMOBJECT( const char *token ) 736 { 737 if ( !strcmp( token, "*NODE_NAME" ) ) 738 { 739 char *name = ase.objects[ase.currentObject].name; 740 741 ASE_GetToken( qtrue ); 742 VERBOSE( ( " %s\n", s_token ) ); 743 strcpy( ase.objects[ase.currentObject].name, s_token + 1 ); 744 if ( strchr( ase.objects[ase.currentObject].name, '"' ) ) 745 *strchr( ase.objects[ase.currentObject].name, '"' ) = 0; 746 747 if ( strstr( name, "tag" ) == name ) 748 { 749 while ( strchr( name, '_' ) != strrchr( name, '_' ) ) 750 { 751 *strrchr( name, '_' ) = 0; 752 } 753 while ( strrchr( name, ' ' ) ) 754 { 755 *strrchr( name, ' ' ) = 0; 756 } 757 } 758 } 759 else if ( !strcmp( token, "*NODE_PARENT" ) ) 760 { 761 ASE_SkipRestOfLine(); 762 } 763 // ignore unused data blocks 764 else if ( !strcmp( token, "*NODE_TM" ) || 765 !strcmp( token, "*TM_ANIMATION" ) ) 766 { 767 ASE_ParseBracedBlock( 0 ); 768 } 769 // ignore regular meshes that aren't part of animation 770 else if ( !strcmp( token, "*MESH" ) && !ase.grabAnims ) 771 { 772 /* 773 if ( strstr( ase.objects[ase.currentObject].name, "tag_" ) == ase.objects[ase.currentObject].name ) 774 { 775 s_forceStaticMesh = true; 776 ASE_ParseBracedBlock( ASE_KeyMESH ); 777 s_forceStaticMesh = false; 778 } 779 */ 780 ASE_ParseBracedBlock( ASE_KeyMESH ); 781 if ( ++ase.objects[ase.currentObject].anim.currentFrame == MAX_ASE_ANIMATION_FRAMES ) 782 { 783 Error( "Too many animation frames" ); 784 } 785 ase.objects[ase.currentObject].anim.numFrames = ase.objects[ase.currentObject].anim.currentFrame; 786 ase.objects[ase.currentObject].numAnimations++; 787 /* 788 // ignore meshes that aren't part of animations if this object isn't a 789 // a tag 790 else 791 { 792 ASE_ParseBracedBlock( 0 ); 793 } 794 */ 795 } 796 // according to spec these are obsolete 797 else if ( !strcmp( token, "*MATERIAL_REF" ) ) 798 { 799 ASE_GetToken( qfalse ); 800 801 ase.objects[ase.currentObject].materialRef = atoi( s_token ); 802 } 803 // loads a sequence of animation frames 804 else if ( !strcmp( token, "*MESH_ANIMATION" ) ) 805 { 806 if ( ase.grabAnims ) 807 { 808 VERBOSE( ( "..found MESH_ANIMATION\n" ) ); 809 810 if ( ase.objects[ase.currentObject].numAnimations ) 811 { 812 Error( "Multiple MESH_ANIMATIONS within a single GEOM_OBJECT" ); 813 } 814 ASE_ParseBracedBlock( ASE_KeyMESH_ANIMATION ); 815 ase.objects[ase.currentObject].anim.numFrames = ase.objects[ase.currentObject].anim.currentFrame; 816 ase.objects[ase.currentObject].numAnimations++; 817 } 818 else 819 { 820 ASE_SkipEnclosingBraces(); 821 } 822 } 823 // skip unused info 824 else if ( !strcmp( token, "*PROP_MOTIONBLUR" ) || 825 !strcmp( token, "*PROP_CASTSHADOW" ) || 826 !strcmp( token, "*PROP_RECVSHADOW" ) ) 827 { 828 ASE_SkipRestOfLine(); 829 } 830 } 831 832 static void ConcatenateObjects( aseGeomObject_t *pObjA, aseGeomObject_t *pObjB ) 833 { 834 } 835 836 static void CollapseObjects( void ) 837 { 838 int i; 839 int numObjects = ase.currentObject; 840 841 for ( i = 0; i < numObjects; i++ ) 842 { 843 int j; 844 845 // skip tags 846 if ( strstr( ase.objects[i].name, "tag" ) == ase.objects[i].name ) 847 { 848 continue; 849 } 850 851 if ( !ase.objects[i].numAnimations ) 852 { 853 continue; 854 } 855 856 for ( j = i + 1; j < numObjects; j++ ) 857 { 858 if ( strstr( ase.objects[j].name, "tag" ) == ase.objects[j].name ) 859 { 860 continue; 861 } 862 if ( ase.objects[i].materialRef == ase.objects[j].materialRef ) 863 { 864 if ( ase.objects[j].numAnimations ) 865 { 866 ConcatenateObjects( &ase.objects[i], &ase.objects[j] ); 867 } 868 } 869 } 870 } 871 } 872 873 /* 874 ** ASE_Process 875 */ 876 static void ASE_Process( void ) 877 { 878 while ( ASE_GetToken( qfalse ) ) 879 { 880 if ( !strcmp( s_token, "*3DSMAX_ASCIIEXPORT" ) || 881 !strcmp( s_token, "*COMMENT" ) ) 882 { 883 ASE_SkipRestOfLine(); 884 } 885 else if ( !strcmp( s_token, "*SCENE" ) ) 886 ASE_SkipEnclosingBraces(); 887 else if ( !strcmp( s_token, "*MATERIAL_LIST" ) ) 888 { 889 VERBOSE( ("MATERIAL_LIST\n") ); 890 891 ASE_ParseBracedBlock( ASE_KeyMATERIAL_LIST ); 892 } 893 else if ( !strcmp( s_token, "*GEOMOBJECT" ) ) 894 { 895 VERBOSE( ("GEOMOBJECT" ) ); 896 897 ASE_ParseBracedBlock( ASE_KeyGEOMOBJECT ); 898 899 if ( strstr( ase.objects[ase.currentObject].name, "Bip" ) || 900 strstr( ase.objects[ase.currentObject].name, "ignore_" ) ) 901 { 902 ASE_FreeGeomObject( ase.currentObject ); 903 VERBOSE( ( "(discarding BIP/ignore object)\n" ) ); 904 } 905 else if ( ( strstr( ase.objects[ase.currentObject].name, "h_" ) != ase.objects[ase.currentObject].name ) && 906 ( strstr( ase.objects[ase.currentObject].name, "l_" ) != ase.objects[ase.currentObject].name ) && 907 ( strstr( ase.objects[ase.currentObject].name, "u_" ) != ase.objects[ase.currentObject].name ) && 908 ( strstr( ase.objects[ase.currentObject].name, "tag" ) != ase.objects[ase.currentObject].name ) && 909 ase.grabAnims ) 910 { 911 VERBOSE( ( "(ignoring improperly labeled object '%s')\n", ase.objects[ase.currentObject].name ) ); 912 ASE_FreeGeomObject( ase.currentObject ); 913 } 914 else 915 { 916 if ( ++ase.currentObject == MAX_ASE_OBJECTS ) 917 { 918 Error( "Too many GEOMOBJECTs" ); 919 } 920 } 921 } 922 else if ( s_token[0] ) 923 { 924 printf( "Unknown token '%s'\n", s_token ); 925 } 926 } 927 928 if ( !ase.currentObject ) 929 Error( "No animation data!" ); 930 931 CollapseObjects(); 932 } 933