diff --git a/source/build/src/clip.cpp b/source/build/src/clip.cpp index a754dd338..b37801337 100644 --- a/source/build/src/clip.cpp +++ b/source/build/src/clip.cpp @@ -263,58 +263,6 @@ static int32_t getwalldist(vec2_t const in, int const wallnum) return abs(closest.X - in.X) + abs(closest.Y - in.Y); } -static void clipupdatesector(vec2_t const pos, int * const sectnum, int walldist) -{ - if (inside_p(pos.X, pos.Y, *sectnum)) - return; - - double nsecs = SquareDistToSector(pos.X * inttoworld, pos.Y * inttoworld, §or[*sectnum]); - - double wd = (walldist + 8) * inttoworld; wd *= wd; - if (nsecs > wd) - { - walldist = 0x7fff; - } - - { - BFSSearch search(sector.Size(), *sectnum); - - for (unsigned listsectnum; (listsectnum = search.GetNext()) != BFSSearch::EOL;) - { - if (inside_p(pos.X, pos.Y, listsectnum)) - { - *sectnum = listsectnum; - return; - } - - for (auto& wal : wallsofsector(listsectnum)) - { - if (wal.nextsector >= 0 && clipsectormap[wal.nextsector]) - search.Add(wal.nextsector); - } - } - } - - { - BFSSearch search(sector.Size(), *sectnum); - - for (unsigned listsectnum; (listsectnum = search.GetNext()) != BFSSearch::EOL;) - { - if (inside_p(pos.X, pos.Y, listsectnum)) - { - *sectnum = listsectnum; - return; - } - for (auto& wal : wallsofsector(listsectnum)) - { - if (wal.nextsector >= 0 && getwalldist(pos, wallnum(&wal)) <= (walldist + 8)) - search.Add(wal.nextsector); - } - } - } - - *sectnum = -1; -} // // clipmove @@ -705,7 +653,8 @@ CollisionBase clipmove_(vec3_t * const pos, int * const sectnum, int32_t xvect, if (enginecompatibility_mode == ENGINECOMPATIBILITY_NONE) { - clipupdatesector(vec, sectnum, rad); + DVector2 v(vec.X* inttoworld, vec.Y* inttoworld); + clipupdatesector(v, sectnum, rad * inttoworld, clipsectormap); } pos->X = vec.X; @@ -841,7 +790,10 @@ int pushmove_(vec3_t *const vect, int *const sectnum, } while (IsCloseToWall(DVector2(vect->X * inttoworld, vect->Y * inttoworld), &wall[i], (walldist - 4) * inttoworld) != EClose::Outside); bad = -1; k--; if (k <= 0) return bad; - clipupdatesector(vect->vec2, sectnum, walldist); + + DVector2 v(vect->vec2.X * inttoworld, vect->vec2.Y * inttoworld); + clipupdatesector(v, sectnum, walldist * inttoworld, clipsectormap); + if (*sectnum < 0) return -1; } else if (!clipsectormap[wal->nextsector]) diff --git a/source/core/updatesector.h b/source/core/updatesector.h index 309f47305..549ac7537 100644 --- a/source/core/updatesector.h +++ b/source/core/updatesector.h @@ -20,8 +20,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ //------------------------------------------------------------------------- // -// updatesector utilities. Uses a breadth-first algorithm similar -// but not identical to EDuke32's updatesectorneighbor. +// updatesector utilities. Reimplementations of EDuke32's checks with +// proper C++ classes. (Original Build updatesector is insufficient and broken) // checker functions for updatesector's template parameter. @@ -50,18 +50,18 @@ void DoUpdateSector(double x, double y, double z, int* sectnum, double maxDistan BFSSearch search(sector.Size(), *sectnum); int iter = 0; - for (unsigned listsectnum; (listsectnum = search.GetNext()) != BFSSearch::EOL;) + for (unsigned secnum; (secnum = search.GetNext()) != BFSSearch::EOL;) { - auto lsect = §or[listsectnum]; + auto lsect = §or[secnum]; if (checker(x, y, z, lsect)) { - *sectnum = listsectnum; + *sectnum = secnum; return; } for (auto& wal : wallsofsector(lsect)) { - if (wal.nextsector >= 0 && !search.Check(wal.nextsector) && (iter == 0 || SquareDistToSector(x, y, wal.nextSector()) <= maxDistSq)) + if (wal.twoSided() && !search.Check(wal.nextsector) && (iter == 0 || SquareDistToSector(x, y, wal.nextSector()) <= maxDistSq)) search.Add(wal.nextsector); } iter++; @@ -118,3 +118,59 @@ inline void updatesector(int x_, int y_, int* sectnum) DoUpdateSector(x, y, 0, sectnum, MAXUPDATESECTORDIST, inside0); } +// clipmove uses this. It's really just two loops nearly identical to DoUpdateSector with different checking conditions. +inline void clipupdatesector(const DVector2& pos, int* const sectnum, double walldist, BitArray& sectormap) +{ + assert(*sectnum >= 0); + sectortype* sect = §or[*sectnum]; + if (inside(pos.X, pos.Y, sect)) + return; + + double sdist = SquareDistToSector(pos.X, pos.Y, sect); + + double wd = (walldist + 8); + wd *= wd; + if (sdist > wd) + { + wd = 2048 * 2048; + } + + { + BFSSearch search(sector.Size(), *sectnum); + + for (unsigned secnum; (secnum = search.GetNext()) != BFSSearch::EOL;) + { + if (inside(pos.X, pos.Y, §or[secnum])) + { + *sectnum = secnum; + return; + } + + for (auto& wal : wallsofsector(secnum)) + { + if (wal.twoSided() && sectormap[wal.nextsector]) + search.Add(wal.nextsector); + } + } + } + + { + BFSSearch search(sector.Size(), *sectnum); + + for (unsigned secnum; (secnum = search.GetNext()) != BFSSearch::EOL;) + { + if (inside(pos.X, pos.Y, §or[secnum])) + { + *sectnum = secnum; + return; + } + for (auto& wal : wallsofsector(secnum)) + { + if (wal.twoSided() && SquareDistToWall(pos.X, pos.Y, &wal) < wd) + search.Add(wal.nextsector); + } + } + } + + *sectnum = -1; +}