Do not use NavMesh to find changed tiles

pull/1633/head
elsid 7 years ago
parent d1e71f9322
commit ed3a255f65
No known key found for this signature in database
GPG Key ID: B845CB9FEE18AB40

@ -166,6 +166,7 @@ namespace MWWorld
mPhysics.reset(new MWPhysics::PhysicsSystem(resourceSystem, rootNode)); mPhysics.reset(new MWPhysics::PhysicsSystem(resourceSystem, rootNode));
DetourNavigator::Settings navigatorSettings; DetourNavigator::Settings navigatorSettings;
navigatorSettings.mBorderSize = Settings::Manager::getInt("border size", "Navigator");
navigatorSettings.mCellHeight = Settings::Manager::getFloat("cell height", "Navigator"); navigatorSettings.mCellHeight = Settings::Manager::getFloat("cell height", "Navigator");
navigatorSettings.mCellSize = Settings::Manager::getFloat("cell size", "Navigator"); navigatorSettings.mCellSize = Settings::Manager::getFloat("cell size", "Navigator");
navigatorSettings.mDetailSampleDist = Settings::Manager::getFloat("detail sample dist", "Navigator"); navigatorSettings.mDetailSampleDist = Settings::Manager::getFloat("detail sample dist", "Navigator");

@ -21,6 +21,7 @@ if (GTEST_FOUND AND GMOCK_FOUND)
detournavigator/navigator.cpp detournavigator/navigator.cpp
detournavigator/settingsutils.cpp detournavigator/settingsutils.cpp
detournavigator/recastmeshbuilder.cpp detournavigator/recastmeshbuilder.cpp
detournavigator/gettilespositions.cpp
) )
source_group(apps\\openmw_test_suite FILES openmw_test_suite.cpp ${UNITTEST_SRC_FILES}) source_group(apps\\openmw_test_suite FILES openmw_test_suite.cpp ${UNITTEST_SRC_FILES})

@ -0,0 +1,104 @@
#include <components/detournavigator/gettilespositions.hpp>
#include <components/detournavigator/debug.hpp>
#include <gtest/gtest.h>
#include <gmock/gmock.h>
namespace
{
using namespace testing;
using namespace DetourNavigator;
struct CollectTilesPositions
{
std::vector<TilePosition>& mTilesPositions;
void operator ()(const TilePosition& value)
{
mTilesPositions.push_back(value);
}
};
struct DetourNavigatorGetTilesPositionsTest : Test
{
Settings mSettings;
std::vector<TilePosition> mTilesPositions;
CollectTilesPositions mCollect {mTilesPositions};
DetourNavigatorGetTilesPositionsTest()
{
mSettings.mBorderSize = 0;
mSettings.mCellSize = 0.5;
mSettings.mRecastScaleFactor = 1;
mSettings.mTileSize = 64;
}
};
TEST_F(DetourNavigatorGetTilesPositionsTest, for_object_in_single_tile_should_return_one_tile)
{
getTilesPositions(osg::Vec3f(2, 2, 0), osg::Vec3f(31, 31, 1), mSettings, mCollect);
EXPECT_THAT(mTilesPositions, ElementsAre(TilePosition(0, 0)));
}
TEST_F(DetourNavigatorGetTilesPositionsTest, for_object_with_x_bounds_in_two_tiles_should_return_two_tiles)
{
getTilesPositions(osg::Vec3f(0, 0, 0), osg::Vec3f(32, 31, 1), mSettings, mCollect);
EXPECT_THAT(mTilesPositions, ElementsAre(TilePosition(0, 0), TilePosition(1, 0)));
}
TEST_F(DetourNavigatorGetTilesPositionsTest, for_object_with_y_bounds_in_two_tiles_should_return_two_tiles)
{
getTilesPositions(osg::Vec3f(0, 0, 0), osg::Vec3f(31, 32, 1), mSettings, mCollect);
EXPECT_THAT(mTilesPositions, ElementsAre(TilePosition(0, 0), TilePosition(0, 1)));
}
TEST_F(DetourNavigatorGetTilesPositionsTest, tiling_works_only_for_x_and_y_coordinates)
{
getTilesPositions(osg::Vec3f(0, 0, 0), osg::Vec3f(31, 31, 32), mSettings, mCollect);
EXPECT_THAT(mTilesPositions, ElementsAre(TilePosition(0, 0)));
}
TEST_F(DetourNavigatorGetTilesPositionsTest, tiling_should_work_with_negative_coordinates)
{
getTilesPositions(osg::Vec3f(-31, -31, 0), osg::Vec3f(31, 31, 1), mSettings, mCollect);
EXPECT_THAT(mTilesPositions, ElementsAre(
TilePosition(-1, -1),
TilePosition(-1, 0),
TilePosition(0, -1),
TilePosition(0, 0)
));
}
TEST_F(DetourNavigatorGetTilesPositionsTest, border_size_should_extend_tile_bounds)
{
mSettings.mBorderSize = 1;
getTilesPositions(osg::Vec3f(0, 0, 0), osg::Vec3f(31.5, 31.5, 1), mSettings, mCollect);
EXPECT_THAT(mTilesPositions, ElementsAre(
TilePosition(-1, -1),
TilePosition(-1, 0),
TilePosition(-1, 1),
TilePosition(0, -1),
TilePosition(0, 0),
TilePosition(0, 1),
TilePosition(1, -1),
TilePosition(1, 0),
TilePosition(1, 1)
));
}
TEST_F(DetourNavigatorGetTilesPositionsTest, should_apply_recast_scale_factor)
{
mSettings.mRecastScaleFactor = 0.5;
getTilesPositions(osg::Vec3f(0, 0, 0), osg::Vec3f(32, 32, 1), mSettings, mCollect);
EXPECT_THAT(mTilesPositions, ElementsAre(TilePosition(0, 0)));
}
}

