// sv_main.c -- server main program
#include "quakedef.h"
-#include "portals.h"
static cvar_t sv_cullentities_pvs = {0, "sv_cullentities_pvs", "0"}; // fast but loose
-static cvar_t sv_cullentities_portal = {0, "sv_cullentities_portal", "0"}; // extremely accurate visibility checking, but too slow
static cvar_t sv_cullentities_trace = {0, "sv_cullentities_trace", "1"}; // tends to get false negatives, uses a timeout to keep entities visible a short time after becoming hidden
static cvar_t sv_cullentities_stats = {0, "sv_cullentities_stats", "0"};
static cvar_t sv_entpatch = {0, "sv_entpatch", "1"};
Cvar_RegisterVariable (&sv_nostep);
Cvar_RegisterVariable (&sv_deltacompress);
Cvar_RegisterVariable (&sv_cullentities_pvs);
- Cvar_RegisterVariable (&sv_cullentities_portal);
Cvar_RegisterVariable (&sv_cullentities_trace);
Cvar_RegisterVariable (&sv_cullentities_stats);
Cvar_RegisterVariable (&sv_entpatch);
=============================================================================
*/
-int fatbytes;
-qbyte fatpvs[MAX_MAP_LEAFS/8];
-
-void SV_AddToFatPVS (vec3_t org, mnode_t *node)
-{
- int i;
- qbyte *pvs;
- mplane_t *plane;
- float d;
-
- while (1)
- {
- // if this is a leaf, accumulate the pvs bits
- if (node->contents < 0)
- {
- if (node->contents != CONTENTS_SOLID)
- {
- pvs = sv.worldmodel->brushq1.LeafPVS(sv.worldmodel, (mleaf_t *)node);
- for (i=0 ; i<fatbytes ; i++)
- fatpvs[i] |= pvs[i];
- }
- return;
- }
-
- plane = node->plane;
- d = DotProduct (org, plane->normal) - plane->dist;
- if (d > 8)
- node = node->children[0];
- else if (d < -8)
- node = node->children[1];
- else
- { // go down both
- SV_AddToFatPVS (org, node->children[0]);
- node = node->children[1];
- }
- }
-}
-
-/*
-=============
-SV_FatPVS
-
-Calculates a PVS that is the inclusive or of all leafs within 8 pixels of the
-given point.
-=============
-*/
-qbyte *SV_FatPVS (vec3_t org)
-{
- fatbytes = (sv.worldmodel->brushq1.numleafs+31)>>3;
- memset (fatpvs, 0, fatbytes);
- SV_AddToFatPVS (org, sv.worldmodel->brushq1.nodes);
- return fatpvs;
-}
-
-//=============================================================================
-
-
-int SV_BoxTouchingPVS (qbyte *pvs, vec3_t mins, vec3_t maxs, mnode_t *node)
-{
- int leafnum;
-loc0:
- if (node->contents < 0)
- {
- // leaf
- if (node->contents == CONTENTS_SOLID)
- return false;
- leafnum = (mleaf_t *)node - sv.worldmodel->brushq1.leafs - 1;
- return pvs[leafnum >> 3] & (1 << (leafnum & 7));
- }
-
- // node - recurse down the BSP tree
- switch (BoxOnPlaneSide(mins, maxs, node->plane))
- {
- case 1: // front
- node = node->children[0];
- goto loc0;
- case 2: // back
- node = node->children[1];
- goto loc0;
- default: // crossing
- if (node->children[0]->contents != CONTENTS_SOLID)
- if (SV_BoxTouchingPVS (pvs, mins, maxs, node->children[0]))
- return true;
- node = node->children[1];
- goto loc0;
- }
- // never reached
- return false;
-}
-
+int sv_writeentitiestoclient_pvsbytes;
+qbyte sv_writeentitiestoclient_pvs[MAX_MAP_LEAFS/8];
/*
=============
void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
{
int e, clentnum, bits, alpha, glowcolor, glowsize, scale, effects, lightsize;
- int culled_pvs, culled_portal, culled_trace, visibleentities, totalentities;
+ int culled_pvs, culled_trace, visibleentities, totalentities;
qbyte *pvs;
vec3_t origin, angles, entmins, entmaxs, testorigin, testeye;
float nextfullupdate, alphaf;
// find the client's PVS
VectorAdd (clent->v->origin, clent->v->view_ofs, testeye);
- pvs = SV_FatPVS (testeye);
+ fatbytes = 0;
+ if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
+ fatbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, testeye, 8, sv_writeentitiestoclient_pvs, sizeof(sv_writeentitiestoclient_pvs));
culled_pvs = 0;
- culled_portal = 0;
culled_trace = 0;
visibleentities = 0;
totalentities = 0;
totalentities++;
// if not touching a visible leaf
- if (sv_cullentities_pvs.integer && !SV_BoxTouchingPVS(pvs, entmins, entmaxs, sv.worldmodel->brushq1.nodes))
+ if (sv_cullentities_pvs.integer && fatbytes && sv.worldmodel && sv.worldmodel->brush.BoxTouchingPVS && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, sv_writeentitiestoclient_pvs, entmins, entmaxs))
{
culled_pvs++;
continue;
}
- // or not visible through the portals
- if (sv_cullentities_portal.integer && !Portal_CheckBox(sv.worldmodel, testeye, entmins, entmaxs))
- {
- culled_portal++;
- continue;
- }
-
// don't try to cull embedded brush models with this, they're sometimes huge (spanning several rooms)
- if (sv_cullentities_trace.integer && (model == NULL || model->type != mod_brush || model->name[0] != '*'))
+ if (sv_cullentities_trace.integer && (model == NULL || model->brush.TraceBox == NULL || model->name[0] != '*'))
{
// LordHavoc: test random offsets, to maximize chance of detection
testorigin[0] = lhrandom(entmins[0], entmaxs[0]);
}
if (sv_cullentities_stats.integer)
- Con_Printf("client \"%s\" entities: %d total, %d visible, %d culled by: %d pvs %d portal %d trace\n", client->name, totalentities, visibleentities, culled_pvs + culled_portal + culled_trace, culled_pvs, culled_portal, culled_trace);
+ Con_Printf("client \"%s\" entities: %d total, %d visible, %d culled by: %d pvs %d trace\n", client->name, totalentities, visibleentities, culled_pvs + culled_trace, culled_pvs, culled_trace);
}
#else
static int numsendentities;
static int sententities[MAX_EDICTS];
static int sententitiesconsideration[MAX_EDICTS];
static int sv_writeentitiestoclient_culled_pvs;
-static int sv_writeentitiestoclient_culled_portal;
static int sv_writeentitiestoclient_culled_trace;
static int sv_writeentitiestoclient_visibleentities;
static int sv_writeentitiestoclient_totalentities;
//static entity_frame_t sv_writeentitiestoclient_entityframe;
static int sv_writeentitiestoclient_clentnum;
-static qbyte *sv_writeentitiestoclient_pvs;
static vec3_t sv_writeentitiestoclient_testeye;
static client_t *sv_writeentitiestoclient_client;
lightmaxs[2] = min(entmaxs[2], s->origin[2] + s->specialvisibilityradius);
sv_writeentitiestoclient_totalentities++;
// if not touching a visible leaf
- if (sv_cullentities_pvs.integer && !SV_BoxTouchingPVS(sv_writeentitiestoclient_pvs, lightmins, lightmaxs, sv.worldmodel->brushq1.nodes))
+ if (sv_cullentities_pvs.integer && sv_writeentitiestoclient_pvsbytes && sv.worldmodel && sv.worldmodel->brush.BoxTouchingPVS && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, sv_writeentitiestoclient_pvs, lightmins, lightmaxs))
{
sv_writeentitiestoclient_culled_pvs++;
return;
}
- // or not visible through the portals
- if (sv_cullentities_portal.integer && !Portal_CheckBox(sv.worldmodel, sv_writeentitiestoclient_testeye, lightmins, lightmaxs))
- {
- sv_writeentitiestoclient_culled_portal++;
- return;
- }
// or not seen by random tracelines
if (sv_cullentities_trace.integer)
{
sv_writeentitiestoclient_client = client;
sv_writeentitiestoclient_culled_pvs = 0;
- sv_writeentitiestoclient_culled_portal = 0;
sv_writeentitiestoclient_culled_trace = 0;
sv_writeentitiestoclient_visibleentities = 0;
sv_writeentitiestoclient_totalentities = 0;
// find the client's PVS
// the real place being tested from
VectorAdd(clent->v->origin, clent->v->view_ofs, sv_writeentitiestoclient_testeye);
- sv_writeentitiestoclient_pvs = SV_FatPVS(sv_writeentitiestoclient_testeye);
+ sv_writeentitiestoclient_pvsbytes = 0;
+ if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
+ sv_writeentitiestoclient_pvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, sv_writeentitiestoclient_testeye, 8, sv_writeentitiestoclient_pvs, sizeof(sv_writeentitiestoclient_pvs));
sv_writeentitiestoclient_clentnum = EDICT_TO_PROG(clent); // LordHavoc: for comparison purposes
d->currentcommit = NULL;
if (sv_cullentities_stats.integer)
- Con_Printf("client \"%s\" entities: %d total, %d visible, %d culled by: %d pvs %d portal %d trace\n", client->name, sv_writeentitiestoclient_totalentities, sv_writeentitiestoclient_visibleentities, sv_writeentitiestoclient_culled_pvs + sv_writeentitiestoclient_culled_portal + sv_writeentitiestoclient_culled_trace, sv_writeentitiestoclient_culled_pvs, sv_writeentitiestoclient_culled_portal, sv_writeentitiestoclient_culled_trace);
+ Con_Printf("client \"%s\" entities: %d total, %d visible, %d culled by: %d pvs %d trace\n", client->name, sv_writeentitiestoclient_totalentities, sv_writeentitiestoclient_visibleentities, sv_writeentitiestoclient_culled_pvs + sv_writeentitiestoclient_culled_trace, sv_writeentitiestoclient_culled_pvs, sv_writeentitiestoclient_culled_trace);
}
#endif
sv.model_precache[0] = "";
sv.model_precache[1] = sv.modelname;
- for (i = 1;i < sv.worldmodel->brushq1.numsubmodels;i++)
+ for (i = 1;i < sv.worldmodel->brush.numsubmodels;i++)
{
sv.model_precache[i+1] = localmodels[i];
sv.models[i+1] = Mod_ForName (localmodels[i], false, false, false);