1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-16 15:29:55 +00:00

Do single navigator update per frame

Primarily for crossing cell border case. Each Navigator::update call has a cost.
Doing it multiple times per frame increased frame duration on cell loading.

Call Navigator::wait only when cell has changed but do not use
Scene::hasCellChanged because it doesn't always indicates it.
This commit is contained in:
elsid 2021-09-18 15:52:03 +02:00
parent 8125d51a0f
commit e1bed86d7e
No known key found for this signature in database
GPG key ID: 4DE04C198CBA7625
16 changed files with 140 additions and 215 deletions

View file

@ -7,8 +7,6 @@
#include <components/esm3/esmwriter.hpp>
#include <components/esm3/stolenitems.hpp>
#include <components/detournavigator/navigator.hpp>
#include <components/sceneutil/positionattitudetransform.hpp>
#include "../mwworld/esmstore.hpp"
@ -813,12 +811,6 @@ namespace MWMechanics
bool MechanicsManager::toggleAI()
{
mAI = !mAI;
MWBase::World* world = MWBase::Environment::get().getWorld();
world->getNavigator()->setUpdatesEnabled(mAI);
if (mAI)
world->getNavigator()->update(world->getPlayerPtr().getRefData().getPosition().asVec3());
return mAI;
}

View file

@ -365,8 +365,6 @@ namespace MWWorld
if (const auto pathgrid = mWorld.getStore().get<ESM::Pathgrid>().search(*cell->getCell()))
mNavigator.removePathgrid(*pathgrid);
mNavigator.update(mWorld.getPlayerPtr().getRefData().getPosition().asVec3());
MWBase::Environment::get().getMechanicsManager()->drop (cell);
mRendering.removeCell(cell);
@ -514,12 +512,7 @@ namespace MWWorld
void Scene::playerMoved(const osg::Vec3f &pos)
{
if (mCurrentCell == nullptr)
return;
mNavigator.updatePlayerPosition(pos);
if (!mCurrentCell->isExterior())
if (!mCurrentCell || !mCurrentCell->isExterior())
return;
osg::Vec2i newCell = getNewGridCenter(pos, &mCurrentGridCenter);
@ -619,7 +612,7 @@ namespace MWWorld
if (changeEvent)
mCellChanged = true;
mNavigator.wait(*loadingListener, DetourNavigator::WaitConditionType::requiredTilesPresent);
mCellLoaded = true;
}
void Scene::addPostponedPhysicsObjects()
@ -868,13 +861,13 @@ namespace MWWorld
if (changeEvent)
mCellChanged = true;
mCellLoaded = true;
if (useFading)
MWBase::Environment::get().getWindowManager()->fadeScreenIn(0.5);
MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell);
mNavigator.wait(*loadingListener, DetourNavigator::WaitConditionType::requiredTilesPresent);
MWBase::Environment::get().getWorld()->getPostProcessor()->setExteriorFlag(cell->getCell()->mData.mFlags & ESM::Cell::QuasiEx);
}
@ -921,11 +914,6 @@ namespace MWWorld
addObject(ptr, mWorld, mPagedRefs, *mPhysics, mRendering);
addObject(ptr, mWorld, *mPhysics, mNavigator);
mWorld.scaleObject(ptr, ptr.getCellRef().getScale());
if (mCurrentCell != nullptr)
{
const auto player = mWorld.getPlayerPtr();
mNavigator.update(player.getRefData().getPosition().asVec3());
}
}
catch (std::exception& e)
{
@ -945,11 +933,6 @@ namespace MWWorld
if (const auto object = mPhysics->getObject(ptr))
{
mNavigator.removeObject(DetourNavigator::ObjectId(object));
if (mCurrentCell != nullptr)
{
const auto player = mWorld.getPlayerPtr();
mNavigator.update(player.getRefData().getPosition().asVec3());
}
}
else if (mPhysics->getActor(ptr))
{

View file

@ -85,6 +85,7 @@ namespace MWWorld
CellStore* mCurrentCell; // the cell the player is in
CellStoreCollection mActiveCells;
bool mCellChanged;
bool mCellLoaded = false;
MWWorld::World& mWorld;
MWPhysics::PhysicsSystem *mPhysics;
MWRender::RenderingManager& mRendering;
@ -152,6 +153,10 @@ namespace MWWorld
bool hasCellChanged() const;
///< Has the set of active cells changed, since the last frame?
bool hasCellLoaded() const { return mCellLoaded; }
void resetCellLoaded() { mCellLoaded = false; }
void changeToInteriorCell (const std::string& cellName, const ESM::Position& position, bool adjustPlayerPos, bool changeEvent=true);
///< Move to interior cell.
/// @param changeEvent Set cellChanged flag?

View file

@ -154,7 +154,6 @@ namespace MWWorld
mUserDataPath(userDataPath),
mDefaultHalfExtents(Settings::Manager::getVector3("default actor pathfind half extents", "Game")),
mDefaultActorCollisionShapeType(DetourNavigator::toCollisionShapeType(Settings::Manager::getInt("actor collision shape type", "Game"))),
mShouldUpdateNavigator(false),
mActivationDistanceOverride (activationDistanceOverride),
mStartCell(startCell), mDistanceToFacedObject(-1.f), mTeleportEnabled(true),
mLevitationEnabled(true), mGoToJail(false), mDaysInPrison(0),
@ -1536,12 +1535,7 @@ namespace MWWorld
if (const auto object = mPhysics->getObject(door.first))
updateNavigatorObject(*object);
auto player = getPlayerPtr();
if (mShouldUpdateNavigator && player.getCell() != nullptr)
{
mNavigator->update(player.getRefData().getPosition().asVec3());
mShouldUpdateNavigator = false;
}
mNavigator->update(getPlayerPtr().getRefData().getPosition().asVec3());
}
void World::updateNavigatorObject(const MWPhysics::Object& object)
@ -1549,8 +1543,7 @@ namespace MWWorld
const MWWorld::Ptr ptr = object.getPtr();
const DetourNavigator::ObjectShapes shapes(object.getShapeInstance(),
DetourNavigator::ObjectTransform {ptr.getRefData().getPosition(), ptr.getCellRef().getScale()});
mShouldUpdateNavigator = mNavigator->updateObject(DetourNavigator::ObjectId(&object), shapes, object.getTransform())
|| mShouldUpdateNavigator;
mNavigator->updateObject(DetourNavigator::ObjectId(&object), shapes, object.getTransform());
}
const MWPhysics::RayCastingInterface* World::getRayCasting() const
@ -1821,10 +1814,7 @@ namespace MWWorld
updateWeather(duration, paused);
if (!paused)
{
updateNavigator();
}
updateNavigator();
mPlayer->update();
@ -1842,6 +1832,13 @@ namespace MWWorld
mSpellPreloadTimer = 0.1f;
preloadSpells();
}
if (mWorldScene->hasCellLoaded())
{
mNavigator->wait(*MWBase::Environment::get().getWindowManager()->getLoadingScreen(),
DetourNavigator::WaitConditionType::requiredTilesPresent);
mWorldScene->resetCellLoaded();
}
}
void World::updatePhysics (float duration, bool paused, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats)

