mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-08 09:37:53 +00:00
3e67f5ffa5
To avoid triggering NavMesh update when RecastMesh change should not change NavMesh. Based on the following assumption: Given a set of transformations and a bounding shape for all these tranformations, a new object transformation that does not change this bounding shape also should not change navmesh if for all of this object transformations resulting navmesh tiles are equivalent The idea is to report back to RecastMeshManager all changes of NavMesh if there are any assiciated with RecastMesh version. So we know the last time when RecastMesh change resulted into the NavMesh change. When later report shows that there was no NavMesh change for a new RecastMesh version we can assume that any object transformation within the same bounding box should not change NavMesh.
115 lines
4.4 KiB
C++
115 lines
4.4 KiB
C++
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_TILECACHEDRECASTMESHMANAGER_H
|
|
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_TILECACHEDRECASTMESHMANAGER_H
|
|
|
|
#include "cachedrecastmeshmanager.hpp"
|
|
#include "tileposition.hpp"
|
|
#include "settingsutils.hpp"
|
|
#include "gettilespositions.hpp"
|
|
#include "version.hpp"
|
|
|
|
#include <components/misc/guarded.hpp>
|
|
|
|
#include <map>
|
|
#include <mutex>
|
|
#include <set>
|
|
|
|
namespace DetourNavigator
|
|
{
|
|
class TileCachedRecastMeshManager
|
|
{
|
|
public:
|
|
TileCachedRecastMeshManager(const Settings& settings);
|
|
|
|
bool addObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform,
|
|
const AreaType areaType);
|
|
|
|
template <class OnChangedTile>
|
|
bool updateObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform,
|
|
const AreaType areaType, OnChangedTile&& onChangedTile)
|
|
{
|
|
const auto object = mObjectsTilesPositions.find(id);
|
|
if (object == mObjectsTilesPositions.end())
|
|
return false;
|
|
auto& currentTiles = object->second;
|
|
const auto border = getBorderSize(mSettings);
|
|
bool changed = false;
|
|
std::set<TilePosition> newTiles;
|
|
{
|
|
auto tiles = mTiles.lock();
|
|
const auto onTilePosition = [&] (const TilePosition& tilePosition)
|
|
{
|
|
if (currentTiles.count(tilePosition))
|
|
{
|
|
newTiles.insert(tilePosition);
|
|
if (updateTile(id, transform, areaType, tilePosition, tiles.get()))
|
|
{
|
|
onChangedTile(tilePosition);
|
|
changed = true;
|
|
}
|
|
}
|
|
else if (addTile(id, shape, transform, areaType, tilePosition, border, tiles.get()))
|
|
{
|
|
newTiles.insert(tilePosition);
|
|
onChangedTile(tilePosition);
|
|
changed = true;
|
|
}
|
|
};
|
|
getTilesPositions(shape, transform, mSettings, onTilePosition);
|
|
for (const auto& tile : currentTiles)
|
|
{
|
|
if (!newTiles.count(tile) && removeTile(id, tile, tiles.get()))
|
|
{
|
|
onChangedTile(tile);
|
|
changed = true;
|
|
}
|
|
}
|
|
}
|
|
std::swap(currentTiles, newTiles);
|
|
if (changed)
|
|
++mRevision;
|
|
return changed;
|
|
}
|
|
|
|
std::optional<RemovedRecastMeshObject> removeObject(const ObjectId id);
|
|
|
|
bool addWater(const osg::Vec2i& cellPosition, const int cellSize, const btTransform& transform);
|
|
|
|
std::optional<RecastMeshManager::Water> removeWater(const osg::Vec2i& cellPosition);
|
|
|
|
std::shared_ptr<RecastMesh> getMesh(const TilePosition& tilePosition);
|
|
|
|
bool hasTile(const TilePosition& tilePosition);
|
|
|
|
template <class Function>
|
|
void forEachTilePosition(Function&& function)
|
|
{
|
|
for (const auto& tile : *mTiles.lock())
|
|
function(tile.first);
|
|
}
|
|
|
|
std::size_t getRevision() const;
|
|
|
|
void reportNavMeshChange(const TilePosition& tilePosition, Version recastMeshVersion, Version navMeshVersion);
|
|
|
|
private:
|
|
const Settings& mSettings;
|
|
Misc::ScopeGuarded<std::map<TilePosition, CachedRecastMeshManager>> mTiles;
|
|
std::unordered_map<ObjectId, std::set<TilePosition>> mObjectsTilesPositions;
|
|
std::map<osg::Vec2i, std::vector<TilePosition>> mWaterTilesPositions;
|
|
std::size_t mRevision = 0;
|
|
std::size_t mTilesGeneration = 0;
|
|
|
|
bool addTile(const ObjectId id, const btCollisionShape& shape, const btTransform& transform,
|
|
const AreaType areaType, const TilePosition& tilePosition, float border,
|
|
std::map<TilePosition, CachedRecastMeshManager>& tiles);
|
|
|
|
bool updateTile(const ObjectId id, const btTransform& transform, const AreaType areaType,
|
|
const TilePosition& tilePosition, std::map<TilePosition, CachedRecastMeshManager>& tiles);
|
|
|
|
std::optional<RemovedRecastMeshObject> removeTile(const ObjectId id, const TilePosition& tilePosition,
|
|
std::map<TilePosition, CachedRecastMeshManager>& tiles);
|
|
};
|
|
}
|
|
|
|
#endif
|