From dd42682791ce98d4c8b418ecc065130ae9faed55 Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Tue, 19 May 2020 16:48:50 +0100
Subject: [PATCH 1/8] remove gxt and gyt, as they are unnecessary

also add a few comments to explain what tx/tz are
---
 src/r_things.c | 40 +++++++++-------------------------------
 1 file changed, 9 insertions(+), 31 deletions(-)

diff --git a/src/r_things.c b/src/r_things.c
index 8a3c2e35f..febb5b6dc 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -1346,7 +1346,6 @@ static void R_ProjectSprite(mobj_t *thing)
 {
 	mobj_t *oldthing = thing;
 	fixed_t tr_x, tr_y;
-	fixed_t gxt, gyt;
 	fixed_t tx, tz;
 	fixed_t xscale, yscale, sortscale; //added : 02-02-98 : aaargll..if I were a math-guy!!!
 
@@ -1399,18 +1398,13 @@ static void R_ProjectSprite(mobj_t *thing)
 	tr_x = thing->x - viewx;
 	tr_y = thing->y - viewy;
 
-	gxt = FixedMul(tr_x, viewcos);
-	gyt = -FixedMul(tr_y, viewsin);
-
-	tz = gxt-gyt;
+	tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); // near/far distance
 
 	// thing is behind view plane?
 	if (!papersprite && (tz < FixedMul(MINZ, this_scale))) // papersprite clipping is handled later
 		return;
 
-	gxt = -FixedMul(tr_x, viewsin);
-	gyt = FixedMul(tr_y, viewcos);
-	basetx = tx = -(gyt + gxt);
+	basetx = tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); // sideways distance
 
 	// too far off the side?
 	if (!papersprite && abs(tx) > tz<<2) // papersprite clipping is handled later
@@ -1561,15 +1555,11 @@ static void R_ProjectSprite(mobj_t *thing)
 
 		tr_x += FixedMul(offset, cosmul);
 		tr_y += FixedMul(offset, sinmul);
-		gxt = FixedMul(tr_x, viewcos);
-		gyt = -FixedMul(tr_y, viewsin);
-		tz = gxt-gyt;
+		tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin);
 		yscale = FixedDiv(projectiony, tz);
 		//if (yscale < 64) return; // Fix some funky visuals
 
-		gxt = -FixedMul(tr_x, viewsin);
-		gyt = FixedMul(tr_y, viewcos);
-		tx = -(gyt + gxt);
+		tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos);
 		xscale = FixedDiv(projection, tz);
 		x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS;
 
@@ -1585,15 +1575,11 @@ static void R_ProjectSprite(mobj_t *thing)
 
 		tr_x += FixedMul(offset2, cosmul);
 		tr_y += FixedMul(offset2, sinmul);
-		gxt = FixedMul(tr_x, viewcos);
-		gyt = -FixedMul(tr_y, viewsin);
-		tz2 = gxt-gyt;
+		tz2 = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin);
 		yscale2 = FixedDiv(projectiony, tz2);
 		//if (yscale2 < 64) return; // ditto
 
-		gxt = -FixedMul(tr_x, viewsin);
-		gyt = FixedMul(tr_y, viewcos);
-		tx2 = -(gyt + gxt);
+		tx2 = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos);
 		xscale2 = FixedDiv(projection, tz2);
 		x2 = ((centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS);
 
@@ -1670,9 +1656,7 @@ static void R_ProjectSprite(mobj_t *thing)
 
 		tr_x = thing->x - viewx;
 		tr_y = thing->y - viewy;
-		gxt = FixedMul(tr_x, viewcos);
-		gyt = -FixedMul(tr_y, viewsin);
-		tz = gxt-gyt;
+		tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin);
 		linkscale = FixedDiv(projectiony, tz);
 
 		if (tz < FixedMul(MINZ, this_scale))
@@ -1872,7 +1856,6 @@ static void R_ProjectSprite(mobj_t *thing)
 static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
 {
 	fixed_t tr_x, tr_y;
-	fixed_t gxt, gyt;
 	fixed_t tx, tz;
 	fixed_t xscale, yscale; //added : 02-02-98 : aaargll..if I were a math-guy!!!
 
@@ -1893,18 +1876,13 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
 	tr_x = thing->x - viewx;
 	tr_y = thing->y - viewy;
 
-	gxt = FixedMul(tr_x, viewcos);
-	gyt = -FixedMul(tr_y, viewsin);
-
-	tz = gxt - gyt;
+	tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); // near/far distance
 
 	// thing is behind view plane?
 	if (tz < MINZ)
 		return;
 
-	gxt = -FixedMul(tr_x, viewsin);
-	gyt = FixedMul(tr_y, viewcos);
-	tx = -(gyt + gxt);
+	tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); // sideways distance
 
 	// too far off the side?
 	if (abs(tx) > tz<<2)

