diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index 9a99ad9db..57fea10ab 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -697,46 +697,6 @@ 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, int16_t 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 09fab5765..9acf67319 100644 --- a/source/core/gamefuncs.cpp +++ b/source/core/gamefuncs.cpp @@ -148,6 +148,48 @@ 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!