From ec3f709602d4eb7697a130fbcc483700ad571c1a Mon Sep 17 00:00:00 2001 From: havoc Date: Mon, 11 Aug 2003 12:20:51 +0000 Subject: [PATCH] moved SV_FatPVS to model code git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@3390 d7cf8633-e32d-0410-b094-e92efae38249 --- model_brush.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++++ model_shared.h | 2 + sv_main.c | 105 ++++---------------------------------- 3 files changed, 145 insertions(+), 95 deletions(-) diff --git a/model_brush.c b/model_brush.c index d832103f..7a99e9fa 100644 --- a/model_brush.c +++ b/model_brush.c @@ -64,6 +64,45 @@ static mleaf_t *Mod_Q1BSP_PointInLeaf(model_t *model, const vec3_t p) return (mleaf_t *)node; } + +static int Mod_Q1BSP_BoxTouchingPVS_RecursiveBSPNode(const model_t *model, const mnode_t *node, const qbyte *pvs, const vec3_t mins, const vec3_t maxs) +{ + int leafnum; +loc0: + if (node->contents < 0) + { + // leaf + if (node->contents == CONTENTS_SOLID) + return false; + leafnum = (mleaf_t *)node - model->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 (Mod_Q1BSP_BoxTouchingPVS_RecursiveBSPNode(model, node->children[0], pvs, mins, maxs)) + return true; + node = node->children[1]; + goto loc0; + } + // never reached + return false; +} + +int Mod_Q1BSP_BoxTouchingPVS(model_t *model, const qbyte *pvs, const vec3_t mins, const vec3_t maxs) +{ + return Mod_Q1BSP_BoxTouchingPVS_RecursiveBSPNode(model, model->brushq1.nodes + model->brushq1.hulls[0].firstclipnode, pvs, mins, maxs); +} + /* static int Mod_Q1BSP_PointContents(model_t *model, const vec3_t p) { @@ -2999,6 +3038,53 @@ 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; + + while (1) + { + // 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); + for (i = 0;i < pvsbytes;i++) + pvsbuffer[i] |= pvs[i]; + } + return; + } + + plane = node->plane; + d = DotProduct(org, plane->normal) - plane->dist; + if (d > radius) + node = node->children[0]; + else if (d < -radius) + node = node->children[1]; + else + { // go down both + Mod_Q1BSP_FatPVS_RecursiveBSPNode(model, org, radius, pvsbuffer, pvsbytes, node->children[0]); + node = node->children[1]; + } + } +} + +//Calculates a PVS that is the inclusive or of all leafs within radius pixels +//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; + memset(pvsbuffer, 0, bytes); + Mod_Q1BSP_FatPVS_RecursiveBSPNode(model, org, radius, pvsbuffer, bytes, sv.worldmodel->brushq1.nodes); + return bytes; +} + extern void R_Model_Brush_DrawSky(entity_render_t *ent); extern void R_Model_Brush_Draw(entity_render_t *ent); extern void R_Model_Brush_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius); @@ -3024,6 +3110,8 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer) Host_Error("Mod_Q1BSP_Load: %s has wrong version number(%i should be %i(Quake) or 30(HalfLife))", mod->name, i, BSPVERSION); mod->brushq1.ishlbsp = i == 30; + mod->brush.FatPVS = Mod_Q1BSP_FatPVS; + mod->brush.BoxTouchingPVS = Mod_Q1BSP_BoxTouchingPVS; mod->brush.LightPoint = Mod_Q1BSP_LightPoint; mod->brush.FindNonSolidLocation = Mod_Q1BSP_FindNonSolidLocation; mod->brush.TraceBox = Mod_Q1BSP_TraceBox; @@ -4400,6 +4488,49 @@ void Mod_Q3BSP_TraceBox(model_t *model, trace_t *trace, const vec3_t boxstartmin Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, model->brushq3.data_brushes[i].colbrushf, model->brushq3.data_brushes[i].colbrushf); } + +static int Mod_Q3BSP_BoxTouchingPVS_RecursiveBSPNode(const model_t *model, const q3mnode_t *node, const qbyte *pvs, const vec3_t mins, const vec3_t maxs) +{ + int clusterindex; +loc0: + if (!node->isnode) + { + // leaf + clusterindex = ((q3mleaf_t *)node)->clusterindex; + return pvs[clusterindex >> 3] & (1 << (clusterindex & 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 (Mod_Q3BSP_BoxTouchingPVS_RecursiveBSPNode(model, node->children[0], pvs, mins, maxs)) + return true; + node = node->children[1]; + goto loc0; + } + // never reached + return false; +} + +int Mod_Q3BSP_BoxTouchingPVS(model_t *model, const qbyte *pvs, const vec3_t mins, const vec3_t maxs) +{ + return Mod_Q3BSP_BoxTouchingPVS_RecursiveBSPNode(model, model->brushq3.data_nodes, pvs, mins, maxs); +} + +int Mod_Q3BSP_FatPVS(model_t *model, const vec3_t org, vec_t radius, qbyte *pvsbuffer, int pvsbufferlength) +{ + // FIXME: write this + memset(pvsbuffer, 0xFF, pvsbufferlength); + return pvsbufferlength; +} + void Mod_Q3BSP_Load(model_t *mod, void *buffer) { int i; @@ -4419,6 +4550,8 @@ void Mod_Q3BSP_Load(model_t *mod, void *buffer) R_ResetQuakeSky(); } + mod->brush.FatPVS = Mod_Q3BSP_FatPVS; + mod->brush.BoxTouchingPVS = Mod_Q3BSP_BoxTouchingPVS; mod->brush.LightPoint = Mod_Q3BSP_LightPoint; mod->brush.FindNonSolidLocation = Mod_Q3BSP_FindNonSolidLocation; mod->brush.TraceBox = Mod_Q3BSP_TraceBox; diff --git a/model_shared.h b/model_shared.h index 2c2a1829..a911946d 100644 --- a/model_shared.h +++ b/model_shared.h @@ -145,6 +145,8 @@ struct trace_s; typedef struct model_brush_s { char *entities; + int (*FatPVS)(struct model_s *model, const vec3_t org, vec_t radius, qbyte *pvsbuffer, int pvsbufferlength); + int (*BoxTouchingPVS)(struct model_s *model, const qbyte *pvs, const vec3_t mins, const vec3_t maxs); void (*LightPoint)(struct model_s *model, const vec3_t p, vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal); void (*FindNonSolidLocation)(struct model_s *model, const vec3_t in, vec3_t out, vec_t radius); void (*TraceBox)(struct model_s *model, struct trace_s *trace, const vec3_t boxstartmins, const vec3_t boxstartmaxs, const vec3_t boxendmins, const vec3_t boxendmaxs); diff --git a/sv_main.c b/sv_main.c index d96e1196..310a726f 100644 --- a/sv_main.c +++ b/sv_main.c @@ -374,96 +374,8 @@ crosses a waterline. ============================================================================= */ -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 ; iplane; - 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]; /* ============= @@ -488,7 +400,9 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) // 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; @@ -589,7 +503,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) 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; @@ -925,7 +839,6 @@ 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; @@ -1006,7 +919,7 @@ void SV_MarkWriteEntityStateToClient(entity_state_t *s) 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; @@ -1097,7 +1010,9 @@ void SV_WriteEntitiesToClient(client_t *client, edict_t *clent, sizebuf_t *msg) // 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 -- 2.39.2