From c568680b774f2205b8d44babcc69e88cfddb7dc0 Mon Sep 17 00:00:00 2001
From: havoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Date: Wed, 3 Mar 2004 06:50:56 +0000
Subject: [PATCH] fixed bmodel realtime lighting/shadowing render crashes (and
 bogus shadows from them)

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@3959 d7cf8633-e32d-0410-b094-e92efae38249
---
 gl_rsurf.c | 175 +++++++++++++++++++++++++++++++++++++++--------------
 todo       |   1 +
 2 files changed, 129 insertions(+), 47 deletions(-)

diff --git a/gl_rsurf.c b/gl_rsurf.c
index 21ab7454..bdff5312 100644
--- a/gl_rsurf.c
+++ b/gl_rsurf.c
@@ -1914,32 +1914,53 @@ void R_Model_Brush_DrawShadowVolume (entity_render_t *ent, vec3_t relativelighto
 	}
 	*/
 	R_Shadow_PrepareShadowMark(ent->model->brush.shadowmesh->numtriangles);
-	pvs = ent->model->brush.GetPVS(ent->model, relativelightorigin);
-	for (leafnum = 0, leaf = ent->model->brushq1.data_leafs;leafnum < ent->model->brushq1.num_leafs;leafnum++, leaf++)
+	if (ent->model->brush.GetPVS && (pvs = ent->model->brush.GetPVS(ent->model, relativelightorigin)))
 	{
-		if (BoxesOverlap(lightmins, lightmaxs, leaf->mins, leaf->maxs) && (pvs == NULL || CHECKPVSBIT(pvs, leaf->clusterindex)))
+		pvs = ent->model->brush.GetPVS(ent->model, relativelightorigin);
+		// FIXME: use BSP recursion in q1bsp as dlights are often small
+		for (leafnum = 0, leaf = ent->model->brushq1.data_leafs;leafnum < ent->model->brushq1.num_leafs;leafnum++, leaf++)
 		{
-			for (marksurfnum = 0;marksurfnum < leaf->nummarksurfaces;marksurfnum++)
+			if (BoxesOverlap(lightmins, lightmaxs, leaf->mins, leaf->maxs) && CHECKPVSBIT(pvs, leaf->clusterindex))
 			{
-				surf = ent->model->brushq1.surfaces + leaf->firstmarksurface[marksurfnum];
-				if (surf->shadowmark != shadowmarkcount)
+				for (marksurfnum = 0;marksurfnum < leaf->nummarksurfaces;marksurfnum++)
 				{
-					surf->shadowmark = shadowmarkcount;
-					if (BoxesOverlap(lightmins, lightmaxs, surf->poly_mins, surf->poly_maxs) && surf->texinfo->texture->rendertype == SURFRENDER_OPAQUE && (surf->flags & SURF_SHADOWCAST))
+					surf = ent->model->brushq1.surfaces + leaf->firstmarksurface[marksurfnum];
+					if (surf->shadowmark != shadowmarkcount)
 					{
-						for (trianglenum = 0, t = surf->num_firstshadowmeshtriangle, e = ent->model->brush.shadowmesh->element3i + t * 3;trianglenum < surf->mesh.num_triangles;trianglenum++, t++, e += 3)
+						surf->shadowmark = shadowmarkcount;
+						if (BoxesOverlap(lightmins, lightmaxs, surf->poly_mins, surf->poly_maxs) && surf->texinfo->texture->rendertype == SURFRENDER_OPAQUE && (surf->flags & SURF_SHADOWCAST))
 						{
-							v[0] = ent->model->brush.shadowmesh->vertex3f + e[0] * 3;
-							v[1] = ent->model->brush.shadowmesh->vertex3f + e[1] * 3;
-							v[2] = ent->model->brush.shadowmesh->vertex3f + e[2] * 3;
-							if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
-								shadowmarklist[numshadowmark++] = t;
+							for (trianglenum = 0, t = surf->num_firstshadowmeshtriangle, e = ent->model->brush.shadowmesh->element3i + t * 3;trianglenum < surf->mesh.num_triangles;trianglenum++, t++, e += 3)
+							{
+								v[0] = ent->model->brush.shadowmesh->vertex3f + e[0] * 3;
+								v[1] = ent->model->brush.shadowmesh->vertex3f + e[1] * 3;
+								v[2] = ent->model->brush.shadowmesh->vertex3f + e[2] * 3;
+								if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
+									shadowmarklist[numshadowmark++] = t;
+							}
 						}
 					}
 				}
 			}
 		}
 	}
