]> de.git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
further cleaning of R_WorldVisibility, which now works the same on q1bsp and q3bsp...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 8 Mar 2005 13:49:25 +0000 (13:49 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 8 Mar 2005 13:49:25 +0000 (13:49 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@5061 d7cf8633-e32d-0410-b094-e92efae38249

gl_rsurf.c

index 754da44979ed7c3f0be74c3481d5ec8e6e8ef558..797a8ec268a27109f9483636d19781bbb126a424 100644 (file)
@@ -1323,83 +1323,77 @@ static void R_DrawPortals(void)
 
 void R_WorldVisibility(void)
 {
+       int i, j, *mark;
+       mleaf_t *leaf;
+       mleaf_t *viewleaf;
        model_t *model = r_refdef.worldmodel;
 
        if (!model)
                return;
 
-       if (model->type == mod_brushq3)
+       // if possible find the leaf the view origin is in
+       viewleaf = model->brushq1.PointInLeaf ? model->brushq1.PointInLeaf(model, r_vieworigin) : NULL;
+
+       // clear the visible surface flags array
+       memset(r_worldsurfacevisible, 0, model->brush.num_surfaces);
+
+       // if the user prefers surfaceworldnode (testing?) or the viewleaf could
+       // not be found, or the viewleaf is not part of the visible world
+       // (floating around in the void), use the pvs method
+       if (r_surfaceworldnode.integer || !viewleaf || viewleaf->clusterindex < 0)
        {
-               int i, j;
-               mleaf_t *leaf;
-               memset(r_worldsurfacevisible, 0, r_refdef.worldmodel->brush.num_surfaces);
-               for (j = 0, leaf = r_refdef.worldmodel->brush.data_leafs;j < r_refdef.worldmodel->brush.num_leafs;j++, leaf++)
+               // pvs method:
+               // similar to quake's RecursiveWorldNode but without cache misses
+               for (j = 0, leaf = model->brush.data_leafs;j < model->brush.num_leafs;j++, leaf++)
                {
+                       // if leaf is in current pvs and on the screen, mark its surfaces
                        if (CHECKPVSBIT(r_pvsbits, leaf->clusterindex) && !R_CullBox(leaf->mins, leaf->maxs))
                        {
                                c_leafs++;
-                               for (i = 0;i < leaf->numleafsurfaces;i++)
-                                       r_worldsurfacevisible[leaf->firstleafsurface[i]] = 1;
+                               if (leaf->numleafsurfaces)
+                                       for (i = 0, mark = leaf->firstleafsurface;i < leaf->numleafsurfaces;i++, mark++)
+                                               r_worldsurfacevisible[*mark] = true;
                        }
                }
        }
-       else if (model->type == mod_brushq1)
+       else
        {
-               int i, j, *mark;
-               mleaf_t *leaf;
-               mleaf_t *viewleaf;
                int leafstackpos;
                mportal_t *p;
                mleaf_t *leafstack[8192];
                qbyte leafvisited[32768];
-
-               viewleaf = model->brushq1.PointInLeaf(model, r_vieworigin);
-               if (!viewleaf)
-                       return;
-
-               memset(r_worldsurfacevisible, 0, r_refdef.worldmodel->brush.num_surfaces);
-               if (viewleaf->clusterindex < 0 || r_surfaceworldnode.integer)
-               {
-                       // equivilant to quake's RecursiveWorldNode but faster and more effective
-                       for (j = 0, leaf = model->brush.data_leafs;j < model->brush.num_leafs;j++, leaf++)
-                       {
-                               if (CHECKPVSBIT(r_pvsbits, leaf->clusterindex) && !R_CullBox (leaf->mins, leaf->maxs))
-                               {
-                                       c_leafs++;
-                                       if (leaf->numleafsurfaces)
-                                               for (i = 0, mark = leaf->firstleafsurface;i < leaf->numleafsurfaces;i++, mark++)
-                                                       r_worldsurfacevisible[*mark] = true;
-                               }
-                       }
+               // portal method:
+               // follows portals leading outward from viewleaf, does not venture
+               // offscreen or into leafs that are not visible, faster than Quake's
+               // RecursiveWorldNode and vastly better in unvised maps, often culls a
+               // lot of surface that pvs alone would miss
+               leafstack[0] = viewleaf;
+               leafstackpos = 1;
+               memset(leafvisited, 0, model->brush.num_leafs);
+               while (leafstackpos)
+               {
+                       c_leafs++;
+                       leaf = leafstack[--leafstackpos];
+                       leafvisited[leaf - model->brush.data_leafs] = 1;
+                       // mark any surfaces bounding this leaf
+                       if (leaf->numleafsurfaces)
+                               for (i = 0, mark = leaf->firstleafsurface;i < leaf->numleafsurfaces;i++, mark++)
+                                       r_worldsurfacevisible[*mark] = true;
+                       // follow portals into other leafs
+                       // the checks are:
+                       // if viewer is behind portal (portal faces outward into the scene)
+                       // and the portal polygon's bounding box is on the screen
+                       // and the leaf has not been visited yet
+                       // and the leaf is visible in the pvs
+                       // (the first two checks won't cause as many cache misses as the leaf checks)
+                       for (p = leaf->portals;p;p = p->next)
+                               if (DotProduct(r_vieworigin, p->plane.normal) < (p->plane.dist + 1) && !R_CullBox(p->mins, p->maxs) && !leafvisited[p->past - model->brush.data_leafs] && CHECKPVSBIT(r_pvsbits, p->past->clusterindex))
+                                       leafstack[leafstackpos++] = p->past;
                }
-               else
-               {
-                       // LordHavoc: portal-passage worldnode with PVS;
-                       // follows portals leading outward from viewleaf, does not venture
-                       // offscreen or into leafs that are not visible, faster than Quake's
-                       // RecursiveWorldNode
-                       leafstack[0] = viewleaf;
-                       leafstackpos = 1;
-                       memset(leafvisited, 0, r_refdef.worldmodel->brush.num_leafs);
-                       while (leafstackpos)
-                       {
-                               c_leafs++;
-                               leaf = leafstack[--leafstackpos];
-                               leafvisited[leaf - r_refdef.worldmodel->brush.data_leafs] = 1;
-                               // draw any surfaces bounding this leaf
-                               if (leaf->numleafsurfaces)
-                                       for (i = 0, mark = leaf->firstleafsurface;i < leaf->numleafsurfaces;i++, mark++)
-                                               r_worldsurfacevisible[*mark] = true;
-                               // follow portals into other leafs
-                               for (p = leaf->portals;p;p = p->next)
-                                       if (DotProduct(r_vieworigin, p->plane.normal) < (p->plane.dist + 1) && !leafvisited[p->past - r_refdef.worldmodel->brush.data_leafs] && CHECKPVSBIT(r_pvsbits, p->past->clusterindex) && !R_CullBox(p->mins, p->maxs))
-                                               leafstack[leafstackpos++] = p->past;
-                       }
-               }
-
-               if (r_drawportals.integer)
-                       R_DrawPortals();
        }
+
+       if (r_drawportals.integer)
+               R_DrawPortals();
 }
 
 void R_Q1BSP_DrawSky(entity_render_t *ent)