diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index db6bda1419..bd7583f404 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -601,6 +601,8 @@ namespace MWBase virtual void updateActorPath(const MWWorld::ConstPtr& actor, const std::deque& path, const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end) const = 0; + + virtual void setNavMeshNumberToRender(const std::size_t value) = 0; }; } diff --git a/apps/openmw/mwrender/navmesh.cpp b/apps/openmw/mwrender/navmesh.cpp index 787e332e92..23f4a8d58b 100644 --- a/apps/openmw/mwrender/navmesh.cpp +++ b/apps/openmw/mwrender/navmesh.cpp @@ -31,12 +31,13 @@ namespace MWRender return mEnabled; } - void NavMesh::update(const DetourNavigator::SharedNavMesh& sharedNavMesh, std::size_t generation, - std::size_t revision, const DetourNavigator::Settings& settings) + void NavMesh::update(const DetourNavigator::SharedNavMesh& sharedNavMesh, const std::size_t id, + const std::size_t generation, const std::size_t revision, const DetourNavigator::Settings& settings) { - if (!mEnabled || (mGeneration >= generation && mRevision >= revision)) + if (!mEnabled || (mId == id && mGeneration >= generation && mRevision >= revision)) return; + mId = id; mGeneration = generation; mRevision = revision; if (mGroup) @@ -49,6 +50,12 @@ namespace MWRender } } + void NavMesh::reset() + { + if (mGroup) + mRootNode->removeChild(mGroup); + } + void NavMesh::enable() { if (mGroup) @@ -58,8 +65,7 @@ namespace MWRender void NavMesh::disable() { - if (mGroup) - mRootNode->removeChild(mGroup); + reset(); mEnabled = false; } } diff --git a/apps/openmw/mwrender/navmesh.hpp b/apps/openmw/mwrender/navmesh.hpp index 0bed616f9c..34e71a70c2 100644 --- a/apps/openmw/mwrender/navmesh.hpp +++ b/apps/openmw/mwrender/navmesh.hpp @@ -21,9 +21,12 @@ namespace MWRender bool toggle(); - void update(const DetourNavigator::SharedNavMesh& sharedNavMesh, std::size_t generation, std::size_t revision, + void update(const DetourNavigator::SharedNavMesh& sharedNavMesh, + const std::size_t number, const std::size_t generation, const std::size_t revision, const DetourNavigator::Settings& settings); + void reset(); + void enable(); void disable(); @@ -31,6 +34,7 @@ namespace MWRender private: osg::ref_ptr mRootNode; bool mEnabled; + std::size_t mId = std::numeric_limits::max(); std::size_t mGeneration; std::size_t mRevision; osg::ref_ptr mGroup; diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 5c0a3347cb..bc540d7e60 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -600,12 +600,20 @@ namespace MWRender } const auto navMeshes = mNavigator.getNavMeshes(); - if (!navMeshes.empty()) + + auto it = navMeshes.begin(); + for (std::size_t i = 0; it != navMeshes.end() && i < mNavMeshNumber; ++i) + ++it; + if (it == navMeshes.end()) + { + mNavMesh->reset(); + } + else { try { - mNavMesh->update(navMeshes.begin()->second->mValue, navMeshes.begin()->second->mGeneration, - navMeshes.begin()->second->mNavMeshRevision, mNavigator.getSettings()); + mNavMesh->update(it->second->mValue, mNavMeshNumber, it->second->mGeneration, + it->second->mNavMeshRevision, mNavigator.getSettings()); } catch (const std::exception& e) { @@ -1388,4 +1396,9 @@ namespace MWRender { mActorsPaths->remove(actor); } + + void RenderingManager::setNavMeshNumber(const std::size_t value) + { + mNavMeshNumber = value; + } } diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 76ec674453..7a4500ac90 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -228,6 +228,8 @@ namespace MWRender void removeActorPath(const MWWorld::ConstPtr& actor) const; + void setNavMeshNumber(const std::size_t value); + private: void updateProjectionMatrix(); void updateTextureFiltering(); @@ -254,6 +256,7 @@ namespace MWRender DetourNavigator::Navigator& mNavigator; std::unique_ptr mNavMesh; + std::size_t mNavMeshNumber = 0; std::unique_ptr mActorsPaths; std::unique_ptr mPathgrid; std::unique_ptr mObjects; diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index bc7d93a136..d346ab6e43 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -457,5 +457,6 @@ op 0x2000306: OnActivate, explicit op 0x2000307: ToggleBorders, tb op 0x2000308: ToggleNavMesh op 0x2000309: ToggleActorsPaths +op 0x200030a: SetNavMeshNumber -opcodes 0x200030a-0x3ffffff unused +opcodes 0x200030b-0x3ffffff unused diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 8507b7628e..0cf2fc464b 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -1345,6 +1345,25 @@ namespace MWScript } }; + class OpSetNavMeshNumberToRender : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + const auto navMeshNumber = runtime[0].mInteger; + runtime.pop(); + + if (navMeshNumber < 0) + { + runtime.getContext().report("Invalid navmesh number: use not less than zero values"); + return; + } + + MWBase::Environment::get().getWorld()->setNavMeshNumberToRender(static_cast(navMeshNumber)); + } + }; + void installOpcodes (Interpreter::Interpreter& interpreter) { interpreter.installSegment5 (Compiler::Misc::opcodeXBox, new OpXBox); @@ -1447,6 +1466,7 @@ namespace MWScript interpreter.installSegment5 (Compiler::Misc::opcodeToggleBorders, new OpToggleBorders); interpreter.installSegment5 (Compiler::Misc::opcodeToggleNavMesh, new OpToggleNavMesh); interpreter.installSegment5 (Compiler::Misc::opcodeToggleActorsPaths, new OpToggleActorsPaths); + interpreter.installSegment5 (Compiler::Misc::opcodeSetNavMeshNumberToRender, new OpSetNavMeshNumberToRender); } } } diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index f68f1008c0..18ceffba42 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -175,8 +175,10 @@ namespace } else if (const auto actor = physics.getActor(ptr)) { - const auto playerHalfExtents = physics.getHalfExtents(MWBase::Environment::get().getWorld()->getPlayerPtr()); - navigator.addAgent(playerHalfExtents); + const auto halfExtents = ptr.getCell()->isExterior() + ? physics.getHalfExtents(MWBase::Environment::get().getWorld()->getPlayerPtr()) + : actor->getHalfExtents(); + navigator.addAgent(halfExtents); } } @@ -344,7 +346,7 @@ namespace MWWorld navigator->removeObject(reinterpret_cast(object)); else if (const auto actor = mPhysics->getActor(ptr)) { - navigator->removeAgent(playerHalfExtents); + navigator->removeAgent(ptr.getCell()->isExterior() ? playerHalfExtents : actor->getHalfExtents()); mRendering.removeActorPath(ptr); } mPhysics->remove(ptr); @@ -812,8 +814,10 @@ namespace MWWorld } else if (const auto actor = mPhysics->getActor(ptr)) { - const auto playerHalfExtents = mPhysics->getHalfExtents(MWBase::Environment::get().getWorld()->getPlayerPtr()); - navigator->removeAgent(playerHalfExtents); + const auto& halfExtents = ptr.getCell()->isExterior() + ? mPhysics->getHalfExtents(MWBase::Environment::get().getWorld()->getPlayerPtr()) + : actor->getHalfExtents(); + navigator->removeAgent(halfExtents); } mPhysics->remove(ptr); mRendering.removeObject (ptr); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index bfa6b5124a..6cfba1e260 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -3767,4 +3767,9 @@ namespace MWWorld mRendering->updateActorPath(actor, path, halfExtents, start, end); } + void World::setNavMeshNumberToRender(const std::size_t value) + { + mRendering->setNavMeshNumber(value); + } + } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index adf6ece3d3..49cae93ec6 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -703,6 +703,8 @@ namespace MWWorld void updateActorPath(const MWWorld::ConstPtr& actor, const std::deque& path, const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end) const override; + + void setNavMeshNumberToRender(const std::size_t value) override; }; } diff --git a/components/compiler/extensions0.cpp b/components/compiler/extensions0.cpp index 241abfaa40..a640d76d89 100644 --- a/components/compiler/extensions0.cpp +++ b/components/compiler/extensions0.cpp @@ -322,6 +322,7 @@ namespace Compiler extensions.registerInstruction ("toggleborders", "", opcodeToggleBorders); extensions.registerInstruction ("togglenavmesh", "", opcodeToggleNavMesh); extensions.registerInstruction ("toggleactorspaths", "", opcodeToggleActorsPaths); + extensions.registerInstruction ("setnavmeshnumber", "l", opcodeSetNavMeshNumberToRender); } } diff --git a/components/compiler/opcodes.hpp b/components/compiler/opcodes.hpp index c591115ec2..a2d8a9467c 100644 --- a/components/compiler/opcodes.hpp +++ b/components/compiler/opcodes.hpp @@ -298,6 +298,7 @@ namespace Compiler const int opcodeToggleBorders = 0x2000307; const int opcodeToggleNavMesh = 0x2000308; const int opcodeToggleActorsPaths = 0x2000309; + const int opcodeSetNavMeshNumberToRender = 0x200030a; } namespace Sky diff --git a/components/detournavigator/navmeshmanager.cpp b/components/detournavigator/navmeshmanager.cpp index 07df5c7af3..67514b8b78 100644 --- a/components/detournavigator/navmeshmanager.cpp +++ b/components/detournavigator/navmeshmanager.cpp @@ -122,11 +122,16 @@ namespace DetourNavigator void NavMeshManager::update(osg::Vec3f playerPosition, const osg::Vec3f& agentHalfExtents) { const auto playerTile = getTilePosition(mSettings, toNavMeshCoordinates(mSettings, playerPosition)); - if (mLastRecastMeshManagerRevision >= mRecastMeshManager.getRevision() && mPlayerTile - && *mPlayerTile == playerTile) + auto& lastRevision = mLastRecastMeshManagerRevision[agentHalfExtents]; + auto lastPlayerTile = mPlayerTile.find(agentHalfExtents); + if (lastRevision >= mRecastMeshManager.getRevision() && lastPlayerTile != mPlayerTile.end() + && lastPlayerTile->second == playerTile) return; - mLastRecastMeshManagerRevision = mRecastMeshManager.getRevision(); - mPlayerTile = playerTile; + lastRevision = mRecastMeshManager.getRevision(); + if (lastPlayerTile == mPlayerTile.end()) + lastPlayerTile = mPlayerTile.insert(std::make_pair(agentHalfExtents, playerTile)).first; + else + lastPlayerTile->second = playerTile; std::map tilesToPost; const auto& cached = getCached(agentHalfExtents); const auto changedTiles = mChangedTiles.find(agentHalfExtents); @@ -163,8 +168,8 @@ namespace DetourNavigator } mAsyncNavMeshUpdater.post(agentHalfExtents, cached, playerTile, tilesToPost); log("cache update posted for agent=", agentHalfExtents, - " playerTile=", *mPlayerTile, - " recastMeshManagerRevision=", mLastRecastMeshManagerRevision, + " playerTile=", lastPlayerTile->second, + " recastMeshManagerRevision=", lastRevision, " changedTiles=", changedTiles->second.size()); } diff --git a/components/detournavigator/navmeshmanager.hpp b/components/detournavigator/navmeshmanager.hpp index acec44eb9e..cd8c55aa06 100644 --- a/components/detournavigator/navmeshmanager.hpp +++ b/components/detournavigator/navmeshmanager.hpp @@ -58,8 +58,8 @@ namespace DetourNavigator std::map> mChangedTiles; AsyncNavMeshUpdater mAsyncNavMeshUpdater; std::size_t mGenerationCounter = 0; - boost::optional mPlayerTile; - std::size_t mLastRecastMeshManagerRevision = 0; + std::map mPlayerTile; + std::map mLastRecastMeshManagerRevision; void addChangedTiles(const btCollisionShape& shape, const btTransform& transform, const ChangeType changeType);