00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "tr_local.h"
00025
00026 #define LL(x) x=LittleLong(x)
00027
00028 static qboolean R_LoadMD3 (model_t *mod, int lod, void *buffer, const char *name );
00029 static qboolean R_LoadMD4 (model_t *mod, void *buffer, const char *name );
00030
00031 model_t *loadmodel;
00032
00033
00034
00035
00036 model_t *R_GetModelByHandle( qhandle_t index ) {
00037 model_t *mod;
00038
00039
00040 if ( index < 1 || index >= tr.numModels ) {
00041 return tr.models[0];
00042 }
00043
00044 mod = tr.models[index];
00045
00046 return mod;
00047 }
00048
00049
00050
00051
00052
00053
00054 model_t *R_AllocModel( void ) {
00055 model_t *mod;
00056
00057 if ( tr.numModels == MAX_MOD_KNOWN ) {
00058 return NULL;
00059 }
00060
00061 mod = ri.Hunk_Alloc( sizeof( *tr.models[tr.numModels] ), h_low );
00062 mod->index = tr.numModels;
00063 tr.models[tr.numModels] = mod;
00064 tr.numModels++;
00065
00066 return mod;
00067 }
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 qhandle_t RE_RegisterModel( const char *name ) {
00082 model_t *mod;
00083 unsigned *buf;
00084 int lod;
00085 int ident;
00086 qboolean loaded;
00087 qhandle_t hModel;
00088 int numLoaded;
00089
00090 if ( !name || !name[0] ) {
00091 ri.Printf( PRINT_ALL, "RE_RegisterModel: NULL name\n" );
00092 return 0;
00093 }
00094
00095 if ( strlen( name ) >= MAX_QPATH ) {
00096 Com_Printf( "Model name exceeds MAX_QPATH\n" );
00097 return 0;
00098 }
00099
00100
00101
00102
00103 for ( hModel = 1 ; hModel < tr.numModels; hModel++ ) {
00104 mod = tr.models[hModel];
00105 if ( !strcmp( mod->name, name ) ) {
00106 if( mod->type == MOD_BAD ) {
00107 return 0;
00108 }
00109 return hModel;
00110 }
00111 }
00112
00113
00114
00115 if ( ( mod = R_AllocModel() ) == NULL ) {
00116 ri.Printf( PRINT_WARNING, "RE_RegisterModel: R_AllocModel() failed for '%s'\n", name);
00117 return 0;
00118 }
00119
00120
00121 Q_strncpyz( mod->name, name, sizeof( mod->name ) );
00122
00123
00124
00125 R_SyncRenderThread();
00126
00127 mod->numLods = 0;
00128
00129
00130
00131
00132 numLoaded = 0;
00133
00134 for ( lod = MD3_MAX_LODS - 1 ; lod >= 0 ; lod-- ) {
00135 char filename[1024];
00136
00137 strcpy( filename, name );
00138
00139 if ( lod != 0 ) {
00140 char namebuf[80];
00141
00142 if ( strrchr( filename, '.' ) ) {
00143 *strrchr( filename, '.' ) = 0;
00144 }
00145 sprintf( namebuf, "_%d.md3", lod );
00146 strcat( filename, namebuf );
00147 }
00148
00149 ri.FS_ReadFile( filename, (void **)&buf );
00150 if ( !buf ) {
00151 continue;
00152 }
00153
00154 loadmodel = mod;
00155
00156 ident = LittleLong(*(unsigned *)buf);
00157 if ( ident == MD4_IDENT ) {
00158 loaded = R_LoadMD4( mod, buf, name );
00159 } else {
00160 if ( ident != MD3_IDENT ) {
00161 ri.Printf (PRINT_WARNING,"RE_RegisterModel: unknown fileid for %s\n", name);
00162 goto fail;
00163 }
00164
00165 loaded = R_LoadMD3( mod, lod, buf, name );
00166 }
00167
00168 ri.FS_FreeFile (buf);
00169
00170 if ( !loaded ) {
00171 if ( lod == 0 ) {
00172 goto fail;
00173 } else {
00174 break;
00175 }
00176 } else {
00177 mod->numLods++;
00178 numLoaded++;
00179
00180
00181
00182
00183
00184
00185 }
00186 }
00187
00188 if ( numLoaded ) {
00189
00190
00191 for ( lod-- ; lod >= 0 ; lod-- ) {
00192 mod->numLods++;
00193 mod->md3[lod] = mod->md3[lod+1];
00194 }
00195
00196 return mod->index;
00197 }
00198 #ifdef _DEBUG
00199 else {
00200 ri.Printf (PRINT_WARNING,"RE_RegisterModel: couldn't load %s\n", name);
00201 }
00202 #endif
00203
00204 fail:
00205
00206
00207 mod->type = MOD_BAD;
00208 return 0;
00209 }
00210
00211
00212
00213
00214
00215
00216
00217 static qboolean R_LoadMD3 (model_t *mod, int lod, void *buffer, const char *mod_name ) {
00218 int i, j;
00219 md3Header_t *pinmodel;
00220 md3Frame_t *frame;
00221 md3Surface_t *surf;
00222 md3Shader_t *shader;
00223 md3Triangle_t *tri;
00224 md3St_t *st;
00225 md3XyzNormal_t *xyz;
00226 md3Tag_t *tag;
00227 int version;
00228 int size;
00229
00230 pinmodel = (md3Header_t *)buffer;
00231
00232 version = LittleLong (pinmodel->version);
00233 if (version != MD3_VERSION) {
00234 ri.Printf( PRINT_WARNING, "R_LoadMD3: %s has wrong version (%i should be %i)\n",
00235 mod_name, version, MD3_VERSION);
00236 return qfalse;
00237 }
00238
00239 mod->type = MOD_MESH;
00240 size = LittleLong(pinmodel->ofsEnd);
00241 mod->dataSize += size;
00242 mod->md3[lod] = ri.Hunk_Alloc( size, h_low );
00243
00244 Com_Memcpy (mod->md3[lod], buffer, LittleLong(pinmodel->ofsEnd) );
00245
00246 LL(mod->md3[lod]->ident);
00247 LL(mod->md3[lod]->version);
00248 LL(mod->md3[lod]->numFrames);
00249 LL(mod->md3[lod]->numTags);
00250 LL(mod->md3[lod]->numSurfaces);
00251 LL(mod->md3[lod]->ofsFrames);
00252 LL(mod->md3[lod]->ofsTags);
00253 LL(mod->md3[lod]->ofsSurfaces);
00254 LL(mod->md3[lod]->ofsEnd);
00255
00256 if ( mod->md3[lod]->numFrames < 1 ) {
00257 ri.Printf( PRINT_WARNING, "R_LoadMD3: %s has no frames\n", mod_name );
00258 return qfalse;
00259 }
00260
00261
00262 frame = (md3Frame_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsFrames );
00263 for ( i = 0 ; i < mod->md3[lod]->numFrames ; i++, frame++) {
00264 frame->radius = LittleFloat( frame->radius );
00265 for ( j = 0 ; j < 3 ; j++ ) {
00266 frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] );
00267 frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] );
00268 frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] );
00269 }
00270 }
00271
00272
00273 tag = (md3Tag_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsTags );
00274 for ( i = 0 ; i < mod->md3[lod]->numTags * mod->md3[lod]->numFrames ; i++, tag++) {
00275 for ( j = 0 ; j < 3 ; j++ ) {
00276 tag->origin[j] = LittleFloat( tag->origin[j] );
00277 tag->axis[0][j] = LittleFloat( tag->axis[0][j] );
00278 tag->axis[1][j] = LittleFloat( tag->axis[1][j] );
00279 tag->axis[2][j] = LittleFloat( tag->axis[2][j] );
00280 }
00281 }
00282
00283
00284 surf = (md3Surface_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsSurfaces );
00285 for ( i = 0 ; i < mod->md3[lod]->numSurfaces ; i++) {
00286
00287 LL(surf->ident);
00288 LL(surf->flags);
00289 LL(surf->numFrames);
00290 LL(surf->numShaders);
00291 LL(surf->numTriangles);
00292 LL(surf->ofsTriangles);
00293 LL(surf->numVerts);
00294 LL(surf->ofsShaders);
00295 LL(surf->ofsSt);
00296 LL(surf->ofsXyzNormals);
00297 LL(surf->ofsEnd);
00298
00299 if ( surf->numVerts > SHADER_MAX_VERTEXES ) {
00300 ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i verts on a surface (%i)",
00301 mod_name, SHADER_MAX_VERTEXES, surf->numVerts );
00302 }
00303 if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) {
00304 ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i triangles on a surface (%i)",
00305 mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles );
00306 }
00307
00308
00309 surf->ident = SF_MD3;
00310
00311
00312 Q_strlwr( surf->name );
00313
00314
00315
00316 j = strlen( surf->name );
00317 if ( j > 2 && surf->name[j-2] == '_' ) {
00318 surf->name[j-2] = 0;
00319 }
00320
00321
00322 shader = (md3Shader_t *) ( (byte *)surf + surf->ofsShaders );
00323 for ( j = 0 ; j < surf->numShaders ; j++, shader++ ) {
00324 shader_t *sh;
00325
00326 sh = R_FindShader( shader->name, LIGHTMAP_NONE, qtrue );
00327 if ( sh->defaultShader ) {
00328 shader->shaderIndex = 0;
00329 } else {
00330 shader->shaderIndex = sh->index;
00331 }
00332 }
00333
00334
00335 tri = (md3Triangle_t *) ( (byte *)surf + surf->ofsTriangles );
00336 for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) {
00337 LL(tri->indexes[0]);
00338 LL(tri->indexes[1]);
00339 LL(tri->indexes[2]);
00340 }
00341
00342
00343 st = (md3St_t *) ( (byte *)surf + surf->ofsSt );
00344 for ( j = 0 ; j < surf->numVerts ; j++, st++ ) {
00345 st->st[0] = LittleFloat( st->st[0] );
00346 st->st[1] = LittleFloat( st->st[1] );
00347 }
00348
00349
00350 xyz = (md3XyzNormal_t *) ( (byte *)surf + surf->ofsXyzNormals );
00351 for ( j = 0 ; j < surf->numVerts * surf->numFrames ; j++, xyz++ )
00352 {
00353 xyz->xyz[0] = LittleShort( xyz->xyz[0] );
00354 xyz->xyz[1] = LittleShort( xyz->xyz[1] );
00355 xyz->xyz[2] = LittleShort( xyz->xyz[2] );
00356
00357 xyz->normal = LittleShort( xyz->normal );
00358 }
00359
00360
00361
00362 surf = (md3Surface_t *)( (byte *)surf + surf->ofsEnd );
00363 }
00364
00365 return qtrue;
00366 }
00367
00368
00369
00370
00371
00372
00373
00374
00375 static qboolean R_LoadMD4( model_t *mod, void *buffer, const char *mod_name ) {
00376 int i, j, k, lodindex;
00377 md4Header_t *pinmodel, *md4;
00378 md4Frame_t *frame;
00379 md4LOD_t *lod;
00380 md4Surface_t *surf;
00381 md4Triangle_t *tri;
00382 md4Vertex_t *v;
00383 int version;
00384 int size;
00385 shader_t *sh;
00386 int frameSize;
00387
00388 pinmodel = (md4Header_t *)buffer;
00389
00390 version = LittleLong (pinmodel->version);
00391 if (version != MD4_VERSION) {
00392 ri.Printf( PRINT_WARNING, "R_LoadMD4: %s has wrong version (%i should be %i)\n",
00393 mod_name, version, MD4_VERSION);
00394 return qfalse;
00395 }
00396
00397 mod->type = MOD_MD4;
00398 size = LittleLong(pinmodel->ofsEnd);
00399 mod->dataSize += size;
00400 md4 = mod->md4 = ri.Hunk_Alloc( size, h_low );
00401
00402 Com_Memcpy( md4, buffer, LittleLong(pinmodel->ofsEnd) );
00403
00404 LL(md4->ident);
00405 LL(md4->version);
00406 LL(md4->numFrames);
00407 LL(md4->numBones);
00408 LL(md4->numLODs);
00409 LL(md4->ofsFrames);
00410 LL(md4->ofsLODs);
00411 LL(md4->ofsEnd);
00412
00413 if ( md4->numFrames < 1 ) {
00414 ri.Printf( PRINT_WARNING, "R_LoadMD4: %s has no frames\n", mod_name );
00415 return qfalse;
00416 }
00417
00418
00419
00420
00421 frameSize = (int)( &((md4Frame_t *)0)->bones[ md4->numBones ] );
00422 for ( i = 0 ; i < md4->numFrames ; i++, frame++) {
00423 frame = (md4Frame_t *) ( (byte *)md4 + md4->ofsFrames + i * frameSize );
00424 frame->radius = LittleFloat( frame->radius );
00425 for ( j = 0 ; j < 3 ; j++ ) {
00426 frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] );
00427 frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] );
00428 frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] );
00429 }
00430 for ( j = 0 ; j < md4->numBones * sizeof( md4Bone_t ) / 4 ; j++ ) {
00431 ((float *)frame->bones)[j] = LittleFloat( ((float *)frame->bones)[j] );
00432 }
00433 }
00434
00435
00436 lod = (md4LOD_t *) ( (byte *)md4 + md4->ofsLODs );
00437 for ( lodindex = 0 ; lodindex < md4->numLODs ; lodindex++ ) {
00438
00439
00440 surf = (md4Surface_t *) ( (byte *)lod + lod->ofsSurfaces );
00441 for ( i = 0 ; i < lod->numSurfaces ; i++) {
00442 LL(surf->ident);
00443 LL(surf->numTriangles);
00444 LL(surf->ofsTriangles);
00445 LL(surf->numVerts);
00446 LL(surf->ofsVerts);
00447 LL(surf->ofsEnd);
00448
00449 if ( surf->numVerts > SHADER_MAX_VERTEXES ) {
00450 ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i verts on a surface (%i)",
00451 mod_name, SHADER_MAX_VERTEXES, surf->numVerts );
00452 }
00453 if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) {
00454 ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i triangles on a surface (%i)",
00455 mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles );
00456 }
00457
00458
00459 surf->ident = SF_MD4;
00460
00461
00462 Q_strlwr( surf->name );
00463
00464
00465 sh = R_FindShader( surf->shader, LIGHTMAP_NONE, qtrue );
00466 if ( sh->defaultShader ) {
00467 surf->shaderIndex = 0;
00468 } else {
00469 surf->shaderIndex = sh->index;
00470 }
00471
00472
00473 tri = (md4Triangle_t *) ( (byte *)surf + surf->ofsTriangles );
00474 for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) {
00475 LL(tri->indexes[0]);
00476 LL(tri->indexes[1]);
00477 LL(tri->indexes[2]);
00478 }
00479
00480
00481
00482
00483
00484
00485 v = (md4Vertex_t *) ( (byte *)surf + surf->ofsVerts);
00486 for ( j = 0 ; j < surf->numVerts ; j++ ) {
00487 v->normal[0] = LittleFloat( v->normal[0] );
00488 v->normal[1] = LittleFloat( v->normal[1] );
00489 v->normal[2] = LittleFloat( v->normal[2] );
00490
00491 v->texCoords[0] = LittleFloat( v->texCoords[0] );
00492 v->texCoords[1] = LittleFloat( v->texCoords[1] );
00493
00494 v->numWeights = LittleLong( v->numWeights );
00495
00496 for ( k = 0 ; k < v->numWeights ; k++ ) {
00497 v->weights[k].boneIndex = LittleLong( v->weights[k].boneIndex );
00498 v->weights[k].boneWeight = LittleFloat( v->weights[k].boneWeight );
00499 v->weights[k].offset[0] = LittleFloat( v->weights[k].offset[0] );
00500 v->weights[k].offset[1] = LittleFloat( v->weights[k].offset[1] );
00501 v->weights[k].offset[2] = LittleFloat( v->weights[k].offset[2] );
00502 }
00503
00504
00505
00506
00507 v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights]);
00508 }
00509
00510
00511 surf = (md4Surface_t *)( (byte *)surf + surf->ofsEnd );
00512 }
00513
00514
00515 lod = (md4LOD_t *)( (byte *)lod + lod->ofsEnd );
00516 }
00517
00518 return qtrue;
00519 }
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529 void RE_BeginRegistration( glconfig_t *glconfigOut ) {
00530
00531 R_Init();
00532
00533 *glconfigOut = glConfig;
00534
00535 R_SyncRenderThread();
00536
00537 tr.viewCluster = -1;
00538 R_ClearFlares();
00539 RE_ClearScene();
00540
00541 tr.registered = qtrue;
00542
00543
00544
00545
00546 RE_StretchPic(0, 0, 0, 0, 0, 0, 1, 1, 0);
00547 }
00548
00549
00550
00551
00552
00553
00554
00555
00556 void R_ModelInit( void ) {
00557 model_t *mod;
00558
00559
00560 tr.numModels = 0;
00561
00562 mod = R_AllocModel();
00563 mod->type = MOD_BAD;
00564 }
00565
00566
00567
00568
00569
00570
00571
00572 void R_Modellist_f( void ) {
00573 int i, j;
00574 model_t *mod;
00575 int total;
00576 int lods;
00577
00578 total = 0;
00579 for ( i = 1 ; i < tr.numModels; i++ ) {
00580 mod = tr.models[i];
00581 lods = 1;
00582 for ( j = 1 ; j < MD3_MAX_LODS ; j++ ) {
00583 if ( mod->md3[j] && mod->md3[j] != mod->md3[j-1] ) {
00584 lods++;
00585 }
00586 }
00587 ri.Printf( PRINT_ALL, "%8i : (%i) %s\n",mod->dataSize, lods, mod->name );
00588 total += mod->dataSize;
00589 }
00590 ri.Printf( PRINT_ALL, "%8i : Total models\n", total );
00591
00592 #if 0 // not working right with new hunk
00593 if ( tr.world ) {
00594 ri.Printf( PRINT_ALL, "\n%8i : %s\n", tr.world->dataSize, tr.world->name );
00595 }
00596 #endif
00597 }
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608 static md3Tag_t *R_GetTag( md3Header_t *mod, int frame, const char *tagName ) {
00609 md3Tag_t *tag;
00610 int i;
00611
00612 if ( frame >= mod->numFrames ) {
00613
00614 frame = mod->numFrames - 1;
00615 }
00616
00617 tag = (md3Tag_t *)((byte *)mod + mod->ofsTags) + frame * mod->numTags;
00618 for ( i = 0 ; i < mod->numTags ; i++, tag++ ) {
00619 if ( !strcmp( tag->name, tagName ) ) {
00620 return tag;
00621 }
00622 }
00623
00624 return NULL;
00625 }
00626
00627
00628
00629
00630
00631
00632 int R_LerpTag( orientation_t *tag, qhandle_t handle, int startFrame, int endFrame,
00633 float frac, const char *tagName ) {
00634 md3Tag_t *start, *end;
00635 int i;
00636 float frontLerp, backLerp;
00637 model_t *model;
00638
00639 model = R_GetModelByHandle( handle );
00640 if ( !model->md3[0] ) {
00641 AxisClear( tag->axis );
00642 VectorClear( tag->origin );
00643 return qfalse;
00644 }
00645
00646 start = R_GetTag( model->md3[0], startFrame, tagName );
00647 end = R_GetTag( model->md3[0], endFrame, tagName );
00648 if ( !start || !end ) {
00649 AxisClear( tag->axis );
00650 VectorClear( tag->origin );
00651 return qfalse;
00652 }
00653
00654 frontLerp = frac;
00655 backLerp = 1.0f - frac;
00656
00657 for ( i = 0 ; i < 3 ; i++ ) {
00658 tag->origin[i] = start->origin[i] * backLerp + end->origin[i] * frontLerp;
00659 tag->axis[0][i] = start->axis[0][i] * backLerp + end->axis[0][i] * frontLerp;
00660 tag->axis[1][i] = start->axis[1][i] * backLerp + end->axis[1][i] * frontLerp;
00661 tag->axis[2][i] = start->axis[2][i] * backLerp + end->axis[2][i] * frontLerp;
00662 }
00663 VectorNormalize( tag->axis[0] );
00664 VectorNormalize( tag->axis[1] );
00665 VectorNormalize( tag->axis[2] );
00666 return qtrue;
00667 }
00668
00669
00670
00671
00672
00673
00674
00675 void R_ModelBounds( qhandle_t handle, vec3_t mins, vec3_t maxs ) {
00676 model_t *model;
00677 md3Header_t *header;
00678 md3Frame_t *frame;
00679
00680 model = R_GetModelByHandle( handle );
00681
00682 if ( model->bmodel ) {
00683 VectorCopy( model->bmodel->bounds[0], mins );
00684 VectorCopy( model->bmodel->bounds[1], maxs );
00685 return;
00686 }
00687
00688 if ( !model->md3[0] ) {
00689 VectorClear( mins );
00690 VectorClear( maxs );
00691 return;
00692 }
00693
00694 header = model->md3[0];
00695
00696 frame = (md3Frame_t *)( (byte *)header + header->ofsFrames );
00697
00698 VectorCopy( frame->bounds[0], mins );
00699 VectorCopy( frame->bounds[1], maxs );
00700 }