]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - model_brush.c
r_showtris/r_shownormals/r_showcollisionbrushes are no longer obscured
[xonotic/darkplaces.git] / model_brush.c
index e1accd99ede0d2eff3a55a554c4a98fd7d5d746c..00df8ca01600c66aa9a8e7205238eb83e6da867b 100644 (file)
@@ -1761,13 +1761,13 @@ static void Mod_Q1BSP_ParseWadsFromEntityLump(const char *data)
        int i, j, k;
        if (!data)
                return;
-       if (!COM_ParseToken_Simple(&data, false))
+       if (!COM_ParseToken_Simple(&data, false, false))
                return; // error
        if (com_token[0] != '{')
                return; // error
        while (1)
        {
-               if (!COM_ParseToken_Simple(&data, false))
+               if (!COM_ParseToken_Simple(&data, false, false))
                        return; // error
                if (com_token[0] == '}')
                        break; // end of worldspawn
@@ -1777,7 +1777,7 @@ static void Mod_Q1BSP_ParseWadsFromEntityLump(const char *data)
                        strlcpy(key, com_token, sizeof(key));
                while (key[strlen(key)-1] == ' ') // remove trailing spaces
                        key[strlen(key)-1] = 0;
-               if (!COM_ParseToken_Simple(&data, false))
+               if (!COM_ParseToken_Simple(&data, false, false))
                        return; // error
                dpsnprintf(value, sizeof(value), "%s", com_token);
                if (!strcmp("wad", key)) // for HalfLife maps
@@ -2191,7 +2191,7 @@ static void Mod_Q1BSP_LoadFaces(lump_t *l)
        totaltris = 0;
        for (surfacenum = 0, in = (dface_t *)(mod_base + l->fileofs);surfacenum < count;surfacenum++, in++)
        {
-               numedges = LittleShort(in->numedges);
+               numedges = (unsigned short)LittleShort(in->numedges);
                totalverts += numedges;
                totaltris += numedges - 2;
        }
@@ -2212,16 +2212,16 @@ static void Mod_Q1BSP_LoadFaces(lump_t *l)
 
                // FIXME: validate edges, texinfo, etc?
                firstedge = LittleLong(in->firstedge);
-               numedges = LittleShort(in->numedges);
+               numedges = (unsigned short)LittleShort(in->numedges);
                if ((unsigned int) firstedge > (unsigned int) loadmodel->brushq1.numsurfedges || (unsigned int) numedges > (unsigned int) loadmodel->brushq1.numsurfedges || (unsigned int) firstedge + (unsigned int) numedges > (unsigned int) loadmodel->brushq1.numsurfedges)
                        Host_Error("Mod_Q1BSP_LoadFaces: invalid edge range (firstedge %i, numedges %i, model edges %i)", firstedge, numedges, loadmodel->brushq1.numsurfedges);
-               i = LittleShort(in->texinfo);
+               i = (unsigned short)LittleShort(in->texinfo);
                if ((unsigned int) i >= (unsigned int) loadmodel->brushq1.numtexinfo)
                        Host_Error("Mod_Q1BSP_LoadFaces: invalid texinfo index %i(model has %i texinfos)", i, loadmodel->brushq1.numtexinfo);
                surface->lightmapinfo->texinfo = loadmodel->brushq1.texinfo + i;
                surface->texture = surface->lightmapinfo->texinfo->texture;
 
-               planenum = LittleShort(in->planenum);
+               planenum = (unsigned short)LittleShort(in->planenum);
                if ((unsigned int) planenum >= (unsigned int) loadmodel->brush.num_planes)
                        Host_Error("Mod_Q1BSP_LoadFaces: invalid plane index %i (model has %i planes)", planenum, loadmodel->brush.num_planes);
 
@@ -2475,16 +2475,45 @@ static void Mod_Q1BSP_LoadNodes(lump_t *l)
                p = LittleLong(in->planenum);
                out->plane = loadmodel->brush.data_planes + p;
 
-               out->firstsurface = LittleShort(in->firstface);
-               out->numsurfaces = LittleShort(in->numfaces);
+               out->firstsurface = (unsigned short)LittleShort(in->firstface);
+               out->numsurfaces = (unsigned short)LittleShort(in->numfaces);
 
                for (j=0 ; j<2 ; j++)
                {
-                       p = LittleShort(in->children[j]);
-                       if (p >= 0)
-                               out->children[j] = loadmodel->brush.data_nodes + p;
+                       // LordHavoc: this code supports more than 32768 nodes or leafs,
+                       // by simply assuming that there are no more than 65536 combined,
+                       // this makes it compatible with the broken arguire qbsp utility
+                       // which can produce more than 32768 nodes (breaking the format)
+                       // note that arguire light and vis utilities still crash on this
+                       //
+                       // I do not encourage support for this weirdness, this code was
+                       // reworked simply to allow flying around leaky maps that exceed
+                       // the limits, with the assumption that a final compile will be
+                       // valid after the leak is fixed.
+                       p = (unsigned short)LittleShort(in->children[j]);
+                       if (p < 65536 - loadmodel->brush.num_leafs)
+                       {
+                               if (p < loadmodel->brush.num_nodes)
+                                       out->children[j] = loadmodel->brush.data_nodes + p;
+                               else
+                               {
+                                       Con_Printf("Mod_Q1BSP_LoadNodes: invalid node index %i (file has only %i nodes)\n", p, loadmodel->brush.num_nodes);
+                                       // map it to the solid leaf
+                                       out->children[j] = (mnode_t *)loadmodel->brush.data_leafs;
+                               }
+                       }
                        else
-                               out->children[j] = (mnode_t *)(loadmodel->brush.data_leafs + (-1 - p));
+                       {
+                               p = 65535 - p;
+                               if (p < loadmodel->brush.num_leafs)
+                                       out->children[j] = (mnode_t *)(loadmodel->brush.data_leafs + p);
+                               else
+                               {
+                                       Con_Printf("Mod_Q1BSP_LoadNodes: invalid leaf index %i (file has only %i leafs)\n", p, loadmodel->brush.num_leafs);
+                                       // map it to the solid leaf
+                                       out->children[j] = (mnode_t *)loadmodel->brush.data_leafs;
+                               }
+                       }
                }
        }
 
