diff --git a/source/build/include/clip.h b/source/build/include/clip.h index 092df4dde..c5271ce25 100644 --- a/source/build/include/clip.h +++ b/source/build/include/clip.h @@ -21,9 +21,6 @@ typedef struct extern int clipsectorlist[MAXCLIPSECTORS]; -int clipinsidebox(const vec2_t &vect, int wallnum, int walldist); -int clipinsideboxline(int x, int y, int x1, int y1, int x2, int y2, int walldist); - struct CollisionBase; CollisionBase clipmove_(vec3_t *const pos, int *const sectnum, int32_t xvect, int32_t yvect, int32_t const walldist, int32_t const ceildist, diff --git a/source/build/src/clip.cpp b/source/build/src/clip.cpp index d510b1b80..1431eb35c 100644 --- a/source/build/src/clip.cpp +++ b/source/build/src/clip.cpp @@ -59,68 +59,12 @@ static inline void get_floorspr_points(DCoreActor *spr, int32_t px, int32_t py, } -// -// clipinsidebox -// -int clipinsidebox(const vec2_t &vect, int wallnum, int walldist) -{ - int const r = walldist << 1; - - auto const wal1 = &wall[wallnum]; - auto const wal2 = wal1->point2Wall(); - - vec2_t const v1 = { wal1->wall_int_pos().X + walldist - vect.X, wal1->wall_int_pos().Y + walldist - vect.Y }; - vec2_t v2 = { wal2->wall_int_pos().X + walldist - vect.X, wal2->wall_int_pos().Y + walldist - vect.Y }; - - if (((v1.X < 0) && (v2.X < 0)) || ((v1.Y < 0) && (v2.Y < 0)) || ((v1.X >= r) && (v2.X >= r)) || ((v1.Y >= r) && (v2.Y >= r))) - return 0; - - v2.X -= v1.X; v2.Y -= v1.Y; - - if (v2.X * (walldist - v1.Y) >= v2.Y * (walldist - v1.X)) // Front - { - v2.X *= ((v2.X > 0) ? (0 - v1.Y) : (r - v1.Y)); - v2.Y *= ((v2.Y > 0) ? (r - v1.X) : (0 - v1.X)); - return v2.X < v2.Y; - } - - v2.X *= ((v2.X > 0) ? (r - v1.Y) : (0 - v1.Y)); - v2.Y *= ((v2.Y > 0) ? (0 - v1.X) : (r - v1.X)); - return (v2.X >= v2.Y) << 1; -} - // // clipinsideboxline // -int clipinsideboxline(int x, int y, int x1, int y1, int x2, int y2, int walldist) +static int clipinsideboxline(int x, int y, int x1, int y1, int x2, int y2, int walldist) { - int const r = walldist << 1; - - x1 += walldist - x; - x2 += walldist - x; - - if (((x1 < 0) && (x2 < 0)) || ((x1 >= r) && (x2 >= r))) - return 0; - - y1 += walldist - y; - y2 += walldist - y; - - if (((y1 < 0) && (y2 < 0)) || ((y1 >= r) && (y2 >= r))) - return 0; - - x2 -= x1; - y2 -= y1; - - if (x2 * (walldist - y1) >= y2 * (walldist - x1)) // Front - { - x2 *= ((x2 > 0) ? (0 - y1) : (r - y1)); - y2 *= ((y2 > 0) ? (r - x1) : (0 - x1)); - return x2 < y2; - } - - x2 *= ((x2 > 0) ? (r - y1) : (0 - y1)); - y2 *= ((y2 > 0) ? (0 - x1) : (r - x1)); - return (x2 >= y2) << 1; + return (int)IsCloseToLine(DVector2(x * inttoworld, y * inttoworld), DVector2(x1 * inttoworld, y1 * inttoworld), DVector2(x2 * inttoworld, y2 * inttoworld), walldist * inttoworld); } static int32_t clipmove_warned; @@ -896,7 +840,7 @@ int pushmove_(vec3_t *const vect, int *const sectnum, int i; for (i=startwall, wal=&wall[startwall]; i!=endwall; i+=dir, wal+=dir) - if (clipinsidebox(vect->vec2, i, walldist-4) == 1) + if (IsCloseToWall(DVector2(vect->X * inttoworld, vect->Y * inttoworld), &wall[i], (walldist-4) * inttoworld) == EClose::InFront) { int j = 0; if (wal->nextsector < 0 || wal->cstat & EWallFlags::FromInt(dawalclipmask)) j = 1; @@ -918,7 +862,7 @@ int pushmove_(vec3_t *const vect, int *const sectnum, { vect->X = (vect->X) + dx; vect->Y = (vect->Y) + dy; bad2--; if (bad2 == 0) break; - } while (clipinsidebox(vect->vec2, i, walldist-4) != 0); + } while (IsCloseToWall(DVector2(vect->X * inttoworld, vect->Y * inttoworld), &wall[i], (walldist - 4) * inttoworld) != EClose::Outside); bad = -1; k--; if (k <= 0) return bad; clipupdatesector(vect->vec2, sectnum, walldist); @@ -1451,4 +1395,3 @@ int hitscan(const vec3_t& start, const sectortype* startsect, const vec3_t& dire return 0; } - diff --git a/source/core/gamefuncs.cpp b/source/core/gamefuncs.cpp index fe5fbb7c8..c7a9f4beb 100644 --- a/source/core/gamefuncs.cpp +++ b/source/core/gamefuncs.cpp @@ -393,6 +393,48 @@ void GetFlatSpritePosition(const tspritetype* spr, const DVector2& pos, DVector2 TGetFlatSpritePosition(spr, pos, out, outz, tspriteGetSlope(spr), render); } +//========================================================================== +// +// checks if the given point is sufficiently close to the given line segment. +// +//========================================================================== + +EClose IsCloseToLine(const DVector2& point, const DVector2& start, const DVector2& end, double maxdist) +{ + auto const v1 = start - point; + auto const v2 = end - point; + + // trivially outside the box. + if ( + ((v1.X < -maxdist) && (v2.X < -maxdist)) || // fully to the left + ((v1.Y < -maxdist) && (v2.Y < -maxdist)) || // fully below + ((v1.X >= maxdist) && (v2.X >= maxdist)) || // fully to the right + ((v1.Y >= maxdist) && (v2.Y >= maxdist))) // fully above + return EClose::Outside; + + auto waldelta = end - start; + + if (waldelta.X * v1.Y <= waldelta.Y * v1.X) + { + // is it in front? + waldelta.X *= waldelta.X > 0 ? v1.Y + maxdist : v1.Y - maxdist; + waldelta.Y *= waldelta.Y > 0 ? v1.X - maxdist : v1.X + maxdist; + return waldelta.X > waldelta.Y ? EClose::InFront : EClose::Outside; + } + else + { + // or behind? + waldelta.X *= waldelta.X > 0 ? v1.Y - maxdist : v1.Y + maxdist; + waldelta.Y *= waldelta.Y > 0 ? v1.X + maxdist : v1.X - maxdist; + return (waldelta.X <= waldelta.Y) ? EClose::Behind : EClose::Outside; + } +} + +EClose IsCloseToWall(const DVector2& point, walltype* wal, double maxdist) +{ + return IsCloseToLine(point, wal->pos, wal->point2Wall()->pos, maxdist); +} + //========================================================================== // // Check if some walls are set to use rotated textures. diff --git a/source/core/gamefuncs.h b/source/core/gamefuncs.h index 88483afbd..fdd14722e 100644 --- a/source/core/gamefuncs.h +++ b/source/core/gamefuncs.h @@ -268,6 +268,16 @@ void setWallSectors(); void GetWallSpritePosition(const spritetypebase* spr, const DVector2& pos, DVector2* out, bool render = false); void GetFlatSpritePosition(DCoreActor* spr, const DVector2& pos, DVector2* out, bool render = false); void GetFlatSpritePosition(const tspritetype* spr, const DVector2& pos, DVector2* out, double* outz, bool render = false); + +enum class EClose +{ + Outside, + InFront, + Behind +}; +EClose IsCloseToLine(const DVector2& vect, const DVector2& start, const DVector2& end, double walldist); +EClose IsCloseToWall(const DVector2& vect, walltype* wal, double walldist); + void checkRotatedWalls(); bool sectorsConnected(int sect1, int sect2); void dragpoint(walltype* wal, int newx, int newy); @@ -288,11 +298,6 @@ inline double getflorzofslopeptrf(const sectortype* sec, double dax, double day) { return getflorzofslopeptr(sec, dax * worldtoint, day * worldtoint) * zinttoworld; } -[[deprecated]] -inline void getzsofslopeptrf(const sectortype* sec, double dax, double day, double* ceilz, double* florz) -{ - getzsofslopeptr(sec, dax, day, ceilz, florz); -} enum EFindNextSector @@ -314,19 +319,6 @@ sectortype* nextsectorneighborzptr(sectortype* sectp, int startz, int flags); -// y is negated so that the orientation is the same as in GZDoom, in order to use its utilities. -// The render code should NOT use Build coordinates for anything! - -inline double RenderX(int x) -{ - return x * (1 / 16.); -} - -inline double RenderY(int y) -{ - return y * (1 / -16.); -} - inline double WallStartX(int wallnum) { return wall[wallnum].pos.X; diff --git a/source/core/sectorgeometry.cpp b/source/core/sectorgeometry.cpp index 26ee264de..a1d4e21cb 100644 --- a/source/core/sectorgeometry.cpp +++ b/source/core/sectorgeometry.cpp @@ -232,8 +232,8 @@ static int OutlineToFloat(Outline& outl, FOutline& polygon) count += outl[i].Size(); for (unsigned j = 0; j < outl[i].Size(); j++) { - float X = RenderX(outl[i][j].X); - float Y = RenderY(outl[i][j].Y); + float X = (outl[i][j].X) * inttoworld; + float Y = (outl[i][j].Y) * -inttoworld; if (fabs(X) > 32768.f || fabs(Y) > 32768.f) { // If we get here there's some fuckery going around with the coordinates. Let's better abort and wait for things to realign. @@ -241,8 +241,8 @@ static int OutlineToFloat(Outline& outl, FOutline& polygon) return -1; } polygon[i][j] = { X, Y }; - } } + } return count; } diff --git a/source/games/duke/src/actors.cpp b/source/games/duke/src/actors.cpp index 6134a0a34..32d561688 100644 --- a/source/games/duke/src/actors.cpp +++ b/source/games/duke/src/actors.cpp @@ -3537,7 +3537,7 @@ void handle_se11(DDukeActor *actor) DukeStatIterator it(STAT_ACTOR); while (auto ac = it.Next()) { - if (ac->spr.extra > 0 && badguy(ac) && clipinsidebox(ac->int_pos().vec2, wallnum(&wal), 256) == 1) + if (ac->spr.extra > 0 && badguy(ac) && IsCloseToWall(ac->spr.pos.XY(), &wal, 16) == EClose::InFront) return; } } @@ -3553,7 +3553,7 @@ void handle_se11(DDukeActor *actor) DukeStatIterator it(STAT_PLAYER); while (auto ac = it.Next()) { - if (ac->GetOwner() && clipinsidebox(ac->int_pos().vec2, wallnum(&wal), 144) == 1) + if (ac->GetOwner() && IsCloseToWall(ac->spr.pos.XY(), &wal, 9) == EClose::InFront) { actor->temp_data[5] = 8; // Delay actor->temp_data[2] -= k; diff --git a/source/games/exhumed/src/move.cpp b/source/games/exhumed/src/move.cpp index a0446752b..ab5566091 100644 --- a/source/games/exhumed/src/move.cpp +++ b/source/games/exhumed/src/move.cpp @@ -237,7 +237,7 @@ void clipwall() } -int BelowNear(DExhumedActor* pActor, int x, int y, int walldist) +int BelowNear(DExhumedActor* pActor, double walldist) { auto pSector = pActor->sector(); int z = pActor->int_pos().Z; @@ -263,8 +263,7 @@ int BelowNear(DExhumedActor* pActor, int x, int y, int walldist) { if (!search.Check(wal.nextSector())) { - vec2_t pos = { x, y }; - if (clipinsidebox(pos, wallnum(&wal), walldist)) + if (IsCloseToWall(pActor->spr.pos, &wal, walldist) != EClose::Outside) { search.Add(wal.nextSector()); } @@ -470,7 +469,7 @@ Collision movespritez(DExhumedActor* pActor, int z, int height, int, int clipdis if (pActor->spr.statnum == 100) { - nRet.exbits |= BelowNear(pActor, pActor->int_pos().X, pActor->int_pos().Y, clipdist + (clipdist / 2)); + nRet.exbits |= BelowNear(pActor, clipdist * (inttoworld * 1.5)); } return nRet; diff --git a/source/games/sw/src/weapon.cpp b/source/games/sw/src/weapon.cpp index 082f0ca19..64619b3c1 100644 --- a/source/games/sw/src/weapon.cpp +++ b/source/games/sw/src/weapon.cpp @@ -13840,36 +13840,9 @@ int InitSerpSlash(DSWActor* actor) bool WallSpriteInsideSprite(DSWActor* wactor, DSWActor* actor) { - int x1, y1, x2, y2; - int xoff; - int dax, day; - int xsiz, mid_dist; - - x1 = wactor->int_pos().X; - y1 = wactor->int_pos().Y; - - xoff = (int) tileLeftOffset(wactor->spr.picnum) + (int) wactor->spr.xoffset; - - if ((wactor->spr.cstat & CSTAT_SPRITE_XFLIP)) - xoff = -xoff; - - // x delta - dax = bsin(wactor->int_ang()) * wactor->spr.xrepeat; - // y delta - day = -bcos(wactor->int_ang()) * wactor->spr.xrepeat; - - xsiz = tileWidth(wactor->spr.picnum); - mid_dist = (xsiz >> 1) + xoff; - - // starting from the center find the first point - x1 -= MulScale(dax, mid_dist, 16); - // starting from the first point find the end point - x2 = x1 + MulScale(dax, xsiz, 16); - - y1 -= MulScale(day, mid_dist, 16); - y2 = y1 + MulScale(day, xsiz, 16); - - return !!clipinsideboxline(actor->int_pos().X, actor->int_pos().Y, x1, y1, x2, y2, ((int) actor->spr.clipdist) << 2); + DVector2 out[2]; + GetWallSpritePosition(&wactor->spr, wactor->spr.pos, out); + return IsCloseToLine(actor->spr.pos.XY(), out[0], out[1], (((int) actor->spr.clipdist) << 2) * inttoworld) != EClose::Outside; }