From 38b49e1a098958ad08f00598a32669e51886e2c7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 23 Oct 2022 18:41:56 +0200 Subject: [PATCH] - new floating point version of clipmove's wall sprite checker. --- source/build/src/clip.cpp | 51 ++++------------------------------ source/core/gamefuncs.cpp | 58 +++++++++++++++++++++++++++++++++++---- source/core/gamefuncs.h | 7 +++-- 3 files changed, 64 insertions(+), 52 deletions(-) diff --git a/source/build/src/clip.cpp b/source/build/src/clip.cpp index a4bda1909..95defa402 100644 --- a/source/build/src/clip.cpp +++ b/source/build/src/clip.cpp @@ -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, §or[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: diff --git a/source/core/gamefuncs.cpp b/source/core/gamefuncs.cpp index e0e85d5c9..cc1aea567 100644 --- a/source/core/gamefuncs.cpp +++ b/source/core/gamefuncs.cpp @@ -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; diff --git a/source/core/gamefuncs.h b/source/core/gamefuncs.h index 3c64c1713..f332e8b98 100644 --- a/source/core/gamefuncs.h +++ b/source/core/gamefuncs.h @@ -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);