From f2fbe3c626ee6b68c329879b69701e434f368a96 Mon Sep 17 00:00:00 2001 From: havoc Date: Wed, 13 Aug 2003 02:17:16 +0000 Subject: [PATCH] more hackish cleanups of PVS stuff, now decompresses the PVS data at load and this got rid of the last of the calls to LeafPVS (now checks the pvs in the leaf directly) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@3393 d7cf8633-e32d-0410-b094-e92efae38249 --- gl_rsurf.c | 34 ++---- model_brush.c | 106 +++++++++--------- model_brush.h | 4 +- model_shared.h | 7 +- pr_cmds.c | 24 ++-- r_light.c | 290 +++++++++++++------------------------------------ r_shadow.c | 17 +-- 7 files changed, 165 insertions(+), 317 deletions(-) diff --git a/gl_rsurf.c b/gl_rsurf.c index 4727958b..fe81def5 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -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); diff --git a/model_brush.c b/model_brush.c index 7a99e9fa..e20c5709 100644 --- a/model_brush.c +++ b/model_brush.c @@ -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 ; imaxs[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; diff --git a/model_brush.h b/model_brush.h index 5772df21..17e69353 100644 --- a/model_brush.h +++ b/model_brush.h @@ -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; diff --git a/model_shared.h b/model_shared.h index a911946d..7023822d 100644 --- a/model_shared.h +++ b/model_shared.h @@ -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; diff --git a/pr_cmds.c b/pr_cmds.c index b34e6b7b..c0d6e440 100644 --- 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 diff --git a/r_light.c b/r_light.c index 0a3e27ff..9fd74782 100644 --- 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< 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)); + } + } } /* diff --git a/r_shadow.c b/r_shadow.c index 1e3f3ec5..3995057d 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -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++) -- 2.39.2