]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - model_brush.c
don't change gamma ramps when running dedicated
[xonotic/darkplaces.git] / model_brush.c
index f1f87b8c27e3fa301a8fcc09fbc7bd243e1019f7..d2cee3f5fcdd1d92de8dc4161ff52656e9b51d4d 100644 (file)
@@ -8,7 +8,7 @@ of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 See the GNU General Public License for more details.
 
@@ -24,8 +24,9 @@ byte  mod_novis[MAX_MAP_LEAFS/8];
 
 qboolean       hlbsp; // LordHavoc: true if it is a HalfLife BSP file (version 30)
 
-cvar_t gl_subdivide_size = {"gl_subdivide_size", "128", true};
-cvar_t halflifebsp = {"halflifebsp", "0"};
+cvar_t gl_subdivide_size = {CVAR_SAVE, "gl_subdivide_size", "128"};
+cvar_t halflifebsp = {0, "halflifebsp", "0"};
+cvar_t r_novis = {0, "r_novis", "0"};
 
 /*
 ===============
@@ -36,6 +37,7 @@ void Mod_BrushInit (void)
 {
        Cvar_RegisterVariable (&gl_subdivide_size);
        Cvar_RegisterVariable (&halflifebsp);
+       Cvar_RegisterVariable (&r_novis);
        memset (mod_novis, 0xff, sizeof(mod_novis));
 }
 
@@ -52,16 +54,11 @@ mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
 //             Sys_Error ("Mod_PointInLeaf: bad model");
 
        node = model->nodes;
-       if (node->contents < 0)
-               return (mleaf_t *)node;
-       while (1)
-       {
+       do
                node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct (p,node->plane->normal)) < node->plane->dist];
-               if (node->contents < 0)
-                       return (mleaf_t *)node;
-       }
-       
-       return NULL;    // never reached
+       while (node->contents == 0);
+
+       return (mleaf_t *)node;
 }
 /*
 mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
@@ -85,7 +82,7 @@ mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
                else
                        node = node->children[1];
        }
-       
+
        return NULL;    // never reached
 }
 */
@@ -102,9 +99,10 @@ byte *Mod_DecompressVis (byte *in, model_t *model)
        byte    *out;
        int             row;
 
-       row = (model->numleafs+7)>>3;   
+       row = (model->numleafs+7)>>3;
        out = decompressed;
 
+       /*
        if (!in)
        {       // no vis info, so make all visible
                while (row)
@@ -114,6 +112,7 @@ byte *Mod_DecompressVis (byte *in, model_t *model)
                }
                return decompressed;            
        }
+       */
 
        do
        {
@@ -137,19 +136,15 @@ byte *Mod_DecompressVis (byte *in, model_t *model)
 
 byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model)
 {
-       if (leaf == model->leafs)
+       if (r_novis.value || leaf == model->leafs || leaf->compressed_vis == NULL)
                return mod_novis;
        return Mod_DecompressVis (leaf->compressed_vis, model);
 }
 
-extern byte    *mod_base;
-
-extern cvar_t r_fullbrights;
-
 rtexture_t *r_notexture;
 texture_t r_notexture_mip;
 
-void Mod_SetupNoTexture()
+void Mod_SetupNoTexture(void)
 {
        int             x, y;
        byte    pix[16][16][4];
@@ -250,6 +245,12 @@ void Mod_LoadTextures (lump_t *l)
                for (;j < 16;j++)
                        tx->name[j] = 0;
 
+               if (!tx->name[0])
+               {
+                       Con_Printf("warning: unnamed texture in %s\n", loadname);
+                       sprintf(tx->name, "unnamed%i", i);
+               }
+
                tx->transparent = false;
                data = loadimagepixels(tx->name, false, 0, 0);
                if (data)
@@ -541,10 +542,6 @@ void Mod_LoadVisibility (lump_t *l)
        memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen);
 }
 
