From c8f4487266cf656bd399f8ab9cba7118947a0911 Mon Sep 17 00:00:00 2001 From: lordhavoc Date: Mon, 29 Oct 2001 07:23:10 +0000 Subject: [PATCH] got rid of leafnums array in edict structure for pvs checking, pvs is now checked based on predicted locations of entities, and some reorganizational optimizations of WriteEntitiestoClient changed an SV_Move call to use the proper MOVE_ define (no behavior change, only cleanup) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@978 d7cf8633-e32d-0410-b094-e92efae38249 --- progs.h | 3 - sv_main.c | 253 +++++++++++++++++++++++++++++++++--------------------- world.c | 56 +----------- 3 files changed, 154 insertions(+), 158 deletions(-) diff --git a/progs.h b/progs.h index 699d84b7..a77faafe 100644 --- a/progs.h +++ b/progs.h @@ -43,9 +43,6 @@ typedef struct edict_s qboolean free; link_t area; - int num_leafs; - short leafnums[MAX_ENT_LEAFS]; - entity_state_t baseline; entity_state_t deltabaseline; // LordHavoc: previous frame diff --git a/sv_main.c b/sv_main.c index 2c82c63c..aad188ab 100644 --- a/sv_main.c +++ b/sv_main.c @@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" +cvar_t sv_pvscheckentities = {0, "sv_pvscheckentities", "1"}; cvar_t sv_vischeckentities = {0, "sv_vischeckentities", "1"}; cvar_t sv_reportvischeckentities = {0, "sv_reportvischeckentities", "0"}; int sv_vischeckentitycullcount = 0; @@ -53,6 +54,7 @@ void SV_Init (void) Cvar_RegisterVariable (&sv_nostep); Cvar_RegisterVariable (&sv_predict); Cvar_RegisterVariable (&sv_deltacompress); + Cvar_RegisterVariable (&sv_pvscheckentities); Cvar_RegisterVariable (&sv_vischeckentities); Cvar_RegisterVariable (&sv_reportvischeckentities); @@ -451,6 +453,40 @@ byte *SV_FatPVS (vec3_t org) //============================================================================= +int SV_BoxTouchingPVS (byte *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->leafs - 1; + return pvs[leafnum >> 3] & (1 << (leafnum & 7)); + } + + // node - recurse down the BSP tree + switch (BOX_ON_PLANE_SIDE(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; +} + + /* ============= SV_WriteEntitiesToClient @@ -466,18 +502,17 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) edict_t *ent; eval_t *val; entity_state_t *baseline; // LordHavoc: delta or startup baseline + trace_t trace; // find the client's PVS VectorAdd (clent->v.origin, clent->v.view_ofs, org); pvs = SV_FatPVS (org); /* - if (dpprotocol) - { - MSG_WriteByte(msg, svc_playerposition); - MSG_WriteFloat(msg, org[0]); - MSG_WriteFloat(msg, org[1]); - MSG_WriteFloat(msg, org[2]); - } + // dp protocol + MSG_WriteByte(msg, svc_playerposition); + MSG_WriteFloat(msg, org[0]); + MSG_WriteFloat(msg, org[1]); + MSG_WriteFloat(msg, org[2]); */ clentnum = EDICT_TO_PROG(clent); // LordHavoc: for comparison purposes @@ -510,36 +545,112 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) continue; if ((val = GETEDICTFIELDVALUE(ent, eval_drawonlytoclient)) && val->edict && val->edict != clentnum) continue; - // ignore if not touching a PV leaf - for (i = 0;i < ent->num_leafs;i++) - if (pvs[ent->leafnums[i] >> 3] & (1 << (ent->leafnums[i]&7) )) - break; + } + } - if (i == ent->num_leafs) - { - // not visible - continue; - } + glowsize = 0; - VectorAdd(ent->v.mins, ent->v.origin, entmins); - VectorAdd(ent->v.maxs, ent->v.origin, entmaxs); - entmins[0] -= 1.0f;entmins[1] -= 1.0f;entmins[2] -= 1.0f; - entmaxs[0] += 1.0f;entmaxs[1] += 1.0f;entmaxs[2] += 1.0f; - if (!Portal_CheckBox(sv.worldmodel, org, entmins, entmaxs)) - { - sv_vischeckentitycullcount++; + if ((val = GETEDICTFIELDVALUE(ent, eval_glow_size))) + glowsize = (int) val->_float >> 2; + if (glowsize > 255) glowsize = 255; + if (glowsize < 0) glowsize = 0; + + if ((val = GETEDICTFIELDVALUE(ent, eval_glow_trail))) + if (val->_float != 0) + bits |= U_GLOWTRAIL; + + if (ent->v.modelindex == 0 || pr_strings[ent->v.model] == 0) // no model + if (ent != clent) // LordHavoc: always send player + if (glowsize == 0 && (bits & U_GLOWTRAIL) == 0) // no effects continue; - } + + if (ent->v.movetype == MOVETYPE_STEP && ((int) ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM))) // monsters have smoothed walking/flying/swimming movement + { + if (!ent->steplerptime || ent->steplerptime > sv.time) // when the level just started... + { + ent->steplerptime = sv.time; + VectorCopy(ent->v.origin, ent->stepoldorigin); + VectorCopy(ent->v.angles, ent->stepoldangles); + VectorCopy(ent->v.origin, ent->steporigin); + VectorCopy(ent->v.angles, ent->stepangles); + } + VectorSubtract(ent->v.origin, ent->steporigin, origin); + VectorSubtract(ent->v.angles, ent->stepangles, angles); + if (DotProduct(origin, origin) >= 0.125 || DotProduct(angles, angles) >= 1.4) + { + // update lerp positions + ent->steplerptime = sv.time; + VectorCopy(ent->steporigin, ent->stepoldorigin); + VectorCopy(ent->stepangles, ent->stepoldangles); + VectorCopy(ent->v.origin, ent->steporigin); + VectorCopy(ent->v.angles, ent->stepangles); + } + movelerp = (sv.time - ent->steplerptime) * 10.0; + if (movelerp > 1) movelerp = 1; + moveilerp = 1 - movelerp; + origin[0] = ent->stepoldorigin[0] * moveilerp + ent->steporigin[0] * movelerp; + origin[1] = ent->stepoldorigin[1] * moveilerp + ent->steporigin[1] * movelerp; + origin[2] = ent->stepoldorigin[2] * moveilerp + ent->steporigin[2] * movelerp; + // choose shortest rotate (to avoid 'spin around' situations) + VectorSubtract(ent->stepangles, ent->stepoldangles, angles); + if (angles[0] < -180) angles[0] += 360;if (angles[0] >= 180) angles[0] -= 360; + if (angles[1] < -180) angles[1] += 360;if (angles[1] >= 180) angles[1] -= 360; + if (angles[2] < -180) angles[2] += 360;if (angles[2] >= 180) angles[2] -= 360; + angles[0] = angles[0] * movelerp + ent->stepoldangles[0]; + angles[1] = angles[1] * movelerp + ent->stepoldangles[1]; + angles[2] = angles[2] * movelerp + ent->stepoldangles[2]; + //VectorMA(origin, host_client->latency, ent->v.velocity, origin); + } + else // copy as they are + { + VectorCopy(ent->v.angles, angles); + if (DotProduct(ent->v.velocity, ent->v.velocity) >= 1.0f) + { + VectorMA(ent->v.origin, host_client->latency, ent->v.velocity, origin); + // LordHavoc: trace predicted movement to avoid putting things in walls + trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, origin, MOVE_NORMAL, ent); + VectorCopy(trace.endpos, origin); + } + else + { + VectorCopy(ent->v.origin, origin); + } + if (ent->v.movetype == MOVETYPE_STEP) // monster, but airborn, update lerp info + { + // update lerp positions + ent->steplerptime = sv.time; + VectorCopy(ent->v.origin, ent->stepoldorigin); + VectorCopy(ent->v.angles, ent->stepoldangles); + VectorCopy(ent->v.origin, ent->steporigin); + VectorCopy(ent->v.angles, ent->stepangles); } } - if ((val = GETEDICTFIELDVALUE(ent, eval_exteriormodeltoclient)) && val->edict == clentnum) - bits = bits | U_EXTERIORMODEL; + // ent has survived every check so far, check if it is visible + if (ent != clent && ((bits & U_VIEWMODEL) == 0)) + { + // use the predicted origin + entmins[0] = ent->v.mins[0] + origin[0] - 1.0f; + entmins[1] = ent->v.mins[1] + origin[1] - 1.0f; + entmins[2] = ent->v.mins[2] + origin[2] - 1.0f; + entmaxs[0] = ent->v.maxs[0] + origin[0] + 1.0f; + entmaxs[1] = ent->v.maxs[1] + origin[1] + 1.0f; + entmaxs[2] = ent->v.maxs[2] + origin[2] + 1.0f; + + // if not touching a visible leaf + if (sv_pvscheckentities.value && !SV_BoxTouchingPVS(pvs, entmins, entmaxs, sv.worldmodel->nodes)) + continue; + + // or not visible through the portals + if (sv_vischeckentities.value && !Portal_CheckBox(sv.worldmodel, org, entmins, entmaxs)) + { + sv_vischeckentitycullcount++; + continue; + } + } - // don't send if flagged for NODRAW and there are no effects alpha = 255; scale = 16; - glowsize = 0; glowcolor = 254; colormod = 255; effects = ent->v.effects; @@ -557,20 +668,11 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) alpha = 255; alpha = bound(0, alpha, 255); - if ((val = GETEDICTFIELDVALUE(ent, eval_glow_size))) - glowsize = (int) val->_float >> 2; - if (glowsize > 255) glowsize = 255; - if (glowsize < 0) glowsize = 0; - if ((val = GETEDICTFIELDVALUE(ent, eval_scale))) if ((scale = (int) (val->_float * 16.0)) == 0) scale = 16; if (scale < 0) scale = 0; if (scale > 255) scale = 255; - if ((val = GETEDICTFIELDVALUE(ent, eval_glow_trail))) - if (val->_float != 0) - bits |= U_GLOWTRAIL; - if ((val = GETEDICTFIELDVALUE(ent, eval_glow_color))) if (val->_float != 0) glowcolor = (int) val->_float; @@ -585,16 +687,17 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) if (ent != clent) { - if (glowsize == 0 && (bits & U_GLOWTRAIL) == 0) // no effects - { - if (ent->v.modelindex && pr_strings[ent->v.model]) // model - { - if (sv.models[ (int)ent->v.modelindex ]->flags == 0 && (ent->v.effects == EF_NODRAW || scale <= 0 || alpha <= 0)) +// if (glowsize == 0 && (bits & U_GLOWTRAIL) == 0) // no effects +// { +// if (ent->v.modelindex && pr_strings[ent->v.model]) // model +// { + // don't send if flagged for NODRAW and there are no effects + if (sv.models[(int)ent->v.modelindex]->flags == 0 && ((effects & EF_NODRAW) || scale <= 0 || alpha <= 0)) continue; - } - else // no model and no effects - continue; - } +// } +// else // no model and no effects +// continue; +// } } if (msg->maxsize - msg->cursize < 32) // LordHavoc: increased check from 16 to 32 @@ -606,6 +709,9 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) return; } + if ((val = GETEDICTFIELDVALUE(ent, eval_exteriormodeltoclient)) && val->edict == clentnum) + bits = bits | U_EXTERIORMODEL; + // send an update baseline = &ent->baseline; @@ -623,7 +729,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) else nextfullupdate = realtime + 0.5f; - // restore nextfullupdate since this is being sent + // restore nextfullupdate since this is being sent for real client->nextfullupdate[e] = nextfullupdate; if (e >= 256) @@ -632,59 +738,6 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) if (ent->v.movetype == MOVETYPE_STEP) bits |= U_STEP; - if (ent->v.movetype == MOVETYPE_STEP && ((int) ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM))) // monsters have smoothed walking/flying/swimming movement - { - if (!ent->steplerptime || ent->steplerptime > sv.time) // when the level just started... - { - ent->steplerptime = sv.time; - VectorCopy(ent->v.origin, ent->stepoldorigin); - VectorCopy(ent->v.angles, ent->stepoldangles); - VectorCopy(ent->v.origin, ent->steporigin); - VectorCopy(ent->v.angles, ent->stepangles); - } - VectorSubtract(ent->v.origin, ent->steporigin, origin); - VectorSubtract(ent->v.angles, ent->stepangles, angles); - if (DotProduct(origin, origin) >= 0.125 || DotProduct(angles, angles) >= 1.4) - { - // update lerp positions - ent->steplerptime = sv.time; - VectorCopy(ent->steporigin, ent->stepoldorigin); - VectorCopy(ent->stepangles, ent->stepoldangles); - VectorCopy(ent->v.origin, ent->steporigin); - VectorCopy(ent->v.angles, ent->stepangles); - } - movelerp = (sv.time - ent->steplerptime) * 10.0; - if (movelerp > 1) movelerp = 1; - moveilerp = 1 - movelerp; - origin[0] = ent->stepoldorigin[0] * moveilerp + ent->steporigin[0] * movelerp; - origin[1] = ent->stepoldorigin[1] * moveilerp + ent->steporigin[1] * movelerp; - origin[2] = ent->stepoldorigin[2] * moveilerp + ent->steporigin[2] * movelerp; - // choose shortest rotate (to avoid 'spin around' situations) - VectorSubtract(ent->stepangles, ent->stepoldangles, angles); - if (angles[0] < -180) angles[0] += 360;if (angles[0] >= 180) angles[0] -= 360; - if (angles[1] < -180) angles[1] += 360;if (angles[1] >= 180) angles[1] -= 360; - if (angles[2] < -180) angles[2] += 360;if (angles[2] >= 180) angles[2] -= 360; - angles[0] = angles[0] * movelerp + ent->stepoldangles[0]; - angles[1] = angles[1] * movelerp + ent->stepoldangles[1]; - angles[2] = angles[2] * movelerp + ent->stepoldangles[2]; - VectorMA(origin, host_client->latency, ent->v.velocity, origin); - } - else // copy as they are - { -// VectorCopy(ent->v.origin, origin); - VectorCopy(ent->v.angles, angles); - VectorMA(ent->v.origin, host_client->latency, ent->v.velocity, origin); - if (ent->v.movetype == MOVETYPE_STEP) // monster, but airborn, update lerp info - { - // update lerp positions - ent->steplerptime = sv.time; - VectorCopy(ent->v.origin, ent->stepoldorigin); - VectorCopy(ent->v.angles, ent->stepoldangles); - VectorCopy(ent->v.origin, ent->steporigin); - VectorCopy(ent->v.angles, ent->stepangles); - } - } - // LordHavoc: old stuff, but rewritten to have more exact tolerances // if ((int)(origin[0]*8.0) != (int)(baseline->origin[0]*8.0)) bits |= U_ORIGIN1; // if ((int)(origin[1]*8.0) != (int)(baseline->origin[1]*8.0)) bits |= U_ORIGIN2; diff --git a/world.c b/world.c index dba8fe9f..fc2f38a4 100644 --- a/world.c +++ b/world.c @@ -404,55 +404,6 @@ loc0: } -/* -=============== -SV_FindTouchedLeafs - -=============== -*/ -void SV_FindTouchedLeafs (edict_t *ent, mnode_t *node) -{ -loc0: - if (node->contents == CONTENTS_SOLID) - return; - -// add an efrag if the node is a leaf - - if ( node->contents < 0) - { - if (ent->num_leafs == MAX_ENT_LEAFS) - { - Con_DPrintf("FindTouchedLeafs overflow\n"); - return; - } - - ent->leafnums[ent->num_leafs++] = (mleaf_t *)node - sv.worldmodel->leafs - 1; - return; - } - -// recurse down the contacted sides - -// sides = BOX_ON_PLANE_SIDE(ent->v.absmin, ent->v.absmax, node->plane); -// if (sides & 1) SV_FindTouchedLeafs (ent, node->children[0]); -// if (sides & 2) SV_FindTouchedLeafs (ent, node->children[1]); - - // LordHavoc: optimized recursion - switch (BOX_ON_PLANE_SIDE(ent->v.absmin, ent->v.absmax, node->plane)) - { - case 1: - node = node->children[0]; - goto loc0; - case 2: - node = node->children[1]; - goto loc0; - default: // 3 - if (node->children[0]->contents != CONTENTS_SOLID) - SV_FindTouchedLeafs (ent, node->children[0]); - node = node->children[1]; - goto loc0; - } -} - /* =============== SV_LinkEdict @@ -533,11 +484,6 @@ void SV_LinkEdict (edict_t *ent, qboolean touch_triggers) ent->v.absmax[2] += 1; } -// link to PVS leafs - ent->num_leafs = 0; - if (ent->v.modelindex) - SV_FindTouchedLeafs (ent, sv.worldmodel->nodes); - if (ent->v.solid == SOLID_NOT) return; @@ -602,7 +548,7 @@ edict_t *SV_TestEntityPosition (edict_t *ent) { trace_t trace; - trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, 0, ent); + trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, MOVE_NORMAL, ent); if (trace.startsolid) return sv.edicts; -- 2.39.2