mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-10-04 22:56:30 +00:00
Merge branch 'fix_navmesh_wait' into 'master'
Fix redundant waiting until navmesh is generated See merge request OpenMW/openmw!861
This commit is contained in:
commit
f1f1703441
11 changed files with 128 additions and 57 deletions
|
@ -619,7 +619,7 @@ namespace MWWorld
|
||||||
if (changeEvent)
|
if (changeEvent)
|
||||||
mCellChanged = true;
|
mCellChanged = true;
|
||||||
|
|
||||||
mNavigator.wait(*loadingListener);
|
mNavigator.wait(*loadingListener, DetourNavigator::WaitConditionType::requiredTilesPresent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::testExteriorCells()
|
void Scene::testExteriorCells()
|
||||||
|
@ -848,7 +848,7 @@ namespace MWWorld
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell);
|
MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell);
|
||||||
|
|
||||||
mNavigator.wait(*loadingListener);
|
mNavigator.wait(*loadingListener, DetourNavigator::WaitConditionType::requiredTilesPresent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::changeToExteriorCell (const ESM::Position& position, bool adjustPlayerPos, bool changeEvent)
|
void Scene::changeToExteriorCell (const ESM::Position& position, bool adjustPlayerPos, bool changeEvent)
|
||||||
|
|
|
@ -127,7 +127,7 @@ namespace
|
||||||
mNavigator->addAgent(mAgentHalfExtents);
|
mNavigator->addAgent(mAgentHalfExtents);
|
||||||
mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity());
|
mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity());
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition);
|
||||||
mNavigator->wait(mListener);
|
mNavigator->wait(mListener, WaitConditionType::requiredTilesPresent);
|
||||||
|
|
||||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
|
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
|
||||||
|
|
||||||
|
@ -177,7 +177,7 @@ namespace
|
||||||
mNavigator->addAgent(mAgentHalfExtents);
|
mNavigator->addAgent(mAgentHalfExtents);
|
||||||
mNavigator->addObject(ObjectId(&heightfieldShape), heightfieldShape, btTransform::getIdentity());
|
mNavigator->addObject(ObjectId(&heightfieldShape), heightfieldShape, btTransform::getIdentity());
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition);
|
||||||
mNavigator->wait(mListener);
|
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||||
|
|
||||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
|
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
|
||||||
|
|
||||||
|
@ -209,7 +209,7 @@ namespace
|
||||||
|
|
||||||
mNavigator->addObject(ObjectId(&compoundShape), compoundShape, btTransform::getIdentity());
|
mNavigator->addObject(ObjectId(&compoundShape), compoundShape, btTransform::getIdentity());
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition);
|
||||||
mNavigator->wait(mListener);
|
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||||
|
|
||||||
mPath.clear();
|
mPath.clear();
|
||||||
mOut = std::back_inserter(mPath);
|
mOut = std::back_inserter(mPath);
|
||||||
|
@ -262,7 +262,7 @@ namespace
|
||||||
mNavigator->addObject(ObjectId(&heightfieldShape), heightfieldShape, btTransform::getIdentity());
|
mNavigator->addObject(ObjectId(&heightfieldShape), heightfieldShape, btTransform::getIdentity());
|
||||||
mNavigator->addObject(ObjectId(&compoundShape), compoundShape, btTransform::getIdentity());
|
mNavigator->addObject(ObjectId(&compoundShape), compoundShape, btTransform::getIdentity());
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition);
|
||||||
mNavigator->wait(mListener);
|
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||||
|
|
||||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
|
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
|
||||||
|
|
||||||
|
@ -296,7 +296,7 @@ namespace
|
||||||
|
|
||||||
mNavigator->updateObject(ObjectId(&compoundShape), compoundShape, btTransform::getIdentity());
|
mNavigator->updateObject(ObjectId(&compoundShape), compoundShape, btTransform::getIdentity());
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition);
|
||||||
mNavigator->wait(mListener);
|
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||||
|
|
||||||
mPath.clear();
|
mPath.clear();
|
||||||
mOut = std::back_inserter(mPath);
|
mOut = std::back_inserter(mPath);
|
||||||
|
@ -355,7 +355,7 @@ namespace
|
||||||
mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity());
|
mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity());
|
||||||
mNavigator->addObject(ObjectId(&shape2), shape2, btTransform::getIdentity());
|
mNavigator->addObject(ObjectId(&shape2), shape2, btTransform::getIdentity());
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition);
|
||||||
mNavigator->wait(mListener);
|
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||||
|
|
||||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
|
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
|
||||||
|
|
||||||
|
@ -411,7 +411,7 @@ namespace
|
||||||
mNavigator->addAgent(mAgentHalfExtents);
|
mNavigator->addAgent(mAgentHalfExtents);
|
||||||
mNavigator->addObject(ObjectId(&shape), ObjectShapes {shape, &shapeAvoid}, btTransform::getIdentity());
|
mNavigator->addObject(ObjectId(&shape), ObjectShapes {shape, &shapeAvoid}, btTransform::getIdentity());
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition);
|
||||||
mNavigator->wait(mListener);
|
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||||
|
|
||||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
|
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
|
||||||
|
|
||||||
|
@ -459,7 +459,7 @@ namespace
|
||||||
mNavigator->addWater(osg::Vec2i(0, 0), 128 * 4, 300, btTransform::getIdentity());
|
mNavigator->addWater(osg::Vec2i(0, 0), 128 * 4, 300, btTransform::getIdentity());
|
||||||
mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity());
|
mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity());
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition);
|
||||||
mNavigator->wait(mListener);
|
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||||
|
|
||||||
mStart.x() = 0;
|
mStart.x() = 0;
|
||||||
mStart.z() = 300;
|
mStart.z() = 300;
|
||||||
|
@ -507,7 +507,7 @@ namespace
|
||||||
mNavigator->addWater(osg::Vec2i(0, 0), 128 * 4, -25, btTransform::getIdentity());
|
mNavigator->addWater(osg::Vec2i(0, 0), 128 * 4, -25, btTransform::getIdentity());
|
||||||
mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity());
|
mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity());
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition);
|
||||||
mNavigator->wait(mListener);
|
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||||
|
|
||||||
mStart.x() = 0;
|
mStart.x() = 0;
|
||||||
mEnd.x() = 0;
|
mEnd.x() = 0;
|
||||||
|
@ -554,7 +554,7 @@ namespace
|
||||||
mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity());
|
mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity());
|
||||||
mNavigator->addWater(osg::Vec2i(0, 0), std::numeric_limits<int>::max(), -25, btTransform::getIdentity());
|
mNavigator->addWater(osg::Vec2i(0, 0), std::numeric_limits<int>::max(), -25, btTransform::getIdentity());
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition);
|
||||||
mNavigator->wait(mListener);
|
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||||
|
|
||||||
mStart.x() = 0;
|
mStart.x() = 0;
|
||||||
mEnd.x() = 0;
|
mEnd.x() = 0;
|
||||||
|
@ -601,7 +601,7 @@ namespace
|
||||||
mNavigator->addWater(osg::Vec2i(0, 0), 128 * 4, -25, btTransform::getIdentity());
|
mNavigator->addWater(osg::Vec2i(0, 0), 128 * 4, -25, btTransform::getIdentity());
|
||||||
mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity());
|
mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity());
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition);
|
||||||
mNavigator->wait(mListener);
|
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||||
|
|
||||||
mStart.x() = 0;
|
mStart.x() = 0;
|
||||||
mEnd.x() = 0;
|
mEnd.x() = 0;
|
||||||
|
@ -645,15 +645,15 @@ namespace
|
||||||
mNavigator->addAgent(mAgentHalfExtents);
|
mNavigator->addAgent(mAgentHalfExtents);
|
||||||
mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity());
|
mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity());
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition);
|
||||||
mNavigator->wait(mListener);
|
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||||
|
|
||||||
mNavigator->removeObject(ObjectId(&shape));
|
mNavigator->removeObject(ObjectId(&shape));
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition);
|
||||||
mNavigator->wait(mListener);
|
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||||
|
|
||||||
mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity());
|
mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity());
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition);
|
||||||
mNavigator->wait(mListener);
|
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||||
|
|
||||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
|
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
|
||||||
|
|
||||||
|
@ -699,7 +699,7 @@ namespace
|
||||||
mNavigator->addAgent(mAgentHalfExtents);
|
mNavigator->addAgent(mAgentHalfExtents);
|
||||||
mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity());
|
mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity());
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition);
|
||||||
mNavigator->wait(mListener);
|
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||||
|
|
||||||
Misc::Rng::init(42);
|
Misc::Rng::init(42);
|
||||||
|
|
||||||
|
@ -748,7 +748,7 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition);
|
||||||
mNavigator->wait(mListener);
|
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||||
|
|
||||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
|
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
|
||||||
|
|
||||||
|
@ -791,7 +791,7 @@ namespace
|
||||||
mNavigator->addObject(ObjectId(&shapes[i]), shapes[i], transform);
|
mNavigator->addObject(ObjectId(&shapes[i]), shapes[i], transform);
|
||||||
}
|
}
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition);
|
||||||
mNavigator->wait(mListener);
|
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||||
|
|
||||||
const auto start = std::chrono::steady_clock::now();
|
const auto start = std::chrono::steady_clock::now();
|
||||||
for (std::size_t i = 0; i < shapes.size(); ++i)
|
for (std::size_t i = 0; i < shapes.size(); ++i)
|
||||||
|
@ -800,7 +800,7 @@ namespace
|
||||||
mNavigator->updateObject(ObjectId(&shapes[i]), shapes[i], transform);
|
mNavigator->updateObject(ObjectId(&shapes[i]), shapes[i], transform);
|
||||||
}
|
}
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition);
|
||||||
mNavigator->wait(mListener);
|
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||||
|
|
||||||
for (std::size_t i = 0; i < shapes.size(); ++i)
|
for (std::size_t i = 0; i < shapes.size(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -808,7 +808,7 @@ namespace
|
||||||
mNavigator->updateObject(ObjectId(&shapes[i]), shapes[i], transform);
|
mNavigator->updateObject(ObjectId(&shapes[i]), shapes[i], transform);
|
||||||
}
|
}
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition);
|
||||||
mNavigator->wait(mListener);
|
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||||
|
|
||||||
const auto duration = std::chrono::steady_clock::now() - start;
|
const auto duration = std::chrono::steady_clock::now() - start;
|
||||||
|
|
||||||
|
@ -831,7 +831,7 @@ namespace
|
||||||
mNavigator->addAgent(mAgentHalfExtents);
|
mNavigator->addAgent(mAgentHalfExtents);
|
||||||
mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity());
|
mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity());
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition);
|
||||||
mNavigator->wait(mListener);
|
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||||
|
|
||||||
const auto result = mNavigator->raycast(mAgentHalfExtents, mStart, mEnd, Flag_walk);
|
const auto result = mNavigator->raycast(mAgentHalfExtents, mStart, mEnd, Flag_walk);
|
||||||
|
|
||||||
|
@ -862,7 +862,7 @@ namespace
|
||||||
mNavigator->addObject(ObjectId(&boderBoxShape), boderBoxShape,
|
mNavigator->addObject(ObjectId(&boderBoxShape), boderBoxShape,
|
||||||
btTransform(btMatrix3x3::getIdentity(), oscillatingBoxShapePosition + btVector3(0, 0, 200)));
|
btTransform(btMatrix3x3::getIdentity(), oscillatingBoxShapePosition + btVector3(0, 0, 200)));
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition);
|
||||||
mNavigator->wait(mListener);
|
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||||
|
|
||||||
const auto navMeshes = mNavigator->getNavMeshes();
|
const auto navMeshes = mNavigator->getNavMeshes();
|
||||||
ASSERT_EQ(navMeshes.size(), 1);
|
ASSERT_EQ(navMeshes.size(), 1);
|
||||||
|
@ -878,7 +878,7 @@ namespace
|
||||||
oscillatingBoxShapePosition);
|
oscillatingBoxShapePosition);
|
||||||
mNavigator->updateObject(ObjectId(&oscillatingBoxShape), oscillatingBoxShape, transform);
|
mNavigator->updateObject(ObjectId(&oscillatingBoxShape), oscillatingBoxShape, transform);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition);
|
||||||
mNavigator->wait(mListener);
|
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_EQ(navMeshes.size(), 1);
|
ASSERT_EQ(navMeshes.size(), 1);
|
||||||
|
|
|
@ -10,7 +10,9 @@
|
||||||
|
|
||||||
#include <osg/Stats>
|
#include <osg/Stats>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -23,12 +25,14 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
int getMinDistanceTo(const TilePosition& position, int maxDistance,
|
int getMinDistanceTo(const TilePosition& position, int maxDistance,
|
||||||
const std::map<osg::Vec3f, std::set<TilePosition>>& tilesPerHalfExtents)
|
const std::map<osg::Vec3f, std::set<TilePosition>>& tilesPerHalfExtents,
|
||||||
|
const std::set<std::tuple<osg::Vec3f, TilePosition>>& presentTiles)
|
||||||
{
|
{
|
||||||
int result = maxDistance;
|
int result = maxDistance;
|
||||||
for (const auto& [halfExtents, tiles] : tilesPerHalfExtents)
|
for (const auto& [halfExtents, tiles] : tilesPerHalfExtents)
|
||||||
for (const TilePosition& tile : tiles)
|
for (const TilePosition& tile : tiles)
|
||||||
result = std::min(result, getManhattanDistance(position, tile));
|
if (presentTiles.find(std::make_tuple(halfExtents, tile)) == presentTiles.end())
|
||||||
|
result = std::min(result, getManhattanDistance(position, tile));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,13 +92,22 @@ namespace DetourNavigator
|
||||||
const SharedNavMeshCacheItem& navMeshCacheItem, const TilePosition& playerTile,
|
const SharedNavMeshCacheItem& navMeshCacheItem, const TilePosition& playerTile,
|
||||||
const std::map<TilePosition, ChangeType>& changedTiles)
|
const std::map<TilePosition, ChangeType>& changedTiles)
|
||||||
{
|
{
|
||||||
*mPlayerTile.lock() = playerTile;
|
bool playerTileChanged = false;
|
||||||
|
{
|
||||||
|
auto locked = mPlayerTile.lock();
|
||||||
|
playerTileChanged = *locked != playerTile;
|
||||||
|
*locked = playerTile;
|
||||||
|
}
|
||||||
|
|
||||||
if (changedTiles.empty())
|
if (!playerTileChanged && changedTiles.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const std::lock_guard<std::mutex> lock(mMutex);
|
const std::lock_guard<std::mutex> lock(mMutex);
|
||||||
|
|
||||||
|
if (playerTileChanged)
|
||||||
|
for (auto& job : mJobs)
|
||||||
|
job.mDistanceToPlayer = getManhattanDistance(job.mChangedTile, playerTile);
|
||||||
|
|
||||||
for (const auto& changedTile : changedTiles)
|
for (const auto& changedTile : changedTiles)
|
||||||
{
|
{
|
||||||
if (mPushed[agentHalfExtents].insert(changedTile.first).second)
|
if (mPushed[agentHalfExtents].insert(changedTile.first).second)
|
||||||
|
@ -112,17 +125,28 @@ namespace DetourNavigator
|
||||||
? mLastUpdates[job.mAgentHalfExtents][job.mChangedTile] + mSettings.get().mMinUpdateInterval
|
? mLastUpdates[job.mAgentHalfExtents][job.mChangedTile] + mSettings.get().mMinUpdateInterval
|
||||||
: std::chrono::steady_clock::time_point();
|
: std::chrono::steady_clock::time_point();
|
||||||
|
|
||||||
mJobs.push(std::move(job));
|
if (playerTileChanged)
|
||||||
|
{
|
||||||
|
mJobs.push_back(std::move(job));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto it = std::upper_bound(mJobs.begin(), mJobs.end(), job);
|
||||||
|
mJobs.insert(it, std::move(job));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (playerTileChanged)
|
||||||
|
std::sort(mJobs.begin(), mJobs.end());
|
||||||
|
|
||||||
Log(Debug::Debug) << "Posted " << mJobs.size() << " navigator jobs";
|
Log(Debug::Debug) << "Posted " << mJobs.size() << " navigator jobs";
|
||||||
|
|
||||||
if (!mJobs.empty())
|
if (!mJobs.empty())
|
||||||
mHasJob.notify_all();
|
mHasJob.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncNavMeshUpdater::wait(Loading::Listener& listener)
|
void AsyncNavMeshUpdater::wait(Loading::Listener& listener, WaitConditionType waitConditionType)
|
||||||
{
|
{
|
||||||
if (mSettings.get().mWaitUntilMinDistanceToPlayer == 0)
|
if (mSettings.get().mWaitUntilMinDistanceToPlayer == 0)
|
||||||
return;
|
return;
|
||||||
|
@ -130,15 +154,26 @@ namespace DetourNavigator
|
||||||
const std::size_t initialJobsLeft = getTotalJobs();
|
const std::size_t initialJobsLeft = getTotalJobs();
|
||||||
std::size_t maxProgress = initialJobsLeft + mThreads.size();
|
std::size_t maxProgress = initialJobsLeft + mThreads.size();
|
||||||
listener.setProgressRange(maxProgress);
|
listener.setProgressRange(maxProgress);
|
||||||
const int minDistanceToPlayer = waitUntilJobsDone(initialJobsLeft, maxProgress, listener);
|
switch (waitConditionType)
|
||||||
if (minDistanceToPlayer < mSettings.get().mWaitUntilMinDistanceToPlayer)
|
|
||||||
{
|
{
|
||||||
mProcessingTiles.wait(mProcessed, [] (const auto& v) { return v.empty(); });
|
case WaitConditionType::requiredTilesPresent:
|
||||||
listener.setProgress(maxProgress);
|
{
|
||||||
|
const int minDistanceToPlayer = waitUntilJobsDoneForNotPresentTiles(initialJobsLeft, maxProgress, listener);
|
||||||
|
if (minDistanceToPlayer < mSettings.get().mWaitUntilMinDistanceToPlayer)
|
||||||
|
{
|
||||||
|
mProcessingTiles.wait(mProcessed, [] (const auto& v) { return v.empty(); });
|
||||||
|
listener.setProgress(maxProgress);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WaitConditionType::allJobsDone:
|
||||||
|
waitUntilAllJobsDone();
|
||||||
|
listener.setProgress(maxProgress);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int AsyncNavMeshUpdater::waitUntilJobsDone(const std::size_t initialJobsLeft, std::size_t& maxProgress, Loading::Listener& listener)
|
int AsyncNavMeshUpdater::waitUntilJobsDoneForNotPresentTiles(const std::size_t initialJobsLeft, std::size_t& maxProgress, Loading::Listener& listener)
|
||||||
{
|
{
|
||||||
std::size_t prevJobsLeft = initialJobsLeft;
|
std::size_t prevJobsLeft = initialJobsLeft;
|
||||||
std::size_t jobsDone = 0;
|
std::size_t jobsDone = 0;
|
||||||
|
@ -154,9 +189,9 @@ namespace DetourNavigator
|
||||||
minDistanceToPlayer = 0;
|
minDistanceToPlayer = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
minDistanceToPlayer = getMinDistanceTo(playerPosition, maxDistanceToPlayer, mPushed);
|
minDistanceToPlayer = getMinDistanceTo(playerPosition, maxDistanceToPlayer, mPushed, mPresentTiles);
|
||||||
for (const auto& [threadId, queue] : mThreadsQueues)
|
for (const auto& [threadId, queue] : mThreadsQueues)
|
||||||
minDistanceToPlayer = getMinDistanceTo(playerPosition, minDistanceToPlayer, queue.mPushed);
|
minDistanceToPlayer = getMinDistanceTo(playerPosition, minDistanceToPlayer, queue.mPushed, mPresentTiles);
|
||||||
return minDistanceToPlayer >= maxDistanceToPlayer;
|
return minDistanceToPlayer >= maxDistanceToPlayer;
|
||||||
};
|
};
|
||||||
std::unique_lock<std::mutex> lock(mMutex);
|
std::unique_lock<std::mutex> lock(mMutex);
|
||||||
|
@ -179,6 +214,15 @@ namespace DetourNavigator
|
||||||
return minDistanceToPlayer;
|
return minDistanceToPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AsyncNavMeshUpdater::waitUntilAllJobsDone()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(mMutex);
|
||||||
|
mDone.wait(lock, [this] { return mJobs.size() + getTotalThreadJobsUnsafe() == 0; });
|
||||||
|
}
|
||||||
|
mProcessingTiles.wait(mProcessed, [] (const auto& v) { return v.empty(); });
|
||||||
|
}
|
||||||
|
|
||||||
void AsyncNavMeshUpdater::reportStats(unsigned int frameNumber, osg::Stats& stats) const
|
void AsyncNavMeshUpdater::reportStats(unsigned int frameNumber, osg::Stats& stats) const
|
||||||
{
|
{
|
||||||
std::size_t jobs = 0;
|
std::size_t jobs = 0;
|
||||||
|
@ -253,6 +297,11 @@ namespace DetourNavigator
|
||||||
navMeshVersion);
|
navMeshVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (status == UpdateNavMeshStatus::removed || status == UpdateNavMeshStatus::lost)
|
||||||
|
mPresentTiles.erase(std::make_tuple(job.mAgentHalfExtents, job.mChangedTile));
|
||||||
|
else if (isSuccess(status) && status != UpdateNavMeshStatus::ignored)
|
||||||
|
mPresentTiles.insert(std::make_tuple(job.mAgentHalfExtents, job.mChangedTile));
|
||||||
|
|
||||||
const auto finish = std::chrono::steady_clock::now();
|
const auto finish = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
writeDebugFiles(job, recastMesh.get());
|
writeDebugFiles(job, recastMesh.get());
|
||||||
|
@ -283,7 +332,7 @@ namespace DetourNavigator
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
const auto hasJob = [&] {
|
const auto hasJob = [&] {
|
||||||
return (!mJobs.empty() && mJobs.top().mProcessTime <= std::chrono::steady_clock::now())
|
return (!mJobs.empty() && mJobs.front().mProcessTime <= std::chrono::steady_clock::now())
|
||||||
|| !threadQueue.mJobs.empty();
|
|| !threadQueue.mJobs.empty();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -318,11 +367,11 @@ namespace DetourNavigator
|
||||||
{
|
{
|
||||||
const auto now = std::chrono::steady_clock::now();
|
const auto now = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
if (jobs.top().mProcessTime > now)
|
if (jobs.front().mProcessTime > now)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
Job job = jobs.top();
|
Job job = jobs.front();
|
||||||
jobs.pop();
|
jobs.pop_front();
|
||||||
|
|
||||||
if (changeLastUpdate && job.mChangeType == ChangeType::update)
|
if (changeLastUpdate && job.mChangeType == ChangeType::update)
|
||||||
mLastUpdates[job.mAgentHalfExtents][job.mChangedTile] = now;
|
mLastUpdates[job.mAgentHalfExtents][job.mChangedTile] = now;
|
||||||
|
@ -376,7 +425,7 @@ namespace DetourNavigator
|
||||||
if (mPushed[job.mAgentHalfExtents].insert(job.mChangedTile).second)
|
if (mPushed[job.mAgentHalfExtents].insert(job.mChangedTile).second)
|
||||||
{
|
{
|
||||||
++job.mTryNumber;
|
++job.mTryNumber;
|
||||||
mJobs.push(std::move(job));
|
mJobs.push_back(std::move(job));
|
||||||
mHasJob.notify_all();
|
mHasJob.notify_all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -385,7 +434,7 @@ namespace DetourNavigator
|
||||||
{
|
{
|
||||||
if (queue.mPushed[job.mAgentHalfExtents].insert(job.mChangedTile).second)
|
if (queue.mPushed[job.mAgentHalfExtents].insert(job.mChangedTile).second)
|
||||||
{
|
{
|
||||||
queue.mJobs.push(std::move(job));
|
queue.mJobs.push_back(std::move(job));
|
||||||
mHasJob.notify_all();
|
mHasJob.notify_all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "tilecachedrecastmeshmanager.hpp"
|
#include "tilecachedrecastmeshmanager.hpp"
|
||||||
#include "tileposition.hpp"
|
#include "tileposition.hpp"
|
||||||
#include "navmeshtilescache.hpp"
|
#include "navmeshtilescache.hpp"
|
||||||
|
#include "waitconditiontype.hpp"
|
||||||
|
|
||||||
#include <osg/Vec3f>
|
#include <osg/Vec3f>
|
||||||
|
|
||||||
|
@ -14,9 +15,10 @@
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <queue>
|
#include <deque>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
class dtNavMesh;
|
class dtNavMesh;
|
||||||
|
|
||||||
|
@ -60,7 +62,7 @@ namespace DetourNavigator
|
||||||
void post(const osg::Vec3f& agentHalfExtents, const SharedNavMeshCacheItem& mNavMeshCacheItem,
|
void post(const osg::Vec3f& agentHalfExtents, const SharedNavMeshCacheItem& mNavMeshCacheItem,
|
||||||
const TilePosition& playerTile, const std::map<TilePosition, ChangeType>& changedTiles);
|
const TilePosition& playerTile, const std::map<TilePosition, ChangeType>& changedTiles);
|
||||||
|
|
||||||
void wait(Loading::Listener& listener);
|
void wait(Loading::Listener& listener, WaitConditionType waitConditionType);
|
||||||
|
|
||||||
void reportStats(unsigned int frameNumber, osg::Stats& stats) const;
|
void reportStats(unsigned int frameNumber, osg::Stats& stats) const;
|
||||||
|
|
||||||
|
@ -83,11 +85,11 @@ namespace DetourNavigator
|
||||||
|
|
||||||
friend inline bool operator <(const Job& lhs, const Job& rhs)
|
friend inline bool operator <(const Job& lhs, const Job& rhs)
|
||||||
{
|
{
|
||||||
return lhs.getPriority() > rhs.getPriority();
|
return lhs.getPriority() < rhs.getPriority();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using Jobs = std::priority_queue<Job, std::deque<Job>>;
|
using Jobs = std::deque<Job>;
|
||||||
using Pushed = std::map<osg::Vec3f, std::set<TilePosition>>;
|
using Pushed = std::map<osg::Vec3f, std::set<TilePosition>>;
|
||||||
|
|
||||||
struct Queue
|
struct Queue
|
||||||
|
@ -113,6 +115,7 @@ namespace DetourNavigator
|
||||||
NavMeshTilesCache mNavMeshTilesCache;
|
NavMeshTilesCache mNavMeshTilesCache;
|
||||||
Misc::ScopeGuarded<std::map<osg::Vec3f, std::map<TilePosition, std::thread::id>>> mProcessingTiles;
|
Misc::ScopeGuarded<std::map<osg::Vec3f, std::map<TilePosition, std::thread::id>>> mProcessingTiles;
|
||||||
std::map<osg::Vec3f, std::map<TilePosition, std::chrono::steady_clock::time_point>> mLastUpdates;
|
std::map<osg::Vec3f, std::map<TilePosition, std::chrono::steady_clock::time_point>> mLastUpdates;
|
||||||
|
std::set<std::tuple<osg::Vec3f, TilePosition>> mPresentTiles;
|
||||||
std::map<std::thread::id, Queue> mThreadsQueues;
|
std::map<std::thread::id, Queue> mThreadsQueues;
|
||||||
std::vector<std::thread> mThreads;
|
std::vector<std::thread> mThreads;
|
||||||
|
|
||||||
|
@ -142,7 +145,9 @@ namespace DetourNavigator
|
||||||
|
|
||||||
void cleanupLastUpdates();
|
void cleanupLastUpdates();
|
||||||
|
|
||||||
int waitUntilJobsDone(const std::size_t initialJobsLeft, std::size_t& maxJobsLeft, Loading::Listener& listener);
|
int waitUntilJobsDoneForNotPresentTiles(const std::size_t initialJobsLeft, std::size_t& maxJobsLeft, Loading::Listener& listener);
|
||||||
|
|
||||||
|
void waitUntilAllJobsDone();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "objectid.hpp"
|
#include "objectid.hpp"
|
||||||
#include "navmeshcacheitem.hpp"
|
#include "navmeshcacheitem.hpp"
|
||||||
#include "recastmeshtiles.hpp"
|
#include "recastmeshtiles.hpp"
|
||||||
|
#include "waitconditiontype.hpp"
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
|
@ -165,9 +166,10 @@ namespace DetourNavigator
|
||||||
virtual void setUpdatesEnabled(bool enabled) = 0;
|
virtual void setUpdatesEnabled(bool enabled) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief wait locks thread until all tiles are updated from last update call.
|
* @brief wait locks thread until tiles are updated from last update call based on passed condition type.
|
||||||
|
* @param waitConditionType defines when waiting will stop
|
||||||
*/
|
*/
|
||||||
virtual void wait(Loading::Listener& listener) = 0;
|
virtual void wait(Loading::Listener& listener, WaitConditionType waitConditionType) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief findPath fills output iterator with points of scene surfaces to be used for actor to walk through.
|
* @brief findPath fills output iterator with points of scene surfaces to be used for actor to walk through.
|
||||||
|
|
|
@ -151,9 +151,9 @@ namespace DetourNavigator
|
||||||
mUpdatesEnabled = enabled;
|
mUpdatesEnabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavigatorImpl::wait(Loading::Listener& listener)
|
void NavigatorImpl::wait(Loading::Listener& listener, WaitConditionType waitConditionType)
|
||||||
{
|
{
|
||||||
mNavMeshManager.wait(listener);
|
mNavMeshManager.wait(listener, waitConditionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedNavMeshCacheItem NavigatorImpl::getNavMesh(const osg::Vec3f& agentHalfExtents) const
|
SharedNavMeshCacheItem NavigatorImpl::getNavMesh(const osg::Vec3f& agentHalfExtents) const
|
||||||
|
|
|
@ -48,7 +48,7 @@ namespace DetourNavigator
|
||||||
|
|
||||||
void setUpdatesEnabled(bool enabled) override;
|
void setUpdatesEnabled(bool enabled) override;
|
||||||
|
|
||||||
void wait(Loading::Listener& listener) override;
|
void wait(Loading::Listener& listener, WaitConditionType waitConditionType) override;
|
||||||
|
|
||||||
SharedNavMeshCacheItem getNavMesh(const osg::Vec3f& agentHalfExtents) const override;
|
SharedNavMeshCacheItem getNavMesh(const osg::Vec3f& agentHalfExtents) const override;
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ namespace DetourNavigator
|
||||||
|
|
||||||
void setUpdatesEnabled(bool /*enabled*/) override {}
|
void setUpdatesEnabled(bool /*enabled*/) override {}
|
||||||
|
|
||||||
void wait(Loading::Listener& /*listener*/) override {}
|
void wait(Loading::Listener& /*listener*/, WaitConditionType /*waitConditionType*/) override {}
|
||||||
|
|
||||||
SharedNavMeshCacheItem getNavMesh(const osg::Vec3f& /*agentHalfExtents*/) const override
|
SharedNavMeshCacheItem getNavMesh(const osg::Vec3f& /*agentHalfExtents*/) const override
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "makenavmesh.hpp"
|
#include "makenavmesh.hpp"
|
||||||
#include "navmeshcacheitem.hpp"
|
#include "navmeshcacheitem.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
#include "waitconditiontype.hpp"
|
||||||
|
|
||||||
#include <components/debug/debuglog.hpp>
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
|
@ -190,9 +191,9 @@ namespace DetourNavigator
|
||||||
" recastMeshManagerRevision=" << lastRevision;
|
" recastMeshManagerRevision=" << lastRevision;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavMeshManager::wait(Loading::Listener& listener)
|
void NavMeshManager::wait(Loading::Listener& listener, WaitConditionType waitConditionType)
|
||||||
{
|
{
|
||||||
mAsyncNavMeshUpdater.wait(listener);
|
mAsyncNavMeshUpdater.wait(listener, waitConditionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedNavMeshCacheItem NavMeshManager::getNavMesh(const osg::Vec3f& agentHalfExtents) const
|
SharedNavMeshCacheItem NavMeshManager::getNavMesh(const osg::Vec3f& agentHalfExtents) const
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "cachedrecastmeshmanager.hpp"
|
#include "cachedrecastmeshmanager.hpp"
|
||||||
#include "offmeshconnectionsmanager.hpp"
|
#include "offmeshconnectionsmanager.hpp"
|
||||||
#include "recastmeshtiles.hpp"
|
#include "recastmeshtiles.hpp"
|
||||||
|
#include "waitconditiontype.hpp"
|
||||||
|
|
||||||
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
|
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ namespace DetourNavigator
|
||||||
|
|
||||||
void update(osg::Vec3f playerPosition, const osg::Vec3f& agentHalfExtents);
|
void update(osg::Vec3f playerPosition, const osg::Vec3f& agentHalfExtents);
|
||||||
|
|
||||||
void wait(Loading::Listener& listener);
|
void wait(Loading::Listener& listener, WaitConditionType waitConditionType);
|
||||||
|
|
||||||
SharedNavMeshCacheItem getNavMesh(const osg::Vec3f& agentHalfExtents) const;
|
SharedNavMeshCacheItem getNavMesh(const osg::Vec3f& agentHalfExtents) const;
|
||||||
|
|
||||||
|
|
13
components/detournavigator/waitconditiontype.hpp
Normal file
13
components/detournavigator/waitconditiontype.hpp
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_WAITCONDITIONTYPE_H
|
||||||
|
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_WAITCONDITIONTYPE_H
|
||||||
|
|
||||||
|
namespace DetourNavigator
|
||||||
|
{
|
||||||
|
enum class WaitConditionType
|
||||||
|
{
|
||||||
|
requiredTilesPresent,
|
||||||
|
allJobsDone,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue