From de212b07cd23acd1c90f20d6be6f587c3e7e9df0 Mon Sep 17 00:00:00 2001
From: Sally Coolatta <tehrealsalt@gmail.com>
Date: Mon, 25 Apr 2022 20:14:53 -0400
Subject: [PATCH] Bring back shadows on polyobjects

Also optimizes the method used so rings can show their shadows too. Using just the subsector is a tad bit imprecise admittedly but any more precise methods get really laggy.
---
 src/r_fps.c    |  5 +++
 src/r_fps.h    |  1 +
 src/r_things.c | 87 ++++++++++++++++----------------------------------
 3 files changed, 33 insertions(+), 60 deletions(-)

diff --git a/src/r_fps.c b/src/r_fps.c
index cc518cc35..c4f69415c 100644
--- a/src/r_fps.c
+++ b/src/r_fps.c
@@ -256,6 +256,8 @@ void R_InterpolateMobjState(mobj_t *mobj, fixed_t frac, interpmobjstate_t *out)
 	out->y = R_LerpFixed(mobj->old_y, mobj->y, frac);
 	out->z = R_LerpFixed(mobj->old_z, mobj->z, frac);
 
+	out->subsector = R_PointInSubsector(out->x, out->y);
+
 	if (mobj->player)
 	{
 		out->angle = R_LerpAngle(mobj->player->old_drawangle, mobj->player->drawangle, frac);
@@ -271,6 +273,9 @@ void R_InterpolatePrecipMobjState(precipmobj_t *mobj, fixed_t frac, interpmobjst
 	out->x = R_LerpFixed(mobj->old_x, mobj->x, frac);
 	out->y = R_LerpFixed(mobj->old_y, mobj->y, frac);
 	out->z = R_LerpFixed(mobj->old_z, mobj->z, frac);
+
+	out->subsector = R_PointInSubsector(out->x, out->y);
+
 	out->angle = R_LerpAngle(mobj->old_angle, mobj->angle, frac);
 }
 
diff --git a/src/r_fps.h b/src/r_fps.h
index 59d3df747..32c9131fe 100644
--- a/src/r_fps.h
+++ b/src/r_fps.h
@@ -53,6 +53,7 @@ typedef struct {
 	fixed_t x;
 	fixed_t y;
 	fixed_t z;
+	subsector_t *subsector;
 	angle_t angle;
 } interpmobjstate_t;
 
diff --git a/src/r_things.c b/src/r_things.c
index 0af691b38..5e10d8fa3 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -1158,8 +1158,8 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope)
 	}
 
 	halfHeight = interp.z + (thing->height >> 1);
-	floorz = P_GetFloorZ(thing, thing->subsector->sector, interp.x, interp.y, NULL);
-	ceilingz = P_GetCeilingZ(thing, thing->subsector->sector, interp.x, interp.y, NULL);
+	floorz = P_GetFloorZ(thing, interp.subsector->sector, interp.x, interp.y, NULL);
+	ceilingz = P_GetCeilingZ(thing, interp.subsector->sector, interp.x, interp.y, NULL);
 
 #define CHECKZ (isflipped ? z > halfHeight && z < groundz : z < halfHeight && z > groundz)
 
@@ -1195,71 +1195,38 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope)
 			}
 	}
 
-	if (isflipped ? (ceilingz < groundz - (!groundslope ? 0 : FixedMul(abs(groundslope->zdelta), thing->radius*3/2)))
-		: (floorz > groundz + (!groundslope ? 0 : FixedMul(abs(groundslope->zdelta), thing->radius*3/2))))
-	{
-		groundz = isflipped ? ceilingz : floorz;
-		groundslope = NULL;
-	}
-
-#if 0 // Unfortunately, this drops CEZ2 down to sub-17 FPS on my i7.
-	// NOTE: this section was not updated to reflect reverse gravity support
-	// Check polyobjects and see if groundz needs to be altered, for rings only because they don't update floorz
-	if (thing->type == MT_RING)
+	// Check polyobjects and see if groundz needs to be altered
 	{
-		INT32 xl, xh, yl, yh, bx, by;
-
-		xl = (unsigned)(interp.x - thing->radius - bmaporgx)>>MAPBLOCKSHIFT;
-		xh = (unsigned)(interp.x + thing->radius - bmaporgx)>>MAPBLOCKSHIFT;
-		yl = (unsigned)(interp.y - thing->radius - bmaporgy)>>MAPBLOCKSHIFT;
-		yh = (unsigned)(interp.y + thing->radius - bmaporgy)>>MAPBLOCKSHIFT;
-
-		BMBOUNDFIX(xl, xh, yl, yh);
-
-		validcount++;
+		// This isn't very precise, but the precise method was far too slow.
+		// (Polies are just naturally pretty flickery anyway :P)
+		polyobj_t *po = interp.subsector->polyList;
 
-		for (by = yl; by <= yh; by++)
-			for (bx = xl; bx <= xh; bx++)
+		while (po)
+		{
+			if (!(po->flags & POF_RENDERPLANES) || !P_MobjInsidePolyobj(po, thing))
 			{
-				INT32 offset;
-				polymaplink_t *plink; // haleyjd 02/22/06
-
-				if (bx < 0 || by < 0 || bx >= bmapwidth || by >= bmapheight)
-					continue;
-
-				offset = by*bmapwidth + bx;
-
-				// haleyjd 02/22/06: consider polyobject lines
-				plink = polyblocklinks[offset];
-
-				while (plink)
-				{
-					polyobj_t *po = plink->po;
-
-					if (po->validcount != validcount) // if polyobj hasn't been checked
-					{
-						po->validcount = validcount;
+				po = (polyobj_t *)(po->link.next);
+				continue;
+			}
 
-						if (!P_MobjInsidePolyobj(po, thing) || !(po->flags & POF_RENDERPLANES))
-						{
-							plink = (polymaplink_t *)(plink->link.next);
-							continue;
-						}
+			// We're inside it! Yess...
+			z = isflipped ? po->lines[0]->backsector->floorheight : po->lines[0]->backsector->ceilingheight;
+			if CHECKZ
+			{
+				groundz = z;
+				groundslope = NULL;
+			}
 
-						// We're inside it! Yess...
-						z = po->lines[0]->backsector->ceilingheight;
+			po = (polyobj_t *)(po->link.next);
+		}
+	}
 
-						if (z < halfHeight && z > groundz)
-						{
-							groundz = z;
-							groundslope = NULL;
-						}
-					}
-					plink = (polymaplink_t *)(plink->link.next);
-				}
-			}
+	if (isflipped ? (ceilingz < groundz - (!groundslope ? 0 : FixedMul(abs(groundslope->zdelta), thing->radius*3/2)))
+		: (floorz > groundz + (!groundslope ? 0 : FixedMul(abs(groundslope->zdelta), thing->radius*3/2))))
+	{
+		groundz = isflipped ? ceilingz : floorz;
+		groundslope = NULL;
 	}
-#endif
 
 	if (shadowslope != NULL)
 		*shadowslope = groundslope;
-- 
GitLab