diff --git a/source/build/include/build.h b/source/build/include/build.h index 3d6f62de1..93341ea9b 100644 --- a/source/build/include/build.h +++ b/source/build/include/build.h @@ -185,13 +185,6 @@ inline void neartag(const DVector3& start, sectortype* sect, DAngle angle, HitIn neartag(vec, sect, angle.Buildang(), result, int(neartagrange * worldtoint), tagsearch); } -int cansee(int x1, int y1, int z1, sectortype* sect1, int x2, int y2, int z2, sectortype* sect2); - -inline int cansee(const DVector3& start, sectortype* sect1, const DVector3& end, sectortype* sect2) -{ - return cansee(start.X * worldtoint, start.Y * worldtoint, start.Z * zworldtoint, sect1, end.X * worldtoint, end.Y * worldtoint, end.Z * zworldtoint, sect2); -} - 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); diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index 548616457..4d214f796 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -59,71 +59,6 @@ void engineInit(void) } -// -// cansee -// - -int cansee(int x1, int y1, int z1, sectortype* sect1, int x2, int y2, int z2, sectortype* sect2) -{ - if (!sect1 || !sect2) return false; - - const int32_t x21 = x2-x1, y21 = y2-y1, z21 = z2-z1; - - if (x1 == x2 && y1 == y2) - return (sect1 == sect2); - - BFSSectorSearch search(sect1); - - while (auto sec = search.GetNext()) - { - const walltype* wal; - int cnt; - for (cnt=sec->wallnum,wal=sec->firstWall(); cnt>0; cnt--,wal++) - { - auto const wal2 = wal->point2Wall(); - const int32_t x31 = wal->wall_int_pos().X-x1, x34 = wal->wall_int_pos().X-wal2->wall_int_pos().X; - const int32_t y31 = wal->wall_int_pos().Y-y1, y34 = wal->wall_int_pos().Y-wal2->wall_int_pos().Y; - - int32_t x, y, z, t, bot; - int32_t cfz[2]; - - bot = y21*x34-x21*y34; if (bot <= 0) continue; - // XXX: OVERFLOW - t = y21*x31-x21*y31; if ((unsigned)t >= (unsigned)bot) continue; - t = y31*x34-x31*y34; - if ((unsigned)t >= (unsigned)bot) - { - continue; - } - - - if (!wal->twoSided() || wal->cstat & CSTAT_WALL_1WAY) - return 0; - - t = DivScale(t,bot, 24); - x = x1 + MulScale(x21,t, 24); - y = y1 + MulScale(y21,t, 24); - z = z1 + MulScale(z21,t, 24); - - int_getzsofslopeptr(sec, x,y, &cfz[0],&cfz[1]); - - if (z <= cfz[0] || z >= cfz[1]) - { - return 0; - } - - auto nexts = wal->nextSector(); - int_getzsofslopeptr(nexts, x,y, &cfz[0],&cfz[1]); - if (z <= cfz[0] || z >= cfz[1]) - return 0; - - search.Add(nexts); - } - - } - return search.Check(sect2); -} - // // neartag // diff --git a/source/core/gamefuncs.cpp b/source/core/gamefuncs.cpp index 922d91753..cfa9c4712 100644 --- a/source/core/gamefuncs.cpp +++ b/source/core/gamefuncs.cpp @@ -541,6 +541,50 @@ sectortype* nextsectorneighborzptr(sectortype* sectp, double startz, int flags) } +//========================================================================== +// +// +// +//========================================================================== + +bool cansee(const DVector3& start, sectortype* sect1, const DVector3& end, sectortype* sect2) +{ + if (!sect1 || !sect2) return false; + + auto delta = end - start; + + if (delta.XY().isZero()) + return (sect1 == sect2); + + BFSSectorSearch search(sect1); + + while (auto sec = search.GetNext()) + { + for (auto& wal : wallsofsector(sec)) + { + double factor = InterceptLineSegments(start.X, start.Y, delta.X, delta.Y, wal.pos.X, wal.pos.Y, wal.delta().X, wal.delta().Y, nullptr, true); + if (factor <= 0 || factor >= 1) continue; + + if (!wal.twoSided() || wal.cstat & CSTAT_WALL_1WAY) + return false; + + auto spot = start + delta * factor; + double floorz, ceilz; + + for (auto isec : { sec, wal.nextSector() }) + { + getzsofslopeptr(isec, spot, &ceilz, &floorz); + + if (spot.Z <= ceilz || spot.Z >= floorz) + return false; + } + search.Add(wal.nextSector()); + } + } + return search.Check(sect2); +} + + //========================================================================== // // diff --git a/source/core/gamefuncs.h b/source/core/gamefuncs.h index e428a8cf2..d77c384c4 100644 --- a/source/core/gamefuncs.h +++ b/source/core/gamefuncs.h @@ -261,6 +261,8 @@ void loaddefinitionsfile(const char* fn, bool cumulative = false, bool maingrp = bool calcChaseCamPos(DVector3& ppos, DCoreActor* pspr, sectortype** psectnum, DAngle ang, fixedhoriz horiz, double const interpfrac); int getslopeval(sectortype* sect, const DVector3& pos, double bazez); +bool cansee(const DVector3& start, sectortype* sect1, const DVector3& end, sectortype* sect2); + @@ -548,11 +550,11 @@ inline double InterceptVector(double v2x, double v2y, double v2dx, double v2dy, } // Essentially two InterceptVector calls. We can reduce the calculations because the denominators for both calculations only differ by their sign. -inline double InterceptLineSegments(double v2x, double v2y, double v2dx, double v2dy, double v1x, double v1y, double v1dx, double v1dy, double* pfactor1 = nullptr) +inline double InterceptLineSegments(double v2x, double v2y, double v2dx, double v2dy, double v1x, double v1y, double v1dx, double v1dy, double* pfactor1 = nullptr, bool forcansee = false) { double den = v1dy * v2dx - v1dx * v2dy; - if (den == 0) + if (den == 0 || (forcansee && den < 0)) // cansee does this added check here, aside from that its logic is virtually the same. return 0; // parallel // perform the division first for better parallelization. @@ -666,6 +668,12 @@ inline int32_t lintersect(const int32_t originX, const int32_t originY, const in return result; } +[[deprecated]] +inline int cansee(int x1, int y1, int z1, sectortype* sect1, int x2, int y2, int z2, sectortype* sect2) +{ + return cansee(DVector3(x1 * inttoworld, y1 * inttoworld, z1 * zinttoworld), sect1, DVector3(x2 * inttoworld, y2 * inttoworld, z2 * zinttoworld), sect2); +} + #include "updatesector.h"