X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=model_shared.c;h=d892a36d3b5aeac9dc9640e41a196677e99af3bc;hb=bff2055635d6a0b18173b0b7a8f5aa7741d1dd4e;hp=ea85c5891d5f84cf6af494466701605c183f7aa2;hpb=cc63b89849022ef37ef113a7dc9489c2e846bd1b;p=xonotic%2Fdarkplaces.git diff --git a/model_shared.c b/model_shared.c index ea85c589..d892a36d 100644 --- a/model_shared.c +++ b/model_shared.c @@ -8,7 +8,7 @@ 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. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -25,54 +25,180 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" model_t *loadmodel; -char loadname[32]; // for hunk tags -void Mod_LoadSpriteModel (model_t *mod, void *buffer); -void Mod_LoadBrushModel (model_t *mod, void *buffer); -void Mod_LoadAliasModel (model_t *mod, void *buffer); -void Mod_LoadQ2AliasModel (model_t *mod, void *buffer); -model_t *Mod_LoadModel (model_t *mod, qboolean crash); - -#define MAX_MOD_KNOWN 512 +// LordHavoc: increased from 512 to 2048 +#define MAX_MOD_KNOWN 2048 model_t mod_known[MAX_MOD_KNOWN]; -int mod_numknown; -extern void Mod_BrushInit(); -extern void Mod_AliasInit(); -extern void Mod_SpriteInit(); +void mod_start() +{ + int i; + for (i = 0;i < MAX_MOD_KNOWN;i++) + if (mod_known[i].name[0]) + Mod_UnloadModel(&mod_known[i]); +} + +void mod_shutdown() +{ + int i; + for (i = 0;i < MAX_MOD_KNOWN;i++) + if (mod_known[i].name[0]) + Mod_UnloadModel(&mod_known[i]); +} + +void mod_newmap() +{ +} /* =============== Mod_Init =============== */ +static void Mod_Print (void); +static void Mod_Flush (void); void Mod_Init (void) { Mod_BrushInit(); Mod_AliasInit(); Mod_SpriteInit(); + + Cmd_AddCommand ("modellist", Mod_Print); + Cmd_AddCommand ("modelflush", Mod_Flush); +} + +void Mod_RenderInit(void) +{ + R_RegisterModule("Models", mod_start, mod_shutdown, mod_newmap); +} + +void Mod_FreeModel (model_t *mod) +{ + R_FreeTexturePool(&mod->texturepool); + Mem_FreePool(&mod->mempool); + + // clear the struct to make it available + memset(mod, 0, sizeof(model_t)); +} + +void Mod_UnloadModel (model_t *mod) +{ + char name[MAX_QPATH]; + qboolean isworldmodel; + strcpy(name, mod->name); + isworldmodel = mod->isworldmodel; + Mod_FreeModel(mod); + strcpy(mod->name, name); + mod->isworldmodel = isworldmodel; + mod->needload = true; } /* -=============== -Mod_Init +================== +Mod_LoadModel -Caches the data if needed -=============== +Loads a model +================== */ -void *Mod_Extradata (model_t *mod) +static model_t *Mod_LoadModel (model_t *mod, qboolean crash, qboolean checkdisk, qboolean isworldmodel) { - void *r; - - r = Cache_Check (&mod->cache); - if (r) - return r; - - Mod_LoadModel (mod, true); - - if (!mod->cache.data) - Host_Error ("Mod_Extradata: caching failed"); - return mod->cache.data; + int crc; + void *buf; + char tempname[MAX_QPATH]; + + mod->used = true; + + if (mod->name[0] == '*') // submodel + return mod; + + if (checkdisk) + { + // load the file + buf = COM_LoadFile (mod->name, false); + if (!buf) + { + if (crash) + Host_Error ("Mod_LoadModel: %s not found", mod->name); // LordHavoc: Sys_Error was *ANNOYING* + return NULL; + } + + crc = CRC_Block(buf, com_filesize); + + if (!mod->needload && mod->crc == crc && mod->isworldmodel == isworldmodel) + { + Mem_Free(buf); + return mod; // already loaded + } + + Con_DPrintf("loading model %s\n", mod->name); + } + else + { + if (!mod->needload && mod->isworldmodel == isworldmodel) + return mod; // already loaded + + Con_DPrintf("loading model %s\n", mod->name); + + buf = COM_LoadFile (mod->name, false); + if (!buf) + { + if (crash) + Host_Error ("Mod_LoadModel: %s not found", mod->name); // LordHavoc: Sys_Error was *ANNOYING* + return NULL; + } + crc = CRC_Block(buf, com_filesize); + } + + // make sure nothing got trashed + Mem_CheckSentinelsGlobal(); + + // allocate a new model + loadmodel = mod; + + // LordHavoc: clear the model struct + strcpy(tempname, mod->name); + Mod_FreeModel(mod); + + strcpy(mod->name, tempname); + mod->isworldmodel = isworldmodel; + mod->needload = false; + mod->used = true; + mod->crc = crc; + + // all models use memory, so allocate a memory pool + mod->mempool = Mem_AllocPool(mod->name); + // all models load textures, so allocate a texture pool + mod->texturepool = R_AllocTexturePool(); + + // call the apropriate loader + if (!memcmp(buf, "IDPO" , 4)) Mod_LoadAliasModel (mod, buf); + else if (!memcmp(buf, "IDP2" , 4)) Mod_LoadQ2AliasModel(mod, buf); + else if (!memcmp(buf, "ZYMOTIC" , 7)) Mod_LoadZymoticModel(mod, buf); + else if (!memcmp(buf, "IDSP" , 4)) Mod_LoadSpriteModel (mod, buf); + else Mod_LoadBrushModel (mod, buf); + + Mem_Free(buf); + + // make sure nothing got trashed + Mem_CheckSentinelsGlobal(); + + return mod; +} + +void Mod_CheckLoaded (model_t *mod) +{ + if (mod) + { + if (!mod->needload) + { + if (mod->type == mod_invalid) + Host_Error("Mod_CheckLoaded: invalid model\n"); + mod->used = true; + return; + } + + Mod_LoadModel(mod, true, true, mod->isworldmodel); + } } /* @@ -81,13 +207,37 @@ Mod_ClearAll =================== */ void Mod_ClearAll (void) +{ + /* + int i; + model_t *mod; + + for (i = 0, mod = mod_known;i < MAX_MOD_KNOWN;i++, mod++) + if (mod->name[0]) + if (mod->usesheap) + Mod_FreeModel(mod); + */ +} + +void Mod_ClearUsed(void) +{ + int i; + model_t *mod; + + for (i = 0, mod = mod_known;i < MAX_MOD_KNOWN;i++, mod++) + if (mod->name[0]) + mod->used = false; +} + +void Mod_PurgeUnused(void) { int i; model_t *mod; - - for (i=0 , mod=mod_known ; itype != mod_alias) - mod->needload = true; + + for (i = 0, mod = mod_known;i < MAX_MOD_KNOWN;i++, mod++) + if (mod->name[0]) + if (!mod->used) + Mod_FreeModel(mod); } /* @@ -99,28 +249,38 @@ Mod_FindName model_t *Mod_FindName (char *name) { int i; - model_t *mod; - + model_t *mod, *freemod; + if (!name[0]) Host_Error ("Mod_ForName: NULL name"); - -// + // search the currently loaded models -// - for (i=0 , mod=mod_known ; iname, name) ) - break; - - if (i == mod_numknown) + freemod = NULL; + for (i = 0, mod = mod_known;i < MAX_MOD_KNOWN;i++, mod++) + { + if (mod->name[0]) + { + if (!strcmp (mod->name, name)) + { + mod->used = true; + return mod; + } + } + else if (freemod == NULL) + freemod = mod; + } + + if (freemod) { - if (mod_numknown == MAX_MOD_KNOWN) - Host_Error ("mod_numknown == MAX_MOD_KNOWN"); + mod = freemod; strcpy (mod->name, name); mod->needload = true; - mod_numknown++; + mod->used = true; + return mod; } - return mod; + Host_Error ("Mod_FindName: ran out of models\n"); + return NULL; } /* @@ -132,78 +292,9 @@ Mod_TouchModel void Mod_TouchModel (char *name) { model_t *mod; - - mod = Mod_FindName (name); - - if (!mod->needload) - { - if (mod->type == mod_alias) - Cache_Check (&mod->cache); - } -} - -/* -================== -Mod_LoadModel - -Loads a model into the cache -================== -*/ -model_t *Mod_LoadModel (model_t *mod, qboolean crash) -{ - void *d; - unsigned *buf; - byte stackbuf[1024]; // avoid dirtying the cache heap - - if (!mod->needload) - { - if (mod->type == mod_alias) - { - d = Cache_Check (&mod->cache); - if (d) - return mod; - } - else - return mod; // not cached at all - } - -// load the file - buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf), false); - if (!buf) - { - if (crash) - Host_Error ("Mod_NumForName: %s not found", mod->name); // LordHavoc: Sys_Error was *ANNOYING* - return NULL; - } - -// allocate a new model - COM_FileBase (mod->name, loadname); - - loadmodel = mod; -// call the apropriate loader - mod->needload = false; - - switch (LittleLong(*(unsigned *)buf)) - { - case IDPOLYHEADER: - Mod_LoadAliasModel (mod, buf); - break; - - case MD2IDALIASHEADER: // LordHavoc: added Quake2 model support - Mod_LoadQ2AliasModel (mod, buf); - break; - - case IDSPRITEHEADER: - Mod_LoadSpriteModel (mod, buf); - break; - - default: - Mod_LoadBrushModel (mod, buf); - break; - } - - return mod; + mod = Mod_FindName (name); + mod->used = true; } /* @@ -213,13 +304,14 @@ Mod_ForName Loads in a model for the given name ================== */ -model_t *Mod_ForName (char *name, qboolean crash) +model_t *Mod_ForName (char *name, qboolean crash, qboolean checkdisk, qboolean isworldmodel) { model_t *mod; - + mod = Mod_FindName (name); - - return Mod_LoadModel (mod, crash); + mod->used = true; + + return Mod_LoadModel (mod, crash, checkdisk, isworldmodel); } byte *mod_base; @@ -229,6 +321,7 @@ byte *mod_base; RadiusFromBounds ================= */ +/* float RadiusFromBounds (vec3_t mins, vec3_t maxs) { int i; @@ -239,6 +332,7 @@ float RadiusFromBounds (vec3_t mins, vec3_t maxs) return Length (corner); } +*/ //============================================================================= @@ -247,16 +341,24 @@ float RadiusFromBounds (vec3_t mins, vec3_t maxs) Mod_Print ================ */ -void Mod_Print (void) +static void Mod_Print (void) { int i; model_t *mod; - Con_Printf ("Cached models:\n"); - for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++) - { - Con_Printf ("%8p : %s\n",mod->cache.data, mod->name); - } + Con_Printf ("Loaded models:\n"); + for (i = 0, mod = mod_known;i < MAX_MOD_KNOWN;i++, mod++) + if (mod->name[0]) + Con_Printf ("%4iK %s\n", mod->mempool ? (mod->mempool->totalsize + 1023) / 1024 : 0, mod->name); } +static void Mod_Flush (void) +{ + int i; + + Con_Printf ("Unloading models\n"); + for (i = 0;i < MAX_MOD_KNOWN;i++) + if (mod_known[i].name[0]) + Mod_UnloadModel(&mod_known[i]); +}