From 5ba005276f1c99bbd9b818d773f2a57d1b29c814 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 8 Nov 2021 23:07:56 +0100 Subject: [PATCH] Revert "- redid the 'inside' function." This reverts commit c034c2a299b18f364493593b1e67a4b7470c0c88. While the function works, it is subtly different for points exactly on a line - enough to cause problems with Shadow Warrior's waypoint implementation. --- source/build/src/engine.cpp | 40 +++++++++++++++++++++++++++++++++++ source/core/gamefuncs.cpp | 42 ------------------------------------- 2 files changed, 40 insertions(+), 42 deletions(-) diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index 57fea10ab..9dcda73d1 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -697,6 +697,46 @@ void initspritelists(void) Numsprites = 0; } +// +// inside +// +// See http://fabiensanglard.net/duke3d/build_engine_internals.php, +// "Inside details" for the idea behind the algorithm. + +int32_t inside(int32_t x, int32_t y, int sectnum) +{ + if (validSectorIndex(sectnum)) + { + uint32_t cnt = 0; + auto wal = (uwallptr_t)&wall[sector[sectnum].wallptr]; + int wallsleft = sector[sectnum].wallnum; + + do + { + // Get the x and y components of the [tested point]-->[wall + // point{1,2}] vectors. + vec2_t v1 = { wal->x - x, wal->y - y }; + auto const &wal2 = *(uwallptr_t)&wall[wal->point2]; + vec2_t v2 = { wal2.x - x, wal2.y - y }; + + // If their signs differ[*], ... + // + // [*] where '-' corresponds to <0 and '+' corresponds to >=0. + // Equivalently, the branch is taken iff + // y1 != y2 AND y_m <= y < y_M, + // where y_m := min(y1, y2) and y_M := max(y1, y2). + if ((v1.y^v2.y) < 0) + cnt ^= (((v1.x^v2.x) >= 0) ? v1.x : (v1.x*v2.y-v2.x*v1.y)^v2.y); + + wal++; + } + while (--wallsleft); + + return cnt>>31; + } + + return -1; +} int32_t getangle(int32_t xvect, int32_t yvect) diff --git a/source/core/gamefuncs.cpp b/source/core/gamefuncs.cpp index 9acf67319..09fab5765 100644 --- a/source/core/gamefuncs.cpp +++ b/source/core/gamefuncs.cpp @@ -148,48 +148,6 @@ bool calcChaseCamPos(int* px, int* py, int* pz, spritetype* pspr, int *psectnum, return true; } - -//========================================================================== -// -// checks if a point is within a given sector -// -// Completely redone based on outside information. -// The math in here is based on this article: https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html -// Copyright (c) 1970-2003, Wm. Randolph Franklin , licensed under BSD 3-clause -// but was transformed to avoid the division it contained and to properly pick the vertices of Build walls. -// -//========================================================================== - -int inside(int x, int y, int sectnum) -{ - if (validSectorIndex(sectnum)) - { - bool c = false; - for (auto& wal : wallsofsector(sectnum)) - { - auto& pt1 = wal.pos; - auto& pt2 = wal.point2Wall()->pos; - - if ((pt1.y > y) != (pt2.y > y)) // skip if both are on the same side. - { - // use 64 bit values to avoid overflows in the multiplications below. - int64_t deltatx = int64_t(x) - pt1.x; - int64_t deltaty = int64_t(y) - pt1.y; - int64_t deltax = int64_t(pt2.x) - pt1.x; - int64_t deltay = int64_t(pt2.y) - pt1.y; - // reformatted to avoid the division - for negative deltay the sign needs to be flipped to give the correct result. - //if (x < deltax * (deltaty) / deltay + pt1.x) // this was the original code. - if (((deltay * deltatx - deltax * deltaty) ^ deltay) < 0) - { - c = !c; - } - } - } - return int(c); - } - return -1; -} - //========================================================================== // // note that this returns values in renderer coordinate space with inverted sign!