]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - model_brush.c
now checks that a lightmap surfacechain is not NULL before dereferencing it
[xonotic/darkplaces.git] / model_brush.c
index 91dd5a04cbc612d836ea32a5a95e6ca03b588193..7835687d56052342d8b11dc603daa125f1da079d 100644 (file)
@@ -23,6 +23,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "r_shadow.h"
 #include "polygon.h"
 #include "curves.h"
+#include "wad.h"
+
 
 // note: model_shared.c sets up r_notexture, and r_surf_notexture
 
@@ -904,6 +906,77 @@ static void Mod_Q1BSP_DecompressVis(const qbyte *in, const qbyte *inend, qbyte *
        }
 }
 
+/*
+=============
+R_Q1BSP_LoadSplitSky
+
+A sky texture is 256*128, with the right side being a masked overlay
+==============
+*/
+void R_Q1BSP_LoadSplitSky (qbyte *src, int width, int height, int bytesperpixel)
+{
+       int i, j;
+       unsigned solidpixels[128*128], alphapixels[128*128];
+
+       // if sky isn't the right size, just use it as a solid layer
+       if (width != 256 || height != 128)
+       {
+               loadmodel->brush.solidskytexture = R_LoadTexture2D(loadmodel->texturepool, "sky_solidtexture", width, height, src, bytesperpixel == 4 ? TEXTYPE_RGBA : TEXTYPE_PALETTE, TEXF_PRECACHE, bytesperpixel == 1 ? palette_complete : NULL);
+               loadmodel->brush.alphaskytexture = NULL;;
+               return;
+       }
+
+       if (bytesperpixel == 4)
+       {
+               for (i = 0;i < 128;i++)
+               {
+                       for (j = 0;j < 128;j++)
+                       {
+                               solidpixels[(i*128) + j] = ((unsigned *)src)[i*256+j+128];
+                               alphapixels[(i*128) + j] = ((unsigned *)src)[i*256+j];
+                       }
+               }
+       }
+       else
+       {
+               // make an average value for the back to avoid
+               // a fringe on the top level
+               int p, r, g, b;
+               union
+               {
+                       unsigned int i;
+                       unsigned char b[4];
+               }
+               rgba;
+               r = g = b = 0;
+               for (i = 0;i < 128;i++)
+               {
+                       for (j = 0;j < 128;j++)
+                       {
+                               rgba.i = palette_complete[src[i*256 + j + 128]];
+                               r += rgba.b[0];
+                               g += rgba.b[1];
+                               b += rgba.b[2];
+                       }
+               }
+               rgba.b[0] = r/(128*128);
+               rgba.b[1] = g/(128*128);
+               rgba.b[2] = b/(128*128);
+               rgba.b[3] = 0;
+               for (i = 0;i < 128;i++)
+               {
+                       for (j = 0;j < 128;j++)
+                       {
+                               solidpixels[(i*128) + j] = palette_complete[src[i*256 + j + 128]];
+                               alphapixels[(i*128) + j] = (p = src[i*256 + j]) ? palette_complete[p] : rgba.i;
+                       }
+               }
+       }
+
+       loadmodel->brush.solidskytexture = R_LoadTexture2D(loadmodel->texturepool, "sky_solidtexture", 128, 128, (qbyte *) solidpixels, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
+       loadmodel->brush.alphaskytexture = R_LoadTexture2D(loadmodel->texturepool, "sky_alphatexture", 128, 128, (qbyte *) alphapixels, TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
+}
+
 static void Mod_Q1BSP_LoadTextures(lump_t *l)
 {
        int i, j, k, num, max, altmax, mtwidth, mtheight, *dofs, incomplete;
@@ -1005,21 +1078,11 @@ static void Mod_Q1BSP_LoadTextures(lump_t *l)
                                data = loadimagepixels(tx->name, false, 0, 0);
                                if (data)
                                {
-                                       if (image_width == 256 && image_height == 128)
-                                       {
-                                               R_InitSky(data, 4);
-                                               Mem_Free(data);
-                                       }
-                                       else
-                                       {
-                                               Mem_Free(data);
-                                               Con_Printf("Invalid replacement texture for sky \"%s\" in %\"%s\", must be 256x128 pixels\n", tx->name, loadmodel->name);
-                                               if (mtdata != NULL)
-                                                       R_InitSky(mtdata, 1);
-                                       }
+                                       R_Q1BSP_LoadSplitSky(data, image_width, image_height, 4);
+                                       Mem_Free(data);
                                }
                                else if (mtdata != NULL)
-                                       R_InitSky(mtdata, 1);
+                                       R_Q1BSP_LoadSplitSky(mtdata, mtwidth, mtheight, 1);
                        }
                }
                else
@@ -2878,7 +2941,7 @@ extern void R_Q1BSP_DrawSky(entity_render_t *ent);
 extern void R_Q1BSP_Draw(entity_render_t *ent);
 extern void R_Q1BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outclusterlist, qbyte *outclusterpvs, int *outnumclusterspointer, int *outsurfacelist, qbyte *outsurfacepvs, int *outnumsurfacespointer);
 extern void R_Q1BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int numsurfaces, const int *surfacelist);
