From: lordhavoc Date: Mon, 29 Oct 2001 07:23:10 +0000 (+0000) Subject: got rid of leafnums array in edict structure for pvs checking, pvs is now checked... X-Git-Tag: RELEASE_0_2_0_RC1~754 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=c8f4487266cf656bd399f8ab9cba7118947a0911;p=xonotic%2Fdarkplaces.git 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 --- 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;