+	else
+	{
+		for (marksurfnum = 0, surf = ent->model->brushq1.surfaces + ent->model->brushq1.firstmodelsurface;marksurfnum < ent->model->brushq1.nummodelsurfaces;marksurfnum++, surf++)
+		{
+			if (BoxesOverlap(lightmins, lightmaxs, surf->poly_mins, surf->poly_maxs) && surf->texinfo->texture->rendertype == SURFRENDER_OPAQUE && (surf->flags & SURF_SHADOWCAST))
+			{
+				for (trianglenum = 0, t = surf->num_firstshadowmeshtriangle, e = ent->model->brush.shadowmesh->element3i + t * 3;trianglenum < surf->mesh.num_triangles;trianglenum++, t++, e += 3)
+				{
+					v[0] = ent->model->brush.shadowmesh->vertex3f + e[0] * 3;
+					v[1] = ent->model->brush.shadowmesh->vertex3f + e[1] * 3;
+					v[2] = ent->model->brush.shadowmesh->vertex3f + e[2] * 3;
+					if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
+						shadowmarklist[numshadowmark++] = t;
+				}
+			}
+		}
+	}
 	R_Shadow_VolumeFromList(ent->model->brush.shadowmesh->numverts, ent->model->brush.shadowmesh->numtriangles, ent->model->brush.shadowmesh->vertex3f, ent->model->brush.shadowmesh->element3i, ent->model->brush.shadowmesh->neighbor3i, relativelightorigin, projectdistance, numshadowmark, shadowmarklist);
 #endif
 }
@@ -1963,30 +1984,48 @@ void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, v
 	lightmaxs[2] = relativelightorigin[2] + lightradius;
 	R_UpdateTextureInfo(ent);
 	shadowmarkcount++;
