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
This commit is contained in:
Spoike 2014-05-23 02:02:51 +00:00
parent faae661e9e
commit 3bd6892353
17 changed files with 224 additions and 131 deletions

View File

@ -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_Resize(cin_t *cin, int x, int y);
void Media_Send_GetSize(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_KeyEvent(cin_t *cin, int button, int unicode, int event);
void Media_Send_Reset(cin_t *cin);
void MVD_Interpolate(void); void MVD_Interpolate(void);

View File

@ -2705,6 +2705,11 @@ void Media_Send_GetSize(cin_t *cin, int *x, int *y)
return; return;
cin->getsize(cin, x, y); cin->getsize(cin, x, y);
} }
void Media_Send_Reset(cin_t *cin)
{
if (!cin || !cin->rewind)
cin->rewind(cin);
}

View File

@ -358,42 +358,54 @@ void QCBUILTIN PF_cl_runningserver (pubprogfuncs_t *prinst, struct globalvars_s
#ifndef NOMEDIA #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) void QCBUILTIN PF_cs_gecko_create (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
const char *shadername = PR_GetStringOfs(prinst, OFS_PARM0); const char *shadername = PR_GetStringOfs(prinst, OFS_PARM0);
cin_t *cin; cin_t *cin;
cin = R_ShaderGetCinematic(R_RegisterShader(shadername, SUF_2D, cin = R_ShaderGetCinematic(R_RegisterShader(shadername, SUF_2D,
"{\n" "{\n"
"program default2d\n"
"{\n" "{\n"
"videomap http:\n" "videomap http:\n"
"rgbgen vertex\n"
"alphagen vertex\n"
"blendfunc blend\n"
"nodepth\n"
"}\n" "}\n"
"}\n" "}\n"
)); ));
if (!cin) if (cin)
G_FLOAT(OFS_RETURN) = 0; {
else
G_FLOAT(OFS_RETURN) = 1; 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) 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) void QCBUILTIN PF_cs_gecko_navigate (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
const char *shader = PR_GetStringOfs(prinst, OFS_PARM0); const char *shader = PR_GetStringOfs(prinst, OFS_PARM0);
const char *command = PR_GetStringOfs(prinst, OFS_PARM1); const char *command = PR_GetStringOfs(prinst, OFS_PARM1);
cin_t *cin; cin_t *cin;
cin = R_ShaderFindCinematic(shader); cin = R_ShaderFindCinematic(shader);
if (!cin) if (!cin)
return; return;
Media_Send_Command(cin, command); 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) void QCBUILTIN PF_cs_gecko_keyevent (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
const char *shader = PR_GetStringOfs(prinst, OFS_PARM0); 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); int eventtype = G_FLOAT(OFS_PARM2);
cin_t *cin; cin_t *cin;
cin = R_ShaderFindCinematic(shader); cin = R_ShaderFindCinematic(shader);
if (!cin) if (!cin)
return; return;
Media_Send_KeyEvent(cin, MP_TranslateQCtoFTECodes(key), (key>127)?0:key, eventtype); 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) void QCBUILTIN PF_cs_gecko_mousemove (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
const char *shader = PR_GetStringOfs(prinst, OFS_PARM0); 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); float posy = G_FLOAT(OFS_PARM2);
cin_t *cin; cin_t *cin;
cin = R_ShaderFindCinematic(shader); cin = R_ShaderFindCinematic(shader);
if (!cin) if (!cin)
return; return;
Media_Send_MouseMove(cin, posx, posy); 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) void QCBUILTIN PF_cs_gecko_resize (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
const char *shader = PR_GetStringOfs(prinst, OFS_PARM0); 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; return;
Media_Send_Resize(cin, sizex, sizey); 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) void QCBUILTIN PF_cs_gecko_get_texture_extent (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
const char *shader = PR_GetStringOfs(prinst, OFS_PARM0); const char *shader = PR_GetStringOfs(prinst, OFS_PARM0);

View File

@ -2030,7 +2030,7 @@ qbyte *R_CalcVis_Q1 (void)
int c; int c;
Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf2, curframevis, sizeof(curframevis)); Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf2, curframevis, sizeof(curframevis));
vis = Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf, NULL, 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 ; i<c ; i++) for (i=0 ; i<c ; i++)
((int *)curframevis)[i] |= ((int *)vis)[i]; ((int *)curframevis)[i] |= ((int *)vis)[i];
vis = curframevis; vis = curframevis;
@ -2080,7 +2080,7 @@ qbyte *R_MarkLeaves_Q1 (void)
if (r_novis.ival) if (r_novis.ival)
{ {
vis = cvis[portal] = fatvis[portal]; vis = cvis[portal] = fatvis[portal];
memset (fatvis[portal], 0xff, (cl.worldmodel->numvisleafs+7)>>3); memset (fatvis[portal], 0xff, (cl.worldmodel->numclusters+7)>>3);
r_oldviewleaf = NULL; r_oldviewleaf = NULL;
r_oldviewleaf2 = NULL; r_oldviewleaf2 = NULL;
@ -2090,7 +2090,7 @@ qbyte *R_MarkLeaves_Q1 (void)
int c; int c;
Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf2, fatvis[portal], sizeof(fatvis[portal])); Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf2, fatvis[portal], sizeof(fatvis[portal]));
vis = cvis[portal] = Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf, NULL, 0); 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 ; i<c ; i++) for (i=0 ; i<c ; i++)
((int *)fatvis[portal])[i] |= ((int *)vis)[i]; ((int *)fatvis[portal])[i] |= ((int *)vis)[i];
@ -2104,7 +2104,7 @@ qbyte *R_MarkLeaves_Q1 (void)
r_visframecount++; r_visframecount++;
for (i=0 ; i<cl.worldmodel->numvisleafs ; i++) for (i=0 ; i<cl.worldmodel->numclusters ; i++)
{ {
if (vis[i>>3] & (1<<(i&7))) if (vis[i>>3] & (1<<(i&7)))
{ {

View File

@ -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 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 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 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; extern mplane_t *box_planes;
@ -3739,10 +3740,12 @@ void CMQ3_CalcPHS (void)
} }
#endif #endif
/*
static qbyte *CM_LeafnumPVS (model_t *model, int leafnum, qbyte *buffer, unsigned int buffersize) static qbyte *CM_LeafnumPVS (model_t *model, int leafnum, qbyte *buffer, unsigned int buffersize)
{ {
return CM_ClusterPVS(model, CM_LeafCluster(model, leafnum), buffer, buffersize); return CM_ClusterPVS(model, CM_LeafCluster(model, leafnum), buffer, buffersize);
} }
*/
#ifndef SERVERONLY #ifndef SERVERONLY
#define GLQ2BSP_LightPointValues GLQ1BSP_LightPointValues #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.EdictInFatPVS = Q2BSP_EdictInFatPVS;
loadmodel->funcs.FindTouchedLeafs = Q2BSP_FindTouchedLeafs; loadmodel->funcs.FindTouchedLeafs = Q2BSP_FindTouchedLeafs;
#endif #endif
loadmodel->funcs.LeafPVS = CM_LeafnumPVS; loadmodel->funcs.ClusterPVS = CM_ClusterPVS;
loadmodel->funcs.LeafnumForPoint = CM_PointLeafnum; loadmodel->funcs.ClusterForPoint = CM_PointCluster;
#ifndef SERVERONLY #ifndef SERVERONLY
loadmodel->funcs.LightPointValues = GLQ3_LightGrid; 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.LightPointValues = NULL;
loadmodel->funcs.StainNode = NULL; loadmodel->funcs.StainNode = NULL;
loadmodel->funcs.MarkLights = NULL; loadmodel->funcs.MarkLights = NULL;
loadmodel->funcs.LeafPVS = CM_LeafnumPVS; loadmodel->funcs.ClusterPVS = CM_ClusterPVS;
loadmodel->funcs.LeafnumForPoint = CM_PointLeafnum; loadmodel->funcs.ClusterForPoint = CM_PointCluster;
loadmodel->funcs.PointContents = Q2BSP_PointContents; loadmodel->funcs.PointContents = Q2BSP_PointContents;
loadmodel->funcs.NativeTrace = CM_NativeTrace; loadmodel->funcs.NativeTrace = CM_NativeTrace;
loadmodel->funcs.NativeContents = CM_NativeContents; 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.LightPointValues = GLQ2BSP_LightPointValues;
loadmodel->funcs.StainNode = GLR_Q2BSP_StainNode; loadmodel->funcs.StainNode = GLR_Q2BSP_StainNode;
loadmodel->funcs.MarkLights = Q2BSP_MarkLights; loadmodel->funcs.MarkLights = Q2BSP_MarkLights;
loadmodel->funcs.LeafPVS = CM_LeafnumPVS; loadmodel->funcs.ClusterPVS = CM_ClusterPVS;
loadmodel->funcs.LeafnumForPoint = CM_PointLeafnum; loadmodel->funcs.ClusterForPoint = CM_PointCluster;
loadmodel->funcs.PointContents = Q2BSP_PointContents; loadmodel->funcs.PointContents = Q2BSP_PointContents;
loadmodel->funcs.NativeTrace = CM_NativeTrace; loadmodel->funcs.NativeTrace = CM_NativeTrace;
loadmodel->funcs.NativeContents = CM_NativeContents; loadmodel->funcs.NativeContents = CM_NativeContents;
@ -4416,8 +4419,8 @@ void CM_InitBoxHull (void)
#ifndef SERVERONLY #ifndef SERVERONLY
box_model.funcs.MarkLights = Q2BSP_MarkLights; box_model.funcs.MarkLights = Q2BSP_MarkLights;
#endif #endif
box_model.funcs.LeafPVS = CM_LeafnumPVS; box_model.funcs.ClusterPVS = CM_ClusterPVS;
box_model.funcs.LeafnumForPoint = CM_PointLeafnum; box_model.funcs.ClusterForPoint = CM_PointCluster;
box_model.funcs.NativeContents = CM_NativeContents; box_model.funcs.NativeContents = CM_NativeContents;
box_model.funcs.NativeTrace = CM_NativeTrace; 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; float d;
mnode_t *node; mnode_t *node;
@ -4547,6 +4550,13 @@ int CM_PointLeafnum (model_t *mod, vec3_t p)
return CM_PointLeafnum_r (mod, p, 0); 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 CM_BoxLeafnums

View File

@ -1519,7 +1519,7 @@ Server only functions
#ifndef CLIENTONLY #ifndef CLIENTONLY
//does the recursive work of Q1BSP_FatPVS //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; int i;
qbyte *pvs; qbyte *pvs;
@ -1562,7 +1562,7 @@ Calculates a PVS that is the inclusive or of all leafs within 8 pixels of the
given point. 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; unsigned int fatbytes = (mod->numleafs+31)>>3;
if (fatbytes > buffersize) if (fatbytes > buffersize)
@ -1574,7 +1574,7 @@ unsigned int Q1BSP_FatPVS (model_t *mod, vec3_t org, qbyte *pvsbuffer, unsigned
} }
#endif #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; int i;
@ -1595,7 +1595,7 @@ SV_FindTouchedLeafs
Links the edict to the right leafs so we can get it's potential visability. 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; mplane_t *splitplane;
mleaf_t *leaf; mleaf_t *leaf;
@ -1635,7 +1635,7 @@ void Q1BSP_RFindTouchedLeafs (model_t *wm, struct pvscache_s *ent, mnode_t *node
if (sides & 2) if (sides & 2)
Q1BSP_RFindTouchedLeafs (wm, ent, node->children[1], mins, maxs); 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; ent->num_leafs = 0;
if (mins && maxs) if (mins && maxs)
@ -1656,13 +1656,13 @@ PVS type stuff
Mod_DecompressVis 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; int c;
qbyte *out; qbyte *out;
int row; int row;
row = (model->numvisleafs+7)>>3; row = (model->numclusters+7)>>3;
out = decompressed; out = decompressed;
if (buffersize < row) 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); 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. //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; mnode_t *node;
float d; float d;
@ -1760,6 +1773,36 @@ mleaf_t *Q1BSP_LeafForPoint (model_t *model, vec3_t p)
return model->leafs + Q1BSP_LeafnumForPoint(model, 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.StainNode = NULL;
mod->funcs.MarkLights = NULL; mod->funcs.MarkLights = NULL;
mod->funcs.LeafnumForPoint = Q1BSP_LeafnumForPoint; mod->funcs.ClusterForPoint = Q1BSP_ClusterForPoint;
mod->funcs.LeafPVS = Q1BSP_LeafnumPVS; mod->funcs.ClusterPVS = Q1BSP_ClusterPVS;
mod->funcs.NativeTrace = Q1BSP_Trace; mod->funcs.NativeTrace = Q1BSP_Trace;
mod->funcs.PointContents = Q1BSP_PointContents; mod->funcs.PointContents = Q1BSP_PointContents;
} }

