1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-04-01 23:06:41 +00:00

Cull navmesh objects by scene bounds

If object is too big iteration over all tiles covering it can take too much
time. Limit bounds to a square around a player position to cover only tiles
that will be present in navmesh based on max tiles number option.
This commit is contained in:
elsid 2022-01-23 14:47:20 +01:00
parent a9ae263acd
commit b0ef20c303
No known key found for this signature in database
GPG key ID: B845CB9FEE18AB40
8 changed files with 61 additions and 6 deletions

View file

@ -822,6 +822,8 @@ namespace MWWorld
loadingListener->setProgressRange(cell->count()); loadingListener->setProgressRange(cell->count());
mNavigator.updatePlayerPosition(position.asVec3());
// Load cell. // Load cell.
mPagedRefs.clear(); mPagedRefs.clear();
loadCell(cell, loadingListener, changeEvent); loadCell(cell, loadingListener, changeEvent);
@ -855,6 +857,8 @@ namespace MWWorld
if (changeEvent) if (changeEvent)
MWBase::Environment::get().getWindowManager()->fadeScreenOut(0.5); MWBase::Environment::get().getWindowManager()->fadeScreenOut(0.5);
mNavigator.updatePlayerPosition(position.asVec3());
changeCellGrid(position.asVec3(), x, y, changeEvent); changeCellGrid(position.asVec3(), x, y, changeEvent);
CellStore* current = MWBase::Environment::get().getWorld()->getExterior(x, y); CellStore* current = MWBase::Environment::get().getWorld()->getExterior(x, y);

View file

@ -90,6 +90,10 @@ namespace
const btBoxShape boxShape(btVector3(20, 20, 100)); const btBoxShape boxShape(btVector3(20, 20, 100));
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(getTileSize(mSettings) / mSettings.mRecastScaleFactor, 0, 0)); const btTransform transform(btMatrix3x3::getIdentity(), btVector3(getTileSize(mSettings) / mSettings.mRecastScaleFactor, 0, 0));
const CollisionShape shape(mInstance, boxShape, mObjectTransform); const CollisionShape shape(mInstance, boxShape, mObjectTransform);
TileBounds bounds;
bounds.mMin = osg::Vec2f(-1000, -1000);
bounds.mMax = osg::Vec2f(1000, 1000);
manager.setBounds(bounds);
manager.addObject(ObjectId(&boxShape), shape, transform, AreaType::AreaType_ground); manager.addObject(ObjectId(&boxShape), shape, transform, AreaType::AreaType_ground);
EXPECT_TRUE(manager.updateObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, EXPECT_TRUE(manager.updateObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground,
[&] (const auto& v) { onChangedTile(v); })); [&] (const auto& v) { onChangedTile(v); }));
@ -137,6 +141,10 @@ namespace
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, get_mesh_for_moved_object_should_return_recast_mesh_for_each_used_tile) TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, get_mesh_for_moved_object_should_return_recast_mesh_for_each_used_tile)
{ {
TileCachedRecastMeshManager manager(mSettings); TileCachedRecastMeshManager manager(mSettings);
TileBounds bounds;
bounds.mMin = osg::Vec2f(-1000, -1000);
bounds.mMax = osg::Vec2f(1000, 1000);
manager.setBounds(bounds);
manager.setWorldspace("worldspace"); manager.setWorldspace("worldspace");
const btBoxShape boxShape(btVector3(20, 20, 100)); const btBoxShape boxShape(btVector3(20, 20, 100));

View file

@ -2,6 +2,7 @@
#include "settings.hpp" #include "settings.hpp"
#include "settingsutils.hpp" #include "settingsutils.hpp"
#include "tileposition.hpp" #include "tileposition.hpp"
#include "tilebounds.hpp"
#include <components/misc/convert.hpp> #include <components/misc/convert.hpp>
@ -32,12 +33,15 @@ namespace DetourNavigator
} }
TilesPositionsRange makeTilesPositionsRange(const btCollisionShape& shape, const btTransform& transform, TilesPositionsRange makeTilesPositionsRange(const btCollisionShape& shape, const btTransform& transform,
const RecastSettings& settings) const TileBounds& bounds, const RecastSettings& settings)
{ {
btVector3 aabbMin; btVector3 aabbMin;
btVector3 aabbMax; btVector3 aabbMax;
shape.getAabb(transform, aabbMin, aabbMax); shape.getAabb(transform, aabbMin, aabbMax);
aabbMin.setX(std::max<btScalar>(aabbMin.x(), bounds.mMin.x()));
aabbMin.setY(std::max<btScalar>(aabbMin.y(), bounds.mMin.y()));
aabbMax.setX(std::min<btScalar>(aabbMax.x(), bounds.mMax.x()));
aabbMax.setY(std::min<btScalar>(aabbMax.y(), bounds.mMax.y()));
return makeTilesPositionsRange(Misc::Convert::toOsg(aabbMin), Misc::Convert::toOsg(aabbMax), settings); return makeTilesPositionsRange(Misc::Convert::toOsg(aabbMin), Misc::Convert::toOsg(aabbMax), settings);
} }

