- redid clipinsidebox* functions.

* Completely rewritten to be less obtuse.
* Consolidated the two variants.
* Renamed to be clearer about what they do.
This commit is contained in:
Christoph Oelckers 2022-08-17 23:24:44 +02:00
parent b9d0c9d6ba
commit 3a9f9988f4
8 changed files with 67 additions and 121 deletions

View file

@ -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,

View file

@ -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;
}

View file

@ -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.

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

@ -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;
}