-	pvs = ent->model->brush.GetPVS(ent->model, relativelightorigin);
-	for (leafnum = 0, leaf = ent->model->brushq1.data_leafs;leafnum < ent->model->brushq1.num_leafs;leafnum++, leaf++)
+	if (ent->model->brush.GetPVS && (pvs = ent->model->brush.GetPVS(ent->model, relativelightorigin)))
 	{
-		if (BoxesOverlap(lightmins, lightmaxs, leaf->mins, leaf->maxs) && (pvs == NULL || CHECKPVSBIT(pvs, leaf->clusterindex)))
+		pvs = ent->model->brush.GetPVS(ent->model, relativelightorigin);
+		for (leafnum = 0, leaf = ent->model->brushq1.data_leafs;leafnum < ent->model->brushq1.num_leafs;leafnum++, leaf++)
 		{
-			for (marksurfnum = 0;marksurfnum < leaf->nummarksurfaces;marksurfnum++)
+			if (BoxesOverlap(lightmins, lightmaxs, leaf->mins, leaf->maxs) && CHECKPVSBIT(pvs, leaf->clusterindex))
 			{
-				surf = ent->model->brushq1.surfaces + leaf->firstmarksurface[marksurfnum];
-				if (surf->shadowmark != shadowmarkcount)
+				for (marksurfnum = 0;marksurfnum < leaf->nummarksurfaces;marksurfnum++)
 				{
-					surf->shadowmark = shadowmarkcount;
-					if ((ent != &cl_entities[0].render || surf->visframe == r_framecount) && BoxesOverlap(lightmins, lightmaxs, surf->poly_mins, surf->poly_maxs))
+					surf = ent->model->brushq1.surfaces + leaf->firstmarksurface[marksurfnum];
+					if (surf->shadowmark != shadowmarkcount)
 					{
-						t = surf->texinfo->texture->currentframe;
-						if (t->rendertype == SURFRENDER_OPAQUE && t->flags & SURF_SHADOWLIGHT)
+						surf->shadowmark = shadowmarkcount;
+						if (BoxesOverlap(lightmins, lightmaxs, surf->poly_mins, surf->poly_maxs) && (ent != &cl_entities[0].render || surf->visframe == r_framecount))
 						{
-							R_Shadow_DiffuseLighting(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i, surf->mesh.data_vertex3f, surf->mesh.data_svector3f, surf->mesh.data_tvector3f, surf->mesh.data_normal3f, surf->mesh.data_texcoordtexture2f, relativelightorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.base, t->skin.nmap, lightcubemap);
-							R_Shadow_SpecularLighting(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i, surf->mesh.data_vertex3f, surf->mesh.data_svector3f, surf->mesh.data_tvector3f, surf->mesh.data_normal3f, surf->mesh.data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.gloss, t->skin.nmap, lightcubemap);
+							t = surf->texinfo->texture->currentframe;
+							if (t->rendertype == SURFRENDER_OPAQUE && t->flags & SURF_SHADOWLIGHT)
+							{
+								R_Shadow_DiffuseLighting(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i, surf->mesh.data_vertex3f, surf->mesh.data_svector3f, surf->mesh.data_tvector3f, surf->mesh.data_normal3f, surf->mesh.data_texcoordtexture2f, relativelightorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.base, t->skin.nmap, lightcubemap);
+								R_Shadow_SpecularLighting(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i, surf->mesh.data_vertex3f, surf->mesh.data_svector3f, surf->mesh.data_tvector3f, surf->mesh.data_normal3f, surf->mesh.data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.gloss, t->skin.nmap, lightcubemap);
+							}
 						}
 					}
 				}
 			}
 		}
 	}
+	else
+	{
+		for (marksurfnum = 0, surf = ent->model->brushq1.surfaces + ent->model->brushq1.firstmodelsurface;marksurfnum < ent->model->brushq1.nummodelsurfaces;marksurfnum++, surf++)
+		{
+			if (BoxesOverlap(lightmins, lightmaxs, surf->poly_mins, surf->poly_maxs) && (ent != &cl_entities[0].render || surf->visframe == r_framecount))
+			{
+				t = surf->texinfo->texture->currentframe;
+				if (t->rendertype == SURFRENDER_OPAQUE && t->flags & SURF_SHADOWLIGHT)
+				{
+					R_Shadow_DiffuseLighting(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i, surf->mesh.data_vertex3f, surf->mesh.data_svector3f, surf->mesh.data_tvector3f, surf->mesh.data_normal3f, surf->mesh.data_texcoordtexture2f, relativelightorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.base, t->skin.nmap, lightcubemap);
+					R_Shadow_SpecularLighting(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i, surf->mesh.data_vertex3f, surf->mesh.data_svector3f, surf->mesh.data_tvector3f, surf->mesh.data_normal3f, surf->mesh.data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.gloss, t->skin.nmap, lightcubemap);
+				}
+			}
+		}
+	}
 }
 
 void R_DrawCollisionBrush(colbrushf_t *brush)
@@ -2519,32 +2558,51 @@ void R_Q3BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin,
 		lightmaxs[1] = relativelightorigin[1] + lightradius;
 		lightmaxs[2] = relativelightorigin[2] + lightradius;
 		R_Shadow_PrepareShadowMark(model->brush.shadowmesh->numtriangles);
