- 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.
This commit is contained in:
Christoph Oelckers 2021-11-30 00:08:24 +01:00
parent f765783437
commit 64cad55d73
3 changed files with 57 additions and 22 deletions

View file

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

View file

@ -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, &sect, INITIALUPDATESECTORDIST, MAXUPDATESECTORDIST);
updatesectorneighbor(x, y, &sect, 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, &sect, 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, &sect);
int blah = sect;
}

View file

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