tr_model.c (18139B)
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 // tr_models.c -- model loading and caching 23 24 #include "tr_local.h" 25 26 #define LL(x) x=LittleLong(x) 27 28 static qboolean R_LoadMD3 (model_t *mod, int lod, void *buffer, const char *name ); 29 static qboolean R_LoadMD4 (model_t *mod, void *buffer, const char *name ); 30 31 model_t *loadmodel; 32 33 /* 34 ** R_GetModelByHandle 35 */ 36 model_t *R_GetModelByHandle( qhandle_t index ) { 37 model_t *mod; 38 39 // out of range gets the defualt model 40 if ( index < 1 || index >= tr.numModels ) { 41 return tr.models[0]; 42 } 43 44 mod = tr.models[index]; 45 46 return mod; 47 } 48 49 //=============================================================================== 50 51 /* 52 ** R_AllocModel 53 */ 54 model_t *R_AllocModel( void ) { 55 model_t *mod; 56 57 if ( tr.numModels == MAX_MOD_KNOWN ) { 58 return NULL; 59 } 60 61 mod = ri.Hunk_Alloc( sizeof( *tr.models[tr.numModels] ), h_low ); 62 mod->index = tr.numModels; 63 tr.models[tr.numModels] = mod; 64 tr.numModels++; 65 66 return mod; 67 } 68 69 /* 70 ==================== 71 RE_RegisterModel 72 73 Loads in a model for the given name 74 75 Zero will be returned if the model fails to load. 76 An entry will be retained for failed models as an 77 optimization to prevent disk rescanning if they are 78 asked for again. 79 ==================== 80 */ 81 qhandle_t RE_RegisterModel( const char *name ) { 82 model_t *mod; 83 unsigned *buf; 84 int lod; 85 int ident; 86 qboolean loaded; 87 qhandle_t hModel; 88 int numLoaded; 89 90 if ( !name || !name[0] ) { 91 ri.Printf( PRINT_ALL, "RE_RegisterModel: NULL name\n" ); 92 return 0; 93 } 94 95 if ( strlen( name ) >= MAX_QPATH ) { 96 Com_Printf( "Model name exceeds MAX_QPATH\n" ); 97 return 0; 98 } 99 100 // 101 // search the currently loaded models 102 // 103 for ( hModel = 1 ; hModel < tr.numModels; hModel++ ) { 104 mod = tr.models[hModel]; 105 if ( !strcmp( mod->name, name ) ) { 106 if( mod->type == MOD_BAD ) { 107 return 0; 108 } 109 return hModel; 110 } 111 } 112 113 // allocate a new model_t 114 115 if ( ( mod = R_AllocModel() ) == NULL ) { 116 ri.Printf( PRINT_WARNING, "RE_RegisterModel: R_AllocModel() failed for '%s'\n", name); 117 return 0; 118 } 119 120 // only set the name after the model has been successfully loaded 121 Q_strncpyz( mod->name, name, sizeof( mod->name ) ); 122 123 124 // make sure the render thread is stopped 125 R_SyncRenderThread(); 126 127 mod->numLods = 0; 128 129 // 130 // load the files 131 // 132 numLoaded = 0; 133 134 for ( lod = MD3_MAX_LODS - 1 ; lod >= 0 ; lod-- ) { 135 char filename[1024]; 136 137 strcpy( filename, name ); 138 139 if ( lod != 0 ) { 140 char namebuf[80]; 141 142 if ( strrchr( filename, '.' ) ) { 143 *strrchr( filename, '.' ) = 0; 144 } 145 sprintf( namebuf, "_%d.md3", lod ); 146 strcat( filename, namebuf ); 147 } 148 149 ri.FS_ReadFile( filename, (void **)&buf ); 150 if ( !buf ) { 151 continue; 152 } 153 154 loadmodel = mod; 155 156 ident = LittleLong(*(unsigned *)buf); 157 if ( ident == MD4_IDENT ) { 158 loaded = R_LoadMD4( mod, buf, name ); 159 } else { 160 if ( ident != MD3_IDENT ) { 161 ri.Printf (PRINT_WARNING,"RE_RegisterModel: unknown fileid for %s\n", name); 162 goto fail; 163 } 164 165 loaded = R_LoadMD3( mod, lod, buf, name ); 166 } 167 168 ri.FS_FreeFile (buf); 169 170 if ( !loaded ) { 171 if ( lod == 0 ) { 172 goto fail; 173 } else { 174 break; 175 } 176 } else { 177 mod->numLods++; 178 numLoaded++; 179 // if we have a valid model and are biased 180 // so that we won't see any higher detail ones, 181 // stop loading them 182 // if ( lod <= r_lodbias->integer ) { 183 // break; 184 // } 185 } 186 } 187 188 if ( numLoaded ) { 189 // duplicate into higher lod spots that weren't 190 // loaded, in case the user changes r_lodbias on the fly 191 for ( lod-- ; lod >= 0 ; lod-- ) { 192 mod->numLods++; 193 mod->md3[lod] = mod->md3[lod+1]; 194 } 195 196 return mod->index; 197 } 198 #ifdef _DEBUG 199 else { 200 ri.Printf (PRINT_WARNING,"RE_RegisterModel: couldn't load %s\n", name); 201 } 202 #endif 203 204 fail: 205 // we still keep the model_t around, so if the model name is asked for 206 // again, we won't bother scanning the filesystem 207 mod->type = MOD_BAD; 208 return 0; 209 } 210 211 212 /* 213 ================= 214 R_LoadMD3 215 ================= 216 */ 217 static qboolean R_LoadMD3 (model_t *mod, int lod, void *buffer, const char *mod_name ) { 218 int i, j; 219 md3Header_t *pinmodel; 220 md3Frame_t *frame; 221 md3Surface_t *surf; 222 md3Shader_t *shader; 223 md3Triangle_t *tri; 224 md3St_t *st; 225 md3XyzNormal_t *xyz; 226 md3Tag_t *tag; 227 int version; 228 int size; 229 230 pinmodel = (md3Header_t *)buffer; 231 232 version = LittleLong (pinmodel->version); 233 if (version != MD3_VERSION) { 234 ri.Printf( PRINT_WARNING, "R_LoadMD3: %s has wrong version (%i should be %i)\n", 235 mod_name, version, MD3_VERSION); 236 return qfalse; 237 } 238 239 mod->type = MOD_MESH; 240 size = LittleLong(pinmodel->ofsEnd); 241 mod->dataSize += size; 242 mod->md3[lod] = ri.Hunk_Alloc( size, h_low ); 243 244 Com_Memcpy (mod->md3[lod], buffer, LittleLong(pinmodel->ofsEnd) ); 245 246 LL(mod->md3[lod]->ident); 247 LL(mod->md3[lod]->version); 248 LL(mod->md3[lod]->numFrames); 249 LL(mod->md3[lod]->numTags); 250 LL(mod->md3[lod]->numSurfaces); 251 LL(mod->md3[lod]->ofsFrames); 252 LL(mod->md3[lod]->ofsTags); 253 LL(mod->md3[lod]->ofsSurfaces); 254 LL(mod->md3[lod]->ofsEnd); 255 256 if ( mod->md3[lod]->numFrames < 1 ) { 257 ri.Printf( PRINT_WARNING, "R_LoadMD3: %s has no frames\n", mod_name ); 258 return qfalse; 259 } 260 261 // swap all the frames 262 frame = (md3Frame_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsFrames ); 263 for ( i = 0 ; i < mod->md3[lod]->numFrames ; i++, frame++) { 264 frame->radius = LittleFloat( frame->radius ); 265 for ( j = 0 ; j < 3 ; j++ ) { 266 frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] ); 267 frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] ); 268 frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] ); 269 } 270 } 271 272 // swap all the tags 273 tag = (md3Tag_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsTags ); 274 for ( i = 0 ; i < mod->md3[lod]->numTags * mod->md3[lod]->numFrames ; i++, tag++) { 275 for ( j = 0 ; j < 3 ; j++ ) { 276 tag->origin[j] = LittleFloat( tag->origin[j] ); 277 tag->axis[0][j] = LittleFloat( tag->axis[0][j] ); 278 tag->axis[1][j] = LittleFloat( tag->axis[1][j] ); 279 tag->axis[2][j] = LittleFloat( tag->axis[2][j] ); 280 } 281 } 282 283 // swap all the surfaces 284 surf = (md3Surface_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsSurfaces ); 285 for ( i = 0 ; i < mod->md3[lod]->numSurfaces ; i++) { 286 287 LL(surf->ident); 288 LL(surf->flags); 289 LL(surf->numFrames); 290 LL(surf->numShaders); 291 LL(surf->numTriangles); 292 LL(surf->ofsTriangles); 293 LL(surf->numVerts); 294 LL(surf->ofsShaders); 295 LL(surf->ofsSt); 296 LL(surf->ofsXyzNormals); 297 LL(surf->ofsEnd); 298 299 if ( surf->numVerts > SHADER_MAX_VERTEXES ) { 300 ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i verts on a surface (%i)", 301 mod_name, SHADER_MAX_VERTEXES, surf->numVerts ); 302 } 303 if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) { 304 ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i triangles on a surface (%i)", 305 mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles ); 306 } 307 308 // change to surface identifier 309 surf->ident = SF_MD3; 310 311 // lowercase the surface name so skin compares are faster 312 Q_strlwr( surf->name ); 313 314 // strip off a trailing _1 or _2 315 // this is a crutch for q3data being a mess 316 j = strlen( surf->name ); 317 if ( j > 2 && surf->name[j-2] == '_' ) { 318 surf->name[j-2] = 0; 319 } 320 321 // register the shaders 322 shader = (md3Shader_t *) ( (byte *)surf + surf->ofsShaders ); 323 for ( j = 0 ; j < surf->numShaders ; j++, shader++ ) { 324 shader_t *sh; 325 326 sh = R_FindShader( shader->name, LIGHTMAP_NONE, qtrue ); 327 if ( sh->defaultShader ) { 328 shader->shaderIndex = 0; 329 } else { 330 shader->shaderIndex = sh->index; 331 } 332 } 333 334 // swap all the triangles 335 tri = (md3Triangle_t *) ( (byte *)surf + surf->ofsTriangles ); 336 for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) { 337 LL(tri->indexes[0]); 338 LL(tri->indexes[1]); 339 LL(tri->indexes[2]); 340 } 341 342 // swap all the ST 343 st = (md3St_t *) ( (byte *)surf + surf->ofsSt ); 344 for ( j = 0 ; j < surf->numVerts ; j++, st++ ) { 345 st->st[0] = LittleFloat( st->st[0] ); 346 st->st[1] = LittleFloat( st->st[1] ); 347 } 348 349 // swap all the XyzNormals 350 xyz = (md3XyzNormal_t *) ( (byte *)surf + surf->ofsXyzNormals ); 351 for ( j = 0 ; j < surf->numVerts * surf->numFrames ; j++, xyz++ ) 352 { 353 xyz->xyz[0] = LittleShort( xyz->xyz[0] ); 354 xyz->xyz[1] = LittleShort( xyz->xyz[1] ); 355 xyz->xyz[2] = LittleShort( xyz->xyz[2] ); 356 357 xyz->normal = LittleShort( xyz->normal ); 358 } 359 360 361 // find the next surface 362 surf = (md3Surface_t *)( (byte *)surf + surf->ofsEnd ); 363 } 364 365 return qtrue; 366 } 367 368 369 370 /* 371 ================= 372 R_LoadMD4 373 ================= 374 */ 375 static qboolean R_LoadMD4( model_t *mod, void *buffer, const char *mod_name ) { 376 int i, j, k, lodindex; 377 md4Header_t *pinmodel, *md4; 378 md4Frame_t *frame; 379 md4LOD_t *lod; 380 md4Surface_t *surf; 381 md4Triangle_t *tri; 382 md4Vertex_t *v; 383 int version; 384 int size; 385 shader_t *sh; 386 int frameSize; 387 388 pinmodel = (md4Header_t *)buffer; 389 390 version = LittleLong (pinmodel->version); 391 if (version != MD4_VERSION) { 392 ri.Printf( PRINT_WARNING, "R_LoadMD4: %s has wrong version (%i should be %i)\n", 393 mod_name, version, MD4_VERSION); 394 return qfalse; 395 } 396 397 mod->type = MOD_MD4; 398 size = LittleLong(pinmodel->ofsEnd); 399 mod->dataSize += size; 400 md4 = mod->md4 = ri.Hunk_Alloc( size, h_low ); 401 402 Com_Memcpy( md4, buffer, LittleLong(pinmodel->ofsEnd) ); 403 404 LL(md4->ident); 405 LL(md4->version); 406 LL(md4->numFrames); 407 LL(md4->numBones); 408 LL(md4->numLODs); 409 LL(md4->ofsFrames); 410 LL(md4->ofsLODs); 411 LL(md4->ofsEnd); 412 413 if ( md4->numFrames < 1 ) { 414 ri.Printf( PRINT_WARNING, "R_LoadMD4: %s has no frames\n", mod_name ); 415 return qfalse; 416 } 417 418 // we don't need to swap tags in the renderer, they aren't used 419 420 // swap all the frames 421 frameSize = (int)( &((md4Frame_t *)0)->bones[ md4->numBones ] ); 422 for ( i = 0 ; i < md4->numFrames ; i++, frame++) { 423 frame = (md4Frame_t *) ( (byte *)md4 + md4->ofsFrames + i * frameSize ); 424 frame->radius = LittleFloat( frame->radius ); 425 for ( j = 0 ; j < 3 ; j++ ) { 426 frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] ); 427 frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] ); 428 frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] ); 429 } 430 for ( j = 0 ; j < md4->numBones * sizeof( md4Bone_t ) / 4 ; j++ ) { 431 ((float *)frame->bones)[j] = LittleFloat( ((float *)frame->bones)[j] ); 432 } 433 } 434 435 // swap all the LOD's 436 lod = (md4LOD_t *) ( (byte *)md4 + md4->ofsLODs ); 437 for ( lodindex = 0 ; lodindex < md4->numLODs ; lodindex++ ) { 438 439 // swap all the surfaces 440 surf = (md4Surface_t *) ( (byte *)lod + lod->ofsSurfaces ); 441 for ( i = 0 ; i < lod->numSurfaces ; i++) { 442 LL(surf->ident); 443 LL(surf->numTriangles); 444 LL(surf->ofsTriangles); 445 LL(surf->numVerts); 446 LL(surf->ofsVerts); 447 LL(surf->ofsEnd); 448 449 if ( surf->numVerts > SHADER_MAX_VERTEXES ) { 450 ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i verts on a surface (%i)", 451 mod_name, SHADER_MAX_VERTEXES, surf->numVerts ); 452 } 453 if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) { 454 ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i triangles on a surface (%i)", 455 mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles ); 456 } 457 458 // change to surface identifier 459 surf->ident = SF_MD4; 460 461 // lowercase the surface name so skin compares are faster 462 Q_strlwr( surf->name ); 463 464 // register the shaders 465 sh = R_FindShader( surf->shader, LIGHTMAP_NONE, qtrue ); 466 if ( sh->defaultShader ) { 467 surf->shaderIndex = 0; 468 } else { 469 surf->shaderIndex = sh->index; 470 } 471 472 // swap all the triangles 473 tri = (md4Triangle_t *) ( (byte *)surf + surf->ofsTriangles ); 474 for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) { 475 LL(tri->indexes[0]); 476 LL(tri->indexes[1]); 477 LL(tri->indexes[2]); 478 } 479 480 // swap all the vertexes 481 // FIXME 482 // This makes TFC's skeletons work. Shouldn't be necessary anymore, but left 483 // in for reference. 484 //v = (md4Vertex_t *) ( (byte *)surf + surf->ofsVerts + 12); 485 v = (md4Vertex_t *) ( (byte *)surf + surf->ofsVerts); 486 for ( j = 0 ; j < surf->numVerts ; j++ ) { 487 v->normal[0] = LittleFloat( v->normal[0] ); 488 v->normal[1] = LittleFloat( v->normal[1] ); 489 v->normal[2] = LittleFloat( v->normal[2] ); 490 491 v->texCoords[0] = LittleFloat( v->texCoords[0] ); 492 v->texCoords[1] = LittleFloat( v->texCoords[1] ); 493 494 v->numWeights = LittleLong( v->numWeights ); 495 496 for ( k = 0 ; k < v->numWeights ; k++ ) { 497 v->weights[k].boneIndex = LittleLong( v->weights[k].boneIndex ); 498 v->weights[k].boneWeight = LittleFloat( v->weights[k].boneWeight ); 499 v->weights[k].offset[0] = LittleFloat( v->weights[k].offset[0] ); 500 v->weights[k].offset[1] = LittleFloat( v->weights[k].offset[1] ); 501 v->weights[k].offset[2] = LittleFloat( v->weights[k].offset[2] ); 502 } 503 // FIXME 504 // This makes TFC's skeletons work. Shouldn't be necessary anymore, but left 505 // in for reference. 506 //v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights] + 12 ); 507 v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights]); 508 } 509 510 // find the next surface 511 surf = (md4Surface_t *)( (byte *)surf + surf->ofsEnd ); 512 } 513 514 // find the next LOD 515 lod = (md4LOD_t *)( (byte *)lod + lod->ofsEnd ); 516 } 517 518 return qtrue; 519 } 520 521 522 523 524 //============================================================================= 525 526 /* 527 ** RE_BeginRegistration 528 */ 529 void RE_BeginRegistration( glconfig_t *glconfigOut ) { 530 531 R_Init(); 532 533 *glconfigOut = glConfig; 534 535 R_SyncRenderThread(); 536 537 tr.viewCluster = -1; // force markleafs to regenerate 538 R_ClearFlares(); 539 RE_ClearScene(); 540 541 tr.registered = qtrue; 542 543 // NOTE: this sucks, for some reason the first stretch pic is never drawn 544 // without this we'd see a white flash on a level load because the very 545 // first time the level shot would not be drawn 546 RE_StretchPic(0, 0, 0, 0, 0, 0, 1, 1, 0); 547 } 548 549 //============================================================================= 550 551 /* 552 =============== 553 R_ModelInit 554 =============== 555 */ 556 void R_ModelInit( void ) { 557 model_t *mod; 558 559 // leave a space for NULL model 560 tr.numModels = 0; 561 562 mod = R_AllocModel(); 563 mod->type = MOD_BAD; 564 } 565 566 567 /* 568 ================ 569 R_Modellist_f 570 ================ 571 */ 572 void R_Modellist_f( void ) { 573 int i, j; 574 model_t *mod; 575 int total; 576 int lods; 577 578 total = 0; 579 for ( i = 1 ; i < tr.numModels; i++ ) { 580 mod = tr.models[i]; 581 lods = 1; 582 for ( j = 1 ; j < MD3_MAX_LODS ; j++ ) { 583 if ( mod->md3[j] && mod->md3[j] != mod->md3[j-1] ) { 584 lods++; 585 } 586 } 587 ri.Printf( PRINT_ALL, "%8i : (%i) %s\n",mod->dataSize, lods, mod->name ); 588 total += mod->dataSize; 589 } 590 ri.Printf( PRINT_ALL, "%8i : Total models\n", total ); 591 592 #if 0 // not working right with new hunk 593 if ( tr.world ) { 594 ri.Printf( PRINT_ALL, "\n%8i : %s\n", tr.world->dataSize, tr.world->name ); 595 } 596 #endif 597 } 598 599 600 //============================================================================= 601 602 603 /* 604 ================ 605 R_GetTag 606 ================ 607 */ 608 static md3Tag_t *R_GetTag( md3Header_t *mod, int frame, const char *tagName ) { 609 md3Tag_t *tag; 610 int i; 611 612 if ( frame >= mod->numFrames ) { 613 // it is possible to have a bad frame while changing models, so don't error 614 frame = mod->numFrames - 1; 615 } 616 617 tag = (md3Tag_t *)((byte *)mod + mod->ofsTags) + frame * mod->numTags; 618 for ( i = 0 ; i < mod->numTags ; i++, tag++ ) { 619 if ( !strcmp( tag->name, tagName ) ) { 620 return tag; // found it 621 } 622 } 623 624 return NULL; 625 } 626 627 /* 628 ================ 629 R_LerpTag 630 ================ 631 */ 632 int R_LerpTag( orientation_t *tag, qhandle_t handle, int startFrame, int endFrame, 633 float frac, const char *tagName ) { 634 md3Tag_t *start, *end; 635 int i; 636 float frontLerp, backLerp; 637 model_t *model; 638 639 model = R_GetModelByHandle( handle ); 640 if ( !model->md3[0] ) { 641 AxisClear( tag->axis ); 642 VectorClear( tag->origin ); 643 return qfalse; 644 } 645 646 start = R_GetTag( model->md3[0], startFrame, tagName ); 647 end = R_GetTag( model->md3[0], endFrame, tagName ); 648 if ( !start || !end ) { 649 AxisClear( tag->axis ); 650 VectorClear( tag->origin ); 651 return qfalse; 652 } 653 654 frontLerp = frac; 655 backLerp = 1.0f - frac; 656 657 for ( i = 0 ; i < 3 ; i++ ) { 658 tag->origin[i] = start->origin[i] * backLerp + end->origin[i] * frontLerp; 659 tag->axis[0][i] = start->axis[0][i] * backLerp + end->axis[0][i] * frontLerp; 660 tag->axis[1][i] = start->axis[1][i] * backLerp + end->axis[1][i] * frontLerp; 661 tag->axis[2][i] = start->axis[2][i] * backLerp + end->axis[2][i] * frontLerp; 662 } 663 VectorNormalize( tag->axis[0] ); 664 VectorNormalize( tag->axis[1] ); 665 VectorNormalize( tag->axis[2] ); 666 return qtrue; 667 } 668 669 670 /* 671 ==================== 672 R_ModelBounds 673 ==================== 674 */ 675 void R_ModelBounds( qhandle_t handle, vec3_t mins, vec3_t maxs ) { 676 model_t *model; 677 md3Header_t *header; 678 md3Frame_t *frame; 679 680 model = R_GetModelByHandle( handle ); 681 682 if ( model->bmodel ) { 683 VectorCopy( model->bmodel->bounds[0], mins ); 684 VectorCopy( model->bmodel->bounds[1], maxs ); 685 return; 686 } 687 688 if ( !model->md3[0] ) { 689 VectorClear( mins ); 690 VectorClear( maxs ); 691 return; 692 } 693 694 header = model->md3[0]; 695 696 frame = (md3Frame_t *)( (byte *)header + header->ofsFrames ); 697 698 VectorCopy( frame->bounds[0], mins ); 699 VectorCopy( frame->bounds[1], maxs ); 700 }