]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - model_shared.c
removed \n from all Host_Error, Sys_Error, PRVM_ERROR, PF_ERROR calls, since Host_Err...
[xonotic/darkplaces.git] / model_shared.c
index 40967880f6238a691c0d54c1cc108bc19ed61809..bbed73d4c9fa2b1c8a6245d2e3b2f409270666af 100644 (file)
@@ -37,18 +37,22 @@ static model_t mod_known[MAX_MOD_KNOWN];
 static void mod_start(void)
 {
        int i;
-       for (i = 0;i < MAX_MOD_KNOWN;i++)
-               if (mod_known[i].name[0])
-                       Mod_UnloadModel(&mod_known[i]);
-       Mod_LoadModels();
+       model_t *mod;
+
+       for (i = 0, mod = mod_known;i < MAX_MOD_KNOWN;i++, mod++)
+               if (mod->name[0])
+                       if (mod->used)
+                               Mod_LoadModel(mod, true, false, mod->isworldmodel);
 }
 
 static void mod_shutdown(void)
 {
        int i;
-       for (i = 0;i < MAX_MOD_KNOWN;i++)
-               if (mod_known[i].name[0])
-                       Mod_UnloadModel(&mod_known[i]);
+       model_t *mod;
+
+       for (i = 0, mod = mod_known;i < MAX_MOD_KNOWN;i++, mod++)
+               if (mod->loaded)
+                       Mod_UnloadModel(mod);
 }
 
 static void mod_newmap(void)