From c8320b6c9dad1996a96557858c00e1f5f9f9a4c9 Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Tue, 19 May 2020 16:58:53 +0100
Subject: [PATCH 2/8] split "rot" into two variables: frame and rot, for frame
 number and rotation angle

it always bothered me that "rot" was used for both of the above, since it confused me as to what it was for every time I look at this function
---
 src/r_things.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/r_things.c b/src/r_things.c
index febb5b6dc..cd19dfa90 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -1358,7 +1358,7 @@ static void R_ProjectSprite(mobj_t *thing)
 #endif
 	size_t lump;
 
-	size_t rot;
+	size_t frame, rot;
 	UINT16 flip;
 	boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !(thing->frame & FF_VERTICALFLIP));
 
@@ -1420,7 +1420,7 @@ static void R_ProjectSprite(mobj_t *thing)
 		I_Error("R_ProjectSprite: invalid sprite number %d ", thing->sprite);
 #endif
 
-	rot = thing->frame&FF_FRAMEMASK;
+	frame = thing->frame&FF_FRAMEMASK;
 
 	//Fab : 02-08-98: 'skin' override spritedef currently used for skin
 	if (thing->skin && thing->sprite == SPR_PLAY)
@@ -1429,15 +1429,15 @@ static void R_ProjectSprite(mobj_t *thing)
 #ifdef ROTSPRITE
 		sprinfo = &((skin_t *)thing->skin)->sprinfo[thing->sprite2];
 #endif
-		if (rot >= sprdef->numframes) {
-			CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid skins[\"%s\"].sprites[%sSPR2_%s] frame %s\n"), ((skin_t *)thing->skin)->name, ((thing->sprite2 & FF_SPR2SUPER) ? "FF_SPR2SUPER|": ""), spr2names[(thing->sprite2 & ~FF_SPR2SUPER)], sizeu5(rot));
+		if (frame >= sprdef->numframes) {
+			CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid skins[\"%s\"].sprites[%sSPR2_%s] frame %s\n"), ((skin_t *)thing->skin)->name, ((thing->sprite2 & FF_SPR2SUPER) ? "FF_SPR2SUPER|": ""), spr2names[(thing->sprite2 & ~FF_SPR2SUPER)], sizeu5(frame));
 			thing->sprite = states[S_UNKNOWN].sprite;
 			thing->frame = states[S_UNKNOWN].frame;
 			sprdef = &sprites[thing->sprite];
 #ifdef ROTSPRITE
 			sprinfo = NULL;
 #endif
-			rot = thing->frame&FF_FRAMEMASK;
+			frame = thing->frame&FF_FRAMEMASK;
 		}
 	}
 	else
@@ -1447,10 +1447,10 @@ static void R_ProjectSprite(mobj_t *thing)
 		sprinfo = NULL;
 #endif
 
-		if (rot >= sprdef->numframes)
+		if (frame >= sprdef->numframes)
 		{
 			CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid sprite frame %s/%s for %s\n"),
-				sizeu1(rot), sizeu2(sprdef->numframes), sprnames[thing->sprite]);
+				sizeu1(frame), sizeu2(sprdef->numframes), sprnames[thing->sprite]);
 			if (thing->sprite == thing->state->sprite && thing->frame == thing->state->frame)
 			{
 				thing->state->sprite = states[S_UNKNOWN].sprite;
@@ -1459,11 +1459,11 @@ static void R_ProjectSprite(mobj_t *thing)
 			thing->sprite = states[S_UNKNOWN].sprite;
 			thing->frame = states[S_UNKNOWN].frame;
 			sprdef = &sprites[thing->sprite];
-			rot = thing->frame&FF_FRAMEMASK;
+			frame = thing->frame&FF_FRAMEMASK;
 		}
 	}
 
-	sprframe = &sprdef->spriteframes[rot];
+	sprframe = &sprdef->spriteframes[frame];
 
 #ifdef PARANOIA
 	if (!sprframe)
@@ -1517,7 +1517,7 @@ static void R_ProjectSprite(mobj_t *thing)
 	{
 		rollangle = R_GetRollAngle(thing->rollangle);
 		if (!(sprframe->rotsprite.cached & (1<<rot)))
-			R_CacheRotSprite(thing->sprite, (thing->frame & FF_FRAMEMASK), sprinfo, sprframe, rot, flip);
+			R_CacheRotSprite(thing->sprite, frame, sprinfo, sprframe, rot, flip);
 		rotsprite = sprframe->rotsprite.patch[rot][rollangle];
 		if (rotsprite != NULL)
 		{

From 1a790235c69833f31e915586b6358c501ef87c20 Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Tue, 19 May 2020 17:19:44 +0100
Subject: [PATCH 3/8] added basic culling of papersprites if tx for either is
 too large, proper clamping to be added later

also removed some commented out old code
---
 src/r_things.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/r_things.c b/src/r_things.c
index cd19dfa90..27a7c0bb6 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -1557,7 +1557,6 @@ static void R_ProjectSprite(mobj_t *thing)
 		tr_y += FixedMul(offset, sinmul);
 		tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin);
 		yscale = FixedDiv(projectiony, tz);
-		//if (yscale < 64) return; // Fix some funky visuals
 
 		tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos);
 		xscale = FixedDiv(projection, tz);