-		pvs = ent->model->brush.GetPVS(ent->model, relativelightorigin);
-		for (leafnum = 0, leaf = ent->model->brushq3.data_leafs;leafnum < ent->model->brushq3.num_leafs;leafnum++, leaf++)
-		{
-			if (BoxesOverlap(lightmins, lightmaxs, leaf->mins, leaf->maxs) && (pvs == NULL || CHECKPVSBIT(pvs, leaf->clusterindex)))
+		if (ent->model->brush.GetPVS && (pvs = ent->model->brush.GetPVS(ent->model, relativelightorigin)))
+		{	
+			for (leafnum = 0, leaf = ent->model->brushq3.data_leafs;leafnum < ent->model->brushq3.num_leafs;leafnum++, leaf++)
 			{
-				for (marksurfnum = 0;marksurfnum < leaf->numleaffaces;marksurfnum++)
+				if (BoxesOverlap(lightmins, lightmaxs, leaf->mins, leaf->maxs) && CHECKPVSBIT(pvs, leaf->clusterindex))
 				{
-					face = leaf->firstleafface[marksurfnum];
-					if (face->shadowmark != shadowmarkcount)
+					for (marksurfnum = 0;marksurfnum < leaf->numleaffaces;marksurfnum++)
 					{
-						face->shadowmark = shadowmarkcount;
-						if (BoxesOverlap(lightmins, lightmaxs, face->mins, face->maxs))
+						face = leaf->firstleafface[marksurfnum];
+						if (face->shadowmark != shadowmarkcount)
 						{
-							for (j = 0, t = face->num_firstshadowmeshtriangle, e = model->brush.shadowmesh->element3i + t * 3;j < face->num_triangles;j++, t++, e += 3)
+							face->shadowmark = shadowmarkcount;
+							if (BoxesOverlap(lightmins, lightmaxs, face->mins, face->maxs))
 							{
-								v[0] = model->brush.shadowmesh->vertex3f + e[0] * 3;
-								v[1] = model->brush.shadowmesh->vertex3f + e[1] * 3;
-								v[2] = model->brush.shadowmesh->vertex3f + e[2] * 3;
-								if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
-									shadowmarklist[numshadowmark++] = t;
+								for (j = 0, t = face->num_firstshadowmeshtriangle, e = model->brush.shadowmesh->element3i + t * 3;j < face->num_triangles;j++, t++, e += 3)
+								{
+									v[0] = model->brush.shadowmesh->vertex3f + e[0] * 3;
+									v[1] = model->brush.shadowmesh->vertex3f + e[1] * 3;
+									v[2] = model->brush.shadowmesh->vertex3f + e[2] * 3;
+									if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
+										shadowmarklist[numshadowmark++] = t;
+								}
 							}
 						}
 					}
 				}
 			}
 		}
+		else
+		{
+			for (marksurfnum = 0, face = model->brushq3.data_thismodel->firstface;marksurfnum < model->brushq3.data_thismodel->numfaces;marksurfnum++, face++)
+			{
+				if (BoxesOverlap(lightmins, lightmaxs, face->mins, face->maxs))
+				{
+					for (j = 0, t = face->num_firstshadowmeshtriangle, e = model->brush.shadowmesh->element3i + t * 3;j < face->num_triangles;j++, t++, e += 3)
+					{
+						v[0] = model->brush.shadowmesh->vertex3f + e[0] * 3;
+						v[1] = model->brush.shadowmesh->vertex3f + e[1] * 3;
+						v[2] = model->brush.shadowmesh->vertex3f + e[2] * 3;
+						if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
+							shadowmarklist[numshadowmark++] = t;
+					}
+				}
+			}
+		}
 		R_Shadow_VolumeFromList(model->brush.shadowmesh->numverts, model->brush.shadowmesh->numtriangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, model->brush.shadowmesh->neighbor3i, relativelightorigin, projectdistance, numshadowmark, shadowmarklist);
 	}
 #endif
