Add updatesectorneighbour() and updatesectorneighbourz() and make them accessible to CON to allow searching for nearby neighbouring sectors from a known sector.

These updatesector counterparts are more performant for tasks that require determining whether nearby sectors exist at a point as they will not exhaustively search the map.
This also leads to more correct behaviour when sectors are disjoint, as queries will breadth-first search neighbouring sectors rather than risk accidentally stumbling first across accomodating disjoint sectors.

git-svn-id: https://svn.eduke32.com/eduke32@7805 1a8010ca-5511-0410-912e-c29ae57300e0

# Conflicts:
#	source/build/include/build.h
This commit is contained in:
pogokeen 2019-07-19 01:46:32 +00:00 committed by Christoph Oelckers
parent 844ec0bd63
commit 3d63d1b720
8 changed files with 131 additions and 52 deletions

View file

@ -1169,14 +1169,6 @@ void neartag(int32_t xs, int32_t ys, int32_t zs, int16_t sectnum, int16_t ange
int32_t (*blacklist_sprite_func)(int32_t)) ATTRIBUTE((nonnull(6,7,8)));
int32_t cansee(int32_t x1, int32_t y1, int32_t z1, int16_t sect1,
int32_t x2, int32_t y2, int32_t z2, int16_t sect2);
void updatesector(int32_t const x, int32_t const y, int16_t * const sectnum) ATTRIBUTE((nonnull(3)));
inline void updatesectorbreadth(int32_t const x, int32_t const y, int16_t *sectnum) ATTRIBUTE((nonnull(3)))
{
updatesector(x, y, sectnum);
}
void updatesectorexclude(int32_t const x, int32_t const y, int16_t * const sectnum,
const uint8_t * const excludesectbitmap) ATTRIBUTE((nonnull(3,4)));
void updatesectorz(int32_t const x, int32_t const y, int32_t const z, int16_t * const sectnum) ATTRIBUTE((nonnull(4)));
int32_t inside(int32_t x, int32_t y, int16_t sectnum);
void dragpoint(int16_t pointhighlight, int32_t dax, int32_t day, uint8_t flags);
void setfirstwall(int16_t sectnum, int16_t newfirstwall);
@ -1184,6 +1176,15 @@ int32_t try_facespr_intersect(uspriteptr_t const spr, const vec3_t *refpos,
int32_t vx, int32_t vy, int32_t vz,
vec3_t *intp, int32_t strictly_smaller_than_p);
#define MAXUPDATESECTORDIST 1536
#define INITIALUPDATESECTORDIST 256
void updatesector(int32_t const x, int32_t const y, int16_t * const sectnum) ATTRIBUTE((nonnull(3)));
void updatesectorexclude(int32_t const x, int32_t const y, int16_t * const sectnum,
const uint8_t * const excludesectbitmap) ATTRIBUTE((nonnull(3,4)));
void updatesectorz(int32_t const x, int32_t const y, int32_t const z, int16_t * const sectnum) ATTRIBUTE((nonnull(4)));
void updatesectorneighbour(int32_t const x, int32_t const y, int16_t * const sectnum, int32_t initialMaxDistance = INITIALUPDATESECTORDIST, int32_t maxDistance = MAXUPDATESECTORDIST) ATTRIBUTE((nonnull(3)));
void updatesectorneighbourz(int32_t const x, int32_t const y, int32_t const z, int16_t * const sectnum, int32_t initialMaxDistance = INITIALUPDATESECTORDIST, int32_t maxDistance = MAXUPDATESECTORDIST) ATTRIBUTE((nonnull(4)));
int findwallbetweensectors(int sect1, int sect2);
static FORCE_INLINE bool sectoradjacent(int sect1, int sect2) { return findwallbetweensectors(sect1, sect2) != -1; }
int32_t getwalldist(vec2_t const &in, int const wallnum, vec2_t * const out = nullptr);

View file

@ -11407,44 +11407,15 @@ int findwallbetweensectors(int sect1, int sect2)
return -1;
}
#define MAXUPDATESECTORDIST 1536
#define INITIALUPDATESECTORDIST 256
//
// updatesector[z]
//
void updatesector(int32_t const x, int32_t const y, int16_t * const sectnum)
{
int const initialsectnum = *sectnum;
if ((unsigned)initialsectnum < (unsigned)numsectors && getsectordist({x, y}, initialsectnum) < INITIALUPDATESECTORDIST)
{
if (inside_p(x, y, initialsectnum))
return;
static int16_t sectlist[MAXSECTORS];
static uint8_t sectbitmap[(MAXSECTORS+7)>>3];
int16_t nsecs;
bfirst_search_init(sectlist, sectbitmap, &nsecs, MAXSECTORS, initialsectnum);
for (int sectcnt=0; sectcnt<nsecs; sectcnt++)
{
int const listsectnum = sectlist[sectcnt];
if (inside_p(x, y, listsectnum))
SET_AND_RETURN(*sectnum, listsectnum);
auto const sec = &sector[listsectnum];
int const startwall = sec->wallptr;
int const endwall = sec->wallptr + sec->wallnum;
auto uwal = (uwallptr_t)&wall[startwall];
for (int j=startwall; j<endwall; j++, uwal++)
if (uwal->nextsector >= 0 && getsectordist({x, y}, uwal->nextsector) < MAXUPDATESECTORDIST)
bfirst_search_try(sectlist, sectbitmap, &nsecs, uwal->nextsector);
}
}
int16_t sect = *sectnum;
updatesectorneighbour(x, y, &sect, INITIALUPDATESECTORDIST, MAXUPDATESECTORDIST);
if (sect != -1)
SET_AND_RETURN(*sectnum, sect);
// we need to support passing in a sectnum of -1, unfortunately
@ -11487,6 +11458,57 @@ void updatesectorexclude(int32_t const x, int32_t const y, int16_t * const sectn
// (not initial anymore because it follows the sector updating due to TROR)
void updatesectorz(int32_t const x, int32_t const y, int32_t const z, int16_t * const sectnum)
{
int16_t sect = *sectnum;
updatesectorneighbourz(x, y, z, &sect, INITIALUPDATESECTORDIST, MAXUPDATESECTORDIST);
if (sect != -1)
SET_AND_RETURN(*sectnum, sect);
// 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))
SET_AND_RETURN(*sectnum, i);
*sectnum = -1;
}
void updatesectorneighbour(int32_t const x, int32_t const y, int16_t * const sectnum, int32_t initialMaxDistance /*= INITIALUPDATESECTORDIST*/, int32_t maxDistance /*= MAXUPDATESECTORDIST*/)
{
int const initialsectnum = *sectnum;
if ((unsigned)initialsectnum < (unsigned)numsectors && getsectordist({x, y}, initialsectnum) <= initialMaxDistance)
{
if (inside_p(x, y, initialsectnum))
return;
static int16_t sectlist[MAXSECTORS];
static uint8_t sectbitmap[(MAXSECTORS+7)>>3];
int16_t nsecs;
bfirst_search_init(sectlist, sectbitmap, &nsecs, MAXSECTORS, initialsectnum);
for (int sectcnt=0; sectcnt<nsecs; sectcnt++)
{
int const listsectnum = sectlist[sectcnt];
if (inside_p(x, y, listsectnum))
SET_AND_RETURN(*sectnum, listsectnum);
auto const sec = &sector[listsectnum];
int const startwall = sec->wallptr;
int const endwall = sec->wallptr + sec->wallnum;
auto uwal = (uwallptr_t)&wall[startwall];
for (int j=startwall; j<endwall; j++, uwal++)
if (uwal->nextsector >= 0 && getsectordist({x, y}, uwal->nextsector) <= maxDistance)
bfirst_search_try(sectlist, sectbitmap, &nsecs, uwal->nextsector);
}
}
*sectnum = -1;
}
void updatesectorneighbourz(int32_t const x, int32_t const y, int32_t const z, int16_t * const sectnum, int32_t initialMaxDistance /*= 0*/, int32_t maxDistance /*= 0*/)
{
bool nofirstzcheck = false;
@ -11498,7 +11520,7 @@ void updatesectorz(int32_t const x, int32_t const y, int32_t const z, int16_t *
uint32_t const correctedsectnum = (unsigned)*sectnum;
if (correctedsectnum < (unsigned)numsectors && getsectordist({x, y}, correctedsectnum) < INITIALUPDATESECTORDIST)
if (correctedsectnum < (unsigned)numsectors && getsectordist({x, y}, correctedsectnum) <= initialMaxDistance)
{
int32_t cz, fz;
getzsofslope(correctedsectnum, x, y, &cz, &fz);
@ -11540,16 +11562,11 @@ void updatesectorz(int32_t const x, int32_t const y, int32_t const z, int16_t *
auto uwal = (uwallptr_t)&wall[startwall];
for (int j=startwall; j<endwall; j++, uwal++)
if (uwal->nextsector >= 0 && getsectordist({x, y}, uwal->nextsector) < MAXUPDATESECTORDIST)
if (uwal->nextsector >= 0 && getsectordist({x, y}, uwal->nextsector) <= maxDistance)
bfirst_search_try(sectlist, sectbitmap, &nsecs, uwal->nextsector);
}
}
// 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))
SET_AND_RETURN(*sectnum, i);
*sectnum = -1;
}

View file

@ -546,6 +546,8 @@ static tokenmap_t const vm_keywords[] =
{ "undefinevolume", CON_UNDEFINEVOLUME },
{ "updatesector", CON_UPDATESECTOR },
{ "updatesectorz", CON_UPDATESECTORZ },
{ "updatesectorneighbour", CON_UPDATESECTORNEIGHBOUR },
{ "updatesectorneighbourz", CON_UPDATESECTORNEIGHBOURZ },
{ "useractor", CON_USERACTOR },
{ "userquote", CON_USERQUOTE },
{ "wackplayer", CON_WACKPLAYER },
@ -4130,6 +4132,7 @@ setvarvar:
case CON_GETFLORZOFSLOPE:
case CON_GETCEILZOFSLOPE:
case CON_UPDATESECTORZ:
case CON_UPDATESECTORNEIGHBOURZ:
C_GetManyVars(3);
C_GetNextVarType(GAMEVAR_READONLY);
continue;
@ -4548,6 +4551,7 @@ ifvar:
case CON_CANSEESPR:
case CON_UPDATESECTOR:
case CON_UPDATESECTORNEIGHBOUR:
case CON_QSTRCMP:
C_GetManyVars(2);
C_GetNextVarType(GAMEVAR_READONLY);

View file

@ -1321,6 +1321,8 @@ enum IterationTypes_t
TRANSFORM(CON_TOSSWEAPON) DELIMITER \
TRANSFORM(CON_UPDATESECTOR) DELIMITER \
TRANSFORM(CON_UPDATESECTORZ) DELIMITER \
TRANSFORM(CON_UPDATESECTORNEIGHBOUR) DELIMITER \
TRANSFORM(CON_UPDATESECTORNEIGHBOURZ) DELIMITER \
TRANSFORM(CON_USERQUOTE) DELIMITER \
TRANSFORM(CON_WACKPLAYER) DELIMITER \
TRANSFORM(CON_WRITEARRAYTOFILE) DELIMITER \

View file

@ -4740,6 +4740,40 @@ badindex:
dispatch();
}
vInstruction(CON_UPDATESECTORNEIGHBOUR):
insptr++;
{
vec2_t vect = { 0, 0 };
Gv_FillWithVars(vect);
int const returnVar = *insptr++;
int16_t sectNum = Gv_GetVar(returnVar);
if ((unsigned)sectNum >= MAXSECTORS)
sectNum = vm.pSprite->sectnum;
updatesectorneighbour(vect.x, vect.y, &sectNum, getsectordist(vect, sectNum));
Gv_SetVar(returnVar, sectNum);
dispatch();
}
vInstruction(CON_UPDATESECTORNEIGHBOURZ):
insptr++;
{
vec3_t vect = { 0, 0, 0 };
Gv_FillWithVars(vect);
int const returnVar = *insptr++;
int16_t sectNum = Gv_GetVar(returnVar);
if ((unsigned)sectNum >= MAXSECTORS)
sectNum = vm.pSprite->sectnum;
updatesectorneighbourz(vect.x, vect.y, vect.z, &sectNum, getsectordist({vect.x, vect.y}, sectNum));
Gv_SetVar(returnVar, sectNum);
dispatch();
}
vInstruction(CON_SPAWN):
insptr++;

View file

@ -341,6 +341,8 @@ const char *keyw[] =
"updatecursectnum",
"updatesector",
"updatesectorz",
"updatesectorneighbour",
"updatesectorneighbourz",
"getzrange",
"clipmove",
"lineintersect",
@ -3063,8 +3065,10 @@ repeatcase:
case CON_UPDATESECTOR:
case CON_UPDATESECTORZ:
case CON_UPDATESECTORNEIGHBOUR:
case CON_UPDATESECTORNEIGHBOURZ:
C_GetManyVars(2);
if (tw==CON_UPDATESECTORZ)
if (tw==CON_UPDATESECTORZ || tw==CON_UPDATESECTORNEIGHBOURZ)
C_GetNextVar();
C_GetNextVarType(GV_WRITABLE);
break;

View file

@ -475,6 +475,8 @@ enum ScriptKeywords_t
CON_UPDATECURSECTNUM,
CON_UPDATESECTOR,
CON_UPDATESECTORZ,
CON_UPDATESECTORNEIGHBOUR,
CON_UPDATESECTORNEIGHBOURZ,
CON_GETZRANGE,
CON_CLIPMOVE,
CON_LINEINTERSECT,

View file

@ -2116,18 +2116,33 @@ badindex:
case CON_UPDATESECTOR:
case CON_UPDATESECTORZ:
case CON_UPDATESECTORNEIGHBOUR:
case CON_UPDATESECTORNEIGHBOURZ:
insptr++;
{
int32_t x=Gv_GetVar(*insptr++), y=Gv_GetVar(*insptr++);
int32_t z=(tw==CON_UPDATESECTORZ)?Gv_GetVar(*insptr++):0;
int32_t z=(tw==CON_UPDATESECTORZ || tw==CON_UPDATESECTORNEIGHBOURZ)?Gv_GetVar(*insptr++):0;
int32_t var=*insptr++;
int16_t w;
X_ERROR_INVALIDCI();
w=sprite[vm.spriteNum].sectnum;
if (tw==CON_UPDATESECTOR) updatesector(x,y,&w);
else updatesectorz(x,y,z,&w);
switch (tw)
{
case CON_UPDATESECTORNEIGHBOURZ:
updatesectorneighbourz(x,y,z,&w,getsectordist({x, y}, w));
continue;
case CON_UPDATESECTORZ:
updatesectorz(x,y,z,&w);
continue;
case CON_UPDATESECTORNEIGHBOUR:
updatesectorneighbour(x,y,&w,getsectordist({x, y}, w));
continue;
default:
updatesector(x,y,&w);
continue;
}
Gv_SetVar(var, w);
continue;