int *outleaflist;
unsigned char *outleafpvs;
int outnumleafs;
+ unsigned char *visitingleafpvs;
int *outsurfacelist;
unsigned char *outsurfacepvs;
unsigned char *tempsurfacepvs;
}
}
-void R_Q1BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outleaflist, unsigned char *outleafpvs, int *outnumleafspointer, int *outsurfacelist, unsigned char *outsurfacepvs, int *outnumsurfacespointer, unsigned char *outshadowtrispvs, unsigned char *outlighttrispvs)
+void R_Q1BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outleaflist, unsigned char *outleafpvs, int *outnumleafspointer, int *outsurfacelist, unsigned char *outsurfacepvs, int *outnumsurfacespointer, unsigned char *outshadowtrispvs, unsigned char *outlighttrispvs, unsigned char *visitingleafpvs)
{
r_q1bsp_getlightinfo_t info;
VectorCopy(relativelightorigin, info.relativelightorigin);
info.outleaflist = outleaflist;
info.outleafpvs = outleafpvs;
info.outnumleafs = 0;
+ info.visitingleafpvs = visitingleafpvs;
info.outsurfacelist = outsurfacelist;
info.outsurfacepvs = outsurfacepvs;
info.outshadowtrispvs = outshadowtrispvs;
info.outnumsurfaces = 0;
VectorCopy(info.relativelightorigin, info.outmins);
VectorCopy(info.relativelightorigin, info.outmaxs);
+ memset(visitingleafpvs, 0, (info.model->brush.num_leafs + 7) >> 3);
memset(outleafpvs, 0, (info.model->brush.num_leafs + 7) >> 3);
memset(outsurfacepvs, 0, (info.model->nummodelsurfaces + 7) >> 3);
if (info.model->brush.shadowmesh)
if (r_shadow_frontsidecasting.integer && r_shadow_compilingrtlight && r_shadow_realtime_world_compileportalculling.integer && info.model->brush.data_portals)
{
// use portal recursion for exact light volume culling, and exact surface checking
- Portal_Visibility(info.model, info.relativelightorigin, info.outleaflist, info.outleafpvs, &info.outnumleafs, info.outsurfacelist, info.outsurfacepvs, &info.outnumsurfaces, NULL, 0, true, info.lightmins, info.lightmaxs, info.outmins, info.outmaxs, info.outshadowtrispvs, info.outlighttrispvs);
+ Portal_Visibility(info.model, info.relativelightorigin, info.outleaflist, info.outleafpvs, &info.outnumleafs, info.outsurfacelist, info.outsurfacepvs, &info.outnumsurfaces, NULL, 0, true, info.lightmins, info.lightmaxs, info.outmins, info.outmaxs, info.outshadowtrispvs, info.outlighttrispvs, info.visitingleafpvs);
}
else if (r_shadow_frontsidecasting.integer && r_shadow_realtime_dlight_portalculling.integer && info.model->brush.data_portals)
{
// use portal recursion for exact light volume culling, but not the expensive exact surface checking
- Portal_Visibility(info.model, info.relativelightorigin, info.outleaflist, info.outleafpvs, &info.outnumleafs, info.outsurfacelist, info.outsurfacepvs, &info.outnumsurfaces, NULL, 0, r_shadow_realtime_dlight_portalculling.integer >= 2, info.lightmins, info.lightmaxs, info.outmins, info.outmaxs, info.outshadowtrispvs, info.outlighttrispvs);
+ Portal_Visibility(info.model, info.relativelightorigin, info.outleaflist, info.outleafpvs, &info.outnumleafs, info.outsurfacelist, info.outsurfacepvs, &info.outnumsurfaces, NULL, 0, r_shadow_realtime_dlight_portalculling.integer >= 2, info.lightmins, info.lightmaxs, info.outmins, info.outmaxs, info.outshadowtrispvs, info.outlighttrispvs, info.visitingleafpvs);
}
else
{
// draw any enabled debugging effects on this model (such as showing triangles, normals, collision brushes...)
void(*DrawDebug)(struct entity_render_s *ent);
// gathers info on which clusters and surfaces are lit by light, as well as calculating a bounding box
- void(*GetLightInfo)(struct entity_render_s *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outleaflist, unsigned char *outleafpvs, int *outnumleafspointer, int *outsurfacelist, unsigned char *outsurfacepvs, int *outnumsurfacespointer, unsigned char *outshadowtrispvs, unsigned char *outlighttrispvs);
+ void(*GetLightInfo)(struct entity_render_s *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outleaflist, unsigned char *outleafpvs, int *outnumleafspointer, int *outsurfacelist, unsigned char *outsurfacepvs, int *outnumsurfacespointer, unsigned char *outshadowtrispvs, unsigned char *outlighttrispvs, unsigned char *visitingleafpvs);
// compile a shadow volume for the model based on light source
void(*CompileShadowVolume)(struct entity_render_s *ent, vec3_t relativelightorigin, vec3_t relativelightdirection, float lightradius, int numsurfaces, const int *surfacelist);
// draw a shadow volume for the model based on light source
void R_Q1BSP_Draw(struct entity_render_s *ent);
void R_Q1BSP_DrawDepth(struct entity_render_s *ent);
void R_Q1BSP_DrawDebug(struct entity_render_s *ent);
-void R_Q1BSP_GetLightInfo(struct entity_render_s *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outleaflist, unsigned char *outleafpvs, int *outnumleafspointer, int *outsurfacelist, unsigned char *outsurfacepvs, int *outnumsurfacespointer, unsigned char *outshadowtrispvs, unsigned char *outlighttrispvs);
+void R_Q1BSP_GetLightInfo(struct entity_render_s *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outleaflist, unsigned char *outleafpvs, int *outnumleafspointer, int *outsurfacelist, unsigned char *outsurfacepvs, int *outnumsurfacespointer, unsigned char *outshadowtrispvs, unsigned char *outlighttrispvs, unsigned char *visitingleafpvs);
void R_Q1BSP_CompileShadowVolume(struct entity_render_s *ent, vec3_t relativelightorigin, vec3_t relativelightdirection, float lightradius, int numsurfaces, const int *surfacelist);
void R_Q1BSP_DrawShadowVolume(struct entity_render_s *ent, const vec3_t relativelightorigin, const vec3_t relativelightdirection, float lightradius, int numsurfaces, const int *surfacelist, const vec3_t lightmins, const vec3_t lightmaxs);
void R_Q1BSP_DrawLight(struct entity_render_s *ent, int numsurfaces, const int *surfacelist, const unsigned char *trispvs);
int *surfacelist;
unsigned char *surfacepvs;
int numleafs;
+ unsigned char *visitingleafpvs; // used to prevent infinite loops
int *leaflist;
unsigned char *leafpvs;
unsigned char *shadowtrispvs;
float dist;
vec3_t center;
tinyplane_t *newplanes;
+ int leafindex = leaf - info->model->brush.data_leafs;
+
+ if (CHECKPVSBIT(info->visitingleafpvs, leafindex))
+ return; // recursive loop of leafs (cmc.bsp for megatf coop)
+
+ SETPVSBIT(info->visitingleafpvs, leafindex);
for (i = 0;i < 3;i++)
{
if (info->leafpvs)
{
- int leafindex = leaf - info->model->brush.data_leafs;
if (!CHECKPVSBIT(info->leafpvs, leafindex))
{
SETPVSBIT(info->leafpvs, leafindex);
}
}
}
+
+ CLEARPVSBIT(info->visitingleafpvs, leafindex);
}
static void Portal_RecursiveFindLeafForFlow(portalrecursioninfo_t *info, mnode_t *node)
}
}
-void Portal_Visibility(dp_model_t *model, const vec3_t eye, int *leaflist, unsigned char *leafpvs, int *numleafspointer, int *surfacelist, unsigned char *surfacepvs, int *numsurfacespointer, const mplane_t *frustumplanes, int numfrustumplanes, int exact, const float *boxmins, const float *boxmaxs, float *updateleafsmins, float *updateleafsmaxs, unsigned char *shadowtrispvs, unsigned char *lighttrispvs)
+void Portal_Visibility(dp_model_t *model, const vec3_t eye, int *leaflist, unsigned char *leafpvs, int *numleafspointer, int *surfacelist, unsigned char *surfacepvs, int *numsurfacespointer, const mplane_t *frustumplanes, int numfrustumplanes, int exact, const float *boxmins, const float *boxmaxs, float *updateleafsmins, float *updateleafsmaxs, unsigned char *shadowtrispvs, unsigned char *lighttrispvs, unsigned char *visitingleafpvs)
{
int i;
portalrecursioninfo_t info;
info.surfacelist = surfacelist;
info.surfacepvs = surfacepvs;
info.numleafs = 0;
+ info.visitingleafpvs = visitingleafpvs;
info.leaflist = leaflist;
info.leafpvs = leafpvs;
info.model = model;
int Portal_CheckPolygon(dp_model_t *model, vec3_t eye, float *polypoints, int numpoints);
int Portal_CheckBox(dp_model_t *model, vec3_t eye, vec3_t a, vec3_t b);
-void Portal_Visibility(dp_model_t *model, const vec3_t eye, int *leaflist, unsigned char *leafpvs, int *numleafspointer, int *surfacelist, unsigned char *surfacepvs, int *numsurfacespointer, const mplane_t *frustumplanes, int numfrustumplanes, int exact, const float *boxmins, const float *boxmaxs, float *updateleafsmins, float *updateleafsmaxs, unsigned char *shadowtrispvs, unsigned char *lighttrispvs);
+void Portal_Visibility(dp_model_t *model, const vec3_t eye, int *leaflist, unsigned char *leafpvs, int *numleafspointer, int *surfacelist, unsigned char *surfacepvs, int *numsurfacespointer, const mplane_t *frustumplanes, int numfrustumplanes, int exact, const float *boxmins, const float *boxmaxs, float *updateleafsmins, float *updateleafsmaxs, unsigned char *shadowtrispvs, unsigned char *lighttrispvs, unsigned char *visitingleafpvs);
#endif
int vertexupdatenum;
int r_shadow_buffer_numleafpvsbytes;
+unsigned char *r_shadow_buffer_visitingleafpvs;
unsigned char *r_shadow_buffer_leafpvs;
int *r_shadow_buffer_leaflist;
shadowmarklist = NULL;
shadowmarkcount = 0;
r_shadow_buffer_numleafpvsbytes = 0;
+ r_shadow_buffer_visitingleafpvs = NULL;
r_shadow_buffer_leafpvs = NULL;
r_shadow_buffer_leaflist = NULL;
r_shadow_buffer_numsurfacepvsbytes = 0;
shadowmarklist = NULL;
shadowmarkcount = 0;
r_shadow_buffer_numleafpvsbytes = 0;
+ if (r_shadow_buffer_visitingleafpvs)
+ Mem_Free(r_shadow_buffer_visitingleafpvs);
+ r_shadow_buffer_visitingleafpvs = NULL;
if (r_shadow_buffer_leafpvs)
Mem_Free(r_shadow_buffer_leafpvs);
r_shadow_buffer_leafpvs = NULL;
shadowmarklist = NULL;
shadowmarkcount = 0;
r_shadow_buffer_numleafpvsbytes = 0;
+ r_shadow_buffer_visitingleafpvs = NULL;
r_shadow_buffer_leafpvs = NULL;
r_shadow_buffer_leaflist = NULL;
r_shadow_buffer_numsurfacepvsbytes = 0;
int numlighttrispvsbytes = (((numlighttriangles + 7) >> 3) + 255) & ~255;
if (r_shadow_buffer_numleafpvsbytes < numleafpvsbytes)
{
+ if (r_shadow_buffer_visitingleafpvs)
+ Mem_Free(r_shadow_buffer_visitingleafpvs);
if (r_shadow_buffer_leafpvs)
Mem_Free(r_shadow_buffer_leafpvs);
if (r_shadow_buffer_leaflist)
Mem_Free(r_shadow_buffer_leaflist);
r_shadow_buffer_numleafpvsbytes = numleafpvsbytes;
+ r_shadow_buffer_visitingleafpvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numleafpvsbytes);
r_shadow_buffer_leafpvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numleafpvsbytes);
r_shadow_buffer_leaflist = (int *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numleafpvsbytes * 8 * sizeof(*r_shadow_buffer_leaflist));
}
// this variable must be set for the CompileShadowVolume code
r_shadow_compilingrtlight = rtlight;
R_Shadow_EnlargeLeafSurfaceTrisBuffer(model->brush.num_leafs, model->num_surfaces, model->brush.shadowmesh ? model->brush.shadowmesh->numtriangles : model->surfmesh.num_triangles, model->surfmesh.num_triangles);
- model->GetLightInfo(ent, rtlight->shadoworigin, rtlight->radius, rtlight->cullmins, rtlight->cullmaxs, r_shadow_buffer_leaflist, r_shadow_buffer_leafpvs, &numleafs, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces, r_shadow_buffer_shadowtrispvs, r_shadow_buffer_lighttrispvs);
+ model->GetLightInfo(ent, rtlight->shadoworigin, rtlight->radius, rtlight->cullmins, rtlight->cullmaxs, r_shadow_buffer_leaflist, r_shadow_buffer_leafpvs, &numleafs, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces, r_shadow_buffer_shadowtrispvs, r_shadow_buffer_lighttrispvs, r_shadow_buffer_visitingleafpvs);
numleafpvsbytes = (model->brush.num_leafs + 7) >> 3;
numshadowtrispvsbytes = ((model->brush.shadowmesh ? model->brush.shadowmesh->numtriangles : model->surfmesh.num_triangles) + 7) >> 3;
numlighttrispvsbytes = (model->surfmesh.num_triangles + 7) >> 3;
// dynamic light, world available and can receive realtime lighting
// calculate lit surfaces and leafs
R_Shadow_EnlargeLeafSurfaceTrisBuffer(r_refdef.scene.worldmodel->brush.num_leafs, r_refdef.scene.worldmodel->num_surfaces, r_refdef.scene.worldmodel->brush.shadowmesh ? r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles : r_refdef.scene.worldmodel->surfmesh.num_triangles, r_refdef.scene.worldmodel->surfmesh.num_triangles);
- r_refdef.scene.worldmodel->GetLightInfo(r_refdef.scene.worldentity, rtlight->shadoworigin, rtlight->radius, rsurface.rtlight_cullmins, rsurface.rtlight_cullmaxs, r_shadow_buffer_leaflist, r_shadow_buffer_leafpvs, &numleafs, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces, r_shadow_buffer_shadowtrispvs, r_shadow_buffer_lighttrispvs);
+ r_refdef.scene.worldmodel->GetLightInfo(r_refdef.scene.worldentity, rtlight->shadoworigin, rtlight->radius, rsurface.rtlight_cullmins, rsurface.rtlight_cullmaxs, r_shadow_buffer_leaflist, r_shadow_buffer_leafpvs, &numleafs, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces, r_shadow_buffer_shadowtrispvs, r_shadow_buffer_lighttrispvs, r_shadow_buffer_visitingleafpvs);
leaflist = r_shadow_buffer_leaflist;
leafpvs = r_shadow_buffer_leafpvs;
surfacelist = r_shadow_buffer_surfacelist;