-extern void R_Q1BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap, int numsurfaces, const int *surfacelist);
+extern void R_Q1BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int numsurfaces, const int *surfacelist);
 void Mod_Q1BSP_Load(model_t *mod, void *buffer)
 {
        int i, j, k;
@@ -2913,11 +2976,7 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer)
        mod->brushq1.BuildPVSTextureChains = Mod_Q1BSP_BuildPVSTextureChains;
 
        if (loadmodel->isworldmodel)
-       {
                Cvar_SetValue("halflifebsp", mod->brush.ishlbsp);
-               // until we get a texture for it...
-               R_ResetQuakeSky();
-       }
 
 // swap all the lumps
        mod_base = (qbyte *)header;
@@ -3509,11 +3568,7 @@ void static Mod_Q2BSP_Load(model_t *mod, void *buffer)
                Host_Error("Mod_Q2BSP_Load: %s has wrong version number (%i, should be %i)", mod->name, i, Q2BSPVERSION);
        mod->brush.ishlbsp = false;
        if (loadmodel->isworldmodel)
-       {
                Cvar_SetValue("halflifebsp", mod->brush.ishlbsp);
-               // until we get a texture for it...
-               R_ResetQuakeSky();
-       }
 
        mod_base = (qbyte *)header;
 
@@ -3686,6 +3741,8 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l)
                                                                                else if (numparameters >= 3 && !strcasecmp(parameter[0], "animmap"))
                                                                                        strlcpy(firstpasstexturename, parameter[2], sizeof(firstpasstexturename));
                                                                        }
+                                                                       if (!strcasecmp(parameter[0], "alphafunc"))
+                                                                               flags2 |= Q3TEXTUREFLAG_ALPHATEST;
                                                                        // break out a level if it was }
                                                                        if (!strcasecmp(com_token, "}"))
                                                                                break;
@@ -3799,7 +3856,7 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l)
                                                // force transparent render path for a number of odd
                                                // shader effects to avoid bogging down the normal
                                                // render path unnecessarily
-                                               if (flags2 & (Q3TEXTUREFLAG_ADDITIVE | Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
+                                               if (flags2 & (Q3TEXTUREFLAG_ADDITIVE | Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2 | Q3TEXTUREFLAG_ALPHATEST))
                                                        flags |= Q3SURFACEPARM_TRANS;
                                                // add shader to list (shadername and flags)
                                                // actually here we just poke into the texture settings
@@ -3848,9 +3905,11 @@ parseerror:
                        //      out->surfaceparms |= Q3SURFACEPARM_TRANS;
                }
                if (!Mod_LoadSkinFrame(&out->skin, out->name, (((out->textureflags & Q3TEXTUREFLAG_NOMIPMAPS) || (out->surfaceparms & Q3SURFACEPARM_NOMIPMAPS)) ? 0 : TEXF_MIPMAP) | TEXF_ALPHA | TEXF_PRECACHE | (out->textureflags & Q3TEXTUREFLAG_NOPICMIP ? 0 : TEXF_PICMIP), false, true, true))
-                       Mod_LoadSkinFrame(&out->skin, out->firstpasstexturename, (((out->textureflags & Q3TEXTUREFLAG_NOMIPMAPS) || (out->surfaceparms & Q3SURFACEPARM_NOMIPMAPS)) ? 0 : TEXF_MIPMAP) | TEXF_ALPHA | TEXF_PRECACHE | (out->textureflags & Q3TEXTUREFLAG_NOPICMIP ? 0 : TEXF_PICMIP), false, true, true);
+                       if (!Mod_LoadSkinFrame(&out->skin, out->firstpasstexturename, (((out->textureflags & Q3TEXTUREFLAG_NOMIPMAPS) || (out->surfaceparms & Q3SURFACEPARM_NOMIPMAPS)) ? 0 : TEXF_MIPMAP) | TEXF_ALPHA | TEXF_PRECACHE | (out->textureflags & Q3TEXTUREFLAG_NOPICMIP ? 0 : TEXF_PICMIP), false, true, true))
+                               Con_Printf("%s: texture loading for shader \"%s\" failed (first layer \"%s\" not found either)\n", loadmodel->name, out->name, out->firstpasstexturename);
        }
