This should fix updatesector/updatesectorz performance while retaining the benefits of breadth-first search

git-svn-id: https://svn.eduke32.com/eduke32@7601 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
terminx 2019-04-18 17:25:11 +00:00 committed by Christoph Oelckers
parent a89c260592
commit ab857c4e8f
2 changed files with 127 additions and 126 deletions

View file

@ -908,51 +908,58 @@ static int32_t get_floorspr_clipyou(int32_t x1, int32_t x2, int32_t x3, int32_t
return clipyou; return clipyou;
} }
static void clipupdatesector(vec2_t const &p, int16_t * const sectnum, int const walldist) static void clipupdatesector(vec2_t const &pos, int16_t * const sectnum, int const walldist)
{ {
if (inside_p(p.x, p.y, *sectnum)) if (inside_p(pos.x, pos.y, *sectnum))
return; return;
static int16_t sectlist[MAXSECTORS]; static int16_t sectlist[MAXSECTORS];
static uint8_t sectbitmap[(MAXSECTORS+7)>>3]; static uint8_t sectbitmap[(MAXSECTORS+7)>>3];
int32_t nsecs; int32_t nsecs;
bfirst_search_init(sectlist, sectbitmap, &nsecs, numsectors, *sectnum); bfirst_search_init(sectlist, sectbitmap, &nsecs, MAXCLIPSECTORS, *sectnum);
for (int sectcnt = 0; sectcnt < nsecs; sectcnt++) for (int sectcnt = 0; sectcnt < nsecs; sectcnt++)
{ {
if (inside_p(p.x, p.y, sectlist[sectcnt])) int const listsectnum = sectlist[sectcnt];
SET_AND_RETURN(*sectnum, sectlist[sectcnt]);
auto const sec = &sector[sectlist[sectcnt]]; if (inside_p(pos.x, pos.y, listsectnum))
SET_AND_RETURN(*sectnum, listsectnum);
auto const sec = &sector[listsectnum];
int const startwall = sec->wallptr; int const startwall = sec->wallptr;
int const endwall = sec->wallptr + sec->wallnum; int const endwall = sec->wallptr + sec->wallnum;
auto uwal = (uwalltype *)&wall[startwall];
for (int j = startwall; j < endwall; j++) for (int j = startwall; j < endwall; j++, uwal++)
if (wall[j].nextsector >= 0 && bitmap_test(clipsectormap, wall[j].nextsector)) if (uwal->nextsector >= 0 && bitmap_test(clipsectormap, uwal->nextsector))
bfirst_search_try(sectlist, sectbitmap, &nsecs, wall[j].nextsector); bfirst_search_try(sectlist, sectbitmap, &nsecs, uwal->nextsector);
} }
bfirst_search_init(sectlist, sectbitmap, &nsecs, numsectors, *sectnum); bfirst_search_init(sectlist, sectbitmap, &nsecs, MAXSECTORS, *sectnum);
for (int sectcnt = 0; sectcnt < nsecs; sectcnt++) for (int sectcnt = 0; sectcnt < nsecs; sectcnt++)
{ {
if (inside_p(p.x, p.y, sectlist[sectcnt])) int const listsectnum = sectlist[sectcnt];
if (inside_p(pos.x, pos.y, listsectnum))
{ {
// add sector to clipping list so the next call to clipupdatesector() // add sector to clipping list so the next call to clipupdatesector()
// finishes in the loop above this one // finishes in the loop above this one
addclipsect(sectlist[sectcnt]); addclipsect(listsectnum);
SET_AND_RETURN(*sectnum, sectlist[sectcnt]); SET_AND_RETURN(*sectnum, listsectnum);
} }
auto const sec = &sector[sectlist[sectcnt]]; auto const sec = &sector[listsectnum];
int const startwall = sec->wallptr; int const startwall = sec->wallptr;
int const endwall = sec->wallptr + sec->wallnum; int const endwall = sec->wallptr + sec->wallnum;
auto uwal = (uwalltype *)&wall[startwall];
// check floor curbs here? // check floor curbs here?
for (int j = startwall; j < endwall; j++)
if (wall[j].nextsector >= 0 && getwalldist(p, j) <= walldist) for (int j = startwall; j < endwall; j++, uwal++)
bfirst_search_try(sectlist, sectbitmap, &nsecs, wall[j].nextsector); if (uwal->nextsector >= 0 && getwalldist(pos, j) <= walldist)
bfirst_search_try(sectlist, sectbitmap, &nsecs, uwal->nextsector);
} }
*sectnum = -1; *sectnum = -1;

View file

@ -10621,37 +10621,32 @@ void get_floorspr_points(uspritetype const * const spr, int32_t px, int32_t py,
int32_t *y1, int32_t *y2, int32_t *y3, int32_t *y4) int32_t *y1, int32_t *y2, int32_t *y3, int32_t *y4)
{ {
const int32_t tilenum = spr->picnum; const int32_t tilenum = spr->picnum;
// &2047 in sinang:
// DNE 1.3D lights camera action (1st level), spr->ang==2306
// (probably from CON)
const int32_t cosang = sintable[(spr->ang+512)&2047]; const int32_t cosang = sintable[(spr->ang+512)&2047];
const int32_t sinang = sintable[spr->ang&2047]; const int32_t sinang = sintable[spr->ang&2047];
const int32_t xspan=tilesiz[tilenum].x, xrepeat=spr->xrepeat; vec2_t const span = { tilesiz[tilenum].x, tilesiz[tilenum].y};
const int32_t yspan=tilesiz[tilenum].y, yrepeat=spr->yrepeat; vec2_t const repeat = { spr->xrepeat, spr->yrepeat };
int32_t xoff = picanm[tilenum].xofs + spr->xoffset; vec2_t adjofs = { picanm[tilenum].xofs + spr->xoffset, picanm[tilenum].yofs + spr->yoffset };
int32_t yoff = picanm[tilenum].yofs + spr->yoffset;
int32_t k, l, dax, day;
if (spr->cstat&4) if (spr->cstat & 4)
xoff = -xoff; adjofs.x = -adjofs.x;
if (spr->cstat&8)
yoff = -yoff;
dax = ((xspan>>1)+xoff)*xrepeat; if (spr->cstat & 8)
day = ((yspan>>1)+yoff)*yrepeat; adjofs.y = -adjofs.y;
*x1 += dmulscale16(sinang,dax, cosang,day) - px; vec2_t const center = { ((span.x >> 1) + adjofs.x) * repeat.x, ((span.y >> 1) + adjofs.y) * repeat.y };
*y1 += dmulscale16(sinang,day, -cosang,dax) - py; vec2_t const rspan = { span.x * repeat.x, span.y * repeat.y };
vec2_t const ofs = { -mulscale16(cosang, rspan.y), -mulscale16(sinang, rspan.y) };
l = xspan*xrepeat; *x1 += dmulscale16(sinang, center.x, cosang, center.y) - px;
*x2 = *x1 - mulscale16(sinang,l); *y1 += dmulscale16(sinang, center.y, -cosang, center.x) - py;
*y2 = *y1 + mulscale16(cosang,l);
l = yspan*yrepeat; *x2 = *x1 - mulscale16(sinang, rspan.x);
k = -mulscale16(cosang,l); *x3 = *x2+k; *x4 = *x1+k; *y2 = *y1 + mulscale16(cosang, rspan.x);
k = -mulscale16(sinang,l); *y3 = *y2+k; *y4 = *y1+k;
*x3 = *x2 + ofs.x, *x4 = *x1 + ofs.x;
*y3 = *y2 + ofs.y, *y4 = *y1 + ofs.y;
} }
// //
@ -10971,17 +10966,17 @@ static inline bool inside_z_p(int32_t const x, int32_t const y, int32_t const z,
return (z >= cz && z <= fz && inside_p(x, y, sectnum)); return (z >= cz && z <= fz && inside_p(x, y, sectnum));
} }
int32_t getwalldist(vec2_t const &p, int const wallnum, vec2_t * const output) int32_t getwalldist(vec2_t const &pos, int const wallnum, vec2_t * const output)
{ {
vec2_t closest; vec2_t closest;
getclosestpointonwall_internal(p, wallnum, &closest); getclosestpointonwall_internal(pos, wallnum, &closest);
if (output) *output = closest; if (output) *output = closest;
return klabs(closest.x - p.x) + klabs(closest.y - p.y); return klabs(closest.x - pos.x) + klabs(closest.y - pos.y);
} }
int32_t getsectordist(vec2_t const &p, int const sectnum) int32_t getsectordist(vec2_t const &pos, int const sectnum)
{ {
if (inside_p(p.x, p.y, sectnum)) if (inside_p(pos.x, pos.y, sectnum))
return 0; return 0;
int32_t distance = INT32_MAX; int32_t distance = INT32_MAX;
@ -10993,7 +10988,7 @@ int32_t getsectordist(vec2_t const &p, int const sectnum)
for (int j = startwall; j < endwall; j++, uwal++) for (int j = startwall; j < endwall; j++, uwal++)
{ {
int32_t const walldist = getwalldist(p, j); int32_t const walldist = getwalldist(pos, j);
distance = min(walldist, distance); distance = min(walldist, distance);
} }
@ -11012,45 +11007,50 @@ bool sectoradjacent(int sect1, int sect2)
return 0; return 0;
} }
#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)
{ {
if (inside_p(x, y, *sectnum)) int const initialsectnum = *sectnum;
return;
if ((unsigned)*sectnum >= (unsigned)numsectors) if ((unsigned)initialsectnum < (unsigned)numsectors && getsectordist({x, y}, initialsectnum) < INITIALUPDATESECTORDIST)
{ {
// we need to support passing in a sectnum of -1, unfortunately if (inside_p(x, y, initialsectnum))
return;
for (int i = numsectors - 1; i >= 0; --i)
if (inside_p(x, y, i))
SET_AND_RETURN(*sectnum, i);
SET_AND_RETURN(*sectnum, -1);
}
static int16_t sectlist[MAXSECTORS]; static int16_t sectlist[MAXSECTORS];
static uint8_t sectbitmap[(MAXSECTORS+7)>>3]; static uint8_t sectbitmap[(MAXSECTORS+7)>>3];
int32_t nsecs; int32_t nsecs;
bfirst_search_init(sectlist, sectbitmap, &nsecs, numsectors, *sectnum); bfirst_search_init(sectlist, sectbitmap, &nsecs, MAXSECTORS, initialsectnum);
for (int sectcnt=0; sectcnt<nsecs; sectcnt++) for (int sectcnt=0; sectcnt<nsecs; sectcnt++)
{ {
if (inside_p(x, y, sectlist[sectcnt])) int const listsectnum = sectlist[sectcnt];
SET_AND_RETURN(*sectnum, sectlist[sectcnt]);
auto const sec = &sector[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 startwall = sec->wallptr;
int const endwall = sec->wallptr + sec->wallnum; int const endwall = sec->wallptr + sec->wallnum;
auto uwal = (uwalltype *)&wall[startwall];
for (int j=startwall; j<endwall; j++) for (int j=startwall; j<endwall; j++, uwal++)
if (wall[j].nextsector >= 0) if (uwal->nextsector >= 0 && getsectordist({x, y}, uwal->nextsector) < MAXUPDATESECTORDIST)
bfirst_search_try(sectlist, sectbitmap, &nsecs, wall[j].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_p(x, y, i))
SET_AND_RETURN(*sectnum, i);
*sectnum = -1; *sectnum = -1;
} }
@ -11090,74 +11090,68 @@ void updatesectorz(int32_t const x, int32_t const y, int32_t const z, int16_t *
{ {
bool nofirstzcheck = false; bool nofirstzcheck = false;
if ((unsigned)*sectnum >= (unsigned)numsectors)
{
if (*sectnum >= MAXSECTORS && (unsigned)*sectnum < (unsigned)numsectors + MAXSECTORS) if (*sectnum >= MAXSECTORS && (unsigned)*sectnum < (unsigned)numsectors + MAXSECTORS)
{ {
*sectnum -= MAXSECTORS; *sectnum -= MAXSECTORS;
nofirstzcheck = true; nofirstzcheck = true;
} }
else
int const correctedsectnum = *sectnum;
if ((unsigned)correctedsectnum < (unsigned)numsectors && getsectordist({x, y}, correctedsectnum) < INITIALUPDATESECTORDIST)
{ {
// we need to support passing in a sectnum of -1, unfortunately if (nofirstzcheck && inside_p(x, y, correctedsectnum))
for (int i = numsectors - 1; i >= 0; --i) return;
if (inside_z_p(x, y, z, i))
SET_AND_RETURN(*sectnum, i);
for (int i = numsectors - 1; i >= 0; --i)
if (inside_p(x, y, i))
SET_AND_RETURN(*sectnum, i);
SET_AND_RETURN(*sectnum, -1);
}
}
int32_t cz, fz; int32_t cz, fz;
getzsofslope(*sectnum, x, y, &cz, &fz); getzsofslope(correctedsectnum, x, y, &cz, &fz);
#ifdef YAX_ENABLE #ifdef YAX_ENABLE
if (z < cz) if (z < cz)
{ {
int const next = yax_getneighborsect(x, y, *sectnum, YAX_CEILING); int const next = yax_getneighborsect(x, y, correctedsectnum, YAX_CEILING);
if (next >= 0 && z >= getceilzofslope(next, x, y)) if (next >= 0 && z >= getceilzofslope(next, x, y))
SET_AND_RETURN(*sectnum, next); SET_AND_RETURN(*sectnum, next);
} }
if (z > fz) if (z > fz)
{ {
int const next = yax_getneighborsect(x, y, *sectnum, YAX_FLOOR); int const next = yax_getneighborsect(x, y, correctedsectnum, YAX_FLOOR);
if (next >= 0 && z <= getflorzofslope(next, x, y)) if (next >= 0 && z <= getflorzofslope(next, x, y))
SET_AND_RETURN(*sectnum, next); SET_AND_RETURN(*sectnum, next);
} }
#endif #endif
if (nofirstzcheck || (z >= cz && z <= fz)) if (z >= cz && z <= fz && inside_p(x, y, correctedsectnum))
if (inside_p(x, y, *sectnum))
return; return;
static int16_t sectlist[MAXSECTORS]; static int16_t sectlist[MAXSECTORS];
static uint8_t sectbitmap[(MAXSECTORS+7)>>3]; static uint8_t sectbitmap[(MAXSECTORS+7)>>3];
int32_t nsecs; int32_t nsecs;
bfirst_search_init(sectlist, sectbitmap, &nsecs, numsectors, *sectnum); bfirst_search_init(sectlist, sectbitmap, &nsecs, MAXSECTORS, correctedsectnum);
for (int sectcnt=0; sectcnt<nsecs; sectcnt++) for (int sectcnt=0; sectcnt<nsecs; sectcnt++)
{ {
if (inside_z_p(x, y, z, sectlist[sectcnt])) int const listsectnum = sectlist[sectcnt];
SET_AND_RETURN(*sectnum, sectlist[sectcnt]);
auto const sec = &sector[sectlist[sectcnt]]; if (inside_z_p(x, y, z, listsectnum))
SET_AND_RETURN(*sectnum, listsectnum);
auto const sec = &sector[listsectnum];
int const startwall = sec->wallptr; int const startwall = sec->wallptr;
int const endwall = sec->wallptr + sec->wallnum; int const endwall = sec->wallptr + sec->wallnum;
auto uwal = (uwalltype *)&wall[startwall];
for (int j=startwall; j<endwall; j++) for (int j=startwall; j<endwall; j++, uwal++)
if (wall[j].nextsector >= 0) if (uwal->nextsector >= 0 && getsectordist({x, y}, uwal->nextsector) < MAXUPDATESECTORDIST)
bfirst_search_try(sectlist, sectbitmap, &nsecs, wall[j].nextsector); bfirst_search_try(sectlist, sectbitmap, &nsecs, uwal->nextsector);
}
} }
// fall back to searching without z... this is really a bullshit worst case scenario // we need to support passing in a sectnum of -1, unfortunately
for (int sectcnt=0; sectcnt<nsecs; sectcnt++) for (int i = numsectors - 1; i >= 0; --i)
if (inside_p(x, y, sectlist[sectcnt])) if (inside_z_p(x, y, z, i))
SET_AND_RETURN(*sectnum, sectlist[sectcnt]); SET_AND_RETURN(*sectnum, i);
*sectnum = -1; *sectnum = -1;
} }