mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-30 09:36:43 +00:00
Split RecastMesh into tiles
This commit is contained in:
parent
dbb1d99bff
commit
d2fd9abd51
19 changed files with 328 additions and 88 deletions
|
@ -21,19 +21,23 @@ namespace
|
||||||
struct DetourNavigatorRecastMeshBuilderTest : Test
|
struct DetourNavigatorRecastMeshBuilderTest : Test
|
||||||
{
|
{
|
||||||
Settings mSettings;
|
Settings mSettings;
|
||||||
RecastMeshBuilder mBuilder;
|
TileBounds mBounds;
|
||||||
|
|
||||||
DetourNavigatorRecastMeshBuilderTest()
|
DetourNavigatorRecastMeshBuilderTest()
|
||||||
: mBuilder(mSettings)
|
|
||||||
{
|
{
|
||||||
mSettings.mRecastScaleFactor = 1.0f;
|
mSettings.mRecastScaleFactor = 1.0f;
|
||||||
mSettings.mTrianglesPerChunk = 256;
|
mSettings.mTrianglesPerChunk = 256;
|
||||||
|
mBounds.mMin = osg::Vec2f(-std::numeric_limits<float>::max() * std::numeric_limits<float>::epsilon(),
|
||||||
|
-std::numeric_limits<float>::max() * std::numeric_limits<float>::epsilon());
|
||||||
|
mBounds.mMax = osg::Vec2f(std::numeric_limits<float>::max() * std::numeric_limits<float>::epsilon(),
|
||||||
|
std::numeric_limits<float>::max() * std::numeric_limits<float>::epsilon());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(DetourNavigatorRecastMeshBuilderTest, create_for_empty_should_return_empty)
|
TEST_F(DetourNavigatorRecastMeshBuilderTest, create_for_empty_should_return_empty)
|
||||||
{
|
{
|
||||||
const auto recastMesh = mBuilder.create();
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
|
const auto recastMesh = builder.create();
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>());
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>());
|
||||||
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>());
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>());
|
||||||
}
|
}
|
||||||
|
@ -43,8 +47,9 @@ namespace
|
||||||
btTriangleMesh mesh;
|
btTriangleMesh mesh;
|
||||||
mesh.addTriangle(btVector3(-1, -1, 0), btVector3(-1, 1, 0), btVector3(1, -1, 0));
|
mesh.addTriangle(btVector3(-1, -1, 0), btVector3(-1, 1, 0), btVector3(1, -1, 0));
|
||||||
btBvhTriangleMeshShape shape(&mesh, true);
|
btBvhTriangleMeshShape shape(&mesh, true);
|
||||||
mBuilder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity());
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
const auto recastMesh = mBuilder.create();
|
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity());
|
||||||
|
const auto recastMesh = builder.create();
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
1, 0, -1,
|
1, 0, -1,
|
||||||
-1, 0, 1,
|
-1, 0, 1,
|
||||||
|
@ -58,9 +63,10 @@ namespace
|
||||||
btTriangleMesh mesh;
|
btTriangleMesh mesh;
|
||||||
mesh.addTriangle(btVector3(-1, -1, 0), btVector3(-1, 1, 0), btVector3(1, -1, 0));
|
mesh.addTriangle(btVector3(-1, -1, 0), btVector3(-1, 1, 0), btVector3(1, -1, 0));
|
||||||
btBvhTriangleMeshShape shape(&mesh, true);
|
btBvhTriangleMeshShape shape(&mesh, true);
|
||||||
mBuilder.addObject(static_cast<const btCollisionShape&>(shape),
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
|
builder.addObject(static_cast<const btCollisionShape&>(shape),
|
||||||
btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)));
|
btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)));
|
||||||
const auto recastMesh = mBuilder.create();
|
const auto recastMesh = builder.create();
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
2, 3, 0,
|
2, 3, 0,
|
||||||
0, 3, 4,
|
0, 3, 4,
|
||||||
|
@ -73,8 +79,9 @@ namespace
|
||||||
{
|
{
|
||||||
const std::array<btScalar, 4> heightfieldData {{0, 0, 0, 0}};
|
const std::array<btScalar, 4> heightfieldData {{0, 0, 0, 0}};
|
||||||
btHeightfieldTerrainShape shape(2, 2, heightfieldData.data(), 1, 0, 0, 2, PHY_FLOAT, false);
|
btHeightfieldTerrainShape shape(2, 2, heightfieldData.data(), 1, 0, 0, 2, PHY_FLOAT, false);
|
||||||
mBuilder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity());
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
const auto recastMesh = mBuilder.create();
|
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity());
|
||||||
|
const auto recastMesh = builder.create();
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
-0.5, 0, -0.5,
|
-0.5, 0, -0.5,
|
||||||
-0.5, 0, 0.5,
|
-0.5, 0, 0.5,
|
||||||
|
@ -89,8 +96,9 @@ namespace
|
||||||
TEST_F(DetourNavigatorRecastMeshBuilderTest, add_box_shape_should_produce_12_triangles)
|
TEST_F(DetourNavigatorRecastMeshBuilderTest, add_box_shape_should_produce_12_triangles)
|
||||||
{
|
{
|
||||||
btBoxShape shape(btVector3(1, 1, 2));
|
btBoxShape shape(btVector3(1, 1, 2));
|
||||||
mBuilder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity());
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
const auto recastMesh = mBuilder.create();
|
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity());
|
||||||
|
const auto recastMesh = builder.create();
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
1, 2, 1,
|
1, 2, 1,
|
||||||
-1, 2, 1,
|
-1, 2, 1,
|
||||||
|
@ -130,8 +138,9 @@ namespace
|
||||||
shape.addChildShape(btTransform::getIdentity(), &triangle1);
|
shape.addChildShape(btTransform::getIdentity(), &triangle1);
|
||||||
shape.addChildShape(btTransform::getIdentity(), &box);
|
shape.addChildShape(btTransform::getIdentity(), &box);
|
||||||
shape.addChildShape(btTransform::getIdentity(), &triangle2);
|
shape.addChildShape(btTransform::getIdentity(), &triangle2);
|
||||||
mBuilder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity());
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
const auto recastMesh = mBuilder.create();
|
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity());
|
||||||
|
const auto recastMesh = builder.create();
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
1, 0, -1,
|
1, 0, -1,
|
||||||
-1, 0, 1,
|
-1, 0, 1,
|
||||||
|
@ -173,9 +182,10 @@ namespace
|
||||||
btBvhTriangleMeshShape triangle(&mesh, true);
|
btBvhTriangleMeshShape triangle(&mesh, true);
|
||||||
btCompoundShape shape;
|
btCompoundShape shape;
|
||||||
shape.addChildShape(btTransform::getIdentity(), &triangle);
|
shape.addChildShape(btTransform::getIdentity(), &triangle);
|
||||||
mBuilder.addObject(static_cast<const btCollisionShape&>(shape),
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)));
|
builder.addObject(static_cast<const btCollisionShape&>(shape),
|
||||||
const auto recastMesh = mBuilder.create();
|
btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)));
|
||||||
|
const auto recastMesh = builder.create();
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
2, 3, 0,
|
2, 3, 0,
|
||||||
0, 3, 4,
|
0, 3, 4,
|
||||||
|
@ -192,9 +202,10 @@ namespace
|
||||||
btCompoundShape shape;
|
btCompoundShape shape;
|
||||||
shape.addChildShape(btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)),
|
shape.addChildShape(btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)),
|
||||||
&triangle);
|
&triangle);
|
||||||
mBuilder.addObject(static_cast<const btCollisionShape&>(shape),
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)));
|
builder.addObject(static_cast<const btCollisionShape&>(shape),
|
||||||
const auto recastMesh = mBuilder.create();
|
btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)));
|
||||||
|
const auto recastMesh = builder.create();
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
3, 12, 2,
|
3, 12, 2,
|
||||||
1, 12, 10,
|
1, 12, 10,
|
||||||
|
@ -202,4 +213,104 @@ namespace
|
||||||
}));
|
}));
|
||||||
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(DetourNavigatorRecastMeshBuilderTest, without_bounds_add_transformed_compound_shape_with_transformed_bhv_triangle_shape_should_not_filter_by_bounds)
|
||||||
|
{
|
||||||
|
btTriangleMesh mesh;
|
||||||
|
mesh.addTriangle(btVector3(-1, -1, 0), btVector3(-1, 1, 0), btVector3(1, -1, 0));
|
||||||
|
mesh.addTriangle(btVector3(-3, -3, 0), btVector3(-3, -2, 0), btVector3(-2, -3, 0));
|
||||||
|
btBvhTriangleMeshShape shape(&mesh, true);
|
||||||
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
|
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity());
|
||||||
|
const auto recastMesh = builder.create();
|
||||||
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
|
1, 0, -1,
|
||||||
|
-1, 0, 1,
|
||||||
|
-1, 0, -1,
|
||||||
|
-2, 0, -3,
|
||||||
|
-3, 0, -2,
|
||||||
|
-3, 0, -3,
|
||||||
|
}));
|
||||||
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2, 3, 4, 5}));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DetourNavigatorRecastMeshBuilderTest, with_bounds_add_transformed_compound_shape_with_transformed_bhv_triangle_shape_should_filter_by_bounds)
|
||||||
|
{
|
||||||
|
mSettings.mRecastScaleFactor = 0.1f;
|
||||||
|
mBounds.mMin = osg::Vec2f(-3, -3) * mSettings.mRecastScaleFactor;
|
||||||
|
mBounds.mMax = osg::Vec2f(-2, -2) * mSettings.mRecastScaleFactor;
|
||||||
|
btTriangleMesh mesh;
|
||||||
|
mesh.addTriangle(btVector3(-1, -1, 0), btVector3(-1, 1, 0), btVector3(1, -1, 0));
|
||||||
|
mesh.addTriangle(btVector3(-3, -3, 0), btVector3(-3, -2, 0), btVector3(-2, -3, 0));
|
||||||
|
btBvhTriangleMeshShape shape(&mesh, true);
|
||||||
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
|
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity());
|
||||||
|
const auto recastMesh = builder.create();
|
||||||
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
|
-0.2f, 0, -0.3f,
|
||||||
|
-0.3f, 0, -0.2f,
|
||||||
|
-0.3f, 0, -0.3f,
|
||||||
|
}));
|
||||||
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DetourNavigatorRecastMeshBuilderTest, with_bounds_add_rotated_by_x_bhv_triangle_shape_should_filter_by_bounds)
|
||||||
|
{
|
||||||
|
mBounds.mMin = osg::Vec2f(-5, -5);
|
||||||
|
mBounds.mMax = osg::Vec2f(5, -3);
|
||||||
|
btTriangleMesh mesh;
|
||||||
|
mesh.addTriangle(btVector3(0, -1, -1), btVector3(0, -1, -1), btVector3(0, 1, -1));
|
||||||
|
mesh.addTriangle(btVector3(0, -3, -3), btVector3(0, -3, -2), btVector3(0, -2, -3));
|
||||||
|
btBvhTriangleMeshShape shape(&mesh, true);
|
||||||
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
|
builder.addObject(static_cast<const btCollisionShape&>(shape),
|
||||||
|
btTransform(btQuaternion(btVector3(1, 0, 0), static_cast<btScalar>(-osg::PI_4))));
|
||||||
|
const auto recastMesh = builder.create();
|
||||||
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
|
0, -0.70710659027099609375, -3.535533905029296875,
|
||||||
|
0, 0.707107067108154296875, -3.535533905029296875,
|
||||||
|
0, 2.384185791015625e-07, -4.24264049530029296875,
|
||||||
|
}));
|
||||||
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DetourNavigatorRecastMeshBuilderTest, with_bounds_add_rotated_by_y_bhv_triangle_shape_should_filter_by_bounds)
|
||||||
|
{
|
||||||
|
mBounds.mMin = osg::Vec2f(-5, -5);
|
||||||
|
mBounds.mMax = osg::Vec2f(-3, 5);
|
||||||
|
btTriangleMesh mesh;
|
||||||
|
mesh.addTriangle(btVector3(-1, 0, -1), btVector3(-1, 0, 1), btVector3(1, 0, -1));
|
||||||
|
mesh.addTriangle(btVector3(-3, 0, -3), btVector3(-3, 0, -2), btVector3(-2, 0, -3));
|
||||||
|
btBvhTriangleMeshShape shape(&mesh, true);
|
||||||
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
|
builder.addObject(static_cast<const btCollisionShape&>(shape),
|
||||||
|
btTransform(btQuaternion(btVector3(0, 1, 0), static_cast<btScalar>(osg::PI_4))));
|
||||||
|
const auto recastMesh = builder.create();
|
||||||
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
|
-3.535533905029296875, -0.70710659027099609375, 0,
|
||||||
|
-3.535533905029296875, 0.707107067108154296875, 0,
|
||||||
|
-4.24264049530029296875, 2.384185791015625e-07, 0,
|
||||||
|
}));
|
||||||
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DetourNavigatorRecastMeshBuilderTest, with_bounds_add_rotated_by_z_bhv_triangle_shape_should_filter_by_bounds)
|
||||||
|
{
|
||||||
|
mBounds.mMin = osg::Vec2f(-5, -5);
|
||||||
|
mBounds.mMax = osg::Vec2f(-1, -1);
|
||||||
|
btTriangleMesh mesh;
|
||||||
|
mesh.addTriangle(btVector3(-1, -1, 0), btVector3(-1, 1, 0), btVector3(1, -1, 0));
|
||||||
|
mesh.addTriangle(btVector3(-3, -3, 0), btVector3(-3, -2, 0), btVector3(-2, -3, 0));
|
||||||
|
btBvhTriangleMeshShape shape(&mesh, true);
|
||||||
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
|
builder.addObject(static_cast<const btCollisionShape&>(shape),
|
||||||
|
btTransform(btQuaternion(btVector3(0, 0, 1), static_cast<btScalar>(osg::PI_4))));
|
||||||
|
const auto recastMesh = builder.create();
|
||||||
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
|
0.707107067108154296875, 0, -3.535533905029296875,
|
||||||
|
-0.70710659027099609375, 0, -3.535533905029296875,
|
||||||
|
2.384185791015625e-07, 0, -4.24264049530029296875,
|
||||||
|
}));
|
||||||
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,6 +168,7 @@ add_component_dir(detournavigator
|
||||||
asyncnavmeshupdater
|
asyncnavmeshupdater
|
||||||
chunkytrimesh
|
chunkytrimesh
|
||||||
recastmesh
|
recastmesh
|
||||||
|
tilecachedrecastmeshmanager
|
||||||
)
|
)
|
||||||
|
|
||||||
set (ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui
|
set (ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui
|
||||||
|
|
|
@ -40,8 +40,9 @@ namespace DetourNavigator
|
||||||
return stream << "unknown";
|
return stream << "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncNavMeshUpdater::AsyncNavMeshUpdater(const Settings& settings)
|
AsyncNavMeshUpdater::AsyncNavMeshUpdater(const Settings& settings, TileCachedRecastMeshManager& recastMeshManager)
|
||||||
: mSettings(std::cref(settings))
|
: mSettings(settings)
|
||||||
|
, mRecastMeshManager(recastMeshManager)
|
||||||
, mShouldStop()
|
, mShouldStop()
|
||||||
, mThread([&] { process(); })
|
, mThread([&] { process(); })
|
||||||
{
|
{
|
||||||
|
@ -57,11 +58,11 @@ namespace DetourNavigator
|
||||||
mThread.join();
|
mThread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncNavMeshUpdater::post(const osg::Vec3f& agentHalfExtents, const std::shared_ptr<RecastMesh>& recastMesh,
|
void AsyncNavMeshUpdater::post(const osg::Vec3f& agentHalfExtents,
|
||||||
const std::shared_ptr<NavMeshCacheItem>& navMeshCacheItem, const TilePosition& playerTile,
|
const std::shared_ptr<NavMeshCacheItem>& navMeshCacheItem, const TilePosition& playerTile,
|
||||||
const std::set<TilePosition>& changedTiles)
|
const std::set<TilePosition>& changedTiles)
|
||||||
{
|
{
|
||||||
setRecastMesh(recastMesh);
|
log("post jobs playerTile=", playerTile);
|
||||||
|
|
||||||
if (changedTiles.empty())
|
if (changedTiles.empty())
|
||||||
return;
|
return;
|
||||||
|
@ -107,9 +108,9 @@ namespace DetourNavigator
|
||||||
|
|
||||||
setFirstStart(start);
|
setFirstStart(start);
|
||||||
|
|
||||||
const auto recastMesh = getRecastMesh();
|
const auto recastMesh = mRecastMeshManager.get().getMesh(job.mChangedTile);
|
||||||
|
|
||||||
const auto status = updateNavMesh(job.mAgentHalfExtents, *recastMesh, job.mChangedTile, mSettings,
|
const auto status = updateNavMesh(job.mAgentHalfExtents, recastMesh.get(), job.mChangedTile, mSettings,
|
||||||
*job.mNavMeshCacheItem);
|
*job.mNavMeshCacheItem);
|
||||||
|
|
||||||
const auto finish = std::chrono::steady_clock::now();
|
const auto finish = std::chrono::steady_clock::now();
|
||||||
|
@ -162,18 +163,6 @@ namespace DetourNavigator
|
||||||
writeToFile(*job.mNavMeshCacheItem->mValue.lock(), mSettings.get().mNavMeshPathPrefix, navMeshRevision);
|
writeToFile(*job.mNavMeshCacheItem->mValue.lock(), mSettings.get().mNavMeshPathPrefix, navMeshRevision);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<RecastMesh> AsyncNavMeshUpdater::getRecastMesh()
|
|
||||||
{
|
|
||||||
const std::lock_guard<std::mutex> lock(mRecastMeshMutex);
|
|
||||||
return mRecastMesh;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AsyncNavMeshUpdater::setRecastMesh(const std::shared_ptr<RecastMesh>& value)
|
|
||||||
{
|
|
||||||
const std::lock_guard<std::mutex> lock(mRecastMeshMutex);
|
|
||||||
mRecastMesh = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::chrono::steady_clock::time_point AsyncNavMeshUpdater::getFirstStart()
|
std::chrono::steady_clock::time_point AsyncNavMeshUpdater::getFirstStart()
|
||||||
{
|
{
|
||||||
const std::lock_guard<std::mutex> lock(mFirstStartMutex);
|
const std::lock_guard<std::mutex> lock(mFirstStartMutex);
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_ASYNCNAVMESHUPDATER_H
|
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_ASYNCNAVMESHUPDATER_H
|
||||||
|
|
||||||
#include "navmeshcacheitem.hpp"
|
#include "navmeshcacheitem.hpp"
|
||||||
#include "recastmesh.hpp"
|
#include "tilecachedrecastmeshmanager.hpp"
|
||||||
#include "tileposition.hpp"
|
#include "tileposition.hpp"
|
||||||
|
|
||||||
#include <osg/Vec3f>
|
#include <osg/Vec3f>
|
||||||
|
@ -25,12 +25,11 @@ namespace DetourNavigator
|
||||||
class AsyncNavMeshUpdater
|
class AsyncNavMeshUpdater
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AsyncNavMeshUpdater(const Settings& settings);
|
AsyncNavMeshUpdater(const Settings& settings, TileCachedRecastMeshManager& recastMeshManager);
|
||||||
~AsyncNavMeshUpdater();
|
~AsyncNavMeshUpdater();
|
||||||
|
|
||||||
void post(const osg::Vec3f& agentHalfExtents, const std::shared_ptr<RecastMesh>& recastMesh,
|
void post(const osg::Vec3f& agentHalfExtents, const std::shared_ptr<NavMeshCacheItem>& mNavMeshCacheItem,
|
||||||
const std::shared_ptr<NavMeshCacheItem>& navMeshCacheItem, const TilePosition& playerTile,
|
const TilePosition& playerTile, const std::set<TilePosition>& changedTiles);
|
||||||
const std::set<TilePosition>& changedTiles);
|
|
||||||
|
|
||||||
void wait();
|
void wait();
|
||||||
|
|
||||||
|
@ -51,13 +50,12 @@ namespace DetourNavigator
|
||||||
using Jobs = std::priority_queue<Job, std::deque<Job>>;
|
using Jobs = std::priority_queue<Job, std::deque<Job>>;
|
||||||
|
|
||||||
std::reference_wrapper<const Settings> mSettings;
|
std::reference_wrapper<const Settings> mSettings;
|
||||||
|
std::reference_wrapper<TileCachedRecastMeshManager> mRecastMeshManager;
|
||||||
std::atomic_bool mShouldStop;
|
std::atomic_bool mShouldStop;
|
||||||
std::mutex mMutex;
|
std::mutex mMutex;
|
||||||
std::condition_variable mHasJob;
|
std::condition_variable mHasJob;
|
||||||
std::condition_variable mDone;
|
std::condition_variable mDone;
|
||||||
Jobs mJobs;
|
Jobs mJobs;
|
||||||
std::mutex mRecastMeshMutex;
|
|
||||||
std::shared_ptr<RecastMesh> mRecastMesh;
|
|
||||||
std::mutex mFirstStartMutex;
|
std::mutex mFirstStartMutex;
|
||||||
boost::optional<std::chrono::steady_clock::time_point> mFirstStart;
|
boost::optional<std::chrono::steady_clock::time_point> mFirstStart;
|
||||||
std::thread mThread;
|
std::thread mThread;
|
||||||
|
@ -72,10 +70,6 @@ namespace DetourNavigator
|
||||||
|
|
||||||
void writeDebugFiles(const Job& job, const RecastMesh& recastMesh) const;
|
void writeDebugFiles(const Job& job, const RecastMesh& recastMesh) const;
|
||||||
|
|
||||||
std::shared_ptr<RecastMesh> getRecastMesh();
|
|
||||||
|
|
||||||
void setRecastMesh(const std::shared_ptr<RecastMesh>& value);
|
|
||||||
|
|
||||||
std::chrono::steady_clock::time_point getFirstStart();
|
std::chrono::steady_clock::time_point getFirstStart();
|
||||||
|
|
||||||
void setFirstStart(const std::chrono::steady_clock::time_point& value);
|
void setFirstStart(const std::chrono::steady_clock::time_point& value);
|
||||||
|
|
|
@ -3,9 +3,10 @@
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
CachedRecastMeshManager::CachedRecastMeshManager(const Settings& settings)
|
CachedRecastMeshManager::CachedRecastMeshManager(const Settings& settings, const TileBounds& bounds)
|
||||||
: mImpl(settings)
|
: mImpl(settings, bounds)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool CachedRecastMeshManager::addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform)
|
bool CachedRecastMeshManager::addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform)
|
||||||
{
|
{
|
||||||
|
@ -29,4 +30,9 @@ namespace DetourNavigator
|
||||||
mCached = mImpl.getMesh();
|
mCached = mImpl.getMesh();
|
||||||
return mCached;
|
return mCached;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CachedRecastMeshManager::isEmpty() const
|
||||||
|
{
|
||||||
|
return mImpl.isEmpty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace DetourNavigator
|
||||||
class CachedRecastMeshManager
|
class CachedRecastMeshManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CachedRecastMeshManager(const Settings& settings);
|
CachedRecastMeshManager(const Settings& settings, const TileBounds& bounds);
|
||||||
|
|
||||||
bool addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform);
|
bool addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform);
|
||||||
|
|
||||||
|
@ -18,6 +18,8 @@ namespace DetourNavigator
|
||||||
|
|
||||||
std::shared_ptr<RecastMesh> getMesh();
|
std::shared_ptr<RecastMesh> getMesh();
|
||||||
|
|
||||||
|
bool isEmpty() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RecastMeshManager mImpl;
|
RecastMeshManager mImpl;
|
||||||
std::shared_ptr<RecastMesh> mCached;
|
std::shared_ptr<RecastMesh> mCached;
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace DetourNavigator
|
||||||
|
|
||||||
template <class Callback>
|
template <class Callback>
|
||||||
void getTilesPositions(const osg::Vec3f& aabbMin, const osg::Vec3f& aabbMax,
|
void getTilesPositions(const osg::Vec3f& aabbMin, const osg::Vec3f& aabbMax,
|
||||||
const Settings& settings, Callback&& callback)
|
const Settings& settings, Callback&& callback)
|
||||||
{
|
{
|
||||||
auto min = toNavMeshCoordinates(settings, aabbMin);
|
auto min = toNavMeshCoordinates(settings, aabbMin);
|
||||||
auto max = toNavMeshCoordinates(settings, aabbMax);
|
auto max = toNavMeshCoordinates(settings, aabbMax);
|
||||||
|
@ -42,7 +42,7 @@ namespace DetourNavigator
|
||||||
|
|
||||||
template <class Callback>
|
template <class Callback>
|
||||||
void getTilesPositions(const btCollisionShape& shape, const btTransform& transform,
|
void getTilesPositions(const btCollisionShape& shape, const btTransform& transform,
|
||||||
const Settings& settings, Callback&& callback)
|
const Settings& settings, Callback&& callback)
|
||||||
{
|
{
|
||||||
btVector3 aabbMin;
|
btVector3 aabbMin;
|
||||||
btVector3 aabbMax;
|
btVector3 aabbMax;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
#include "settingsutils.hpp"
|
#include "settingsutils.hpp"
|
||||||
#include "sharednavmesh.hpp"
|
#include "sharednavmesh.hpp"
|
||||||
|
#include "settingsutils.hpp"
|
||||||
|
|
||||||
#include <DetourNavMesh.h>
|
#include <DetourNavMesh.h>
|
||||||
#include <DetourNavMeshBuilder.h>
|
#include <DetourNavMeshBuilder.h>
|
||||||
|
@ -269,8 +270,9 @@ namespace DetourNavigator
|
||||||
return navMesh;
|
return navMesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateNavMeshStatus updateNavMesh(const osg::Vec3f& agentHalfExtents, const RecastMesh& recastMesh,
|
UpdateNavMeshStatus updateNavMesh(const osg::Vec3f& agentHalfExtents,
|
||||||
const TilePosition& changedTile, const Settings& settings, NavMeshCacheItem& navMeshCacheItem)
|
const RecastMesh* recastMesh, const TilePosition& changedTile, const Settings& settings,
|
||||||
|
NavMeshCacheItem& navMeshCacheItem)
|
||||||
{
|
{
|
||||||
log("update NavMesh with mutiple tiles:",
|
log("update NavMesh with mutiple tiles:",
|
||||||
" agentHeight=", std::setprecision(std::numeric_limits<float>::max_exponent10),
|
" agentHeight=", std::setprecision(std::numeric_limits<float>::max_exponent10),
|
||||||
|
@ -298,8 +300,14 @@ namespace DetourNavigator
|
||||||
|
|
||||||
incRev.mNavMeshChanged = removed;
|
incRev.mNavMeshChanged = removed;
|
||||||
|
|
||||||
const auto& boundsMin = recastMesh.getBoundsMin();
|
if (!recastMesh)
|
||||||
const auto& boundsMax = recastMesh.getBoundsMax();
|
{
|
||||||
|
log("ignore add tile: recastMesh is null");
|
||||||
|
return makeUpdateNavMeshStatus(removed, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& boundsMin = recastMesh->getBoundsMin();
|
||||||
|
const auto& boundsMax = recastMesh->getBoundsMax();
|
||||||
|
|
||||||
if (boundsMin == boundsMax)
|
if (boundsMin == boundsMax)
|
||||||
{
|
{
|
||||||
|
@ -311,7 +319,7 @@ namespace DetourNavigator
|
||||||
const osg::Vec3f tileBorderMin(tileBounds.mMin.x(), boundsMin.y() - 1, tileBounds.mMin.y());
|
const osg::Vec3f tileBorderMin(tileBounds.mMin.x(), boundsMin.y() - 1, tileBounds.mMin.y());
|
||||||
const osg::Vec3f tileBorderMax(tileBounds.mMax.x(), boundsMax.y() + 1, tileBounds.mMax.y());
|
const osg::Vec3f tileBorderMax(tileBounds.mMax.x(), boundsMax.y() + 1, tileBounds.mMax.y());
|
||||||
|
|
||||||
auto navMeshData = makeNavMeshTileData(agentHalfExtents, recastMesh, x, y,
|
auto navMeshData = makeNavMeshTileData(agentHalfExtents, *recastMesh, x, y,
|
||||||
tileBorderMin, tileBorderMax, settings);
|
tileBorderMin, tileBorderMax, settings);
|
||||||
|
|
||||||
if (!navMeshData.mValue)
|
if (!navMeshData.mValue)
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
#include "navmeshcacheitem.hpp"
|
#include "navmeshcacheitem.hpp"
|
||||||
#include "tileposition.hpp"
|
#include "tileposition.hpp"
|
||||||
|
#include "tilebounds.hpp"
|
||||||
|
|
||||||
#include <osg/Vec3f>
|
#include <osg/Vec3f>
|
||||||
|
|
||||||
|
@ -30,8 +31,8 @@ namespace DetourNavigator
|
||||||
|
|
||||||
NavMeshPtr makeEmptyNavMesh(const Settings& settings);
|
NavMeshPtr makeEmptyNavMesh(const Settings& settings);
|
||||||
|
|
||||||
UpdateNavMeshStatus updateNavMesh(const osg::Vec3f& agentHalfExtents, const RecastMesh& recastMesh,
|
UpdateNavMeshStatus updateNavMesh(const osg::Vec3f& agentHalfExtents, const RecastMesh* recastMesh,
|
||||||
const TilePosition& changedTile, const Settings& settings, NavMeshCacheItem& navMeshCacheItem);
|
const TilePosition& changedTile, const Settings& settings, NavMeshCacheItem& navMeshCacheItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,11 +11,10 @@ namespace DetourNavigator
|
||||||
{
|
{
|
||||||
SharedNavMesh mValue;
|
SharedNavMesh mValue;
|
||||||
std::size_t mGeneration;
|
std::size_t mGeneration;
|
||||||
std::size_t mRecastMeshRevision;
|
|
||||||
std::atomic_size_t mNavMeshRevision;
|
std::atomic_size_t mNavMeshRevision;
|
||||||
|
|
||||||
NavMeshCacheItem(const NavMeshPtr& value, std::size_t generation, std::size_t revision)
|
NavMeshCacheItem(const NavMeshPtr& value, std::size_t generation)
|
||||||
: mValue(value), mGeneration(generation), mRecastMeshRevision(revision), mNavMeshRevision(0) {}
|
: mValue(value), mGeneration(generation), mNavMeshRevision(0) {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "exceptions.hpp"
|
#include "exceptions.hpp"
|
||||||
#include "gettilespositions.hpp"
|
#include "gettilespositions.hpp"
|
||||||
#include "makenavmesh.hpp"
|
#include "makenavmesh.hpp"
|
||||||
|
#include "navmeshcacheitem.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
#include "sharednavmesh.hpp"
|
#include "sharednavmesh.hpp"
|
||||||
|
|
||||||
|
@ -17,14 +18,14 @@ namespace DetourNavigator
|
||||||
NavMeshManager::NavMeshManager(const Settings& settings)
|
NavMeshManager::NavMeshManager(const Settings& settings)
|
||||||
: mSettings(settings)
|
: mSettings(settings)
|
||||||
, mRecastMeshManager(settings)
|
, mRecastMeshManager(settings)
|
||||||
, mAsyncNavMeshUpdater(settings)
|
, mAsyncNavMeshUpdater(settings, mRecastMeshManager)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool NavMeshManager::addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform)
|
bool NavMeshManager::addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform)
|
||||||
{
|
{
|
||||||
if (!mRecastMeshManager.addObject(id, shape, transform))
|
if (!mRecastMeshManager.addObject(id, shape, transform))
|
||||||
return false;
|
return false;
|
||||||
++mRevision;
|
|
||||||
addChangedTiles(shape, transform);
|
addChangedTiles(shape, transform);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -34,7 +35,6 @@ namespace DetourNavigator
|
||||||
const auto object = mRecastMeshManager.removeObject(id);
|
const auto object = mRecastMeshManager.removeObject(id);
|
||||||
if (!object)
|
if (!object)
|
||||||
return false;
|
return false;
|
||||||
++mRevision;
|
|
||||||
addChangedTiles(*object->mShape, object->mTransform);
|
addChangedTiles(*object->mShape, object->mTransform);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -45,8 +45,7 @@ namespace DetourNavigator
|
||||||
if (cached != mCache.end())
|
if (cached != mCache.end())
|
||||||
return;
|
return;
|
||||||
mCache.insert(std::make_pair(agentHalfExtents,
|
mCache.insert(std::make_pair(agentHalfExtents,
|
||||||
std::make_shared<NavMeshCacheItem>(makeEmptyNavMesh(mSettings), ++mGenerationCounter, mRevision))
|
std::make_shared<NavMeshCacheItem>(makeEmptyNavMesh(mSettings), ++mGenerationCounter)));
|
||||||
);
|
|
||||||
log("cache add for agent=", agentHalfExtents);
|
log("cache add for agent=", agentHalfExtents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,18 +57,15 @@ namespace DetourNavigator
|
||||||
void NavMeshManager::update(osg::Vec3f playerPosition, const osg::Vec3f& agentHalfExtents)
|
void NavMeshManager::update(osg::Vec3f playerPosition, const osg::Vec3f& agentHalfExtents)
|
||||||
{
|
{
|
||||||
const auto& cached = getCached(agentHalfExtents);
|
const auto& cached = getCached(agentHalfExtents);
|
||||||
if (cached->mRecastMeshRevision >= mRevision)
|
|
||||||
return;
|
|
||||||
cached->mRecastMeshRevision = mRevision;
|
|
||||||
const auto changedTiles = mChangedTiles.find(agentHalfExtents);
|
const auto changedTiles = mChangedTiles.find(agentHalfExtents);
|
||||||
if (changedTiles != mChangedTiles.end())
|
if (changedTiles != mChangedTiles.end())
|
||||||
{
|
{
|
||||||
playerPosition *= mSettings.mRecastScaleFactor;
|
playerPosition *= mSettings.mRecastScaleFactor;
|
||||||
std::swap(playerPosition.y(), playerPosition.z());
|
std::swap(playerPosition.y(), playerPosition.z());
|
||||||
mAsyncNavMeshUpdater.post(agentHalfExtents, mRecastMeshManager.getMesh(), cached,
|
mAsyncNavMeshUpdater.post(agentHalfExtents, cached, getTilePosition(mSettings, playerPosition),
|
||||||
getTilePosition(mSettings, playerPosition), changedTiles->second);
|
changedTiles->second);
|
||||||
|
log("cache update posted for agent=", agentHalfExtents, " changedTiles=", changedTiles->second.size());
|
||||||
mChangedTiles.erase(changedTiles);
|
mChangedTiles.erase(changedTiles);
|
||||||
log("cache update posted for agent=", agentHalfExtents);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,9 +40,8 @@ namespace DetourNavigator
|
||||||
std::map<osg::Vec3f, std::shared_ptr<NavMeshCacheItem>> getNavMeshes() const;
|
std::map<osg::Vec3f, std::shared_ptr<NavMeshCacheItem>> getNavMeshes() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::size_t mRevision = 0;
|
|
||||||
const Settings& mSettings;
|
const Settings& mSettings;
|
||||||
CachedRecastMeshManager mRecastMeshManager;
|
TileCachedRecastMeshManager mRecastMeshManager;
|
||||||
std::map<osg::Vec3f, std::shared_ptr<NavMeshCacheItem>> mCache;
|
std::map<osg::Vec3f, std::shared_ptr<NavMeshCacheItem>> mCache;
|
||||||
std::map<osg::Vec3f, std::set<TilePosition>> mChangedTiles;
|
std::map<osg::Vec3f, std::set<TilePosition>> mChangedTiles;
|
||||||
AsyncNavMeshUpdater mAsyncNavMeshUpdater;
|
AsyncNavMeshUpdater mAsyncNavMeshUpdater;
|
||||||
|
|
|
@ -27,9 +27,13 @@ namespace DetourNavigator
|
||||||
{
|
{
|
||||||
using BulletHelpers::makeProcessTriangleCallback;
|
using BulletHelpers::makeProcessTriangleCallback;
|
||||||
|
|
||||||
RecastMeshBuilder::RecastMeshBuilder(const Settings& settings)
|
RecastMeshBuilder::RecastMeshBuilder(const Settings& settings, const TileBounds& bounds)
|
||||||
: mSettings(settings)
|
: mSettings(settings)
|
||||||
{}
|
, mBounds(bounds)
|
||||||
|
{
|
||||||
|
mBounds.mMin /= mSettings.get().mRecastScaleFactor;
|
||||||
|
mBounds.mMax /= mSettings.get().mRecastScaleFactor;
|
||||||
|
}
|
||||||
|
|
||||||
void RecastMeshBuilder::addObject(const btCollisionShape& shape, const btTransform& transform)
|
void RecastMeshBuilder::addObject(const btCollisionShape& shape, const btTransform& transform)
|
||||||
{
|
{
|
||||||
|
@ -54,7 +58,7 @@ namespace DetourNavigator
|
||||||
|
|
||||||
void RecastMeshBuilder::addObject(const btConcaveShape& shape, const btTransform& transform)
|
void RecastMeshBuilder::addObject(const btConcaveShape& shape, const btTransform& transform)
|
||||||
{
|
{
|
||||||
return addObject(shape, makeProcessTriangleCallback([&] (btVector3* triangle, int, int)
|
return addObject(shape, transform, makeProcessTriangleCallback([&] (btVector3* triangle, int, int)
|
||||||
{
|
{
|
||||||
for (std::size_t i = 3; i > 0; --i)
|
for (std::size_t i = 3; i > 0; --i)
|
||||||
addTriangleVertex(transform(triangle[i - 1]));
|
addTriangleVertex(transform(triangle[i - 1]));
|
||||||
|
@ -63,7 +67,7 @@ namespace DetourNavigator
|
||||||
|
|
||||||
void RecastMeshBuilder::addObject(const btHeightfieldTerrainShape& shape, const btTransform& transform)
|
void RecastMeshBuilder::addObject(const btHeightfieldTerrainShape& shape, const btTransform& transform)
|
||||||
{
|
{
|
||||||
return addObject(shape, makeProcessTriangleCallback([&] (btVector3* triangle, int, int)
|
return addObject(shape, transform, makeProcessTriangleCallback([&] (btVector3* triangle, int, int)
|
||||||
{
|
{
|
||||||
for (std::size_t i = 0; i < 3; ++i)
|
for (std::size_t i = 0; i < 3; ++i)
|
||||||
addTriangleVertex(transform(triangle[i]));
|
addTriangleVertex(transform(triangle[i]));
|
||||||
|
@ -111,11 +115,29 @@ namespace DetourNavigator
|
||||||
mVertices.clear();
|
mVertices.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecastMeshBuilder::addObject(const btConcaveShape& shape, btTriangleCallback&& callback)
|
void RecastMeshBuilder::addObject(const btConcaveShape& shape, const btTransform& transform,
|
||||||
|
btTriangleCallback&& callback)
|
||||||
{
|
{
|
||||||
btVector3 aabbMin;
|
btVector3 aabbMin;
|
||||||
btVector3 aabbMax;
|
btVector3 aabbMax;
|
||||||
shape.getAabb(btTransform::getIdentity(), aabbMin, aabbMax);
|
shape.getAabb(btTransform::getIdentity(), aabbMin, aabbMax);
|
||||||
|
const btVector3 boundsMinMin(mBounds.mMin.x(), mBounds.mMin.y(), 0);
|
||||||
|
const btVector3 boundsMinMax(mBounds.mMin.x(), mBounds.mMax.y(), 0);
|
||||||
|
const btVector3 boundsMaxMin(mBounds.mMax.x(), mBounds.mMin.y(), 0);
|
||||||
|
const btVector3 boundsMaxMax(mBounds.mMax.x(), mBounds.mMax.y(), 0);
|
||||||
|
const auto inversedTransform = transform.inverse();
|
||||||
|
const auto localBoundsMinMin = inversedTransform(boundsMinMin);
|
||||||
|
const auto localBoundsMinMax = inversedTransform(boundsMinMax);
|
||||||
|
const auto localBoundsMaxMin = inversedTransform(boundsMaxMin);
|
||||||
|
const auto localBoundsMaxMax = inversedTransform(boundsMaxMax);
|
||||||
|
aabbMin.setX(std::min({localBoundsMinMin.x(), localBoundsMinMax.x(),
|
||||||
|
localBoundsMaxMin.x(), localBoundsMaxMax.x()}));
|
||||||
|
aabbMin.setY(std::min({localBoundsMinMin.y(), localBoundsMinMax.y(),
|
||||||
|
localBoundsMaxMin.y(), localBoundsMaxMax.y()}));
|
||||||
|
aabbMax.setX(std::max({localBoundsMinMin.x(), localBoundsMinMax.x(),
|
||||||
|
localBoundsMaxMin.x(), localBoundsMaxMax.x()}));
|
||||||
|
aabbMax.setY(std::max({localBoundsMinMin.y(), localBoundsMinMax.y(),
|
||||||
|
localBoundsMaxMin.y(), localBoundsMaxMax.y()}));
|
||||||
shape.processAllTriangles(&callback, aabbMin, aabbMax);
|
shape.processAllTriangles(&callback, aabbMin, aabbMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_RECASTMESHBUILDER_H
|
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_RECASTMESHBUILDER_H
|
||||||
|
|
||||||
#include "recastmesh.hpp"
|
#include "recastmesh.hpp"
|
||||||
|
#include "tilebounds.hpp"
|
||||||
|
|
||||||
class btBoxShape;
|
class btBoxShape;
|
||||||
class btCollisionShape;
|
class btCollisionShape;
|
||||||
|
@ -17,7 +18,7 @@ namespace DetourNavigator
|
||||||
class RecastMeshBuilder
|
class RecastMeshBuilder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RecastMeshBuilder(const Settings& settings);
|
RecastMeshBuilder(const Settings& settings, const TileBounds& bounds);
|
||||||
|
|
||||||
void addObject(const btCollisionShape& shape, const btTransform& transform);
|
void addObject(const btCollisionShape& shape, const btTransform& transform);
|
||||||
|
|
||||||
|
@ -35,10 +36,11 @@ namespace DetourNavigator
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::reference_wrapper<const Settings> mSettings;
|
std::reference_wrapper<const Settings> mSettings;
|
||||||
|
TileBounds mBounds;
|
||||||
std::vector<int> mIndices;
|
std::vector<int> mIndices;
|
||||||
std::vector<float> mVertices;
|
std::vector<float> mVertices;
|
||||||
|
|
||||||
void addObject(const btConcaveShape& shape, btTriangleCallback&& callback);
|
void addObject(const btConcaveShape& shape, const btTransform& transform, btTriangleCallback&& callback);
|
||||||
|
|
||||||
void addTriangleVertex(const btVector3& worldPosition);
|
void addTriangleVertex(const btVector3& worldPosition);
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
RecastMeshManager::RecastMeshManager(const Settings& settings)
|
RecastMeshManager::RecastMeshManager(const Settings& settings, const TileBounds& bounds)
|
||||||
: mShouldRebuild(false)
|
: mShouldRebuild(false)
|
||||||
, mMeshBuilder(settings)
|
, mMeshBuilder(settings, bounds)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,11 @@ namespace DetourNavigator
|
||||||
return mMeshBuilder.create();
|
return mMeshBuilder.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RecastMeshManager::isEmpty() const
|
||||||
|
{
|
||||||
|
return mObjects.empty();
|
||||||
|
}
|
||||||
|
|
||||||
void RecastMeshManager::rebuild()
|
void RecastMeshManager::rebuild()
|
||||||
{
|
{
|
||||||
if (!mShouldRebuild)
|
if (!mShouldRebuild)
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace DetourNavigator
|
||||||
btTransform mTransform;
|
btTransform mTransform;
|
||||||
};
|
};
|
||||||
|
|
||||||
RecastMeshManager(const Settings& settings);
|
RecastMeshManager(const Settings& settings, const TileBounds& bounds);
|
||||||
|
|
||||||
bool addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform);
|
bool addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform);
|
||||||
|
|
||||||
|
@ -30,6 +30,8 @@ namespace DetourNavigator
|
||||||
|
|
||||||
std::shared_ptr<RecastMesh> getMesh();
|
std::shared_ptr<RecastMesh> getMesh();
|
||||||
|
|
||||||
|
bool isEmpty() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mShouldRebuild;
|
bool mShouldRebuild;
|
||||||
RecastMeshBuilder mMeshBuilder;
|
RecastMeshBuilder mMeshBuilder;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_SETTINGSUTILS_H
|
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_SETTINGSUTILS_H
|
||||||
|
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
#include "tilebounds.hpp"
|
||||||
#include "tileposition.hpp"
|
#include "tileposition.hpp"
|
||||||
#include "tilebounds.hpp"
|
#include "tilebounds.hpp"
|
||||||
|
|
||||||
|
|
71
components/detournavigator/tilecachedrecastmeshmanager.cpp
Normal file
71
components/detournavigator/tilecachedrecastmeshmanager.cpp
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
#include "tilecachedrecastmeshmanager.hpp"
|
||||||
|
#include "makenavmesh.hpp"
|
||||||
|
#include "gettilespositions.hpp"
|
||||||
|
#include "settingsutils.hpp"
|
||||||
|
|
||||||
|
namespace DetourNavigator
|
||||||
|
{
|
||||||
|
TileCachedRecastMeshManager::TileCachedRecastMeshManager(const Settings& settings)
|
||||||
|
: mSettings(settings)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TileCachedRecastMeshManager::addObject(std::size_t id, const btCollisionShape& shape,
|
||||||
|
const btTransform& transform)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
auto& tilesPositions = mObjectsTilesPositions[id];
|
||||||
|
const auto border = getBorderSize(mSettings);
|
||||||
|
getTilesPositions(shape, transform, mSettings, [&] (const TilePosition& tilePosition)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(mTilesMutex);
|
||||||
|
auto tile = mTiles.find(tilePosition);
|
||||||
|
if (tile == mTiles.end())
|
||||||
|
{
|
||||||
|
auto tileBounds = makeTileBounds(mSettings, tilePosition);
|
||||||
|
tileBounds.mMin -= osg::Vec2f(border, border);
|
||||||
|
tileBounds.mMax += osg::Vec2f(border, border);
|
||||||
|
tile = mTiles.insert(std::make_pair(tilePosition,
|
||||||
|
CachedRecastMeshManager(mSettings, tileBounds))).first;
|
||||||
|
}
|
||||||
|
if (tile->second.addObject(id, shape, transform))
|
||||||
|
{
|
||||||
|
lock.unlock();
|
||||||
|
tilesPositions.push_back(tilePosition);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::optional<RecastMeshManager::Object> TileCachedRecastMeshManager::removeObject(std::size_t id)
|
||||||
|
{
|
||||||
|
const auto object = mObjectsTilesPositions.find(id);
|
||||||
|
if (object == mObjectsTilesPositions.end())
|
||||||
|
return boost::none;
|
||||||
|
boost::optional<RecastMeshManager::Object> result;
|
||||||
|
for (const auto& tilePosition : object->second)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(mTilesMutex);
|
||||||
|
const auto tile = mTiles.find(tilePosition);
|
||||||
|
if (tile == mTiles.end())
|
||||||
|
continue;
|
||||||
|
const auto tileResult = tile->second.removeObject(id);
|
||||||
|
if (tile->second.isEmpty())
|
||||||
|
mTiles.erase(tile);
|
||||||
|
lock.unlock();
|
||||||
|
if (tileResult && !result)
|
||||||
|
result = tileResult;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<RecastMesh> TileCachedRecastMeshManager::getMesh(const TilePosition& tilePosition)
|
||||||
|
{
|
||||||
|
const std::lock_guard<std::mutex> lock(mTilesMutex);
|
||||||
|
const auto it = mTiles.find(tilePosition);
|
||||||
|
if (it == mTiles.end())
|
||||||
|
return nullptr;
|
||||||
|
return it->second.getMesh();
|
||||||
|
}
|
||||||
|
}
|
31
components/detournavigator/tilecachedrecastmeshmanager.hpp
Normal file
31
components/detournavigator/tilecachedrecastmeshmanager.hpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_TILECACHEDRECASTMESHMANAGER_H
|
||||||
|
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_TILECACHEDRECASTMESHMANAGER_H
|
||||||
|
|
||||||
|
#include "cachedrecastmeshmanager.hpp"
|
||||||
|
#include "tileposition.hpp"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
namespace DetourNavigator
|
||||||
|
{
|
||||||
|
class TileCachedRecastMeshManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TileCachedRecastMeshManager(const Settings& settings);
|
||||||
|
|
||||||
|
bool addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform);
|
||||||
|
|
||||||
|
boost::optional<RecastMeshManager::Object> removeObject(std::size_t id);
|
||||||
|
|
||||||
|
std::shared_ptr<RecastMesh> getMesh(const TilePosition& tilePosition);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Settings& mSettings;
|
||||||
|
std::mutex mTilesMutex;
|
||||||
|
std::map<TilePosition, CachedRecastMeshManager> mTiles;
|
||||||
|
std::unordered_map<std::size_t, std::vector<TilePosition>> mObjectsTilesPositions;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue