mirror of
https://github.com/ZDoom/Raze.git
synced 2024-11-22 12:11:17 +00:00
- reimplemented the wall collision check for clipmove.
This commit is contained in:
parent
aed69bd4c2
commit
9b8252e2da
4 changed files with 85 additions and 25 deletions
|
@ -221,8 +221,6 @@ CollisionBase clipmove_(vec3_t * const pos, int * const sectnum, int32_t xvect,
|
|||
if ((xvect|yvect) == 0 || *sectnum < 0)
|
||||
return b;
|
||||
|
||||
DCoreActor* curspr=NULL; // non-NULL when handling sprite with sector-like clipping
|
||||
|
||||
int const initialsectnum = *sectnum;
|
||||
|
||||
int32_t const dawalclipmask = (cliptype & 65535); // CLIPMASK0 = 0x00010001 (in desperate need of getting fixed!)
|
||||
|
@ -237,6 +235,16 @@ CollisionBase clipmove_(vec3_t * const pos, int * const sectnum, int32_t xvect,
|
|||
int32_t const rad = ksqrt((int64_t)diff.X * diff.X + (int64_t)diff.Y * diff.Y) + MAXCLIPDIST + walldist + 8;
|
||||
vec2_t const clipMin = { cent.X - rad, cent.Y - rad };
|
||||
vec2_t const clipMax = { cent.X + rad, cent.Y + rad };
|
||||
|
||||
MoveClipper clip;
|
||||
|
||||
clip.moveDelta = { (xvect >> 14) * inttoworld, (yvect >> 14) * inttoworld }; // beware of excess precision here!
|
||||
clip.rect.min = { clipMin.X * inttoworld, clipMin.Y * inttoworld };
|
||||
clip.rect.max = { clipMax.X * inttoworld, clipMax.Y * inttoworld };
|
||||
clip.wallflags = EWallFlags::FromInt(dawalclipmask);
|
||||
clip.ceilingdist = ceildist * zinttoworld;
|
||||
clip.floordist = flordist * zinttoworld;
|
||||
clip.walldist = walldist * inttoworld;
|
||||
|
||||
int clipsectcnt = 0;
|
||||
int clipspritecnt = 0;
|
||||
|
@ -255,33 +263,44 @@ CollisionBase clipmove_(vec3_t * const pos, int * const sectnum, int32_t xvect,
|
|||
do
|
||||
{
|
||||
int const dasect = clipsectorlist[clipsectcnt++];
|
||||
//if (curspr)
|
||||
// Printf("sprite %d/%d: sect %d/%d (%d)\n", clipspritecnt,clipspritenum, clipsectcnt,clipsectnum,dasect);
|
||||
|
||||
|
||||
////////// Walls //////////
|
||||
|
||||
auto const sec = §or[dasect];
|
||||
|
||||
for (auto& wal : sec->walls)
|
||||
{
|
||||
clip.pos = { pos->X * inttoworld, pos->Y * inttoworld, pos->Z * zinttoworld};
|
||||
|
||||
int clipyou2 = checkClipWall(clip, &wal);
|
||||
|
||||
auto const wal2 = wal.point2Wall();
|
||||
vec2_t p1 = wal.wall_int_pos();
|
||||
vec2_t p2 = wal2->wall_int_pos();
|
||||
|
||||
if ((p1.X < clipMin.X && p2.X < clipMin.X) || (p1.X > clipMax.X && p2.X > clipMax.X) ||
|
||||
(p1.Y < clipMin.Y && p2.Y < clipMin.Y) || (p1.Y > clipMax.Y && p2.Y > clipMax.Y))
|
||||
{
|
||||
assert(clipyou2 != 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
vec2_t d = { p2.X-p1.X, p2.Y-p1.Y };
|
||||
|
||||
if (d.X * (pos->Y-p1.Y) < (pos->X-p1.X) * d.Y)
|
||||
continue; //If wall's not facing you
|
||||
{
|
||||
assert(clipyou2 != 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
vec2_t const r = { (d.Y > 0) ? clipMax.X : clipMin.X, (d.X > 0) ? clipMin.Y : clipMax.Y };
|
||||
vec2_t v = { d.X * (r.Y - p1.Y), d.Y * (r.X - p1.X) };
|
||||
|
||||
if (v.X >= v.Y)
|
||||
{
|
||||
assert(clipyou2 != 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
int clipyou = 0;
|
||||
|
||||
|
@ -297,31 +316,14 @@ CollisionBase clipmove_(vec3_t * const pos, int * const sectnum, int32_t xvect,
|
|||
ceildist * zinttoworld, flordist * zinttoworld, enginecompatibility_mode == ENGINECOMPATIBILITY_NONE);
|
||||
v.X = int(ipos.X * worldtoint);
|
||||
v.Y = int(ipos.Y * worldtoint);
|
||||
|
||||
}
|
||||
|
||||
// We're not interested in any sector reached by portal traversal that we're "inside" of.
|
||||
if (enginecompatibility_mode == ENGINECOMPATIBILITY_NONE && !curspr && dasect != initialsectnum
|
||||
&& inside(pos->X * inttoworld, pos->Y * inttoworld, sec) == 1)
|
||||
{
|
||||
bool found = false;
|
||||
for (auto& wwal : sec->walls)
|
||||
{
|
||||
if (wwal.nextsector == initialsectnum)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
break;
|
||||
}
|
||||
|
||||
assert(clipyou == clipyou2);
|
||||
if (clipyou)
|
||||
{
|
||||
CollisionBase objtype;
|
||||
if (curspr) objtype.setSprite(curspr);
|
||||
else objtype.setWall(&wal);
|
||||
objtype.setWall(&wal);
|
||||
|
||||
//Add 2 boxes at endpoints
|
||||
int32_t bsz = walldist; if (diff.X < 0) bsz = -bsz;
|
||||
|
@ -331,6 +333,7 @@ CollisionBase clipmove_(vec3_t * const pos, int * const sectnum, int32_t xvect,
|
|||
addclipline(p1.X+bsz, p1.Y-bsz, p1.X-bsz, p1.Y-bsz, objtype, false);
|
||||
addclipline(p2.X+bsz, p2.Y-bsz, p2.X-bsz, p2.Y-bsz, objtype, false);
|
||||
|
||||
vec2_t v;
|
||||
v.X = walldist; if (d.Y > 0) v.X = -v.X;
|
||||
v.Y = walldist; if (d.X < 0) v.Y = -v.Y;
|
||||
|
||||
|
|
|
@ -232,3 +232,11 @@ inline bool BoxInRange(const DVector2& boxtl, const DVector2& boxbr, const DVect
|
|||
boxtl.Y < max(start.Y, end.Y) &&
|
||||
boxbr.Y > min(start.Y, end.Y);
|
||||
}
|
||||
|
||||
inline bool BoxInRange2(const DVector2& boxtl, const DVector2& boxbr, const DVector2& start, const DVector2& end)
|
||||
{
|
||||
return boxtl.X <= max(start.X, end.X) &&
|
||||
boxbr.X >= min(start.X, end.X) &&
|
||||
boxtl.Y <= max(start.Y, end.Y) &&
|
||||
boxbr.Y >= min(start.Y, end.Y);
|
||||
}
|
||||
|
|
|
@ -1230,6 +1230,38 @@ int pushmove(DVector3& pos, sectortype** pSect, double walldist, double ceildist
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int checkClipWall(const MoveClipper& clip, walltype* wal)
|
||||
{
|
||||
auto wal2 = wal->point2Wall();
|
||||
auto waldelta = wal->delta();
|
||||
|
||||
// out of reach?
|
||||
if (!BoxInRange2(clip.rect.min, clip.rect.max, wal->pos, wal2->pos)) return -1;
|
||||
|
||||
// facing back side?
|
||||
if (PointOnLineSide(clip.pos.XY(), wal) > 0) return -1;
|
||||
|
||||
// do we touch it?
|
||||
if (BoxOnLineSide(clip.rect.min, clip.rect.max, wal->pos, waldelta) != -1) return -1;
|
||||
|
||||
if (!wal->twoSided() || (wal->cstat & clip.wallflags))
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
DVector2 intersect;
|
||||
double factor = InterceptLineSegments(clip.pos.X, clip.pos.Y, clip.moveDelta.X, clip.moveDelta.Y, wal->pos.X, wal->pos.Y, waldelta.X, waldelta.Y);
|
||||
if (factor < 0) intersect = clip.pos.XY();
|
||||
else intersect = clip.pos.XY() + clip.moveDelta * factor;
|
||||
return checkOpening(intersect, clip.pos.Z, wal->sectorp(), wal->nextSector(), clip.ceilingdist, clip.floordist);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FindBestSector(const DVector3& pos)
|
||||
{
|
||||
int bestnum = -1;
|
||||
|
|
|
@ -234,8 +234,25 @@ inline int pushmove(DVector2& pos, double z, sectortype** pSect, double walldist
|
|||
pos = vect.XY();
|
||||
return result;
|
||||
}
|
||||
struct ClipRect
|
||||
{
|
||||
DVector2 min;
|
||||
DVector2 max;
|
||||
};
|
||||
|
||||
struct MoveClipper
|
||||
{
|
||||
DVector3 pos;
|
||||
DVector2 pest;
|
||||
DVector2 moveDelta;
|
||||
ClipRect rect;
|
||||
EWallFlags wallflags;
|
||||
double ceilingdist;
|
||||
double floordist;
|
||||
double walldist;
|
||||
};
|
||||
|
||||
int checkClipWall(const MoveClipper& clip, walltype* wal);
|
||||
|
||||
|
||||
int FindBestSector(const DVector3& pos);
|
||||
|
|
Loading…
Reference in a new issue