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));
DetourNavigator::Settings navigatorSettings;
navigatorSettings.mBorderSize = Settings::Manager::getInt("border size", "Navigator");
navigatorSettings.mCellHeight = Settings::Manager::getFloat("cell height", "Navigator");
navigatorSettings.mCellSize = Settings::Manager::getFloat("cell size", "Navigator");
navigatorSettings.mDetailSampleDist = Settings::Manager::getFloat("detail sample dist", "Navigator");

@ -21,6 +21,7 @@ if (GTEST_FOUND AND GMOCK_FOUND)
detournavigator/navigator.cpp
detournavigator/settingsutils.cpp
detournavigator/recastmeshbuilder.cpp
detournavigator/gettilespositions.cpp
)
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.mEnableRecastMeshFileNameRevision = false;
mSettings.mEnableNavMeshFileNameRevision = false;
mSettings.mBorderSize = 16;
mSettings.mCellHeight = 0.2f;
mSettings.mCellSize = 0.2f;
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.detailSampleDist = settings.mDetailSampleDist < 0.9f ? 0 : config.cs * settings.mDetailSampleDist;
config.detailSampleMaxError = config.ch * settings.mDetailSampleMaxError;
config.borderSize = config.walkableRadius + 3;
config.borderSize = settings.mBorderSize;
config.width = settings.mTileSize + config.borderSize * 2;
config.height = settings.mTileSize + config.borderSize * 2;
rcVcopy(config.bmin, boundsMin.ptr());
rcVcopy(config.bmax, boundsMax.ptr());
config.bmin[0] -= config.borderSize * config.cs;
config.bmin[2] -= config.borderSize * config.cs;
config.bmax[0] += config.borderSize * config.cs;
config.bmax[2] += config.borderSize * config.cs;
config.bmin[0] -= getBorderSize(settings);
config.bmin[2] -= getBorderSize(settings);
config.bmax[0] += getBorderSize(settings);
config.bmax[2] += getBorderSize(settings);
rcHeightfield solid;
OPENMW_CHECK_DT_RESULT(rcCreateHeightfield(nullptr, solid, config.width, config.height,

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

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

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

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

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

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

@ -567,6 +567,9 @@ max simplification error = 1.3
# The width and height of each tile. (value > 0)
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)
max edge len = 12
@ -593,9 +596,21 @@ triangles per chunk = 256
# Enable debug log (true, 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
# Write NavMesh to file to be able to open by RecastDemo (true, 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
# Write each nav mesh file with revision in name. Otherwise will rewrite same file. (true, false)
enable nav mesh file name revision = false
# Write recast mesh file at path with this prefix
recast mesh path prefix =
# Write nav mesh file at path with this prefix
nav mesh path prefix =

Loading…
Cancel
Save