From 3bd6892353a16d76000d0c314da16cee7b034de7 Mon Sep 17 00:00:00 2001 From: Spoike Date: Fri, 23 May 2014 02:02:51 +0000 Subject: [PATCH] try to fix q2/q3bsp checkclient bug by rewriting everything to do with pvs! git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4668 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/client.h | 1 + engine/client/m_mp3.c | 5 +++ engine/client/pr_clcmd.c | 38 ++++++++++++-------- engine/client/renderer.c | 8 ++--- engine/common/gl_q2bsp.c | 28 ++++++++++----- engine/common/q1bsp.c | 67 +++++++++++++++++++++++++++++------- engine/gl/gl_heightmap.c | 15 ++++---- engine/gl/gl_model.c | 8 ++--- engine/gl/gl_model.h | 9 ++--- engine/gl/gl_rmain.c | 12 +++---- engine/gl/gl_shadow.c | 45 +++++++++++++----------- engine/server/net_preparse.c | 25 ++++++++------ engine/server/pr_cmds.c | 17 ++++----- engine/server/sv_ents.c | 27 +++++++++------ engine/server/sv_init.c | 9 ++--- engine/server/sv_send.c | 39 ++++++++++++--------- engine/server/svq3_game.c | 2 +- 17 files changed, 224 insertions(+), 131 deletions(-) diff --git a/engine/client/client.h b/engine/client/client.h index e6a37dc2..631e05e3 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -1387,6 +1387,7 @@ void Media_Send_MouseMove(cin_t *cin, float x, float y); void Media_Send_Resize(cin_t *cin, int x, int y); void Media_Send_GetSize(cin_t *cin, int *x, int *y); void Media_Send_KeyEvent(cin_t *cin, int button, int unicode, int event); +void Media_Send_Reset(cin_t *cin); void MVD_Interpolate(void); diff --git a/engine/client/m_mp3.c b/engine/client/m_mp3.c index 57b30bfd..0161cbea 100644 --- a/engine/client/m_mp3.c +++ b/engine/client/m_mp3.c @@ -2705,6 +2705,11 @@ void Media_Send_GetSize(cin_t *cin, int *x, int *y) return; cin->getsize(cin, x, y); } +void Media_Send_Reset(cin_t *cin) +{ + if (!cin || !cin->rewind) + cin->rewind(cin); +} diff --git a/engine/client/pr_clcmd.c b/engine/client/pr_clcmd.c index d4ce809c..e06b2f15 100644 --- a/engine/client/pr_clcmd.c +++ b/engine/client/pr_clcmd.c @@ -358,42 +358,54 @@ void QCBUILTIN PF_cl_runningserver (pubprogfuncs_t *prinst, struct globalvars_s #ifndef NOMEDIA -// #487 float(string name) gecko_create( string name ) +// #487 float(string name) gecko_create void QCBUILTIN PF_cs_gecko_create (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { const char *shadername = PR_GetStringOfs(prinst, OFS_PARM0); cin_t *cin; cin = R_ShaderGetCinematic(R_RegisterShader(shadername, SUF_2D, "{\n" + "program default2d\n" "{\n" "videomap http:\n" + "rgbgen vertex\n" + "alphagen vertex\n" + "blendfunc blend\n" + "nodepth\n" "}\n" "}\n" )); - if (!cin) - G_FLOAT(OFS_RETURN) = 0; - else + if (cin) + { G_FLOAT(OFS_RETURN) = 1; + Media_Send_Reset(cin); + } + else + G_FLOAT(OFS_RETURN) = 0; } -// #488 void(string name) gecko_destroy( string name ) +// #488 void(string name) gecko_destroy void QCBUILTIN PF_cs_gecko_destroy (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { + const char *shader = PR_GetStringOfs(prinst, OFS_PARM0); + cin_t *cin; + cin = R_ShaderFindCinematic(shader); + if (!cin) + return; + Media_Send_Reset(cin); //FIXME } -// #489 void(string name) gecko_navigate( string name, string URI ) +// #489 void(string name, string URI) gecko_navigate void QCBUILTIN PF_cs_gecko_navigate (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { const char *shader = PR_GetStringOfs(prinst, OFS_PARM0); const char *command = PR_GetStringOfs(prinst, OFS_PARM1); cin_t *cin; cin = R_ShaderFindCinematic(shader); - if (!cin) return; - Media_Send_Command(cin, command); } -// #490 float(string name) gecko_keyevent( string name, float key, float eventtype ) +// #490 float(string name, float key, float eventtype) gecko_keyevent void QCBUILTIN PF_cs_gecko_keyevent (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { const char *shader = PR_GetStringOfs(prinst, OFS_PARM0); @@ -401,12 +413,11 @@ void QCBUILTIN PF_cs_gecko_keyevent (pubprogfuncs_t *prinst, struct globalvars_s int eventtype = G_FLOAT(OFS_PARM2); cin_t *cin; cin = R_ShaderFindCinematic(shader); - if (!cin) return; Media_Send_KeyEvent(cin, MP_TranslateQCtoFTECodes(key), (key>127)?0:key, eventtype); } -// #491 void gecko_mousemove( string name, float x, float y ) +// #491 void(string name, float x, float y) gecko_mousemove void QCBUILTIN PF_cs_gecko_mousemove (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { const char *shader = PR_GetStringOfs(prinst, OFS_PARM0); @@ -414,12 +425,11 @@ void QCBUILTIN PF_cs_gecko_mousemove (pubprogfuncs_t *prinst, struct globalvars_ float posy = G_FLOAT(OFS_PARM2); cin_t *cin; cin = R_ShaderFindCinematic(shader); - if (!cin) return; Media_Send_MouseMove(cin, posx, posy); } -// #492 void gecko_resize( string name, float w, float h ) +// #492 void(string name, float w, float h) gecko_resize void QCBUILTIN PF_cs_gecko_resize (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { const char *shader = PR_GetStringOfs(prinst, OFS_PARM0); @@ -431,7 +441,7 @@ void QCBUILTIN PF_cs_gecko_resize (pubprogfuncs_t *prinst, struct globalvars_s * return; Media_Send_Resize(cin, sizex, sizey); } -// #493 vector gecko_get_texture_extent( string name ) +// #493 vector(string name) gecko_get_texture_extent void QCBUILTIN PF_cs_gecko_get_texture_extent (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { const char *shader = PR_GetStringOfs(prinst, OFS_PARM0); diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 7db96b82..a5d3f361 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -2030,7 +2030,7 @@ qbyte *R_CalcVis_Q1 (void) int c; Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf2, curframevis, sizeof(curframevis)); vis = Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf, NULL, sizeof(curframevis)); - c = (cl.worldmodel->numvisleafs+31)/32; + c = (cl.worldmodel->numclusters+31)/32; for (i=0 ; inumvisleafs+7)>>3); + memset (fatvis[portal], 0xff, (cl.worldmodel->numclusters+7)>>3); r_oldviewleaf = NULL; r_oldviewleaf2 = NULL; @@ -2090,7 +2090,7 @@ qbyte *R_MarkLeaves_Q1 (void) int c; Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf2, fatvis[portal], sizeof(fatvis[portal])); vis = cvis[portal] = Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf, NULL, 0); - c = (cl.worldmodel->numvisleafs+31)/32; + c = (cl.worldmodel->numclusters+31)/32; for (i=0 ; inumvisleafs ; i++) + for (i=0 ; inumclusters ; i++) { if (vis[i>>3] & (1<<(i&7))) { diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index 06027ef9..5b74b43b 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -57,6 +57,7 @@ void Mod_LoadLighting (lump_t *l); static qboolean CM_NativeTrace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int contents, trace_t *trace); static unsigned int CM_NativeContents(struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p, vec3_t mins, vec3_t maxs); static unsigned int Q2BSP_PointContents(model_t *mod, vec3_t axis[3], vec3_t p); +static int CM_PointCluster (model_t *mod, vec3_t p); extern mplane_t *box_planes; @@ -3739,10 +3740,12 @@ void CMQ3_CalcPHS (void) } #endif +/* static qbyte *CM_LeafnumPVS (model_t *model, int leafnum, qbyte *buffer, unsigned int buffersize) { return CM_ClusterPVS(model, CM_LeafCluster(model, leafnum), buffer, buffersize); } +*/ #ifndef SERVERONLY #define GLQ2BSP_LightPointValues GLQ1BSP_LightPointValues @@ -4079,8 +4082,8 @@ cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned *c loadmodel->funcs.EdictInFatPVS = Q2BSP_EdictInFatPVS; loadmodel->funcs.FindTouchedLeafs = Q2BSP_FindTouchedLeafs; #endif - loadmodel->funcs.LeafPVS = CM_LeafnumPVS; - loadmodel->funcs.LeafnumForPoint = CM_PointLeafnum; + loadmodel->funcs.ClusterPVS = CM_ClusterPVS; + loadmodel->funcs.ClusterForPoint = CM_PointCluster; #ifndef SERVERONLY loadmodel->funcs.LightPointValues = GLQ3_LightGrid; @@ -4170,8 +4173,8 @@ cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned *c loadmodel->funcs.LightPointValues = NULL; loadmodel->funcs.StainNode = NULL; loadmodel->funcs.MarkLights = NULL; - loadmodel->funcs.LeafPVS = CM_LeafnumPVS; - loadmodel->funcs.LeafnumForPoint = CM_PointLeafnum; + loadmodel->funcs.ClusterPVS = CM_ClusterPVS; + loadmodel->funcs.ClusterForPoint = CM_PointCluster; loadmodel->funcs.PointContents = Q2BSP_PointContents; loadmodel->funcs.NativeTrace = CM_NativeTrace; loadmodel->funcs.NativeContents = CM_NativeContents; @@ -4220,8 +4223,8 @@ cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned *c loadmodel->funcs.LightPointValues = GLQ2BSP_LightPointValues; loadmodel->funcs.StainNode = GLR_Q2BSP_StainNode; loadmodel->funcs.MarkLights = Q2BSP_MarkLights; - loadmodel->funcs.LeafPVS = CM_LeafnumPVS; - loadmodel->funcs.LeafnumForPoint = CM_PointLeafnum; + loadmodel->funcs.ClusterPVS = CM_ClusterPVS; + loadmodel->funcs.ClusterForPoint = CM_PointCluster; loadmodel->funcs.PointContents = Q2BSP_PointContents; loadmodel->funcs.NativeTrace = CM_NativeTrace; loadmodel->funcs.NativeContents = CM_NativeContents; @@ -4416,8 +4419,8 @@ void CM_InitBoxHull (void) #ifndef SERVERONLY box_model.funcs.MarkLights = Q2BSP_MarkLights; #endif - box_model.funcs.LeafPVS = CM_LeafnumPVS; - box_model.funcs.LeafnumForPoint = CM_PointLeafnum; + box_model.funcs.ClusterPVS = CM_ClusterPVS; + box_model.funcs.ClusterForPoint = CM_PointCluster; box_model.funcs.NativeContents = CM_NativeContents; box_model.funcs.NativeTrace = CM_NativeTrace; @@ -4516,7 +4519,7 @@ CM_PointLeafnum_r ================== */ -int CM_PointLeafnum_r (model_t *mod, vec3_t p, int num) +static int CM_PointLeafnum_r (model_t *mod, vec3_t p, int num) { float d; mnode_t *node; @@ -4547,6 +4550,13 @@ int CM_PointLeafnum (model_t *mod, vec3_t p) return CM_PointLeafnum_r (mod, p, 0); } +static int CM_PointCluster (model_t *mod, vec3_t p) +{ + if (!mod || mod->needload) + return 0; // sound may call this without map loaded + return CM_LeafCluster(mod, CM_PointLeafnum_r (mod, p, 0)); +} + /* ============= CM_BoxLeafnums diff --git a/engine/common/q1bsp.c b/engine/common/q1bsp.c index b1f3dd1f..4365300e 100644 --- a/engine/common/q1bsp.c +++ b/engine/common/q1bsp.c @@ -1519,7 +1519,7 @@ Server only functions #ifndef CLIENTONLY //does the recursive work of Q1BSP_FatPVS -void SV_Q1BSP_AddToFatPVS (model_t *mod, vec3_t org, mnode_t *node, qbyte *buffer, unsigned int buffersize) +static void SV_Q1BSP_AddToFatPVS (model_t *mod, vec3_t org, mnode_t *node, qbyte *buffer, unsigned int buffersize) { int i; qbyte *pvs; @@ -1562,7 +1562,7 @@ Calculates a PVS that is the inclusive or of all leafs within 8 pixels of the given point. ============= */ -unsigned int Q1BSP_FatPVS (model_t *mod, vec3_t org, qbyte *pvsbuffer, unsigned int buffersize, qboolean add) +static unsigned int Q1BSP_FatPVS (model_t *mod, vec3_t org, qbyte *pvsbuffer, unsigned int buffersize, qboolean add) { unsigned int fatbytes = (mod->numleafs+31)>>3; if (fatbytes > buffersize) @@ -1574,7 +1574,7 @@ unsigned int Q1BSP_FatPVS (model_t *mod, vec3_t org, qbyte *pvsbuffer, unsigned } #endif -qboolean Q1BSP_EdictInFatPVS(model_t *mod, struct pvscache_s *ent, qbyte *pvs) +static qboolean Q1BSP_EdictInFatPVS(model_t *mod, struct pvscache_s *ent, qbyte *pvs) { int i; @@ -1595,7 +1595,7 @@ SV_FindTouchedLeafs Links the edict to the right leafs so we can get it's potential visability. =============== */ -void Q1BSP_RFindTouchedLeafs (model_t *wm, struct pvscache_s *ent, mnode_t *node, float *mins, float *maxs) +static void Q1BSP_RFindTouchedLeafs (model_t *wm, struct pvscache_s *ent, mnode_t *node, float *mins, float *maxs) { mplane_t *splitplane; mleaf_t *leaf; @@ -1635,7 +1635,7 @@ void Q1BSP_RFindTouchedLeafs (model_t *wm, struct pvscache_s *ent, mnode_t *node if (sides & 2) Q1BSP_RFindTouchedLeafs (wm, ent, node->children[1], mins, maxs); } -void Q1BSP_FindTouchedLeafs(model_t *mod, struct pvscache_s *ent, float *mins, float *maxs) +static void Q1BSP_FindTouchedLeafs(model_t *mod, struct pvscache_s *ent, float *mins, float *maxs) { ent->num_leafs = 0; if (mins && maxs) @@ -1656,13 +1656,13 @@ PVS type stuff Mod_DecompressVis =================== */ -qbyte *Q1BSP_DecompressVis (qbyte *in, model_t *model, qbyte *decompressed, unsigned int buffersize) +static qbyte *Q1BSP_DecompressVis (qbyte *in, model_t *model, qbyte *decompressed, unsigned int buffersize) { int c; qbyte *out; int row; - row = (model->numvisleafs+7)>>3; + row = (model->numclusters+7)>>3; out = decompressed; if (buffersize < row) @@ -1720,13 +1720,26 @@ qbyte *Q1BSP_LeafPVS (model_t *model, mleaf_t *leaf, qbyte *buffer, unsigned int return Q1BSP_DecompressVis (leaf->compressed_vis, model, buffer, buffersize); } -qbyte *Q1BSP_LeafnumPVS (model_t *model, int leafnum, qbyte *buffer, unsigned int buffersize) +//pvs is 1-based. clusters are 0-based. otherwise, q1bsp has a 1:1 mapping. +static qbyte *Q1BSP_ClusterPVS (model_t *model, int cluster, qbyte *buffer, unsigned int buffersize) { - return Q1BSP_LeafPVS(model, model->leafs + leafnum, buffer, buffersize); + static qbyte decompressed[MAX_MAP_LEAFS/8]; + + if (cluster == -1) + return mod_novis; + cluster++; + + if (!buffer) + { + buffer = decompressed; + buffersize = sizeof(decompressed); + } + + return Q1BSP_DecompressVis (model->leafs[cluster+1].compressed_vis, model, buffer, buffersize); } //returns the leaf number, which is used as a bit index into the pvs. -int Q1BSP_LeafnumForPoint (model_t *model, vec3_t p) +static int Q1BSP_LeafnumForPoint (model_t *model, vec3_t p) { mnode_t *node; float d; @@ -1760,6 +1773,36 @@ mleaf_t *Q1BSP_LeafForPoint (model_t *model, vec3_t p) return model->leafs + Q1BSP_LeafnumForPoint(model, p); } +//returns the leaf number, which is used as a direct bit index into the pvs. +//-1 for invalid +static int Q1BSP_ClusterForPoint (model_t *model, vec3_t p) +{ + mnode_t *node; + float d; + mplane_t *plane; + + if (!model) + { + Sys_Error ("Mod_PointInLeaf: bad model"); + } + if (!model->nodes) + return -1; + + node = model->nodes; + while (1) + { + if (node->contents < 0) + return ((mleaf_t *)node - model->leafs) - 1; + plane = node->plane; + d = DotProduct (p,plane->normal) - plane->dist; + if (d > 0) + node = node->children[0]; + else + node = node->children[1]; + } + + return -1; // never reached +} /* @@ -1858,8 +1901,8 @@ void Q1BSP_SetModelFuncs(model_t *mod) mod->funcs.StainNode = NULL; mod->funcs.MarkLights = NULL; - mod->funcs.LeafnumForPoint = Q1BSP_LeafnumForPoint; - mod->funcs.LeafPVS = Q1BSP_LeafnumPVS; + mod->funcs.ClusterForPoint = Q1BSP_ClusterForPoint; + mod->funcs.ClusterPVS = Q1BSP_ClusterPVS; mod->funcs.NativeTrace = Q1BSP_Trace; mod->funcs.PointContents = Q1BSP_PointContents; } diff --git a/engine/gl/gl_heightmap.c b/engine/gl/gl_heightmap.c index 16170054..376bdd9a 100644 --- a/engine/gl/gl_heightmap.c +++ b/engine/gl/gl_heightmap.c @@ -3697,14 +3697,15 @@ void Heightmap_MarkLights (dlight_t *light, int bit, mnode_t *node) { } -qbyte *Heightmap_LeafnumPVS (model_t *model, int num, qbyte *buffer, unsigned int buffersize) +qbyte *Heightmap_ClusterPVS (model_t *model, int num, qbyte *buffer, unsigned int buffersize) { - static qbyte heightmappvs = 255; - return &heightmappvs; + return NULL; +// static qbyte heightmappvs = 255; +// return &heightmappvs; } -int Heightmap_LeafForPoint (model_t *model, vec3_t point) +int Heightmap_ClusterForPoint (model_t *model, vec3_t point) { - return 0; + return -1; } #ifndef SERVERONLY @@ -4572,8 +4573,8 @@ qboolean QDECL Terr_LoadTerrainModel (model_t *mod, void *buffer, size_t bufsize mod->funcs.StainNode = Heightmap_StainNode; mod->funcs.MarkLights = Heightmap_MarkLights; - mod->funcs.LeafnumForPoint = Heightmap_LeafForPoint; - mod->funcs.LeafPVS = Heightmap_LeafnumPVS; + mod->funcs.ClusterForPoint = Heightmap_ClusterForPoint; + mod->funcs.ClusterPVS = Heightmap_ClusterPVS; #ifndef CLIENTONLY mod->funcs.FindTouchedLeafs = Heightmap_FindTouchedLeafs; diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index dbe96883..b27aa894 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -3337,7 +3337,7 @@ qboolean Mod_LoadLeafs (lump_t *l, int lm) loadmodel->leafs = out; loadmodel->numleafs = count; - loadmodel->numvisleafs = count-1; + loadmodel->numclusters = count-1; for ( i=0 ; ileafs = out; loadmodel->numleafs = count; - loadmodel->numvisleafs = count-1; + loadmodel->numclusters = count-1; for ( i=0 ; ileafs = out; loadmodel->numleafs = count; - loadmodel->numvisleafs = count-1; + loadmodel->numclusters = count-1; for ( i=0 ; iradius = RadiusFromBounds (mod->mins, mod->maxs); - mod->numvisleafs = bm->visleafs; + mod->numclusters = bm->visleafs; memset(&mod->batches, 0, sizeof(mod->batches)); mod->vbos = NULL; diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index 046ffc0c..eaa0bd94 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -216,8 +216,8 @@ typedef struct { void (*StainNode) (struct mnode_s *node, float *parms); void (*MarkLights) (struct dlight_s *light, int bit, struct mnode_s *node); - qbyte *(*LeafPVS) (struct model_s *model, int num, qbyte *buffer, unsigned int buffersize); - int (*LeafnumForPoint) (struct model_s *model, vec3_t point); + int (*ClusterForPoint) (struct model_s *model, vec3_t point); //pvs index. may be negative (ie: no pvs). + qbyte *(*ClusterPVS) (struct model_s *model, int cluster, qbyte *buffer, unsigned int buffersize); } modelfuncs_t; @@ -501,9 +501,6 @@ void Q1BSP_MarkLights (dlight_t *light, int bit, mnode_t *node); void GLQ1BSP_LightPointValues(struct model_s *model, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir); qboolean Q1BSP_Trace(struct model_s *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int hitcontentsmask, struct trace_s *trace); qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, struct trace_s *trace); -unsigned int Q1BSP_FatPVS (struct model_s *mod, vec3_t org, qbyte *pvsbuffer, unsigned int buffersize, qboolean add); -qboolean Q1BSP_EdictInFatPVS(struct model_s *mod, struct pvscache_s *ent, qbyte *pvs); -void Q1BSP_FindTouchedLeafs(struct model_s *mod, struct pvscache_s *ent, float *mins, float *maxs); qbyte *Q1BSP_LeafPVS (struct model_s *model, mleaf_t *leaf, qbyte *buffer, unsigned int buffersize); /* @@ -874,7 +871,7 @@ typedef struct model_s int numplanes; mplane_t *planes; - int numvisleafs; + int numclusters; int numleafs; // number of visible leafs, not counting 0 mleaf_t *leafs; diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index 22eb9b99..a0824261 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -876,12 +876,12 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, batch_t *depthmasklist[2], //use the player's origin for r_viewleaf, because there's not much we can do anyway*/ VectorCopy(r_origin, r_refdef.pvsorigin); - if (cl.worldmodel && cl.worldmodel->funcs.LeafPVS && !r_novis.ival) + if (cl.worldmodel && cl.worldmodel->funcs.ClusterPVS && !r_novis.ival) { - int lnum, i, j; + int clust, i, j; float d; vec3_t point; - int pvsbytes = (cl.worldmodel->numvisleafs+7)>>3; + int pvsbytes = (cl.worldmodel->numclusters+7)>>3; if (pvsbytes > sizeof(newvis)) pvsbytes = sizeof(newvis); r_refdef.forcevis = true; @@ -897,16 +897,16 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, batch_t *depthmasklist[2], d += 0.1; //an epsilon on the far side VectorMA(point, d, plane.normal, point); - lnum = cl.worldmodel->funcs.LeafnumForPoint(cl.worldmodel, point); + clust = cl.worldmodel->funcs.ClusterForPoint(cl.worldmodel, point); if (i == batch->firstmesh) - r_refdef.forcedvis = cl.worldmodel->funcs.LeafPVS(cl.worldmodel, lnum, newvis, sizeof(newvis)); + r_refdef.forcedvis = cl.worldmodel->funcs.ClusterPVS(cl.worldmodel, clust, newvis, sizeof(newvis)); else { if (r_refdef.forcedvis != newvis) { memcpy(newvis, r_refdef.forcedvis, pvsbytes); } - r_refdef.forcedvis = cl.worldmodel->funcs.LeafPVS(cl.worldmodel, lnum, NULL, sizeof(newvis)); + r_refdef.forcedvis = cl.worldmodel->funcs.ClusterPVS(cl.worldmodel, clust, NULL, sizeof(newvis)); for (j = 0; j < pvsbytes; j+= 4) { diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index ccc184c2..f57075b3 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -449,7 +449,7 @@ static void SHM_BeginShadowMesh(dlight_t *dl, int type) unsigned int lb; sh_vertnum = 0; - lb = (cl.worldmodel->numvisleafs+7)/8; + lb = (cl.worldmodel->numclusters+7)/8; if (!dl->die || !dl->key) { sh_shmesh = dl->worldshadowmesh; @@ -978,7 +978,7 @@ static void SHM_MarkLeavesQ2(dlight_t *dl, unsigned char *lvis, unsigned char *v { //static //variation on mark leaves - for (i=0,leaf=cl.worldmodel->leafs ; inumvisleafs ; i++, leaf++) + for (i=0,leaf=cl.worldmodel->leafs ; inumleafs ; i++, leaf++) { cluster = leaf->cluster; if (cluster == -1) @@ -1000,7 +1000,7 @@ static void SHM_MarkLeavesQ2(dlight_t *dl, unsigned char *lvis, unsigned char *v { //dynamic lights will be discarded after this frame anyway, so only include leafs that are visible //variation on mark leaves - for (i=0,leaf=cl.worldmodel->leafs ; inumvisleafs ; i++, leaf++) + for (i=0,leaf=cl.worldmodel->leafs ; inumleafs ; i++, leaf++) { cluster = leaf->cluster; if (cluster == -1) @@ -1027,8 +1027,11 @@ static void SHM_MarkLeavesQ1(dlight_t *dl, unsigned char *lvis) int i; sh_shadowframe++; + if (!lvis) + return; + //variation on mark leaves - for (i=0 ; inumvisleafs ; i++) + for (i=0 ; inumclusters ; i++) { if (lvis[i>>3] & (1<<(i&7))) { @@ -1395,9 +1398,9 @@ static struct shadowmesh_s *SHM_BuildShadowMesh(dlight_t *dl, unsigned char *lvi if (!lvis) { - int leaf; - leaf = cl.worldmodel->funcs.LeafnumForPoint(cl.worldmodel, dl->origin); - lvis = cl.worldmodel->funcs.LeafPVS(cl.worldmodel, leaf, lvisb, sizeof(lvisb)); + int clus; + clus = cl.worldmodel->funcs.ClusterForPoint(cl.worldmodel, dl->origin); + lvis = cl.worldmodel->funcs.ClusterPVS(cl.worldmodel, clus, lvisb, sizeof(lvisb)); } firstedge=0; @@ -1512,9 +1515,9 @@ static struct shadowmesh_s *SHM_BuildShadowMesh(dlight_t *dl, unsigned char *lvi static qboolean Sh_VisOverlaps(qbyte *v1, qbyte *v2) { int i, m; - if (!v2) + if (!v2 || !v1) return false; - m = (cl.worldmodel->numvisleafs+7)>>3; + m = (cl.worldmodel->numclusters+7)>>3; for (i=(m&~3) ; ifuncs.LeafnumForPoint(cl.worldmodel, l->origin); - lvis = cl.worldmodel->funcs.LeafPVS(cl.worldmodel, leaf, lvisb, sizeof(lvisb)); + int clus; + clus = cl.worldmodel->funcs.ClusterForPoint(cl.worldmodel, l->origin); + lvis = cl.worldmodel->funcs.ClusterPVS(cl.worldmodel, clus, lvisb, sizeof(lvisb)); + //FIXME: surely we can use the phs for this? + if (!Sh_VisOverlaps(lvis, vvis)) //The two viewing areas do not intersect. { RQuantAdd(RQUANT_RTLIGHT_CULL_PVS, 1); @@ -2816,7 +2821,7 @@ static void Sh_DrawStencilLightShadows(dlight_t *dl, qbyte *lvis, qbyte *vvis, q static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis) { int sref; - int leaf; + int clus; qbyte *lvis; srect_t rect; @@ -2849,8 +2854,8 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis) } else { - leaf = cl.worldmodel->funcs.LeafnumForPoint(cl.worldmodel, dl->origin); - lvis = cl.worldmodel->funcs.LeafPVS(cl.worldmodel, leaf, lvisb, sizeof(lvisb)); + clus = cl.worldmodel->funcs.ClusterForPoint(cl.worldmodel, dl->origin); + lvis = cl.worldmodel->funcs.ClusterPVS(cl.worldmodel, clus, lvisb, sizeof(lvisb)); if (!Sh_VisOverlaps(lvis, vvis)) //The two viewing areas do not intersect. { @@ -3073,11 +3078,11 @@ static void Sh_DrawShadowlessLight(dlight_t *dl, vec3_t colour, qbyte *vvis) } else { - int leaf; + int clus; qbyte *lvis; - leaf = cl.worldmodel->funcs.LeafnumForPoint(cl.worldmodel, dl->origin); - lvis = cl.worldmodel->funcs.LeafPVS(cl.worldmodel, leaf, lvisb, sizeof(lvisb)); + clus = cl.worldmodel->funcs.ClusterForPoint(cl.worldmodel, dl->origin); + lvis = cl.worldmodel->funcs.ClusterPVS(cl.worldmodel, clus, lvisb, sizeof(lvisb)); SHM_BuildShadowMesh(dl, lvis, vvis, SMT_SHADOWLESS); @@ -3255,8 +3260,8 @@ void Sh_PreGenerateLights(void) else shadowtype = SMT_STENCILVOLUME; - leaf = cl.worldmodel->funcs.LeafnumForPoint(cl.worldmodel, dl->origin); - lvis = cl.worldmodel->funcs.LeafPVS(cl.worldmodel, leaf, lvisb, sizeof(lvisb)); + leaf = cl.worldmodel->funcs.ClusterForPoint(cl.worldmodel, dl->origin); + lvis = cl.worldmodel->funcs.ClusterPVS(cl.worldmodel, leaf, lvisb, sizeof(lvisb)); SHM_BuildShadowMesh(dl, lvis, NULL, shadowtype); continue; diff --git a/engine/server/net_preparse.c b/engine/server/net_preparse.c index 67d606e2..461a2ec2 100644 --- a/engine/server/net_preparse.c +++ b/engine/server/net_preparse.c @@ -79,26 +79,32 @@ static void pp_flush(multicast_t to, vec3_t origin, void (*flushfunc)(client_t * case MULTICAST_ALL_R: reliable = true; // intentional fallthrough case MULTICAST_ALL: - mask = sv.pvs; // leaf 0 is everything; + mask = NULL; break; case MULTICAST_PHS_R: reliable = true; // intentional fallthrough case MULTICAST_PHS: if (!sv.phs) - mask = sv.pvs; + mask = NULL; else { - leafnum = sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, origin); - mask = sv.phs + leafnum * 4*((sv.world.worldmodel->numvisleafs+31)>>5); + cluster = sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, origin); + if (cluster >= 0) + mask = sv.phs + cluster * 4*((sv.world.worldmodel->numclusters+31)>>5); + else + mask = NULL; } break; case MULTICAST_PVS_R: reliable = true; // intentional fallthrough case MULTICAST_PVS: - leafnum = sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, origin); - mask = sv.pvs + leafnum * 4*((sv.world.worldmodel->numvisleafs+31)>>5); + cluster = sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, origin); + if (cluster >= 0) + mask = sv.pvs + cluster * 4*((sv.world.worldmodel->numclusters+31)>>5); + else + mask = NULL; break; default: @@ -125,11 +131,10 @@ static void pp_flush(multicast_t to, vec3_t origin, void (*flushfunc)(client_t * goto inrange; } - // -1 is because pvs rows are 1 based, not 0 based like leafs - if (mask != sv.pvs) + if (mask) { - leafnum = sv.world.worldmodel->funcs.LeafnumForPoint (sv.world.worldmodel, client->edict->v->origin)-1; - if ( !(mask[leafnum>>3] & (1<<(leafnum&7)) ) ) + cluster = sv.world.worldmodel->funcs.ClusterForPoint (sv.world.worldmodel, client->edict->v->origin); + if (cluster >= 0 && !(mask[leafnum>>3] & (1<<(leafnum&7)) ) ) { continue; } diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 3c67c319..ee47e806 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -3250,13 +3250,14 @@ static void QCBUILTIN PF_TraceToss (pubprogfuncs_t *prinst, struct globalvars_s qbyte checkpvsbuffer[MAX_MAP_LEAFS/8]; qbyte *checkpvs; vec3_t checkorg; +extern cvar_t sv_nopvs; int PF_newcheckclient (pubprogfuncs_t *prinst, int check) { int i; // qbyte *pvs; edict_t *ent; - int leaf; + int cluster; // cycle to the next one @@ -3272,7 +3273,7 @@ int PF_newcheckclient (pubprogfuncs_t *prinst, int check) for ( ; ; i++) { - if (i == sv.allocated_client_slots+1) + if (i >= sv.allocated_client_slots+1) i = 1; ent = EDICT_NUM(prinst, i); @@ -3293,12 +3294,12 @@ int PF_newcheckclient (pubprogfuncs_t *prinst, int check) // get the PVS for the entity VectorAdd (ent->v->origin, ent->v->view_ofs, checkorg); - if (sv.world.worldmodel->type == mod_heightmap) + if (sv.world.worldmodel->type == mod_heightmap || sv_nopvs.ival) checkpvs = NULL; else { - leaf = sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, checkorg); - checkpvs = sv.world.worldmodel->funcs.LeafPVS (sv.world.worldmodel, leaf, checkpvsbuffer, sizeof(checkpvsbuffer)); + cluster = sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, checkorg); + checkpvs = sv.world.worldmodel->funcs.ClusterPVS (sv.world.worldmodel, cluster, checkpvsbuffer, sizeof(checkpvsbuffer)); } return i; @@ -3324,7 +3325,7 @@ int c_invis, c_notvis; int PF_checkclient_Internal (pubprogfuncs_t *prinst) { edict_t *ent, *self; - int l; + int clust; vec3_t view; vec3_t dist; world_t *w = &sv.world; @@ -3353,8 +3354,8 @@ int PF_checkclient_Internal (pubprogfuncs_t *prinst) if (checkpvs) { - l = w->worldmodel->funcs.LeafnumForPoint(w->worldmodel, view)-1; - if ( (l<0) || !(checkpvs[l>>3] & (1<<(l&7)) ) ) + clust = w->worldmodel->funcs.ClusterForPoint(w->worldmodel, view); + if ( (clust<0) || !(checkpvs[clust>>3] & (1<<(clust&7)) ) ) { c_notvis++; return 0; diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index ad79dc00..a5c4fc70 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -2733,7 +2733,7 @@ unsigned int Q2BSP_FatPVS(model_t *mod, vec3_t org, qbyte *buffer, unsigned int {//fixme: this doesn't add int leafnum; leafnum = CM_PointLeafnum (mod, org); - clientarea = CM_LeafArea (mod, leafnum); +/// clientarea = CM_LeafArea (mod, leafnum); return SV_Q2BSP_FatPVS (mod, org, buffer, buffersize, add); } @@ -3216,17 +3216,24 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, pvscamera_t } else if ((pvsflags & PVSF_MODE_MASK) == PVSF_USEPHS && sv.world.worldmodel->fromgame == fg_quake) { - int leafnum; + int cluster; unsigned char *mask; if (sv.phs) { - leafnum = sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, host_client->edict->v->origin); - mask = sv.phs + leafnum * 4*((sv.world.worldmodel->numvisleafs+31)>>5); - - leafnum = sv.world.worldmodel->funcs.LeafnumForPoint (sv.world.worldmodel, ent->v->origin)-1; - if ( !(mask[leafnum>>3] & (1<<(leafnum&7)) ) ) + //FIXME: this lookup should be cachable or something. + if (client->edict) + cluster = sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, client->edict->v->origin); + else + cluster = -1; //mvd + if (cluster >= 0) { - continue; + mask = sv.phs + cluster * 4*((sv.world.worldmodel->numclusters+31)>>5); + + cluster = sv.world.worldmodel->funcs.ClusterForPoint (sv.world.worldmodel, ent->v->origin); + if (cluster >= 0 && !(mask[cluster>>3] & (1<<(cluster&7)) ) ) + { + continue; + } } } tracecullent = NULL; @@ -3243,11 +3250,11 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, pvscamera_t //DP_SV_NODRAWONLYTOCLIENT if (ent->xv->nodrawtoclient) //DP extension. - if (ent->xv->nodrawtoclient == EDICT_TO_PROG(svprogfuncs, client->edict)) + if (client->edict && ent->xv->nodrawtoclient == EDICT_TO_PROG(svprogfuncs, client->edict)) continue; //DP_SV_DRAWONLYTOCLIENT if (ent->xv->drawonlytoclient) - if (ent->xv->drawonlytoclient != EDICT_TO_PROG(svprogfuncs, client->edict)) + if (!client->edict || ent->xv->drawonlytoclient != EDICT_TO_PROG(svprogfuncs, client->edict)) { client_t *split; for (split = client->controlled; split; split=split->controlled) diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index 6844caaf..55d00ba0 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -407,7 +407,7 @@ void SV_CalcPHS (void) return; } - num = sv.world.worldmodel->numleafs; + num = sv.world.worldmodel->numclusters; rowwords = (num+31)>>5; rowbytes = rowwords*4; @@ -417,7 +417,7 @@ void SV_CalcPHS (void) scan = sv.pvs; for (i=0 ; ifuncs.LeafPVS(sv.world.worldmodel, i, scan, rowbytes); + lf = sv.world.worldmodel->funcs.ClusterPVS(sv.world.worldmodel, i, scan, rowbytes); if (lf != scan) memcpy (scan, lf, rowbytes); } @@ -432,7 +432,7 @@ void SV_CalcPHS (void) vcount = 0; for (i=0 ; ifuncs.LeafPVS(sv.world.worldmodel, i, scan, rowbytes); + lf = sv.world.worldmodel->funcs.ClusterPVS(sv.world.worldmodel, i, scan, rowbytes); if (lf != scan) memcpy (scan, lf, rowbytes); if (i == 0) @@ -488,7 +488,8 @@ void SV_CalcPHS (void) continue; // or this pvs row into the phs // +1 because pvs is 1 based - index = ((j<<3)+k+1); + //except we now use clusters internally, which are 0-based (ie: leaf 0 is invalid and maps to cluster -1) + index = ((j<<3)+k); if (index >= num) continue; src = (unsigned *)sv.pvs + index*rowwords; diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 23ed47a1..729dcf31 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -545,10 +545,10 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int { client_t *client; qbyte *mask; - int leafnum; + int cluster; int j; qboolean reliable; - int pnum = 0; + int pnum = -1; if (to == MULTICAST_INIT) { @@ -580,7 +580,7 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int #ifdef Q2BSPS if (sv.world.worldmodel->fromgame == fg_quake2 || sv.world.worldmodel->fromgame == fg_quake3) { - int area1, area2, cluster; + int area1, area2, leafnum; reliable = false; @@ -656,12 +656,12 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int } } - if (!mask) + if (pnum >= 0) { if (pnum != j) continue; } - else + else if (mask) { #ifdef Q2SERVER if (ge) @@ -743,26 +743,32 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int case MULTICAST_ALL_R: reliable = true; // intentional fallthrough case MULTICAST_ALL: - mask = sv.pvs; // leaf 0 is everything; + mask = NULL; break; case MULTICAST_PHS_R: reliable = true; // intentional fallthrough case MULTICAST_PHS: if (!sv.phs) /*broadcast if no pvs*/ - mask = sv.pvs; + mask = NULL; else { - leafnum = sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, origin); - mask = sv.phs + leafnum * 4*((sv.world.worldmodel->numleafs+31)>>5); + cluster = sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, origin); + if (cluster >= 0) + mask = sv.phs + cluster * 4*((sv.world.worldmodel->numclusters+31)>>5); + else + mask = NULL; } break; case MULTICAST_PVS_R: reliable = true; // intentional fallthrough case MULTICAST_PVS: - leafnum = sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, origin); - mask = sv.pvs + leafnum * 4*((sv.world.worldmodel->numleafs+31)>>5); + cluster = sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, origin); + if (cluster >= 0) + mask = sv.pvs + cluster * 4*((sv.world.worldmodel->numclusters+31)>>5); + else + mask = NULL; break; case MULTICAST_ONE_R: @@ -804,7 +810,7 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int } } - if (!mask) + if (pnum >= 0) { if (pnum != j) continue; @@ -814,6 +820,9 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int if (!((int)client->edict->xv->dimension_see & dimension_mask)) continue; + if (!mask) //no pvs? broadcast. + goto inrange; + if (to == MULTICAST_PHS_R || to == MULTICAST_PHS) { vec3_t delta; @@ -822,13 +831,11 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int goto inrange; } - if (mask != sv.pvs) //leaf 0 is the solid see-all region, so no point figuring out where the players are { vec3_t pos; VectorAdd(client->edict->v->origin, client->edict->v->view_ofs, pos); - // -1 is because pvs rows are 1 based, not 0 based like leafs - leafnum = sv.world.worldmodel->funcs.LeafnumForPoint (sv.world.worldmodel, pos)-1; - if ( !(mask[leafnum>>3] & (1<<(leafnum&7)) ) ) + cluster = sv.world.worldmodel->funcs.ClusterForPoint (sv.world.worldmodel, pos); + if (cluster>= 0 && !(mask[cluster>>3] & (1<<(cluster&7)) ) ) { // Con_Printf ("PVS supressed multicast\n"); continue; diff --git a/engine/server/svq3_game.c b/engine/server/svq3_game.c index 5967b0f3..c4dfc873 100644 --- a/engine/server/svq3_game.c +++ b/engine/server/svq3_game.c @@ -2317,7 +2317,7 @@ void SVQ3_BuildClientSnapshot( client_t *client ) org[2] += ps->viewheight; clientarea = CM_PointLeafnum(sv.world.worldmodel, org); - bitvector = sv.world.worldmodel->funcs.LeafPVS(sv.world.worldmodel, sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, org), NULL, 0); + bitvector = sv.world.worldmodel->funcs.ClusterPVS(sv.world.worldmodel, sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, org), NULL, 0); clientarea = CM_LeafArea(sv.world.worldmodel, clientarea); /* if (client->areanum != clientarea)