From ef2f781e093118df585528de6b04732147f42664 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 25 Sep 2022 10:57:46 +0200 Subject: [PATCH] - rewrite from scratch of neartag. --- source/build/include/build.h | 16 ------- source/build/src/engine.cpp | 81 ------------------------------- source/core/gamefuncs.cpp | 88 ++++++++++++++++++++++++++++++++++ source/core/gamefuncs.h | 29 +---------- source/games/sw/src/sector.cpp | 2 +- 5 files changed, 90 insertions(+), 126 deletions(-) diff --git a/source/build/include/build.h b/source/build/include/build.h index 4ff7da8f5..ea8b143fc 100644 --- a/source/build/include/build.h +++ b/source/build/include/build.h @@ -173,22 +173,6 @@ inline int hitscan(const DVector3& start, const sectortype* startsect, const vec return hitscan(istart, startsect, direction, hitinfo, cliptype); } -void neartag(const vec3_t& pos, sectortype* sect, int angle, HitInfoBase& result, int neartagrange, int tagsearch); -inline void neartag(const DVector3& start, sectortype* sect, DAngle angle, HitInfoBase& result, int neartagrange, int tagsearch) -{ - vec3_t vec(start.X * worldtoint, start.Y * worldtoint, start.Z * zworldtoint); - neartag(vec, sect, angle.Buildang(), result, neartagrange, tagsearch); -} -inline void neartag(const DVector3& start, sectortype* sect, DAngle angle, HitInfoBase& result, double neartagrange, int tagsearch) -{ - vec3_t vec(start.X * worldtoint, start.Y * worldtoint, start.Z * zworldtoint); - neartag(vec, sect, angle.Buildang(), result, int(neartagrange * worldtoint), tagsearch); -} - -int32_t try_facespr_intersect(DCoreActor* spr, vec3_t const in, - int32_t vx, int32_t vy, int32_t vz, - vec3_t * const intp, int32_t strictly_smaller_than_p); - extern const int16_t *chsecptr_onextwall; diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index 4d649f855..89b492791 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -59,87 +59,6 @@ void engineInit(void) } -// -// neartag -// - -void neartag(const vec3_t& sv, sectortype* sect, int ange, HitInfoBase& result, int neartagrange, int tagsearch) -{ - const int32_t vx = MulScale(bcos(ange), neartagrange, 14); - const int32_t vy = MulScale(bsin(ange), neartagrange, 14); - vec3_t hitv = { sv.X+vx, sv.Y+vy, 0 }; - - result.clearObj(); - result.hitpos.X = 0; - - if (!sect || (tagsearch & 3) == 0) - return; - - BFSSectorSearch search(sect); - - while (auto dasect = search.GetNext()) - { - for (auto& w : wallsofsector(dasect)) - { - auto wal = &w; - auto const wal2 = wal->point2Wall(); - const auto nextsect = wal->nextSector(); - - const int32_t x1 = wal->wall_int_pos().X, y1 = wal->wall_int_pos().Y, x2 = wal2->wall_int_pos().X, y2 = wal2->wall_int_pos().Y; - int32_t intx, inty, intz, good = 0; - - if (wal->twoSided()) - { - if ((tagsearch & 1) && nextsect->lotag) good |= 1; - if ((tagsearch & 2) && nextsect->hitag) good |= 1; - } - - if ((tagsearch & 1) && wal->lotag) good |= 2; - if ((tagsearch & 2) && wal->hitag) good |= 2; - - if ((good == 0) && (!wal->twoSided())) continue; - if ((coord_t)(x1 - sv.X) * (y2 - sv.Y) < (coord_t)(x2 - sv.X) * (y1 - sv.Y)) continue; - - if (lintersect(sv.X, sv.Y, sv.Z, hitv.X, hitv.Y, hitv.Z, x1, y1, x2, y2, &intx, &inty, &intz) == 1) - { - if (good != 0) - { - if (good & 1) result.hitSector = nextsect; - if (good & 2) result.hitWall = wal; - result.hitpos.X = DMulScale(intx - sv.X, bcos(ange), inty - sv.Y, bsin(ange), 14) * inttoworld; - hitv.X = intx; hitv.Y = inty; hitv.Z = intz; - } - - if (wal->twoSided()) - { - search.Add(nextsect); - } - } - } - - if (tagsearch & 4) - continue; // skip sprite search - - TSectIterator it(dasect); - while (auto actor = it.Next()) - { - if (actor->spr.cstat2 & CSTAT2_SPRITE_NOFIND) - continue; - - if (((tagsearch&1) && actor->spr.lotag) || ((tagsearch&2) && actor->spr.hitag)) - { - DVector3 v; - if (intersectSprite(actor, DVector3(sv.X * inttoworld, sv.Y * inttoworld, sv.Z * zinttoworld), - DVector3(vx * inttoworld, vy * inttoworld, 0), v, 1 / 256.)) - { - vec3_t hitv(v.X * worldtoint, v.Y * worldtoint, v.Z * zworldtoint); - result.hitActor = actor; - result.hitpos.X = DMulScale(hitv.X-sv.X, bcos(ange), hitv.Y-sv.Y, bsin(ange), 14) * inttoworld; - } - } - } - } -} int tilehasmodelorvoxel(int const tilenume, int pal) { diff --git a/source/core/gamefuncs.cpp b/source/core/gamefuncs.cpp index c0fe0c805..3449deb81 100644 --- a/source/core/gamefuncs.cpp +++ b/source/core/gamefuncs.cpp @@ -623,7 +623,95 @@ bool intersectSprite(DCoreActor* actor, const DVector3& start, const DVector3& d return 1; } +//========================================================================== +// +// +// +//========================================================================== +void neartag(const DVector3& pos, sectortype* startsect, DAngle angle, HitInfoBase& result, double range, int flags) +{ + auto checkTag = [=](const auto* object) + { + return (((flags & NT_Lotag) && object->lotag) || ((flags & NT_Hitag) && object->hitag)); + }; + + auto v = DVector3(angle.ToVector() * range * 1.000001, 0); // extend the range a tiny bit so that we really find everything we need. + + result.clearObj(); + result.hitpos.X = result.hitpos.Y = 0; + + if (!startsect || (flags & (NT_Lotag | NT_Hitag)) == 0) + return; + + BFSSectorSearch search(startsect); + + while (auto sect = search.GetNext()) + { + for (auto& wal : wallsofsector(sect)) + { + const auto nextsect = wal.nextSector(); + + if (PointOnLineSide(pos.XY(), &wal) > 0) continue; + + double factor = InterceptLineSegments(pos.X, pos.Y, v.X, v.Y, wal.pos.X, wal.pos.Y, wal.delta().X, wal.delta().Y); + if (factor > 0 && factor < 1) + { + bool foundsector = (wal.twoSided() && checkTag(nextsect)); + bool foundwall = checkTag(&wal); +#if 0 // does not work if the trace goes right through the vertex between two walls. + if (!wal.twoSided() && !foundwall && !foundsector) + { + // this case was not handled by Build: + // If we hit an untagged one-sided wall it should both shorten the scan trace and clear all hits beyond. + // Otherwise this may cause problems with some weirdly shaped sectors. + result.hitSector = nullptr; + result.hitWall = nullptr; + result.hitpos.X = 0; + v *= factor; + continue; + } +#endif + if (foundsector) result.hitSector = nextsect; + if (foundwall) result.hitWall = &wal; + + if (foundwall || foundsector) + { + v *= factor; + result.hitpos.X = v.XY().Length(); + } + + if (wal.twoSided()) + { + search.Add(nextsect); + } + } + } + + if (!(flags & NT_NoSpriteCheck)) + { + TSectIterator it(sect); + while (auto actor = it.Next()) + { + if (actor->spr.cstat2 & CSTAT2_SPRITE_NOFIND) + continue; + + if (checkTag(&actor->spr)) + { + DVector3 spot; + if (intersectSprite(actor, pos, v, spot, 1 / 256.)) + { + result.hitActor = actor; + // return distance to sprite in a separate variable because there is + // no means to determine what is for if both a sprite and wall are found. + // Only SW's NearTagList actually uses it. + result.hitpos.Y = (spot - pos).XY().Length(); + } + } + } + } + } +} //========================================================================== // diff --git a/source/core/gamefuncs.h b/source/core/gamefuncs.h index c0c99c725..0ea187288 100644 --- a/source/core/gamefuncs.h +++ b/source/core/gamefuncs.h @@ -263,6 +263,7 @@ bool calcChaseCamPos(DVector3& ppos, DCoreActor* pspr, sectortype** psectnum, DA int getslopeval(sectortype* sect, const DVector3& pos, double bazez); bool cansee(const DVector3& start, sectortype* sect1, const DVector3& end, sectortype* sect2); bool intersectSprite(DCoreActor* actor, const DVector3& start, const DVector3& end, DVector3& result, double displacement); +void neartag(const DVector3& start, sectortype* sect, DAngle angle, HitInfoBase& result, double neartagrange, int tagsearch); @@ -584,15 +585,6 @@ inline double GetRayIntersect(const DVector3& start1, const DVector3& vect1, con return factor2; } -inline bool GetLineIntersect(const DVector3& start1, const DVector3& vect1, const DVector2& start2, const DVector2& vect2, DVector3& retv) -{ - double factor = InterceptLineSegments(start1.X, start1.Y, vect1.X, vect1.Y, start2.X, start2.Y, vect2.X, vect2.Y); - if (factor <= 0 || factor > 1) return false; - retv = start1 + (factor) * vect1; - return true; -} - - inline void alignceilslope(sectortype* sect, const DVector3& pos) { sect->setceilingslope(getslopeval(sect, pos, sect->ceilingz)); @@ -657,25 +649,6 @@ inline int rintersect(int x1, int y1, int z1, int vx, int vy, int vz, int x3, in return FloatToFixed(result); } -[[deprecated]] -inline int32_t lintersect(const int32_t originX, const int32_t originY, const int32_t originZ, - const int32_t destX, const int32_t destY, const int32_t destZ, - const int32_t lineStartX, const int32_t lineStartY, const int32_t lineEndX, const int32_t lineEndY, - int32_t* intersectionX, int32_t* intersectionY, int32_t* intersectionZ) -{ - DVector3 retv; - bool result = GetLineIntersect(DVector3(originX * inttoworld, originY * inttoworld, originZ * zinttoworld), - DVector3((destX - originX) * inttoworld, (destY - originY) * inttoworld, (destZ - originZ) * zinttoworld), - DVector2(lineStartX * inttoworld, lineStartY * inttoworld), DVector2((lineEndX - lineStartX) * inttoworld, (lineEndY - lineStartY) * inttoworld), retv); - if (result) - { - *intersectionX = retv.X * worldtoint; - *intersectionY = retv.Y * worldtoint; - *intersectionZ = retv.Z * zworldtoint; - } - return result; -} - [[deprecated]] inline int cansee(int x1, int y1, int z1, sectortype* sect1, int x2, int y2, int z2, sectortype* sect2) { diff --git a/source/games/sw/src/sector.cpp b/source/games/sw/src/sector.cpp index 093ab73db..a37709801 100644 --- a/source/games/sw/src/sector.cpp +++ b/source/games/sw/src/sector.cpp @@ -2282,7 +2282,7 @@ void NearTagList(NEAR_TAG_INFO* ntip, PLAYER* pp, double z, double dist, int typ save_lotag = actor->spr.lotag; save_hitag = actor->spr.hitag; - ntip->Dist = near.hitpos.X; + ntip->Dist = near.hitpos.Y; ntip->sectp = nullptr; ntip->wallp = nullptr; ntip->actor = actor;