-void CL_ParseEntityLump(char *entdata);
-
-extern qboolean isworldmodel;
-
 /*
 =================
 Mod_LoadEntities
@@ -616,7 +613,8 @@ void Mod_LoadSubmodels (lump_t *l)
        for ( i=0 ; i<count ; i++, in++, out++)
        {
                for (j=0 ; j<3 ; j++)
-               {       // spread the mins / maxs by a pixel
+               {
+                       // spread the mins / maxs by a pixel
                        out->mins[j] = LittleFloat (in->mins[j]) - 1;
                        out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
                        out->origin[j] = LittleFloat (in->origin[j]);
@@ -761,8 +759,6 @@ void CalcSurfaceExtents (msurface_t *s)
 
 void GL_SubdivideSurface (msurface_t *fa);
 
-extern char skyname[];
-
 /*
 =================
 Mod_LoadFaces
@@ -800,7 +796,7 @@ void Mod_LoadFaces (lump_t *l)
                out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo);
 
                CalcSurfaceExtents (out);
-                               
+
        // lighting info
 
                for (i=0 ; i<MAXLIGHTMAPS ; i++)
@@ -822,7 +818,7 @@ void Mod_LoadFaces (lump_t *l)
                 && (out->texinfo->texture->name[2] == 'y' || out->texinfo->texture->name[2] == 'Y'))
                {
                        // LordHavoc: for consistency reasons, mark sky as fullbright and solid as well
-                       out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED | SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA);
+                       out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED | SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA | SURF_CLIPSOLID);
                        GL_SubdivideSurface (out);      // cut up polygon for warps
                        continue;
                }
@@ -844,7 +840,8 @@ void Mod_LoadFaces (lump_t *l)
                        GL_SubdivideSurface (out);      // cut up polygon for warps
                        continue;
                }
-
+               
+               out->flags |= SURF_CLIPSOLID;
        }
 }
 
@@ -950,7 +947,6 @@ void Mod_LoadLeafs (lump_t *l)
                        out->compressed_vis = NULL;
                else
                        out->compressed_vis = loadmodel->visdata + p;
-//             out->efrags = NULL;
                
                for (j=0 ; j<4 ; j++)
                        out->ambient_sound_level[j] = in->ambient_level[j];
@@ -1159,7 +1155,6 @@ void Mod_LoadPlanes (lump_t *l)
        mplane_t        *out;
        dplane_t        *in;
        int                     count;
-       int                     bits;
        
        in = (void *)(mod_base + l->fileofs);
        if (l->filelen % sizeof(*in))
@@ -1172,18 +1167,13 @@ void Mod_LoadPlanes (lump_t *l)
 
        for ( i=0 ; i<count ; i++, in++, out++)
        {
-               bits = 0;
                for (j=0 ; j<3 ; j++)
-               {
                        out->normal[j] = LittleFloat (in->normal[j]);
-//                     if (out->normal[j] < 0)
-//                             bits |= 1<<j;
-               }
 
                out->dist = LittleFloat (in->dist);
-               out->type = LittleLong (in->type);
-//             out->signbits = bits;
-               BoxOnPlaneSideClassify(out);
+               // LordHavoc: recalculated by PlaneClassify, FIXME: validate type and report error if type does not match normal?
+//             out->type = LittleLong (in->type);
+               PlaneClassify(out);
        }
 }
 
@@ -1210,7 +1200,7 @@ winding_t *NewWinding (int points)
                Host_Error("NewWinding: too many points\n");
 
        size = (int)((winding_t *)0)->points[points];
-       w = malloc (size);
+       w = qmalloc (size);
        memset (w, 0, size);
 
        return w;
@@ -1218,7 +1208,7 @@ winding_t *NewWinding (int points)
 
 void FreeWinding (winding_t *w)
 {
-       free (w);
+       qfree (w);
 }
 
 /*
@@ -1486,25 +1476,87 @@ AllocPortal
 portal_t *AllocPortal (void)
 {
        portal_t *p;
-       p = malloc(sizeof(portal_t));
+       p = qmalloc(sizeof(portal_t));
        memset(p, 0, sizeof(portal_t));
        p->chain = portalchain;
        portalchain = p;
        return p;
 }
 
-void Mod_FinalizePortals()
+void Mod_RecursiveRecalcNodeBBox(mnode_t *node)
+{
+       // calculate children first
+       if (node->children[0]->contents >= 0)
+               Mod_RecursiveRecalcNodeBBox(node->children[0]);
+       if (node->children[1]->contents >= 0)
+               Mod_RecursiveRecalcNodeBBox(node->children[1]);
+
+       // make combined bounding box from children
+       node->mins[0] = min(node->children[0]->mins[0], node->children[1]->mins[0]);
+       node->mins[1] = min(node->children[0]->mins[1], node->children[1]->mins[1]);
+       node->mins[2] = min(node->children[0]->mins[2], node->children[1]->mins[2]);
+       node->maxs[0] = max(node->children[0]->maxs[0], node->children[1]->maxs[0]);
+       node->maxs[1] = max(node->children[0]->maxs[1], node->children[1]->maxs[1]);
+       node->maxs[2] = max(node->children[0]->maxs[2], node->children[1]->maxs[2]);
+}
+
+void Mod_FinalizePortals(void)
 {
        int i, j, numportals, numpoints;
        portal_t *p, *pnext;
        mportal_t *portal;
        mvertex_t *point;
+       mleaf_t *leaf, *endleaf;
+       winding_t *w;
+
+       // recalculate bounding boxes for all leafs (because qbsp is very sloppy)
+       leaf = loadmodel->leafs;
+       endleaf = leaf + loadmodel->numleafs;
+       for (;leaf < endleaf;leaf++)
+       {
+               VectorSet( 2000000000,  2000000000,  2000000000, leaf->mins);
+               VectorSet(-2000000000, -2000000000, -2000000000, leaf->maxs);
+       }
+       p = portalchain;
+       while(p)
+       {
+               if (p->winding)
+               {
+                       for (i = 0;i < 2;i++)
+                       {
+                               leaf = (mleaf_t *)p->nodes[i];
+                               w = p->winding;
+                               for (j = 0;j < w->numpoints;j++)
+                               {
+                                       if (leaf->mins[0] > w->points[j][0]) leaf->mins[0] = w->points[j][0];
+                                       if (leaf->mins[1] > w->points[j][1]) leaf->mins[1] = w->points[j][1];
+                                       if (leaf->mins[2] > w->points[j][2]) leaf->mins[2] = w->points[j][2];
+                                       if (leaf->maxs[0] < w->points[j][0]) leaf->maxs[0] = w->points[j][0];
+                                       if (leaf->maxs[1] < w->points[j][1]) leaf->maxs[1] = w->points[j][1];
+                                       if (leaf->maxs[2] < w->points[j][2]) leaf->maxs[2] = w->points[j][2];
+                               }
+                       }
+               }
+               p = p->chain;
+       }
+
+//     Hunk_Check();
+
+       Mod_RecursiveRecalcNodeBBox(loadmodel->nodes);
+
+//     Hunk_Check();
+
+       // tally up portal and point counts
        p = portalchain;
        numportals = 0;
        numpoints = 0;
        while(p)
        {
-               if (p->winding && p->nodes[0] != p->nodes[1] && p->nodes[0]->contents != CONTENTS_SOLID && p->nodes[1]->contents != CONTENTS_SOLID)
+               // note: this check must match the one below or it will usually corrupt the hunk
+               // the nodes[0] != nodes[1] check is because leaf 0 is the shared solid leaf, it can have many portals inside with leaf 0 on both sides
+               if (p->winding && p->nodes[0] != p->nodes[1]
+                && p->nodes[0]->contents != CONTENTS_SOLID && p->nodes[1]->contents != CONTENTS_SOLID
+                && p->nodes[0]->contents != CONTENTS_SKY && p->nodes[1]->contents != CONTENTS_SKY)
                {
                        numportals += 2;
                        numpoints += p->winding->numpoints * 2;
@@ -1529,8 +1581,11 @@ void Mod_FinalizePortals()
 
                if (p->winding)
                {
+                       // note: this check must match the one below or it will usually corrupt the hunk
                        // the nodes[0] != nodes[1] check is because leaf 0 is the shared solid leaf, it can have many portals inside with leaf 0 on both sides
-                       if (p->nodes[0] != p->nodes[1] && p->nodes[0]->contents != CONTENTS_SOLID && p->nodes[1]->contents != CONTENTS_SOLID)
+                       if (p->nodes[0] != p->nodes[1]
+                        && p->nodes[0]->contents != CONTENTS_SOLID && p->nodes[1]->contents != CONTENTS_SOLID
+                        && p->nodes[0]->contents != CONTENTS_SKY && p->nodes[1]->contents != CONTENTS_SKY)
                        {
                                // first make the back to front portal (forward portal)
                                portal->points = point;
@@ -1545,6 +1600,7 @@ void Mod_FinalizePortals()
                                        VectorCopy(p->winding->points[j], point->position);
                                        point++;
                                }
+                               PlaneClassify(&portal->plane);
 
                                // link into leaf's portal chain
                                portal->next = portal->here->portals;
@@ -1566,6 +1622,7 @@ void Mod_FinalizePortals()
                                        VectorCopy(p->winding->points[j], point->position);
                                        point++;
                                }
+                               PlaneClassify(&portal->plane);
 
                                // link into leaf's portal chain
                                portal->next = portal->here->portals;
@@ -1576,7 +1633,7 @@ void Mod_FinalizePortals()
                        }
                        FreeWinding(p->winding);
                }
-               free(p);
+               qfree(p);
                p = pnext;
        }
 }
@@ -1620,7 +1677,7 @@ void RemovePortalFromNodes(portal_t *portal)
        {
                node = portal->nodes[i];
 
-               portalpointer = &node->portals;
+               portalpointer = (void **) &node->portals;
                while (1)
                {
                        t = *portalpointer;
@@ -1636,7 +1693,7 @@ void RemovePortalFromNodes(portal_t *portal)
                                }
                                else if (portal->nodes[1] == node)
                                {
-                                       *portalpointer = portal->next[1];       
+                                       *portalpointer = portal->next[1];
                                        portal->nodes[1] = NULL;
                                }
                                else
@@ -1645,9 +1702,9 @@ void RemovePortalFromNodes(portal_t *portal)
                        }
 
                        if (t->nodes[0] == node)
-                               portalpointer = &t->next[0];
+                               portalpointer = (void **) &t->next[0];
                        else if (t->nodes[1] == node)
-                               portalpointer = &t->next[1];
+                               portalpointer = (void **) &t->next[1];
                        else
                                Host_Error ("RemovePortalFromNodes: portal not bounding leaf");
                }
@@ -1815,7 +1872,7 @@ void Mod_MakeOutsidePortals(mnode_t *node)
 }
 */
 
