]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - model_shared.c
patch from div0 that enables printf format warnings in gcc
[xonotic/darkplaces.git] / model_shared.c
index 841346b4dd37253794e919c782269a6b16b9d579..a613449eb92d80caf06203a777c32b61a91c0e5a 100644 (file)
@@ -49,7 +49,7 @@ static void mod_start(void)
        model_t *mod;
 
        for (i = 0, mod = mod_known;i < mod_numknown;i++, mod++)
-               if (mod->name[0])
+               if (mod->name[0] && mod->name[0] != '*')
                        if (mod->used)
                                Mod_LoadModel(mod, true, false, mod->isworldmodel);
 }
@@ -60,7 +60,7 @@ static void mod_shutdown(void)
        model_t *mod;
 
        for (i = 0, mod = mod_known;i < mod_numknown;i++, mod++)
-               if (mod->loaded)
+               if (mod->loaded || mod->mempool)
                        Mod_UnloadModel(mod);
 }
 
@@ -118,7 +118,7 @@ void Mod_UnloadModel (model_t *mod)
        char name[MAX_QPATH];
        qboolean isworldmodel;
        qboolean used;
-       strcpy(name, mod->name);
+       strlcpy(name, mod->name, sizeof(name));
        isworldmodel = mod->isworldmodel;
        used = mod->used;
        // free textures/memory attached to the model
@@ -127,7 +127,7 @@ void Mod_UnloadModel (model_t *mod)
        // clear the struct to make it available
        memset(mod, 0, sizeof(model_t));
        // restore the fields we want to preserve
-       strcpy(mod->name, name);
+       strlcpy(mod->name, name, sizeof(mod->name));
        mod->isworldmodel = isworldmodel;
        mod->used = used;
        mod->loaded = false;
@@ -178,7 +178,7 @@ 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)
-       if (mod->loaded)
+       if (mod->loaded || mod->mempool)
                Mod_UnloadModel(mod);
 
        // load the model
@@ -197,15 +197,16 @@ model_t *Mod_LoadModel(model_t *mod, qboolean crash, qboolean checkdisk, qboolea
        VectorSet(mod->rotatedmins, -mod->radius, -mod->radius, -mod->radius);
        VectorSet(mod->rotatedmaxs, mod->radius, mod->radius, mod->radius);
 
-       // all models use memory, so allocate a memory pool
-       mod->mempool = Mem_AllocPool(mod->name, 0, NULL);
-       // all models load textures, so allocate a texture pool
-       if (cls.state != ca_dedicated)
-               mod->texturepool = R_AllocTexturePool();
-
        if (buf)
        {
                char *bufend = (char *)buf + filesize;
+
+               // all models use memory, so allocate a memory pool
+               mod->mempool = Mem_AllocPool(mod->name, 0, NULL);
+               // all models load textures, so allocate a texture pool
+               if (cls.state != ca_dedicated)
+                       mod->texturepool = R_AllocTexturePool();
+
                num = LittleLong(*((int *)buf));
                // call the apropriate loader
                loadmodel = mod;
@@ -223,15 +224,14 @@ model_t *Mod_LoadModel(model_t *mod, qboolean crash, qboolean checkdisk, qboolea
                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);
+               // no fatal errors occurred, so this model is ready to use.
+               mod->loaded = true;
        }
        else if (crash)
        {
                // LordHavoc: Sys_Error was *ANNOYING*
                Con_Printf ("Mod_LoadModel: %s not found\n", mod->name);
        }
-
-       // no errors occurred
-       mod->loaded = true;
        return mod;
 }
 
@@ -323,7 +323,7 @@ model_t *Mod_FindName(const char *name)
        if (mod_numknown == i)
                mod_numknown++;
        mod = mod_known + i;
-       strcpy (mod->name, name);
+       strlcpy (mod->name, name, sizeof(mod->name));
        mod->loaded = false;
        mod->used = true;
        return mod;
@@ -345,6 +345,24 @@ model_t *Mod_ForName(const char *name, qboolean crash, qboolean checkdisk, qbool
        return model;
 }
 
+/*
+==================
+Mod_Reload
+
+Reloads all models if they have changed
+==================
+*/
+void Mod_Reload()
+{
+       int i;
+       model_t *mod;
+
+       for (i = 0, mod = mod_known;i < mod_numknown;i++, mod++)
+               if (mod->name[0] && mod->name[0] != '*')
+                       if (mod->used)
+                               Mod_LoadModel(mod, true, true, mod->isworldmodel);
+}
+
 unsigned char *mod_base;
 
 
@@ -363,7 +381,7 @@ static void Mod_Print(void)
        Con_Print("Loaded models:\n");
        for (i = 0, mod = mod_known;i < mod_numknown;i++, mod++)
                if (mod->name[0])