View file

@ -113,7 +113,6 @@ namespace MWWorld
osg::Vec3f mDefaultHalfExtents;
DetourNavigator::CollisionShapeType mDefaultActorCollisionShapeType;
bool mShouldUpdateNavigator;
int mActivationDistanceOverride;

View file

@ -439,8 +439,17 @@ namespace
const int cellSize2 = mHeightfieldTileSize * (surface2.mSize - 1);
mNavigator->addAgent(mAgentBounds);
EXPECT_TRUE(mNavigator->addHeightfield(mCellPosition, cellSize1, surface1));
EXPECT_FALSE(mNavigator->addHeightfield(mCellPosition, cellSize2, surface2));
mNavigator->addHeightfield(mCellPosition, cellSize1, surface1);
mNavigator->update(mPlayerPosition);
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
const Version version = mNavigator->getNavMesh(mAgentBounds)->lockConst()->getVersion();
mNavigator->addHeightfield(mCellPosition, cellSize2, surface2);
mNavigator->update(mPlayerPosition);
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
EXPECT_EQ(mNavigator->getNavMesh(mAgentBounds)->lockConst()->getVersion(), version);
}
TEST_F(DetourNavigatorNavigatorTest, path_should_be_around_avoid_shape)
@ -1142,7 +1151,16 @@ namespace
const float level2 = 2;
mNavigator->addAgent(mAgentBounds);
EXPECT_TRUE(mNavigator->addWater(mCellPosition, cellSize1, level1));
EXPECT_FALSE(mNavigator->addWater(mCellPosition, cellSize2, level2));
mNavigator->addWater(mCellPosition, cellSize1, level1);
mNavigator->update(mPlayerPosition);
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
const Version version = mNavigator->getNavMesh(mAgentBounds)->lockConst()->getVersion();
mNavigator->addWater(mCellPosition, cellSize2, level2);
mNavigator->update(mPlayerPosition);
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
EXPECT_EQ(mNavigator->getNavMesh(mAgentBounds)->lockConst()->getVersion(), version);
}
}