@ -37,6 +37,7 @@ namespace
mSettings.mEnableWriteNavMeshToFile = false; mSettings.mEnableWriteNavMeshToFile = false;
mSettings.mEnableRecastMeshFileNameRevision = false; mSettings.mEnableRecastMeshFileNameRevision = false;
mSettings.mEnableNavMeshFileNameRevision = false; mSettings.mEnableNavMeshFileNameRevision = false;
mSettings.mBorderSize = 16;
mSettings.mCellHeight = 0.2f; mSettings.mCellHeight = 0.2f;
mSettings.mCellSize = 0.2f; mSettings.mCellSize = 0.2f;
mSettings.mDetailSampleDist = 6; mSettings.mDetailSampleDist = 6;

@ -0,0 +1,55 @@
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_GETTILESPOSITIONS_H
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_GETTILESPOSITIONS_H
#include "settings.hpp"
#include "settingsutils.hpp"
#include <BulletCollision/CollisionShapes/btCollisionShape.h>
#include <osg/Vec3f>
namespace DetourNavigator
{
inline osg::Vec3f makeOsgVec3f(const btVector3& value)
{
return osg::Vec3f(value.x(), value.y(), value.z());
}
template <class Callback>
void getTilesPositions(const osg::Vec3f& aabbMin, const osg::Vec3f& aabbMax,
const Settings& settings, Callback&& callback)
{
auto min = toNavMeshCoordinates(settings, aabbMin);
auto max = toNavMeshCoordinates(settings, aabbMax);
const auto border = getBorderSize(settings);
min -= osg::Vec3f(border, border, border);
max += osg::Vec3f(border, border, border);
auto minTile = getTilePosition(settings, min);
auto maxTile = getTilePosition(settings, max);
if (minTile.x() > maxTile.x())
std::swap(minTile.x(), maxTile.x());
if (minTile.y() > maxTile.y())
std::swap(minTile.y(), maxTile.y());
for (int tileX = minTile.x(); tileX <= maxTile.x(); ++tileX)
for (int tileY = minTile.y(); tileY <= maxTile.y(); ++tileY)
callback(TilePosition {tileX, tileY});
}
template <class Callback>
void getTilesPositions(const btCollisionShape& shape, const btTransform& transform,
const Settings& settings, Callback&& callback)
{
btVector3 aabbMin;
btVector3 aabbMax;
shape.getAabb(transform, aabbMin, aabbMax);
getTilesPositions(makeOsgVec3f(aabbMin), makeOsgVec3f(aabbMax), settings, std::forward<Callback>(callback));
}
}
#endif