@@ -2523,9 +2552,9 @@ static void Mod_Q1BSP_LoadLeafs(lump_t *l)
 
                out->contents = LittleLong(in->contents);
 
-               out->firstleafsurface = loadmodel->brush.data_leafsurfaces + LittleShort(in->firstmarksurface);
-               out->numleafsurfaces = LittleShort(in->nummarksurfaces);
-               if (out->firstleafsurface < 0 || LittleShort(in->firstmarksurface) + out->numleafsurfaces > loadmodel->brush.num_leafsurfaces)
+               out->firstleafsurface = loadmodel->brush.data_leafsurfaces + (unsigned short)LittleShort(in->firstmarksurface);
+               out->numleafsurfaces = (unsigned short)LittleShort(in->nummarksurfaces);
+               if (out->firstleafsurface < 0 || (unsigned short)LittleShort(in->firstmarksurface) + out->numleafsurfaces > loadmodel->brush.num_leafsurfaces)
                {
                        Con_Printf("Mod_Q1BSP_LoadLeafs: invalid leafsurface range %i:%i outside range %i:%i\n", (int)(out->firstleafsurface - loadmodel->brush.data_leafsurfaces), (int)(out->firstleafsurface + out->numleafsurfaces - loadmodel->brush.data_leafsurfaces), 0, loadmodel->brush.num_leafsurfaces);
                        out->firstleafsurface = NULL;
@@ -2655,7 +2684,7 @@ static void Mod_Q1BSP_LoadLeaffaces(lump_t *l)
 
        for (i = 0;i < loadmodel->brush.num_leafsurfaces;i++)
        {
-               j = (unsigned) LittleShort(in[i]);
+               j = (unsigned short) LittleShort(in[i]);
                if (j >= loadmodel->num_surfaces)
                        Host_Error("Mod_Q1BSP_LoadLeaffaces: bad surface number");
                loadmodel->brush.data_leafsurfaces[i] = j;
@@ -2716,12 +2745,12 @@ static void Mod_Q1BSP_LoadMapBrushes(void)
        if (!maptext)
                return;
        text = maptext;
-       if (!COM_ParseToken_Simple(&data, false))
+       if (!COM_ParseToken_Simple(&data, false, false))
                return; // error
        submodel = 0;
        for (;;)
        {
-               if (!COM_ParseToken_Simple(&data, false))
+               if (!COM_ParseToken_Simple(&data, false, false))
                        break;
                if (com_token[0] != '{')
                        return; // error
@@ -2732,7 +2761,7 @@ static void Mod_Q1BSP_LoadMapBrushes(void)
                brushes = Mem_Alloc(loadmodel->mempool, maxbrushes * sizeof(mbrush_t));
                for (;;)
                {
-                       if (!COM_ParseToken_Simple(&data, false))
+                       if (!COM_ParseToken_Simple(&data, false, false))
                                return; // error
                        if (com_token[0] == '}')
                                break; // end of entity
@@ -2756,7 +2785,7 @@ static void Mod_Q1BSP_LoadMapBrushes(void)
                                }
                                for (;;)
                                {
-                                       if (!COM_ParseToken_Simple(&data, false))
+                                       if (!COM_ParseToken_Simple(&data, false, false))
                                                return; // error
                                        if (com_token[0] == '}')
                                                break; // end of brush
@@ -2765,25 +2794,25 @@ static void Mod_Q1BSP_LoadMapBrushes(void)
                                        // FIXME: support hl .map format
                                        for (pointnum = 0;pointnum < 3;pointnum++)
                                        {
-                                               COM_ParseToken_Simple(&data, false);
+                                               COM_ParseToken_Simple(&data, false, false);
                                                for (componentnum = 0;componentnum < 3;componentnum++)
                                                {
-                                                       COM_ParseToken_Simple(&data, false);
+                                                       COM_ParseToken_Simple(&data, false, false);
                                                        point[pointnum][componentnum] = atof(com_token);
                                                }
-                                               COM_ParseToken_Simple(&data, false);
+                                               COM_ParseToken_Simple(&data, false, false);
                                        }
-                                       COM_ParseToken_Simple(&data, false);
+                                       COM_ParseToken_Simple(&data, false, false);
                                        strlcpy(facetexture, com_token, sizeof(facetexture));
-                                       COM_ParseToken_Simple(&data, false);
+                                       COM_ParseToken_Simple(&data, false, false);
                                        //scroll_s = atof(com_token);
-                                       COM_ParseToken_Simple(&data, false);
+                                       COM_ParseToken_Simple(&data, false, false);
                                        //scroll_t = atof(com_token);
-                                       COM_ParseToken_Simple(&data, false);
+                                       COM_ParseToken_Simple(&data, false, false);
                                        //rotate = atof(com_token);
-                                       COM_ParseToken_Simple(&data, false);
+                                       COM_ParseToken_Simple(&data, false, false);
                                        //scale_s = atof(com_token);
-                                       COM_ParseToken_Simple(&data, false);
+                                       COM_ParseToken_Simple(&data, false, false);
                                        //scale_t = atof(com_token);
                                        TriangleNormal(point[0], point[1], point[2], planenormal);
                                        VectorNormalizeDouble(planenormal);
@@ -3280,7 +3309,7 @@ static void Mod_Q1BSP_FatPVS_RecursiveBSPNode(model_t *model, const vec3_t org,
 
 //Calculates a PVS that is the inclusive or of all leafs within radius pixels
 //of the given point.
-static int Mod_Q1BSP_FatPVS(model_t *model, const vec3_t org, vec_t radius, unsigned char *pvsbuffer, int pvsbufferlength)
+static int Mod_Q1BSP_FatPVS(model_t *model, const vec3_t org, vec_t radius, unsigned char *pvsbuffer, int pvsbufferlength, qboolean merge)
 {
        int bytes = model->brush.num_pvsclusterbytes;
        bytes = min(bytes, pvsbufferlength);
@@ -3289,7 +3318,8 @@ static int Mod_Q1BSP_FatPVS(model_t *model, const vec3_t org, vec_t radius, unsi
                memset(pvsbuffer, 0xFF, bytes);
                return bytes;
        }
-       memset(pvsbuffer, 0, bytes);
+       if (!merge)
+               memset(pvsbuffer, 0, bytes);
        Mod_Q1BSP_FatPVS_RecursiveBSPNode(model, org, radius, pvsbuffer, bytes, model->brush.data_nodes);
        return bytes;
 }
@@ -3595,10 +3625,12 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer, void *bufferend)
                for (j = 0;j < mod->nummodelsurfaces;j++)
                        mod->surfacelist[j] = mod->firstmodelsurface + j;
 
-               // this gets altered below if sky is used
+               // this gets altered below if sky or water is used
                mod->DrawSky = NULL;
+               mod->DrawAddWaterPlanes = NULL;
                mod->Draw = R_Q1BSP_Draw;
                mod->DrawDepth = R_Q1BSP_DrawDepth;
+               mod->DrawDebug = R_Q1BSP_DrawDebug;
                mod->GetLightInfo = R_Q1BSP_GetLightInfo;
                mod->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
                mod->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
@@ -3628,6 +3660,8 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer, void *bufferend)
                                // we only need to have a drawsky function if it is used(usually only on world model)
                                if (surface->texture->basematerialflags & MATERIALFLAG_SKY)
                                        mod->DrawSky = R_Q1BSP_DrawSky;
+                               if (surface->texture->basematerialflags & MATERIALFLAG_WATERALPHA)
+                                       mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
                                // calculate bounding shapes
                                for (k = 0, vec = (loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex);k < surface->num_vertices;k++, vec += 3)
                                {
@@ -4132,11 +4166,11 @@ static void Mod_Q3BSP_LoadEntities(lump_t *l)
        memcpy(loadmodel->brush.entities, mod_base + l->fileofs, l->filelen);
        data = loadmodel->brush.entities;
        // some Q3 maps override the lightgrid_cellsize with a worldspawn key
-       if (data && COM_ParseToken_Simple(&data, false) && com_token[0] == '{')
+       if (data && COM_ParseToken_Simple(&data, false, false) && com_token[0] == '{')
        {
                while (1)
                {
-                       if (!COM_ParseToken_Simple(&data, false))
+                       if (!COM_ParseToken_Simple(&data, false, false))
                                break; // error
                        if (com_token[0] == '}')
                                break; // end of worldspawn
@@ -4146,7 +4180,7 @@ static void Mod_Q3BSP_LoadEntities(lump_t *l)
                                strlcpy(key, com_token, sizeof(key));
                        while (key[strlen(key)-1] == ' ') // remove trailing spaces
                                key[strlen(key)-1] = 0;
-                       if (!COM_ParseToken_Simple(&data, false))
+                       if (!COM_ParseToken_Simple(&data, false, false))
                                break; // error
                        strlcpy(value, com_token, sizeof(value));
                        if (!strcmp("gridsize", key))
@@ -5585,10 +5619,12 @@ void Mod_Q3BSP_Load(model_t *mod, void *buffer, void *bufferend)
        mod->brush.PointInLeaf = Mod_Q1BSP_PointInLeaf;
        mod->Draw = R_Q1BSP_Draw;
        mod->DrawDepth = R_Q1BSP_DrawDepth;
+       mod->DrawDebug = R_Q1BSP_DrawDebug;
        mod->GetLightInfo = R_Q1BSP_GetLightInfo;
        mod->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
        mod->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
        mod->DrawLight = R_Q1BSP_DrawLight;
+       mod->DrawAddWaterPlanes = NULL;
 
        mod_base = (unsigned char *)header;
 
@@ -5720,12 +5756,20 @@ void Mod_Q3BSP_Load(model_t *mod, void *buffer, void *bufferend)
                mod->radius2 = modelradius * modelradius;
 
                for (j = 0;j < mod->nummodelsurfaces;j++)
-                       if (mod->data_surfaces[j + mod->firstmodelsurface].texture->surfaceflags & Q3SURFACEFLAG_SKY)
+                       if (mod->data_surfaces[j + mod->firstmodelsurface].texture->basematerialflags & MATERIALFLAG_SKY)
                                break;
                if (j < mod->nummodelsurfaces)
                        mod->DrawSky = R_Q1BSP_DrawSky;
                else
                        mod->DrawSky = NULL;
+
+               for (j = 0;j < mod->nummodelsurfaces;j++)
+                       if (mod->data_surfaces[j + mod->firstmodelsurface].texture->basematerialflags & MATERIALFLAG_WATERALPHA)
+                               break;
+               if (j < mod->nummodelsurfaces)
+                       mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
+               else
+                       mod->DrawAddWaterPlanes = NULL;
        }
 }