View file

@ -1,6 +1,7 @@
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_GETTILESPOSITIONS_H #ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_GETTILESPOSITIONS_H
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_GETTILESPOSITIONS_H #define OPENMW_COMPONENTS_DETOURNAVIGATOR_GETTILESPOSITIONS_H
#include "tilebounds.hpp"
#include "tileposition.hpp" #include "tileposition.hpp"
class btVector3; class btVector3;
@ -26,7 +27,7 @@ namespace DetourNavigator
const osg::Vec3f& aabbMax, const RecastSettings& settings); const osg::Vec3f& aabbMax, const RecastSettings& settings);
TilesPositionsRange makeTilesPositionsRange(const btCollisionShape& shape, TilesPositionsRange makeTilesPositionsRange(const btCollisionShape& shape,
const btTransform& transform, const RecastSettings& settings); const btTransform& transform, const TileBounds& bounds, const RecastSettings& settings);
TilesPositionsRange makeTilesPositionsRange(const int cellSize, const btVector3& shift, TilesPositionsRange makeTilesPositionsRange(const int cellSize, const btVector3& shift,
const RecastSettings& settings); const RecastSettings& settings);

View file

@ -42,6 +42,18 @@ namespace
namespace DetourNavigator namespace DetourNavigator
{ {
namespace
{
TileBounds makeBounds(const RecastSettings& settings, const osg::Vec2f& center, int maxTiles)
{
const float radius = fromNavMeshCoordinates(settings, std::ceil(std::sqrt(static_cast<float>(maxTiles) / osg::PIf) + 1) * getTileSize(settings));
TileBounds result;
result.mMin = center - osg::Vec2f(radius, radius);
result.mMax = center + osg::Vec2f(radius, radius);
return result;
}
}
NavMeshManager::NavMeshManager(const Settings& settings, std::unique_ptr<NavMeshDb>&& db) NavMeshManager::NavMeshManager(const Settings& settings, std::unique_ptr<NavMeshDb>&& db)
: mSettings(settings) : mSettings(settings)
, mRecastMeshManager(settings.mRecast) , mRecastMeshManager(settings.mRecast)
@ -205,6 +217,7 @@ namespace DetourNavigator
} }
} }
const auto maxTiles = std::min(mSettings.mMaxTilesNumber, navMesh.getParams()->maxTiles); const auto maxTiles = std::min(mSettings.mMaxTilesNumber, navMesh.getParams()->maxTiles);
mRecastMeshManager.setBounds(makeBounds(mSettings.mRecast, osg::Vec2f(playerPosition.x(), playerPosition.y()), maxTiles));
mRecastMeshManager.forEachTile([&] (const TilePosition& tile, CachedRecastMeshManager& recastMeshManager) mRecastMeshManager.forEachTile([&] (const TilePosition& tile, CachedRecastMeshManager& recastMeshManager)
{ {
if (tilesToPost.count(tile)) if (tilesToPost.count(tile))
@ -263,7 +276,7 @@ namespace DetourNavigator
void NavMeshManager::addChangedTiles(const btCollisionShape& shape, const btTransform& transform, void NavMeshManager::addChangedTiles(const btCollisionShape& shape, const btTransform& transform,
const ChangeType changeType) const ChangeType changeType)
{ {
getTilesPositions(makeTilesPositionsRange(shape, transform, mSettings.mRecast), getTilesPositions(makeTilesPositionsRange(shape, transform, mRecastMeshManager.getBounds(), mSettings.mRecast),
[&] (const TilePosition& v) { addChangedTile(v, changeType); }); [&] (const TilePosition& v) { addChangedTile(v, changeType); });
} }

View file

@ -37,6 +37,11 @@ namespace DetourNavigator
}; };
} }
inline float fromNavMeshCoordinates(const RecastSettings& settings, float value)
{
return value / settings.mRecastScaleFactor;
}
inline osg::Vec3f fromNavMeshCoordinates(const RecastSettings& settings, osg::Vec3f position) inline osg::Vec3f fromNavMeshCoordinates(const RecastSettings& settings, osg::Vec3f position)
{ {
const auto factor = 1.0f / settings.mRecastScaleFactor; const auto factor = 1.0f / settings.mRecastScaleFactor;

View file

@ -8,13 +8,28 @@
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#include <limits>
namespace DetourNavigator namespace DetourNavigator
{ {
TileCachedRecastMeshManager::TileCachedRecastMeshManager(const RecastSettings& settings) TileCachedRecastMeshManager::TileCachedRecastMeshManager(const RecastSettings& settings)
: mSettings(settings) : mSettings(settings)
, mBounds {osg::Vec2f(-std::numeric_limits<float>::max(), -std::numeric_limits<float>::max()),
osg::Vec2f(std::numeric_limits<float>::max(), std::numeric_limits<float>::max())}
{} {}
TileBounds TileCachedRecastMeshManager::getBounds() const
{
const std::lock_guard lock(mMutex);
return mBounds;
}
void TileCachedRecastMeshManager::setBounds(const TileBounds& bounds)
{
const std::lock_guard lock(mMutex);
mBounds = bounds;
}
std::string TileCachedRecastMeshManager::getWorldspace() const std::string TileCachedRecastMeshManager::getWorldspace() const
{ {
const std::lock_guard lock(mMutex); const std::lock_guard lock(mMutex);
@ -36,7 +51,7 @@ namespace DetourNavigator
std::vector<TilePosition> tilesPositions; std::vector<TilePosition> tilesPositions;
{ {
const std::lock_guard lock(mMutex); const std::lock_guard lock(mMutex);
getTilesPositions(makeTilesPositionsRange(shape.getShape(), transform, mSettings), getTilesPositions(makeTilesPositionsRange(shape.getShape(), transform, mBounds, mSettings),
[&] (const TilePosition& tilePosition) [&] (const TilePosition& tilePosition)
{ {
if (addTile(id, shape, transform, areaType, tilePosition, mTiles)) if (addTile(id, shape, transform, areaType, tilePosition, mTiles))

View file

@ -20,6 +20,10 @@ namespace DetourNavigator
public: public:
explicit TileCachedRecastMeshManager(const RecastSettings& settings); explicit TileCachedRecastMeshManager(const RecastSettings& settings);
TileBounds getBounds() const;
void setBounds(const TileBounds& bounds);
std::string getWorldspace() const; std::string getWorldspace() const;
void setWorldspace(std::string_view worldspace); void setWorldspace(std::string_view worldspace);
@ -57,7 +61,7 @@ namespace DetourNavigator
changed = true; changed = true;
} }
}; };
getTilesPositions(makeTilesPositionsRange(shape.getShape(), transform, mSettings), onTilePosition); getTilesPositions(makeTilesPositionsRange(shape.getShape(), transform, mBounds, mSettings), onTilePosition);
std::sort(newTiles.begin(), newTiles.end()); std::sort(newTiles.begin(), newTiles.end());
for (const auto& tile : currentTiles) for (const auto& tile : currentTiles)
{ {
@ -109,6 +113,7 @@ namespace DetourNavigator
const RecastSettings& mSettings; const RecastSettings& mSettings;
mutable std::mutex mMutex; mutable std::mutex mMutex;
TileBounds mBounds;
std::string mWorldspace; std::string mWorldspace;
TilesMap mTiles; TilesMap mTiles;
std::unordered_map<ObjectId, std::vector<TilePosition>> mObjectsTilesPositions; std::unordered_map<ObjectId, std::vector<TilePosition>> mObjectsTilesPositions;