-void Mod_MakePortals()
+void Mod_MakePortals(void)
 {
 //     Con_Printf("building portals for %s\n", loadmodel->name);
 
@@ -1835,9 +1892,9 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
        int                     i, j;
        dheader_t       *header;
        dmodel_t        *bm;
-       
+
        loadmodel->type = mod_brush;
-       
+
        header = (dheader_t *)buffer;
 
        i = LittleLong (header->version);
@@ -1853,7 +1910,7 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
                ((int *)header)[i] = LittleLong ( ((int *)header)[i]);
 
 // load into heap
-       
+
        // LordHavoc: had to move entity loading above everything to allow parsing various settings from worldspawn
        Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
 
@@ -1876,9 +1933,9 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
        Mod_MakeHull0 ();
 
        Mod_MakePortals();
-       
+
        mod->numframes = 2;             // regular and alternate animation
-       
+
 //
 // set up the submodels (FIXME: this is confusing)
 //
@@ -1892,10 +1949,10 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
                        mod->hulls[j].firstclipnode = bm->headnode[j];
                        mod->hulls[j].lastclipnode = mod->numclipnodes - 1;
                }
-               
+
                mod->firstmodelsurface = bm->firstface;
                mod->nummodelsurfaces = bm->numfaces;
-               
+
                VectorCopy (bm->maxs, mod->maxs);
                VectorCopy (bm->mins, mod->mins);