diff options
Diffstat (limited to 'src/renderer/tr_model.c')
| -rw-r--r-- | src/renderer/tr_model.c | 416 |
1 files changed, 291 insertions, 125 deletions
diff --git a/src/renderer/tr_model.c b/src/renderer/tr_model.c index b02d52a4..2933e7e0 100644 --- a/src/renderer/tr_model.c +++ b/src/renderer/tr_model.c @@ -26,13 +26,194 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define LL(x) x=LittleLong(x) -static qboolean R_LoadMD3 (model_t *mod, int lod, void *buffer, const char *name ); -static qboolean R_LoadMD4 (model_t *mod, void *buffer, const char *name ); +static qboolean R_LoadMD3(model_t *mod, int lod, void *buffer, const char *name ); +static qboolean R_LoadMD4(model_t *mod, void *buffer, const char *name ); #ifdef RAVENMD4 -static qboolean R_LoadMDR (model_t *mod, void *buffer, int filesize, const char *name ); +static qboolean R_LoadMDR(model_t *mod, void *buffer, int filesize, const char *name ); #endif -model_t *loadmodel; +/* +==================== +R_RegisterMD3 +==================== +*/ +qhandle_t R_RegisterMD3(const char *name, model_t *mod) +{ + union { + unsigned *u; + void *v; + } buf; + int lod; + int ident; + qboolean loaded = qfalse; + int numLoaded; + char filename[MAX_QPATH], namebuf[MAX_QPATH+20]; + char *fext, defex[] = "md3"; + + numLoaded = 0; + + strcpy(filename, name); + + fext = strchr(filename, '.'); + if(!fext) + fext = defex; + else + { + *fext = '\0'; + fext++; + } + + for (lod = MD3_MAX_LODS - 1 ; lod >= 0 ; lod--) + { + if(lod) + Com_sprintf(namebuf, sizeof(namebuf), "%s_%d.%s", filename, lod, fext); + else + Com_sprintf(namebuf, sizeof(namebuf), "%s.%s", filename, fext); + + ri.FS_ReadFile( namebuf, &buf.v ); + if(!buf.u) + continue; + + ident = LittleLong(* (unsigned *) buf.u); + if (ident == MD4_IDENT) + loaded = R_LoadMD4(mod, buf.u, name); + else + { + if (ident == MD3_IDENT) + loaded = R_LoadMD3(mod, lod, buf.u, name); + else + ri.Printf(PRINT_WARNING,"RE_RegisterMD3: unknown fileid for %s\n", name); + } + + ri.FS_FreeFile(buf.v); + + if(loaded) + { + mod->numLods++; + numLoaded++; + } + else + break; + } + + if(numLoaded) + { + // duplicate into higher lod spots that weren't + // loaded, in case the user changes r_lodbias on the fly + for(lod--; lod >= 0; lod--) + { + mod->numLods++; + mod->md3[lod] = mod->md3[lod + 1]; + } + + return mod->index; + } + +#ifdef _DEBUG + ri.Printf(PRINT_WARNING,"RE_RegisterMD3: couldn't load %s\n", name); +#endif + + mod->type = MOD_BAD; + return 0; +} + +#ifdef RAVENMD4 +/* +==================== +R_RegisterMDR +==================== +*/ +qhandle_t R_RegisterMDR(const char *name, model_t *mod) +{ + union { + unsigned *u; + void *v; + } buf; + int ident; + qboolean loaded = qfalse; + int filesize; + + filesize = ri.FS_ReadFile(name, (void **) &buf.v); + if(!buf.u) + { + mod->type = MOD_BAD; + return 0; + } + + ident = LittleLong(*(unsigned *)buf.u); + if(ident == MDR_IDENT) + loaded = R_LoadMDR(mod, buf.u, filesize, name); + + ri.FS_FreeFile (buf.v); + + if(!loaded) + { + ri.Printf(PRINT_WARNING,"RE_RegisterMDR: couldn't load mdr file %s\n", name); + mod->type = MOD_BAD; + return 0; + } + + return mod->index; +} +#endif + +/* +==================== +R_RegisterIQM +==================== +*/ +qhandle_t R_RegisterIQM(const char *name, model_t *mod) +{ + union { + unsigned *u; + void *v; + } buf; + qboolean loaded = qfalse; + int filesize; + + filesize = ri.FS_ReadFile(name, (void **) &buf.v); + if(!buf.u) + { + mod->type = MOD_BAD; + return 0; + } + + loaded = R_LoadIQM(mod, buf.u, filesize, name); + + ri.FS_FreeFile (buf.v); + + if(!loaded) + { + ri.Printf(PRINT_WARNING,"RE_RegisterIQM: couldn't load mdr file %s\n", name); + mod->type = MOD_BAD; + return 0; + } + + return mod->index; +} + + +typedef struct +{ + char *ext; + qhandle_t (*ModelLoader)( const char *, model_t * ); +} modelExtToLoaderMap_t; + +// Note that the ordering indicates the order of preference used +// when there are multiple models of different formats available +static modelExtToLoaderMap_t modelLoaders[ ] = +{ +#ifdef RAVENMD4 + { "mdr", R_RegisterMDR }, +#endif + { "md4", R_RegisterMD3 }, + { "md3", R_RegisterMD3 }, + { "iqm", R_RegisterIQM } +}; + +static int numModelLoaders = ARRAY_LEN(modelLoaders); + +//=============================================================================== /* ** R_GetModelByHandle @@ -84,16 +265,13 @@ asked for again. */ qhandle_t RE_RegisterModel( const char *name ) { model_t *mod; - union { - unsigned *u; - void *v; - } buf; - int lod; - int ident; - qboolean loaded = qfalse; qhandle_t hModel; - int numLoaded; - char *fext, defex[] = "md3", filename[MAX_QPATH], namebuf[MAX_QPATH+20]; + qboolean orgNameFailed = qfalse; + int orgLoader = -1; + int i; + char localName[ MAX_QPATH ]; + const char *ext; + char *altName; if ( !name || !name[0] ) { ri.Printf( PRINT_ALL, "RE_RegisterModel: NULL name\n" ); @@ -132,125 +310,75 @@ qhandle_t RE_RegisterModel( const char *name ) { // make sure the render thread is stopped R_SyncRenderThread(); + mod->type = MOD_BAD; mod->numLods = 0; // // load the files // - numLoaded = 0; + Q_strncpyz( localName, name, MAX_QPATH ); - strcpy(filename, name); + ext = COM_GetExtension( localName ); - fext = strchr(filename, '.'); - if(!fext) - fext = defex; - else + if( *ext ) { - *fext = '\0'; - fext++; - } - -#ifdef RAVENMD4 - if(!Q_stricmp(fext, "mdr")) - { - int filesize; - - filesize = ri.FS_ReadFile(name, (void **) &buf.v); - if(!buf.u) + // Look for the correct loader and use it + for( i = 0; i < numModelLoaders; i++ ) { - ri.Printf (PRINT_WARNING,"RE_RegisterModel: couldn't load %s\n", name); - mod->type = MOD_BAD; - return 0; + if( !Q_stricmp( ext, modelLoaders[ i ].ext ) ) + { + // Load + hModel = modelLoaders[ i ].ModelLoader( localName, mod ); + break; + } } - - ident = LittleLong(*(unsigned *)buf.u); - if(ident == MDR_IDENT) - loaded = R_LoadMDR(mod, buf.u, filesize, name); - ri.FS_FreeFile (buf.v); - - if(!loaded) + // A loader was found + if( i < numModelLoaders ) { - ri.Printf(PRINT_WARNING,"RE_RegisterModel: couldn't load mdr file %s\n", name); - mod->type = MOD_BAD; - return 0; + if( !hModel ) + { + // Loader failed, most likely because the file isn't there; + // try again without the extension + orgNameFailed = qtrue; + orgLoader = i; + COM_StripExtension( name, localName, MAX_QPATH ); + } + else + { + // Something loaded + return mod->index; + } } - - return mod->index; } -#endif - - fext = defex; - - for ( lod = MD3_MAX_LODS - 1 ; lod >= 0 ; lod-- ) { - if ( lod ) - Com_sprintf(namebuf, sizeof(namebuf), "%s_%d.%s", filename, lod, fext); - else - Com_sprintf(namebuf, sizeof(namebuf), "%s.%s", filename, fext); - ri.FS_ReadFile( namebuf, &buf.v ); - if ( !buf.u ) { + // Try and find a suitable match using all + // the model formats supported + for( i = 0; i < numModelLoaders; i++ ) + { + if (i == orgLoader) continue; - } - - loadmodel = mod; - - ident = LittleLong(*(unsigned *)buf.u); - if ( ident == MD4_IDENT ) { - loaded = R_LoadMD4( mod, buf.u, name ); - } else { - if ( ident != MD3_IDENT ) { - ri.Printf (PRINT_WARNING,"RE_RegisterModel: unknown fileid for %s\n", name); - goto fail; - } - loaded = R_LoadMD3( mod, lod, buf.u, name ); - } - - ri.FS_FreeFile (buf.v); + altName = va( "%s.%s", localName, modelLoaders[ i ].ext ); - if ( !loaded ) { - if ( lod == 0 ) { - goto fail; - } else { - break; + // Load + hModel = modelLoaders[ i ].ModelLoader( altName, mod ); + + if( hModel ) + { + if( orgNameFailed ) + { + ri.Printf( PRINT_DEVELOPER, "WARNING: %s not present, using %s instead\n", + name, altName ); } - } else { - mod->numLods++; - numLoaded++; - // if we have a valid model and are biased - // so that we won't see any higher detail ones, - // stop loading them -// if ( lod <= r_lodbias->integer ) { -// break; -// } - } - } - if ( numLoaded ) { - // duplicate into higher lod spots that weren't - // loaded, in case the user changes r_lodbias on the fly - for ( lod-- ; lod >= 0 ; lod-- ) { - mod->numLods++; - mod->md3[lod] = mod->md3[lod+1]; + break; } - - return mod->index; - } -#ifdef _DEBUG - else { - ri.Printf (PRINT_WARNING,"RE_RegisterModel: couldn't load %s\n", name); } -#endif -fail: - // we still keep the model_t around, so if the model name is asked for - // again, we won't bother scanning the filesystem - mod->type = MOD_BAD; - return 0; + return hModel; } - /* ================= R_LoadMD3 @@ -780,7 +908,7 @@ static qboolean R_LoadMD4( model_t *mod, void *buffer, const char *mod_name ) { mod->type = MOD_MD4; size = LittleLong(pinmodel->ofsEnd); mod->dataSize += size; - md4 = mod->md4 = ri.Hunk_Alloc( size, h_low ); + mod->modelData = md4 = ri.Hunk_Alloc( size, h_low ); Com_Memcpy(md4, buffer, size); @@ -1071,16 +1199,20 @@ int R_LerpTag( orientation_t *tag, qhandle_t handle, int startFrame, int endFram if ( !model->md3[0] ) { #ifdef RAVENMD4 - if(model->md4) + if(model->type == MOD_MDR) { start = &start_space; end = &end_space; - R_GetAnimTag((mdrHeader_t *) model->md4, startFrame, tagName, start); - R_GetAnimTag((mdrHeader_t *) model->md4, endFrame, tagName, end); + R_GetAnimTag((mdrHeader_t *) model->modelData, startFrame, tagName, start); + R_GetAnimTag((mdrHeader_t *) model->modelData, endFrame, tagName, end); } else #endif - { + if( model->type == MOD_IQM ) { + return R_IQMLerpTag( tag, model->modelData, + startFrame, endFrame, + frac, tagName ); + } else { AxisClear( tag->axis ); VectorClear( tag->origin ); @@ -1122,28 +1254,62 @@ R_ModelBounds */ void R_ModelBounds( qhandle_t handle, vec3_t mins, vec3_t maxs ) { model_t *model; - md3Header_t *header; - md3Frame_t *frame; model = R_GetModelByHandle( handle ); - if ( model->bmodel ) { + if(model->type == MOD_BRUSH) { VectorCopy( model->bmodel->bounds[0], mins ); VectorCopy( model->bmodel->bounds[1], maxs ); + return; - } + } else if (model->type == MOD_MESH) { + md3Header_t *header; + md3Frame_t *frame; + + header = model->md3[0]; + frame = (md3Frame_t *) ((byte *)header + header->ofsFrames); - if ( !model->md3[0] ) { - VectorClear( mins ); - VectorClear( maxs ); + VectorCopy( frame->bounds[0], mins ); + VectorCopy( frame->bounds[1], maxs ); + return; - } + } else if (model->type == MOD_MD4) { + md4Header_t *header; + md4Frame_t *frame; + + header = (md4Header_t *)model->modelData; + frame = (md4Frame_t *) ((byte *)header + header->ofsFrames); + + VectorCopy( frame->bounds[0], mins ); + VectorCopy( frame->bounds[1], maxs ); + + return; +#ifdef RAVENMD4 + } else if (model->type == MOD_MDR) { + mdrHeader_t *header; + mdrFrame_t *frame; - header = model->md3[0]; + header = (mdrHeader_t *)model->modelData; + frame = (mdrFrame_t *) ((byte *)header + header->ofsFrames); - frame = (md3Frame_t *)( (byte *)header + header->ofsFrames ); + VectorCopy( frame->bounds[0], mins ); + VectorCopy( frame->bounds[1], maxs ); + + return; +#endif + } else if(model->type == MOD_IQM) { + iqmData_t *iqmData; + + iqmData = model->modelData; - VectorCopy( frame->bounds[0], mins ); - VectorCopy( frame->bounds[1], maxs ); -} + if(iqmData->bounds) + { + VectorCopy(iqmData->bounds, mins); + VectorCopy(iqmData->bounds + 3, maxs); + return; + } + } + VectorClear( mins ); + VectorClear( maxs ); +} |
