]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
Refactor the model loading code to use an array of structs for each format
authorcloudwalk <cloudwalk@d7cf8633-e32d-0410-b094-e92efae38249>
Thu, 9 Jul 2020 16:58:42 +0000 (16:58 +0000)
committercloudwalk <cloudwalk@d7cf8633-e32d-0410-b094-e92efae38249>
Thu, 9 Jul 2020 16:58:42 +0000 (16:58 +0000)
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

bspfile.h
model_brush.c
model_shared.c
model_shared.h

index b1bdc350289644d62ed899992e9a865aac4da97d..f918d7943798adbadb8e607e3e2632f2a61b3710 100644 (file)
--- 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
 {
index b56321f51ad3da6d57cb59f8386550b958c36187..934791bec3bc1d0b800e8dc276d53f2ef4db3a67 100644 (file)
@@ -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]);
index 14b8ec903e9d1d5cb9677b38ea0a50b96e94f5d6..c4d89707556af87a3413c82318e1d0e7d757f498 100644 (file)
@@ -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;
index fc04c7fb7cb03c4d2cab35041839e478a5723421..38469a560dea575a83d3700d43d6817f36639239 100644 (file)
@@ -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);