mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-25 15:35:23 +00:00
Fix calculating min distance to nearest absent tile
Tile can be present in either mPushed (waiting in a queue), mProcessingTiles ( being processed or waiting in db queue), mPresentTiles (added to navmesh). It's not enough to walk over mPushed tiles to find all not present. Need also to check mProcessingTiles. Otherwise if all tiles are in mProcessingTiles only waitUntilJobsDoneForNotPresentTiles may return too early because there are none in mPushed and therefore none tiles are considered to be absent on navmesh which is not true.
This commit is contained in:
parent
de80b86cc1
commit
98ddc31902
@ -21,6 +21,8 @@
|
||||
#include <numeric>
|
||||
#include <set>
|
||||
#include <type_traits>
|
||||
#include <optional>
|
||||
#include <tuple>
|
||||
|
||||
namespace DetourNavigator
|
||||
{
|
||||
@ -31,15 +33,22 @@ namespace DetourNavigator
|
||||
return std::abs(lhs.x() - rhs.x()) + std::abs(lhs.y() - rhs.y());
|
||||
}
|
||||
|
||||
int getMinDistanceTo(const TilePosition& position, int maxDistance,
|
||||
const std::set<std::tuple<AgentBounds, TilePosition>>& pushedTiles,
|
||||
const std::set<std::tuple<AgentBounds, TilePosition>>& presentTiles)
|
||||
bool isAbsentTileTooClose(const TilePosition& position, int distance,
|
||||
const std::set<std::tuple<AgentBounds, TilePosition>>& pushedTiles,
|
||||
const std::set<std::tuple<AgentBounds, TilePosition>>& presentTiles,
|
||||
const Misc::ScopeGuarded<std::set<std::tuple<AgentBounds, TilePosition>>>& processingTiles)
|
||||
{
|
||||
int result = maxDistance;
|
||||
for (const auto& [agentBounds, tile] : pushedTiles)
|
||||
if (presentTiles.find(std::tie(agentBounds, tile)) == presentTiles.end())
|
||||
result = std::min(result, getManhattanDistance(position, tile));
|
||||
return result;
|
||||
const auto isAbsentAndCloserThan = [&] (const std::tuple<AgentBounds, TilePosition>& v)
|
||||
{
|
||||
return presentTiles.find(v) == presentTiles.end()
|
||||
&& getManhattanDistance(position, std::get<1>(v)) < distance;
|
||||
};
|
||||
if (std::any_of(pushedTiles.begin(), pushedTiles.end(), isAbsentAndCloserThan))
|
||||
return true;
|
||||
if (const auto locked = processingTiles.lockConst();
|
||||
std::any_of(locked->begin(), locked->end(), isAbsentAndCloserThan))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto getPriority(const Job& job) noexcept
|
||||
@ -248,27 +257,22 @@ namespace DetourNavigator
|
||||
void AsyncNavMeshUpdater::waitUntilJobsDoneForNotPresentTiles(Loading::Listener& listener)
|
||||
{
|
||||
const std::size_t initialJobsLeft = getTotalJobs();
|
||||
std::size_t maxProgress = initialJobsLeft + mThreads.size();
|
||||
std::size_t maxProgress = initialJobsLeft;
|
||||
std::size_t prevJobsLeft = initialJobsLeft;
|
||||
std::size_t jobsDone = 0;
|
||||
std::size_t jobsLeft = 0;
|
||||
const int maxDistanceToPlayer = mSettings.get().mWaitUntilMinDistanceToPlayer;
|
||||
const TilePosition playerPosition = *mPlayerTile.lockConst();
|
||||
int minDistanceToPlayer = 0;
|
||||
const auto isDone = [&]
|
||||
{
|
||||
jobsLeft = mJobs.size();
|
||||
if (jobsLeft == 0)
|
||||
{
|
||||
minDistanceToPlayer = 0;
|
||||
return true;
|
||||
}
|
||||
minDistanceToPlayer = getMinDistanceTo(playerPosition, maxDistanceToPlayer, mPushed, mPresentTiles);
|
||||
return minDistanceToPlayer >= maxDistanceToPlayer;
|
||||
return !isAbsentTileTooClose(playerPosition, maxDistanceToPlayer, mPushed, mPresentTiles, mProcessingTiles);
|
||||
};
|
||||
std::unique_lock<std::mutex> lock(mMutex);
|
||||
if (getMinDistanceTo(playerPosition, maxDistanceToPlayer, mPushed, mPresentTiles) >= maxDistanceToPlayer
|
||||
|| (mJobs.empty() && mProcessingTiles.lockConst()->empty()))
|
||||
if (!isAbsentTileTooClose(playerPosition, maxDistanceToPlayer, mPushed, mPresentTiles, mProcessingTiles)
|
||||
|| mJobs.empty())
|
||||
return;
|
||||
Loading::ScopedLoad load(&listener);
|
||||
listener.setLabel("#{Navigation:BuildingNavigationMesh}");
|
||||
@ -277,7 +281,7 @@ namespace DetourNavigator
|
||||
{
|
||||
if (maxProgress < jobsLeft)
|
||||
{
|
||||
maxProgress = jobsLeft + mThreads.size();
|
||||
maxProgress = jobsLeft;
|
||||
listener.setProgressRange(maxProgress);
|
||||
listener.setProgress(jobsDone);
|
||||
}
|
||||
@ -289,12 +293,6 @@ namespace DetourNavigator
|
||||
listener.increaseProgress(newJobsDone);
|
||||
}
|
||||
}
|
||||
lock.unlock();
|
||||
if (minDistanceToPlayer < maxDistanceToPlayer)
|
||||
{
|
||||
mProcessingTiles.wait(mProcessed, [] (const auto& v) { return v.empty(); });
|
||||
listener.setProgress(maxProgress);
|
||||
}
|
||||
}
|
||||
|
||||
void AsyncNavMeshUpdater::waitUntilAllJobsDone()
|
||||
|
Loading…
x
Reference in New Issue
Block a user