From: cloudwalk Date: Thu, 9 Jul 2020 16:58:42 +0000 (+0000) Subject: Refactor the model loading code to use an array of structs for each format X-Git-Url: http://git.xonotic.org/?a=commitdiff_plain;h=2be46db656e453c09ca0b7318f7185d59b2275ee;p=xonotic%2Fdarkplaces.git Refactor the model loading code to use an array of structs for each format Allows to cleanly and explicitly define a model and what the loader should look for. git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@12793 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/bspfile.h b/bspfile.h index b1bdc350..f918d794 100644 --- a/bspfile.h +++ b/bspfile.h @@ -25,6 +25,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define BSPVERSION 29 +#define HLBSPVERSION 30 +#define _2PSBVERSION ('2' + 'P' * 256 + 'S' * 65536 + 'B' * 16777216) +#define BSP2VERSION ('B' + 'S' * 256 + 'P' * 65536 + '2' * 16777216) typedef struct lump_s { diff --git a/model_brush.c b/model_brush.c index b56321f5..934791be 100644 --- a/model_brush.c +++ b/model_brush.c @@ -3848,6 +3848,28 @@ static void Mod_Q1BSP_RoundUpToHullSize(dp_model_t *cmodel, const vec3_t inmins, void Mod_CollisionBIH_TraceLineAgainstSurfaces(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask); +void Mod_2PSB_Load(dp_model_t *mod, void *buffer, void *bufferend) +{ + mod->brush.isbsp2 = true; + mod->brush.isbsp2rmqe = true; // like bsp2 except leaf/node bounds are 16bit (unexpanded) + mod->modeldatatypestring = "Q1BSP2rmqe"; + Mod_Q1BSP_Load(mod, buffer, bufferend); +} + +void Mod_BSP2_Load(dp_model_t *mod, void *buffer, void *bufferend) +{ + mod->brush.isbsp2 = true; + mod->modeldatatypestring = "Q1BSP2"; + Mod_Q1BSP_Load(mod, buffer, bufferend); +} + +void Mod_HLBSP_Load(dp_model_t *mod, void *buffer, void *bufferend) +{ + mod->brush.ishlbsp = true; + mod->modeldatatypestring = "HLBSP"; + Mod_Q1BSP_Load(mod, buffer, bufferend); +} + void Mod_Q1BSP_Load(dp_model_t *mod, void *buffer, void *bufferend) { int i, j, k; @@ -3872,29 +3894,9 @@ void Mod_Q1BSP_Load(dp_model_t *mod, void *buffer, void *bufferend) mod->brush.isq3bsp = false; mod->brush.skymasking = true; i = MSG_ReadLittleLong(&sb); - switch(i) - { - case BSPVERSION: + + if(!mod->modeldatatypestring) mod->modeldatatypestring = "Q1BSP"; - break; - case 30: - mod->brush.ishlbsp = true; - mod->modeldatatypestring = "HLBSP"; - break; - case ('2' + 'P' * 256 + 'S' * 65536 + 'B' * 16777216): - mod->brush.isbsp2 = true; - mod->brush.isbsp2rmqe = true; // like bsp2 except leaf/node bounds are 16bit (unexpanded) - mod->modeldatatypestring = "Q1BSP2rmqe"; - break; - case ('B' + 'S' * 256 + 'P' * 65536 + '2' * 16777216): - mod->brush.isbsp2 = true; - mod->modeldatatypestring = "Q1BSP2"; - break; - default: - mod->modeldatatypestring = "Unknown BSP"; - Host_Error("Mod_Q1BSP_Load: %s has wrong version number %i: supported versions are 29 (Quake), 30 (Half-Life), \"BSP2\" or \"2PSB\" (rmqe)", mod->name, i); - return; - } // fill in hull info VectorClear (hullinfo.hullsizes[0][0]); diff --git a/model_shared.c b/model_shared.c index 14b8ec90..c4d89707 100644 --- a/model_shared.c +++ b/model_shared.c @@ -41,6 +41,28 @@ cvar_t mod_generatelightmaps_gridradius = {CVAR_CLIENT | CVAR_SAVE, "mod_generat dp_model_t *loadmodel; +// Supported model formats +static modloader_t loader[] = +{ + {"obj", NULL, 0, Mod_OBJ_Load}, + {NULL, "IDPO", 4, Mod_IDP0_Load}, + {NULL, "IDP2", 4, Mod_IDP2_Load}, + {NULL, "IDP3", 4, Mod_IDP3_Load}, + {NULL, "IDSP", 4, Mod_IDSP_Load}, + {NULL, "IDS2", 4, Mod_IDS2_Load}, + {NULL, "\035", 1, Mod_Q1BSP_Load}, + {NULL, "\036", 1, Mod_HLBSP_Load}, + {NULL, "BSP2", 4, Mod_BSP2_Load}, + {NULL, "2PSB", 4, Mod_2PSB_Load}, + {NULL, "IBSP", 4, Mod_IBSP_Load}, + {NULL, "ZYMOTICMODEL", 13, Mod_ZYMOTICMODEL_Load}, + {NULL, "DARKPLACESMODEL", 16, Mod_DARKPLACESMODEL_Load}, + {NULL, "PSKMODEL", 9, Mod_PSKMODEL_Load}, + {NULL, "INTERQUAKEMODEL", 16, Mod_INTERQUAKEMODEL_Load}, + {"map", NULL, 0, Mod_MAP_Load}, + {NULL, NULL, 0, NULL} +}; + static mempool_t *mod_mempool; static memexpandablearray_t models; @@ -382,7 +404,6 @@ Loads a model */ dp_model_t *Mod_LoadModel(dp_model_t *mod, qboolean crash, qboolean checkdisk) { - int num; unsigned int crc; void *buf; fs_offset_t filesize = 0; @@ -490,46 +511,45 @@ dp_model_t *Mod_LoadModel(dp_model_t *mod, qboolean crash, qboolean checkdisk) if (buf) { + int i; + const char *ext = FS_FileExtension(mod->name); char *bufend = (char *)buf + filesize; - // all models use memory, so allocate a memory pool mod->mempool = Mem_AllocPool(mod->name, 0, NULL); - num = LittleLong(*((int *)buf)); // call the apropriate loader loadmodel = mod; - if (!strcasecmp(FS_FileExtension(mod->name), "obj")) Mod_OBJ_Load(mod, buf, bufend); - else if (!memcmp(buf, "IDPO", 4)) Mod_IDP0_Load(mod, buf, bufend); - else if (!memcmp(buf, "IDP2", 4)) Mod_IDP2_Load(mod, buf, bufend); - else if (!memcmp(buf, "IDP3", 4)) Mod_IDP3_Load(mod, buf, bufend); - else if (!memcmp(buf, "IDSP", 4)) Mod_IDSP_Load(mod, buf, bufend); - else if (!memcmp(buf, "IDS2", 4)) Mod_IDS2_Load(mod, buf, bufend); - else if (!memcmp(buf, "IBSP", 4)) Mod_IBSP_Load(mod, buf, bufend); - else if (!memcmp(buf, "ZYMOTICMODEL", 12)) Mod_ZYMOTICMODEL_Load(mod, buf, bufend); - else if (!memcmp(buf, "DARKPLACESMODEL", 16)) Mod_DARKPLACESMODEL_Load(mod, buf, bufend); - else if (!memcmp(buf, "ACTRHEAD", 8)) Mod_PSKMODEL_Load(mod, buf, bufend); - else if (!memcmp(buf, "INTERQUAKEMODEL", 16)) Mod_INTERQUAKEMODEL_Load(mod, buf, bufend); - else if (strlen(mod->name) >= 4 && !strcmp(mod->name + strlen(mod->name) - 4, ".map")) Mod_MAP_Load(mod, buf, bufend); - else if (num == BSPVERSION || num == 30 || !memcmp(buf, "BSP2", 4) || !memcmp(buf, "2PSB", 4)) Mod_Q1BSP_Load(mod, buf, bufend); - else Con_Printf("Mod_LoadModel: model \"%s\" is of unknown/unsupported type\n", mod->name); - Mem_Free(buf); - - Mod_FindPotentialDeforms(mod); - - buf = FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.framegroups", mod->name), tempmempool, false, &filesize); - if(buf) + + // Try matching magic bytes. + for (i = 0; loader[i].Load; i++) { - Mod_FrameGroupify(mod, (const char *)buf); - Mem_Free(buf); - } + // Headerless formats can just load based on extension. Otherwise match the magic string. + if((loader[i].extension && !strcasecmp(ext, loader[i].extension) && !loader[i].header) || + (loader[i].header && !memcmp(buf, loader[i].header, loader[i].headersize))) + { + // Matched. Load it. + loader[i].Load(mod, buf, bufend); + Mem_Free(buf); + + Mod_FindPotentialDeforms(mod); - Mod_BuildVBOs(); + buf = FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.framegroups", mod->name), tempmempool, false, &filesize); + if(buf) + { + Mod_FrameGroupify(mod, (const char *)buf); + Mem_Free(buf); + } + + Mod_BuildVBOs(); + break; + } + } + if(!loader[i].Load) + Con_Printf(CON_ERROR "Mod_LoadModel: model \"%s\" is of unknown/unsupported type\n", mod->name); } else if (crash) - { // LadyHavoc: Sys_Error was *ANNOYING* - Con_Printf ("Mod_LoadModel: %s not found\n", mod->name); - } + Con_Printf (CON_ERROR "Mod_LoadModel: %s not found\n", mod->name); // no fatal errors occurred, so this model is ready to use. mod->loaded = true; diff --git a/model_shared.h b/model_shared.h index fc04c7fb..38469a56 100644 --- a/model_shared.h +++ b/model_shared.h @@ -1071,6 +1071,15 @@ dp_model_t; // model loading extern dp_model_t *loadmodel; extern unsigned char *mod_base; + +typedef struct modloader_s +{ + char *extension; + char *header; + size_t headersize; // The header might not be NULL terminated + void (*Load)(dp_model_t *, void *, void *); +} modloader_t; + // sky/water subdivision //extern cvar_t gl_subdivide_size; // texture fullbrights @@ -1242,6 +1251,9 @@ void Mod_Skeletal_FreeBuffers(void); void Mod_SpriteInit(void); // loaders +void Mod_2PSB_Load(dp_model_t *mod, void *buffer, void *bufferend); +void Mod_BSP2_Load(dp_model_t *mod, void *buffer, void *bufferend); +void Mod_HLBSP_Load(dp_model_t *mod, void *buffer, void *bufferend); void Mod_Q1BSP_Load(dp_model_t *mod, void *buffer, void *bufferend); void Mod_IBSP_Load(dp_model_t *mod, void *buffer, void *bufferend); void Mod_MAP_Load(dp_model_t *mod, void *buffer, void *bufferend);