mirror of
https://github.com/ZDoom/Raze.git
synced 2024-11-26 05:51:30 +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)
|
if ((xvect|yvect) == 0 || *sectnum < 0)
|
||||||
return b;
|
return b;
|
||||||
|
|
||||||
DCoreActor* curspr=NULL; // non-NULL when handling sprite with sector-like clipping
|
|
||||||
|
|
||||||
int const initialsectnum = *sectnum;
|
int const initialsectnum = *sectnum;
|
||||||
|
|
||||||
int32_t const dawalclipmask = (cliptype & 65535); // CLIPMASK0 = 0x00010001 (in desperate need of getting fixed!)
|
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;
|
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 clipMin = { cent.X - rad, cent.Y - rad };
|
||||||
vec2_t const clipMax = { 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 clipsectcnt = 0;
|
||||||
int clipspritecnt = 0;
|
int clipspritecnt = 0;
|
||||||
|
@ -255,33 +263,44 @@ CollisionBase clipmove_(vec3_t * const pos, int * const sectnum, int32_t xvect,
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
int const dasect = clipsectorlist[clipsectcnt++];
|
int const dasect = clipsectorlist[clipsectcnt++];
|
||||||
//if (curspr)
|
|
||||||
// Printf("sprite %d/%d: sect %d/%d (%d)\n", clipspritecnt,clipspritenum, clipsectcnt,clipsectnum,dasect);
|
|
||||||
|
|
||||||
////////// Walls //////////
|
////////// Walls //////////
|
||||||
|
|
||||||
auto const sec = §or[dasect];
|
auto const sec = §or[dasect];
|
||||||
|
|
||||||
for (auto& wal : sec->walls)
|
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();
|
auto const wal2 = wal.point2Wall();
|
||||||
vec2_t p1 = wal.wall_int_pos();
|
vec2_t p1 = wal.wall_int_pos();
|
||||||
vec2_t p2 = wal2->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) ||
|
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))
|
(p1.Y < clipMin.Y && p2.Y < clipMin.Y) || (p1.Y > clipMax.Y && p2.Y > clipMax.Y))
|
||||||
|
{
|
||||||
|
assert(clipyou2 != 1);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
vec2_t d = { p2.X-p1.X, p2.Y-p1.Y };
|
vec2_t d = { p2.X-p1.X, p2.Y-p1.Y };
|
||||||
|
|
||||||
if (d.X * (pos->Y-p1.Y) < (pos->X-p1.X) * d.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 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) };
|
vec2_t v = { d.X * (r.Y - p1.Y), d.Y * (r.X - p1.X) };
|
||||||
|
|
||||||
if (v.X >= v.Y)
|
if (v.X >= v.Y)
|
||||||
|
{
|
||||||
|
assert(clipyou2 != 1);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
int clipyou = 0;
|
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);
|
ceildist * zinttoworld, flordist * zinttoworld, enginecompatibility_mode == ENGINECOMPATIBILITY_NONE);
|
||||||
v.X = int(ipos.X * worldtoint);
|
v.X = int(ipos.X * worldtoint);
|
||||||
v.Y = int(ipos.Y * 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)
|
if (clipyou)
|
||||||
{
|
{
|
||||||
CollisionBase objtype;
|
CollisionBase objtype;
|
||||||
if (curspr) objtype.setSprite(curspr);
|
objtype.setWall(&wal);
|
||||||
else objtype.setWall(&wal);
|
|
||||||
|
|
||||||
//Add 2 boxes at endpoints
|
//Add 2 boxes at endpoints
|
||||||
int32_t bsz = walldist; if (diff.X < 0) bsz = -bsz;
|
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(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);
|
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.X = walldist; if (d.Y > 0) v.X = -v.X;
|
||||||
v.Y = walldist; if (d.X < 0) v.Y = -v.Y;
|
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) &&
|
boxtl.Y < max(start.Y, end.Y) &&
|
||||||
boxbr.Y > min(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 FindBestSector(const DVector3& pos)
|
||||||
{
|
{
|
||||||
int bestnum = -1;
|
int bestnum = -1;
|
||||||
|
|
|
@ -234,8 +234,25 @@ inline int pushmove(DVector2& pos, double z, sectortype** pSect, double walldist
|
||||||
pos = vect.XY();
|
pos = vect.XY();
|
||||||
return result;
|
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);
|
int FindBestSector(const DVector3& pos);
|
||||||
|
|
Loading…
Reference in a new issue