From c24251431ccd5c1f69eecacde6126f0bdb182504 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 23 Oct 2022 21:19:09 +0200 Subject: [PATCH] - float version of clipmove's slope sprite collector. This could be simplified quite a bit by leveraging the info returned by GetFlatSpritePosition. --- source/build/src/clip.cpp | 67 ++------------------------------------- source/core/gamefuncs.cpp | 56 +++++++++++++++++++++++++++++--- source/core/gamefuncs.h | 3 +- 3 files changed, 57 insertions(+), 69 deletions(-) diff --git a/source/build/src/clip.cpp b/source/build/src/clip.cpp index 7d26269d7..5789c28d6 100644 --- a/source/build/src/clip.cpp +++ b/source/build/src/clip.cpp @@ -236,17 +236,12 @@ CollisionBase clipmove_(vec3_t * const pos, int * const sectnum, int32_t xvect, TSectIterator it(dasect); while (auto actor = it.Next()) { - const int32_t cstat = actor->spr.cstat; + int cstat = actor->spr.cstat; if (actor->spr.cstat2 & CSTAT2_SPRITE_NOFIND) continue; - if ((cstat&dasprclipmask) == 0) + if ((cstat & dasprclipmask) == 0) continue; - auto p1 = actor->int_pos().vec2; - - CollisionBase obj; - obj.setSprite(actor); - switch (cstat & (CSTAT_SPRITE_ALIGNMENT_MASK)) { case CSTAT_SPRITE_ALIGNMENT_FACING: @@ -262,63 +257,7 @@ CollisionBase clipmove_(vec3_t * const pos, int * const sectnum, int32_t xvect, break; case CSTAT_SPRITE_ALIGNMENT_SLOPE: - { - - if (!processClipFloorSprite(clip, actor)) continue; - int heinum = spriteGetSlope(actor); - - if (heinum == 0) continue; - - // the rest is for slope sprites only. - const int32_t tilenum = actor->spr.picnum; - const int32_t cosang = bcos(actor->int_ang()); - const int32_t sinang = bsin(actor->int_ang()); - vec2_t const span = { tileWidth(tilenum), tileHeight(tilenum) }; - vec2_t const repeat = { int(actor->spr.scale.X * scaletoint), int(actor->spr.scale.Y * scaletoint) }; - vec2_t adjofs = { tileLeftOffset(tilenum), tileTopOffset(tilenum) }; - - if (actor->spr.cstat & CSTAT_SPRITE_XFLIP) - adjofs.X = -adjofs.X; - - if (actor->spr.cstat & CSTAT_SPRITE_YFLIP) - adjofs.Y = -adjofs.Y; - - int32_t const centerx = ((span.X >> 1) + adjofs.X) * repeat.X; - int32_t const centery = ((span.Y >> 1) + adjofs.Y) * repeat.Y; - int32_t const rspanx = span.X * repeat.X; - int32_t const rspany = span.Y * repeat.Y; - int32_t const ratio = ksqrt(heinum * heinum + SLOPEVAL_FACTOR * SLOPEVAL_FACTOR); - int32_t zz[3] = { pos->Z, pos->Z + flordist, pos->Z - ceildist }; - for (int k = 0; k < 3; k++) - { - int32_t jj = DivScale(actor->int_pos().Z - zz[k], heinum, 18); - int32_t jj2 = MulScale(jj, ratio, 12); - if (jj2 > (centery << 8) || jj2 < ((centery - rspany) << 8)) - continue; - int32_t x1 = actor->int_pos().X + MulScale(sinang, centerx, 16) + MulScale(jj, cosang, 24); - int32_t y1 = actor->int_pos().Y - MulScale(cosang, centerx, 16) + MulScale(jj, sinang, 24); - int32_t x2 = x1 - MulScale(sinang, rspanx, 16); - int32_t y2 = y1 + MulScale(cosang, rspanx, 16); - - vec2_t const v = { MulScale(bcos(actor->int_ang() - 256), walldist, 14), - MulScale(bsin(actor->int_ang() - 256), walldist, 14) }; - - if (clipinsideboxline(cent.X, cent.Y, x1, y1, x2, y2, rad) != 0) - { - if ((x1 - pos->X) * (y2 - pos->Y) >= (x2 - pos->X) * (y1 - pos->Y)) - { - addclipline(x1 + v.X, y1 + v.Y, x2 + v.Y, y2 - v.X, obj, false); - } - else - { - if ((cstat & CSTAT_SPRITE_ONE_SIDE) != 0) - continue; - addclipline(x2 - v.X, y2 - v.Y, x1 - v.Y, y1 + v.X, obj, false); - } - } - } - break; - } + processClipSlopeSprite(clip, actor); } } } while (clipsectcnt < clipsectnum || clipspritecnt < clipspritenum); diff --git a/source/core/gamefuncs.cpp b/source/core/gamefuncs.cpp index ddb2182c7..7be3a53b4 100644 --- a/source/core/gamefuncs.cpp +++ b/source/core/gamefuncs.cpp @@ -1435,14 +1435,13 @@ void processClipWallSprite(MoveClipper& clip, DCoreActor* actor) } } - //========================================================================== // // // //========================================================================== -bool processClipFloorSprite(MoveClipper& clip, DCoreActor* actor) +bool processClipFloorSprite(MoveClipper& clip, DCoreActor* actor, DVector2* points, double* heights) { int heinum = spriteGetSlope(actor); double sprz = spriteGetZOfSlopef(&actor->spr, actor->spr.pos, heinum); @@ -1454,8 +1453,9 @@ bool processClipFloorSprite(MoveClipper& clip, DCoreActor* actor) if ((clip.pos.Z > sprz) == ((actor->spr.cstat & CSTAT_SPRITE_YFLIP) == 0)) return false; } - DVector2 points[4]; - GetFlatSpritePosition(actor, actor->spr.pos, points, nullptr); + DVector2 opoints[4]; + if (!points) points = opoints; + GetFlatSpritePosition(actor, actor->spr.pos, points, heights); auto offset = (actor->spr.angle - DAngle45).ToVector() * clip.walldist; @@ -1496,6 +1496,54 @@ bool processClipFloorSprite(MoveClipper& clip, DCoreActor* actor) // //========================================================================== +void processClipSlopeSprite(MoveClipper& clip, DCoreActor* actor) +{ + auto spos = actor->spr.pos; + DVector2 points[4]; + double heights[4]; + DVector2 lpoints[2]; + + if (!processClipFloorSprite(clip, actor, points, heights)) return; + int heinum = spriteGetSlope(actor); + if (heinum == 0) return; + + double zz[3] = { clip.pos.Z, clip.pos.Z + clip.floordist, clip.pos.Z - clip.ceilingdist }; + + CollisionBase objtype; + objtype.setSprite(actor); + + for (int k = 0; k < 3; k++) + { + double factor = (zz[k] - heights[0]) / (heights[2] - heights[0]); + if (factor < 0 || factor > 1) continue; // sprite never hits the desired height. + lpoints[0] = points[0] + (points[2] - points[0]) * factor; + lpoints[1] = lpoints[0] + (points[1] - points[0]); + + // The rest is just the same as the main part of the wall sprite collector. + if (IsCloseToLine(clip.center, lpoints[0], lpoints[1], clip.movedist) == EClose::Outside) continue; // out of reach + + auto offset = (actor->spr.angle - DAngle45).ToVector() * clip.walldist; + auto d = lpoints[1] - lpoints[0]; + + if (PointOnLineSide(clip.center.X, clip.center.Y, lpoints[0].X, lpoints[0].Y, d.X, d.Y) <= 0) + { + // in front + addClipLine(clip, lpoints[0] + offset, lpoints[1] + offset.Rotated90CW(), objtype); + } + else if (!(actor->spr.cstat & CSTAT_SPRITE_ONE_SIDE)) + { + // behind + addClipLine(clip, lpoints[0] - offset, lpoints[1] + offset.Rotated90CCW(), objtype); + } + } +} + +//========================================================================== +// +// +// +//========================================================================== + bool isAwayFromWall(DCoreActor* ac, double delta) { sectortype* s1; diff --git a/source/core/gamefuncs.h b/source/core/gamefuncs.h index 8912cbc19..ba5c6f032 100644 --- a/source/core/gamefuncs.h +++ b/source/core/gamefuncs.h @@ -294,7 +294,8 @@ void processClipWalls(MoveClipper& clip, sectortype* sec); void processClipFaceSprite(MoveClipper& clip, DCoreActor* actor); void processClipWallSprite(MoveClipper& clip, DCoreActor* actor); -bool processClipFloorSprite(MoveClipper& clip, DCoreActor* actor); +bool processClipFloorSprite(MoveClipper& clip, DCoreActor* actor, DVector2* points = nullptr, double* heights = nullptr); +void processClipSlopeSprite(MoveClipper& clip, DCoreActor* actor); int FindBestSector(const DVector3& pos);