View file

@ -216,27 +216,13 @@ namespace DetourNavigator
void AsyncNavMeshUpdater::wait(Loading::Listener& listener, WaitConditionType waitConditionType)
{
if (mSettings.get().mWaitUntilMinDistanceToPlayer == 0)
return;
listener.setLabel("#{Navigation:BuildingNavigationMesh}");
const std::size_t initialJobsLeft = getTotalJobs();
std::size_t maxProgress = initialJobsLeft + mThreads.size();
listener.setProgressRange(maxProgress);
switch (waitConditionType)
{
case WaitConditionType::requiredTilesPresent:
{
const int minDistanceToPlayer = waitUntilJobsDoneForNotPresentTiles(initialJobsLeft, maxProgress, listener);
if (minDistanceToPlayer < mSettings.get().mWaitUntilMinDistanceToPlayer)
{
mProcessingTiles.wait(mProcessed, [] (const auto& v) { return v.empty(); });
listener.setProgress(maxProgress);
}
waitUntilJobsDoneForNotPresentTiles(listener);
break;
}
case WaitConditionType::allJobsDone:
waitUntilAllJobsDone();
listener.setProgress(maxProgress);
break;
}
}
@ -255,8 +241,10 @@ namespace DetourNavigator
thread.join();
}
int AsyncNavMeshUpdater::waitUntilJobsDoneForNotPresentTiles(const std::size_t initialJobsLeft, std::size_t& maxProgress, Loading::Listener& listener)
void AsyncNavMeshUpdater::waitUntilJobsDoneForNotPresentTiles(Loading::Listener& listener)
{
const std::size_t initialJobsLeft = getTotalJobs();
std::size_t maxProgress = initialJobsLeft + mThreads.size();
std::size_t prevJobsLeft = initialJobsLeft;
std::size_t jobsDone = 0;
std::size_t jobsLeft = 0;
@ -275,7 +263,13 @@ namespace DetourNavigator
return minDistanceToPlayer >= maxDistanceToPlayer;
};
std::unique_lock<std::mutex> lock(mMutex);
while (!mDone.wait_for(lock, std::chrono::milliseconds(250), isDone))
if (getMinDistanceTo(playerPosition, maxDistanceToPlayer, mPushed, mPresentTiles) >= maxDistanceToPlayer
|| (mJobs.empty() && mProcessingTiles.lockConst()->empty()))
return;
Loading::ScopedLoad load(&listener);
listener.setLabel("#{Navigation:BuildingNavigationMesh}");
listener.setProgressRange(maxProgress);
while (!mDone.wait_for(lock, std::chrono::milliseconds(20), isDone))
{
if (maxProgress < jobsLeft)
{
@ -291,14 +285,19 @@ namespace DetourNavigator
listener.increaseProgress(newJobsDone);
}
}
return minDistanceToPlayer;
lock.unlock();
if (minDistanceToPlayer < maxDistanceToPlayer)
{
mProcessingTiles.wait(mProcessed, [] (const auto& v) { return v.empty(); });
listener.setProgress(maxProgress);
}
}
void AsyncNavMeshUpdater::waitUntilAllJobsDone()
{
{
std::unique_lock<std::mutex> lock(mMutex);
mDone.wait(lock, [this] { return mJobs.size() == 0; });
mDone.wait(lock, [this] { return mJobs.empty(); });
}
mProcessingTiles.wait(mProcessed, [] (const auto& v) { return v.empty(); });
}