-                       Con_Printf("%4iK %s\n", mod->mempool ? (mod->mempool->totalsize + 1023) / 1024 : 0, mod->name);
+                       Con_Printf("%4iK %s\n", mod->mempool ? (int)((mod->mempool->totalsize + 1023) / 1024) : 0, mod->name);
 }
 
 /*
@@ -605,20 +623,16 @@ void Mod_BuildBumpVectors(const float *v0, const float *v1, const float *v2, con
 }
 
 // warning: this is a very expensive function!
-void Mod_BuildTextureVectorsAndNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const float *texcoord2f, const int *elements, float *svector3f, float *tvector3f, float *normal3f, qboolean areaweighting)
+void Mod_BuildTextureVectorsFromNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const float *texcoord2f, const float *normal3f, const int *elements, float *svector3f, float *tvector3f, qboolean areaweighting)
 {
        int i, tnum;
-       float sdir[3], tdir[3], normal[3], *v;
-       const float *v0, *v1, *v2, *tc0, *tc1, *tc2;
+       float sdir[3], tdir[3], normal[3], *sv, *tv;
+       const float *v0, *v1, *v2, *tc0, *tc1, *tc2, *n;
        float f, tangentcross[3], v10[3], v20[3], tc10[2], tc20[2];
        const int *e;
        // clear the vectors
-       if (svector3f)
-               memset(svector3f + 3 * firstvertex, 0, numvertices * sizeof(float[3]));
-       if (tvector3f)
-               memset(tvector3f + 3 * firstvertex, 0, numvertices * sizeof(float[3]));
-       if (normal3f)
-               memset(normal3f + 3 * firstvertex, 0, numvertices * sizeof(float[3]));
+       memset(svector3f + 3 * firstvertex, 0, numvertices * sizeof(float[3]));
+       memset(tvector3f + 3 * firstvertex, 0, numvertices * sizeof(float[3]));
        // process each vertex of each triangle and accumulate the results
        for (tnum = 0, e = elements;tnum < numtriangles;tnum++, e += 3)
        {
@@ -653,17 +667,6 @@ void Mod_BuildTextureVectorsAndNormals(int firstvertex, int numvertices, int num
                tdir[1] = tc10[0] * v20[1] - tc20[0] * v10[1];
                tdir[2] = tc10[0] * v20[2] - tc20[0] * v10[2];
 
-               // make the tangents completely perpendicular to the surface normal
-               // 12 multiply, 4 add, 6 subtract
-               f = DotProduct(sdir, normal);
-               sdir[0] -= f * normal[0];
-               sdir[1] -= f * normal[1];
-               sdir[2] -= f * normal[2];
-               f = DotProduct(tdir, normal);
-               tdir[0] -= f * normal[0];
-               tdir[1] -= f * normal[1];
-               tdir[2] -= f * normal[2];
-
                // if texture is mapped the wrong way (counterclockwise), the tangents
                // have to be flipped, this is detected by calculating a normal from the
                // two tangents, and seeing if it is opposite the surface normal
@@ -679,32 +682,25 @@ void Mod_BuildTextureVectorsAndNormals(int firstvertex, int numvertices, int num
                {
                        VectorNormalize(sdir);
                        VectorNormalize(tdir);
-                       VectorNormalize(normal);
                }
-               if (svector3f)
-                       for (i = 0;i < 3;i++)
-                               VectorAdd(svector3f + e[i]*3, sdir, svector3f + e[i]*3);
-               if (tvector3f)
-                       for (i = 0;i < 3;i++)
-                               VectorAdd(tvector3f + e[i]*3, tdir, tvector3f + e[i]*3);
-               if (normal3f)
-                       for (i = 0;i < 3;i++)
-                               VectorAdd(normal3f + e[i]*3, normal, normal3f + e[i]*3);
+               for (i = 0;i < 3;i++)
+               {
+                       VectorAdd(svector3f + e[i]*3, sdir, svector3f + e[i]*3);
+                       VectorAdd(tvector3f + e[i]*3, tdir, tvector3f + e[i]*3);
+               }
+       }
+       // make the tangents completely perpendicular to the surface normal, and
+       // then normalize them
+       // 16 assignments, 2 divide, 2 sqrt, 2 negates, 14 adds, 24 multiplies
+       for (i = 0, sv = svector3f + 3 * firstvertex, tv = tvector3f + 3 * firstvertex, n = normal3f + 3 * firstvertex;i < numvertices;i++, sv += 3, tv += 3, n += 3)
+       {
+               f = -DotProduct(sv, n);
+               VectorMA(sv, f, n, sv);
+               VectorNormalize(sv);
+               f = -DotProduct(tv, n);
+               VectorMA(tv, f, n, tv);
+               VectorNormalize(tv);
        }
-       // now we could divide the vectors by the number of averaged values on
-       // each vertex...  but instead normalize them
-       // 4 assignments, 1 divide, 1 sqrt, 2 adds, 6 multiplies
-       if (svector3f)
-               for (i = 0, v = svector3f + 3 * firstvertex;i < numvertices;i++, v += 3)
-                       VectorNormalize(v);
-       // 4 assignments, 1 divide, 1 sqrt, 2 adds, 6 multiplies
-       if (tvector3f)
-               for (i = 0, v = tvector3f + 3 * firstvertex;i < numvertices;i++, v += 3)
-                       VectorNormalize(v);
-       // 4 assignments, 1 divide, 1 sqrt, 2 adds, 6 multiplies
-       if (normal3f)
-               for (i = 0, v = normal3f + 3 * firstvertex;i < numvertices;i++, v += 3)
-                       VectorNormalize(v);
 }
 
 void Mod_AllocSurfMesh(mempool_t *mempool, int numvertices, int numtriangles, qboolean lightmapoffsets, qboolean vertexcolors, qboolean neighbors)
@@ -976,13 +972,18 @@ void Mod_ShadowMesh_Free(shadowmesh_t *mesh)
        }
 }
 
-static rtexture_t *GL_TextureForSkinLayer(const unsigned char *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, qboolean force)
 {
        int i;
-       for (i = 0;i < width*height;i++)
-               if (((unsigned char *)&palette[in[i]])[3] > 0)
-                       return R_LoadTexture2D (loadmodel->texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
-       return NULL;
+       if (!force)
+       {
+               for (i = 0;i < width*height;i++)
+                       if (((unsigned char *)&palette[in[i]])[3] > 0)
+                               break;
+               if (i == width*height)
+                       return NULL;
+       }
+       return R_LoadTexture2D (loadmodel->texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
 }
 
 int Mod_LoadSkinFrame(skinframe_t *skinframe, const char *basename, int textureflags, int loadpantsandshirt, int loadglowtexture)
@@ -1044,7 +1045,7 @@ int Mod_LoadSkinFrame_Internal(skinframe_t *skinframe, const char *basename, int
                                        break;
                        if (i < width * height * 4)
                        {
-                               unsigned char *fogpixels = Mem_Alloc(loadmodel->mempool, width * height * 4);
+                               unsigned char *fogpixels = (unsigned char *)Mem_Alloc(loadmodel->mempool, width * height * 4);
                                memcpy(fogpixels, skindata, width * height * 4);
                                for (i = 0;i < width * height * 4;i += 4)
                                        fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
@@ -1071,16 +1072,16 @@ int Mod_LoadSkinFrame_Internal(skinframe_t *skinframe, const char *basename, int
                        Mem_Free(temp1);
                }
                // use either a custom palette, or the quake palette
-               skinframe->base = skinframe->merged = GL_TextureForSkinLayer(skindata, width, height, va("%s_merged", basename), palette ? palette : (loadglowtexture ? palette_nofullbrights : ((textureflags & TEXF_ALPHA) ? palette_transparent : palette_complete)), textureflags); // all
+               skinframe->base = skinframe->merged = GL_TextureForSkinLayer(skindata, width, height, va("%s_merged", basename), palette ? palette : (loadglowtexture ? palette_nofullbrights : ((textureflags & TEXF_ALPHA) ? palette_transparent : palette_complete)), textureflags, true); // all
                if (!palette && loadglowtexture)
-                       skinframe->glow = GL_TextureForSkinLayer(skindata, width, height, va("%s_glow", basename), palette_onlyfullbrights, textureflags); // glow
+                       skinframe->glow = GL_TextureForSkinLayer(skindata, width, height, va("%s_glow", basename), palette_onlyfullbrights, textureflags, false); // glow
                if (!palette && loadpantsandshirt)
                {
-                       skinframe->pants = GL_TextureForSkinLayer(skindata, width, height, va("%s_pants", basename), palette_pantsaswhite, textureflags); // pants
-                       skinframe->shirt = GL_TextureForSkinLayer(skindata, width, height, va("%s_shirt", basename), palette_shirtaswhite, textureflags); // shirt
+                       skinframe->pants = GL_TextureForSkinLayer(skindata, width, height, va("%s_pants", basename), palette_pantsaswhite, textureflags, false); // pants
+                       skinframe->shirt = GL_TextureForSkinLayer(skindata, width, height, va("%s_shirt", basename), palette_shirtaswhite, textureflags, false); // shirt
                }
                if (skinframe->pants || skinframe->shirt)
-                       skinframe->base = GL_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, textureflags); // no special colors
+                       skinframe->base = GL_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, textureflags, false); // no special colors
                if (textureflags & TEXF_ALPHA)
                {
                        // if not using a custom alphapalette, use the quake one
@@ -1090,7 +1091,7 @@ int Mod_LoadSkinFrame_Internal(skinframe_t *skinframe, const char *basename, int
                                if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
                                        break;
                        if (i < width * height)
-                               skinframe->fog = GL_TextureForSkinLayer(skindata, width, height, va("%s_fog", basename), alphapalette, textureflags); // fog mask
+                               skinframe->fog = GL_TextureForSkinLayer(skindata, width, height, va("%s_fog", basename), alphapalette, textureflags, true); // fog mask
                }
        }
        else