- redid the 'inside' function.

This is based on external information and does not use any of the original Build code.
Despite being a lot clearer than Build's bit masking voodoo and using 64 bit math to avoid overflows it is roughly 10% faster. :)

Code was moved to gamefuncs.cpp because this no longer falls under the Build license.
This commit is contained in:
Christoph Oelckers 2021-11-08 20:24:49 +01:00
parent 5cfc418c5f
commit c034c2a299
2 changed files with 42 additions and 40 deletions

View file

@ -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)

View file

@ -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!