View file

@ -223,9 +223,9 @@ namespace DetourNavigator
void cleanupLastUpdates();
int waitUntilJobsDoneForNotPresentTiles(const std::size_t initialJobsLeft, std::size_t& maxJobsLeft, Loading::Listener& listener);
inline void waitUntilJobsDoneForNotPresentTiles(Loading::Listener& listener);
void waitUntilAllJobsDone();
inline void waitUntilAllJobsDone();
};
void reportStats(const AsyncNavMeshUpdater::Stats& stats, unsigned int frameNumber, osg::Stats& out);

View file

@ -3,6 +3,7 @@
#include "recastmesh.hpp"
#include "settings.hpp"
#include "settingsutils.hpp"
#include "version.hpp"
#include <components/bullethelpers/operators.hpp>
@ -191,6 +192,11 @@ namespace DetourNavigator
return stream << "ChangeType::" << static_cast<int>(value);
}
std::ostream& operator<<(std::ostream& stream, const Version& value)
{
return stream << "Version {" << value.mGeneration << ", " << value.mRevision << "}";
}
void writeToFile(const RecastMesh& recastMesh, const std::string& pathPrefix,
const std::string& revision, const RecastSettings& settings)
{

View file

@ -18,6 +18,8 @@ class dtNavMesh;
namespace DetourNavigator
{
struct Version;
std::ostream& operator<<(std::ostream& stream, const TileBounds& value);
std::ostream& operator<<(std::ostream& stream, Status value);
@ -54,6 +56,8 @@ namespace DetourNavigator
std::ostream& operator<<(std::ostream& stream, ChangeType value);
std::ostream& operator<<(std::ostream& stream, const Version& value);
class RecastMesh;
struct RecastSettings;

View file

@ -100,65 +100,56 @@ namespace DetourNavigator
* @param id is used to distinguish different objects
* @param shape members must live until object is updated by another shape removed from Navigator
* @param transform allows to setup objects geometry according to its world state
* @return true if object is added, false if there is already object with given id
*/
virtual bool addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) = 0;
virtual void addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) = 0;
/**
* @brief addObject is used to add doors.
* @param id is used to distinguish different objects.
* @param shape members must live until object is updated by another shape or removed from Navigator.
* @param transform allows to setup objects geometry according to its world state.
* @return true if object is added, false if there is already object with given id.
*/
virtual bool addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) = 0;
virtual void addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) = 0;
/**
* @brief updateObject replace object geometry by given data.
* @param id is used to find object.
* @param shape members must live until object is updated by another shape removed from Navigator.
* @param transform allows to setup objects geometry according to its world state.
* @return true if object is updated, false if there is no object with given id.
*/
virtual bool updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) = 0;
virtual void updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) = 0;
/**
* @brief updateObject replace object geometry by given data.
* @param id is used to find object.
* @param shape members must live until object is updated by another shape removed from Navigator.
* @param transform allows to setup objects geometry according to its world state.
* @return true if object is updated, false if there is no object with given id.
*/
virtual bool updateObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) = 0;
virtual void updateObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) = 0;
/**
* @brief removeObject to make it no more available at the scene.
* @param id is used to find object.
* @return true if object is removed, false if there is no object with given id.
*/
virtual bool removeObject(const ObjectId id) = 0;
virtual void removeObject(const ObjectId id) = 0;
/**
* @brief addWater is used to set water level at given world cell.
* @param cellPosition allows to distinguish cells if there is many in current world.
* @param cellSize set cell borders. std::numeric_limits<int>::max() disables cell borders.
* @param shift set global shift of cell center.
* @return true if there was no water at given cell if cellSize != std::numeric_limits<int>::max() or there is
* at least single object is added to the scene, false if there is already water for given cell or there is no
* any other objects.
*/
virtual bool addWater(const osg::Vec2i& cellPosition, int cellSize, float level) = 0;
virtual void addWater(const osg::Vec2i& cellPosition, int cellSize, float level) = 0;
/**
* @brief removeWater to make it no more available at the scene.
* @param cellPosition allows to find cell.
* @return true if there was water at given cell.
*/
virtual bool removeWater(const osg::Vec2i& cellPosition) = 0;
virtual void removeWater(const osg::Vec2i& cellPosition) = 0;
virtual bool addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape) = 0;
virtual void addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape) = 0;
virtual bool removeHeightfield(const osg::Vec2i& cellPosition) = 0;
virtual void removeHeightfield(const osg::Vec2i& cellPosition) = 0;
virtual void addPathgrid(const ESM::Cell& cell, const ESM::Pathgrid& pathgrid) = 0;
@ -170,17 +161,6 @@ namespace DetourNavigator
*/
virtual void update(const osg::Vec3f& playerPosition) = 0;
/**
* @brief updatePlayerPosition starts background navmesh update using current scene state only when player position has been changed.
* @param playerPosition setup initial point to order build tiles of navmesh.
*/
virtual void updatePlayerPosition(const osg::Vec3f& playerPosition) = 0;
/**
* @brief disable navigator updates
*/
virtual void setUpdatesEnabled(bool enabled) = 0;
/**
* @brief wait locks thread until tiles are updated from last update call based on passed condition type.
* @param waitConditionType defines when waiting will stop

View file

@ -11,7 +11,6 @@ namespace DetourNavigator
NavigatorImpl::NavigatorImpl(const Settings& settings, std::unique_ptr<NavMeshDb>&& db)
: mSettings(settings)
, mNavMeshManager(mSettings, std::move(db))
, mUpdatesEnabled(true)
{
}
@ -42,7 +41,12 @@ namespace DetourNavigator
mNavMeshManager.updateBounds(playerPosition);
}
bool NavigatorImpl::addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform)
void NavigatorImpl::addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform)
{
addObjectImpl(id, shapes, transform);
}
bool NavigatorImpl::addObjectImpl(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform)
{
const CollisionShape collisionShape(shapes.mShapeInstance, *shapes.mShapeInstance->mCollisionShape, shapes.mTransform);
bool result = mNavMeshManager.addObject(id, collisionShape, transform, AreaType_ground);
@ -59,72 +63,65 @@ namespace DetourNavigator
return result;
}
bool NavigatorImpl::addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform)
void NavigatorImpl::addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform)
{
if (addObject(id, static_cast<const ObjectShapes&>(shapes), transform))
if (addObjectImpl(id, static_cast<const ObjectShapes&>(shapes), transform))
{
const osg::Vec3f start = toNavMeshCoordinates(mSettings.mRecast, shapes.mConnectionStart);
const osg::Vec3f end = toNavMeshCoordinates(mSettings.mRecast, shapes.mConnectionEnd);
mNavMeshManager.addOffMeshConnection(id, start, end, AreaType_door);
mNavMeshManager.addOffMeshConnection(id, end, start, AreaType_door);
return true;
}
return false;
}
bool NavigatorImpl::updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform)
void NavigatorImpl::updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform)
{
const CollisionShape collisionShape(shapes.mShapeInstance, *shapes.mShapeInstance->mCollisionShape, shapes.mTransform);
bool result = mNavMeshManager.updateObject(id, collisionShape, transform, AreaType_ground);
mNavMeshManager.updateObject(id, collisionShape, transform, AreaType_ground);
if (const btCollisionShape* const avoidShape = shapes.mShapeInstance->mAvoidCollisionShape.get())
{
const ObjectId avoidId(avoidShape);
const CollisionShape avoidCollisionShape(shapes.mShapeInstance, *avoidShape, shapes.mTransform);
if (mNavMeshManager.updateObject(avoidId, avoidCollisionShape, transform, AreaType_null))
{
updateAvoidShapeId(id, avoidId);
result = true;
}
}
return result;
}
bool NavigatorImpl::updateObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform)
void NavigatorImpl::updateObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform)
{
return updateObject(id, static_cast<const ObjectShapes&>(shapes), transform);
}
bool NavigatorImpl::removeObject(const ObjectId id)
void NavigatorImpl::removeObject(const ObjectId id)
{
bool result = mNavMeshManager.removeObject(id);
mNavMeshManager.removeObject(id);
const auto avoid = mAvoidIds.find(id);
if (avoid != mAvoidIds.end())
result = mNavMeshManager.removeObject(avoid->second) || result;
mNavMeshManager.removeObject(avoid->second);
const auto water = mWaterIds.find(id);
if (water != mWaterIds.end())
result = mNavMeshManager.removeObject(water->second) || result;
mNavMeshManager.removeObject(water->second);
mNavMeshManager.removeOffMeshConnections(id);
return result;
}
bool NavigatorImpl::addWater(const osg::Vec2i& cellPosition, int cellSize, float level)
void NavigatorImpl::addWater(const osg::Vec2i& cellPosition, int cellSize, float level)
{
return mNavMeshManager.addWater(cellPosition, cellSize, level);
mNavMeshManager.addWater(cellPosition, cellSize, level);
}
bool NavigatorImpl::removeWater(const osg::Vec2i& cellPosition)
void NavigatorImpl::removeWater(const osg::Vec2i& cellPosition)
{
return mNavMeshManager.removeWater(cellPosition);
mNavMeshManager.removeWater(cellPosition);
}
bool NavigatorImpl::addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape)
void NavigatorImpl::addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape)
{
return mNavMeshManager.addHeightfield(cellPosition, cellSize, shape);
mNavMeshManager.addHeightfield(cellPosition, cellSize, shape);
}
bool NavigatorImpl::removeHeightfield(const osg::Vec2i& cellPosition)
void NavigatorImpl::removeHeightfield(const osg::Vec2i& cellPosition)
{
return mNavMeshManager.removeHeightfield(cellPosition);
mNavMeshManager.removeHeightfield(cellPosition);
}
void NavigatorImpl::addPathgrid(const ESM::Cell& cell, const ESM::Pathgrid& pathgrid)
@ -150,31 +147,15 @@ namespace DetourNavigator
void NavigatorImpl::update(const osg::Vec3f& playerPosition)
{
if (!mUpdatesEnabled)
return;
removeUnusedNavMeshes();
for (const auto& v : mAgents)
mNavMeshManager.update(playerPosition, v.first);
}
void NavigatorImpl::updatePlayerPosition(const osg::Vec3f& playerPosition)
{
const TilePosition tilePosition = getTilePosition(mSettings.mRecast, toNavMeshCoordinates(mSettings.mRecast, playerPosition));
if (mLastPlayerPosition.has_value() && *mLastPlayerPosition == tilePosition)
return;
mNavMeshManager.updateBounds(playerPosition);
update(playerPosition);
mLastPlayerPosition = tilePosition;
}
void NavigatorImpl::setUpdatesEnabled(bool enabled)
{
mUpdatesEnabled = enabled;
}
void NavigatorImpl::wait(Loading::Listener& listener, WaitConditionType waitConditionType)
{
mNavMeshManager.wait(listener, waitConditionType);
if (mSettings.mWaitUntilMinDistanceToPlayer > 0)
mNavMeshManager.wait(listener, waitConditionType);
}
SharedNavMeshCacheItem NavigatorImpl::getNavMesh(const AgentBounds& agentBounds) const

View file

@ -26,23 +26,23 @@ namespace DetourNavigator
void updateBounds(const osg::Vec3f& playerPosition) override;
bool addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) override;
void addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) override;
bool addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) override;
void addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) override;
bool updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) override;
void updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) override;
bool updateObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) override;
void updateObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) override;
bool removeObject(const ObjectId id) override;
void removeObject(const ObjectId id) override;
bool addWater(const osg::Vec2i& cellPosition, int cellSize, float level) override;
void addWater(const osg::Vec2i& cellPosition, int cellSize, float level) override;
bool removeWater(const osg::Vec2i& cellPosition) override;
void removeWater(const osg::Vec2i& cellPosition) override;
bool addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape) override;
void addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape) override;
bool removeHeightfield(const osg::Vec2i& cellPosition) override;
void removeHeightfield(const osg::Vec2i& cellPosition) override;
void addPathgrid(const ESM::Cell& cell, const ESM::Pathgrid& pathgrid) override;
@ -50,10 +50,6 @@ namespace DetourNavigator
void update(const osg::Vec3f& playerPosition) override;
void updatePlayerPosition(const osg::Vec3f& playerPosition) override;
void setUpdatesEnabled(bool enabled) override;
void wait(Loading::Listener& listener, WaitConditionType waitConditionType) override;
SharedNavMeshCacheItem getNavMesh(const AgentBounds& agentBounds) const override;
@ -71,12 +67,12 @@ namespace DetourNavigator
private:
Settings mSettings;
NavMeshManager mNavMeshManager;
bool mUpdatesEnabled;
std::optional<TilePosition> mLastPlayerPosition;
std::map<AgentBounds, std::size_t> mAgents;
std::unordered_map<ObjectId, ObjectId> mAvoidIds;
std::unordered_map<ObjectId, ObjectId> mWaterIds;
inline bool addObjectImpl(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform);
void updateAvoidShapeId(const ObjectId id, const ObjectId avoidId);
void updateWaterShapeId(const ObjectId id, const ObjectId waterId);
void updateId(const ObjectId id, const ObjectId waterId, std::unordered_map<ObjectId, ObjectId>& ids);

View file

@ -22,50 +22,24 @@ namespace DetourNavigator
void setWorldspace(std::string_view /*worldspace*/) override {}
bool addObject(const ObjectId /*id*/, const ObjectShapes& /*shapes*/, const btTransform& /*transform*/) override
{
return false;
}
void addObject(const ObjectId /*id*/, const ObjectShapes& /*shapes*/, const btTransform& /*transform*/) override {}
bool addObject(const ObjectId /*id*/, const DoorShapes& /*shapes*/, const btTransform& /*transform*/) override
{
return false;
}
void addObject(const ObjectId /*id*/, const DoorShapes& /*shapes*/, const btTransform& /*transform*/) override {}
bool updateObject(const ObjectId /*id*/, const ObjectShapes& /*shapes*/, const btTransform& /*transform*/) override
{
return false;
}
void updateObject(const ObjectId /*id*/, const ObjectShapes& /*shapes*/, const btTransform& /*transform*/) override {}
bool updateObject(const ObjectId /*id*/, const DoorShapes& /*shapes*/, const btTransform& /*transform*/) override
{
return false;
}
void updateObject(const ObjectId /*id*/, const DoorShapes& /*shapes*/, const btTransform& /*transform*/) override {}
bool removeObject(const ObjectId /*id*/) override
{
return false;
}
void removeObject(const ObjectId /*id*/) override {}
bool addWater(const osg::Vec2i& /*cellPosition*/, int /*cellSize*/, float /*level*/) override
{
return false;
}
void addWater(const osg::Vec2i& /*cellPosition*/, int /*cellSize*/, float /*level*/) override {}
bool removeWater(const osg::Vec2i& /*cellPosition*/) override
{
return false;
}
void removeWater(const osg::Vec2i& /*cellPosition*/) override {}
bool addHeightfield(const osg::Vec2i& /*cellPosition*/, int /*cellSize*/, const HeightfieldShape& /*height*/) override
{
return false;
}
void addHeightfield(const osg::Vec2i& /*cellPosition*/, int /*cellSize*/, const HeightfieldShape& /*height*/)
override {}
bool removeHeightfield(const osg::Vec2i& /*cellPosition*/) override
{
return false;
}
void removeHeightfield(const osg::Vec2i& /*cellPosition*/) override {}
void addPathgrid(const ESM::Cell& /*cell*/, const ESM::Pathgrid& /*pathgrid*/) override {}
@ -75,10 +49,6 @@ namespace DetourNavigator
void updateBounds(const osg::Vec3f& /*playerPosition*/) override {}
void updatePlayerPosition(const osg::Vec3f& /*playerPosition*/) override {};
void setUpdatesEnabled(bool /*enabled*/) override {}
void wait(Loading::Listener& /*listener*/, WaitConditionType /*waitConditionType*/) override {}
SharedNavMeshCacheItem getNavMesh(const AgentBounds& /*agentBounds*/) const override

