mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-18 23:11:38 +00:00
[model] Remove 64k limit on visible leafs
Modern maps can have many more leafs (eg, ad_tears has 98983 leafs). Using set_t makes dynamic leaf counts easy to support and the code much easier to read (though set_is_member and the iterators are a little slower). The main thing to watch out for is the novis set and the set returned by Mod_LeafPVS never shrink, and may have excess elements (ie, indicate that nonexistent leafs are visible).
This commit is contained in:
parent
03921c03c5
commit
f47e03e606
16 changed files with 154 additions and 142 deletions
|
@ -103,7 +103,7 @@ typedef struct lightingframe_s {
|
|||
};
|
||||
// A fat PVS of leafs visible from visible leafs so hidden lights can
|
||||
// illuminate the leafs visible to the player
|
||||
byte pvs[MAP_PVS_BYTES];
|
||||
struct set_s *pvs;
|
||||
struct mleaf_s *leaf; // the last leaf used to generate the pvs
|
||||
qfv_lightvisset_t lightvis;
|
||||
} lightingframe_t;
|
||||
|
@ -124,7 +124,7 @@ typedef struct lightingctx_s {
|
|||
qfv_imageset_t lightimages;
|
||||
qfv_lightintset_t lightlayers;
|
||||
qfv_imageviewset_t lightviews;
|
||||
byte sun_pvs[MAX_MAP_LEAFS];
|
||||
struct set_s *sun_pvs;
|
||||
} lightingctx_t;
|
||||
|
||||
struct vulkan_ctx_s;
|
||||
|
|
|
@ -230,7 +230,7 @@ typedef struct mod_brush_s {
|
|||
int numplanes;
|
||||
plane_t *planes;
|
||||
|
||||
int numleafs; // number of visible leafs, not counting 0
|
||||
unsigned numleafs; // number of visible leafs, not counting 0
|
||||
mleaf_t *leafs;
|
||||
|
||||
int numvertexes;
|
||||
|
@ -432,13 +432,12 @@ model_t *Mod_ForName (const char *name, qboolean crash);
|
|||
void Mod_TouchModel (const char *name);
|
||||
// brush specific
|
||||
mleaf_t *Mod_PointInLeaf (const vec3_t p, model_t *model) __attribute__((pure));
|
||||
byte *Mod_LeafPVS (const mleaf_t *leaf, const model_t *model);
|
||||
struct set_s *Mod_LeafPVS (const mleaf_t *leaf, const model_t *model);
|
||||
|
||||
// NOTE: the buffer pointed to by out must be at least MAP_PVS_BYTES in size
|
||||
void Mod_LeafPVS_set (const mleaf_t *leaf, const model_t *model, byte defvis,
|
||||
byte *out);
|
||||
struct set_s *pvs);
|
||||
void Mod_LeafPVS_mix (const mleaf_t *leaf, const model_t *model, byte defvis,
|
||||
byte *out);
|
||||
struct set_s *pvs);
|
||||
|
||||
void Mod_Print (void);
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "QF/qendian.h"
|
||||
#include "QF/quakefs.h"
|
||||
#include "QF/render.h"
|
||||
#include "QF/set.h"
|
||||
#include "QF/sys.h"
|
||||
#include "QF/va.h"
|
||||
|
||||
|
@ -55,8 +56,6 @@
|
|||
#include "compat.h"
|
||||
#include "mod_internal.h"
|
||||
|
||||
static byte mod_novis[MAP_PVS_BYTES];
|
||||
|
||||
VISIBLE cvar_t *gl_sky_divide; //FIXME visibility?
|
||||
VISIBLE int mod_lightmap_bytes = 1; //FIXME should this be visible?
|
||||
|
||||
|
@ -87,8 +86,9 @@ Mod_PointInLeaf (const vec3_t p, model_t *model)
|
|||
|
||||
static inline void
|
||||
Mod_DecompressVis_set (const byte *in, const mod_brush_t *brush, byte defvis,
|
||||
byte *out)
|
||||
set_t *pvs)
|
||||
{
|
||||
byte *out = (byte *) pvs->map;
|
||||
byte *start = out;
|
||||
int row, c;
|
||||
|
||||
|
@ -119,8 +119,9 @@ Mod_DecompressVis_set (const byte *in, const mod_brush_t *brush, byte defvis,
|
|||
|
||||
static inline void
|
||||
Mod_DecompressVis_mix (const byte *in, const mod_brush_t *brush, byte defvis,
|
||||
byte *out)
|
||||
set_t *pvs)
|
||||
{
|
||||
byte *out = (byte *) pvs->map;
|
||||
byte *start = out;
|
||||
int row, c;
|
||||
|
||||
|
@ -146,16 +147,30 @@ Mod_DecompressVis_mix (const byte *in, const mod_brush_t *brush, byte defvis,
|
|||
} while (out - start < row);
|
||||
}
|
||||
|
||||
VISIBLE byte *
|
||||
VISIBLE set_t *
|
||||
Mod_LeafPVS (const mleaf_t *leaf, const model_t *model)
|
||||
{
|
||||
static byte decompressed[MAP_PVS_BYTES];
|
||||
static set_t *novis;
|
||||
static set_t *decompressed;
|
||||
unsigned numvis = model->brush.numleafs;
|
||||
|
||||
if (leaf == model->brush.leafs) {
|
||||
if (!mod_novis[0]) {
|
||||
memset (mod_novis, 0xff, sizeof (mod_novis));
|
||||
if (!novis) {
|
||||
novis = set_new_size (numvis);
|
||||
}
|
||||
return mod_novis;
|
||||
if (!novis->map[0] || SET_SIZE (numvis) > novis->size) {
|
||||
unsigned excess = SET_SIZE (numvis) - numvis;
|
||||
set_expand (novis, numvis);
|
||||
memset (novis->map, 0xff,
|
||||
SET_WORDS (novis) * sizeof (*novis->map));
|
||||
novis->map[SET_WORDS (novis) - 1] &= (~SET_ZERO) >> excess;
|
||||
}
|
||||
return novis;
|
||||
}
|
||||
if (!decompressed) {
|
||||
decompressed = set_new ();
|
||||
}
|
||||
set_expand (decompressed, numvis);
|
||||
Mod_DecompressVis_set (leaf->compressed_vis, &model->brush, 0xff,
|
||||
decompressed);
|
||||
return decompressed;
|
||||
|
@ -163,10 +178,14 @@ Mod_LeafPVS (const mleaf_t *leaf, const model_t *model)
|
|||
|
||||
VISIBLE void
|
||||
Mod_LeafPVS_set (const mleaf_t *leaf, const model_t *model, byte defvis,
|
||||
byte *out)
|
||||
set_t *out)
|
||||
{
|
||||
unsigned numvis = model->brush.numleafs;
|
||||
set_expand (out, numvis);
|
||||
if (leaf == model->brush.leafs) {
|
||||
memset (out, defvis, sizeof (mod_novis));
|
||||
unsigned excess = SET_SIZE (numvis) - numvis;
|
||||
memset (out->map, defvis, SET_WORDS (out) * sizeof (*out->map));
|
||||
out->map[SET_WORDS (out) - 1] &= (~SET_ZERO) >> excess;
|
||||
return;
|
||||
}
|
||||
Mod_DecompressVis_set (leaf->compressed_vis, &model->brush, defvis, out);
|
||||
|
@ -174,12 +193,17 @@ Mod_LeafPVS_set (const mleaf_t *leaf, const model_t *model, byte defvis,
|
|||
|
||||
VISIBLE void
|
||||
Mod_LeafPVS_mix (const mleaf_t *leaf, const model_t *model, byte defvis,
|
||||
byte *out)
|
||||
set_t *out)
|
||||
{
|
||||
unsigned numvis = model->brush.numleafs;
|
||||
set_expand (out, numvis);
|
||||
if (leaf == model->brush.leafs) {
|
||||
for (int i = MAP_PVS_BYTES; i-- > 0; ) {
|
||||
*out++ |= defvis;
|
||||
unsigned excess = SET_SIZE (numvis) - numvis;
|
||||
byte *o = (byte *) out->map;
|
||||
for (int i = SET_WORDS (out) * sizeof (*out->map); i-- > 0; ) {
|
||||
*o++ |= defvis;
|
||||
}
|
||||
out->map[SET_WORDS (out) - 1] &= (~SET_ZERO) >> excess;
|
||||
return;
|
||||
}
|
||||
Mod_DecompressVis_mix (leaf->compressed_vis, &model->brush, defvis, out);
|
||||
|
@ -431,11 +455,6 @@ Mod_LoadSubmodels (model_t *mod, bsp_t *bsp)
|
|||
|
||||
out = brush->submodels;
|
||||
|
||||
if (out->visleafs > MAX_MAP_LEAFS) {
|
||||
Sys_Error ("Mod_LoadSubmodels: too many visleafs (%d, max = %d) in %s",
|
||||
out->visleafs, MAX_MAP_LEAFS, mod->path);
|
||||
}
|
||||
|
||||
if (out->visleafs > 8192)
|
||||
Sys_MaskPrintf (SYS_warn,
|
||||
"%i visleafs exceeds standard limit of 8192.\n",
|
||||
|
@ -654,7 +673,7 @@ Mod_SetParent (mod_brush_t *brush, mnode_t *node, mnode_t *parent)
|
|||
static void
|
||||
Mod_SetLeafFlags (mod_brush_t *brush)
|
||||
{
|
||||
for (int i = 0; i < brush->numleafs; i++) {
|
||||
for (unsigned i = 0; i < brush->numleafs; i++) {
|
||||
int flags = 0;
|
||||
mleaf_t *leaf = &brush->leafs[i];
|
||||
for (int j = 0; j < leaf->nummarksurfaces; j++) {
|
||||
|
@ -704,7 +723,7 @@ Mod_LoadNodes (model_t *mod, bsp_t *bsp)
|
|||
out->children[j] = brush->nodes + p;
|
||||
} else {
|
||||
p = ~p;
|
||||
if (p < brush->numleafs) {
|
||||
if ((unsigned) p < brush->numleafs) {
|
||||
out->children[j] = (mnode_t *) (brush->leafs + p);
|
||||
} else {
|
||||
Sys_Printf ("Mod_LoadNodes: invalid leaf index %i "
|
||||
|
|
|
@ -184,11 +184,10 @@ register_textures (mod_brush_t *brush)
|
|||
void
|
||||
gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
|
||||
{
|
||||
int i;
|
||||
texture_t *tex;
|
||||
mod_brush_t *brush;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
for (int i = 0; i < 256; i++)
|
||||
d_lightstylevalue[i] = 264; // normal light value
|
||||
|
||||
memset (&r_worldentity, 0, sizeof (r_worldentity));
|
||||
|
@ -198,7 +197,7 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
|
|||
R_FreeAllEntities ();
|
||||
|
||||
// clear out efrags in case the level hasn't been reloaded
|
||||
for (i = 0; i < brush->numleafs; i++)
|
||||
for (unsigned i = 0; i < brush->numleafs; i++)
|
||||
brush->leafs[i].efrags = NULL;
|
||||
|
||||
// Force a vis update
|
||||
|
@ -212,7 +211,7 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
|
|||
// identify sky texture
|
||||
gl_mirrortexturenum = -1;
|
||||
gl_R_ClearTextures ();
|
||||
for (i = 0; i < brush->numtextures; i++) {
|
||||
for (int i = 0; i < brush->numtextures; i++) {
|
||||
tex = brush->textures[i];
|
||||
if (!tex)
|
||||
continue;
|
||||
|
@ -226,7 +225,7 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
|
|||
gl_R_InitSurfaceChains (brush);
|
||||
gl_R_AddTexture (r_notexture_mip);
|
||||
register_textures (brush);
|
||||
for (i = 0; i < num_models; i++) {
|
||||
for (int i = 0; i < num_models; i++) {
|
||||
if (!models[i])
|
||||
continue;
|
||||
if (*models[i]->path == '*')
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#endif
|
||||
|
||||
#include "QF/cvar.h"
|
||||
#include "QF/set.h"
|
||||
#include "QF/sys.h"
|
||||
|
||||
#include "r_internal.h"
|
||||
|
@ -43,14 +44,13 @@
|
|||
mvertex_t *r_pcurrentvertbase;
|
||||
mleaf_t *r_viewleaf;
|
||||
static mleaf_t *r_oldviewleaf;
|
||||
static set_t *solid;
|
||||
|
||||
void
|
||||
R_MarkLeaves (void)
|
||||
{
|
||||
byte solid[8192];
|
||||
byte *vis;
|
||||
set_t *vis;
|
||||
int c;
|
||||
unsigned int i;
|
||||
mleaf_t *leaf;
|
||||
mnode_t *node;
|
||||
msurface_t **mark;
|
||||
|
@ -67,13 +67,16 @@ R_MarkLeaves (void)
|
|||
if (r_novis->int_val) {
|
||||
r_oldviewleaf = 0; // so vis will be recalcualted when novis gets
|
||||
// turned off
|
||||
if (!solid) {
|
||||
solid = set_new ();
|
||||
set_everything (solid);
|
||||
}
|
||||
vis = solid;
|
||||
memset (solid, 0xff, (brush->numleafs + 7) >> 3);
|
||||
} else
|
||||
vis = Mod_LeafPVS (r_viewleaf, r_worldentity.renderer.model);
|
||||
|
||||
for (i = 0; (int) i < brush->numleafs; i++) {
|
||||
if (vis[i >> 3] & (1 << (i & 7))) {
|
||||
for (unsigned i = 0; i < brush->numleafs; i++) {
|
||||
if (set_is_member (vis, i)) {
|
||||
leaf = &brush->leafs[i + 1];
|
||||
if ((c = leaf->nummarksurfaces)) {
|
||||
mark = leaf->firstmarksurface;
|
||||
|
|
|
@ -271,7 +271,7 @@ R_MarkLights (const vec3_t lightorigin, dlight_t *light, int lightnum,
|
|||
} else {
|
||||
float radius = light->radius;
|
||||
vec3_t mins, maxs;
|
||||
int leafnum = 0;
|
||||
unsigned leafnum = 0;
|
||||
byte *in = pvsleaf->compressed_vis;
|
||||
byte vis_bits;
|
||||
|
||||
|
|
|
@ -164,7 +164,6 @@ sw_R_Init (void)
|
|||
void
|
||||
R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
|
||||
{
|
||||
int i;
|
||||
mod_brush_t *brush = &worldmodel->brush;
|
||||
|
||||
memset (&r_worldentity, 0, sizeof (r_worldentity));
|
||||
|
@ -174,7 +173,7 @@ R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
|
|||
|
||||
// clear out efrags in case the level hasn't been reloaded
|
||||
// FIXME: is this one short?
|
||||
for (i = 0; i < brush->numleafs; i++)
|
||||
for (unsigned i = 0; i < brush->numleafs; i++)
|
||||
brush->leafs[i].efrags = NULL;
|
||||
|
||||
if (brush->skytexture)
|
||||
|
|
|
@ -179,7 +179,6 @@ sw32_R_Init (void)
|
|||
void
|
||||
sw32_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
|
||||
{
|
||||
int i;
|
||||
mod_brush_t *brush = &worldmodel->brush;
|
||||
|
||||
memset (&r_worldentity, 0, sizeof (r_worldentity));
|
||||
|
@ -189,7 +188,7 @@ sw32_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
|
|||
|
||||
// clear out efrags in case the level hasn't been reloaded
|
||||
// FIXME: is this one short?
|
||||
for (i = 0; i < brush->numleafs; i++)
|
||||
for (unsigned i = 0; i < brush->numleafs; i++)
|
||||
brush->leafs[i].efrags = NULL;
|
||||
|
||||
if (brush->skytexture)
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "QF/plist.h"
|
||||
#include "QF/progs.h"
|
||||
#include "QF/script.h"
|
||||
#include "QF/set.h"
|
||||
#include "QF/sys.h"
|
||||
#include "QF/va.h"
|
||||
|
||||
|
@ -68,12 +69,12 @@
|
|||
static vec4f_t ref_direction = { 0, 0, 1, 0 };
|
||||
|
||||
static void
|
||||
expand_pvs (byte *pvs, model_t *model)
|
||||
expand_pvs (set_t *pvs, model_t *model)
|
||||
{
|
||||
byte base_pvs[MAP_PVS_BYTES];
|
||||
memcpy (base_pvs, pvs, sizeof (base_pvs));
|
||||
for (int i = 0; i < model->brush.numleafs; i++) {
|
||||
if (base_pvs[(unsigned) i / 8] & (1 << ((unsigned) i % 8))) {
|
||||
set_t base_pvs = SET_STATIC_INIT (model->brush.numleafs, alloca);
|
||||
set_assign (&base_pvs, pvs);
|
||||
for (unsigned i = 0; i < model->brush.numleafs; i++) {
|
||||
if (set_is_member (&base_pvs, i)) {
|
||||
Mod_LeafPVS_mix (model->brush.leafs + i + 1, model, 0, pvs);
|
||||
}
|
||||
}
|
||||
|
@ -99,13 +100,13 @@ find_visible_lights (vulkan_ctx_t *ctx)
|
|||
int flags = 0;
|
||||
|
||||
if (leaf == model->brush.leafs) {
|
||||
memset (lframe->pvs, 0xff, sizeof (lframe->pvs));
|
||||
set_everything (lframe->pvs);
|
||||
} else {
|
||||
Mod_LeafPVS_set (leaf, model, 0, lframe->pvs);
|
||||
expand_pvs (lframe->pvs, model);
|
||||
}
|
||||
for (int i = 0; i < model->brush.numleafs; i++) {
|
||||
if (lframe->pvs[i / 8] & (1 << (i % 8))) {
|
||||
for (unsigned i = 0; i < model->brush.numleafs; i++) {
|
||||
if (set_is_member (lframe->pvs, i)) {
|
||||
flags |= model->brush.leaf_flags[i + 1];
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +120,7 @@ find_visible_lights (vulkan_ctx_t *ctx)
|
|||
for (size_t i = 0; i < lctx->lightleafs.size; i++) {
|
||||
int l = lctx->lightleafs.a[i];
|
||||
if ((l == -1 && (flags & SURF_DRAWSKY))
|
||||
|| lframe->pvs[l / 8] & (1 << (l % 8))) {
|
||||
|| set_is_member (lframe->pvs, l)) {
|
||||
lframe->lightvis.a[i] = 1;
|
||||
visible++;
|
||||
}
|
||||
|
@ -307,6 +308,8 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx)
|
|||
DARRAY_RESIZE (&lctx->frames, frames);
|
||||
lctx->frames.grow = 0;
|
||||
|
||||
lctx->sun_pvs = set_new ();
|
||||
|
||||
lctx->pipeline = Vulkan_CreatePipeline (ctx, "lighting");
|
||||
lctx->layout = Vulkan_CreatePipelineLayout (ctx, "lighting_layout");
|
||||
lctx->sampler = Vulkan_CreateSampler (ctx, "shadow_sampler");
|
||||
|
@ -369,6 +372,8 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx)
|
|||
shadow_set->a[i],
|
||||
va (ctx->va_ctx, "lighting:shadow_set:%zd", i));
|
||||
|
||||
lframe->pvs = set_new ();
|
||||
|
||||
DARRAY_INIT (&lframe->lightvis, 16);
|
||||
lframe->leaf = 0;
|
||||
|
||||
|
@ -551,7 +556,8 @@ parse_sun (lightingctx_t *lctx, plitem_t *entity, model_t *model)
|
|||
//float sunlight2;
|
||||
vec3_t sunangle = { 0, -90, 0 };
|
||||
|
||||
memset (lctx->sun_pvs, 0, MAX_MAP_LEAFS);
|
||||
set_expand (lctx->sun_pvs, model->brush.numleafs);
|
||||
set_empty (lctx->sun_pvs);
|
||||
sunlight = parse_float (PL_String (PL_ObjectForKey (entity,
|
||||
"_sunlight")), 0);
|
||||
//sunlight2 = parse_float (PL_String (PL_ObjectForKey (entity,
|
||||
|
@ -571,9 +577,9 @@ parse_sun (lightingctx_t *lctx, plitem_t *entity, model_t *model)
|
|||
|
||||
// Any leaf with sky surfaces can potentially see the sun, thus put
|
||||
// the sun "in" every leaf with a sky surface
|
||||
for (int l = 0; l < model->brush.numleafs; l++) {
|
||||
for (unsigned l = 0; l < model->brush.numleafs; l++) {
|
||||
if (model->brush.leaf_flags[l] & SURF_DRAWSKY) {
|
||||
lctx->sun_pvs[l / 8] |= 1 << (l % 8);
|
||||
set_add (lctx->sun_pvs, l);
|
||||
}
|
||||
}
|
||||
// any leaf visible from a leaf with a sky surface (and thus the sun)
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "QF/cvar.h"
|
||||
#include "QF/msg.h"
|
||||
#include "QF/mathlib.h"
|
||||
#include "QF/set.h"
|
||||
#include "QF/sys.h"
|
||||
#include "QF/va.h"
|
||||
|
||||
|
@ -388,24 +389,20 @@ SV_ClearDatagram (void)
|
|||
crosses a waterline.
|
||||
*/
|
||||
|
||||
int fatbytes;
|
||||
byte fatpvs[MAP_PVS_BYTES];
|
||||
static set_t *fatpvs;
|
||||
|
||||
static void
|
||||
SV_AddToFatPVS (vec3_t org, mnode_t *node)
|
||||
{
|
||||
int i;
|
||||
float d;
|
||||
byte *pvs;
|
||||
plane_t *plane;
|
||||
|
||||
while (1) {
|
||||
// if this is a leaf, accumulate the pvs bits
|
||||
if (node->contents < 0) {
|
||||
if (node->contents != CONTENTS_SOLID) {
|
||||
pvs = Mod_LeafPVS ((mleaf_t *) node, sv.worldmodel);
|
||||
for (i = 0; i < fatbytes; i++)
|
||||
fatpvs[i] |= pvs[i];
|
||||
set_union (fatpvs, Mod_LeafPVS ((mleaf_t *) node,
|
||||
sv.worldmodel));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -429,11 +426,14 @@ SV_AddToFatPVS (vec3_t org, mnode_t *node)
|
|||
Calculates a PVS that is the inclusive or of all leafs within 8 pixels of the
|
||||
given point.
|
||||
*/
|
||||
static byte *
|
||||
static set_t *
|
||||
SV_FatPVS (vec3_t org)
|
||||
{
|
||||
fatbytes = (sv.worldmodel->brush.numleafs + 31) >> 3;
|
||||
memset (fatpvs, 0, fatbytes);
|
||||
if (!fatpvs) {
|
||||
fatpvs = set_new_size (sv.worldmodel->brush.numleafs);
|
||||
}
|
||||
set_expand (fatpvs, sv.worldmodel->brush.numleafs);
|
||||
set_empty (fatpvs);
|
||||
SV_AddToFatPVS (org, sv.worldmodel->brush.nodes);
|
||||
return fatpvs;
|
||||
}
|
||||
|
@ -444,7 +444,7 @@ static void
|
|||
SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg)
|
||||
{
|
||||
int bits, e, i;
|
||||
byte *pvs;
|
||||
set_t *pvs;
|
||||
float miss;
|
||||
vec3_t org;
|
||||
edict_t *ent;
|
||||
|
@ -473,7 +473,7 @@ SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg)
|
|||
continue;
|
||||
|
||||
for (el = SVdata (ent)->leafs; el; el = el->next) {
|
||||
if (pvs[el->leafnum >> 3] & (1 << (el->leafnum & 7)))
|
||||
if (set_is_member (pvs, el->leafnum))
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "QF/cvar.h"
|
||||
#include "QF/msg.h"
|
||||
#include "QF/ruamoko.h"
|
||||
#include "QF/set.h"
|
||||
#include "QF/sys.h"
|
||||
#include "QF/va.h"
|
||||
|
||||
|
@ -539,12 +540,11 @@ PF_checkpos (progs_t *pr)
|
|||
{
|
||||
}
|
||||
|
||||
byte checkpvs[MAP_PVS_BYTES];
|
||||
static set_t *checkpvs;
|
||||
|
||||
static int
|
||||
PF_newcheckclient (progs_t *pr, int check)
|
||||
{
|
||||
byte *pvs;
|
||||
edict_t *ent;
|
||||
int i;
|
||||
mleaf_t *leaf;
|
||||
|
@ -584,8 +584,10 @@ PF_newcheckclient (progs_t *pr, int check)
|
|||
// get the PVS for the entity
|
||||
VectorAdd (SVvector (ent, origin), SVvector (ent, view_ofs), org);
|
||||
leaf = Mod_PointInLeaf (org, sv.worldmodel);
|
||||
pvs = Mod_LeafPVS (leaf, sv.worldmodel);
|
||||
memcpy (checkpvs, pvs, (sv.worldmodel->brush.numleafs + 7) >> 3);
|
||||
if (!checkpvs) {
|
||||
checkpvs = set_new_size (sv.worldmodel->brush.numleafs);
|
||||
}
|
||||
set_assign (checkpvs, Mod_LeafPVS (leaf, sv.worldmodel));
|
||||
|
||||
return i;
|
||||
}
|
||||
|
@ -631,7 +633,7 @@ PF_checkclient (progs_t *pr)
|
|||
VectorAdd (SVvector (self, origin), SVvector (self, view_ofs), view);
|
||||
leaf = Mod_PointInLeaf (view, sv.worldmodel);
|
||||
l = (leaf - sv.worldmodel->brush.leafs) - 1;
|
||||
if ((l < 0) || !(checkpvs[l >> 3] & (1 << (l & 7)))) {
|
||||
if (!set_is_member (checkpvs, l)) {
|
||||
c_notvis++;
|
||||
RETURN_EDICT (pr, sv.edicts);
|
||||
return;
|
||||
|
|
|
@ -86,7 +86,7 @@ typedef struct {
|
|||
// struct edict_s is variable sized, but can
|
||||
// be used to reference the world ent
|
||||
|
||||
byte *pvs, *phs; // fully expanded and decompressed
|
||||
struct set_s *pvs, *phs; // fully expanded and decompressed
|
||||
|
||||
//antilag
|
||||
float lagentsfrac;
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
#include "QF/cvar.h"
|
||||
#include "QF/msg.h"
|
||||
#include "QF/set.h"
|
||||
#include "QF/sys.h"
|
||||
|
||||
#include "compat.h"
|
||||
|
@ -54,25 +55,21 @@
|
|||
when the bob crosses a waterline.
|
||||
*/
|
||||
|
||||
byte fatpvs[MAP_PVS_BYTES];
|
||||
int fatbytes;
|
||||
static set_t *fatpvs;
|
||||
|
||||
|
||||
static void
|
||||
SV_AddToFatPVS (vec3_t org, mnode_t *node)
|
||||
{
|
||||
byte *pvs;
|
||||
int i;
|
||||
float d;
|
||||
float d;
|
||||
plane_t *plane;
|
||||
|
||||
while (1) {
|
||||
// if this is a leaf, accumulate the pvs bits
|
||||
if (node->contents < 0) {
|
||||
if (node->contents != CONTENTS_SOLID) {
|
||||
pvs = Mod_LeafPVS ((mleaf_t *) node, sv.worldmodel);
|
||||
for (i = 0; i < fatbytes; i++)
|
||||
fatpvs[i] |= pvs[i];
|
||||
set_union (fatpvs, Mod_LeafPVS ((mleaf_t *) node,
|
||||
sv.worldmodel));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -96,11 +93,14 @@ SV_AddToFatPVS (vec3_t org, mnode_t *node)
|
|||
Calculates a PVS that is the inclusive or of all leafs within 8 pixels
|
||||
of the given point.
|
||||
*/
|
||||
static byte *
|
||||
static set_t *
|
||||
SV_FatPVS (vec3_t org)
|
||||
{
|
||||
fatbytes = (sv.worldmodel->brush.numleafs + 31) >> 3;
|
||||
memset (fatpvs, 0, fatbytes);
|
||||
if (!fatpvs) {
|
||||
fatpvs = set_new_size (sv.worldmodel->brush.numleafs);
|
||||
}
|
||||
set_expand (fatpvs, sv.worldmodel->brush.numleafs);
|
||||
set_empty (fatpvs);
|
||||
SV_AddToFatPVS (org, sv.worldmodel->brush.nodes);
|
||||
return fatpvs;
|
||||
}
|
||||
|
@ -549,7 +549,7 @@ write_player (delta_t *delta, plent_state_t *from, plent_state_t *to,
|
|||
}
|
||||
|
||||
static void
|
||||
SV_WritePlayersToClient (delta_t *delta, byte *pvs, sizebuf_t *msg)
|
||||
SV_WritePlayersToClient (delta_t *delta, set_t *pvs, sizebuf_t *msg)
|
||||
{
|
||||
int j, k;
|
||||
client_t *cl;
|
||||
|
@ -613,7 +613,7 @@ SV_WritePlayersToClient (delta_t *delta, byte *pvs, sizebuf_t *msg)
|
|||
if (pvs) {
|
||||
// ignore if not touching a PV leaf
|
||||
for (el = SVdata (ent)->leafs; el; el = el->next) {
|
||||
if (pvs[el->leafnum >> 3] & (1 << (el->leafnum & 7)))
|
||||
if (set_is_member (pvs, el->leafnum))
|
||||
break;
|
||||
}
|
||||
if (!el)
|
||||
|
@ -706,10 +706,10 @@ SV_WritePlayersToClient (delta_t *delta, byte *pvs, sizebuf_t *msg)
|
|||
}
|
||||
}
|
||||
|
||||
static inline byte *
|
||||
static inline set_t *
|
||||
calc_pvs (delta_t *delta)
|
||||
{
|
||||
byte *pvs = 0;
|
||||
set_t *pvs = 0;
|
||||
vec3_t org;
|
||||
|
||||
// find the client's PVS
|
||||
|
@ -756,7 +756,7 @@ calc_pvs (delta_t *delta)
|
|||
void
|
||||
SV_WriteEntitiesToClient (delta_t *delta, sizebuf_t *msg)
|
||||
{
|
||||
byte *pvs = 0;
|
||||
set_t *pvs = 0;
|
||||
int e, num_edicts;
|
||||
int max_packet_entities = MAX_DEMO_PACKET_ENTITIES;
|
||||
int stdver = 1;
|
||||
|
@ -801,7 +801,7 @@ SV_WriteEntitiesToClient (delta_t *delta, sizebuf_t *msg)
|
|||
if (pvs) {
|
||||
// ignore if not touching a PV leaf
|
||||
for (el = SVdata (ent)->leafs; el; el = el->next) {
|
||||
if (pvs[el->leafnum >> 3] & (1 << (el->leafnum & 7)))
|
||||
if (set_is_member (pvs, el->leafnum))
|
||||
break;
|
||||
}
|
||||
if (!el)
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "QF/info.h"
|
||||
#include "QF/msg.h"
|
||||
#include "QF/quakefs.h"
|
||||
#include "QF/set.h"
|
||||
#include "QF/sys.h"
|
||||
#include "QF/va.h"
|
||||
|
||||
|
@ -222,62 +223,45 @@ SV_SaveSpawnparms (void)
|
|||
static void
|
||||
SV_CalcPHS (void)
|
||||
{
|
||||
byte *scan;
|
||||
int bitbyte, count, index, num, rowbytes, rowwords, vcount, i, j,
|
||||
k, l;
|
||||
unsigned int *dest, *src;
|
||||
int count, num, vcount, i;
|
||||
|
||||
SV_Printf ("Building PHS...\n");
|
||||
|
||||
num = sv.worldmodel->brush.numleafs;
|
||||
rowwords = (num + 31) >> 5;
|
||||
rowbytes = rowwords * 4;
|
||||
|
||||
sv.pvs = Hunk_Alloc (rowbytes * num);
|
||||
scan = sv.pvs;
|
||||
sv.pvs = Hunk_Alloc (num * sizeof (set_t));
|
||||
vcount = 0;
|
||||
for (i = 0; i < num; i++, scan += rowbytes) {
|
||||
memcpy (scan, Mod_LeafPVS (sv.worldmodel->brush.leafs + i,
|
||||
sv.worldmodel),
|
||||
rowbytes);
|
||||
for (i = 0; i < num; i++) {
|
||||
sv.pvs[i] = (set_t) SET_STATIC_INIT (num, Hunk_Alloc);
|
||||
Mod_LeafPVS_set (sv.worldmodel->brush.leafs + i, sv.worldmodel, 0xff,
|
||||
&sv.pvs[i]);
|
||||
if (i == 0)
|
||||
continue;
|
||||
for (j = 0; j < num; j++) {
|
||||
if (scan[j >> 3] & (1 << (j & 7))) {
|
||||
vcount++;
|
||||
}
|
||||
for (set_iter_t *iter = set_first (&sv.pvs[i]); iter;
|
||||
iter = set_next (iter)) {
|
||||
vcount++;
|
||||
}
|
||||
}
|
||||
|
||||
sv.phs = Hunk_Alloc (rowbytes * num);
|
||||
sv.phs = Hunk_Alloc (num * sizeof (set_t));
|
||||
count = 0;
|
||||
scan = sv.pvs;
|
||||
dest = (unsigned int *) sv.phs;
|
||||
for (i = 0; i < num; i++, dest += rowwords, scan += rowbytes) {
|
||||
memcpy (dest, scan, rowbytes);
|
||||
for (j = 0; j < rowbytes; j++) {
|
||||
bitbyte = scan[j];
|
||||
if (!bitbyte)
|
||||
continue;
|
||||
for (k = 0; k < 8; k++) {
|
||||
if (!(bitbyte & (1 << k)))
|
||||
continue;
|
||||
// or this pvs row into the phs
|
||||
// +1 because pvs is 1 based
|
||||
index = ((j << 3) + k + 1);
|
||||
if (index >= num)
|
||||
continue;
|
||||
src = (unsigned int *) sv.pvs + index * rowwords;
|
||||
for (l = 0; l < rowwords; l++)
|
||||
dest[l] |= src[l];
|
||||
}
|
||||
for (i = 0; i < num; i++) {
|
||||
sv.phs[i] = (set_t) SET_STATIC_INIT (num, Hunk_Alloc);
|
||||
set_assign (&sv.phs[i], &sv.pvs[i]);
|
||||
|
||||
for (set_iter_t *iter = set_first (&sv.pvs[i]); iter;
|
||||
iter = set_next (iter)) {
|
||||
// or this pvs row into the phs
|
||||
// +1 because pvs is 1 based
|
||||
set_union (&sv.phs[i], &sv.pvs[iter->element + 1]);
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
continue;
|
||||
for (j = 0; j < num; j++)
|
||||
if (((byte *) dest)[j >> 3] & (1 << (j & 7)))
|
||||
count++;
|
||||
for (set_iter_t *iter = set_first (&sv.phs[i]); iter;
|
||||
iter = set_next (iter)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
SV_Printf ("Average leafs visible / hearable / total: %i / %i / %i\n",
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "QF/cvar.h"
|
||||
#include "QF/msg.h"
|
||||
#include "QF/ruamoko.h"
|
||||
#include "QF/set.h"
|
||||
#include "QF/sys.h"
|
||||
#include "QF/va.h"
|
||||
|
||||
|
@ -460,12 +461,11 @@ PF_checkpos (progs_t *pr)
|
|||
{
|
||||
}
|
||||
|
||||
byte checkpvs[MAP_PVS_BYTES];
|
||||
set_t *checkpvs;
|
||||
|
||||
static int
|
||||
PF_newcheckclient (progs_t *pr, int check)
|
||||
{
|
||||
byte *pvs;
|
||||
edict_t *ent;
|
||||
int i;
|
||||
mleaf_t *leaf;
|
||||
|
@ -505,8 +505,10 @@ PF_newcheckclient (progs_t *pr, int check)
|
|||
// get the PVS for the entity
|
||||
VectorAdd (SVvector (ent, origin), SVvector (ent, view_ofs), org);
|
||||
leaf = Mod_PointInLeaf (org, sv.worldmodel);
|
||||
pvs = Mod_LeafPVS (leaf, sv.worldmodel);
|
||||
memcpy (checkpvs, pvs, (sv.worldmodel->brush.numleafs + 7) >> 3);
|
||||
if (!checkpvs) {
|
||||
checkpvs = set_new_size (sv.worldmodel->brush.numleafs);
|
||||
}
|
||||
set_assign (checkpvs, Mod_LeafPVS (leaf, sv.worldmodel));
|
||||
|
||||
return i;
|
||||
}
|
||||
|
@ -552,7 +554,7 @@ PF_checkclient (progs_t *pr)
|
|||
VectorAdd (SVvector (self, origin), SVvector (self, view_ofs), view);
|
||||
leaf = Mod_PointInLeaf (view, sv.worldmodel);
|
||||
l = (leaf - sv.worldmodel->brush.leafs) - 1;
|
||||
if ((l < 0) || !(checkpvs[l >> 3] & (1 << (l & 7)))) {
|
||||
if (!set_is_member (checkpvs, l)) {
|
||||
c_notvis++;
|
||||
RETURN_EDICT (pr, sv.edicts);
|
||||
return;
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "QF/console.h"
|
||||
#include "QF/dstring.h"
|
||||
#include "QF/msg.h"
|
||||
#include "QF/set.h"
|
||||
#include "QF/sound.h" // FIXME: DEFAULT_SOUND_PACKET_*
|
||||
#include "QF/sys.h"
|
||||
|
||||
|
@ -295,7 +296,7 @@ SV_PrintToClient (client_t *cl, int level, const char *string)
|
|||
void
|
||||
SV_Multicast (const vec3_t origin, int to)
|
||||
{
|
||||
byte *mask;
|
||||
set_t *mask;
|
||||
client_t *client;
|
||||
int leafnum, j;
|
||||
mleaf_t *leaf;
|
||||
|
@ -314,23 +315,22 @@ SV_Multicast (const vec3_t origin, int to)
|
|||
case MULTICAST_ALL_R:
|
||||
reliable = true; // intentional fallthrough
|
||||
case MULTICAST_ALL:
|
||||
mask = sv.pvs; // leaf 0 is everything;
|
||||
mask = &sv.pvs[0]; // leaf 0 is everything;
|
||||
break;
|
||||
|
||||
case MULTICAST_PHS_R:
|
||||
reliable = true; // intentional fallthrough
|
||||
case MULTICAST_PHS:
|
||||
mask = sv.phs + leafnum * 4 * ((brush->numleafs + 31) >> 5);
|
||||
mask = &sv.phs[leafnum];
|
||||
break;
|
||||
|
||||
case MULTICAST_PVS_R:
|
||||
reliable = true; // intentional fallthrough
|
||||
case MULTICAST_PVS:
|
||||
mask = sv.pvs + leafnum * 4 * ((brush->numleafs + 31) >> 5);
|
||||
mask = &sv.pvs[leafnum];
|
||||
break;
|
||||
|
||||
default:
|
||||
mask = NULL;
|
||||
Sys_Error ("SV_Multicast: bad to:%i", to);
|
||||
}
|
||||
|
||||
|
@ -352,7 +352,7 @@ SV_Multicast (const vec3_t origin, int to)
|
|||
if (leaf) {
|
||||
// -1 is because pvs rows are 1 based, not 0 based like leafs
|
||||
leafnum = leaf - brush->leafs - 1;
|
||||
if (!(mask[leafnum >> 3] & (1 << (leafnum & 7)))) {
|
||||
if (!set_is_member (mask, leafnum)) {
|
||||
// SV_Printf ("supressed multicast\n");
|
||||
continue;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue