]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - model_brush.c
implemented sv_fixedframeratesingleplayer cvar
[xonotic/darkplaces.git] / model_brush.c
index 0d3f10dca050c78949108b2ac5d452a9c6123804..cd92bb8ccace9dd1058ae7b55d1e4e0a2c39e900 100644 (file)
@@ -74,8 +74,6 @@ static mleaf_t *Mod_Q1BSP_PointInLeaf(model_t *model, const vec3_t p)
        if (model == NULL)
                return NULL;
 
-       Mod_CheckLoaded(model);
-
        // LordHavoc: modified to start at first clip node,
        // in other words: first node of the (sub)model
        node = model->brush.data_nodes + model->brushq1.hulls[0].firstclipnode;
@@ -104,19 +102,84 @@ static void Mod_Q1BSP_AmbientSoundLevelsForPoint(model_t *model, const vec3_t p,
                memset(out, 0, outsize);
 }
 
+static int Mod_Q1BSP_FindBoxClusters(model_t *model, const vec3_t mins, const vec3_t maxs, int maxclusters, int *clusterlist)
+{
+       int numclusters = 0;
+       int nodestackindex = 0;
+       mnode_t *node, *nodestack[1024];
+       if (!model->brush.num_pvsclusters)
+               return -1;
+       node = model->brush.data_nodes;
+       for (;;)
+       {
+#if 1
+               if (node->plane)
+               {
+                       // node - recurse down the BSP tree
+                       int side = BoxOnPlaneSide(mins, maxs, node->plane) - 1;
+                       if (side < 2)
+                       {
+                               // box is on one side of plane, take that path
+                               node = node->children[side];
+                       }
+                       else
+                       {
+                               // box crosses plane, take one path and remember the other
+                               if (nodestackindex < 1024)
+                                       nodestack[nodestackindex++] = node->children[0];
+                               node = node->children[1];
+                       }
+                       continue;
+               }
+               else
+               {
+                       // leaf - add clusterindex to list
+                       if (numclusters < maxclusters)
+                               clusterlist[numclusters] = ((mleaf_t *)node)->clusterindex;
+                       numclusters++;
+               }
+#else
+               if (BoxesOverlap(mins, maxs, node->mins, node->maxs))
+               {
+                       if (node->plane)
+                       {
+                               if (nodestackindex < 1024)
+                                       nodestack[nodestackindex++] = node->children[0];
+                               node = node->children[1];
+                               continue;
+                       }
+                       else
+                       {
+                               // leaf - add clusterindex to list
+                               if (numclusters < maxclusters)
+                                       clusterlist[numclusters] = ((mleaf_t *)node)->clusterindex;
+                               numclusters++;
+                       }
+               }
+#endif
+               // try another path we didn't take earlier
+               if (nodestackindex == 0)
+                       break;
+               node = nodestack[--nodestackindex];
+       }
+       // return number of clusters found (even if more than the maxclusters)
+       return numclusters;
+}
+
 static int Mod_Q1BSP_BoxTouchingPVS(model_t *model, const qbyte *pvs, const vec3_t mins, const vec3_t maxs)
 {
-       int clusterindex, side, nodestackindex = 0;
+       int nodestackindex = 0;
        mnode_t *node, *nodestack[1024];
        if (!model->brush.num_pvsclusters)
                return true;
        node = model->brush.data_nodes;
        for (;;)
        {
+#if 1
                if (node->plane)
                {
                        // node - recurse down the BSP tree
-                       side = BoxOnPlaneSide(mins, maxs, node->plane) - 1;
+                       int side = BoxOnPlaneSide(mins, maxs, node->plane) - 1;
                        if (side < 2)
                        {
                                // box is on one side of plane, take that path
@@ -129,24 +192,44 @@ static int Mod_Q1BSP_BoxTouchingPVS(model_t *model, const qbyte *pvs, const vec3
                                        nodestack[nodestackindex++] = node->children[0];
                                node = node->children[1];
                        }
+                       continue;
                }
                else
                {
                        // leaf - check cluster bit
-                       clusterindex = ((mleaf_t *)node)->clusterindex;
+                       int clusterindex = ((mleaf_t *)node)->clusterindex;
                        if (CHECKPVSBIT(pvs, clusterindex))
                        {
                                // it is visible, return immediately with the news
                                return true;
                        }
+               }
+#else
+               if (BoxesOverlap(mins, maxs, node->mins, node->maxs))
+               {
+                       if (node->plane)
+                       {
+                               if (nodestackindex < 1024)
+                                       nodestack[nodestackindex++] = node->children[0];
+                               node = node->children[1];
+                               continue;
+                       }
                        else
                        {
-                               // nothing to see here, try another path we didn't take earlier
-                               if (nodestackindex == 0)
-                                       break;
-                               node = nodestack[--nodestackindex];
+                               // leaf - check cluster bit
+                               int clusterindex = ((mleaf_t *)node)->clusterindex;
+                               if (CHECKPVSBIT(pvs, clusterindex))
+                               {
+                                       // it is visible, return immediately with the news
+                                       return true;
+                               }
                        }
                }
+#endif
+               // nothing to see here, try another path we didn't take earlier
+               if (nodestackindex == 0)
+                       break;
+               node = nodestack[--nodestackindex];
        }
        // it is not visible
        return false;
@@ -154,17 +237,18 @@ static int Mod_Q1BSP_BoxTouchingPVS(model_t *model, const qbyte *pvs, const vec3
 
 static int Mod_Q1BSP_BoxTouchingLeafPVS(model_t *model, const qbyte *pvs, const vec3_t mins, const vec3_t maxs)
 {
-       int clusterindex, side, nodestackindex = 0;
+       int nodestackindex = 0;
        mnode_t *node, *nodestack[1024];
        if (!model->brush.num_leafs)
                return true;
        node = model->brush.data_nodes;
        for (;;)
        {
+#if 1
                if (node->plane)
                {
                        // node - recurse down the BSP tree
-                       side = BoxOnPlaneSide(mins, maxs, node->plane) - 1;
+                       int side = BoxOnPlaneSide(mins, maxs, node->plane) - 1;
                        if (side < 2)
                        {
                                // box is on one side of plane, take that path
@@ -177,24 +261,44 @@ static int Mod_Q1BSP_BoxTouchingLeafPVS(model_t *model, const qbyte *pvs, const
                                        nodestack[nodestackindex++] = node->children[0];
                                node = node->children[1];
                        }
+                       continue;
                }
                else
                {
                        // leaf - check cluster bit
-                       clusterindex = ((mleaf_t *)node) - model->brush.data_leafs;
+                       int clusterindex = ((mleaf_t *)node) - model->brush.data_leafs;
                        if (CHECKPVSBIT(pvs, clusterindex))
                        {
                                // it is visible, return immediately with the news
                                return true;
                        }
+               }
+#else
+               if (BoxesOverlap(mins, maxs, node->mins, node->maxs))
+               {
+                       if (node->plane)
+                       {
+                               if (nodestackindex < 1024)
+                                       nodestack[nodestackindex++] = node->children[0];
+                               node = node->children[1];
+                               continue;
+                       }
                        else
                        {
-                               // nothing to see here, try another path we didn't take earlier
-                               if (nodestackindex == 0)
-                                       break;
-                               node = nodestack[--nodestackindex];
+                               // leaf - check cluster bit
+                               int clusterindex = ((mleaf_t *)node) - model->brush.data_leafs;
+                               if (CHECKPVSBIT(pvs, clusterindex))
+                               {
+                                       // it is visible, return immediately with the news
+                                       return true;
+                               }
                        }
                }
+#endif
+               // nothing to see here, try another path we didn't take earlier
+               if (nodestackindex == 0)
+                       break;
+               node = nodestack[--nodestackindex];
        }
        // it is not visible
        return false;
@@ -202,15 +306,18 @@ static int Mod_Q1BSP_BoxTouchingLeafPVS(model_t *model, const qbyte *pvs, const
 
 static int Mod_Q1BSP_BoxTouchingVisibleLeafs(model_t *model, const qbyte *visibleleafs, const vec3_t mins, const vec3_t maxs)
 {
-       int side, nodestackindex = 0;
+       int nodestackindex = 0;
        mnode_t *node, *nodestack[1024];
+       if (!model->brush.num_leafs)
+               return true;
        node = model->brush.data_nodes;
        for (;;)
        {
+#if 1
                if (node->plane)
                {
                        // node - recurse down the BSP tree
-                       side = BoxOnPlaneSide(mins, maxs, node->plane) - 1;
+                       int side = BoxOnPlaneSide(mins, maxs, node->plane) - 1;
                        if (side < 2)
                        {
                                // box is on one side of plane, take that path
@@ -223,6 +330,7 @@ static int Mod_Q1BSP_BoxTouchingVisibleLeafs(model_t *model, const qbyte *visibl
                                        nodestack[nodestackindex++] = node->children[0];
                                node = node->children[1];
                        }
+                       continue;
                }
                else
                {
@@ -232,14 +340,32 @@ static int Mod_Q1BSP_BoxTouchingVisibleLeafs(model_t *model, const qbyte *visibl
                                // it is visible, return immediately with the news
                                return true;
                        }
+               }
+#else
+               if (BoxesOverlap(mins, maxs, node->mins, node->maxs))
+               {
+                       if (node->plane)
+                       {
+                               if (nodestackindex < 1024)
+                                       nodestack[nodestackindex++] = node->children[0];
+                               node = node->children[1];
+                               continue;
+                       }
                        else
                        {
-                               // nothing to see here, try another path we didn't take earlier
-                               if (nodestackindex == 0)
-                                       break;
-                               node = nodestack[--nodestackindex];
+                               // leaf - check if it is visible
+                               if (visibleleafs[(mleaf_t *)node - model->brush.data_leafs])
+                               {
+                                       // it is visible, return immediately with the news
+                                       return true;
+                               }
                        }
                }
+#endif
+               // nothing to see here, try another path we didn't take earlier
+               if (nodestackindex == 0)
+                       break;
+               node = nodestack[--nodestackindex];
        }
        // it is not visible
        return false;
@@ -858,7 +984,7 @@ loc0:
 
                                        for (maps = 0;maps < MAXLIGHTMAPS && surface->lightmapinfo->styles[maps] != 255;maps++)
                                        {
-                                               scale = d_lightstylevalue[surface->lightmapinfo->styles[maps]];
+                                               scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[maps]];
                                                r00 += lightmap[      0] * scale;g00 += lightmap[      1] * scale;b00 += lightmap[      2] * scale;
                                                r01 += lightmap[      3] * scale;g01 += lightmap[      4] * scale;b01 += lightmap[      5] * scale;
                                                r10 += lightmap[line3+0] * scale;g10 += lightmap[line3+1] * scale;b10 += lightmap[line3+2] * scale;
@@ -2426,7 +2552,8 @@ static void Mod_Q1BSP_FinalizePortals(void)
        mvertex_t *point;
        mleaf_t *leaf, *endleaf;
 
-       // recalculate bounding boxes for all leafs(because qbsp is very sloppy)
+       // tally up portal and point counts and recalculate bounding boxes for all
+       // leafs (because qbsp is very sloppy)
        leaf = loadmodel->brush.data_leafs;
        endleaf = leaf + loadmodel->brush.num_leafs;
        for (;leaf < endleaf;leaf++)
@@ -2435,31 +2562,6 @@ static void Mod_Q1BSP_FinalizePortals(void)
                VectorSet(leaf->maxs, -2000000000, -2000000000, -2000000000);
        }
        p = portalchain;
-       while (p)
-       {
-               if (p->numpoints >= 3)
-               {
-                       for (i = 0;i < 2;i++)
-                       {
-                               leaf = (mleaf_t *)p->nodes[i];
-                               for (j = 0;j < p->numpoints;j++)
-                               {
-                                       if (leaf->mins[0] > p->points[j*3+0]) leaf->mins[0] = p->points[j*3+0];
-                                       if (leaf->mins[1] > p->points[j*3+1]) leaf->mins[1] = p->points[j*3+1];
-                                       if (leaf->mins[2] > p->points[j*3+2]) leaf->mins[2] = p->points[j*3+2];
-                                       if (leaf->maxs[0] < p->points[j*3+0]) leaf->maxs[0] = p->points[j*3+0];
-                                       if (leaf->maxs[1] < p->points[j*3+1]) leaf->maxs[1] = p->points[j*3+1];
-                                       if (leaf->maxs[2] < p->points[j*3+2]) leaf->maxs[2] = p->points[j*3+2];
-                               }
-                       }
-               }
-               p = p->chain;
-       }
-
-       Mod_Q1BSP_RecursiveRecalcNodeBBox(loadmodel->brush.data_nodes);
-
-       // tally up portal and point counts
-       p = portalchain;
        numportals = 0;
        numpoints = 0;
        while (p)
@@ -2489,59 +2591,78 @@ static void Mod_Q1BSP_FinalizePortals(void)
        {
                pnext = p->chain;
 
-               // note: this check must match the one above or it will usually corrupt memory
-               // 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->numpoints >= 3 && p->nodes[0] != p->nodes[1] && ((mleaf_t *)p->nodes[0])->clusterindex >= 0 && ((mleaf_t *)p->nodes[1])->clusterindex >= 0)
+               if (p->numpoints >= 3 && p->nodes[0] != p->nodes[1])
                {
-                       // first make the back to front portal(forward portal)
-                       portal->points = point;
-                       portal->numpoints = p->numpoints;
-                       portal->plane.dist = p->plane.dist;
-                       VectorCopy(p->plane.normal, portal->plane.normal);
-                       portal->here = (mleaf_t *)p->nodes[1];
-                       portal->past = (mleaf_t *)p->nodes[0];
-                       // copy points
-                       for (j = 0;j < portal->numpoints;j++)
+                       // note: this check must match the one above or it will usually corrupt memory
+                       // 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 (((mleaf_t *)p->nodes[0])->clusterindex >= 0 && ((mleaf_t *)p->nodes[1])->clusterindex >= 0)
                        {
-                               VectorCopy(p->points + j*3, point->position);
-                               point++;
+                               // first make the back to front portal(forward portal)
+                               portal->points = point;
+                               portal->numpoints = p->numpoints;
+                               portal->plane.dist = p->plane.dist;
+                               VectorCopy(p->plane.normal, portal->plane.normal);
+                               portal->here = (mleaf_t *)p->nodes[1];
+                               portal->past = (mleaf_t *)p->nodes[0];
+                               // copy points
+                               for (j = 0;j < portal->numpoints;j++)
+                               {
+                                       VectorCopy(p->points + j*3, point->position);
+                                       point++;
+                               }
+                               BoxFromPoints(portal->mins, portal->maxs, portal->numpoints, portal->points->position);
+                               PlaneClassify(&portal->plane);
+
+                               // link into leaf's portal chain
+                               portal->next = portal->here->portals;
+                               portal->here->portals = portal;
+
+                               // advance to next portal
+                               portal++;
+
+                               // then make the front to back portal(backward portal)
+                               portal->points = point;
+                               portal->numpoints = p->numpoints;
+                               portal->plane.dist = -p->plane.dist;
+                               VectorNegate(p->plane.normal, portal->plane.normal);
+                               portal->here = (mleaf_t *)p->nodes[0];
+                               portal->past = (mleaf_t *)p->nodes[1];
+                               // copy points
+                               for (j = portal->numpoints - 1;j >= 0;j--)
+                               {
+                                       VectorCopy(p->points + j*3, point->position);
+                                       point++;
+                               }
+                               BoxFromPoints(portal->mins, portal->maxs, portal->numpoints, portal->points->position);
+                               PlaneClassify(&portal->plane);
+
+                               // link into leaf's portal chain
+                               portal->next = portal->here->portals;
+                               portal->here->portals = portal;
+
+                               // advance to next portal
+                               portal++;
                        }
-                       BoxFromPoints(portal->mins, portal->maxs, portal->numpoints, portal->points->position);
-                       PlaneClassify(&portal->plane);
-
-                       // link into leaf's portal chain
-                       portal->next = portal->here->portals;
-                       portal->here->portals = portal;
-
-                       // advance to next portal
-                       portal++;
-
-                       // then make the front to back portal(backward portal)
-                       portal->points = point;
-                       portal->numpoints = p->numpoints;
-                       portal->plane.dist = -p->plane.dist;
-                       VectorNegate(p->plane.normal, portal->plane.normal);
-                       portal->here = (mleaf_t *)p->nodes[0];
-                       portal->past = (mleaf_t *)p->nodes[1];
-                       // copy points
-                       for (j = portal->numpoints - 1;j >= 0;j--)
+                       // add the portal's polygon points to the leaf bounding boxes
+                       for (i = 0;i < 2;i++)
                        {
-                               VectorCopy(p->points + j*3, point->position);
-                               point++;
+                               leaf = (mleaf_t *)p->nodes[i];
+                               for (j = 0;j < p->numpoints;j++)
+                               {
+                                       if (leaf->mins[0] > p->points[j*3+0]) leaf->mins[0] = p->points[j*3+0];
+                                       if (leaf->mins[1] > p->points[j*3+1]) leaf->mins[1] = p->points[j*3+1];
+                                       if (leaf->mins[2] > p->points[j*3+2]) leaf->mins[2] = p->points[j*3+2];
+                                       if (leaf->maxs[0] < p->points[j*3+0]) leaf->maxs[0] = p->points[j*3+0];
+                                       if (leaf->maxs[1] < p->points[j*3+1]) leaf->maxs[1] = p->points[j*3+1];
+                                       if (leaf->maxs[2] < p->points[j*3+2]) leaf->maxs[2] = p->points[j*3+2];
+                               }
                        }
-                       BoxFromPoints(portal->mins, portal->maxs, portal->numpoints, portal->points->position);
-                       PlaneClassify(&portal->plane);
-
-                       // link into leaf's portal chain
-                       portal->next = portal->here->portals;
-                       portal->here->portals = portal;
-
-                       // advance to next portal
-                       portal++;
                }
                FreePortal(p);
                p = pnext;
        }
+       // now recalculate the node bounding boxes from the leafs
+       Mod_Q1BSP_RecursiveRecalcNodeBBox(loadmodel->brush.data_nodes);
 }
 
 /*
@@ -2813,7 +2934,6 @@ static void Mod_Q1BSP_BuildLightmapUpdateChains(mempool_t *mempool, model_t *mod
 static qbyte *Mod_Q1BSP_GetPVS(model_t *model, const vec3_t p)
 {
        mnode_t *node;
-       Mod_CheckLoaded(model);
        node = model->brush.data_nodes;
        while (node->plane)
                node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct(p,node->plane->normal)) < node->plane->dist];
@@ -3013,6 +3133,7 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer, void *bufferend)
        mod->brush.BoxTouchingPVS = Mod_Q1BSP_BoxTouchingPVS;
        mod->brush.BoxTouchingLeafPVS = Mod_Q1BSP_BoxTouchingLeafPVS;
        mod->brush.BoxTouchingVisibleLeafs = Mod_Q1BSP_BoxTouchingVisibleLeafs;
+       mod->brush.FindBoxClusters = Mod_Q1BSP_FindBoxClusters;
        mod->brush.LightPoint = Mod_Q1BSP_LightPoint;
        mod->brush.FindNonSolidLocation = Mod_Q1BSP_FindNonSolidLocation;
        mod->brush.AmbientSoundLevelsForPoint = Mod_Q1BSP_AmbientSoundLevelsForPoint;
@@ -3164,6 +3285,7 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer, void *bufferend)
                        mod->brush.BoxTouchingPVS = NULL;
                        mod->brush.BoxTouchingLeafPVS = NULL;
                        mod->brush.BoxTouchingVisibleLeafs = NULL;
+                       mod->brush.FindBoxClusters = NULL;
                        mod->brush.LightPoint = NULL;
                        mod->brush.AmbientSoundLevelsForPoint = NULL;
                }
@@ -4969,7 +5091,7 @@ static void Mod_Q3BSP_TraceLine_RecursiveBSPNode(trace_t *trace, model_t *model,
 static void Mod_Q3BSP_TraceBrush_RecursiveBSPNode(trace_t *trace, model_t *model, mnode_t *node, const colbrushf_t *thisbrush_start, const colbrushf_t *thisbrush_end, int markframe, const vec3_t segmentmins, const vec3_t segmentmaxs)
 {
        int i;
-       //int sides;
+       int sides;
        float nodesegmentmins[3], nodesegmentmaxs[3];
        mleaf_t *leaf;
        colbrushf_t *brush;
@@ -5190,6 +5312,57 @@ static void Mod_Q3BSP_TraceBrush_RecursiveBSPNode(trace_t *trace, model_t *model
                }
        */
 #if 1
+       for (;;)
+       {
+               mplane_t *plane = node->plane;
+               if (!plane)
+                       break;
+               // axial planes are much more common than non-axial, so an optimized
+               // axial case pays off here
+               if (plane->type < 3)
+               {
+                       // this is an axial plane, compare bounding box directly to it and
+                       // recurse sides accordingly
+                       // recurse down node sides
+                       // use an inlined axial BoxOnPlaneSide to slightly reduce overhead
+                       //sides = BoxOnPlaneSide(nodesegmentmins, nodesegmentmaxs, plane);
+                       sides = ((segmentmaxs[plane->type] >= plane->dist) | ((segmentmins[plane->type] < plane->dist) << 1));
+                       if (sides == 3)
+                       {
+                               // segment box crosses plane
+                               Mod_Q3BSP_TraceBrush_RecursiveBSPNode(trace, model, node->children[0], thisbrush_start, thisbrush_end, markframe, segmentmins, segmentmaxs);
+                               sides = 2;
+                       }
+               }
+               else
+               {
+                       // this is a non-axial plane, entire trace bounding box
+                       // comparisons against it are likely to be very sloppy, so in if
+                       // the whole box is split by the plane we then test the start/end
+                       // boxes against it to be sure
+                       sides = BoxOnPlaneSide(segmentmins, segmentmaxs, plane);
+                       if (sides == 3)
+                       {
+                               // segment box crosses plane
+                               // now check start and end brush boxes to handle a lot of 'diagonal' cases more efficiently...
+                               sides = BoxOnPlaneSide(thisbrush_start->mins, thisbrush_start->maxs, plane) | BoxOnPlaneSide(thisbrush_end->mins, thisbrush_end->maxs, plane);
+                               if (sides == 3)
+                               {
+                                       Mod_Q3BSP_TraceBrush_RecursiveBSPNode(trace, model, node->children[0], thisbrush_start, thisbrush_end, markframe, segmentmins, segmentmaxs);
+                                       sides = 2;
+                               }
+                       }
+               }
+               // take whichever side the segment box is on
+               node = node->children[sides - 1];
+       }
+       nodesegmentmins[0] = max(segmentmins[0], node->mins[0]);
+       nodesegmentmins[1] = max(segmentmins[1], node->mins[1]);
+       nodesegmentmins[2] = max(segmentmins[2], node->mins[2]);
+       nodesegmentmaxs[0] = min(segmentmaxs[0], node->maxs[0]);
+       nodesegmentmaxs[1] = min(segmentmaxs[1], node->maxs[1]);
+       nodesegmentmaxs[2] = min(segmentmaxs[2], node->maxs[2]);
+#elif 1
        for (;;)
        {
                nodesegmentmins[0] = max(segmentmins[0], node->mins[0]);
@@ -5514,6 +5687,7 @@ void Mod_Q3BSP_Load(model_t *mod, void *buffer, void *bufferend)
        mod->brush.BoxTouchingPVS = Mod_Q1BSP_BoxTouchingPVS;
        mod->brush.BoxTouchingLeafPVS = Mod_Q1BSP_BoxTouchingLeafPVS;
        mod->brush.BoxTouchingVisibleLeafs = Mod_Q1BSP_BoxTouchingVisibleLeafs;
+       mod->brush.FindBoxClusters = Mod_Q1BSP_FindBoxClusters;
        mod->brush.LightPoint = Mod_Q3BSP_LightPoint;
        mod->brush.FindNonSolidLocation = Mod_Q1BSP_FindNonSolidLocation;
        mod->brush.PointInLeaf = Mod_Q1BSP_PointInLeaf;
@@ -5605,6 +5779,7 @@ void Mod_Q3BSP_Load(model_t *mod, void *buffer, void *bufferend)
                        mod->brush.BoxTouchingPVS = NULL;
                        mod->brush.BoxTouchingLeafPVS = NULL;
                        mod->brush.BoxTouchingVisibleLeafs = NULL;
+                       mod->brush.FindBoxClusters = NULL;
                        mod->brush.LightPoint = NULL;
                        mod->brush.FindNonSolidLocation = Mod_Q1BSP_FindNonSolidLocation;
                }