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 (*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 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); 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); 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 dragpoint(int16_t pointhighlight, int32_t dax, int32_t day, uint8_t flags);
void setfirstwall(int16_t sectnum, int16_t newfirstwall); 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, int32_t vx, int32_t vy, int32_t vz,
vec3_t *intp, int32_t strictly_smaller_than_p); 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); int findwallbetweensectors(int sect1, int sect2);
static FORCE_INLINE bool sectoradjacent(int sect1, int sect2) { return findwallbetweensectors(sect1, sect2) != -1; } 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); 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; return -1;
} }
#define MAXUPDATESECTORDIST 1536
#define INITIALUPDATESECTORDIST 256
// //
// updatesector[z] // updatesector[z]
// //
void updatesector(int32_t const x, int32_t const y, int16_t * const sectnum) void updatesector(int32_t const x, int32_t const y, int16_t * const sectnum)
{ {
int const initialsectnum = *sectnum; int16_t sect = *sectnum;
updatesectorneighbour(x, y, &sect, INITIALUPDATESECTORDIST, MAXUPDATESECTORDIST);
if ((unsigned)initialsectnum < (unsigned)numsectors && getsectordist({x, y}, initialsectnum) < INITIALUPDATESECTORDIST) if (sect != -1)
{ SET_AND_RETURN(*sectnum, sect);
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);
}
}
// we need to support passing in a sectnum of -1, unfortunately // 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) // (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) 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; 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; 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; int32_t cz, fz;
getzsofslope(correctedsectnum, x, y, &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]; auto uwal = (uwallptr_t)&wall[startwall];
for (int j=startwall; j<endwall; j++, uwal++) 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); 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; *sectnum = -1;
} }

View file

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

View file

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

View file

@ -4740,6 +4740,40 @@ badindex:
dispatch(); 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): vInstruction(CON_SPAWN):
insptr++; insptr++;

View file

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

View file

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

View file

@ -2116,18 +2116,33 @@ badindex:
case CON_UPDATESECTOR: case CON_UPDATESECTOR:
case CON_UPDATESECTORZ: case CON_UPDATESECTORZ:
case CON_UPDATESECTORNEIGHBOUR:
case CON_UPDATESECTORNEIGHBOURZ:
insptr++; insptr++;
{ {
int32_t x=Gv_GetVar(*insptr++), y=Gv_GetVar(*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++; int32_t var=*insptr++;
int16_t w; int16_t w;
X_ERROR_INVALIDCI(); X_ERROR_INVALIDCI();
w=sprite[vm.spriteNum].sectnum; w=sprite[vm.spriteNum].sectnum;
if (tw==CON_UPDATESECTOR) updatesector(x,y,&w); switch (tw)
else updatesectorz(x,y,z,&w); {
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); Gv_SetVar(var, w);
continue; continue;