From 64cad55d73e4752c1c428f8821a2ef0ec62d6e63 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 30 Nov 2021 00:08:24 +0100 Subject: [PATCH] - fixed updatesector and changed updatesectorz to use the same search algorithm. The initial distance check in updatesectorneighbor had a far too low threshold which would skip the breadth-first search for relatively small distances already. Exhumed's LEV1 and Duke's Lunatic Fringe were the most obvious candidates where this could cause problems. Changed to use a mixture of the original updatesector with the revised algorithm so that all immediate neighbors of the start sector will get visited unconditionally. updatesectorz was still the original function from Shadow Warrior, this also was changed to use the same algorithm as uodatesector. --- source/build/include/build.h | 6 +-- source/build/src/engine.cpp | 69 ++++++++++++++++++++++-------- source/games/duke/src/actors_d.cpp | 4 +- 3 files changed, 57 insertions(+), 22 deletions(-) diff --git a/source/build/include/build.h b/source/build/include/build.h index 754128cfd..336e74551 100644 --- a/source/build/include/build.h +++ b/source/build/include/build.h @@ -439,7 +439,7 @@ int32_t try_facespr_intersect(uspriteptr_t const spr, vec3_t const in, vec3_t * const intp, int32_t strictly_smaller_than_p); #define MAXUPDATESECTORDIST 1536 -#define INITIALUPDATESECTORDIST 256 +#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) { @@ -449,8 +449,8 @@ inline void updatesector(int const x, int const y, sectortype** const sectp) } void updatesectorz(int32_t const x, int32_t const y, int32_t const z, int * const sectnum) ATTRIBUTE((nonnull(4))); -void updatesectorneighbor(int32_t const x, int32_t const y, int * const sectnum, int32_t initialMaxDistance = INITIALUPDATESECTORDIST, int32_t maxDistance = MAXUPDATESECTORDIST) ATTRIBUTE((nonnull(3))); -void updatesectorneighborz(int32_t const x, int32_t const y, int32_t const z, int * const sectnum, int32_t initialMaxDistance = INITIALUPDATESECTORDIST, int32_t maxDistance = MAXUPDATESECTORDIST) ATTRIBUTE((nonnull(4))); +void updatesectorneighbor(int32_t const x, int32_t const y, int * const sectnum, int32_t maxDistance = MAXUPDATESECTORDIST) ATTRIBUTE((nonnull(3))); +void updatesectorneighborz(int32_t const x, int32_t const y, int32_t const z, int * const sectnum, int32_t maxDistance = MAXUPDATESECTORDIST) ATTRIBUTE((nonnull(4))); int findwallbetweensectors(int sect1, int sect2); diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index 657f4e18b..61f8c0c7c 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -1184,7 +1184,8 @@ int findwallbetweensectors(int sect1, int sect2) void updatesector(int32_t const x, int32_t const y, int * const sectnum) { int sect = *sectnum; - updatesectorneighbor(x, y, §, INITIALUPDATESECTORDIST, MAXUPDATESECTORDIST); + + updatesectorneighbor(x, y, §, MAXUPDATESECTORDIST); if (sect != -1) SET_AND_RETURN(*sectnum, sect); @@ -1200,21 +1201,13 @@ void updatesector(int32_t const x, int32_t const y, int * const sectnum) void updatesectorz(int32_t const x, int32_t const y, int32_t const z, int* const sectnum) { - int32_t cz, fz; - getzsofslope(*sectnum, x, y, &cz, &fz); + int sect = *sectnum; + + updatesectorneighborz(x, y, z, §, MAXUPDATESECTORDIST); + if (sect != -1) + SET_AND_RETURN(*sectnum, sect); - walltype const * wal = &wall[sector[*sectnum].wallptr]; - int wallsleft = sector[*sectnum].wallnum; - do - { - int const next = wal->nextsector; - if (next>=0 && inside_z_p(x,y,z, next)) - SET_AND_RETURN(*sectnum, next); - wal++; - } - while (--wallsleft); - // we need to support passing in a sectnum of -1, unfortunately for (int i = numsectors - 1; i >= 0; --i) if (inside_z_p(x, y, z, i)) @@ -1223,17 +1216,18 @@ void updatesectorz(int32_t const x, int32_t const y, int32_t const z, int* const *sectnum = -1; } -void updatesectorneighbor(int32_t const x, int32_t const y, int * const sectnum, int32_t initialMaxDistance /*= INITIALUPDATESECTORDIST*/, int32_t maxDistance /*= MAXUPDATESECTORDIST*/) +void updatesectorneighbor(int32_t const x, int32_t const y, int * const sectnum, int32_t maxDistance) { int const initialsectnum = *sectnum; - if ((validSectorIndex(initialsectnum)) && getsectordist({x, y}, initialsectnum) <= initialMaxDistance) + if ((validSectorIndex(initialsectnum))) { if (inside_p(x, y, initialsectnum)) return; BFSSearch search(numsectors, *sectnum); + int iter = 0; for (unsigned listsectnum; (listsectnum = search.GetNext()) != BFSSearch::EOL;) { if (inside_p(x, y, listsectnum)) @@ -1244,9 +1238,42 @@ void updatesectorneighbor(int32_t const x, int32_t const y, int * const sectnum, for (auto& wal : wallsofsector(listsectnum)) { - if (wal.nextsector >= 0 && getsectordist({ x, y }, wal.nextsector) <= maxDistance) + if (wal.nextsector >= 0 && (iter == 0 || getsectordist({ x, y }, wal.nextsector) <= maxDistance)) search.Add(wal.nextsector); } + iter++; + } + } + + *sectnum = -1; +} + +void updatesectorneighborz(int32_t const x, int32_t const y, int32_t const z, int* const sectnum, int32_t maxDistance) +{ + int const initialsectnum = *sectnum; + + if ((validSectorIndex(initialsectnum))) + { + if (inside_z_p(x, y, z, initialsectnum)) + return; + + BFSSearch search(numsectors, *sectnum); + + int iter = 0; + for (unsigned listsectnum; (listsectnum = search.GetNext()) != BFSSearch::EOL;) + { + if (inside_z_p(x, y, z, listsectnum)) + { + *sectnum = listsectnum; + return; + } + + for (auto& wal : wallsofsector(listsectnum)) + { + if (wal.nextsector >= 0 && (iter == 0 || getsectordist({ x, y }, wal.nextsector) <= maxDistance)) + search.Add(wal.nextsector); + } + iter++; } } @@ -1449,3 +1476,11 @@ int tilehasmodelorvoxel(int const tilenume, int pal) (mdinited && hw_models && tile2model[Ptile2tile(tilenume, pal)].modelid != -1) || (r_voxels && tiletovox[tilenume] != -1); } + + +CCMD(updatesectordebug) +{ + int sect = 319; + updatesector(1792, 24334, §); + int blah = sect; +} \ No newline at end of file diff --git a/source/games/duke/src/actors_d.cpp b/source/games/duke/src/actors_d.cpp index c5ce345eb..68ee6de1f 100644 --- a/source/games/duke/src/actors_d.cpp +++ b/source/games/duke/src/actors_d.cpp @@ -1108,7 +1108,7 @@ static void movetripbomb(DDukeActor *actor) int const oldSectNum = s->sectnum; int curSectNum = s->sectnum; - updatesectorneighbor(s->x, s->y, &curSectNum, 1024, 2048); + updatesectorneighbor(s->x, s->y, &curSectNum, 2048); changeactorsect(actor, curSectNum); DDukeActor* hit; @@ -1139,7 +1139,7 @@ static void movetripbomb(DDukeActor *actor) s->x += bcos(actor->temp_data[5], -4); s->y += bsin(actor->temp_data[5], -4); - updatesectorneighbor(s->x, s->y, &curSectNum, 1024, 2048); + updatesectorneighbor(s->x, s->y, &curSectNum, 2048); if (curSectNum == -1) break;