@@ -61,7 +65,7 @@ static void mod_newmap(void)
 
        for (i = 0;i < MAX_MOD_KNOWN;i++)
        {
-               if (mod_known[i].name[0])
+               if (mod_known[i].mempool && mod_known[i].data_surfaces)
                {
                        for (surfacenum = 0, surface = mod_known[i].data_surfaces;surfacenum < mod_known[i].num_surfaces;surfacenum++, surface++)
                        {
@@ -100,15 +104,6 @@ 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];
@@ -117,7 +112,12 @@ void Mod_UnloadModel (model_t *mod)
        strcpy(name, mod->name);
        isworldmodel = mod->isworldmodel;
        used = mod->used;
-       Mod_FreeModel(mod);
+       // free textures/memory attached to the model
+       R_FreeTexturePool(&mod->texturepool);
+       Mem_FreePool(&mod->mempool);
+       // clear the struct to make it available
+       memset(mod, 0, sizeof(model_t));
+       // restore the fields we want to preserve
        strcpy(mod->name, name);
        mod->isworldmodel = isworldmodel;
        mod->used = used;
@@ -136,6 +136,7 @@ model_t *Mod_LoadModel(model_t *mod, qboolean crash, qboolean checkdisk, qboolea
        int num;
        unsigned int crc;
        void *buf;
+       fs_offset_t filesize;
 
        mod->used = true;
 
@@ -150,10 +151,10 @@ model_t *Mod_LoadModel(model_t *mod, qboolean crash, qboolean checkdisk, qboolea
        {
                if (checkdisk && mod->loaded)
                        Con_DPrintf("checking model %s\n", mod->name);
-               buf = FS_LoadFile (mod->name, tempmempool, false);
+               buf = FS_LoadFile (mod->name, tempmempool, false, &filesize);
                if (buf)
                {
-                       crc = CRC_Block(buf, fs_filesize);
+                       crc = CRC_Block((unsigned char *)buf, filesize);
                        if (mod->crc != crc)
                                mod->loaded = false;
                }
@@ -163,7 +164,8 @@ model_t *Mod_LoadModel(model_t *mod, qboolean crash, qboolean checkdisk, qboolea
 
        Con_DPrintf("loading model %s\n", mod->name);
        // LordHavoc: unload the existing model in this slot (if there is one)
-       Mod_UnloadModel(mod);
+       if (mod->loaded)
+               Mod_UnloadModel(mod);
 
        // load the model
        mod->isworldmodel = isworldmodel;
@@ -189,7 +191,7 @@ model_t *Mod_LoadModel(model_t *mod, qboolean crash, qboolean checkdisk, qboolea
 
        if (buf)
        {
-               char *bufend = (char *)buf + fs_filesize;
+               char *bufend = (char *)buf + filesize;
                num = LittleLong(*((int *)buf));
                // call the apropriate loader
                loadmodel = mod;
@@ -201,9 +203,9 @@ model_t *Mod_LoadModel(model_t *mod, qboolean crash, qboolean checkdisk, qboolea
                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 (!strcmp(buf, "ACTRHEAD")) Mod_PSKMODEL_Load(mod, buf, bufend);
+               else if (!memcmp(buf, "ACTRHEAD", 8)) Mod_PSKMODEL_Load(mod, buf, bufend);
                else if (strlen(mod->name) >= 4 && !strcmp(mod->name - 4, ".map")) Mod_MAP_Load(mod, buf, bufend);
-               else if (!memcmp(buf, "MCBSP", 5)) Mod_Q1BSP_Load(mod, buf, bufend);
+               else if (!memcmp(buf, "MCBSPpad", 8)) Mod_Q1BSP_Load(mod, buf, bufend);
                else if (num == BSPVERSION || num == 30) Mod_Q1BSP_Load(mod, buf, bufend);
                else Con_Printf("Mod_LoadModel: model \"%s\" is of unknown/unsupported type\n", mod->name);
                Mem_Free(buf);
@@ -230,12 +232,14 @@ void Mod_ClearAll(void)
 
 void Mod_ClearUsed(void)
 {
+#if 0
        int i;
        model_t *mod;
 
        for (i = 0, mod = mod_known;i < MAX_MOD_KNOWN;i++, mod++)
                if (mod->name[0])
                        mod->used = false;
+#endif
 }
 
 void Mod_PurgeUnused(void)
@@ -246,27 +250,24 @@ void Mod_PurgeUnused(void)
        for (i = 0, mod = mod_known;i < MAX_MOD_KNOWN;i++, mod++)
                if (mod->name[0])
                        if (!mod->used)
-                               Mod_FreeModel(mod);
+                               Mod_UnloadModel(mod);
 }
 
 // only used during loading!
 void Mod_RemoveStaleWorldModels(model_t *skip)
-{
-       int i;
-       for (i = 0;i < MAX_MOD_KNOWN;i++)
-               if (mod_known[i].isworldmodel && skip != &mod_known[i])
-                       Mod_UnloadModel(mod_known + i);
-}
-
-void Mod_LoadModels(void)
 {
        int i;
        model_t *mod;
 
        for (i = 0, mod = mod_known;i < MAX_MOD_KNOWN;i++, mod++)
-               if (mod->name[0])
-                       if (mod->used)
-                               Mod_CheckLoaded(mod);
+       {
+               if (mod->isworldmodel && mod->loaded && skip != mod)
+               {
+                       Mod_UnloadModel(mod);
+                       mod->isworldmodel = false;
+                       mod->used = false;
+               }
+       }
 }
 
 /*
@@ -308,7 +309,7 @@ model_t *Mod_FindName(const char *name)
                return mod;
        }
 
-       Host_Error ("Mod_FindName: ran out of models\n");
+       Host_Error ("Mod_FindName: ran out of models");
        return NULL;
 }
 
@@ -321,10 +322,14 @@ Loads in a model for the given name
 */
 model_t *Mod_ForName(const char *name, qboolean crash, qboolean checkdisk, qboolean isworldmodel)
 {
-       return Mod_LoadModel(Mod_FindName(name), crash, checkdisk, isworldmodel);
+       model_t *model;
+       model = Mod_FindName(name);
+       if (model->name[0] != '*' && (!model->loaded || checkdisk))
+               Mod_LoadModel(model, crash, checkdisk, isworldmodel);
+       return model;
 }
 
-qbyte *mod_base;
+unsigned char *mod_base;
 
 
 //=============================================================================
@@ -361,8 +366,8 @@ static void Mod_Precache(void)
 int Mod_BuildVertexRemapTableFromElements(int numelements, const int *elements, int numvertices, int *remapvertices)
 {
        int i, count;
-       qbyte *used;
-       used = Mem_Alloc(tempmempool, numvertices);
+       unsigned char *used;
+       used = (unsigned char *)Mem_Alloc(tempmempool, numvertices);
        memset(used, 0, numvertices);
        for (i = 0;i < numelements;i++)
                used[elements[i]] = 1;
@@ -391,7 +396,7 @@ void Mod_BuildTriangleNeighbors(int *neighbors, const int *elements, int numtria
        edgehashentries = edgehashentriesbuffer;
        // if there are too many triangles for the stack array, allocate larger buffer
        if (numtriangles > TRIANGLEEDGEHASH)
-               edgehashentries = Mem_Alloc(tempmempool, numtriangles * 3 * sizeof(edgehashentry_t));
+               edgehashentries = (edgehashentry_t *)Mem_Alloc(tempmempool, numtriangles * 3 * sizeof(edgehashentry_t));
        // find neighboring triangles
        for (i = 0, e = elements, n = neighbors;i < numtriangles;i++, e += 3, n += 3)
        {
@@ -635,11 +640,11 @@ void Mod_BuildTextureVectorsAndNormals(int firstvertex, int numvertices, int num
 surfmesh_t *Mod_AllocSurfMesh(mempool_t *mempool, int numvertices, int numtriangles, qboolean lightmapoffsets, qboolean vertexcolors, qboolean neighbors)
 {
        surfmesh_t *mesh;
-       qbyte *data;
-       mesh = Mem_Alloc(mempool, sizeof(surfmesh_t) + numvertices * (3 + 3 + 3 + 3 + 2 + 2 + (vertexcolors ? 4 : 0)) * sizeof(float) + numvertices * (lightmapoffsets ? 1 : 0) * sizeof(int) + numtriangles * (3 + 3 + (neighbors ? 3 : 0)) * sizeof(int));
+       unsigned char *data;
+       mesh = (surfmesh_t *)Mem_Alloc(mempool, sizeof(surfmesh_t) + numvertices * (3 + 3 + 3 + 3 + 2 + 2 + (vertexcolors ? 4 : 0)) * sizeof(float) + numvertices * (lightmapoffsets ? 1 : 0) * sizeof(int) + numtriangles * (3 + (neighbors ? 3 : 0)) * sizeof(int));
        mesh->num_vertices = numvertices;
        mesh->num_triangles = numtriangles;
-       data = (qbyte *)(mesh + 1);
+       data = (unsigned char *)(mesh + 1);
        if (mesh->num_vertices)
        {
                mesh->data_vertex3f = (float *)data, data += sizeof(float[3]) * mesh->num_vertices;
@@ -655,7 +660,6 @@ surfmesh_t *Mod_AllocSurfMesh(mempool_t *mempool, int numvertices, int numtriang
        }
        if (mesh->num_triangles)
        {
-               mesh->data_element3i = (int *)data, data += sizeof(int[3]) * mesh->num_triangles;
                mesh->data_element3i = (int *)data, data += sizeof(int[3]) * mesh->num_triangles;
                if (neighbors)
                        mesh->data_neighbor3i = (int *)data, data += sizeof(int[3]) * mesh->num_triangles;
@@ -666,7 +670,7 @@ surfmesh_t *Mod_AllocSurfMesh(mempool_t *mempool, int numvertices, int numtriang
 shadowmesh_t *Mod_ShadowMesh_Alloc(mempool_t *mempool, int maxverts, int maxtriangles, rtexture_t *map_diffuse, rtexture_t *map_specular, rtexture_t *map_normal, int light, int neighbors, int expandable)
 {
        shadowmesh_t *newmesh;
-       qbyte *data;
+       unsigned char *data;
        int size;
        size = sizeof(shadowmesh_t);
        size += maxverts * sizeof(float[3]);
@@ -677,8 +681,8 @@ shadowmesh_t *Mod_ShadowMesh_Alloc(mempool_t *mempool, int maxverts, int maxtria
                size += maxtriangles * sizeof(int[3]);
        if (expandable)
                size += SHADOWMESHVERTEXHASH * sizeof(shadowmeshvertexhash_t *) + maxverts * sizeof(shadowmeshvertexhash_t);
-       data = Mem_Alloc(mempool, size);
-       newmesh = (void *)data;data += sizeof(*newmesh);
+       data = (unsigned char *)Mem_Alloc(mempool, size);
+       newmesh = (shadowmesh_t *)data;data += sizeof(*newmesh);
        newmesh->map_diffuse = map_diffuse;
        newmesh->map_specular = map_specular;
        newmesh->map_normal = map_normal;
@@ -687,23 +691,23 @@ shadowmesh_t *Mod_ShadowMesh_Alloc(mempool_t *mempool, int maxverts, int maxtria
        newmesh->numverts = 0;
        newmesh->numtriangles = 0;
 
-       newmesh->vertex3f = (void *)data;data += maxverts * sizeof(float[3]);
+       newmesh->vertex3f = (float *)data;data += maxverts * sizeof(float[3]);
        if (light)
        {
-               newmesh->svector3f = (void *)data;data += maxverts * sizeof(float[3]);
-               newmesh->tvector3f = (void *)data;data += maxverts * sizeof(float[3]);
-               newmesh->normal3f = (void *)data;data += maxverts * sizeof(float[3]);
-               newmesh->texcoord2f = (void *)data;data += maxverts * sizeof(float[2]);
+               newmesh->svector3f = (float *)data;data += maxverts * sizeof(float[3]);
+               newmesh->tvector3f = (float *)data;data += maxverts * sizeof(float[3]);
+               newmesh->normal3f = (float *)data;data += maxverts * sizeof(float[3]);
+               newmesh->texcoord2f = (float *)data;data += maxverts * sizeof(float[2]);
        }
-       newmesh->element3i = (void *)data;data += maxtriangles * sizeof(int[3]);
+       newmesh->element3i = (int *)data;data += maxtriangles * sizeof(int[3]);
        if (neighbors)
        {
-               newmesh->neighbor3i = (void *)data;data += maxtriangles * sizeof(int[3]);
+               newmesh->neighbor3i = (int *)data;data += maxtriangles * sizeof(int[3]);
        }
        if (expandable)
        {
-               newmesh->vertexhashtable = (void *)data;data += SHADOWMESHVERTEXHASH * sizeof(shadowmeshvertexhash_t *);
-               newmesh->vertexhashentries = (void *)data;data += maxverts * sizeof(shadowmeshvertexhash_t);
+               newmesh->vertexhashtable = (shadowmeshvertexhash_t **)data;data += SHADOWMESHVERTEXHASH * sizeof(shadowmeshvertexhash_t *);
+               newmesh->vertexhashentries = (shadowmeshvertexhash_t *)data;data += maxverts * sizeof(shadowmeshvertexhash_t);
        }
        return newmesh;
 }
@@ -852,6 +856,8 @@ void Mod_ShadowMesh_CalcBBox(shadowmesh_t *firstmesh, vec3_t mins, vec3_t maxs,
        shadowmesh_t *mesh;
        vec3_t nmins, nmaxs, ncenter, temp;
        float nradius2, dist2, *v;
+       VectorClear(nmins);
+       VectorClear(nmaxs);
        // calculate bbox
        for (mesh = firstmesh;mesh;mesh = mesh->next)
        {
@@ -903,11 +909,11 @@ void Mod_ShadowMesh_Free(shadowmesh_t *mesh)
        }
 }
 
-static rtexture_t *GL_TextureForSkinLayer(const qbyte *in, int width, int height, const char *name, const unsigned int *palette, int textureflags)
+static rtexture_t *GL_TextureForSkinLayer(const unsigned char *in, int width, int height, const char *name, const unsigned int *palette, int textureflags)
 {
        int i;
        for (i = 0;i < width*height;i++)
-               if (((qbyte *)&palette[in[i]])[3] > 0)
+               if (((unsigned char *)&palette[in[i]])[3] > 0)
                        return R_LoadTexture2D (loadmodel->texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
        return NULL;
 }
@@ -942,15 +948,15 @@ int Mod_LoadSkinFrame(skinframe_t *skinframe, char *basename, int textureflags,
        return true;
 }
 
-int Mod_LoadSkinFrame_Internal(skinframe_t *skinframe, char *basename, int textureflags, int loadpantsandshirt, int loadglowtexture, qbyte *skindata, int width, int height)
+int Mod_LoadSkinFrame_Internal(skinframe_t *skinframe, char *basename, int textureflags, int loadpantsandshirt, int loadglowtexture, unsigned char *skindata, int width, int height)
 {
-       qbyte *temp1, *temp2;
+       unsigned char *temp1, *temp2;
        memset(skinframe, 0, sizeof(*skinframe));
        if (!skindata)
                return false;
        if (r_shadow_bumpscale_basetexture.value > 0)
        {
-               temp1 = Mem_Alloc(loadmodel->mempool, width * height * 8);
+               temp1 = (unsigned char *)Mem_Alloc(loadmodel->mempool, width * height * 8);
                temp2 = temp1 + width * height * 4;
                Image_Copy8bitRGBA(skindata, temp1, width * height, palette_nofullbrights);
                Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
@@ -985,7 +991,7 @@ int Mod_LoadSkinFrame_Internal(skinframe_t *skinframe, char *basename, int textu
        return true;
 }
 
-void Mod_GetTerrainVertex3fTexCoord2fFromRGBA(const qbyte *imagepixels, int imagewidth, int imageheight, int ix, int iy, float *vertex3f, float *texcoord2f, matrix4x4_t *pixelstepmatrix, matrix4x4_t *pixeltexturestepmatrix)
+void Mod_GetTerrainVertex3fTexCoord2fFromRGBA(const unsigned char *imagepixels, int imagewidth, int imageheight, int ix, int iy, float *vertex3f, float *texcoord2f, matrix4x4_t *pixelstepmatrix, matrix4x4_t *pixeltexturestepmatrix)
 {
        float v[3], tc[3];
        v[0] = ix;
@@ -1000,7 +1006,7 @@ void Mod_GetTerrainVertex3fTexCoord2fFromRGBA(const qbyte *imagepixels, int imag
        texcoord2f[1] = tc[1];
 }
 
-void Mod_GetTerrainVertexFromRGBA(const qbyte *imagepixels, int imagewidth, int imageheight, int ix, int iy, float *vertex3f, float *svector3f, float *tvector3f, float *normal3f, float *texcoord2f, matrix4x4_t *pixelstepmatrix, matrix4x4_t *pixeltexturestepmatrix)
+void Mod_GetTerrainVertexFromRGBA(const unsigned char *imagepixels, int imagewidth, int imageheight, int ix, int iy, float *vertex3f, float *svector3f, float *tvector3f, float *normal3f, float *texcoord2f, matrix4x4_t *pixelstepmatrix, matrix4x4_t *pixeltexturestepmatrix)
 {
        float vup[3], vdown[3], vleft[3], vright[3];
        float tcup[3], tcdown[3], tcleft[3], tcright[3];
@@ -1025,7 +1031,7 @@ void Mod_GetTerrainVertexFromRGBA(const qbyte *imagepixels, int imagewidth, int
        VectorAdd(normal3f, nl, normal3f);
 }
 
-void Mod_ConstructTerrainPatchFromRGBA(const qbyte *imagepixels, int imagewidth, int imageheight, int x1, int y1, int width, int height, int *element3i, int *neighbor3i, float *vertex3f, float *svector3f, float *tvector3f, float *normal3f, float *texcoord2f, matrix4x4_t *pixelstepmatrix, matrix4x4_t *pixeltexturestepmatrix)
+void Mod_ConstructTerrainPatchFromRGBA(const unsigned char *imagepixels, int imagewidth, int imageheight, int x1, int y1, int width, int height, int *element3i, int *neighbor3i, float *vertex3f, float *svector3f, float *tvector3f, float *normal3f, float *texcoord2f, matrix4x4_t *pixelstepmatrix, matrix4x4_t *pixeltexturestepmatrix)
 {
        int x, y, ix, iy, *e;
        e = element3i;
@@ -1076,19 +1082,19 @@ tag_torso,
 */
        memset(tagsets, 0, sizeof(tagsets));
        memset(word, 0, sizeof(word));
-       for (i = 0;i < MAX_SKINS && (data = text = FS_LoadFile(va("%s_%i.skin", loadmodel->name, i), tempmempool, true));i++)
+       for (i = 0;i < MAX_SKINS && (data = text = (char *)FS_LoadFile(va("%s_%i.skin", loadmodel->name, i), tempmempool, true, NULL));i++)
        {
                numtags = 0;
 
                // If it's the first file we parse
                if (skinfile == NULL)
                {
-                       skinfile = Mem_Alloc(tempmempool, sizeof(skinfile_t));
+                       skinfile = (skinfile_t *)Mem_Alloc(tempmempool, sizeof(skinfile_t));
                        first = skinfile;
                }
                else
                {
-                       skinfile->next = Mem_Alloc(tempmempool, sizeof(skinfile_t));
+                       skinfile->next = (skinfile_t *)Mem_Alloc(tempmempool, sizeof(skinfile_t));
                        skinfile = skinfile->next;
                }
                skinfile->next = NULL;
@@ -1121,7 +1127,7 @@ tag_torso,
                                if (words == 3)
                                {
                                        Con_DPrintf("Mod_LoadSkinFiles: parsed mesh \"%s\" shader replacement \"%s\"\n", word[1], word[2]);
-                                       skinfileitem = Mem_Alloc(tempmempool, sizeof(skinfileitem_t));
+                                       skinfileitem = (skinfileitem_t *)Mem_Alloc(tempmempool, sizeof(skinfileitem_t));
                                        skinfileitem->next = skinfile->items;
                                        skinfile->items = skinfileitem;
                                        strlcpy (skinfileitem->name, word[1], sizeof (skinfileitem->name));
@@ -1142,7 +1148,7 @@ tag_torso,
                        {
                                // mesh shader name, like "U_RArm,models/players/Legoman/BikerA1.tga"
                                Con_DPrintf("Mod_LoadSkinFiles: parsed mesh \"%s\" shader replacement \"%s\"\n", word[0], word[2]);
-                               skinfileitem = Mem_Alloc(tempmempool, sizeof(skinfileitem_t));
+                               skinfileitem = (skinfileitem_t *)Mem_Alloc(tempmempool, sizeof(skinfileitem_t));
                                skinfileitem->next = skinfile->items;
                                skinfile->items = skinfileitem;
                                strlcpy (skinfileitem->name, word[0], sizeof (skinfileitem->name));
@@ -1158,14 +1164,14 @@ tag_torso,
                        overridetagnameset_t *t;
                        t = tagsets + i;
                        t->num_overridetagnames = numtags;
-                       t->data_overridetagnames = Mem_Alloc(loadmodel->mempool, t->num_overridetagnames * sizeof(overridetagname_t));
+                       t->data_overridetagnames = (overridetagname_t *)Mem_Alloc(loadmodel->mempool, t->num_overridetagnames * sizeof(overridetagname_t));
                        memcpy(t->data_overridetagnames, tags, t->num_overridetagnames * sizeof(overridetagname_t));
                        tagsetsused = true;
                }
        }
        if (tagsetsused)
        {
-               loadmodel->data_overridetagnamesforskin = Mem_Alloc(loadmodel->mempool, i * sizeof(overridetagnameset_t));
+               loadmodel->data_overridetagnamesforskin = (overridetagnameset_t *)Mem_Alloc(loadmodel->mempool, i * sizeof(overridetagnameset_t));
                memcpy(loadmodel->data_overridetagnamesforskin, tagsets, i * sizeof(overridetagnameset_t));
        }
        if (i)