mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-29 21:45:32 +00:00
Do not use NavMesh to find changed tiles
This commit is contained in:
parent
d1e71f9322
commit
ed3a255f65
13 changed files with 200 additions and 54 deletions
|
@ -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})
|
||||
|
|
104
apps/openmw_test_suite/detournavigator/gettilespositions.cpp
Normal file
104
apps/openmw_test_suite/detournavigator/gettilespositions.cpp
Normal file
|
@ -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;
|
||||
|
|
55
components/detournavigator/gettilespositions.hpp
Normal file
55
components/detournavigator/gettilespositions.hpp
Normal file
|
@ -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…
Reference in a new issue