mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-29 17:15:34 +00:00
Limit RecastMeshManager range by active cell grid
This commit is contained in:
parent
49db37ee29
commit
45d62ee59f
12 changed files with 180 additions and 31 deletions
|
@ -572,11 +572,11 @@ namespace MWWorld
|
|||
|
||||
void Scene::changeCellGrid(const osg::Vec3f& pos, ESM::ExteriorCellLocation playerCellIndex, bool changeEvent)
|
||||
{
|
||||
mHalfGridSize
|
||||
const int halfGridSize
|
||||
= isEsm4Ext(playerCellIndex.mWorldspace) ? Constants::ESM4CellGridRadius : Constants::CellGridRadius;
|
||||
auto navigatorUpdateGuard = mNavigator.makeUpdateGuard();
|
||||
int playerCellX = playerCellIndex.mX;
|
||||
int playerCellY = playerCellIndex.mY;
|
||||
const int playerCellX = playerCellIndex.mX;
|
||||
const int playerCellY = playerCellIndex.mY;
|
||||
|
||||
for (auto iter = mActiveCells.begin(); iter != mActiveCells.end();)
|
||||
{
|
||||
|
@ -585,15 +585,21 @@ namespace MWWorld
|
|||
{
|
||||
const auto dx = std::abs(playerCellX - cell->getCell()->getGridX());
|
||||
const auto dy = std::abs(playerCellY - cell->getCell()->getGridY());
|
||||
if (dx > mHalfGridSize || dy > mHalfGridSize)
|
||||
if (dx > halfGridSize || dy > halfGridSize)
|
||||
unloadCell(cell, navigatorUpdateGuard.get());
|
||||
}
|
||||
else
|
||||
unloadCell(cell, navigatorUpdateGuard.get());
|
||||
}
|
||||
|
||||
mNavigator.updateBounds(playerCellIndex.mWorldspace, pos, navigatorUpdateGuard.get());
|
||||
const DetourNavigator::CellGridBounds cellGridBounds{
|
||||
.mCenter = osg::Vec2i(playerCellX, playerCellY),
|
||||
.mHalfSize = halfGridSize,
|
||||
};
|
||||
|
||||
mNavigator.updateBounds(playerCellIndex.mWorldspace, cellGridBounds, pos, navigatorUpdateGuard.get());
|
||||
|
||||
mHalfGridSize = halfGridSize;
|
||||
mCurrentGridCenter = osg::Vec2i(playerCellX, playerCellY);
|
||||
osg::Vec4i newGrid = gridCenterToBounds(mCurrentGridCenter);
|
||||
mRendering.setActiveGrid(newGrid);
|
||||
|
@ -696,7 +702,16 @@ namespace MWWorld
|
|||
ESM::ExteriorCellLocation(it->mData.mX, it->mData.mY, ESM::Cell::sDefaultWorldspaceId));
|
||||
const osg::Vec3f position
|
||||
= osg::Vec3f(it->mData.mX + 0.5f, it->mData.mY + 0.5f, 0) * Constants::CellSizeInUnits;
|
||||
mNavigator.updateBounds(ESM::Cell::sDefaultWorldspaceId, position, navigatorUpdateGuard.get());
|
||||
const osg::Vec2i cellPosition(it->mData.mX, it->mData.mY);
|
||||
|
||||
const DetourNavigator::CellGridBounds cellGridBounds{
|
||||
.mCenter = osg::Vec2i(it->mData.mX, it->mData.mY),
|
||||
.mHalfSize = Constants::CellGridRadius,
|
||||
};
|
||||
|
||||
mNavigator.updateBounds(
|
||||
ESM::Cell::sDefaultWorldspaceId, cellGridBounds, position, navigatorUpdateGuard.get());
|
||||
|
||||
loadCell(cell, nullptr, false, position, navigatorUpdateGuard.get());
|
||||
|
||||
mNavigator.update(position, navigatorUpdateGuard.get());
|
||||
|
@ -752,7 +767,8 @@ namespace MWWorld
|
|||
CellStore& cell = mWorld.getWorldModel().getInterior(it->mName);
|
||||
ESM::Position position;
|
||||
mWorld.findInteriorPosition(it->mName, position);
|
||||
mNavigator.updateBounds(cell.getCell()->getWorldSpace(), position.asVec3(), navigatorUpdateGuard.get());
|
||||
mNavigator.updateBounds(
|
||||
cell.getCell()->getWorldSpace(), std::nullopt, position.asVec3(), navigatorUpdateGuard.get());
|
||||
loadCell(cell, nullptr, false, position.asVec3(), navigatorUpdateGuard.get());
|
||||
|
||||
mNavigator.update(position.asVec3(), navigatorUpdateGuard.get());
|
||||
|
@ -902,7 +918,8 @@ namespace MWWorld
|
|||
|
||||
loadingListener->setProgressRange(cell.count());
|
||||
|
||||
mNavigator.updateBounds(cell.getCell()->getWorldSpace(), position.asVec3(), navigatorUpdateGuard.get());
|
||||
mNavigator.updateBounds(
|
||||
cell.getCell()->getWorldSpace(), std::nullopt, position.asVec3(), navigatorUpdateGuard.get());
|
||||
|
||||
// Load cell.
|
||||
mPagedRefs.clear();
|
||||
|
|
|
@ -859,6 +859,17 @@ namespace
|
|||
EXPECT_EQ(mNavigator->getNavMesh(mAgentBounds)->lockConst()->getVersion(), version);
|
||||
}
|
||||
|
||||
std::pair<TilePosition, TilePosition> getMinMax(const RecastMeshTiles& tiles)
|
||||
{
|
||||
const auto lessByX = [](const auto& l, const auto& r) { return l.first.x() < r.first.x(); };
|
||||
const auto lessByY = [](const auto& l, const auto& r) { return l.first.y() < r.first.y(); };
|
||||
|
||||
const auto [minX, maxX] = std::ranges::minmax_element(tiles, lessByX);
|
||||
const auto [minY, maxY] = std::ranges::minmax_element(tiles, lessByY);
|
||||
|
||||
return { TilePosition(minX->first.x(), minY->first.y()), TilePosition(maxX->first.x(), maxY->first.y()) };
|
||||
}
|
||||
|
||||
TEST_F(DetourNavigatorNavigatorTest, update_for_very_big_object_should_be_limited)
|
||||
{
|
||||
const float size = static_cast<float>((1 << 22) - 1);
|
||||
|
@ -867,8 +878,10 @@ namespace
|
|||
.mPosition = ESM::Position{ .pos = { 0, 0, 0 }, .rot{ 0, 0, 0 } },
|
||||
.mScale = 1.0f,
|
||||
};
|
||||
const std::optional<CellGridBounds> cellGridBounds = std::nullopt;
|
||||
const osg::Vec3f playerPosition(32, 1024, 0);
|
||||
|
||||
mNavigator->updateBounds(mWorldspace, mPlayerPosition, nullptr);
|
||||
mNavigator->updateBounds(mWorldspace, cellGridBounds, playerPosition, nullptr);
|
||||
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
|
||||
mNavigator->addObject(ObjectId(&bigBox.shape()), ObjectShapes(bigBox.instance(), objectTransform),
|
||||
btTransform::getIdentity(), nullptr);
|
||||
|
@ -878,7 +891,8 @@ namespace
|
|||
std::mutex mutex;
|
||||
|
||||
std::thread thread([&] {
|
||||
mNavigator->update(mPlayerPosition, nullptr);
|
||||
auto guard = mNavigator->makeUpdateGuard();
|
||||
mNavigator->update(playerPosition, guard.get());
|
||||
std::lock_guard lock(mutex);
|
||||
updated = true;
|
||||
updateFinished.notify_all();
|
||||
|
@ -886,7 +900,7 @@ namespace
|
|||
|
||||
{
|
||||
std::unique_lock lock(mutex);
|
||||
updateFinished.wait_for(lock, std::chrono::seconds(3), [&] { return updated; });
|
||||
updateFinished.wait_for(lock, std::chrono::seconds(10), [&] { return updated; });
|
||||
ASSERT_TRUE(updated);
|
||||
}
|
||||
|
||||
|
@ -894,14 +908,69 @@ namespace
|
|||
|
||||
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||
|
||||
EXPECT_EQ(mNavigator->getRecastMeshTiles().size(), 509);
|
||||
const auto recastMeshTiles = mNavigator->getRecastMeshTiles();
|
||||
ASSERT_EQ(recastMeshTiles.size(), 1033);
|
||||
EXPECT_EQ(getMinMax(recastMeshTiles), std::pair(TilePosition(-18, -17), TilePosition(18, 19)));
|
||||
|
||||
const auto navMesh = mNavigator->getNavMesh(mAgentBounds);
|
||||
ASSERT_NE(navMesh, nullptr);
|
||||
|
||||
std::size_t usedNavMeshTiles = 0;
|
||||
navMesh->lockConst()->forEachUsedTile([&](const auto&...) { ++usedNavMeshTiles; });
|
||||
EXPECT_EQ(usedNavMeshTiles, 509);
|
||||
EXPECT_EQ(usedNavMeshTiles, 1024);
|
||||
}
|
||||
|
||||
TEST_F(DetourNavigatorNavigatorTest, update_should_be_limited_by_cell_grid_bounds)
|
||||
{
|
||||
const float size = static_cast<float>((1 << 22) - 1);
|
||||
CollisionShapeInstance bigBox(std::make_unique<btBoxShape>(btVector3(size, size, 1)));
|
||||
const ObjectTransform objectTransform{
|
||||
.mPosition = ESM::Position{ .pos = { 0, 0, 0 }, .rot{ 0, 0, 0 } },
|
||||
.mScale = 1.0f,
|
||||
};
|
||||
const CellGridBounds cellGridBounds{
|
||||
.mCenter = osg::Vec2i(0, 0),
|
||||
.mHalfSize = 1,
|
||||
};
|
||||
const osg::Vec3f playerPosition(32, 1024, 0);
|
||||
|
||||
mNavigator->updateBounds(mWorldspace, cellGridBounds, playerPosition, nullptr);
|
||||
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
|
||||
mNavigator->addObject(ObjectId(&bigBox.shape()), ObjectShapes(bigBox.instance(), objectTransform),
|
||||
btTransform::getIdentity(), nullptr);
|
||||
|
||||
bool updated = false;
|
||||
std::condition_variable updateFinished;
|
||||
std::mutex mutex;
|
||||
|
||||
std::thread thread([&] {
|
||||
auto guard = mNavigator->makeUpdateGuard();
|
||||
mNavigator->update(playerPosition, guard.get());
|
||||
std::lock_guard lock(mutex);
|
||||
updated = true;
|
||||
updateFinished.notify_all();
|
||||
});
|
||||
|
||||
{
|
||||
std::unique_lock lock(mutex);
|
||||
updateFinished.wait_for(lock, std::chrono::seconds(10), [&] { return updated; });
|
||||
ASSERT_TRUE(updated);
|
||||
}
|
||||
|
||||
thread.join();
|
||||
|
||||
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||
|
||||
const auto recastMeshTiles = mNavigator->getRecastMeshTiles();
|
||||
ASSERT_EQ(recastMeshTiles.size(), 854);
|
||||
EXPECT_EQ(getMinMax(recastMeshTiles), std::pair(TilePosition(-12, -12), TilePosition(18, 19)));
|
||||
|
||||
const auto navMesh = mNavigator->getNavMesh(mAgentBounds);
|
||||
ASSERT_NE(navMesh, nullptr);
|
||||
|
||||
std::size_t usedNavMeshTiles = 0;
|
||||
navMesh->lockConst()->forEachUsedTile([&](const auto&...) { ++usedNavMeshTiles; });
|
||||
EXPECT_EQ(usedNavMeshTiles, 854);
|
||||
}
|
||||
|
||||
struct DetourNavigatorNavigatorNotSupportedAgentBoundsTest : TestWithParam<AgentBounds>
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace DetourNavigator
|
|||
result.mDetour.mMaxPolygonPathSize = 1024;
|
||||
result.mDetour.mMaxSmoothPathSize = 1024;
|
||||
result.mDetour.mMaxPolys = 4096;
|
||||
result.mMaxTilesNumber = 512;
|
||||
result.mMaxTilesNumber = 1024;
|
||||
result.mMinUpdateInterval = std::chrono::milliseconds(50);
|
||||
result.mWriteToNavMeshDb = true;
|
||||
return result;
|
||||
|
|
|
@ -173,7 +173,7 @@ namespace
|
|||
TileCachedRecastMeshManager manager(mSettings);
|
||||
const TilesPositionsRange range{
|
||||
.mBegin = TilePosition(-1, -1),
|
||||
.mEnd = TilePosition(1, 1),
|
||||
.mEnd = TilePosition(2, 2),
|
||||
};
|
||||
manager.setRange(range, nullptr);
|
||||
manager.setWorldspace(mWorldspace, nullptr);
|
||||
|
|
15
components/detournavigator/cellgridbounds.hpp
Normal file
15
components/detournavigator/cellgridbounds.hpp
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_CELLGRIDBOUNDS_H
|
||||
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_CELLGRIDBOUNDS_H
|
||||
|
||||
#include <osg/Vec2i>
|
||||
|
||||
namespace DetourNavigator
|
||||
{
|
||||
struct CellGridBounds
|
||||
{
|
||||
osg::Vec2i mCenter;
|
||||
int mHalfSize;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -3,7 +3,9 @@
|
|||
|
||||
#include <cassert>
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
|
||||
#include "cellgridbounds.hpp"
|
||||
#include "heightfieldshape.hpp"
|
||||
#include "objectid.hpp"
|
||||
#include "objecttransform.hpp"
|
||||
|
@ -89,7 +91,8 @@ namespace DetourNavigator
|
|||
virtual void removeAgent(const AgentBounds& agentBounds) = 0;
|
||||
|
||||
// Updates bounds for recast mesh and navmesh tiles, removes tiles outside the range.
|
||||
virtual void updateBounds(ESM::RefId worldspace, const osg::Vec3f& playerPosition, const UpdateGuard* guard)
|
||||
virtual void updateBounds(ESM::RefId worldspace, const std::optional<CellGridBounds>& cellGridBounds,
|
||||
const osg::Vec3f& playerPosition, const UpdateGuard* guard)
|
||||
= 0;
|
||||
|
||||
/**
|
||||
|
|
|
@ -33,9 +33,10 @@ namespace DetourNavigator
|
|||
--it->second;
|
||||
}
|
||||
|
||||
void NavigatorImpl::updateBounds(ESM::RefId worldspace, const osg::Vec3f& playerPosition, const UpdateGuard* guard)
|
||||
void NavigatorImpl::updateBounds(ESM::RefId worldspace, const std::optional<CellGridBounds>& cellGridBounds,
|
||||
const osg::Vec3f& playerPosition, const UpdateGuard* guard)
|
||||
{
|
||||
mNavMeshManager.updateBounds(worldspace, playerPosition, guard);
|
||||
mNavMeshManager.updateBounds(worldspace, cellGridBounds, playerPosition, guard);
|
||||
}
|
||||
|
||||
void NavigatorImpl::addObject(
|
||||
|
|
|
@ -27,7 +27,8 @@ namespace DetourNavigator
|
|||
|
||||
void removeAgent(const AgentBounds& agentBounds) override;
|
||||
|
||||
void updateBounds(ESM::RefId worldspace, const osg::Vec3f& playerPosition, const UpdateGuard* guard) override;
|
||||
void updateBounds(ESM::RefId worldspace, const std::optional<CellGridBounds>& cellGridBounds,
|
||||
const osg::Vec3f& playerPosition, const UpdateGuard* guard) override;
|
||||
|
||||
void addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform,
|
||||
const UpdateGuard* guard) override;
|
||||
|
|
|
@ -24,8 +24,8 @@ namespace DetourNavigator
|
|||
|
||||
void removeAgent(const AgentBounds& /*agentBounds*/) override {}
|
||||
|
||||
void updateBounds(
|
||||
ESM::RefId /*worldspace*/, const osg::Vec3f& /*playerPosition*/, const UpdateGuard* /*guard*/) override
|
||||
void updateBounds(ESM::RefId /*worldspace*/, const std::optional<CellGridBounds>& /*cellGridBounds*/,
|
||||
const osg::Vec3f& /*playerPosition*/, const UpdateGuard* /*guard*/) override
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "navmeshmanager.hpp"
|
||||
|
||||
#include "debug.hpp"
|
||||
#include "gettilespositions.hpp"
|
||||
#include "makenavmesh.hpp"
|
||||
|
@ -8,6 +9,7 @@
|
|||
#include "waitconditiontype.hpp"
|
||||
|
||||
#include <components/debug/debuglog.hpp>
|
||||
#include <components/esm/util.hpp>
|
||||
|
||||
#include <osg/io_utils>
|
||||
|
||||
|
@ -35,15 +37,46 @@ namespace DetourNavigator
|
|||
{
|
||||
namespace
|
||||
{
|
||||
TilesPositionsRange makeRange(const TilePosition& center, int maxTiles)
|
||||
int getMaxRadius(int maxTiles)
|
||||
{
|
||||
return static_cast<int>(std::ceil(std::sqrt(static_cast<float>(maxTiles) / osg::PIf) + 1));
|
||||
}
|
||||
|
||||
TilesPositionsRange makeRange(const TilePosition& center, int radius)
|
||||
{
|
||||
const int radius = static_cast<int>(std::ceil(std::sqrt(static_cast<float>(maxTiles) / osg::PIf) + 1));
|
||||
return TilesPositionsRange{
|
||||
.mBegin = center - TilePosition(radius, radius),
|
||||
.mEnd = center + TilePosition(radius + 1, radius + 1),
|
||||
};
|
||||
}
|
||||
|
||||
osg::Vec2f getMinCellGridPosition(const osg::Vec2i& center, int offset, float cellSize)
|
||||
{
|
||||
const osg::Vec2i cell = center + osg::Vec2i(offset, offset);
|
||||
return osg::Vec2f(static_cast<float>(cell.x()) * cellSize, static_cast<float>(cell.y()) * cellSize);
|
||||
}
|
||||
|
||||
TilesPositionsRange makeCellGridRange(
|
||||
const RecastSettings& settings, ESM::RefId worldspace, const CellGridBounds& bounds)
|
||||
{
|
||||
const float floatCellSize = static_cast<float>(ESM::getCellSize(worldspace));
|
||||
const osg::Vec2f min = getMinCellGridPosition(bounds.mCenter, -bounds.mHalfSize, floatCellSize);
|
||||
const osg::Vec2f max = getMinCellGridPosition(bounds.mCenter, bounds.mHalfSize + 1, floatCellSize);
|
||||
return TilesPositionsRange{
|
||||
.mBegin = getTilePosition(settings, toNavMeshCoordinates(settings, min)),
|
||||
.mEnd = getTilePosition(settings, toNavMeshCoordinates(settings, max)),
|
||||
};
|
||||
}
|
||||
|
||||
TilesPositionsRange makeRange(const Settings& settings, ESM::RefId worldspace,
|
||||
const std::optional<CellGridBounds>& bounds, int radius, const TilePosition& center)
|
||||
{
|
||||
TilesPositionsRange result = makeRange(center, radius);
|
||||
if (bounds.has_value())
|
||||
result = getIntersection(result, makeCellGridRange(settings.mRecast, worldspace, *bounds));
|
||||
return result;
|
||||
}
|
||||
|
||||
TilePosition toNavMeshTilePosition(const RecastSettings& settings, const osg::Vec3f& position)
|
||||
{
|
||||
return getTilePosition(settings, toNavMeshCoordinates(settings, position));
|
||||
|
@ -52,13 +85,15 @@ namespace DetourNavigator
|
|||
|
||||
NavMeshManager::NavMeshManager(const Settings& settings, std::unique_ptr<NavMeshDb>&& db)
|
||||
: mSettings(settings)
|
||||
, mMaxRadius(getMaxRadius(settings.mMaxTilesNumber))
|
||||
, mRecastMeshManager(settings.mRecast)
|
||||
, mOffMeshConnectionsManager(settings.mRecast)
|
||||
, mAsyncNavMeshUpdater(settings, mRecastMeshManager, mOffMeshConnectionsManager, std::move(db))
|
||||
{
|
||||
}
|
||||
|
||||
void NavMeshManager::updateBounds(ESM::RefId worldspace, const osg::Vec3f& playerPosition, const UpdateGuard* guard)
|
||||
void NavMeshManager::updateBounds(ESM::RefId worldspace, const std::optional<CellGridBounds>& cellGridBounds,
|
||||
const osg::Vec3f& playerPosition, const UpdateGuard* guard)
|
||||
{
|
||||
if (worldspace != mWorldspace)
|
||||
{
|
||||
|
@ -69,8 +104,9 @@ namespace DetourNavigator
|
|||
}
|
||||
|
||||
const TilePosition playerTile = toNavMeshTilePosition(mSettings.mRecast, playerPosition);
|
||||
const TilesPositionsRange range = makeRange(playerTile, mSettings.mMaxTilesNumber);
|
||||
mRecastMeshManager.setRange(range, guard);
|
||||
|
||||
mRecastMeshManager.setRange(makeRange(mSettings, worldspace, cellGridBounds, mMaxRadius, playerTile), guard);
|
||||
mCellGridBounds = cellGridBounds;
|
||||
}
|
||||
|
||||
bool NavMeshManager::addObject(const ObjectId id, const CollisionShape& shape, const btTransform& transform,
|
||||
|
@ -162,7 +198,7 @@ namespace DetourNavigator
|
|||
return;
|
||||
mLastRecastMeshManagerRevision = mRecastMeshManager.getRevision();
|
||||
mPlayerTile = playerTile;
|
||||
mRecastMeshManager.setRange(makeRange(playerTile, mSettings.mMaxTilesNumber), guard);
|
||||
mRecastMeshManager.setRange(makeRange(mSettings, mWorldspace, mCellGridBounds, mMaxRadius, playerTile), guard);
|
||||
const auto changedTiles = mRecastMeshManager.takeChangedTiles(guard);
|
||||
const TilesPositionsRange range = mRecastMeshManager.getLimitedObjectsRange();
|
||||
for (const auto& [agentBounds, cached] : mCache)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "agentbounds.hpp"
|
||||
#include "asyncnavmeshupdater.hpp"
|
||||
#include "cellgridbounds.hpp"
|
||||
#include "heightfieldshape.hpp"
|
||||
#include "offmeshconnectionsmanager.hpp"
|
||||
#include "recastmeshtiles.hpp"
|
||||
|
@ -24,7 +25,8 @@ namespace DetourNavigator
|
|||
|
||||
ScopedUpdateGuard makeUpdateGuard() { return mRecastMeshManager.makeUpdateGuard(); }
|
||||
|
||||
void updateBounds(ESM::RefId worldspace, const osg::Vec3f& playerPosition, const UpdateGuard* guard);
|
||||
void updateBounds(ESM::RefId worldspace, const std::optional<CellGridBounds>& cellGridBounds,
|
||||
const osg::Vec3f& playerPosition, const UpdateGuard* guard);
|
||||
|
||||
bool addObject(const ObjectId id, const CollisionShape& shape, const btTransform& transform,
|
||||
const AreaType areaType, const UpdateGuard* guard);
|
||||
|
@ -65,7 +67,9 @@ namespace DetourNavigator
|
|||
|
||||
private:
|
||||
const Settings& mSettings;
|
||||
const int mMaxRadius;
|
||||
ESM::RefId mWorldspace;
|
||||
std::optional<CellGridBounds> mCellGridBounds;
|
||||
TileCachedRecastMeshManager mRecastMeshManager;
|
||||
OffMeshConnectionsManager mOffMeshConnectionsManager;
|
||||
AsyncNavMeshUpdater mAsyncNavMeshUpdater;
|
||||
|
|
|
@ -107,11 +107,10 @@ namespace DetourNavigator
|
|||
});
|
||||
}
|
||||
|
||||
const MaybeLockGuard lock(mMutex, guard);
|
||||
|
||||
if (changed)
|
||||
{
|
||||
const MaybeLockGuard lock(mMutex, guard);
|
||||
++mRevision;
|
||||
}
|
||||
|
||||
mRange = range;
|
||||
}
|
||||
|
@ -357,6 +356,8 @@ namespace DetourNavigator
|
|||
const std::lock_guard lock(mMutex);
|
||||
if (mWorldspace != worldspace)
|
||||
return nullptr;
|
||||
if (!isInTilesPositionsRange(mRange, tilePosition))
|
||||
return nullptr;
|
||||
const auto it = mCache.find(tilePosition);
|
||||
if (it != mCache.end() && it->second.mRecastMesh->getVersion() == it->second.mVersion)
|
||||
return it->second.mRecastMesh;
|
||||
|
@ -380,6 +381,8 @@ namespace DetourNavigator
|
|||
const std::lock_guard lock(mMutex);
|
||||
if (mWorldspace != worldspace)
|
||||
return nullptr;
|
||||
if (!isInTilesPositionsRange(mRange, tilePosition))
|
||||
return nullptr;
|
||||
const auto it = mCache.find(tilePosition);
|
||||
if (it == mCache.end())
|
||||
return nullptr;
|
||||
|
|
Loading…
Reference in a new issue