This repository has been archived on 2022-06-27. You can view files and clone it, but cannot push or open issues or pull requests.
Xash3DArchive/engine/common/model.c

610 lines
13 KiB
C
Raw Normal View History

2011-05-09 22:00:00 +02:00
/*
model.c - modelloader
Copyright (C) 2007 Uncle Mike
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
2010-05-22 22:00:00 +02:00
2011-04-06 22:00:00 +02:00
#include "mod_local.h"
2010-09-10 22:00:00 +02:00
#include "sprite.h"
2010-05-22 22:00:00 +02:00
#include "mathlib.h"
2017-06-23 23:00:00 +02:00
#include "alias.h"
2010-09-10 22:00:00 +02:00
#include "studio.h"
#include "wadfile.h"
2010-11-21 22:00:00 +01:00
#include "world.h"
2010-12-03 22:00:00 +01:00
#include "gl_local.h"
2012-05-21 22:00:00 +02:00
#include "features.h"
2014-04-01 22:00:00 +02:00
#include "client.h"
2018-04-16 23:00:00 +02:00
#include "server.h"
2012-05-21 22:00:00 +02:00
2018-02-25 22:00:00 +01:00
static model_info_t mod_crcinfo[MAX_MODELS];
static model_t mod_known[MAX_MODELS];
static int mod_numknown = 0;
2018-02-05 22:00:00 +01:00
byte *com_studiocache; // cache for submodels
2012-02-11 21:00:00 +01:00
convar_t *mod_studiocache;
2016-03-17 22:00:00 +01:00
convar_t *r_wadtextures;
2018-05-26 23:00:00 +02:00
convar_t *r_showhull;
2010-08-12 22:00:00 +02:00
model_t *loadmodel;
2010-05-22 22:00:00 +02:00
/*
===============================================================================
2010-12-08 22:00:00 +01:00
MOD COMMON UTILS
2010-05-22 22:00:00 +02:00
===============================================================================
2018-02-05 22:00:00 +01:00
*/
2010-05-22 22:00:00 +02:00
/*
2018-02-05 22:00:00 +01:00
================
Mod_Modellist_f
================
2010-05-22 22:00:00 +02:00
*/
2018-02-05 22:00:00 +01:00
static void Mod_Modellist_f( void )
2010-05-22 22:00:00 +02:00
{
2018-02-05 22:00:00 +01:00
int i, nummodels;
model_t *mod;
2010-05-22 22:00:00 +02:00
2018-02-28 22:00:00 +01:00
Con_Printf( "\n" );
Con_Printf( "-----------------------------------\n" );
2010-05-22 22:00:00 +02:00
2018-02-25 22:00:00 +01:00
for( i = nummodels = 0, mod = mod_known; i < mod_numknown; i++, mod++ )
2010-05-22 22:00:00 +02:00
{
2018-02-05 22:00:00 +01:00
if( !mod->name[0] )
continue; // free slot
2018-02-28 22:00:00 +01:00
Con_Printf( "%s\n", mod->name );
2018-02-05 22:00:00 +01:00
nummodels++;
2010-05-22 22:00:00 +02:00
}
2018-02-05 22:00:00 +01:00
2018-02-28 22:00:00 +01:00
Con_Printf( "-----------------------------------\n" );
Con_Printf( "%i total models\n", nummodels );
Con_Printf( "\n" );
2010-05-22 22:00:00 +02:00
}
2010-12-06 22:00:00 +01:00
/*
2018-02-05 22:00:00 +01:00
================
Mod_FreeUserData
================
2010-12-06 22:00:00 +01:00
*/
2018-02-05 22:00:00 +01:00
static void Mod_FreeUserData( model_t *mod )
2010-12-06 22:00:00 +01:00
{
2018-02-25 22:00:00 +01:00
// ignore submodels and freed models
if( !mod->name[0] || mod->name[0] == '*' )
2018-02-05 22:00:00 +01:00
return;
2010-12-06 22:00:00 +01:00
2018-02-05 22:00:00 +01:00
if( host.type == HOST_DEDICATED )
2010-12-06 22:00:00 +01:00
{
2018-02-05 22:00:00 +01:00
if( svgame.physFuncs.Mod_ProcessUserData != NULL )
2010-12-08 22:00:00 +01:00
{
2018-02-05 22:00:00 +01:00
// let the server.dll free custom data
svgame.physFuncs.Mod_ProcessUserData( mod, false, NULL );
}
}
else
{
if( clgame.drawFuncs.Mod_ProcessUserData != NULL )
{
// let the client.dll free custom data
clgame.drawFuncs.Mod_ProcessUserData( mod, false, NULL );
2010-12-08 22:00:00 +01:00
}
2010-12-06 22:00:00 +01:00
}
}
2010-05-22 22:00:00 +02:00
/*
2018-02-05 22:00:00 +01:00
================
Mod_FreeModel
================
2010-05-22 22:00:00 +02:00
*/
2018-02-05 22:00:00 +01:00
static void Mod_FreeModel( model_t *mod )
2010-05-22 22:00:00 +02:00
{
2018-02-05 22:00:00 +01:00
// already freed?
if( !mod || !mod->name[0] )
2010-05-22 22:00:00 +02:00
return;
2018-03-09 22:00:00 +01:00
if( mod->name[0] != '*' )
Mod_FreeUserData( mod );
2016-11-28 22:00:00 +01:00
2018-02-05 22:00:00 +01:00
// select the properly unloader
switch( mod->type )
2010-05-31 22:00:00 +02:00
{
2018-02-05 22:00:00 +01:00
case mod_sprite:
Mod_UnloadSpriteModel( mod );
break;
case mod_studio:
Mod_UnloadStudioModel( mod );
break;
case mod_brush:
Mod_UnloadBrushModel( mod );
break;
case mod_alias:
Mod_UnloadAliasModel( mod );
break;
2010-05-31 22:00:00 +02:00
}
2018-02-25 22:00:00 +01:00
memset( mod, 0, sizeof( *mod ));
2018-02-05 22:00:00 +01:00
}
2010-05-31 22:00:00 +02:00
2018-02-05 22:00:00 +01:00
/*
===============================================================================
2017-10-12 23:00:00 +02:00
2018-04-16 23:00:00 +02:00
MODEL INITIALIZE\SHUTDOWN
2010-12-09 22:00:00 +01:00
2018-02-05 22:00:00 +01:00
===============================================================================
*/
2019-02-21 22:00:00 +01:00
/*
================
Mod_Init
================
*/
2018-02-05 22:00:00 +01:00
void Mod_Init( void )
{
com_studiocache = Mem_AllocPool( "Studio Cache" );
mod_studiocache = Cvar_Get( "r_studiocache", "1", FCVAR_ARCHIVE, "enables studio cache for speedup tracing hitboxes" );
r_wadtextures = Cvar_Get( "r_wadtextures", "0", 0, "completely ignore textures in the bsp-file if enabled" );
2018-05-26 23:00:00 +02:00
r_showhull = Cvar_Get( "r_showhull", "0", 0, "draw collision hulls 1-3" );
2010-05-22 22:00:00 +02:00
2018-02-05 22:00:00 +01:00
Cmd_AddCommand( "mapstats", Mod_PrintWorldStats_f, "show stats for currently loaded map" );
Cmd_AddCommand( "modellist", Mod_Modellist_f, "display loaded models list" );
2011-04-05 22:00:00 +02:00
2018-02-05 22:00:00 +01:00
Mod_ResetStudioAPI ();
Mod_InitStudioHull ();
}
2018-02-02 22:00:00 +01:00
2018-02-25 22:00:00 +01:00
/*
================
Mod_FreeAll
================
*/
void Mod_FreeAll( void )
2018-02-05 22:00:00 +01:00
{
int i;
2012-02-12 21:00:00 +01:00
2018-05-26 23:00:00 +02:00
Mod_ReleaseHullPolygons();
2018-04-16 23:00:00 +02:00
for( i = 0; i < mod_numknown; i++ )
Mod_FreeModel( &mod_known[i] );
2018-02-25 22:00:00 +01:00
mod_numknown = 0;
}
/*
================
Mod_ClearUserData
================
*/
2018-02-05 22:00:00 +01:00
void Mod_ClearUserData( void )
{
int i;
2017-07-20 23:00:00 +02:00
2018-02-25 22:00:00 +01:00
for( i = 0; i < mod_numknown; i++ )
Mod_FreeUserData( &mod_known[i] );
2018-02-05 22:00:00 +01:00
}
2010-12-12 22:00:00 +01:00
2018-02-25 22:00:00 +01:00
/*
================
Mod_Shutdown
================
*/
2018-02-05 22:00:00 +01:00
void Mod_Shutdown( void )
{
2018-02-25 22:00:00 +01:00
Mod_FreeAll();
2018-02-05 22:00:00 +01:00
Mem_FreePool( &com_studiocache );
}
2011-07-22 22:00:00 +02:00
2018-02-05 22:00:00 +01:00
/*
===============================================================================
2017-10-12 23:00:00 +02:00
2018-02-05 22:00:00 +01:00
MODELS MANAGEMENT
2010-05-22 22:00:00 +02:00
2018-02-05 22:00:00 +01:00
===============================================================================
*/
2010-12-08 22:00:00 +01:00
/*
==================
Mod_FindName
2010-08-25 22:00:00 +02:00
2018-10-05 23:00:00 +02:00
never return NULL
2010-12-08 22:00:00 +01:00
==================
*/
2018-02-25 22:00:00 +01:00
model_t *Mod_FindName( const char *filename, qboolean trackCRC )
2010-10-18 22:00:00 +02:00
{
2018-02-25 22:00:00 +01:00
char modname[MAX_QPATH];
2010-10-18 22:00:00 +02:00
model_t *mod;
2011-04-17 22:00:00 +02:00
int i;
2011-03-31 22:00:00 +02:00
2018-02-25 22:00:00 +01:00
Q_strncpy( modname, filename, sizeof( modname ));
2010-10-18 22:00:00 +02:00
// search the currently loaded models
2018-02-25 22:00:00 +01:00
for( i = 0, mod = mod_known; i < mod_numknown; i++, mod++ )
2010-12-08 22:00:00 +01:00
{
2018-02-25 22:00:00 +01:00
if( !Q_stricmp( mod->name, modname ))
2010-10-18 22:00:00 +02:00
{
2018-02-28 22:00:00 +01:00
if( mod->mempool || mod->name[0] == '*' )
2018-02-25 22:00:00 +01:00
mod->needload = NL_PRESENT;
else mod->needload = NL_NEEDS_LOADED;
2010-10-18 22:00:00 +02:00
return mod;
}
}
// find a free model slot spot
2018-02-25 22:00:00 +01:00
for( i = 0, mod = mod_known; i < mod_numknown; i++, mod++ )
2010-12-08 22:00:00 +01:00
if( !mod->name[0] ) break; // this is a valid spot
2010-10-18 22:00:00 +02:00
2018-02-25 22:00:00 +01:00
if( i == mod_numknown )
2010-10-18 22:00:00 +02:00
{
2018-02-25 22:00:00 +01:00
if( mod_numknown == MAX_MODELS )
2018-04-16 23:00:00 +02:00
Host_Error( "MAX_MODELS limit exceeded (%d)\n", MAX_MODELS );
2018-02-25 22:00:00 +01:00
mod_numknown++;
2010-10-18 22:00:00 +02:00
}
2010-12-08 22:00:00 +01:00
// copy name, so model loader can find model file
2018-02-25 22:00:00 +01:00
Q_strncpy( mod->name, modname, sizeof( mod->name ));
if( trackCRC ) mod_crcinfo[i].flags = FCRC_SHOULD_CHECKSUM;
else mod_crcinfo[i].flags = 0;
2018-02-28 22:00:00 +01:00
mod->needload = NL_NEEDS_LOADED;
2018-02-25 22:00:00 +01:00
mod_crcinfo[i].initialCRC = 0;
2010-12-08 22:00:00 +01:00
return mod;
}
/*
==================
Mod_LoadModel
Loads a model into the cache
==================
*/
2010-12-27 22:00:00 +01:00
model_t *Mod_LoadModel( model_t *mod, qboolean crash )
2010-12-08 22:00:00 +01:00
{
2018-04-16 23:00:00 +02:00
char tempname[MAX_QPATH];
2018-02-20 22:00:00 +01:00
long length = 0;
qboolean loaded;
byte *buf;
model_info_t *p;
2010-12-08 22:00:00 +01:00
2018-03-13 22:00:00 +01:00
ASSERT( mod != NULL );
2010-12-08 22:00:00 +01:00
// check if already loaded (or inline bmodel)
if( mod->mempool || mod->name[0] == '*' )
2018-02-25 22:00:00 +01:00
{
mod->needload = NL_PRESENT;
2010-12-08 22:00:00 +01:00
return mod;
2018-02-25 22:00:00 +01:00
}
2010-12-08 22:00:00 +01:00
2018-02-28 22:00:00 +01:00
ASSERT( mod->needload == NL_NEEDS_LOADED );
2013-04-25 22:00:00 +02:00
// store modelname to show error
Q_strncpy( tempname, mod->name, sizeof( tempname ));
COM_FixSlashes( tempname );
2011-10-14 22:00:00 +02:00
2018-02-20 22:00:00 +01:00
buf = FS_LoadFile( tempname, &length, false );
2011-07-07 22:00:00 +02:00
2010-10-18 22:00:00 +02:00
if( !buf )
{
2016-11-17 22:00:00 +01:00
memset( mod, 0, sizeof( model_t ));
2011-07-07 22:00:00 +02:00
2018-03-13 22:00:00 +01:00
if( crash ) Host_Error( "%s couldn't load\n", tempname );
else Con_Printf( S_ERROR "%s couldn't load\n", tempname );
2011-07-07 22:00:00 +02:00
2010-10-18 22:00:00 +02:00
return NULL;
}
2018-03-14 22:00:00 +01:00
Con_Reportf( "loading %s\n", mod->name );
2018-02-28 22:00:00 +01:00
mod->needload = NL_PRESENT;
2010-10-18 22:00:00 +02:00
mod->type = mod_bad;
loadmodel = mod;
// call the apropriate loader
2010-11-21 22:00:00 +01:00
switch( *(uint *)buf )
2010-10-18 22:00:00 +02:00
{
case IDSTUDIOHEADER:
2011-07-22 22:00:00 +02:00
Mod_LoadStudioModel( mod, buf, &loaded );
2010-10-18 22:00:00 +02:00
break;
case IDSPRITEHEADER:
2012-01-27 21:00:00 +01:00
Mod_LoadSpriteModel( mod, buf, &loaded, 0 );
2010-10-18 22:00:00 +02:00
break;
2017-06-23 23:00:00 +02:00
case IDALIASHEADER:
Mod_LoadAliasModel( mod, buf, &loaded );
break;
2010-12-08 22:00:00 +01:00
case Q1BSP_VERSION:
case HLBSP_VERSION:
2017-07-31 23:00:00 +02:00
case QBSP2_VERSION:
2011-07-22 22:00:00 +02:00
Mod_LoadBrushModel( mod, buf, &loaded );
2010-10-18 22:00:00 +02:00
break;
2011-09-19 22:00:00 +02:00
default:
Mem_Free( buf );
2018-03-13 22:00:00 +01:00
if( crash ) Host_Error( "%s has unknown format\n", tempname );
else Con_Printf( S_ERROR "%s has unknown format\n", tempname );
2011-09-19 22:00:00 +02:00
return NULL;
2010-10-18 22:00:00 +02:00
}
2011-07-22 22:00:00 +02:00
if( !loaded )
2010-10-18 22:00:00 +02:00
{
2010-12-02 22:00:00 +01:00
Mod_FreeModel( mod );
2014-05-08 22:00:00 +02:00
Mem_Free( buf );
2010-10-18 22:00:00 +02:00
2018-03-13 22:00:00 +01:00
if( crash ) Host_Error( "%s couldn't load\n", tempname );
else Con_Printf( S_ERROR "%s couldn't load\n", tempname );
2014-05-08 22:00:00 +02:00
2010-10-18 22:00:00 +02:00
return NULL;
}
2016-12-09 22:00:00 +01:00
else
2014-04-01 22:00:00 +02:00
{
2018-03-03 22:00:00 +01:00
if( world.loading )
SetBits( mod->flags, MODEL_WORLD ); // mark worldmodel
2016-12-09 22:00:00 +01:00
if( host.type == HOST_DEDICATED )
{
if( svgame.physFuncs.Mod_ProcessUserData != NULL )
{
// let the server.dll load custom data
svgame.physFuncs.Mod_ProcessUserData( mod, true, buf );
}
}
else
{
if( clgame.drawFuncs.Mod_ProcessUserData != NULL )
{
// let the client.dll load custom data
clgame.drawFuncs.Mod_ProcessUserData( mod, true, buf );
}
}
2014-04-01 22:00:00 +02:00
}
2018-02-25 22:00:00 +01:00
p = &mod_crcinfo[mod - mod_known];
mod->needload = NL_PRESENT;
2018-02-20 22:00:00 +01:00
if( FBitSet( p->flags, FCRC_SHOULD_CHECKSUM ))
{
CRC32_t currentCRC;
CRC32_Init( &currentCRC );
CRC32_ProcessBuffer( &currentCRC, buf, length );
2018-03-05 22:00:00 +01:00
currentCRC = CRC32_Final( currentCRC );
2018-02-20 22:00:00 +01:00
if( FBitSet( p->flags, FCRC_CHECKSUM_DONE ))
{
if( currentCRC != p->initialCRC )
2018-04-16 23:00:00 +02:00
Host_Error( "%s has a bad checksum\n", tempname );
2018-02-20 22:00:00 +01:00
}
else
{
SetBits( p->flags, FCRC_CHECKSUM_DONE );
p->initialCRC = currentCRC;
}
}
2014-05-08 22:00:00 +02:00
Mem_Free( buf );
2010-10-18 22:00:00 +02:00
return mod;
}
2010-12-08 22:00:00 +01:00
/*
==================
Mod_ForName
2010-08-12 22:00:00 +02:00
2010-12-08 22:00:00 +01:00
Loads in a model for the given name
==================
*/
2018-02-25 22:00:00 +01:00
model_t *Mod_ForName( const char *name, qboolean crash, qboolean trackCRC )
2010-12-08 22:00:00 +01:00
{
2018-10-05 23:00:00 +02:00
model_t *mod;
if( !COM_CheckString( name ))
return NULL;
mod = Mod_FindName( name, trackCRC );
2010-12-27 22:00:00 +01:00
return Mod_LoadModel( mod, crash );
2010-05-22 22:00:00 +02:00
}
/*
==================
2018-02-25 22:00:00 +01:00
Mod_PurgeStudioCache
2010-05-22 22:00:00 +02:00
2018-02-25 22:00:00 +01:00
free studio cache on change level
2010-05-22 22:00:00 +02:00
==================
*/
2018-04-16 23:00:00 +02:00
static void Mod_PurgeStudioCache( void )
2010-05-22 22:00:00 +02:00
{
2010-12-19 22:00:00 +01:00
int i;
2018-05-26 23:00:00 +02:00
// refresh hull data
SetBits( r_showhull->flags, FCVAR_CHANGED );
Mod_ReleaseHullPolygons();
2018-03-09 22:00:00 +01:00
// release previois map
Mod_FreeModel( mod_known ); // world is stuck on slot #0 always
2018-02-25 22:00:00 +01:00
// we should release all the world submodels
// and clear studio sequences
for( i = 1; i < mod_numknown; i++ )
2010-05-22 22:00:00 +02:00
{
2018-02-25 22:00:00 +01:00
if( mod_known[i].type == mod_studio )
mod_known[i].submodels = NULL;
if( mod_known[i].name[0] == '*' )
Mod_FreeModel( &mod_known[i] );
2018-02-28 22:00:00 +01:00
mod_known[i].needload = NL_UNREFERENCED;
2010-05-22 22:00:00 +02:00
}
2018-02-25 22:00:00 +01:00
Mem_EmptyPool( com_studiocache );
Mod_ClearStudioCache();
}
2010-12-19 22:00:00 +01:00
2018-02-25 22:00:00 +01:00
/*
==================
Mod_LoadWorld
Loads in the map and all submodels
==================
*/
model_t *Mod_LoadWorld( const char *name, qboolean preload )
{
model_t *pworld;
// already loaded?
if( !Q_stricmp( mod_known->name, name ))
return mod_known;
// free sequence files on studiomodels
Mod_PurgeStudioCache();
2010-05-22 22:00:00 +02:00
// load the newmap
2010-12-27 22:00:00 +01:00
world.loading = true;
2018-02-25 22:00:00 +01:00
pworld = Mod_FindName( name, false );
if( preload ) Mod_LoadModel( pworld, true );
2010-12-27 22:00:00 +01:00
world.loading = false;
2018-02-25 22:00:00 +01:00
ASSERT( pworld == mod_known );
return pworld;
2010-05-22 22:00:00 +02:00
}
2010-12-08 22:00:00 +01:00
/*
==================
Mod_FreeUnused
Purge all unused models
==================
*/
void Mod_FreeUnused( void )
2010-05-22 22:00:00 +02:00
{
2010-08-12 22:00:00 +02:00
model_t *mod;
2010-05-22 22:00:00 +02:00
int i;
2018-03-07 22:00:00 +01:00
// never tries to release worldmodel
for( i = 1, mod = &mod_known[1]; i < mod_numknown; i++, mod++ )
2010-05-22 22:00:00 +02:00
{
2018-02-28 22:00:00 +01:00
if( mod->needload == NL_UNREFERENCED && COM_CheckString( mod->name ))
2010-12-02 22:00:00 +01:00
Mod_FreeModel( mod );
2010-05-22 22:00:00 +02:00
}
}
2018-02-05 22:00:00 +01:00
/*
===============================================================================
MODEL ROUTINES
===============================================================================
*/
2010-11-15 22:00:00 +01:00
/*
===============
Mod_Calloc
===============
*/
void *Mod_Calloc( int number, size_t size )
{
2013-11-03 21:00:00 +01:00
cache_user_t *cu;
2011-09-28 22:00:00 +02:00
2010-11-15 22:00:00 +01:00
if( number <= 0 || size <= 0 ) return NULL;
2018-05-26 23:00:00 +02:00
cu = (cache_user_t *)Mem_Calloc( com_studiocache, sizeof( cache_user_t ) + number * size );
2011-09-28 22:00:00 +02:00
cu->data = (void *)cu; // make sure what cu->data is not NULL
return cu;
2010-11-15 22:00:00 +01:00
}
/*
===============
Mod_CacheCheck
===============
*/
void *Mod_CacheCheck( cache_user_t *c )
{
2010-12-09 22:00:00 +01:00
return Cache_Check( com_studiocache, c );
2010-11-15 22:00:00 +01:00
}
/*
===============
Mod_LoadCacheFile
===============
*/
2011-04-08 22:00:00 +02:00
void Mod_LoadCacheFile( const char *filename, cache_user_t *cu )
2010-11-15 22:00:00 +01:00
{
2018-02-25 22:00:00 +01:00
char modname[MAX_QPATH];
size_t size;
2010-11-15 22:00:00 +01:00
byte *buf;
2018-02-12 22:00:00 +01:00
Assert( cu != NULL );
2010-11-15 22:00:00 +01:00
2018-02-25 22:00:00 +01:00
if( !COM_CheckString( filename ))
return;
2010-11-15 22:00:00 +01:00
2018-02-25 22:00:00 +01:00
Q_strncpy( modname, filename, sizeof( modname ));
COM_FixSlashes( modname );
2010-11-15 22:00:00 +01:00
2018-02-25 22:00:00 +01:00
buf = FS_LoadFile( modname, &size, false );
2011-08-21 22:00:00 +02:00
if( !buf || !size ) Host_Error( "LoadCacheFile: ^1can't load %s^7\n", filename );
2018-05-26 23:00:00 +02:00
cu->data = Mem_Malloc( com_studiocache, size );
2016-11-17 22:00:00 +01:00
memcpy( cu->data, buf, size );
2010-11-15 22:00:00 +01:00
Mem_Free( buf );
}
/*
===============
2017-07-02 23:00:00 +02:00
Mod_AliasExtradata
2010-11-15 22:00:00 +01:00
===============
*/
2017-07-02 23:00:00 +02:00
void *Mod_AliasExtradata( model_t *mod )
{
if( mod && mod->type == mod_alias )
return mod->cache.data;
return NULL;
}
/*
===============
Mod_StudioExtradata
===============
*/
void *Mod_StudioExtradata( model_t *mod )
2010-11-15 22:00:00 +01:00
{
if( mod && mod->type == mod_studio )
2010-11-21 22:00:00 +01:00
return mod->cache.data;
2010-11-15 22:00:00 +01:00
return NULL;
2010-12-08 22:00:00 +01:00
}
2018-02-20 22:00:00 +01:00
/*
==================
Mod_ValidateCRC
==================
*/
qboolean Mod_ValidateCRC( const char *name, CRC32_t crc )
{
model_info_t *p;
model_t *mod;
mod = Mod_FindName( name, true );
2018-02-25 22:00:00 +01:00
p = &mod_crcinfo[mod - mod_known];
2018-02-20 22:00:00 +01:00
if( !FBitSet( p->flags, FCRC_CHECKSUM_DONE ))
return true;
if( p->initialCRC == crc )
return true;
return false;
}
/*
==================
Mod_NeedCRC
==================
*/
void Mod_NeedCRC( const char *name, qboolean needCRC )
{
model_t *mod;
model_info_t *p;
mod = Mod_FindName( name, true );
2018-02-25 22:00:00 +01:00
p = &mod_crcinfo[mod - mod_known];
2018-02-20 22:00:00 +01:00
if( needCRC ) SetBits( p->flags, FCRC_SHOULD_CHECKSUM );
else ClearBits( p->flags, FCRC_SHOULD_CHECKSUM );
2010-05-22 22:00:00 +02:00
}