View File

@ -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 NULL;
return &heightmappvs; // 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 #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.StainNode = Heightmap_StainNode;
mod->funcs.MarkLights = Heightmap_MarkLights; mod->funcs.MarkLights = Heightmap_MarkLights;
mod->funcs.LeafnumForPoint = Heightmap_LeafForPoint; mod->funcs.ClusterForPoint = Heightmap_ClusterForPoint;
mod->funcs.LeafPVS = Heightmap_LeafnumPVS; mod->funcs.ClusterPVS = Heightmap_ClusterPVS;
#ifndef CLIENTONLY #ifndef CLIENTONLY
mod->funcs.FindTouchedLeafs = Heightmap_FindTouchedLeafs; mod->funcs.FindTouchedLeafs = Heightmap_FindTouchedLeafs;

View File

@ -3337,7 +3337,7 @@ qboolean Mod_LoadLeafs (lump_t *l, int lm)
loadmodel->leafs = out; loadmodel->leafs = out;
loadmodel->numleafs = count; loadmodel->numleafs = count;
loadmodel->numvisleafs = count-1; loadmodel->numclusters = count-1;
for ( i=0 ; i<count ; i++, in++, out++) for ( i=0 ; i<count ; i++, in++, out++)
{ {
@ -3400,7 +3400,7 @@ qboolean Mod_LoadLeafs (lump_t *l, int lm)
loadmodel->leafs = out; loadmodel->leafs = out;
loadmodel->numleafs = count; loadmodel->numleafs = count;
loadmodel->numvisleafs = count-1; loadmodel->numclusters = count-1;
for ( i=0 ; i<count ; i++, in++, out++) for ( i=0 ; i<count ; i++, in++, out++)
{ {
@ -3463,7 +3463,7 @@ qboolean Mod_LoadLeafs (lump_t *l, int lm)
loadmodel->leafs = out; loadmodel->leafs = out;
loadmodel->numleafs = count; loadmodel->numleafs = count;
loadmodel->numvisleafs = count-1; loadmodel->numclusters = count-1;
for ( i=0 ; i<count ; i++, in++, out++) for ( i=0 ; i<count ; i++, in++, out++)
{ {
@ -4424,7 +4424,7 @@ TRACE(("LoadBrushModel %i\n", __LINE__));
mod->radius = RadiusFromBounds (mod->mins, mod->maxs); mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
mod->numvisleafs = bm->visleafs; mod->numclusters = bm->visleafs;
memset(&mod->batches, 0, sizeof(mod->batches)); memset(&mod->batches, 0, sizeof(mod->batches));
mod->vbos = NULL; mod->vbos = NULL;

View File

@ -216,8 +216,8 @@ typedef struct {
void (*StainNode) (struct mnode_s *node, float *parms); void (*StainNode) (struct mnode_s *node, float *parms);
void (*MarkLights) (struct dlight_s *light, int bit, struct mnode_s *node); 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 (*ClusterForPoint) (struct model_s *model, vec3_t point); //pvs index. may be negative (ie: no pvs).
int (*LeafnumForPoint) (struct model_s *model, vec3_t point); qbyte *(*ClusterPVS) (struct model_s *model, int cluster, qbyte *buffer, unsigned int buffersize);
} modelfuncs_t; } 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); 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_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); 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); 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; int numplanes;
mplane_t *planes; mplane_t *planes;
int numvisleafs; int numclusters;
int numleafs; // number of visible leafs, not counting 0 int numleafs; // number of visible leafs, not counting 0
mleaf_t *leafs; mleaf_t *leafs;

View File

@ -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*/ //use the player's origin for r_viewleaf, because there's not much we can do anyway*/
VectorCopy(r_origin, r_refdef.pvsorigin); 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; float d;
vec3_t point; vec3_t point;
int pvsbytes = (cl.worldmodel->numvisleafs+7)>>3; int pvsbytes = (cl.worldmodel->numclusters+7)>>3;
if (pvsbytes > sizeof(newvis)) if (pvsbytes > sizeof(newvis))
pvsbytes = sizeof(newvis); pvsbytes = sizeof(newvis);
r_refdef.forcevis = true; 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 d += 0.1; //an epsilon on the far side
VectorMA(point, d, plane.normal, point); 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) 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 else
{ {
if (r_refdef.forcedvis != newvis) if (r_refdef.forcedvis != newvis)
{ {
memcpy(newvis, r_refdef.forcedvis, pvsbytes); 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) for (j = 0; j < pvsbytes; j+= 4)
{ {

View File

@ -449,7 +449,7 @@ static void SHM_BeginShadowMesh(dlight_t *dl, int type)
unsigned int lb; unsigned int lb;
sh_vertnum = 0; sh_vertnum = 0;
lb = (cl.worldmodel->numvisleafs+7)/8; lb = (cl.worldmodel->numclusters+7)/8;
if (!dl->die || !dl->key) if (!dl->die || !dl->key)
{ {
sh_shmesh = dl->worldshadowmesh; sh_shmesh = dl->worldshadowmesh;
@ -978,7 +978,7 @@ static void SHM_MarkLeavesQ2(dlight_t *dl, unsigned char *lvis, unsigned char *v
{ {
//static //static
//variation on mark leaves //variation on mark leaves
for (i=0,leaf=cl.worldmodel->leafs ; i<cl.worldmodel->numvisleafs ; i++, leaf++) for (i=0,leaf=cl.worldmodel->leafs ; i<cl.worldmodel->numleafs ; i++, leaf++)
{ {
cluster = leaf->cluster; cluster = leaf->cluster;
if (cluster == -1) 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 //dynamic lights will be discarded after this frame anyway, so only include leafs that are visible
//variation on mark leaves //variation on mark leaves
for (i=0,leaf=cl.worldmodel->leafs ; i<cl.worldmodel->numvisleafs ; i++, leaf++) for (i=0,leaf=cl.worldmodel->leafs ; i<cl.worldmodel->numleafs ; i++, leaf++)
{ {
cluster = leaf->cluster; cluster = leaf->cluster;
if (cluster == -1) if (cluster == -1)
@ -1027,8 +1027,11 @@ static void SHM_MarkLeavesQ1(dlight_t *dl, unsigned char *lvis)
int i; int i;
sh_shadowframe++; sh_shadowframe++;
if (!lvis)
return;
//variation on mark leaves //variation on mark leaves
for (i=0 ; i<cl.worldmodel->numvisleafs ; i++) for (i=0 ; i<cl.worldmodel->numclusters ; i++)
{ {
if (lvis[i>>3] & (1<<(i&7))) 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) if (!lvis)
{ {
int leaf; int clus;
leaf = cl.worldmodel->funcs.LeafnumForPoint(cl.worldmodel, dl->origin); clus = cl.worldmodel->funcs.ClusterForPoint(cl.worldmodel, dl->origin);
lvis = cl.worldmodel->funcs.LeafPVS(cl.worldmodel, leaf, lvisb, sizeof(lvisb)); lvis = cl.worldmodel->funcs.ClusterPVS(cl.worldmodel, clus, lvisb, sizeof(lvisb));
} }
firstedge=0; 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) static qboolean Sh_VisOverlaps(qbyte *v1, qbyte *v2)
{ {
int i, m; int i, m;
if (!v2) if (!v2 || !v1)
return false; return false;
m = (cl.worldmodel->numvisleafs+7)>>3; m = (cl.worldmodel->numclusters+7)>>3;
for (i=(m&~3) ; i<m ; i++) for (i=(m&~3) ; i<m ; i++)
{ {
@ -2502,9 +2505,11 @@ static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis)
} }
else else
{ {
int leaf; int clus;
leaf = cl.worldmodel->funcs.LeafnumForPoint(cl.worldmodel, l->origin); clus = cl.worldmodel->funcs.ClusterForPoint(cl.worldmodel, l->origin);
lvis = cl.worldmodel->funcs.LeafPVS(cl.worldmodel, leaf, lvisb, sizeof(lvisb)); 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. if (!Sh_VisOverlaps(lvis, vvis)) //The two viewing areas do not intersect.
{ {
RQuantAdd(RQUANT_RTLIGHT_CULL_PVS, 1); 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) static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis)
{ {
int sref; int sref;
int leaf; int clus;
qbyte *lvis; qbyte *lvis;
srect_t rect; srect_t rect;
@ -2849,8 +2854,8 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis)
} }
else else
{ {
leaf = cl.worldmodel->funcs.LeafnumForPoint(cl.worldmodel, dl->origin); clus = cl.worldmodel->funcs.ClusterForPoint(cl.worldmodel, dl->origin);
lvis = cl.worldmodel->funcs.LeafPVS(cl.worldmodel, leaf, lvisb, sizeof(lvisb)); lvis = cl.worldmodel->funcs.ClusterPVS(cl.worldmodel, clus, lvisb, sizeof(lvisb));
if (!Sh_VisOverlaps(lvis, vvis)) //The two viewing areas do not intersect. 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 else
{ {
int leaf; int clus;
qbyte *lvis; qbyte *lvis;
leaf = cl.worldmodel->funcs.LeafnumForPoint(cl.worldmodel, dl->origin); clus = cl.worldmodel->funcs.ClusterForPoint(cl.worldmodel, dl->origin);
lvis = cl.worldmodel->funcs.LeafPVS(cl.worldmodel, leaf, lvisb, sizeof(lvisb)); lvis = cl.worldmodel->funcs.ClusterPVS(cl.worldmodel, clus, lvisb, sizeof(lvisb));
SHM_BuildShadowMesh(dl, lvis, vvis, SMT_SHADOWLESS); SHM_BuildShadowMesh(dl, lvis, vvis, SMT_SHADOWLESS);
@ -3255,8 +3260,8 @@ void Sh_PreGenerateLights(void)
else else
shadowtype = SMT_STENCILVOLUME; shadowtype = SMT_STENCILVOLUME;
leaf = cl.worldmodel->funcs.LeafnumForPoint(cl.worldmodel, dl->origin); leaf = cl.worldmodel->funcs.ClusterForPoint(cl.worldmodel, dl->origin);
lvis = cl.worldmodel->funcs.LeafPVS(cl.worldmodel, leaf, lvisb, sizeof(lvisb)); lvis = cl.worldmodel->funcs.ClusterPVS(cl.worldmodel, leaf, lvisb, sizeof(lvisb));
SHM_BuildShadowMesh(dl, lvis, NULL, shadowtype); SHM_BuildShadowMesh(dl, lvis, NULL, shadowtype);
continue; continue;

View File

@ -79,26 +79,32 @@ static void pp_flush(multicast_t to, vec3_t origin, void (*flushfunc)(client_t *
case MULTICAST_ALL_R: case MULTICAST_ALL_R:
reliable = true; // intentional fallthrough reliable = true; // intentional fallthrough
case MULTICAST_ALL: case MULTICAST_ALL:
mask = sv.pvs; // leaf 0 is everything; mask = NULL;
break; break;
case MULTICAST_PHS_R: case MULTICAST_PHS_R:
reliable = true; // intentional fallthrough reliable = true; // intentional fallthrough
case MULTICAST_PHS: case MULTICAST_PHS:
if (!sv.phs) if (!sv.phs)
mask = sv.pvs; mask = NULL;
else else
{ {
leafnum = sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, origin); cluster = sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, origin);
mask = sv.phs + leafnum * 4*((sv.world.worldmodel->numvisleafs+31)>>5); if (cluster >= 0)
mask = sv.phs + cluster * 4*((sv.world.worldmodel->numclusters+31)>>5);
else
mask = NULL;
} }
break; break;
case MULTICAST_PVS_R: case MULTICAST_PVS_R:
reliable = true; // intentional fallthrough reliable = true; // intentional fallthrough
case MULTICAST_PVS: case MULTICAST_PVS:
leafnum = sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, origin); cluster = sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, origin);
mask = sv.pvs + leafnum * 4*((sv.world.worldmodel->numvisleafs+31)>>5); if (cluster >= 0)
mask = sv.pvs + cluster * 4*((sv.world.worldmodel->numclusters+31)>>5);
else
mask = NULL;
break; break;
default: default:
@ -125,11 +131,10 @@ static void pp_flush(multicast_t to, vec3_t origin, void (*flushfunc)(client_t *
goto inrange; goto inrange;
} }
// -1 is because pvs rows are 1 based, not 0 based like leafs if (mask)
if (mask != sv.pvs)
{ {
leafnum = sv.world.worldmodel->funcs.LeafnumForPoint (sv.world.worldmodel, client->edict->v->origin)-1; cluster = sv.world.worldmodel->funcs.ClusterForPoint (sv.world.worldmodel, client->edict->v->origin);
if ( !(mask[leafnum>>3] & (1<<(leafnum&7)) ) ) if (cluster >= 0 && !(mask[leafnum>>3] & (1<<(leafnum&7)) ) )
{ {
continue; continue;
} }

View File

@ -3250,13 +3250,14 @@ static void QCBUILTIN PF_TraceToss (pubprogfuncs_t *prinst, struct globalvars_s
qbyte checkpvsbuffer[MAX_MAP_LEAFS/8]; qbyte checkpvsbuffer[MAX_MAP_LEAFS/8];
qbyte *checkpvs; qbyte *checkpvs;
vec3_t checkorg; vec3_t checkorg;
extern cvar_t sv_nopvs;
int PF_newcheckclient (pubprogfuncs_t *prinst, int check) int PF_newcheckclient (pubprogfuncs_t *prinst, int check)
{ {
int i; int i;
// qbyte *pvs; // qbyte *pvs;
edict_t *ent; edict_t *ent;
int leaf; int cluster;
// cycle to the next one // cycle to the next one
@ -3272,7 +3273,7 @@ int PF_newcheckclient (pubprogfuncs_t *prinst, int check)
for ( ; ; i++) for ( ; ; i++)
{ {
if (i == sv.allocated_client_slots+1) if (i >= sv.allocated_client_slots+1)
i = 1; i = 1;
ent = EDICT_NUM(prinst, i); ent = EDICT_NUM(prinst, i);
@ -3293,12 +3294,12 @@ int PF_newcheckclient (pubprogfuncs_t *prinst, int check)
// get the PVS for the entity // get the PVS for the entity
VectorAdd (ent->v->origin, ent->v->view_ofs, checkorg); 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; checkpvs = NULL;
else else
{ {
leaf = sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, checkorg); cluster = sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, checkorg);
checkpvs = sv.world.worldmodel->funcs.LeafPVS (sv.world.worldmodel, leaf, checkpvsbuffer, sizeof(checkpvsbuffer)); checkpvs = sv.world.worldmodel->funcs.ClusterPVS (sv.world.worldmodel, cluster, checkpvsbuffer, sizeof(checkpvsbuffer));
} }
return i; return i;
@ -3324,7 +3325,7 @@ int c_invis, c_notvis;
int PF_checkclient_Internal (pubprogfuncs_t *prinst) int PF_checkclient_Internal (pubprogfuncs_t *prinst)
{ {
edict_t *ent, *self; edict_t *ent, *self;
int l; int clust;
vec3_t view; vec3_t view;
vec3_t dist; vec3_t dist;
world_t *w = &sv.world; world_t *w = &sv.world;
@ -3353,8 +3354,8 @@ int PF_checkclient_Internal (pubprogfuncs_t *prinst)
if (checkpvs) if (checkpvs)
{ {
l = w->worldmodel->funcs.LeafnumForPoint(w->worldmodel, view)-1; clust = w->worldmodel->funcs.ClusterForPoint(w->worldmodel, view);
if ( (l<0) || !(checkpvs[l>>3] & (1<<(l&7)) ) ) if ( (clust<0) || !(checkpvs[clust>>3] & (1<<(clust&7)) ) )
{ {
c_notvis++; c_notvis++;
return 0; return 0;

View File

@ -2733,7 +2733,7 @@ unsigned int Q2BSP_FatPVS(model_t *mod, vec3_t org, qbyte *buffer, unsigned int
{//fixme: this doesn't add {//fixme: this doesn't add
int leafnum; int leafnum;
leafnum = CM_PointLeafnum (mod, org); leafnum = CM_PointLeafnum (mod, org);
clientarea = CM_LeafArea (mod, leafnum); /// clientarea = CM_LeafArea (mod, leafnum);
return SV_Q2BSP_FatPVS (mod, org, buffer, buffersize, add); 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) else if ((pvsflags & PVSF_MODE_MASK) == PVSF_USEPHS && sv.world.worldmodel->fromgame == fg_quake)
{ {
int leafnum; int cluster;
unsigned char *mask; unsigned char *mask;
if (sv.phs) if (sv.phs)
{ {
leafnum = sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, host_client->edict->v->origin); //FIXME: this lookup should be cachable or something.
mask = sv.phs + leafnum * 4*((sv.world.worldmodel->numvisleafs+31)>>5); if (client->edict)
cluster = sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, client->edict->v->origin);
leafnum = sv.world.worldmodel->funcs.LeafnumForPoint (sv.world.worldmodel, ent->v->origin)-1; else
if ( !(mask[leafnum>>3] & (1<<(leafnum&7)) ) ) 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; tracecullent = NULL;
@ -3243,11 +3250,11 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, pvscamera_t
//DP_SV_NODRAWONLYTOCLIENT //DP_SV_NODRAWONLYTOCLIENT
if (ent->xv->nodrawtoclient) //DP extension. 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; continue;
//DP_SV_DRAWONLYTOCLIENT //DP_SV_DRAWONLYTOCLIENT
if (ent->xv->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; client_t *split;
for (split = client->controlled; split; split=split->controlled) for (split = client->controlled; split; split=split->controlled)

View File

@ -407,7 +407,7 @@ void SV_CalcPHS (void)
return; return;
} }
num = sv.world.worldmodel->numleafs; num = sv.world.worldmodel->numclusters;
rowwords = (num+31)>>5; rowwords = (num+31)>>5;
rowbytes = rowwords*4; rowbytes = rowwords*4;
@ -417,7 +417,7 @@ void SV_CalcPHS (void)
scan = sv.pvs; scan = sv.pvs;
for (i=0 ; i<num ; i++, scan+=rowbytes) for (i=0 ; i<num ; i++, scan+=rowbytes)
{ {
lf = sv.world.worldmodel->funcs.LeafPVS(sv.world.worldmodel, i, scan, rowbytes); lf = sv.world.worldmodel->funcs.ClusterPVS(sv.world.worldmodel, i, scan, rowbytes);
if (lf != scan) if (lf != scan)
memcpy (scan, lf, rowbytes); memcpy (scan, lf, rowbytes);
} }
@ -432,7 +432,7 @@ void SV_CalcPHS (void)
vcount = 0; vcount = 0;
for (i=0 ; i<num ; i++, scan+=rowbytes) for (i=0 ; i<num ; i++, scan+=rowbytes)
{ {
lf = sv.world.worldmodel->funcs.LeafPVS(sv.world.worldmodel, i, scan, rowbytes); lf = sv.world.worldmodel->funcs.ClusterPVS(sv.world.worldmodel, i, scan, rowbytes);
if (lf != scan) if (lf != scan)
memcpy (scan, lf, rowbytes); memcpy (scan, lf, rowbytes);
if (i == 0) if (i == 0)
@ -488,7 +488,8 @@ void SV_CalcPHS (void)
continue; continue;
// or this pvs row into the phs // or this pvs row into the phs
// +1 because pvs is 1 based // +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) if (index >= num)
continue; continue;
src = (unsigned *)sv.pvs + index*rowwords; src = (unsigned *)sv.pvs + index*rowwords;

View File

@ -545,10 +545,10 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int
{ {
client_t *client; client_t *client;
qbyte *mask; qbyte *mask;
int leafnum; int cluster;
int j; int j;
qboolean reliable; qboolean reliable;
int pnum = 0; int pnum = -1;
if (to == MULTICAST_INIT) if (to == MULTICAST_INIT)
{ {
@ -580,7 +580,7 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int
#ifdef Q2BSPS #ifdef Q2BSPS
if (sv.world.worldmodel->fromgame == fg_quake2 || sv.world.worldmodel->fromgame == fg_quake3) if (sv.world.worldmodel->fromgame == fg_quake2 || sv.world.worldmodel->fromgame == fg_quake3)
{ {
int area1, area2, cluster; int area1, area2, leafnum;
reliable = false; 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) if (pnum != j)
continue; continue;
} }
else else if (mask)
{ {
#ifdef Q2SERVER #ifdef Q2SERVER
if (ge) if (ge)
@ -743,26 +743,32 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int
case MULTICAST_ALL_R: case MULTICAST_ALL_R:
reliable = true; // intentional fallthrough reliable = true; // intentional fallthrough
case MULTICAST_ALL: case MULTICAST_ALL:
mask = sv.pvs; // leaf 0 is everything; mask = NULL;
break; break;
case MULTICAST_PHS_R: case MULTICAST_PHS_R:
reliable = true; // intentional fallthrough reliable = true; // intentional fallthrough
case MULTICAST_PHS: case MULTICAST_PHS:
if (!sv.phs) /*broadcast if no pvs*/ if (!sv.phs) /*broadcast if no pvs*/
mask = sv.pvs; mask = NULL;
else else
{ {
leafnum = sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, origin); cluster = sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, origin);
mask = sv.phs + leafnum * 4*((sv.world.worldmodel->numleafs+31)>>5); if (cluster >= 0)
mask = sv.phs + cluster * 4*((sv.world.worldmodel->numclusters+31)>>5);
else
mask = NULL;
} }
break; break;
case MULTICAST_PVS_R: case MULTICAST_PVS_R:
reliable = true; // intentional fallthrough reliable = true; // intentional fallthrough
case MULTICAST_PVS: case MULTICAST_PVS:
leafnum = sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, origin); cluster = sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, origin);
mask = sv.pvs + leafnum * 4*((sv.world.worldmodel->numleafs+31)>>5); if (cluster >= 0)
mask = sv.pvs + cluster * 4*((sv.world.worldmodel->numclusters+31)>>5);
else
mask = NULL;
break; break;
case MULTICAST_ONE_R: 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) if (pnum != j)
continue; 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)) if (!((int)client->edict->xv->dimension_see & dimension_mask))
continue; continue;
if (!mask) //no pvs? broadcast.
goto inrange;
if (to == MULTICAST_PHS_R || to == MULTICAST_PHS) if (to == MULTICAST_PHS_R || to == MULTICAST_PHS)
{ {
vec3_t delta; vec3_t delta;
@ -822,13 +831,11 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int
goto inrange; 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; vec3_t pos;
VectorAdd(client->edict->v->origin, client->edict->v->view_ofs, 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 cluster = sv.world.worldmodel->funcs.ClusterForPoint (sv.world.worldmodel, pos);
leafnum = sv.world.worldmodel->funcs.LeafnumForPoint (sv.world.worldmodel, pos)-1; if (cluster>= 0 && !(mask[cluster>>3] & (1<<(cluster&7)) ) )
if ( !(mask[leafnum>>3] & (1<<(leafnum&7)) ) )
{ {
// Con_Printf ("PVS supressed multicast\n"); // Con_Printf ("PVS supressed multicast\n");
continue; continue;

View File

@ -2317,7 +2317,7 @@ void SVQ3_BuildClientSnapshot( client_t *client )
org[2] += ps->viewheight; org[2] += ps->viewheight;
clientarea = CM_PointLeafnum(sv.world.worldmodel, org); 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); clientarea = CM_LeafArea(sv.world.worldmodel, clientarea);
/* /*
if (client->areanum != clientarea) if (client->areanum != clientarea)