@@ -2560,8 +2618,10 @@ void R_Q3BSP_DrawFaceLight(entity_render_t *ent, q3mface_t *face, vec3_t relativ
 
 void R_Q3BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap)
 {
-	int i;
+	int leafnum, marksurfnum;
+	const qbyte *pvs;
 	q3mface_t *face;
+	q3mleaf_t *leaf;
 	vec3_t modelorg, lightmins, lightmaxs;
 	model_t *model;
 	//qbyte *pvs;
@@ -2577,12 +2637,33 @@ void R_Q3BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t
 		lightmaxs[0] = relativelightorigin[0] + lightradius;
 		lightmaxs[1] = relativelightorigin[1] + lightradius;
 		lightmaxs[2] = relativelightorigin[2] + lightradius;
-		//if (ent == &cl_entities[0].render && model->brush.num_pvsclusters && !r_novis.integer && (pvs = model->brush.GetPVS(model, modelorg)))
-		//	R_Q3BSP_RecursiveWorldNode(ent, model->brushq3.data_nodes, modelorg, pvs, ++markframe);
-		//else
-			for (i = 0, face = model->brushq3.data_thismodel->firstface;i < model->brushq3.data_thismodel->numfaces;i++, face++)
-				if ((ent != &cl_entities[0].render || face->visframe == r_framecount) && BoxesOverlap(lightmins, lightmaxs, face->mins, face->maxs))
+
+		if (ent->model->brush.GetPVS && (pvs = ent->model->brush.GetPVS(ent->model, relativelightorigin)))
+		{	
+			pvs = ent->model->brush.GetPVS(ent->model, relativelightorigin);
+			for (leafnum = 0, leaf = ent->model->brushq3.data_leafs;leafnum < ent->model->brushq3.num_leafs;leafnum++, leaf++)
+			{
+				if (BoxesOverlap(lightmins, lightmaxs, leaf->mins, leaf->maxs) && CHECKPVSBIT(pvs, leaf->clusterindex))
+				{
+					for (marksurfnum = 0;marksurfnum < leaf->numleaffaces;marksurfnum++)
+					{
+						face = leaf->firstleafface[marksurfnum];
+						if (face->shadowmark != shadowmarkcount)
+						{
+							face->shadowmark = shadowmarkcount;
+							if (BoxesOverlap(lightmins, lightmaxs, face->mins, face->maxs) && (ent != &cl_entities[0].render || face->visframe == r_framecount))
+								R_Q3BSP_DrawFaceLight(ent, face, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, lightcubemap);
+						}
+					}
+				}
+			}
+		}
+		else
+		{
+			for (marksurfnum = 0, face = model->brushq3.data_thismodel->firstface;marksurfnum < model->brushq3.data_thismodel->numfaces;marksurfnum++, face++)
+				if (BoxesOverlap(lightmins, lightmaxs, face->mins, face->maxs) && (ent != &cl_entities[0].render || face->visframe == r_framecount))
 					R_Q3BSP_DrawFaceLight(ent, face, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, lightcubemap);
+		}
 	}
 }
 
diff --git a/todo b/todo
index 223691e2..2179f2dd 100644
--- a/todo
+++ b/todo
@@ -37,6 +37,7 @@ d darkplaces: revert noclip movement to match nq for compatibility with mods tha
 d darkplaces: make light_lev dlights from qc require PFLAGS_FULLDYNAMIC flag
 d darkplaces: improve tenebrae compatibility by handling EF_FULLDYNAMIC flag in tenebrae mode, also make all sprites render additive
 d darkplaces: add r_showtris cvar (Riot)
+0 darkplaces: fix model lighting with r_shadow_realtime_world_lightmaps mode, it seems to be adding dlights to vertices? (Mitchell)
 3 darkplaces: figure out BoxOnPlaneSide crash that happens in dpmod dpdm2 deathmatch 7 occasionally
 2 darkplaces: add q2 sprite support sometime
 0 dpmod: fix tilted corpse bug
-- 
2.39.5