-       Con_DPrintf("%s: %i textures missing shaders\n", loadmodel->name, c);
+       if (c)
+               Con_DPrintf("%s: %i textures missing shaders\n", loadmodel->name, c);
 }
 
 static void Mod_Q3BSP_LoadPlanes(lump_t *l)
@@ -4139,11 +4198,13 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l)
                else
                        out->effect = loadmodel->brushq3.data_effects + n;
                n = LittleLong(in->lightmapindex);
-               if (n < -1 || n >= loadmodel->brushq3.num_lightmaps)
+               if (n >= loadmodel->brushq3.num_lightmaps)
                {
-                       Con_DPrintf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid lightmapindex %i (%i lightmaps)\n", i, out->texture->name, n, loadmodel->brushq3.num_lightmaps);
+                       Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid lightmapindex %i (%i lightmaps)\n", i, out->texture->name, n, loadmodel->brushq3.num_lightmaps);
                        n = -1;
                }
+               else if (n < 0)
+                       n = -1;
                if (n == -1)
                        out->lightmaptexture = NULL;
                else
@@ -4718,7 +4779,7 @@ static void Mod_Q3BSP_LoadPVS(lump_t *l)
                // leafs to find real number of clusters
                loadmodel->brush.num_pvsclusters = 1;
                for (i = 0;i < loadmodel->brushq3.num_leafs;i++)
-                       loadmodel->brush.num_pvsclusters = min(loadmodel->brush.num_pvsclusters, loadmodel->brushq3.data_leafs[i].clusterindex + 1);
+                       loadmodel->brush.num_pvsclusters = max(loadmodel->brush.num_pvsclusters, loadmodel->brushq3.data_leafs[i].clusterindex + 1);
 
                // create clusters
                loadmodel->brush.num_pvsclusterbytes = (loadmodel->brush.num_pvsclusters + 7) / 8;
@@ -5616,7 +5677,7 @@ extern void R_Q3BSP_DrawSky(struct entity_render_s *ent);
 extern void R_Q3BSP_Draw(struct entity_render_s *ent);
 extern void R_Q3BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outclusterlist, qbyte *outclusterpvs, int *outnumclusterspointer, int *outsurfacelist, qbyte *outsurfacepvs, int *outnumsurfacespointer);
 extern void R_Q3BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int numsurfaces, const int *surfacelist);
-extern void R_Q3BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap, int numsurfaces, const int *surfacelist);
+extern void R_Q3BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int numsurfaces, const int *surfacelist);
 void Mod_Q3BSP_Load(model_t *mod, void *buffer)
 {
        int i, j, numshadowmeshtriangles;
@@ -5634,11 +5695,7 @@ void Mod_Q3BSP_Load(model_t *mod, void *buffer)
        if (i != Q3BSPVERSION)
                Host_Error("Mod_Q3BSP_Load: %s has wrong version number (%i, should be %i)", mod->name, i, Q3BSPVERSION);
        if (mod->isworldmodel)
-       {
                Cvar_SetValue("halflifebsp", false);
-               // until we get a texture for it...
-               R_ResetQuakeSky();
-       }
 
        mod->soundfromcenter = true;
        mod->TraceBox = Mod_Q3BSP_TraceBox;