2022-08-04 21:48:07 +00:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
/*
|
|
|
|
Copyright (C) 2022 Christoph Oelckers
|
|
|
|
|
|
|
|
This is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
|
|
|
*/
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
//
|
2022-09-30 18:18:58 +00:00
|
|
|
// updatesector utilities. Reimplementations of EDuke32's checks with
|
|
|
|
// proper C++ classes. (Original Build updatesector is insufficient and broken)
|
2022-08-04 21:48:07 +00:00
|
|
|
|
|
|
|
|
|
|
|
// checker functions for updatesector's template parameter.
|
|
|
|
inline int inside0(double x, double y, double z, const sectortype* sect)
|
|
|
|
{
|
|
|
|
return inside(x, y, sect);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline int insideZ(double x, double y, double z, const sectortype* sect)
|
|
|
|
{
|
|
|
|
double cz, fz;
|
|
|
|
getzsofslopeptr(sect, x, y, &cz, &fz);
|
|
|
|
return (z >= cz && z <= fz && inside(x, y, sect) != 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class Inside>
|
|
|
|
void DoUpdateSector(double x, double y, double z, int* sectnum, double maxDistance, Inside checker)
|
|
|
|
{
|
|
|
|
double maxDistSq = maxDistance * maxDistance;
|
|
|
|
|
2022-08-06 07:15:47 +00:00
|
|
|
if (validSectorIndex(*sectnum))
|
2022-08-04 21:48:07 +00:00
|
|
|
{
|
|
|
|
if (checker(x, y, z, §or[*sectnum]))
|
|
|
|
return;
|
|
|
|
|
|
|
|
BFSSearch search(sector.Size(), *sectnum);
|
|
|
|
|
|
|
|
int iter = 0;
|
2022-09-30 18:18:58 +00:00
|
|
|
for (unsigned secnum; (secnum = search.GetNext()) != BFSSearch::EOL;)
|
2022-08-04 21:48:07 +00:00
|
|
|
{
|
2022-09-30 18:18:58 +00:00
|
|
|
auto lsect = §or[secnum];
|
2022-08-04 21:48:07 +00:00
|
|
|
if (checker(x, y, z, lsect))
|
|
|
|
{
|
2022-09-30 18:18:58 +00:00
|
|
|
*sectnum = secnum;
|
2022-08-04 21:48:07 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto& wal : wallsofsector(lsect))
|
|
|
|
{
|
2022-09-30 18:18:58 +00:00
|
|
|
if (wal.twoSided() && !search.Check(wal.nextsector) && (iter == 0 || SquareDistToSector(x, y, wal.nextSector()) <= maxDistSq))
|
2022-08-04 21:48:07 +00:00
|
|
|
search.Add(wal.nextsector);
|
|
|
|
}
|
|
|
|
iter++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = (int)sector.Size() - 1; i >= 0; i--)
|
|
|
|
if (checker(x, y, z, §or[i]))
|
|
|
|
{
|
2022-09-24 11:22:53 +00:00
|
|
|
*sectnum = i;
|
|
|
|
return;
|
2022-08-04 21:48:07 +00:00
|
|
|
}
|
2022-09-24 11:22:53 +00:00
|
|
|
*sectnum = -1;
|
2022-08-04 21:48:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-08-29 17:29:20 +00:00
|
|
|
constexpr int MAXUPDATESECTORDIST = 96;
|
2022-08-04 21:48:07 +00:00
|
|
|
|
2022-09-24 11:22:53 +00:00
|
|
|
inline void updatesector(const DVector3& pos, sectortype** const sectp)
|
|
|
|
{
|
|
|
|
int sectno = *sectp ? sector.IndexOf(*sectp) : -1;
|
|
|
|
DoUpdateSector(pos.X, pos.Y, pos.Z, §no, MAXUPDATESECTORDIST, inside0);
|
|
|
|
*sectp = sectno == -1 ? nullptr : §or[sectno];
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void updatesector(const DVector2& pos, sectortype** const sectp)
|
|
|
|
{
|
|
|
|
int sectno = *sectp ? sector.IndexOf(*sectp) : -1;
|
|
|
|
DoUpdateSector(pos.X, pos.Y, 0, §no, MAXUPDATESECTORDIST, inside0);
|
|
|
|
*sectp = sectno == -1 ? nullptr : §or[sectno];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
inline void updatesectorz(const DVector3& pos, sectortype** const sectp)
|
|
|
|
{
|
|
|
|
int sectno = *sectp ? sector.IndexOf(*sectp) : -1;
|
|
|
|
DoUpdateSector(pos.X, pos.Y, pos.Z, §no, MAXUPDATESECTORDIST, insideZ);
|
|
|
|
*sectp = sectno == -1 ? nullptr : §or[sectno];
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void updatesectorneighbor(const DVector3& pos, sectortype** const sect, double maxDistance = MAXUPDATESECTORDIST)
|
|
|
|
{
|
|
|
|
int sectno = *sect? sector.IndexOf(*sect) : -1;
|
|
|
|
DoUpdateSector(pos.X, pos.Y, 0, §no, maxDistance, inside0);
|
|
|
|
*sect = sectno < 0? nullptr : §or[sectno];
|
|
|
|
}
|
|
|
|
|
|
|
|
[[deprecated]]
|
2022-08-04 21:48:07 +00:00
|
|
|
inline void updatesector(int x_, int y_, int* sectnum)
|
|
|
|
{
|
|
|
|
double x = x_ * inttoworld;
|
|
|
|
double y = y_ * inttoworld;
|
|
|
|
|
2022-08-29 17:29:20 +00:00
|
|
|
DoUpdateSector(x, y, 0, sectnum, MAXUPDATESECTORDIST, inside0);
|
2022-08-04 21:48:07 +00:00
|
|
|
}
|
|
|
|
|
2022-09-30 18:18:58 +00:00
|
|
|
// clipmove uses this. It's really just two loops nearly identical to DoUpdateSector with different checking conditions.
|
|
|
|
inline void clipupdatesector(const DVector2& pos, int* const sectnum, double walldist, BitArray& sectormap)
|
|
|
|
{
|
|
|
|
assert(*sectnum >= 0);
|
|
|
|
sectortype* sect = §or[*sectnum];
|
|
|
|
if (inside(pos.X, pos.Y, sect))
|
|
|
|
return;
|
|
|
|
|
|
|
|
double sdist = SquareDistToSector(pos.X, pos.Y, sect);
|
|
|
|
|
|
|
|
double wd = (walldist + 8);
|
|
|
|
wd *= wd;
|
|
|
|
if (sdist > wd)
|
|
|
|
{
|
|
|
|
wd = 2048 * 2048;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
BFSSearch search(sector.Size(), *sectnum);
|
|
|
|
|
|
|
|
for (unsigned secnum; (secnum = search.GetNext()) != BFSSearch::EOL;)
|
|
|
|
{
|
|
|
|
if (inside(pos.X, pos.Y, §or[secnum]))
|
|
|
|
{
|
|
|
|
*sectnum = secnum;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto& wal : wallsofsector(secnum))
|
|
|
|
{
|
|
|
|
if (wal.twoSided() && sectormap[wal.nextsector])
|
|
|
|
search.Add(wal.nextsector);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
BFSSearch search(sector.Size(), *sectnum);
|
|
|
|
|
|
|
|
for (unsigned secnum; (secnum = search.GetNext()) != BFSSearch::EOL;)
|
|
|
|
{
|
|
|
|
if (inside(pos.X, pos.Y, §or[secnum]))
|
|
|
|
{
|
|
|
|
*sectnum = secnum;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (auto& wal : wallsofsector(secnum))
|
|
|
|
{
|
|
|
|
if (wal.twoSided() && SquareDistToWall(pos.X, pos.Y, &wal) < wd)
|
|
|
|
search.Add(wal.nextsector);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*sectnum = -1;
|
|
|
|
}
|