@@ -1577,7 +1576,6 @@ static void R_ProjectSprite(mobj_t *thing)
 		tr_y += FixedMul(offset2, sinmul);
 		tz2 = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin);
 		yscale2 = FixedDiv(projectiony, tz2);
-		//if (yscale2 < 64) return; // ditto
 
 		tx2 = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos);
 		xscale2 = FixedDiv(projection, tz2);
@@ -1586,6 +1584,9 @@ static void R_ProjectSprite(mobj_t *thing)
 		if (max(tz, tz2) < FixedMul(MINZ, this_scale)) // non-papersprite clipping is handled earlier
 			return;
 
+		if (tx2 < -(tz2<<2) || tx > tz<<2) // too far off the side?
+			return;
+
 		// Needs partially clipped
 		if (tz < FixedMul(MINZ, this_scale))
 		{
@@ -1606,6 +1607,8 @@ static void R_ProjectSprite(mobj_t *thing)
 			x2 = (centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS;
 		}
 
+		// TODO: tx clamping
+
 		// off the right side?
 		if (x1 > viewwidth)
 			return;

From 12e109414384ab80c702382a7fa2549c6eec26a1 Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Tue, 19 May 2020 17:23:22 +0100
Subject: [PATCH 4/8] We don't actually need x1 or x2 until these points in the
 function, at least for papersprites

---
 src/r_things.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/r_things.c b/src/r_things.c
index 27a7c0bb6..a4bd19627 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -1560,7 +1560,6 @@ static void R_ProjectSprite(mobj_t *thing)
 
 		tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos);
 		xscale = FixedDiv(projection, tz);
-		x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS;
 
 		// Get paperoffset (offset) and paperoffset (distance)
 		paperoffset = -FixedMul(tr_x, cosmul) - FixedMul(tr_y, sinmul);
@@ -1579,7 +1578,6 @@ static void R_ProjectSprite(mobj_t *thing)
 
 		tx2 = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos);
 		xscale2 = FixedDiv(projection, tz2);
-		x2 = ((centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS);
 
 		if (max(tz, tz2) < FixedMul(MINZ, this_scale)) // non-papersprite clipping is handled earlier
 			return;
@@ -1595,7 +1593,6 @@ static void R_ProjectSprite(mobj_t *thing)
 			tz = FixedMul(MINZ, this_scale);
 			yscale = FixedDiv(projectiony, tz);
 			xscale = FixedDiv(projection, tz);
-			x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS;
 		}
 		else if (tz2 < FixedMul(MINZ, this_scale))
 		{
@@ -1604,15 +1601,18 @@ static void R_ProjectSprite(mobj_t *thing)
 			tz2 = FixedMul(MINZ, this_scale);
 			yscale2 = FixedDiv(projectiony, tz2);
 			xscale2 = FixedDiv(projection, tz2);
-			x2 = (centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS;
 		}
 
 		// TODO: tx clamping
 
+		x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS;
+
 		// off the right side?
 		if (x1 > viewwidth)
 			return;
 
+		x2 = (centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS;
+
 		// off the left side
 		if (x2 < 0)
 			return;

From 35e5d673e08485e685a0f7660397348f81e2982d Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Tue, 19 May 2020 18:43:33 +0100
Subject: [PATCH 5/8] do tx checking after tz clamping, not before

---
 src/r_things.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/r_things.c b/src/r_things.c
index a4bd19627..6bdb7cae8 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -1582,9 +1582,6 @@ static void R_ProjectSprite(mobj_t *thing)
 		if (max(tz, tz2) < FixedMul(MINZ, this_scale)) // non-papersprite clipping is handled earlier
 			return;
 
-		if (tx2 < -(tz2<<2) || tx > tz<<2) // too far off the side?
-			return;
-
 		// Needs partially clipped
 		if (tz < FixedMul(MINZ, this_scale))
 		{
@@ -1603,6 +1600,9 @@ static void R_ProjectSprite(mobj_t *thing)
 			xscale2 = FixedDiv(projection, tz2);
 		}
 
+		if (tx2 < -(tz2<<2) || tx > tz<<2) // too far off the side?
+			return;
+
 		// TODO: tx clamping
 
 		x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS;

From 65d6b04fd283a76bc505b1aab81abe3583038ea3 Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Tue, 19 May 2020 18:54:39 +0100
Subject: [PATCH 6/8] change limits for tx based on fov, by multiplying by
 fovtan

this makes it so that higher fov values can actually let you see all the sprites that should be in the view
---
 src/r_things.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/r_things.c b/src/r_things.c
index 6bdb7cae8..a29fb6cb7 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -1407,7 +1407,7 @@ static void R_ProjectSprite(mobj_t *thing)
 	basetx = tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); // sideways distance
 
 	// too far off the side?
-	if (!papersprite && abs(tx) > tz<<2) // papersprite clipping is handled later
+	if (!papersprite && abs(tx) > FixedMul(tz, fovtan)<<2) // papersprite clipping is handled later
 		return;
 
 	// aspect ratio stuff
@@ -1600,7 +1600,7 @@ static void R_ProjectSprite(mobj_t *thing)
 			xscale2 = FixedDiv(projection, tz2);
 		}
 
