- new floating point version of clipmove's wall sprite checker.

This commit is contained in:
Christoph Oelckers 2022-10-23 18:41:56 +02:00 committed by Christoph Oelckers
parent 5e4f638e83
commit 38b49e1a09
3 changed files with 64 additions and 52 deletions

View file

@ -43,16 +43,6 @@ static inline int bcos(const int ang)
inline uint8_t bitmap_test(uint8_t const* const ptr, int const n) { return ptr[n >> 3] & (1 << (n & 7)); }
// x1, y1: in/out
// rest x/y: out
static inline void get_wallspr_points(DCoreActor* actor, int32_t *x1, int32_t *x2, int32_t *y1, int32_t *y2)
{
DVector2 out[2];
GetWallSpritePosition(&actor->spr, DVector2(*x1 * inttoworld, *y1 * inttoworld), out);
*x1 = int(out[0].X * worldtoint); *y1 = int(out[0].Y * worldtoint);
*x2 = int(out[1].X * worldtoint); *y2 = int(out[1].Y * worldtoint);
}
// x1, y1: in/out
// rest x/y: out
static inline void get_floorspr_points(DCoreActor *spr, int32_t px, int32_t py,
@ -241,6 +231,10 @@ CollisionBase clipmove_(vec3_t * const pos, int * const sectnum, int32_t xvect,
clip.ceilingdist = ceildist * zinttoworld;
clip.floordist = flordist * zinttoworld;
clip.walldist = walldist * inttoworld;
clip.pos = { pos->X * inttoworld, pos->Y * inttoworld, pos->Z * zinttoworld };
clip.dest = { goal.X * inttoworld, goal.Y * inttoworld };
clip.center = (clip.pos.XY() + clip.dest) * 0.5;
clip.movedist = clip.moveDelta.Length() + clip.walldist + 0.5 + MAXCLIPDIST * inttoworld;
int clipsectcnt = 0;
int clipspritecnt = 0;
@ -259,7 +253,6 @@ CollisionBase clipmove_(vec3_t * const pos, int * const sectnum, int32_t xvect,
do
{
int const dasect = clipsectorlist[clipsectcnt++];
clip.pos = { pos->X * inttoworld, pos->Y * inttoworld, pos->Z * zinttoworld };
////////// Walls //////////
processClipWalls(clip, &sector[dasect]);
@ -292,43 +285,11 @@ CollisionBase clipmove_(vec3_t * const pos, int * const sectnum, int32_t xvect,
switch (cstat & (CSTAT_SPRITE_ALIGNMENT_MASK))
{
case CSTAT_SPRITE_ALIGNMENT_FACING:
processClipFaceSprites(clip, actor);
processClipFaceSprite(clip, actor);
break;
case CSTAT_SPRITE_ALIGNMENT_WALL:
{
double height_, daz_ = actor->spr.pos.Z + actor->GetOffsetAndHeight(height_);
int height = int(height_ * zworldtoint), daz = int(daz_ * zworldtoint);
if (pos->Z > daz-height-flordist && pos->Z < daz+ceildist)
{
vec2_t p2;
get_wallspr_points(actor, &p1.X, &p2.X, &p1.Y, &p2.Y);
if (clipinsideboxline(cent.X, cent.Y, p1.X, p1.Y, p2.X, p2.Y, rad) != 0)
{
vec2_t v = { MulScale(bcos(actor->int_ang() + 256), walldist, 14),
MulScale(bsin(actor->int_ang() + 256), walldist, 14) };
if ((p1.X-pos->X) * (p2.Y-pos->Y) >= (p2.X-pos->X) * (p1.Y-pos->Y)) // Front
addclipline(p1.X+v.X, p1.Y+v.Y, p2.X+v.Y, p2.Y-v.X, obj, false);
else
{
if ((cstat & CSTAT_SPRITE_ONE_SIDE) != 0)
continue;
addclipline(p2.X-v.X, p2.Y-v.Y, p1.X-v.Y, p1.Y+v.X, obj, false);
}
//Side blocker
if ((p2.X-p1.X) * (pos->X-p1.X)+(p2.Y-p1.Y) * (pos->Y-p1.Y) < 0)
addclipline(p1.X-v.Y, p1.Y+v.X, p1.X+v.X, p1.Y+v.Y, obj, true);
else if ((p1.X-p2.X) * (pos->X-p2.X)+(p1.Y-p2.Y) * (pos->Y-p2.Y) < 0)
addclipline(p2.X+v.Y, p2.Y-v.X, p2.X-v.X, p2.Y-v.Y, obj, true);
}
}
break;
}
processClipWallSprite(clip, actor);
case CSTAT_SPRITE_ALIGNMENT_FLOOR:
case CSTAT_SPRITE_ALIGNMENT_SLOPE:

View file

@ -1269,11 +1269,11 @@ static int checkClipWall(const MoveClipper& clip, walltype* wal)
static void addPointToClipList(MoveClipper& clip, const DVector2& pos, double radius, CollisionBase& objtype)
{
double waldist = (clip.moveDelta.X < 0)? radius : -radius;
addClipLine(clip, pos + DVector2(waldist, waldist), pos + DVector2(waldist, -waldist), objtype);
double waldistx = (clip.moveDelta.X < 0)? radius : -radius;
addClipLine(clip, pos + DVector2(waldistx, waldistx), pos + DVector2(waldistx, -waldistx), objtype);
waldist = (clip.moveDelta.Y < 0) ? radius : -radius;
addClipLine(clip, pos + DVector2(-waldist, waldist), pos + DVector2(waldist, waldist), objtype);
double waldisty = (clip.moveDelta.Y < 0) ? radius : -radius;
addClipLine(clip, pos + DVector2(-waldisty, waldisty), pos + DVector2(waldisty, waldisty), objtype);
}
//==========================================================================
@ -1344,7 +1344,7 @@ void processClipWalls(MoveClipper& clip, sectortype* sec)
//
//==========================================================================
void processClipFaceSprites(MoveClipper& clip, DCoreActor* actor)
void processClipFaceSprite(MoveClipper& clip, DCoreActor* actor)
{
auto spos = actor->spr.pos;
if (!PointInRect(spos.XY(), clip.rect.min, clip.rect.max)) return; // are we outside this sprite's bounding box?
@ -1368,6 +1368,54 @@ void processClipFaceSprites(MoveClipper& clip, DCoreActor* actor)
//
//==========================================================================
void processClipWallSprite(MoveClipper& clip, DCoreActor* actor)
{
auto spos = actor->spr.pos;
double height, z = spos.Z + actor->GetOffsetAndHeight(height);
if (clip.pos.Z <= z - height - clip.floordist) return; // are we above the sprite?
if (clip.pos.Z >= z + clip.ceilingdist) return; // are we below the sprite?
DVector2 points[2];
GetWallSpritePosition(&actor->spr, actor->spr.pos.XY(), points, false);
if (IsCloseToLine(clip.center, points[0], points[1], clip.movedist) == EClose::Outside) return; // out of reach
CollisionBase objtype;
objtype.setSprite(actor);
auto offset = (actor->spr.Angles.Yaw + DAngle45).ToVector() * clip.walldist; // Ok, why 45°?
auto d = points[1] - points[0];
if (PointOnLineSide(clip.pos.X, clip.pos.Y, points[0].X, points[0].Y, d.X, d.Y) <= 0)
{
// in front
addClipLine(clip, points[0] + offset, points[1] + offset.Rotated90CW(), objtype);
}
else if (!(actor->spr.cstat & CSTAT_SPRITE_ONE_SIDE))
{
// behind
addClipLine(clip, points[0] - offset, points[1] + offset.Rotated90CCW(), objtype);
}
else return; // one-sided wall sprite from the back side does not count.
if (d.dot(clip.pos.XY() - points[0]) < 0)
{
addClipLine(clip, points[0] + offset.Rotated90CCW(), points[0] + offset, objtype, true);
}
else if (d.dot(clip.pos.XY() - points[1]) > 0)
{
addClipLine(clip, points[1] + offset.Rotated90CW(), points[1] - offset, objtype, true);
}
}
//==========================================================================
//
//
//
//==========================================================================
int FindBestSector(const DVector3& pos)
{
int bestnum = -1;

View file

@ -243,13 +243,15 @@ struct ClipRect
struct MoveClipper
{
DVector3 pos;
DVector2 pest;
DVector2 dest;
DVector2 center;
DVector2 moveDelta;
ClipRect rect;
EWallFlags wallflags;
double ceilingdist;
double floordist;
double walldist;
double movedist;
};
void addClipLine(MoveClipper& clip, const DVector2& start, const DVector2& end, const CollisionBase& daoval, int nofix = false);
@ -257,7 +259,8 @@ void addClipSect(MoveClipper& clip, int sec);
void processClipWalls(MoveClipper& clip, sectortype* sec);
void processClipFaceSprites(MoveClipper& clip, DCoreActor* actor);
void processClipFaceSprite(MoveClipper& clip, DCoreActor* actor);
void processClipWallSprite(MoveClipper& clip, DCoreActor* actor);
int FindBestSector(const DVector3& pos);