From 12c26976f02604ecdaf871da6df4b6d07a5c4267 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 16 Nov 2021 21:36:46 +0100 Subject: [PATCH] - GetClosestSpriteSectors: replace distance calculation with proper math. No need to sample multiple points along the wall if we can just properly calculate the actual distance. :) --- source/core/gamefuncs.h | 23 +++++++++++++++++++++ source/games/blood/src/gameutil.cpp | 32 ++++------------------------- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/source/core/gamefuncs.h b/source/core/gamefuncs.h index 96bd5a33b..c2dd85787 100644 --- a/source/core/gamefuncs.h +++ b/source/core/gamefuncs.h @@ -251,3 +251,26 @@ inline int sectnum(sectortype* sect) return int(sect - sector); } +inline double SquareDist(double lx1, double ly1, double lx2, double ly2) +{ + double dx = lx2 - lx1; + double dy = ly2 - ly1; + return dx * dx + dy * dy; +} + +inline double SquareDistToWall(double px, double py, const walltype* wal) +{ + double lx1 = wal->x; + double ly1 = wal->y; + double lx2 = wal->point2Wall()->x; + double ly2 = wal->point2Wall()->y; + + double wall_length = SquareDist(lx1, ly1, lx2, ly2); + + if (wall_length == 0) return SquareDist(px, py, lx1, ly1); + + double t = ((px - lx1) * (lx2 - lx1) + (py - ly1) * (ly2 - ly1)) / wall_length; + t = clamp(t, 0., 1.); + return SquareDist(px, py, lx1 + t * (lx2 - lx1), ly1 + t * (ly2 - ly1)); +} + diff --git a/source/games/blood/src/gameutil.cpp b/source/games/blood/src/gameutil.cpp index c66a6c728..56d962b7b 100644 --- a/source/games/blood/src/gameutil.cpp +++ b/source/games/blood/src/gameutil.cpp @@ -761,6 +761,7 @@ BitArray GetClosestSpriteSectors(int nSector, int x, int y, int nDist, TArrayx, y2 = wal.point2Wall()->y; - int point1Dist = approxDist(x - x1, y - y1); // setup edge distance needed for below loop (determines which point to shift closer to center) - int point2Dist = approxDist(x - x2, y - y2); - int nLength = approxDist(x1 - x2, y1 - y2); - const int nDist4 = nDist << 4; - nLength = ClipRange(nLength / (nDist4 + (nDist4 >> 1)), 1, 4); // always test midpoint at least once, and never split more than 4 times - for (int k = 0; true; k++) // check both points of wall and subdivide span into smaller chunks towards target - { - withinRange = (point1Dist < nDist4) || (point2Dist < nDist4); // check if both points of span is within radius - if (withinRange) - break; - if (k == nLength) // reached end - break; - const int xcenter = (x1 + x2) >> 1, ycenter = (y1 + y2) >> 1; - if (point1Dist < point2Dist) // shift closest side of wall towards target point, and refresh point distance values - { - x2 = xcenter, y2 = ycenter; - point2Dist = approxDist(x - x2, y - y2); - } - else - { - x1 = xcenter, y1 = ycenter; - point1Dist = approxDist(x - x1, y - y1); - } - } + double dist1 = SquareDistToWall(x, y, &wal); + withinRange = dist1 <= nDist4sq; } if (withinRange) // if new sector is within range, add it to the processing queue {