-		if (tx2 < -(tz2<<2) || tx > tz<<2) // too far off the side?
+		if (tx2 < -(FixedMul(tz2, fovtan)<<2) || tx > FixedMul(tz, fovtan)<<2) // too far off the side?
 			return;
 
 		// TODO: tx clamping

From c3d576058a2f59833026a3ef6fd1a9c35524c5ab Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Tue, 19 May 2020 22:00:34 +0100
Subject: [PATCH 7/8] on second thought maybe we don't need extra tx clamping,
 it turns out to be more effort than it's worth (at least for now)

meanwhile, let's move x/yscale calculations down since we don't actually need them until later on
---
 src/r_things.c | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/src/r_things.c b/src/r_things.c
index a29fb6cb7..a40c61058 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -1556,10 +1556,8 @@ static void R_ProjectSprite(mobj_t *thing)
 		tr_x += FixedMul(offset, cosmul);
 		tr_y += FixedMul(offset, sinmul);
 		tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin);
-		yscale = FixedDiv(projectiony, tz);
 
 		tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos);
-		xscale = FixedDiv(projection, tz);
 
 		// Get paperoffset (offset) and paperoffset (distance)
 		paperoffset = -FixedMul(tr_x, cosmul) - FixedMul(tr_y, sinmul);
@@ -1574,10 +1572,8 @@ static void R_ProjectSprite(mobj_t *thing)
 		tr_x += FixedMul(offset2, cosmul);
 		tr_y += FixedMul(offset2, sinmul);
 		tz2 = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin);
-		yscale2 = FixedDiv(projectiony, tz2);
 
 		tx2 = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos);
-		xscale2 = FixedDiv(projection, tz2);
 
 		if (max(tz, tz2) < FixedMul(MINZ, this_scale)) // non-papersprite clipping is handled earlier
 			return;
@@ -1588,22 +1584,19 @@ static void R_ProjectSprite(mobj_t *thing)
 			fixed_t div = FixedDiv(tz2-tz, FixedMul(MINZ, this_scale)-tz);
 			tx += FixedDiv(tx2-tx, div);
 			tz = FixedMul(MINZ, this_scale);
-			yscale = FixedDiv(projectiony, tz);
-			xscale = FixedDiv(projection, tz);
 		}
 		else if (tz2 < FixedMul(MINZ, this_scale))
 		{
 			fixed_t div = FixedDiv(tz-tz2, FixedMul(MINZ, this_scale)-tz2);
 			tx2 += FixedDiv(tx-tx2, div);
 			tz2 = FixedMul(MINZ, this_scale);
-			yscale2 = FixedDiv(projectiony, tz2);
-			xscale2 = FixedDiv(projection, tz2);
 		}
 
 		if (tx2 < -(FixedMul(tz2, fovtan)<<2) || tx > FixedMul(tz, fovtan)<<2) // too far off the side?
 			return;
 
-		// TODO: tx clamping
+		yscale = FixedDiv(projectiony, tz);
+		xscale = FixedDiv(projection, tz);
 
 		x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS;
 
@@ -1611,6 +1604,9 @@ static void R_ProjectSprite(mobj_t *thing)
 		if (x1 > viewwidth)
 			return;
 
+		yscale2 = FixedDiv(projectiony, tz2);
+		xscale2 = FixedDiv(projection, tz2);
+
 		x2 = (centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS;
 
 		// off the left side

From 702a7041d4e7f3274e6c05347e72c8bc0952cf1d Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Wed, 20 May 2020 19:34:18 +0100
Subject: [PATCH 8/8] also do the fovtan multiplication thing with precip
 sprites

---
 src/r_things.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/r_things.c b/src/r_things.c
index a40c61058..14782d0c2 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -1884,7 +1884,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
 	tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); // sideways distance
 
 	// too far off the side?
-	if (abs(tx) > tz<<2)
+	if (abs(tx) > FixedMul(tz, fovtan)<<2)
 		return;
 
 	// aspect ratio stuff :