@ -82,15 +82,15 @@ namespace
config.maxVertsPerPoly = settings.mMaxVertsPerPoly; config.maxVertsPerPoly = settings.mMaxVertsPerPoly;
config.detailSampleDist = settings.mDetailSampleDist < 0.9f ? 0 : config.cs * settings.mDetailSampleDist; config.detailSampleDist = settings.mDetailSampleDist < 0.9f ? 0 : config.cs * settings.mDetailSampleDist;
config.detailSampleMaxError = config.ch * settings.mDetailSampleMaxError; config.detailSampleMaxError = config.ch * settings.mDetailSampleMaxError;
config.borderSize = config.walkableRadius + 3; config.borderSize = settings.mBorderSize;
config.width = settings.mTileSize + config.borderSize * 2; config.width = settings.mTileSize + config.borderSize * 2;
config.height = settings.mTileSize + config.borderSize * 2; config.height = settings.mTileSize + config.borderSize * 2;
rcVcopy(config.bmin, boundsMin.ptr()); rcVcopy(config.bmin, boundsMin.ptr());
rcVcopy(config.bmax, boundsMax.ptr()); rcVcopy(config.bmax, boundsMax.ptr());
config.bmin[0] -= config.borderSize * config.cs; config.bmin[0] -= getBorderSize(settings);
config.bmin[2] -= config.borderSize * config.cs; config.bmin[2] -= getBorderSize(settings);
config.bmax[0] += config.borderSize * config.cs; config.bmax[0] += getBorderSize(settings);
config.bmax[2] += config.borderSize * config.cs; config.bmax[2] += getBorderSize(settings);
rcHeightfield solid; rcHeightfield solid;
OPENMW_CHECK_DT_RESULT(rcCreateHeightfield(nullptr, solid, config.width, config.height, OPENMW_CHECK_DT_RESULT(rcCreateHeightfield(nullptr, solid, config.width, config.height,

@ -1,6 +1,7 @@
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_MAKENAVMESH_H #ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_MAKENAVMESH_H
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_MAKENAVMESH_H #define OPENMW_COMPONENTS_DETOURNAVIGATOR_MAKENAVMESH_H
#include "settings.hpp"
#include "tileposition.hpp" #include "tileposition.hpp"
#include <osg/Vec3f> #include <osg/Vec3f>

@ -1,6 +1,7 @@
#include "navmeshmanager.hpp" #include "navmeshmanager.hpp"
#include "debug.hpp" #include "debug.hpp"
#include "exceptions.hpp" #include "exceptions.hpp"
#include "gettilespositions.hpp"
#include "makenavmesh.hpp" #include "makenavmesh.hpp"
#include "settings.hpp" #include "settings.hpp"
#include "sharednavmesh.hpp" #include "sharednavmesh.hpp"
@ -63,12 +64,10 @@ namespace DetourNavigator
const auto changedTiles = mChangedTiles.find(agentHalfExtents); const auto changedTiles = mChangedTiles.find(agentHalfExtents);
if (changedTiles != mChangedTiles.end()) if (changedTiles != mChangedTiles.end())
{ {
TilePosition playerTile;
playerPosition *= mSettings.mRecastScaleFactor; playerPosition *= mSettings.mRecastScaleFactor;
std::swap(playerPosition.y(), playerPosition.z()); std::swap(playerPosition.y(), playerPosition.z());
cached->mValue.raw()->calcTileLoc(playerPosition.ptr(), &playerTile.x(), &playerTile.y()); mAsyncNavMeshUpdater.post(agentHalfExtents, mRecastMeshManager.getMesh(), cached,
mAsyncNavMeshUpdater.post(agentHalfExtents, mRecastMeshManager.getMesh(), cached, playerTile, getTilePosition(mSettings, playerPosition), changedTiles->second);
changedTiles->second);
mChangedTiles.erase(changedTiles); mChangedTiles.erase(changedTiles);
log("cache update posted for agent=", agentHalfExtents); log("cache update posted for agent=", agentHalfExtents);
} }
@ -91,39 +90,11 @@ namespace DetourNavigator
void NavMeshManager::addChangedTiles(const btCollisionShape& shape, const btTransform& transform) void NavMeshManager::addChangedTiles(const btCollisionShape& shape, const btTransform& transform)
{ {
btVector3 aabbMin; getTilesPositions(shape, transform, mSettings, [&] (const TilePosition& v) {
btVector3 aabbMax; for (const auto& cached : mCache)
shape.getAabb(transform, aabbMin, aabbMax); if (cached.second)
osg::Vec3f min(aabbMin.x(), aabbMin.z(), aabbMin.y()); mChangedTiles[cached.first].insert(v);
osg::Vec3f max(aabbMax.x(), aabbMax.z(), aabbMax.y()); });
min *= mSettings.mRecastScaleFactor;
max *= mSettings.mRecastScaleFactor;
for (auto& v : mCache)
{
if (const auto& item = v.second)
{
auto& changedTiles = mChangedTiles[v.first];
int minTileX;
int minTileY;
item->mValue.raw()->calcTileLoc(min.ptr(), &minTileX, &minTileY);
int maxTileX;
int maxTileY;
item->mValue.raw()->calcTileLoc(max.ptr(), &maxTileX, &maxTileY);
if (minTileX > maxTileX)
std::swap(minTileX, maxTileX);
if (minTileY > maxTileY)
std::swap(minTileY, maxTileY);
for (int tileX = minTileX; tileX <= maxTileX; ++tileX)
for (int tileY = minTileY; tileY <= maxTileY; ++tileY)
changedTiles.insert(TilePosition {tileX, tileY});
}
}
} }
const std::shared_ptr<NavMeshCacheItem>& NavMeshManager::getCached(const osg::Vec3f& agentHalfExtents) const const std::shared_ptr<NavMeshCacheItem>& NavMeshManager::getCached(const osg::Vec3f& agentHalfExtents) const

@ -7,7 +7,8 @@ namespace DetourNavigator
RecastMeshManager::RecastMeshManager(const Settings& settings) RecastMeshManager::RecastMeshManager(const Settings& settings)
: mShouldRebuild(false) : mShouldRebuild(false)
, mMeshBuilder(settings) , mMeshBuilder(settings)
{} {
}
bool RecastMeshManager::addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform) bool RecastMeshManager::addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform)
{ {
@ -40,12 +41,7 @@ namespace DetourNavigator
return; return;
mMeshBuilder.reset(); mMeshBuilder.reset();
for (const auto& v : mObjects) for (const auto& v : mObjects)
{ mMeshBuilder.addObject(*v.second.mShape, v.second.mTransform);
if (v.second.mShape->getShapeType() == TERRAIN_SHAPE_PROXYTYPE)
mMeshBuilder.addObject(*static_cast<const btHeightfieldTerrainShape*>(v.second.mShape), v.second.mTransform);
else if (v.second.mShape->isConcave())
mMeshBuilder.addObject(*static_cast<const btConcaveShape*>(v.second.mShape), v.second.mTransform);
}
mShouldRebuild = false; mShouldRebuild = false;
} }
} }

