diff --git a/source/build/include/build.h b/source/build/include/build.h index ecdfef573..89c035d73 100644 --- a/source/build/include/build.h +++ b/source/build/include/build.h @@ -333,22 +333,6 @@ int32_t getceilzofslopeptr(usectorptr_t sec, int32_t dax, int32_t day) ATTRIBU int32_t getflorzofslopeptr(usectorptr_t sec, int32_t dax, int32_t day) ATTRIBUTE((nonnull(1))); void getzsofslopeptr(usectorptr_t sec, int32_t dax, int32_t day, int32_t *ceilz, int32_t *florz) ATTRIBUTE((nonnull(1,4,5))); -void yax_getzsofslope(int sectNum, int playerX, int playerY, int32_t* pCeilZ, int32_t* pFloorZ); - -inline int32_t getceilzofslope(int sectnum, int32_t dax, int32_t day) -{ - return getceilzofslopeptr((usectorptr_t)§or[sectnum], dax, day); -} - -inline int32_t getflorzofslope(int sectnum, int32_t dax, int32_t day) -{ - return getflorzofslopeptr((usectorptr_t)§or[sectnum], dax, day); -} - -inline void getzsofslope(int sectnum, int32_t dax, int32_t day, int32_t *ceilz, int32_t *florz) -{ - getzsofslopeptr((usectorptr_t)§or[sectnum], dax, day, ceilz, florz); -} inline void getcorrectzsofslope(int sectnum, int32_t dax, int32_t day, int32_t *ceilz, int32_t *florz) { diff --git a/source/build/src/clip.cpp b/source/build/src/clip.cpp index d89fa0108..02a3590bc 100644 --- a/source/build/src/clip.cpp +++ b/source/build/src/clip.cpp @@ -225,13 +225,13 @@ static int cliptestsector(int const dasect, int const nextsect, int32_t const fl break; default: { - int32_t daz = getflorzofslope(dasect, pos.x, pos.y); - int32_t daz2 = getflorzofslope(nextsect, pos.x, pos.y); + int32_t daz = getflorzofslopeptr(§or[dasect], pos.x, pos.y); + int32_t daz2 = getflorzofslopeptr(sec2, pos.x, pos.y); if (daz2 < daz-(1<<8) && (sec2->floorstat&1) == 0) if (posz >= daz2-(flordist-1)) return 1; - daz = getceilzofslope(dasect, pos.x, pos.y); - daz2 = getceilzofslope(nextsect, pos.x, pos.y); + daz = getceilzofslopeptr(§or[dasect], pos.x, pos.y); + daz2 = getceilzofslopeptr(sec2, pos.x, pos.y); if (daz2 > daz+(1<<8) && (sec2->ceilingstat&1) == 0) if (posz <= daz2+(ceildist-1)) return 1; @@ -784,28 +784,30 @@ CollisionBase clipmove_(vec3_t * const pos, int * const sectnum, int32_t xvect, int32_t tempint2, tempint1 = INT32_MAX; *sectnum = -1; - for (int j=numsectors-1; j>=0; j--) - if (inside_p(pos->x, pos->y, j) == 1) + for (int j = numsectors - 1; j >= 0; j--) + { + auto sect = §or[j]; + if (inside(pos->x, pos->y, sect) == 1) { - if (enginecompatibility_mode != ENGINECOMPATIBILITY_19950829 && (sector[j].ceilingstat&2)) - tempint2 = getceilzofslope(j, pos->x, pos->y) - pos->z; + if (enginecompatibility_mode != ENGINECOMPATIBILITY_19950829 && (sect->ceilingstat & CSTAT_SECTOR_SLOPE)) + tempint2 = getceilzofslopeptr(sect, pos->x, pos->y) - pos->z; else - tempint2 = sector[j].ceilingz - pos->z; + tempint2 = sect->ceilingz - pos->z; if (tempint2 > 0) { if (tempint2 < tempint1) { - *sectnum = (int16_t)j; + *sectnum = (int16_t)j; tempint1 = tempint2; } } else { - if (enginecompatibility_mode != ENGINECOMPATIBILITY_19950829 && (sector[j].floorstat&2)) - tempint2 = pos->z - getflorzofslope(j, pos->x, pos->y); + if (enginecompatibility_mode != ENGINECOMPATIBILITY_19950829 && (sect->ceilingstat & CSTAT_SECTOR_SLOPE)) + tempint2 = pos->z - getflorzofslopeptr(sect, pos->x, pos->y); else - tempint2 = pos->z - sector[j].floorz; + tempint2 = pos->z - sect->floorz; if (tempint2 <= 0) { @@ -819,6 +821,7 @@ CollisionBase clipmove_(vec3_t * const pos, int * const sectnum, int32_t xvect, } } } + } } return clipReturn; diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index ef044f2f1..afdef5a3c 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -675,7 +675,7 @@ void dragpoint(int w, int32_t dax, int32_t day) static inline int inside_z_p(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); + getzsofslopeptr(§or[sectnum], x, y, &cz, &fz); return (z >= cz && z <= fz && inside_p(x, y, sectnum)); } @@ -890,67 +890,6 @@ void renderRestoreTarget() } -int32_t getceilzofslopeptr(usectorptr_t sec, int32_t dax, int32_t day) -{ - if (!(sec->ceilingstat&2)) - return sec->ceilingz; - - auto const wal = (uwallptr_t)sec->firstWall(); - auto const wal2 = (uwallptr_t)wal->point2Wall(); - - vec2_t const w = *(vec2_t const *)wal; - vec2_t const d = { wal2->x - w.x, wal2->y - w.y }; - - int const i = ksqrt(uhypsq(d.x,d.y))<<5; - if (i == 0) return sec->ceilingz; - - int const j = DMulScale(d.x, day-w.y, -d.y, dax-w.x, 3); - int const shift = enginecompatibility_mode != ENGINECOMPATIBILITY_NONE ? 0 : 1; - return sec->ceilingz + (Scale(sec->ceilingheinum,j>>shift,i)<floorstat&2)) - return sec->floorz; - - auto const wal = (uwallptr_t)sec->firstWall(); - auto const wal2 = (uwallptr_t)wal->point2Wall(); - - vec2_t const w = *(vec2_t const *)wal; - vec2_t const d = { wal2->x - w.x, wal2->y - w.y }; - - int const i = ksqrt(uhypsq(d.x,d.y))<<5; - if (i == 0) return sec->floorz; - - int const j = DMulScale(d.x, day-w.y, -d.y, dax-w.x, 3); - int const shift = enginecompatibility_mode != ENGINECOMPATIBILITY_NONE ? 0 : 1; - return sec->floorz + (Scale(sec->floorheinum,j>>shift,i)<ceilingz; *florz = sec->floorz; - - if (((sec->ceilingstat|sec->floorstat)&2) != 2) - return; - - auto const wal = (uwallptr_t)sec->firstWall(); - auto const wal2 = (uwallptr_t)wal->point2Wall(); - - vec2_t const d = { wal2->x - wal->x, wal2->y - wal->y }; - - int const i = ksqrt(uhypsq(d.x,d.y))<<5; - if (i == 0) return; - - int const j = DMulScale(d.x,day-wal->y, -d.y,dax-wal->x, 3); - int const shift = enginecompatibility_mode != ENGINECOMPATIBILITY_NONE ? 0 : 1; - if (sec->ceilingstat&2) - *ceilz += Scale(sec->ceilingheinum,j>>shift,i)<floorstat&2) - *florz += Scale(sec->floorheinum,j>>shift,i)< getflorzofslope(sectnum, globalposx, globalposy)) + if (globalposz > getflorzofslopeptr(sec, globalposx, globalposy)) domostpolymethod = DAMETH_BACKFACECULL; //Back-face culling if (domostpolymethod & DAMETH_MASKPROPS) @@ -1169,7 +1170,7 @@ static void polymost_internal_nonparallaxed(FVector2 n0, FVector2 n1, float ryp0 } else { - if (globalposz < getceilzofslope(sectnum, globalposx, globalposy)) + if (globalposz < getceilzofslopeptr(sec, globalposx, globalposy)) domostpolymethod = DAMETH_BACKFACECULL; //Back-face culling if (domostpolymethod & DAMETH_MASKPROPS) @@ -1245,60 +1246,21 @@ static inline int polymost_getclosestpointonwall(vec2_t const * const pos, int32 static float fgetceilzofslope(usectorptr_t sec, float dax, float day) { - if (!(sec->ceilingstat&2)) - return float(sec->ceilingz); - - auto const wal = (uwallptr_t)sec->firstWall(); - auto const wal2 = (uwallptr_t)wal->point2Wall(); - - vec2_t const w = *(vec2_t const *)wal; - vec2_t const d = { wal2->x - w.x, wal2->y - w.y }; - - int const i = ksqrt(uhypsq(d.x,d.y))<<5; - if (i == 0) return sec->ceilingz; - - float const j = (d.x*(day-w.y)-d.y*(dax-w.x))*(1.f/8.f); - return float(sec->ceilingz) + (sec->ceilingheinum*j)/i; + float z; + calcSlope(sec, dax, day, &z, nullptr); + return z; } static float fgetflorzofslope(usectorptr_t sec, float dax, float day) { - if (!(sec->floorstat&2)) - return float(sec->floorz); - - auto const wal = (uwallptr_t)sec->firstWall(); - auto const wal2 = (uwallptr_t)wal->point2Wall(); - - vec2_t const w = *(vec2_t const *)wal; - vec2_t const d = { wal2->x - w.x, wal2->y - w.y }; - - int const i = ksqrt(uhypsq(d.x,d.y))<<5; - if (i == 0) return sec->floorz; - - float const j = (d.x*(day-w.y)-d.y*(dax-w.x))*(1.f/8.f); - return float(sec->floorz) + (sec->floorheinum*j)/i; + float z; + calcSlope(sec, dax, day, nullptr, &z); + return z; } static void fgetzsofslope(usectorptr_t sec, float dax, float day, float* ceilz, float *florz) { - *ceilz = float(sec->ceilingz); *florz = float(sec->floorz); - - if (((sec->ceilingstat|sec->floorstat)&2) != 2) - return; - - auto const wal = (uwallptr_t)sec->firstWall(); - auto const wal2 = (uwallptr_t)wal->point2Wall(); - - vec2_t const d = { wal2->x - wal->x, wal2->y - wal->y }; - - int const i = ksqrt(uhypsq(d.x,d.y))<<5; - if (i == 0) return; - - float const j = (d.x*(day-wal->y)-d.y*(dax-wal->x))*(1.f/8.f); - if (sec->ceilingstat&2) - *ceilz += (sec->ceilingheinum*j)/i; - if (sec->floorstat&2) - *florz += (sec->floorheinum*j)/i; + calcSlope(sec, dax, day, ceilz, florz); } static void polymost_flatskyrender(FVector2 const* const dpxy, int32_t const n, int32_t method, const vec2_16_t &tilesize) @@ -1620,7 +1582,7 @@ static void polymost_drawalls(int32_t const bunch) } else if (!(globalorientation&1)) { - int32_t fz = getflorzofslope(sectnum, globalposx, globalposy); + int32_t fz = getflorzofslopeptr(sec, globalposx, globalposy); if (globalposz <= fz) polymost_internal_nonparallaxed(n0, n1, ryp0, ryp1, x0, x1, fy0, fy1, sectnum, true); } @@ -1673,7 +1635,7 @@ static void polymost_drawalls(int32_t const bunch) } else if (!(globalorientation&1)) { - int32_t cz = getceilzofslope(sectnum, globalposx, globalposy); + int32_t cz = getceilzofslopeptr(sec, globalposx, globalposy); if (globalposz >= cz) polymost_internal_nonparallaxed(n0, n1, ryp0, ryp1, x0, x1, cy0, cy1, sectnum, false); } @@ -2383,11 +2345,11 @@ static void polymost_drawmaskwallinternal(int32_t wallIndex) int32_t m0 = (int32_t)((wal2->x - wal->x) * t0 + wal->x); int32_t m1 = (int32_t)((wal2->y - wal->y) * t0 + wal->y); int32_t cz[4], fz[4]; - getzsofslope(sectnum, m0, m1, &cz[0], &fz[0]); + getzsofslopeptr(sec, m0, m1, &cz[0], &fz[0]); getzsofslopeptr(wal->nextSector(), m0, m1, &cz[1], &fz[1]); m0 = (int32_t)((wal2->x - wal->x) * t1 + wal->x); m1 = (int32_t)((wal2->y - wal->y) * t1 + wal->y); - getzsofslope(sectnum, m0, m1, &cz[2], &fz[2]); + getzsofslopeptr(sec, m0, m1, &cz[2], &fz[2]); getzsofslopeptr(wal->nextSector(), m0, m1, &cz[3], &fz[3]); float ryp0 = 1.f/p0.Y; diff --git a/source/core/gamefuncs.cpp b/source/core/gamefuncs.cpp index e598fdf8c..c4610c689 100644 --- a/source/core/gamefuncs.cpp +++ b/source/core/gamefuncs.cpp @@ -146,36 +146,79 @@ bool calcChaseCamPos(int* px, int* py, int* pz, spritetype* pspr, sectortype** p //========================================================================== // -// note that this returns values in renderer coordinate space with inverted sign! +// consolidated slope calculation +// +//========================================================================== + +void calcSlope(const sectortype* sec, float xpos, float ypos, float* pceilz, float* pflorz) +{ + int bits = 0; + if (pceilz) + { + bits |= sec->ceilingstat; + *pceilz = float(sec->ceilingz); + } + if (pflorz) + { + bits |= sec->floorstat; + *pflorz = float(sec->floorz); + } + + if ((bits & CSTAT_SECTOR_SLOPE) == CSTAT_SECTOR_SLOPE) + { + auto wal = sec->firstWall(); + int len = wal->Length(); + if (len != 0) + { + float den = (wal->deltax() * (float(ypos - wal->y)) - wal->deltay() * (float(xpos - wal->x))) * (1.f / 8.f); + if (pceilz && sec->ceilingstat & CSTAT_SECTOR_SLOPE) *pceilz += (sec->ceilingheinum * den) / len; + if (pflorz && sec->floorstat & CSTAT_SECTOR_SLOPE) *pflorz += (sec->floorheinum * den) / len; + } + } +} + +//========================================================================== +// +// for the renderer (Polymost variants are in polymost.cpp) // //========================================================================== void PlanesAtPoint(const sectortype* sec, int dax, int day, float* pceilz, float* pflorz) { - float ceilz = float(sec->ceilingz); - float florz = float(sec->floorz); - - if (((sec->ceilingstat | sec->floorstat) & CSTAT_SECTOR_SLOPE) == CSTAT_SECTOR_SLOPE) - { - auto wal = sec->firstWall(); - auto wal2 = wal->point2Wall(); - - float dx = float(wal2->x - wal->x); - float dy = float(wal2->y - wal->y); - - int i = (int)sqrt(dx * dx + dy * dy) << 5; // length of sector's first wall. - if (i != 0) - { - float const j = (dx * (float(day - wal->y)) - dy * (float(dax - wal->x))) * (1.f / 8.f); - if (sec->ceilingstat & CSTAT_SECTOR_SLOPE) ceilz += (sec->ceilingheinum * j) / i; - if (sec->floorstat & CSTAT_SECTOR_SLOPE) florz += (sec->floorheinum * j) / i; - } - } - // Scale to render coordinates. - if (pceilz) *pceilz = ceilz * -(1.f / 256.f); - if (pflorz) *pflorz = florz * -(1.f / 256.f); + calcSlope(sec, dax, day, pceilz, pflorz); + if (pceilz) *pceilz *= -(1 / 256.f); + if (pflorz) *pflorz *= -(1 / 256.f); } +//========================================================================== +// +// for the games +// +//========================================================================== + +int32_t getceilzofslopeptr(usectorptr_t sec, int32_t dax, int32_t day) +{ + float z; + calcSlope(sec, dax, day, &z, nullptr); + return int(z); +} + +int32_t getflorzofslopeptr(usectorptr_t sec, int32_t dax, int32_t day) +{ + float z; + calcSlope(sec, dax, day, nullptr, &z); + return int(z); +} + +void getzsofslopeptr(usectorptr_t sec, int32_t dax, int32_t day, int32_t* ceilz, int32_t* florz) +{ + float c, f; + calcSlope(sec, dax, day, &c, &f); + *ceilz = int(c); + *florz = int(f); +} + + //========================================================================== // // Calculate the position of a wall sprite in the world diff --git a/source/core/maploader.cpp b/source/core/maploader.cpp index 556c1b5cb..b8f48a6ff 100644 --- a/source/core/maploader.cpp +++ b/source/core/maploader.cpp @@ -59,6 +59,14 @@ TArray wall; TArray sectorbackup; TArray wallbackup; +void walltype::calcLength() +{ + lengthflags &= ~1; + point2Wall()->lengthflags &= ~2; + auto d = delta(); + length = (int)sqrt(d.x * d.x + d.y * d.y) << 5; +} + // needed for skipping over to get the map size first. enum { diff --git a/source/core/maptypes.h b/source/core/maptypes.h index 3a73e8f9b..940c979ab 100644 --- a/source/core/maptypes.h +++ b/source/core/maptypes.h @@ -334,6 +334,8 @@ struct walltype int deltax() const { return point2Wall()->x - x; } int deltay() const { return point2Wall()->y - y; } bool twoSided() const { return nextsector >= 0; } + int Length(); + void calcLength(); // this is deliberately not inlined and stored in a file where it can't be found at compile time. void move(int newx, int newy); void moved(); @@ -649,6 +651,16 @@ inline void walltype::move(int newx, int newy) sectorp()->dirty = EDirty::AllDirty; } +inline int walltype::Length() +{ + if ((lengthflags & 1) || (point2Wall()->lengthflags & 2)) + { + // value is stale, recreate + calcLength(); + } + return length; +} + //============================================================================= // // Map loader stuff diff --git a/source/games/blood/src/_polymost.cpp b/source/games/blood/src/_polymost.cpp index 24dc19ebc..493fe0d39 100644 --- a/source/games/blood/src/_polymost.cpp +++ b/source/games/blood/src/_polymost.cpp @@ -19,7 +19,7 @@ void collectTSpritesForPortal(int x, int y, int i, int interpolation) int top, bottom; GetSpriteExtents(pSprite, &top, &bottom); int zCeil, zFloor; - getzsofslope(nSector, pSprite->x, pSprite->y, &zCeil, &zFloor); + getzsofslopeptr(§or[nSector], pSprite->x, pSprite->y, &zCeil, &zFloor); if (pSprite->statnum == kStatDude && (top < zCeil || bottom > zFloor)) { int j = i;