more hackish cleanups of PVS stuff, now decompresses the PVS data at load and this...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 13 Aug 2003 02:17:16 +0000 (02:17 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 13 Aug 2003 02:17:16 +0000 (02:17 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@3393 d7cf8633-e32d-0410-b094-e92efae38249

gl_rsurf.c
model_brush.c
model_brush.h
model_shared.h
pr_cmds.c
r_light.c
r_shadow.c

index 4727958..fe81def 100644 (file)
@@ -1713,9 +1713,9 @@ static void R_PortalWorldNode(entity_render_t *ent, mleaf_t *viewleaf)
 
 void R_PVSUpdate (entity_render_t *ent, mleaf_t *viewleaf)
 {
-       int i, j, l, c, bits, *surfacepvsframes, *mark;
+       int j, c, *surfacepvsframes, *mark;
        mleaf_t *leaf;
-       qbyte *vis;
+       qbyte *pvs;
        model_t *model;
 
        model = ent->model;
@@ -1728,29 +1728,19 @@ void R_PVSUpdate (entity_render_t *ent, mleaf_t *viewleaf)
                model->brushq1.pvssurflistlength = 0;
                if (viewleaf)
                {
+                       pvs = viewleaf->pvsdata;
                        surfacepvsframes = model->brushq1.surfacepvsframes;
-                       vis = model->brushq1.LeafPVS(model, viewleaf);
-                       for (j = 0;j < model->brushq1.numleafs;j += 8)
+                       for (j = 0;j < model->brushq1.numleafs-1;j++)
                        {
-                               bits = *vis++;
-                               if (bits)
+                               if (pvs[j >> 3] & (1 << (j & 7)))
                                {
-                                       l = model->brushq1.numleafs - j;
-                                       if (l > 8)
-                                               l = 8;
-                                       for (i = 0;i < l;i++)
-                                       {
-                                               if (bits & (1 << i))
-                                               {
-                                                       leaf = &model->brushq1.leafs[j + i + 1];
-                                                       leaf->pvschain = model->brushq1.pvsleafchain;
-                                                       model->brushq1.pvsleafchain = leaf;
-                                                       leaf->pvsframe = model->brushq1.pvsframecount;
-                                                       // mark surfaces bounding this leaf as visible
-                                                       for (c = leaf->nummarksurfaces, mark = leaf->firstmarksurface;c;c--, mark++)
-                                                               surfacepvsframes[*mark] = model->brushq1.pvsframecount;
-                                               }
-                                       }
+                                       leaf = model->brushq1.leafs + j + 1;
+                                       leaf->pvsframe = model->brushq1.pvsframecount;
+                                       leaf->pvschain = model->brushq1.pvsleafchain;
+                                       model->brushq1.pvsleafchain = leaf;
+                                       // mark surfaces bounding this leaf as visible
+                                       for (c = leaf->nummarksurfaces, mark = leaf->firstmarksurface;c;c--, mark++)
+                                               surfacepvsframes[*mark] = model->brushq1.pvsframecount;
                                }
                        }
                        model->brushq1.BuildPVSTextureChains(model);
index 7a99e9f..e20c570 100644 (file)
@@ -648,41 +648,32 @@ void Mod_Q1BSP_LightPoint(model_t *model, const vec3_t p, vec3_t ambientcolor, v
        Mod_Q1BSP_LightPoint_RecursiveBSPNode(ambientcolor, diffusecolor, diffusenormal, cl.worldmodel->brushq1.nodes + cl.worldmodel->brushq1.hulls[0].firstclipnode, p[0], p[1], p[2], p[2] - 65536);
 }
 
-static qbyte *Mod_Q1BSP_DecompressVis(model_t *model, qbyte *in)
+static void Mod_Q1BSP_DecompressVis(const qbyte *in, const qbyte *inend, qbyte *out, qbyte *outend)
 {
-       static qbyte decompressed[MAX_MAP_LEAFS/8];
        int c;
-       qbyte *out;
-       int row;
-
-       row = (model->brushq1.numleafs+7)>>3;
-       out = decompressed;
-
-       do
+       while (out < outend)
        {
-               if (*in)
+               if (in == inend)
                {
-                       *out++ = *in++;
-                       continue;
+                       Con_Printf("Mod_Q1BSP_DecompressVis: input underrun\n");
+                       return;
                }
-
-               c = in[1];
-               in += 2;
-               while (c)
+               c = *in++;
+               if (c)
+                       *out++ = c;
+               else
                {
-                       *out++ = 0;
-                       c--;
+                       for (c = *in++;c > 0;c--)
+                       {
+                               if (out == outend)
+                               {
+                                       Con_Printf("Mod_Q1BSP_DecompressVis: output overrun\n");
+                                       return;
+                               }
+                               *out++ = 0;
+                       }
                }
-       } while (out - decompressed < row);
-
-       return decompressed;
-}
-
-static qbyte *Mod_Q1BSP_LeafPVS(model_t *model, mleaf_t *leaf)
-{
-       if (r_novis.integer || leaf == model->brushq1.leafs || leaf->compressed_vis == NULL)
-               return mod_q1bsp_novis;
-       return Mod_Q1BSP_DecompressVis(model, leaf->compressed_vis);
+       }
 }
 
 static void Mod_Q1BSP_LoadTextures(lump_t *l)
@@ -1364,11 +1355,13 @@ static void Mod_Q1BSP_ProcessLightList(void)
 
 static void Mod_Q1BSP_LoadVisibility(lump_t *l)
 {
-       loadmodel->brushq1.visdata = NULL;
+       loadmodel->brushq1.num_compressedpvs = 0;
+       loadmodel->brushq1.data_compressedpvs = NULL;
        if (!l->filelen)
                return;
-       loadmodel->brushq1.visdata = Mem_Alloc(loadmodel->mempool, l->filelen);
-       memcpy(loadmodel->brushq1.visdata, mod_base + l->fileofs, l->filelen);
+       loadmodel->brushq1.num_compressedpvs = l->filelen;
+       loadmodel->brushq1.data_compressedpvs = Mem_Alloc(loadmodel->mempool, l->filelen);
+       memcpy(loadmodel->brushq1.data_compressedpvs, mod_base + l->fileofs, l->filelen);
 }
 
 // used only for HalfLife maps
@@ -2012,9 +2005,10 @@ static void Mod_Q1BSP_LoadNodes(lump_t *l)
 
 static void Mod_Q1BSP_LoadLeafs(lump_t *l)
 {
-       dleaf_t         *in;
-       mleaf_t         *out;
-       int                     i, j, count, p;
+       dleaf_t *in;
+       mleaf_t *out;
+       int i, j, count, p, pvschainbytes;
+       qbyte *pvs;
 
        in = (void *)(mod_base + l->fileofs);
        if (l->filelen % sizeof(*in))
@@ -2024,6 +2018,8 @@ static void Mod_Q1BSP_LoadLeafs(lump_t *l)
 
        loadmodel->brushq1.leafs = out;
        loadmodel->brushq1.numleafs = count;
+       pvschainbytes = ((loadmodel->brushq1.num_leafs - 1)+7)>>3;
+       loadmodel->brushq1.data_decompressedpvs = pvs = Mem_Alloc(loadmodel->mempool, loadmodel->brushq1.numleafs * pvschainbytes);
 
        for ( i=0 ; i<count ; i++, in++, out++)
        {
@@ -2033,20 +2029,23 @@ static void Mod_Q1BSP_LoadLeafs(lump_t *l)
                        out->maxs[j] = LittleShort(in->maxs[j]);
                }
 
-               p = LittleLong(in->contents);
-               out->contents = p;
+               // FIXME: this function could really benefit from some error checking
+
+               out->contents = LittleLong(in->contents);
 
-               out->firstmarksurface = loadmodel->brushq1.marksurfaces +
-                       LittleShort(in->firstmarksurface);
+               out->firstmarksurface = loadmodel->brushq1.marksurfaces + LittleShort(in->firstmarksurface);
                out->nummarksurfaces = LittleShort(in->nummarksurfaces);
 
+               out->pvsdata = pvs;
+               pvs += pvschainbytes;
+
                p = LittleLong(in->visofs);
-               if (p == -1)
-                       out->compressed_vis = NULL;
+               if (p >= 0)
+                       Mod_Q1BSP_DecompressVis(loadmodel->brushq1.data_compressedpvs + p, loadmodel->brushq1.data_compressedpvs + loadmodel->brushq1.num_compressedpvs, out->pvsdata, out->pvsdata + pvschainbytes);
                else
-                       out->compressed_vis = loadmodel->brushq1.visdata + p;
+                       memset(out->pvsdata, 0xFF, pvschainbytes);
 
-               for (j=0 ; j<4 ; j++)
+               for (j = 0;j < 4;j++)
                        out->ambient_sound_level[j] = in->ambient_level[j];
 
                // FIXME: Insert caustics here
@@ -3041,7 +3040,6 @@ static void Mod_Q1BSP_BuildPVSTextureChains(model_t *model)
 void Mod_Q1BSP_FatPVS_RecursiveBSPNode(model_t *model, const vec3_t org, vec_t radius, qbyte *pvsbuffer, int pvsbytes, mnode_t *node)
 {
        int i;
-       qbyte *pvs;
        mplane_t *plane;
        float d;
 
@@ -3050,12 +3048,9 @@ void Mod_Q1BSP_FatPVS_RecursiveBSPNode(model_t *model, const vec3_t org, vec_t r
        // if this is a leaf, accumulate the pvs bits
                if (node->contents < 0)
                {
-                       if (node->contents != CONTENTS_SOLID)
-                       {
-                               pvs = model->brushq1.LeafPVS(model, (mleaf_t *)node);
+                       if (node->contents != CONTENTS_SOLID && ((mleaf_t *)node)->pvsdata)
                                for (i = 0;i < pvsbytes;i++)
-                                       pvsbuffer[i] |= pvs[i];
-                       }
+                                       pvsbuffer[i] |= ((mleaf_t *)node)->pvsdata[i];
                        return;
                }
 
@@ -3077,9 +3072,8 @@ void Mod_Q1BSP_FatPVS_RecursiveBSPNode(model_t *model, const vec3_t org, vec_t r
 //of the given point.
 int Mod_Q1BSP_FatPVS(model_t *model, const vec3_t org, vec_t radius, qbyte *pvsbuffer, int pvsbufferlength)
 {
-       int bytes = (sv.worldmodel->brushq1.numleafs+31)>>3;
-       if (bytes > pvsbufferlength)
-               bytes = pvsbufferlength;
+       int bytes = ((model->brushq1.num_leafs - 1) + 7) >> 3;
+       bytes = min(bytes, pvsbufferlength);
        memset(pvsbuffer, 0, bytes);
        Mod_Q1BSP_FatPVS_RecursiveBSPNode(model, org, radius, pvsbuffer, bytes, sv.worldmodel->brushq1.nodes);
        return bytes;
@@ -3116,7 +3110,6 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer)
        mod->brush.FindNonSolidLocation = Mod_Q1BSP_FindNonSolidLocation;
        mod->brush.TraceBox = Mod_Q1BSP_TraceBox;
        mod->brushq1.PointInLeaf = Mod_Q1BSP_PointInLeaf;
-       mod->brushq1.LeafPVS = Mod_Q1BSP_LeafPVS;
        mod->brushq1.BuildPVSTextureChains = Mod_Q1BSP_BuildPVSTextureChains;
 
        if (loadmodel->isworldmodel)
@@ -3153,9 +3146,17 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer)
        Mod_Q1BSP_LoadClipnodes(&header->lumps[LUMP_CLIPNODES]);
        Mod_Q1BSP_LoadSubmodels(&header->lumps[LUMP_MODELS]);
 
+       if (mod->brushq1.data_compressedpvs)
+               Mem_Free(mod->brushq1.data_compressedpvs);
+       mod->brushq1.data_compressedpvs = NULL;
+       mod->brushq1.num_compressedpvs = 0;
+
        Mod_Q1BSP_MakeHull0();
        Mod_Q1BSP_MakePortals();
 
+       if (developer.integer)
+               Con_Printf("Some stats for q1bsp model \"%s\": %i faces, %i nodes, %i leafs, %i visleafs, %i visleafportals\n", loadmodel->name, loadmodel->brushq1.numsurfaces, loadmodel->brushq1.numnodes, loadmodel->brushq1.numleafs, loadmodel->brushq1.num_leafs - 1, loadmodel->brushq1.numportals);
+
        mod->numframes = 2;             // regular and alternate animation
 
        mainmempool = mod->mempool;
@@ -4556,7 +4557,6 @@ void Mod_Q3BSP_Load(model_t *mod, void *buffer)
        mod->brush.FindNonSolidLocation = Mod_Q3BSP_FindNonSolidLocation;
        mod->brush.TraceBox = Mod_Q3BSP_TraceBox;
        //mod->brushq1.PointInLeaf = Mod_Q1BSP_PointInLeaf;
-       //mod->brushq1.LeafPVS = Mod_Q1BSP_LeafPVS;
        //mod->brushq1.BuildPVSTextureChains = Mod_Q1BSP_BuildPVSTextureChains;
 
        mod_base = (qbyte *)header;
index 5772df2..17e6935 100644 (file)
@@ -276,7 +276,9 @@ typedef struct mleaf_s
        // used by polygon-through-portals visibility checker
        int portalmarkid;
 
-       qbyte *compressed_vis;
+       // decompressed pvs bits (potentially visible set)
+       // note: never NULL, always present, may be full of 0xFF though
+       qbyte *pvsdata;
 
        int *firstmarksurface;
        int nummarksurfaces;
index a911946..7023822 100644 (file)
@@ -207,7 +207,11 @@ typedef struct model_brushq1_s
        int                             numtextures;
        texture_t               *textures;
 
-       qbyte                   *visdata;
+       int                             num_compressedpvs;
+       qbyte                   *data_compressedpvs;
+       qbyte                   *data_decompressedpvs;
+
+       int                             num_lightdata;
        qbyte                   *lightdata;
 
        int                             numportals;
@@ -242,7 +246,6 @@ typedef struct model_brushq1_s
        float                   light_ambient;
 
        mleaf_t *(*PointInLeaf)(struct model_s *model, const float *p);
-       qbyte *(*LeafPVS)(struct model_s *model, mleaf_t *leaf);
        void (*BuildPVSTextureChains)(struct model_s *model);
 }
 model_brushq1_t;
index b34e6b7..c0d6e44 100644 (file)
--- a/pr_cmds.c
+++ b/pr_cmds.c
@@ -818,6 +818,7 @@ void PF_checkpos (void)
 
 //============================================================================
 
+int checkpvsbytes;
 qbyte checkpvs[MAX_MAP_LEAFS/8];
 
 int PF_newcheckclient (int check)
@@ -851,8 +852,10 @@ int PF_newcheckclient (int check)
        }
 
 // get the PVS for the entity
-       VectorAdd (ent->v->origin, ent->v->view_ofs, org);
-       memcpy (checkpvs, sv.worldmodel->brushq1.LeafPVS(sv.worldmodel, sv.worldmodel->brushq1.PointInLeaf(sv.worldmodel, org)), (sv.worldmodel->brushq1.numleafs+7)>>3 );
+       VectorAdd(ent->v->origin, ent->v->view_ofs, org);
+       checkpvsbytes = 0;
+       if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
+               checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
 
        return i;
 }
@@ -876,8 +879,6 @@ int c_invis, c_notvis;
 void PF_checkclient (void)
 {
        edict_t *ent, *self;
-       mleaf_t *leaf;
-       int             l;
        vec3_t  view;
 
        // find a new check if on a new frame
@@ -897,17 +898,12 @@ void PF_checkclient (void)
 
        // if current entity can't possibly see the check entity, return 0
        self = PROG_TO_EDICT(pr_global_struct->self);
-       VectorAdd (self->v->origin, self->v->view_ofs, view);
-       leaf = sv.worldmodel->brushq1.PointInLeaf(sv.worldmodel, view);
-       if (leaf)
+       VectorAdd(self->v->origin, self->v->view_ofs, view);
+       if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
        {
-               l = (leaf - sv.worldmodel->brushq1.leafs) - 1;
-               if ( (l<0) || !(checkpvs[l>>3] & (1<<(l&7)) ) )
-               {
-                       c_notvis++;
-                       RETURN_EDICT(sv.edicts);
-                       return;
-               }
+               c_notvis++;
+               RETURN_EDICT(sv.edicts);
+               return;
        }
 
        // might be able to see it
index 0a3e27f..9fd7478 100644 (file)
--- a/r_light.c
+++ b/r_light.c
@@ -173,255 +173,111 @@ DYNAMIC LIGHTS
 =============================================================================
 */
 
+static int lightpvsbytes;
+static qbyte lightpvs[(MAX_MAP_LEAFS+7)>>3];
+
 /*
 =============
 R_MarkLights
 =============
 */
-static void R_OldMarkLights (entity_render_t *ent, vec3_t lightorigin, rdlight_t *rd, int bit, int bitindex, mnode_t *node)
+static void R_RecursiveMarkLights(entity_render_t *ent, vec3_t lightorigin, rdlight_t *rd, int bit, int bitindex, mnode_t *node, qbyte *pvs, int pvsbits)
 {
-       float ndist, maxdist;
-       msurface_t *surf;
-       int i, *surfacepvsframes;
-       int d, impacts, impactt;
-       float dist, dist2, impact[3];
-
-       if (!r_dynamic.integer)
-               return;
+       int i;
+       mleaf_t *leaf;
+       float dist;
 
        // for comparisons to minimum acceptable light
-       maxdist = rd->cullradius2;
-
-       surfacepvsframes = ent->model->brushq1.surfacepvsframes;
-loc0:
-       if (node->contents < 0)
-               return;
-
-       ndist = PlaneDiff(lightorigin, node->plane);
-
-       if (ndist > rd->cullradius)
+       while(node->contents >= 0)
        {
-               node = node->children[0];
-               goto loc0;
-       }
-       if (ndist < -rd->cullradius)
-       {
-               node = node->children[1];
-               goto loc0;
-       }
-
-// mark the polygons
-       surf = ent->model->brushq1.surfaces + node->firstsurface;
-       for (i = 0;i < node->numsurfaces;i++, surf++)
-       {
-               if (surfacepvsframes[surf->number] != ent->model->brushq1.pvsframecount)
-                       continue;
-               dist = ndist;
-               if (surf->flags & SURF_PLANEBACK)
-                       dist = -dist;
-
-               if (dist < -0.25f && !(surf->flags & SURF_LIGHTBOTHSIDES))
-                       continue;
-
-               dist2 = dist * dist;
-               if (dist2 >= maxdist)
-                       continue;
-
-               if (node->plane->type < 3)
-               {
-                       VectorCopy(lightorigin, impact);
-                       impact[node->plane->type] -= dist;
-               }
+               dist = PlaneDiff(lightorigin, node->plane);
+               if (dist > rd->cullradius)
+                       node = node->children[0];
                else
                {
-                       impact[0] = lightorigin[0] - surf->plane->normal[0] * dist;
-                       impact[1] = lightorigin[1] - surf->plane->normal[1] * dist;
-                       impact[2] = lightorigin[2] - surf->plane->normal[2] * dist;
-               }
-
-               impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
-
-               d = bound(0, impacts, surf->extents[0] + 16) - impacts;
-               dist2 += d * d;
-               if (dist2 > maxdist)
-                       continue;
-
-               impactt = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1];
-
-               d = bound(0, impactt, surf->extents[1] + 16) - impactt;
-               dist2 += d * d;
-               if (dist2 > maxdist)
-                       continue;
-
-               if (surf->dlightframe != r_framecount) // not dynamic until now
-               {
-                       surf->dlightbits[0] = surf->dlightbits[1] = surf->dlightbits[2] = surf->dlightbits[3] = surf->dlightbits[4] = surf->dlightbits[5] = surf->dlightbits[6] = surf->dlightbits[7] = 0;
-                       surf->dlightframe = r_framecount;
-                       if (r_dlightmap.integer)
-                               surf->cached_dlight = true;
+                       if (dist >= -rd->cullradius)
+                               R_RecursiveMarkLights(ent, lightorigin, rd, bit, bitindex, node->children[0], pvs, pvsbits);
+                       node = node->children[1];
                }
-               surf->dlightbits[bitindex] |= bit;
        }
 
-       if (node->children[0]->contents >= 0)
+       // check if leaf is visible according to pvs
+       leaf = (mleaf_t *)node;
+       i = (leaf - ent->model->brushq1.leafs) - 1;
+       if (leaf->nummarksurfaces && (i >= pvsbits || pvs[i >> 3] & (1 << (i & 7))))
        {
-               if (node->children[1]->contents >= 0)
-               {
-                       R_OldMarkLights (ent, lightorigin, rd, bit, bitindex, node->children[0]);
-                       node = node->children[1];
-                       goto loc0;
-               }
-               else
+               int *surfacepvsframes, d, impacts, impactt;
+               float sdist, maxdist, dist2, impact[3];
+               msurface_t *surf;
+               // mark the polygons
+               maxdist = rd->cullradius2;
+               surfacepvsframes = ent->model->brushq1.surfacepvsframes;
+               for (i = 0;i < leaf->nummarksurfaces;i++)
                {
-                       node = node->children[0];
-                       goto loc0;
-               }
-       }
-       else if (node->children[1]->contents >= 0)
-       {
-               node = node->children[1];
-               goto loc0;
-       }
-}
+                       if (surfacepvsframes[leaf->firstmarksurface[i]] != ent->model->brushq1.pvsframecount)
+                               continue;
+                       surf = ent->model->brushq1.surfaces + leaf->firstmarksurface[i];
+                       dist = sdist = PlaneDiff(lightorigin, surf->plane);
+                       if (surf->flags & SURF_PLANEBACK)
+                               dist = -dist;
 
+                       if (dist < -0.25f && !(surf->flags & SURF_LIGHTBOTHSIDES))
+                               continue;
 
-static void R_VisMarkLights (entity_render_t *ent, rdlight_t *rd, int bit, int bitindex)
-{
-       static int lightframe = 0;
-       mleaf_t *pvsleaf;
-       vec3_t lightorigin;
-       model_t *model;
-       int i, k, m, c, leafnum, *surfacepvsframes, *mark;
-       msurface_t *surf;
-       mleaf_t *leaf;
-       qbyte *in;
-       int row;
-       float low[3], high[3], dist, maxdist;
+                       dist2 = dist * dist;
+                       if (dist2 >= maxdist)
+                               continue;
 
-       if (!r_dynamic.integer || !ent->model)
-               return;
-
-       Matrix4x4_Transform(&ent->inversematrix, rd->origin, lightorigin);
-
-       model = ent->model;
-       pvsleaf = model->brushq1.PointInLeaf(model, lightorigin);
-       if (pvsleaf == NULL)
-               return;
-
-       in = pvsleaf->compressed_vis;
-       if (!r_vismarklights.integer || !in)
-       {
-               // told not to use pvs, or there's no pvs to use
-               R_OldMarkLights(ent, lightorigin, rd, bit, bitindex, model->brushq1.nodes + model->brushq1.hulls[0].firstclipnode);
-               return;
-       }
+                       VectorCopy(lightorigin, impact);
+                       if (surf->plane->type >= 3)
+                               VectorMA(impact, -sdist, surf->plane->normal, impact);
+                       else
+                               impact[surf->plane->type] -= sdist;
 
-       lightframe++;
+                       impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
 
-       low[0] = lightorigin[0] - rd->cullradius;low[1] = lightorigin[1] - rd->cullradius;low[2] = lightorigin[2] - rd->cullradius;
-       high[0] = lightorigin[0] + rd->cullradius;high[1] = lightorigin[1] + rd->cullradius;high[2] = lightorigin[2] + rd->cullradius;
+                       d = bound(0, impacts, surf->extents[0] + 16) - impacts;
+                       dist2 += d * d;
+                       if (dist2 > maxdist)
+                               continue;
 
-       // for comparisons to minimum acceptable light
-       maxdist = rd->cullradius2;
+                       impactt = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1];
 
-       row = (model->brushq1.numleafs+7)>>3;
-       surfacepvsframes = model->brushq1.surfacepvsframes;
+                       d = bound(0, impactt, surf->extents[1] + 16) - impactt;
+                       dist2 += d * d;
+                       if (dist2 > maxdist)
+                               continue;
 
-       k = 0;
-       while (k < row)
-       {
-               c = *in++;
-               if (c)
-               {
-                       for (i = 0;i < 8;i++)
+                       if (surf->dlightframe != r_framecount) // not dynamic until now
                        {
-                               if (c & (1<<i))
-                               {
-                                       // warning to the clumsy: numleafs is one less than it should be, it only counts leafs with vis bits (skips leaf 0)
-                                       leafnum = (k << 3)+i+1;
-                                       if (leafnum > model->brushq1.numleafs)
-                                               return;
-                                       leaf = &model->brushq1.leafs[leafnum];
-                                       if (leaf->mins[0] > high[0] || leaf->maxs[0] < low[0]
-                                        || leaf->mins[1] > high[1] || leaf->maxs[1] < low[1]
-                                        || leaf->mins[2] > high[2] || leaf->maxs[2] < low[2])
-                                               continue;
-                                       if ((m = leaf->nummarksurfaces))
-                                       {
-                                               mark = leaf->firstmarksurface;
-                                               do
-                                               {
-                                                       surf = model->brushq1.surfaces + *mark++;
-                                                       // if not visible in current frame, or already marked because it was in another leaf we passed, skip
-                                                       if (surf->lightframe == lightframe)
-                                                               continue;
-                                                       surf->lightframe = lightframe;
-                                                       if (surfacepvsframes[surf->number] != model->brushq1.pvsframecount)
-                                                               continue;
-                                                       dist = PlaneDiff(lightorigin, surf->plane);
-                                                       if (surf->flags & SURF_PLANEBACK)
-                                                               dist = -dist;
-                                                       // LordHavoc: make sure it is infront of the surface and not too far away
-                                                       if (dist < rd->cullradius && (dist > -0.25f || ((surf->flags & SURF_LIGHTBOTHSIDES) && dist > -rd->cullradius)))
-                                                       {
-                                                               int d;
-                                                               int impacts, impactt;
-                                                               float dist2, impact[3];
-
-                                                               dist2 = dist * dist;
-
-                                                               if (surf->plane->type < 3)
-                                                               {
-                                                                       VectorCopy(lightorigin, impact);
-                                                                       impact[surf->plane->type] -= dist;
-                                                               }
-                                                               else
-                                                               {
-                                                                       impact[0] = lightorigin[0] - surf->plane->normal[0] * dist;
-                                                                       impact[1] = lightorigin[1] - surf->plane->normal[1] * dist;
-                                                                       impact[2] = lightorigin[2] - surf->plane->normal[2] * dist;
-                                                               }
-
-                                                               impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
-                                                               d = bound(0, impacts, surf->extents[0] + 16) - impacts;
-                                                               dist2 += d * d;
-                                                               if (dist2 > maxdist)
-                                                                       continue;
-
-                                                               impactt = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1];
-                                                               d = bound(0, impactt, surf->extents[1] + 16) - impactt;
-                                                               dist2 += d * d;
-                                                               if (dist2 > maxdist)
-                                                                       continue;
-
-                                                               if (surf->dlightframe != r_framecount) // not dynamic until now
-                                                               {
-                                                                       surf->dlightbits[0] = surf->dlightbits[1] = surf->dlightbits[2] = surf->dlightbits[3] = surf->dlightbits[4] = surf->dlightbits[5] = surf->dlightbits[6] = surf->dlightbits[7] = 0;
-                                                                       surf->dlightframe = r_framecount;
-                                                                       if (r_dlightmap.integer)
-                                                                               surf->cached_dlight = true;
-                                                               }
-                                                               surf->dlightbits[bitindex] |= bit;
-                                                       }
-                                               }
-                                               while (--m);
-                                       }
-                               }
+                               surf->dlightbits[0] = surf->dlightbits[1] = surf->dlightbits[2] = surf->dlightbits[3] = surf->dlightbits[4] = surf->dlightbits[5] = surf->dlightbits[6] = surf->dlightbits[7] = 0;
+                               surf->dlightframe = r_framecount;
+                               if (r_dlightmap.integer)
+                                       surf->cached_dlight = true;
                        }
-                       k++;
-                       continue;
+                       surf->dlightbits[bitindex] |= bit;
                }
-
-               k += *in++;
        }
 }
 
 void R_MarkLights(entity_render_t *ent)
 {
-       int i;
-       if (!gl_flashblend.integer)
-               for (i = 0;i < r_numdlights;i++)
-                       R_VisMarkLights (ent, r_dlight + i, 1 << (i & 31), i >> 5);
+       int i, bit, bitindex;
+       rdlight_t *rd;
+       vec3_t lightorigin;
+       if (!gl_flashblend.integer && r_dynamic.integer && ent->model)
+       {
+               for (i = 0, rd = r_dlight;i < r_numdlights;i++, rd++)
+               {
+                       bit = 1 << (i & 31);
+                       bitindex = i >> 5;
+                       Matrix4x4_Transform(&ent->inversematrix, rd->origin, lightorigin);
+                       lightpvsbytes = 0;
+                       if (r_vismarklights.integer && ent->model->brush.FatPVS)
+                               lightpvsbytes = ent->model->brush.FatPVS(ent->model, lightorigin, 0, lightpvs, sizeof(lightpvs));
+                       R_RecursiveMarkLights(ent, lightorigin, rd, bit, bitindex, ent->model->brushq1.nodes + ent->model->brushq1.hulls[0].firstclipnode, lightpvs, min(lightpvsbytes * 8, ent->model->brushq1.num_leafs - 1));
+               }
+       }
 }
 
 /*
index 1e3f3ec..3995057 100644 (file)
@@ -1841,6 +1841,9 @@ worldlight_t *r_shadow_worldlightchain;
 worldlight_t *r_shadow_selectedlight;
 vec3_t r_editlights_cursorlocation;
 
+static int lightpvsbytes;
+static qbyte lightpvs[(MAX_MAP_LEAFS + 7)/ 8];
+
 static int castshadowcount = 1;
 void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style, const char *cubemapname, int castshadow)
 {
@@ -1850,7 +1853,6 @@ void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style
        shadowmesh_t *mesh, *castmesh;
        mleaf_t *leaf;
        msurface_t *surf;
-       qbyte *pvs;
        surfmesh_t *surfmesh;
 
        if (radius < 15 || DotProduct(color, color) < 0.03)
@@ -1895,13 +1897,13 @@ void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style
                        qbyte *byteleafpvs;
                        qbyte *bytesurfacepvs;
 
-                       byteleafpvs = Mem_Alloc(tempmempool, cl.worldmodel->brushq1.numleafs + 1);
+                       byteleafpvs = Mem_Alloc(tempmempool, cl.worldmodel->brushq1.numleafs);
                        bytesurfacepvs = Mem_Alloc(tempmempool, cl.worldmodel->brushq1.numsurfaces);
 
                        Portal_Visibility(cl.worldmodel, e->origin, byteleafpvs, bytesurfacepvs, NULL, 0, true, RadiusFromBoundsAndOrigin(e->mins, e->maxs, e->origin));
 
-                       for (i = 0, leaf = cl.worldmodel->brushq1.leafs + 1;i < cl.worldmodel->brushq1.numleafs;i++, leaf++)
-                               if (byteleafpvs[i+1] && BoxesOverlap(leaf->mins, leaf->maxs, e->mins, e->maxs))
+                       for (i = 0, leaf = cl.worldmodel->brushq1.leafs;i < cl.worldmodel->brushq1.numleafs;i++, leaf++)
+                               if (byteleafpvs[i] && BoxesOverlap(leaf->mins, leaf->maxs, e->mins, e->maxs))
                                        leaf->worldnodeframe = castshadowcount;
 
                        for (i = 0, surf = cl.worldmodel->brushq1.surfaces;i < cl.worldmodel->brushq1.numsurfaces;i++, surf++)
@@ -1913,11 +1915,10 @@ void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style
                }
                else
                {
-                       leaf = cl.worldmodel->brushq1.PointInLeaf(cl.worldmodel, origin);
-                       pvs = cl.worldmodel->brushq1.LeafPVS(cl.worldmodel, leaf);
-                       for (i = 0, leaf = cl.worldmodel->brushq1.leafs + 1;i < cl.worldmodel->brushq1.numleafs;i++, leaf++)
+                       lightpvsbytes = cl.worldmodel->brush.FatPVS(cl.worldmodel, origin, 0, lightpvs, sizeof(lightpvs));
+                       for (i = 0, leaf = cl.worldmodel->brushq1.leafs + 1;i < cl.worldmodel->brushq1.numleafs - 1;i++, leaf++)
                        {
-                               if (pvs[i >> 3] & (1 << (i & 7)) && BoxesOverlap(leaf->mins, leaf->maxs, e->mins, e->maxs))
+                               if (lightpvs[i >> 3] & (1 << (i & 7)) && BoxesOverlap(leaf->mins, leaf->maxs, e->mins, e->maxs))
                                {
                                        leaf->worldnodeframe = castshadowcount;
                                        for (j = 0, mark = leaf->firstmarksurface;j < leaf->nummarksurfaces;j++, mark++)