@ -19,6 +19,7 @@ namespace DetourNavigator
float mMaxSimplificationError; float mMaxSimplificationError;
float mMaxSlope; float mMaxSlope;
float mRecastScaleFactor; float mRecastScaleFactor;
int mBorderSize;
int mMaxEdgeLen; int mMaxEdgeLen;
int mMaxNavMeshQueryNodes; int mMaxNavMeshQueryNodes;
int mMaxVertsPerPoly; int mMaxVertsPerPoly;

@ -60,6 +60,11 @@ namespace DetourNavigator
osg::Vec2f(tilePosition.x() + 1, tilePosition.y() + 1) * getTileSize(settings), osg::Vec2f(tilePosition.x() + 1, tilePosition.y() + 1) * getTileSize(settings),
}; };
} }
inline float getBorderSize(const Settings& settings)
{
return settings.mBorderSize * settings.mCellSize;
}
} }
#endif #endif

@ -44,11 +44,6 @@ namespace DetourNavigator
return LockedSharedNavMesh(*mMutex, mValue); return LockedSharedNavMesh(*mMutex, mValue);
} }
NavMeshPtr raw() const
{
return mValue;
}
private: private:
std::shared_ptr<std::mutex> mMutex; std::shared_ptr<std::mutex> mMutex;
NavMeshPtr mValue; NavMeshPtr mValue;

@ -567,6 +567,9 @@ max simplification error = 1.3
# The width and height of each tile. (value > 0) # The width and height of each tile. (value > 0)
tile size = 64 tile size = 64
# The size of the non-navigable border around the heightfield. (value >= 0)
border size = 16
# The maximum allowed length for contour edges along the border of the mesh. (value >= 0) # The maximum allowed length for contour edges along the border of the mesh. (value >= 0)
max edge len = 12 max edge len = 12
@ -593,9 +596,21 @@ triangles per chunk = 256
# Enable debug log (true, false) # Enable debug log (true, false)
enable log = false enable log = false
# Write recast mesh to file in .obj format for each use to update nav mesh (true, false)
enable write recast mesh to file = false enable write recast mesh to file = false
# Write NavMesh to file to be able to open by RecastDemo (true, false)
enable write nav mesh to file = false enable write nav mesh to file = false
# Write each recast mesh file with revision in name. Otherwise will rewrite same file. (true, false)
enable recast mesh file name revision = false enable recast mesh file name revision = false
# Write each nav mesh file with revision in name. Otherwise will rewrite same file. (true, false)
enable nav mesh file name revision = false enable nav mesh file name revision = false
# Write recast mesh file at path with this prefix
recast mesh path prefix = recast mesh path prefix =
# Write nav mesh file at path with this prefix
nav mesh path prefix = nav mesh path prefix =

Loading…
Cancel
Save