mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-05-08 03:28:15 +03:00
Explicitly bind TileCachedRecastMeshManager with mutex
This commit is contained in:
parent
3caeda7299
commit
0b644a897e
2 changed files with 54 additions and 49 deletions
|
@ -43,7 +43,7 @@ namespace DetourNavigator
|
||||||
|
|
||||||
if (mBounds != infiniteTileBounds)
|
if (mBounds != infiniteTileBounds)
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const auto locked = mWorldspaceTiles.lock();
|
||||||
for (auto& object : mObjects)
|
for (auto& object : mObjects)
|
||||||
{
|
{
|
||||||
const ObjectId id = object.first;
|
const ObjectId id = object.first;
|
||||||
|
@ -58,7 +58,7 @@ namespace DetourNavigator
|
||||||
if (it == data.mTiles.end())
|
if (it == data.mTiles.end())
|
||||||
return;
|
return;
|
||||||
data.mTiles.erase(it);
|
data.mTiles.erase(it);
|
||||||
if (removeTile(id, position, mTiles))
|
if (removeTile(id, position, locked->mTiles))
|
||||||
changedTiles.emplace_back(position, ChangeType::remove);
|
changedTiles.emplace_back(position, ChangeType::remove);
|
||||||
};
|
};
|
||||||
getTilesPositions(getIntersection(mRange, objectRange), onOldTilePosition);
|
getTilesPositions(getIntersection(mRange, objectRange), onOldTilePosition);
|
||||||
|
@ -67,7 +67,7 @@ namespace DetourNavigator
|
||||||
{
|
{
|
||||||
if (data.mTiles.find(position) != data.mTiles.end())
|
if (data.mTiles.find(position) != data.mTiles.end())
|
||||||
return;
|
return;
|
||||||
if (addTile(id, data.mShape, data.mTransform, data.mAreaType, position, mTiles))
|
if (addTile(id, data.mShape, data.mTransform, data.mAreaType, position, locked->mTiles))
|
||||||
{
|
{
|
||||||
data.mTiles.insert(position);
|
data.mTiles.insert(position);
|
||||||
changedTiles.emplace_back(position, ChangeType::add);
|
changedTiles.emplace_back(position, ChangeType::add);
|
||||||
|
@ -91,17 +91,16 @@ namespace DetourNavigator
|
||||||
|
|
||||||
std::string TileCachedRecastMeshManager::getWorldspace() const
|
std::string TileCachedRecastMeshManager::getWorldspace() const
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
return mWorldspaceTiles.lockConst()->mWorldspace;
|
||||||
return mWorldspace;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileCachedRecastMeshManager::setWorldspace(std::string_view worldspace)
|
void TileCachedRecastMeshManager::setWorldspace(std::string_view worldspace)
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const auto locked = mWorldspaceTiles.lock();
|
||||||
if (mWorldspace == worldspace)
|
if (locked->mWorldspace == worldspace)
|
||||||
return;
|
return;
|
||||||
mTiles.clear();
|
locked->mTiles.clear();
|
||||||
mWorldspace = worldspace;
|
locked->mWorldspace = worldspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<RemovedRecastMeshObject> TileCachedRecastMeshManager::removeObject(const ObjectId id)
|
std::optional<RemovedRecastMeshObject> TileCachedRecastMeshManager::removeObject(const ObjectId id)
|
||||||
|
@ -111,10 +110,10 @@ namespace DetourNavigator
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
std::optional<RemovedRecastMeshObject> result;
|
std::optional<RemovedRecastMeshObject> result;
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const auto locked = mWorldspaceTiles.lock();
|
||||||
for (const auto& tilePosition : object->second.mTiles)
|
for (const auto& tilePosition : object->second.mTiles)
|
||||||
{
|
{
|
||||||
const auto removed = removeTile(id, tilePosition, mTiles);
|
const auto removed = removeTile(id, tilePosition, locked->mTiles);
|
||||||
if (removed && !result)
|
if (removed && !result)
|
||||||
result = removed;
|
result = removed;
|
||||||
}
|
}
|
||||||
|
@ -138,8 +137,8 @@ namespace DetourNavigator
|
||||||
|
|
||||||
if (cellSize == std::numeric_limits<int>::max())
|
if (cellSize == std::numeric_limits<int>::max())
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const auto locked = mWorldspaceTiles.lock();
|
||||||
for (auto& tile : mTiles)
|
for (auto& tile : locked->mTiles)
|
||||||
{
|
{
|
||||||
if (tile.second->addWater(cellPosition, cellSize, level))
|
if (tile.second->addWater(cellPosition, cellSize, level))
|
||||||
{
|
{
|
||||||
|
@ -154,12 +153,12 @@ namespace DetourNavigator
|
||||||
getTilesPositions(makeTilesPositionsRange(cellSize, shift, mSettings),
|
getTilesPositions(makeTilesPositionsRange(cellSize, shift, mSettings),
|
||||||
[&] (const TilePosition& tilePosition)
|
[&] (const TilePosition& tilePosition)
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const auto locked = mWorldspaceTiles.lock();
|
||||||
auto tile = mTiles.find(tilePosition);
|
auto tile = locked->mTiles.find(tilePosition);
|
||||||
if (tile == mTiles.end())
|
if (tile == locked->mTiles.end())
|
||||||
{
|
{
|
||||||
const TileBounds tileBounds = makeRealTileBoundsWithBorder(mSettings, tilePosition);
|
const TileBounds tileBounds = makeRealTileBoundsWithBorder(mSettings, tilePosition);
|
||||||
tile = mTiles.emplace_hint(tile, tilePosition,
|
tile = locked->mTiles.emplace_hint(tile, tilePosition,
|
||||||
std::make_shared<CachedRecastMeshManager>(tileBounds, mTilesGeneration));
|
std::make_shared<CachedRecastMeshManager>(tileBounds, mTilesGeneration));
|
||||||
}
|
}
|
||||||
if (tile->second->addWater(cellPosition, cellSize, level))
|
if (tile->second->addWater(cellPosition, cellSize, level))
|
||||||
|
@ -184,14 +183,14 @@ namespace DetourNavigator
|
||||||
std::optional<Water> result;
|
std::optional<Water> result;
|
||||||
for (const auto& tilePosition : object->second)
|
for (const auto& tilePosition : object->second)
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const auto locked = mWorldspaceTiles.lock();
|
||||||
const auto tile = mTiles.find(tilePosition);
|
const auto tile = locked->mTiles.find(tilePosition);
|
||||||
if (tile == mTiles.end())
|
if (tile == locked->mTiles.end())
|
||||||
continue;
|
continue;
|
||||||
const auto tileResult = tile->second->removeWater(cellPosition);
|
const auto tileResult = tile->second->removeWater(cellPosition);
|
||||||
if (tile->second->isEmpty())
|
if (tile->second->isEmpty())
|
||||||
{
|
{
|
||||||
mTiles.erase(tile);
|
locked->mTiles.erase(tile);
|
||||||
++mTilesGeneration;
|
++mTilesGeneration;
|
||||||
}
|
}
|
||||||
if (tileResult && !result)
|
if (tileResult && !result)
|
||||||
|
@ -219,12 +218,12 @@ namespace DetourNavigator
|
||||||
getTilesPositions(makeTilesPositionsRange(cellSize, shift, mSettings),
|
getTilesPositions(makeTilesPositionsRange(cellSize, shift, mSettings),
|
||||||
[&] (const TilePosition& tilePosition)
|
[&] (const TilePosition& tilePosition)
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const auto locked = mWorldspaceTiles.lock();
|
||||||
auto tile = mTiles.find(tilePosition);
|
auto tile = locked->mTiles.find(tilePosition);
|
||||||
if (tile == mTiles.end())
|
if (tile == locked->mTiles.end())
|
||||||
{
|
{
|
||||||
const TileBounds tileBounds = makeRealTileBoundsWithBorder(mSettings, tilePosition);
|
const TileBounds tileBounds = makeRealTileBoundsWithBorder(mSettings, tilePosition);
|
||||||
tile = mTiles.emplace_hint(tile, tilePosition,
|
tile = locked->mTiles.emplace_hint(tile, tilePosition,
|
||||||
std::make_shared<CachedRecastMeshManager>(tileBounds, mTilesGeneration));
|
std::make_shared<CachedRecastMeshManager>(tileBounds, mTilesGeneration));
|
||||||
}
|
}
|
||||||
if (tile->second->addHeightfield(cellPosition, cellSize, shape))
|
if (tile->second->addHeightfield(cellPosition, cellSize, shape))
|
||||||
|
@ -248,14 +247,14 @@ namespace DetourNavigator
|
||||||
std::optional<SizedHeightfieldShape> result;
|
std::optional<SizedHeightfieldShape> result;
|
||||||
for (const auto& tilePosition : object->second)
|
for (const auto& tilePosition : object->second)
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const auto locked = mWorldspaceTiles.lock();
|
||||||
const auto tile = mTiles.find(tilePosition);
|
const auto tile = locked->mTiles.find(tilePosition);
|
||||||
if (tile == mTiles.end())
|
if (tile == locked->mTiles.end())
|
||||||
continue;
|
continue;
|
||||||
const auto tileResult = tile->second->removeHeightfield(cellPosition);
|
const auto tileResult = tile->second->removeHeightfield(cellPosition);
|
||||||
if (tile->second->isEmpty())
|
if (tile->second->isEmpty())
|
||||||
{
|
{
|
||||||
mTiles.erase(tile);
|
locked->mTiles.erase(tile);
|
||||||
++mTilesGeneration;
|
++mTilesGeneration;
|
||||||
}
|
}
|
||||||
if (tileResult && !result)
|
if (tileResult && !result)
|
||||||
|
@ -295,9 +294,9 @@ namespace DetourNavigator
|
||||||
|
|
||||||
void TileCachedRecastMeshManager::reportNavMeshChange(const TilePosition& tilePosition, Version recastMeshVersion, Version navMeshVersion) const
|
void TileCachedRecastMeshManager::reportNavMeshChange(const TilePosition& tilePosition, Version recastMeshVersion, Version navMeshVersion) const
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const auto locked = mWorldspaceTiles.lockConst();
|
||||||
const auto it = mTiles.find(tilePosition);
|
const auto it = locked->mTiles.find(tilePosition);
|
||||||
if (it == mTiles.end())
|
if (it == locked->mTiles.end())
|
||||||
return;
|
return;
|
||||||
it->second->reportNavMeshChange(recastMeshVersion, navMeshVersion);
|
it->second->reportNavMeshChange(recastMeshVersion, navMeshVersion);
|
||||||
}
|
}
|
||||||
|
@ -341,11 +340,11 @@ namespace DetourNavigator
|
||||||
std::shared_ptr<CachedRecastMeshManager> TileCachedRecastMeshManager::getManager(std::string_view worldspace,
|
std::shared_ptr<CachedRecastMeshManager> TileCachedRecastMeshManager::getManager(std::string_view worldspace,
|
||||||
const TilePosition& tilePosition) const
|
const TilePosition& tilePosition) const
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const auto locked = mWorldspaceTiles.lockConst();
|
||||||
if (mWorldspace != worldspace)
|
if (locked->mWorldspace != worldspace)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
const auto it = mTiles.find(tilePosition);
|
const auto it = locked->mTiles.find(tilePosition);
|
||||||
if (it == mTiles.end())
|
if (it == locked->mTiles.end())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
#include "heightfieldshape.hpp"
|
#include "heightfieldshape.hpp"
|
||||||
#include "changetype.hpp"
|
#include "changetype.hpp"
|
||||||
|
|
||||||
|
#include <components/misc/guarded.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
@ -42,11 +44,11 @@ namespace DetourNavigator
|
||||||
std::set<TilePosition> tilesPositions;
|
std::set<TilePosition> tilesPositions;
|
||||||
if (range.mBegin != range.mEnd)
|
if (range.mBegin != range.mEnd)
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const auto locked = mWorldspaceTiles.lock();
|
||||||
getTilesPositions(range,
|
getTilesPositions(range,
|
||||||
[&] (const TilePosition& tilePosition)
|
[&] (const TilePosition& tilePosition)
|
||||||
{
|
{
|
||||||
if (addTile(id, shape, transform, areaType, tilePosition, mTiles))
|
if (addTile(id, shape, transform, areaType, tilePosition, locked->mTiles))
|
||||||
tilesPositions.insert(tilePosition);
|
tilesPositions.insert(tilePosition);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -67,31 +69,31 @@ namespace DetourNavigator
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
std::set<TilePosition> newTiles;
|
std::set<TilePosition> newTiles;
|
||||||
{
|
{
|
||||||
|
const TilesPositionsRange objectRange = makeTilesPositionsRange(shape.getShape(), transform, mSettings);
|
||||||
|
const TilesPositionsRange range = getIntersection(mRange, objectRange);
|
||||||
|
const auto locked = mWorldspaceTiles.lock();
|
||||||
const auto onTilePosition = [&] (const TilePosition& tilePosition)
|
const auto onTilePosition = [&] (const TilePosition& tilePosition)
|
||||||
{
|
{
|
||||||
if (data.mTiles.find(tilePosition) != data.mTiles.end())
|
if (data.mTiles.find(tilePosition) != data.mTiles.end())
|
||||||
{
|
{
|
||||||
newTiles.insert(tilePosition);
|
newTiles.insert(tilePosition);
|
||||||
if (updateTile(id, transform, areaType, tilePosition, mTiles))
|
if (updateTile(id, transform, areaType, tilePosition, locked->mTiles))
|
||||||
{
|
{
|
||||||
onChangedTile(tilePosition, ChangeType::update);
|
onChangedTile(tilePosition, ChangeType::update);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (addTile(id, shape, transform, areaType, tilePosition, mTiles))
|
else if (addTile(id, shape, transform, areaType, tilePosition, locked->mTiles))
|
||||||
{
|
{
|
||||||
newTiles.insert(tilePosition);
|
newTiles.insert(tilePosition);
|
||||||
onChangedTile(tilePosition, ChangeType::add);
|
onChangedTile(tilePosition, ChangeType::add);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const TilesPositionsRange objectRange = makeTilesPositionsRange(shape.getShape(), transform, mSettings);
|
|
||||||
const TilesPositionsRange range = getIntersection(mRange, objectRange);
|
|
||||||
const std::lock_guard lock(mMutex);
|
|
||||||
getTilesPositions(range, onTilePosition);
|
getTilesPositions(range, onTilePosition);
|
||||||
for (const auto& tile : data.mTiles)
|
for (const auto& tile : data.mTiles)
|
||||||
{
|
{
|
||||||
if (newTiles.find(tile) == newTiles.end() && removeTile(id, tile, mTiles))
|
if (newTiles.find(tile) == newTiles.end() && removeTile(id, tile, locked->mTiles))
|
||||||
{
|
{
|
||||||
onChangedTile(tile, ChangeType::remove);
|
onChangedTile(tile, ChangeType::remove);
|
||||||
changed = true;
|
changed = true;
|
||||||
|
@ -125,8 +127,8 @@ namespace DetourNavigator
|
||||||
template <class Function>
|
template <class Function>
|
||||||
void forEachTile(Function&& function) const
|
void forEachTile(Function&& function) const
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const auto& locked = mWorldspaceTiles.lockConst();
|
||||||
for (auto& [tilePosition, recastMeshManager] : mTiles)
|
for (const auto& [tilePosition, recastMeshManager] : locked->mTiles)
|
||||||
function(tilePosition, *recastMeshManager);
|
function(tilePosition, *recastMeshManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,12 +147,16 @@ namespace DetourNavigator
|
||||||
std::set<TilePosition> mTiles;
|
std::set<TilePosition> mTiles;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct WorldspaceTiles
|
||||||
|
{
|
||||||
|
std::string mWorldspace;
|
||||||
|
TilesMap mTiles;
|
||||||
|
};
|
||||||
|
|
||||||
const RecastSettings& mSettings;
|
const RecastSettings& mSettings;
|
||||||
mutable std::mutex mMutex;
|
|
||||||
TileBounds mBounds;
|
TileBounds mBounds;
|
||||||
TilesPositionsRange mRange;
|
TilesPositionsRange mRange;
|
||||||
std::string mWorldspace;
|
Misc::ScopeGuarded<WorldspaceTiles> mWorldspaceTiles;
|
||||||
TilesMap mTiles;
|
|
||||||
std::unordered_map<ObjectId, ObjectData> mObjects;
|
std::unordered_map<ObjectId, ObjectData> mObjects;
|
||||||
std::map<osg::Vec2i, std::vector<TilePosition>> mWaterTilesPositions;
|
std::map<osg::Vec2i, std::vector<TilePosition>> mWaterTilesPositions;
|
||||||
std::map<osg::Vec2i, std::vector<TilePosition>> mHeightfieldTilesPositions;
|
std::map<osg::Vec2i, std::vector<TilePosition>> mHeightfieldTilesPositions;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue