diff --git a/source/build/include/build.h b/source/build/include/build.h index a6fe2f90d..4d3472526 100644 --- a/source/build/include/build.h +++ b/source/build/include/build.h @@ -149,28 +149,6 @@ int32_t try_facespr_intersect(DCoreActor* spr, vec3_t const in, int32_t vx, int32_t vy, int32_t vz, vec3_t * const intp, int32_t strictly_smaller_than_p); -#define MAXUPDATESECTORDIST 1536 -#define INITIALUPDATESECTORDIST 512 // was 256 which is too low - Exhumed LEV1 has problems with it -void updatesector(int const x, int const y, int * const sectnum) ATTRIBUTE((nonnull(3))); -inline void updatesector(int const x, int const y, sectortype** const sectp) -{ - int sectno = *sectp? sector.IndexOf(*sectp) : -1; - updatesector(x, y, §no); - *sectp = sectno == -1? nullptr : §or[sectno]; -} -void updatesectorz(int32_t const x, int32_t const y, int32_t const z, int * const sectnum) ATTRIBUTE((nonnull(4))); - -inline void updatesectorz(int32_t const x, int32_t const y, int32_t const z, sectortype** const sectp) -{ - int sectno = *sectp ? sector.IndexOf(*sectp) : -1; - updatesectorz(x, y, z, §no); - *sectp = sectno == -1 ? nullptr : §or[sectno]; -} - - - -void updatesectorneighbor(int32_t const x, int32_t const y, int * const sectnum, int32_t maxDistance = MAXUPDATESECTORDIST) ATTRIBUTE((nonnull(3))); - extern const int16_t *chsecptr_onextwall; diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index 71272b3e3..c46fb8934 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -449,106 +449,6 @@ void neartag(const vec3_t& sv, sectortype* sect, int ange, HitInfoBase& result, } -////////// UPDATESECTOR* FAMILY OF FUNCTIONS ////////// - -/* Different "is inside" predicates. - * NOTE: The redundant bound checks are expected to be optimized away in the - * inlined code. */ - -/* NOTE: no bound check */ -static inline int inside_z_p(int32_t const x, int32_t const y, int32_t const z, int const sectnum) -{ - int32_t cz, fz; - getzsofslopeptr(§or[sectnum], x, y, &cz, &fz); - return (z >= cz && z <= fz && inside_p(x, y, sectnum)); -} - -int32_t getwalldist(vec2_t const in, int const wallnum, vec2_t * const out) -{ - auto dvec = NearestPointOnWall(in.X * maptoworld, in.Y * maptoworld, &wall[wallnum]); - *out = { int(dvec.X * worldtoint), int(dvec.Y * worldtoint) }; - return abs(out->X - in.X) + abs(out->Y - in.Y); -} - - -template -void updatesectorneighborz(int32_t const x, int32_t const y, int32_t const z, int* const sectnum, int32_t maxDistance, Inside checker) -{ - int const initialsectnum = *sectnum; - double maxDist = maxDistance * inttoworld; maxDist *= maxDist; - - if ((validSectorIndex(initialsectnum))) - { - if (checker(x, y, z, initialsectnum)) - return; - - BFSSearch search(sector.Size(), *sectnum); - - int iter = 0; - for (unsigned listsectnum; (listsectnum = search.GetNext()) != BFSSearch::EOL;) - { - if (checker(x, y, z, listsectnum)) - { - *sectnum = listsectnum; - return; - } - - for (auto& wal : wallsofsector(listsectnum)) - { - if (wal.nextsector >= 0 && (iter == 0 || SquareDistToSector(x * inttoworld, y * inttoworld, wal.nextSector()) <= maxDist)) - search.Add(wal.nextsector); - } - iter++; - } - } - - *sectnum = -1; -} - -void updatesectorneighbor(int32_t const x, int32_t const y, int* const sectnum, int32_t maxDistance) -{ - updatesectorneighborz(x, y, 0, sectnum, maxDistance, inside_p0); -} - - -// -// updatesector[z] -// -void updatesector(int32_t const x, int32_t const y, int * const sectnum) -{ - int sect = *sectnum; - - updatesectorneighbor(x, y, §, MAXUPDATESECTORDIST); - if (sect != -1) - SET_AND_RETURN(*sectnum, sect); - - // we need to support passing in a sectnum of -1, unfortunately - - for (int i = (int)sector.Size() - 1; i >= 0; --i) - if (inside_p(x, y, i)) - SET_AND_RETURN(*sectnum, i); - - *sectnum = -1; -} - - -void updatesectorz(int32_t const x, int32_t const y, int32_t const z, int* const sectnum) -{ - int sect = *sectnum; - - updatesectorneighborz(x, y, z, §, MAXUPDATESECTORDIST, inside_z_p); - if (sect != -1) - SET_AND_RETURN(*sectnum, sect); - - - // we need to support passing in a sectnum of -1, unfortunately - for (int i = (int)sector.Size() - 1; i >= 0; --i) - if (inside_z_p(x, y, z, i)) - SET_AND_RETURN(*sectnum, i); - - *sectnum = -1; -} - // // rotatepoint diff --git a/source/core/gamefuncs.cpp b/source/core/gamefuncs.cpp index c9703ed25..84a77685d 100644 --- a/source/core/gamefuncs.cpp +++ b/source/core/gamefuncs.cpp @@ -181,7 +181,7 @@ void calcSlope(const sectortype* sec, float xpos, float ypos, float* pceilz, flo //========================================================================== // -// for the renderer (Polymost variants are in polymost.cpp) +// for the renderer // //========================================================================== @@ -220,6 +220,14 @@ void getzsofslopeptr(const sectortype* sec, int dax, int day, int* ceilz, int* f *florz = int(f); } +void getzsofslopeptr(const sectortype* sec, double dax, double day, double* ceilz, double* florz) +{ + float c, f; + calcSlope(sec, dax * worldtoint, day * worldtoint, &c, &f); + *ceilz = c * zinttoworld; + *florz = f * zinttoworld; +} + void getcorrectzsofslope(int sectnum, int dax, int day, int* ceilz, int* florz) { DVector2 closestv; diff --git a/source/core/gamefuncs.h b/source/core/gamefuncs.h index fbfdfd62c..c5cfc03bd 100644 --- a/source/core/gamefuncs.h +++ b/source/core/gamefuncs.h @@ -178,6 +178,7 @@ void getcorrectzsofslope(int sectnum, int dax, int day, int* ceilz, int* florz); int getceilzofslopeptr(const sectortype* sec, int dax, int day); int getflorzofslopeptr(const sectortype* sec, int dax, int day); void getzsofslopeptr(const sectortype* sec, int dax, int day, int* ceilz, int* florz); +void getzsofslopeptr(const sectortype* sec, double dax, double day, double* ceilz, double* florz); // y is negated so that the orientation is the same as in GZDoom, in order to use its utilities. @@ -316,8 +317,6 @@ inline int inside(int x, int y, const sectortype* sect) // still needed by some parts in the engine. inline int inside_p(int x, int y, int sectnum) { return (sectnum >= 0 && inside(x, y, §or[sectnum]) == 1); } -// this one is for template substitution. -inline int inside_p0(int32_t const x, int32_t const y, int32_t const z, int const sectnum) { return inside_p(x, y, sectnum); } @@ -428,9 +427,5 @@ inline void alignflorslope(sectortype* sect, int x, int y, int z) { sect->setfloorslope(getslopeval(sect, x, y, z, sect->floorz)); } -inline void updatesectorneighbor(int32_t const x, int32_t const y, sectortype* * const sect, int32_t maxDistance = MAXUPDATESECTORDIST) -{ - int sectno = *sect? sector.IndexOf(*sect) : -1; - updatesectorneighbor(x, y, §no, maxDistance); - *sect = sectno < 0? nullptr : §or[sectno]; -} + +#include "updatesector.h" diff --git a/source/core/updatesector.h b/source/core/updatesector.h new file mode 100644 index 000000000..460072cea --- /dev/null +++ b/source/core/updatesector.h @@ -0,0 +1,125 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 2022 Christoph Oelckers + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +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. + + +// checker functions for updatesector's template parameter. +inline int inside0(double x, double y, double z, const sectortype* sect) +{ + return inside(x, y, sect); +} + +inline int insideZ(double x, double y, double z, const sectortype* sect) +{ + double cz, fz; + getzsofslopeptr(sect, x, y, &cz, &fz); + return (z >= cz && z <= fz && inside(x, y, sect) != 0); +} + +template +void DoUpdateSector(double x, double y, double z, int* sectnum, double maxDistance, Inside checker) +{ + double maxDistSq = maxDistance * maxDistance; + + if (sectnum) + { + if (checker(x, y, z, §or[*sectnum])) + return; + + BFSSearch search(sector.Size(), *sectnum); + + int iter = 0; + for (unsigned listsectnum; (listsectnum = search.GetNext()) != BFSSearch::EOL;) + { + auto lsect = §or[listsectnum]; + if (checker(x, y, z, lsect)) + { + *sectnum = listsectnum; + return; + } + + for (auto& wal : wallsofsector(lsect)) + { + if (wal.nextsector >= 0 && !search.Check(wal.nextsector) && (iter == 0 || SquareDistToSector(x, y, wal.nextSector()) <= maxDistSq)) + search.Add(wal.nextsector); + } + iter++; + } + *sectnum = -1; + } +} + +template +int FindSector(double x, double y, double z, Inside checker) +{ + for (int i = (int)sector.Size() - 1; i >= 0; i--) + if (checker(x, y, z, §or[i])) + { + return i; + } + return -1; +} + + +constexpr int MAXUPDATESECTORDIST = 1536; + +inline void updatesector(int x_, int y_, int* sectnum) +{ + double x = x_ * inttoworld; + double y = y_ * inttoworld; + + DoUpdateSector(x, y, 0, sectnum, MAXUPDATESECTORDIST * inttoworld, inside0); + if (*sectnum == -1) *sectnum = FindSector(x, y, 0, inside0); +} + +inline void updatesectorz(int x_, int y_, int z_, int* sectnum) +{ + double x = x_ * inttoworld; + double y = y_ * inttoworld; + double z = z_ * zinttoworld; + + DoUpdateSector(x, y, z, sectnum, MAXUPDATESECTORDIST * inttoworld, insideZ); + if (*sectnum == -1) *sectnum = FindSector(x, y, z, insideZ); +} + +inline void updatesector(int const x, int const y, sectortype** const sectp) +{ + int sectno = *sectp? sector.IndexOf(*sectp) : -1; + updatesector(x, y, §no); + *sectp = sectno == -1? nullptr : §or[sectno]; +} + +inline void updatesectorz(int x, int y, int z, sectortype** const sectp) +{ + int sectno = *sectp ? sector.IndexOf(*sectp) : -1; + updatesectorz(x, y, z, §no); + *sectp = sectno == -1 ? nullptr : §or[sectno]; +} + +inline void updatesectorneighbor(int x, int y, sectortype** const sect, int maxDistance = MAXUPDATESECTORDIST) +{ + int sectno = *sect? sector.IndexOf(*sect) : -1; + DoUpdateSector(x * inttoworld, y * inttoworld, 0, §no, maxDistance * inttoworld, inside0); + *sect = sectno < 0? nullptr : §or[sectno]; +}