View file

@ -107,51 +107,46 @@ namespace DetourNavigator
[&] (const TilePosition& tile, ChangeType changeType) { addChangedTile(tile, changeType); });
}
bool NavMeshManager::removeObject(const ObjectId id)
void NavMeshManager::removeObject(const ObjectId id)
{
const auto object = mRecastMeshManager.removeObject(id);
if (!object)
return false;
return;
addChangedTiles(object->mShape, object->mTransform, ChangeType::remove);
return true;
}
bool NavMeshManager::addWater(const osg::Vec2i& cellPosition, int cellSize, float level)
void NavMeshManager::addWater(const osg::Vec2i& cellPosition, int cellSize, float level)
{
if (!mRecastMeshManager.addWater(cellPosition, cellSize, level))
return false;
return;
const btVector3 shift = Misc::Convert::toBullet(getWaterShift3d(cellPosition, cellSize, level));
addChangedTiles(cellSize, shift, ChangeType::add);
return true;
}
bool NavMeshManager::removeWater(const osg::Vec2i& cellPosition)
void NavMeshManager::removeWater(const osg::Vec2i& cellPosition)
{
const auto water = mRecastMeshManager.removeWater(cellPosition);
if (!water)
return false;
return;
const btVector3 shift = Misc::Convert::toBullet(getWaterShift3d(cellPosition, water->mCellSize, water->mLevel));
addChangedTiles(water->mCellSize, shift, ChangeType::remove);
return true;
}
bool NavMeshManager::addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape)
void NavMeshManager::addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape)
{
if (!mRecastMeshManager.addHeightfield(cellPosition, cellSize, shape))
return false;
return;
const btVector3 shift = getHeightfieldShift(shape, cellPosition, cellSize);
addChangedTiles(cellSize, shift, ChangeType::add);
return true;
}
bool NavMeshManager::removeHeightfield(const osg::Vec2i& cellPosition)
void NavMeshManager::removeHeightfield(const osg::Vec2i& cellPosition)
{
const auto heightfield = mRecastMeshManager.removeHeightfield(cellPosition);
if (!heightfield)
return false;
return;
const btVector3 shift = getHeightfieldShift(heightfield->mShape, cellPosition, heightfield->mCellSize);
addChangedTiles(heightfield->mCellSize, shift, ChangeType::remove);
return true;
}
void NavMeshManager::addAgent(const AgentBounds& agentBounds)

View file

@ -32,17 +32,17 @@ namespace DetourNavigator
bool updateObject(const ObjectId id, const CollisionShape& shape, const btTransform& transform,
const AreaType areaType);
bool removeObject(const ObjectId id);
void removeObject(const ObjectId id);
void addAgent(const AgentBounds& agentBounds);
bool addWater(const osg::Vec2i& cellPosition, int cellSize, float level);
void addWater(const osg::Vec2i& cellPosition, int cellSize, float level);
bool removeWater(const osg::Vec2i& cellPosition);
void removeWater(const osg::Vec2i& cellPosition);
bool addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape);
void addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape);
bool removeHeightfield(const osg::Vec2i& cellPosition);
void removeHeightfield(const osg::Vec2i& cellPosition);
bool reset(const AgentBounds& agentBounds);