mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-24 11:41:33 +00:00
Merge branch 'navigator_fixes' into 'master'
Navigator fixes See merge request OpenMW/openmw!2373
This commit is contained in:
commit
c4deacbff8
18 changed files with 97 additions and 121 deletions
|
@ -140,12 +140,14 @@ namespace
|
|||
const CollisionShapeType agentShapeType = CollisionShapeType::Aabb;
|
||||
const osg::Vec3f agentHalfExtents = generateAgentHalfExtents(0.5, 1.5, random);
|
||||
const TilePosition tilePosition = generateVec2i(10000, random);
|
||||
const std::size_t generation = std::uniform_int_distribution<std::size_t>(0, 100)(random);
|
||||
const std::size_t revision = std::uniform_int_distribution<std::size_t>(0, 10000)(random);
|
||||
const Version version {
|
||||
.mGeneration = std::uniform_int_distribution<std::size_t>(0, 100)(random),
|
||||
.mRevision = std::uniform_int_distribution<std::size_t>(0, 10000)(random),
|
||||
};
|
||||
Mesh mesh = generateMesh(triangles, random);
|
||||
std::vector<CellWater> water;
|
||||
generateWater(std::back_inserter(water), 1, random);
|
||||
RecastMesh recastMesh(generation, revision, std::move(mesh), std::move(water),
|
||||
RecastMesh recastMesh(version, std::move(mesh), std::move(water),
|
||||
{generateHeightfield(random)}, {generateFlatHeightfield(random)}, {});
|
||||
return Key {AgentBounds {agentShapeType, agentHalfExtents}, tilePosition, std::move(recastMesh)};
|
||||
}
|
||||
|
|
|
@ -53,8 +53,7 @@ namespace MWRender
|
|||
continue;
|
||||
}
|
||||
|
||||
if (it->second.mGeneration != tile->second->getGeneration()
|
||||
|| it->second.mRevision != tile->second->getRevision())
|
||||
if (it->second.mVersion != tile->second->getVersion())
|
||||
{
|
||||
const auto group = SceneUtil::createRecastMeshGroup(*tile->second, settings.mRecast);
|
||||
MWBase::Environment::get().getResourceSystem()->getSceneManager()->recreateShaders(group, "debug");
|
||||
|
@ -62,8 +61,7 @@ namespace MWRender
|
|||
mRootNode->removeChild(it->second.mValue);
|
||||
mRootNode->addChild(group);
|
||||
it->second.mValue = group;
|
||||
it->second.mGeneration = tile->second->getGeneration();
|
||||
it->second.mRevision = tile->second->getRevision();
|
||||
it->second.mVersion = tile->second->getVersion();
|
||||
}
|
||||
|
||||
++it;
|
||||
|
@ -76,7 +74,7 @@ namespace MWRender
|
|||
const auto group = SceneUtil::createRecastMeshGroup(*tile.second, settings.mRecast);
|
||||
MWBase::Environment::get().getResourceSystem()->getSceneManager()->recreateShaders(group, "debug");
|
||||
group->setNodeMask(Mask_Debug);
|
||||
mGroups.emplace(tile.first, Group {tile.second->getGeneration(), tile.second->getRevision(), group});
|
||||
mGroups.emplace(tile.first, Group {tile.second->getVersion(), group});
|
||||
mRootNode->addChild(group);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define OPENMW_MWRENDER_RECASTMESH_H
|
||||
|
||||
#include <components/detournavigator/recastmeshtiles.hpp>
|
||||
#include <components/detournavigator/version.hpp>
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
|
@ -44,8 +45,7 @@ namespace MWRender
|
|||
private:
|
||||
struct Group
|
||||
{
|
||||
std::size_t mGeneration;
|
||||
std::size_t mRevision;
|
||||
DetourNavigator::Version mVersion;
|
||||
osg::ref_ptr<osg::Group> mValue;
|
||||
};
|
||||
|
||||
|
|
|
@ -391,8 +391,6 @@ namespace MWWorld
|
|||
const int cellX = cell->getCell()->getGridX();
|
||||
const int cellY = cell->getCell()->getGridY();
|
||||
|
||||
mNavigator.setWorldspace(cell->getCell()->mCellId.mWorldspace);
|
||||
|
||||
if (cell->getCell()->isExterior())
|
||||
{
|
||||
osg::ref_ptr<const ESMTerrain::LandObject> land = mRendering.getLandManager()->getLand(cellX, cellY);
|
||||
|
@ -541,6 +539,7 @@ namespace MWWorld
|
|||
unloadCell (cell);
|
||||
}
|
||||
|
||||
mNavigator.setWorldspace(mWorld.getExterior(playerCellX, playerCellY)->getCell()->mCellId.mWorldspace);
|
||||
mNavigator.updateBounds(pos);
|
||||
|
||||
mCurrentGridCenter = osg::Vec2i(playerCellX, playerCellY);
|
||||
|
@ -659,7 +658,10 @@ namespace MWWorld
|
|||
loadingListener->setLabel("Testing exterior cells ("+std::to_string(i)+"/"+std::to_string(cells.getExtSize())+")...");
|
||||
|
||||
CellStore *cell = mWorld.getExterior(it->mData.mX, it->mData.mY);
|
||||
loadCell(cell, nullptr, false, osg::Vec3f(it->mData.mX + 0.5f, it->mData.mY + 0.5f, 0) * Constants::CellSizeInUnits);
|
||||
mNavigator.setWorldspace(cell->getCell()->mCellId.mWorldspace);
|
||||
const osg::Vec3f position = osg::Vec3f(it->mData.mX + 0.5f, it->mData.mY + 0.5f, 0) * Constants::CellSizeInUnits;
|
||||
mNavigator.updateBounds(position);
|
||||
loadCell(cell, nullptr, false, position);
|
||||
|
||||
auto iter = mActiveCells.begin();
|
||||
while (iter != mActiveCells.end())
|
||||
|
@ -704,8 +706,10 @@ namespace MWWorld
|
|||
loadingListener->setLabel("Testing interior cells ("+std::to_string(i)+"/"+std::to_string(cells.getIntSize())+")...");
|
||||
|
||||
CellStore *cell = mWorld.getInterior(it->mName);
|
||||
mNavigator.setWorldspace(cell->getCell()->mCellId.mWorldspace);
|
||||
ESM::Position position;
|
||||
mWorld.findInteriorPosition(it->mName, position);
|
||||
mNavigator.updateBounds(position.asVec3());
|
||||
loadCell(cell, nullptr, false, position.asVec3());
|
||||
|
||||
auto iter = mActiveCells.begin();
|
||||
|
@ -844,6 +848,7 @@ namespace MWWorld
|
|||
|
||||
loadingListener->setProgressRange(cell->count());
|
||||
|
||||
mNavigator.setWorldspace(cell->getCell()->mCellId.mWorldspace);
|
||||
mNavigator.updateBounds(position.asVec3());
|
||||
|
||||
// Load cell.
|
||||
|
|
|
@ -190,6 +190,9 @@ namespace
|
|||
|
||||
TEST_F(DetourNavigatorNavigatorTest, add_object_should_change_navmesh)
|
||||
{
|
||||
mSettings.mWaitUntilMinDistanceToPlayer = 0;
|
||||
mNavigator.reset(new NavigatorImpl(mSettings, std::make_unique<NavMeshDb>(":memory:", std::numeric_limits<std::uint64_t>::max())));
|
||||
|
||||
const std::array<float, 5 * 5> heightfieldData {{
|
||||
0, 0, 0, 0, 0,
|
||||
0, -25, -25, -25, -25,
|
||||
|
|
|
@ -97,14 +97,13 @@ namespace
|
|||
{
|
||||
const AgentBounds mAgentBounds {CollisionShapeType::Aabb, {1, 2, 3}};
|
||||
const TilePosition mTilePosition {0, 0};
|
||||
const std::size_t mGeneration = 0;
|
||||
const std::size_t mRevision = 0;
|
||||
const Version mVersion {0, 0};
|
||||
const Mesh mMesh {makeMesh()};
|
||||
const std::vector<CellWater> mWater {};
|
||||
const std::vector<Heightfield> mHeightfields {};
|
||||
const std::vector<FlatHeightfield> mFlatHeightfields {};
|
||||
const std::vector<MeshSource> mSources {};
|
||||
const RecastMesh mRecastMesh {mGeneration, mRevision, mMesh, mWater, mHeightfields, mFlatHeightfields, mSources};
|
||||
const RecastMesh mRecastMesh {mVersion, mMesh, mWater, mHeightfields, mFlatHeightfields, mSources};
|
||||
std::unique_ptr<PreparedNavMeshData> mPreparedNavMeshData {makePeparedNavMeshData(3)};
|
||||
|
||||
const std::size_t mRecastMeshSize = sizeof(mRecastMesh) + getSize(mRecastMesh);
|
||||
|
@ -192,7 +191,7 @@ namespace
|
|||
const std::size_t maxSize = 1;
|
||||
NavMeshTilesCache cache(maxSize);
|
||||
const std::vector<CellWater> water(1, CellWater {osg::Vec2i(), Water {1, 0.0f}});
|
||||
const RecastMesh unexistentRecastMesh(mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields, mSources);
|
||||
const RecastMesh unexistentRecastMesh(mVersion, mMesh, water, mHeightfields, mFlatHeightfields, mSources);
|
||||
|
||||
cache.set(mAgentBounds, mTilePosition, mRecastMesh, std::move(mPreparedNavMeshData));
|
||||
EXPECT_FALSE(cache.get(mAgentBounds, mTilePosition, unexistentRecastMesh));
|
||||
|
@ -204,7 +203,7 @@ namespace
|
|||
NavMeshTilesCache cache(maxSize);
|
||||
|
||||
const std::vector<CellWater> water(1, CellWater {osg::Vec2i(), Water {1, 0.0f}});
|
||||
const RecastMesh anotherRecastMesh(mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields, mSources);
|
||||
const RecastMesh anotherRecastMesh(mVersion, mMesh, water, mHeightfields, mFlatHeightfields, mSources);
|
||||
auto anotherPreparedNavMeshData = makePeparedNavMeshData(3);
|
||||
const auto copy = clone(*anotherPreparedNavMeshData);
|
||||
|
||||
|
@ -222,7 +221,7 @@ namespace
|
|||
NavMeshTilesCache cache(maxSize);
|
||||
|
||||
const std::vector<CellWater> water(1, CellWater {osg::Vec2i(), Water {1, 0.0f}});
|
||||
const RecastMesh anotherRecastMesh(mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields, mSources);
|
||||
const RecastMesh anotherRecastMesh(mVersion, mMesh, water, mHeightfields, mFlatHeightfields, mSources);
|
||||
auto anotherPreparedNavMeshData = makePeparedNavMeshData(3);
|
||||
|
||||
const auto value = cache.set(mAgentBounds, mTilePosition, mRecastMesh,
|
||||
|
@ -238,12 +237,12 @@ namespace
|
|||
const auto copy = clone(*mPreparedNavMeshData);
|
||||
|
||||
const std::vector<CellWater> leastRecentlySetWater(1, CellWater {osg::Vec2i(), Water {1, 0.0f}});
|
||||
const RecastMesh leastRecentlySetRecastMesh(mGeneration, mRevision, mMesh, leastRecentlySetWater,
|
||||
const RecastMesh leastRecentlySetRecastMesh(mVersion, mMesh, leastRecentlySetWater,
|
||||
mHeightfields, mFlatHeightfields, mSources);
|
||||
auto leastRecentlySetData = makePeparedNavMeshData(3);
|
||||
|
||||
const std::vector<CellWater> mostRecentlySetWater(1, CellWater {osg::Vec2i(), Water {2, 0.0f}});
|
||||
const RecastMesh mostRecentlySetRecastMesh(mGeneration, mRevision, mMesh, mostRecentlySetWater,
|
||||
const RecastMesh mostRecentlySetRecastMesh(mVersion, mMesh, mostRecentlySetWater,
|
||||
mHeightfields, mFlatHeightfields, mSources);
|
||||
auto mostRecentlySetData = makePeparedNavMeshData(3);
|
||||
|
||||
|
@ -266,13 +265,13 @@ namespace
|
|||
NavMeshTilesCache cache(maxSize);
|
||||
|
||||
const std::vector<CellWater> leastRecentlyUsedWater(1, CellWater {osg::Vec2i(), Water {1, 0.0f}});
|
||||
const RecastMesh leastRecentlyUsedRecastMesh(mGeneration, mRevision, mMesh, leastRecentlyUsedWater,
|
||||
const RecastMesh leastRecentlyUsedRecastMesh(mVersion, mMesh, leastRecentlyUsedWater,
|
||||
mHeightfields, mFlatHeightfields, mSources);
|
||||
auto leastRecentlyUsedData = makePeparedNavMeshData(3);
|
||||
const auto leastRecentlyUsedCopy = clone(*leastRecentlyUsedData);
|
||||
|
||||
const std::vector<CellWater> mostRecentlyUsedWater(1, CellWater {osg::Vec2i(), Water {2, 0.0f}});
|
||||
const RecastMesh mostRecentlyUsedRecastMesh(mGeneration, mRevision, mMesh, mostRecentlyUsedWater,
|
||||
const RecastMesh mostRecentlyUsedRecastMesh(mVersion, mMesh, mostRecentlyUsedWater,
|
||||
mHeightfields, mFlatHeightfields, mSources);
|
||||
auto mostRecentlyUsedData = makePeparedNavMeshData(3);
|
||||
const auto mostRecentlyUsedCopy = clone(*mostRecentlyUsedData);
|
||||
|
@ -307,7 +306,7 @@ namespace
|
|||
NavMeshTilesCache cache(maxSize);
|
||||
|
||||
const std::vector<CellWater> water(1, CellWater {osg::Vec2i(), Water {1, 0.0f}});
|
||||
const RecastMesh tooLargeRecastMesh(mGeneration, mRevision, mMesh, water,
|
||||
const RecastMesh tooLargeRecastMesh(mVersion, mMesh, water,
|
||||
mHeightfields, mFlatHeightfields, mSources);
|
||||
auto tooLargeData = makePeparedNavMeshData(10);
|
||||
|
||||
|
@ -322,12 +321,12 @@ namespace
|
|||
NavMeshTilesCache cache(maxSize);
|
||||
|
||||
const std::vector<CellWater> anotherWater(1, CellWater {osg::Vec2i(), Water {1, 0.0f}});
|
||||
const RecastMesh anotherRecastMesh(mGeneration, mRevision, mMesh, anotherWater,
|
||||
const RecastMesh anotherRecastMesh(mVersion, mMesh, anotherWater,
|
||||
mHeightfields, mFlatHeightfields, mSources);
|
||||
auto anotherData = makePeparedNavMeshData(3);
|
||||
|
||||
const std::vector<CellWater> tooLargeWater(1, CellWater {osg::Vec2i(), Water {2, 0.0f}});
|
||||
const RecastMesh tooLargeRecastMesh(mGeneration, mRevision, mMesh, tooLargeWater,
|
||||
const RecastMesh tooLargeRecastMesh(mVersion, mMesh, tooLargeWater,
|
||||
mHeightfields, mFlatHeightfields, mSources);
|
||||
auto tooLargeData = makePeparedNavMeshData(10);
|
||||
|
||||
|
@ -348,7 +347,7 @@ namespace
|
|||
NavMeshTilesCache cache(maxSize);
|
||||
|
||||
const std::vector<CellWater> water(1, CellWater {osg::Vec2i(), Water {1, 0.0f}});
|
||||
const RecastMesh anotherRecastMesh(mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields, mSources);
|
||||
const RecastMesh anotherRecastMesh(mVersion, mMesh, water, mHeightfields, mFlatHeightfields, mSources);
|
||||
auto anotherData = makePeparedNavMeshData(3);
|
||||
|
||||
const auto firstCopy = cache.set(mAgentBounds, mTilePosition, mRecastMesh, std::move(mPreparedNavMeshData));
|
||||
|
@ -367,7 +366,7 @@ namespace
|
|||
NavMeshTilesCache cache(maxSize);
|
||||
|
||||
const std::vector<CellWater> water(1, CellWater {osg::Vec2i(), Water {1, 0.0f}});
|
||||
const RecastMesh anotherRecastMesh(mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields, mSources);
|
||||
const RecastMesh anotherRecastMesh(mVersion, mMesh, water, mHeightfields, mFlatHeightfields, mSources);
|
||||
auto anotherData = makePeparedNavMeshData(3);
|
||||
|
||||
cache.set(mAgentBounds, mTilePosition, mRecastMesh, std::move(mPreparedNavMeshData));
|
||||
|
|
|
@ -58,8 +58,7 @@ namespace
|
|||
struct DetourNavigatorRecastMeshBuilderTest : Test
|
||||
{
|
||||
TileBounds mBounds;
|
||||
const std::size_t mGeneration = 0;
|
||||
const std::size_t mRevision = 0;
|
||||
const Version mVersion {0, 0};
|
||||
const osg::ref_ptr<const Resource::BulletShape> mSource {nullptr};
|
||||
const ObjectTransform mObjectTransform {ESM::Position {{0, 0, 0}, {0, 0, 0}}, 0.0f};
|
||||
|
||||
|
@ -75,7 +74,7 @@ namespace
|
|||
TEST_F(DetourNavigatorRecastMeshBuilderTest, create_for_empty_should_return_empty)
|
||||
{
|
||||
RecastMeshBuilder builder(mBounds);
|
||||
const auto recastMesh = std::move(builder).create(mGeneration, mRevision);
|
||||
const auto recastMesh = std::move(builder).create(mVersion);
|
||||
EXPECT_EQ(recastMesh->getMesh().getVertices(), std::vector<float>());
|
||||
EXPECT_EQ(recastMesh->getMesh().getIndices(), std::vector<int>());
|
||||
EXPECT_EQ(recastMesh->getMesh().getAreaTypes(), std::vector<AreaType>());
|
||||
|
@ -90,7 +89,7 @@ namespace
|
|||
RecastMeshBuilder builder(mBounds);
|
||||
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity(),
|
||||
AreaType_ground, mSource, mObjectTransform);
|
||||
const auto recastMesh = std::move(builder).create(mGeneration, mRevision);
|
||||
const auto recastMesh = std::move(builder).create(mVersion);
|
||||
EXPECT_EQ(recastMesh->getMesh().getVertices(), std::vector<float>({
|
||||
-1, -1, 0,
|
||||
-1, 1, 0,
|
||||
|
@ -111,7 +110,7 @@ namespace
|
|||
btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)),
|
||||
AreaType_ground, mSource, mObjectTransform
|
||||
);
|
||||
const auto recastMesh = std::move(builder).create(mGeneration, mRevision);
|
||||
const auto recastMesh = std::move(builder).create(mVersion);
|
||||
EXPECT_EQ(recastMesh->getMesh().getVertices(), std::vector<float>({
|
||||
0, 0, 3,
|
||||
0, 4, 3,
|
||||
|
@ -128,7 +127,7 @@ namespace
|
|||
RecastMeshBuilder builder(mBounds);
|
||||
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity(),
|
||||
AreaType_ground, mSource, mObjectTransform);
|
||||
const auto recastMesh = std::move(builder).create(mGeneration, mRevision);
|
||||
const auto recastMesh = std::move(builder).create(mVersion);
|
||||
EXPECT_EQ(recastMesh->getMesh().getVertices(), std::vector<float>({
|
||||
-0.5, -0.5, 0,
|
||||
-0.5, 0.5, 0,
|
||||
|
@ -145,7 +144,7 @@ namespace
|
|||
RecastMeshBuilder builder(mBounds);
|
||||
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity(),
|
||||
AreaType_ground, mSource, mObjectTransform);
|
||||
const auto recastMesh = std::move(builder).create(mGeneration, mRevision);
|
||||
const auto recastMesh = std::move(builder).create(mVersion);
|
||||
EXPECT_EQ(recastMesh->getMesh().getVertices(), std::vector<float>({
|
||||
-1, -1, -2,
|
||||
-1, -1, 2,
|
||||
|
@ -192,7 +191,7 @@ namespace
|
|||
btTransform::getIdentity(),
|
||||
AreaType_ground, mSource, mObjectTransform
|
||||
);
|
||||
const auto recastMesh = std::move(builder).create(mGeneration, mRevision);
|
||||
const auto recastMesh = std::move(builder).create(mVersion);
|
||||
EXPECT_EQ(recastMesh->getMesh().getVertices(), std::vector<float>({
|
||||
-1, -1, -2,
|
||||
-1, -1, 0,
|
||||
|
@ -239,7 +238,7 @@ namespace
|
|||
btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)),
|
||||
AreaType_ground, mSource, mObjectTransform
|
||||
);
|
||||
const auto recastMesh = std::move(builder).create(mGeneration, mRevision);
|
||||
const auto recastMesh = std::move(builder).create(mVersion);
|
||||
EXPECT_EQ(recastMesh->getMesh().getVertices(), std::vector<float>({
|
||||
0, 0, 3,
|
||||
0, 4, 3,
|
||||
|
@ -263,7 +262,7 @@ namespace
|
|||
btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)),
|
||||
AreaType_ground, mSource, mObjectTransform
|
||||
);
|
||||
const auto recastMesh = std::move(builder).create(mGeneration, mRevision);
|
||||
const auto recastMesh = std::move(builder).create(mVersion);
|
||||
EXPECT_EQ(recastMesh->getMesh().getVertices(), std::vector<float>({
|
||||
1, 2, 12,
|
||||
1, 10, 12,
|
||||
|
@ -285,7 +284,7 @@ namespace
|
|||
btTransform::getIdentity(),
|
||||
AreaType_ground, mSource, mObjectTransform
|
||||
);
|
||||
const auto recastMesh = std::move(builder).create(mGeneration, mRevision);
|
||||
const auto recastMesh = std::move(builder).create(mVersion);
|
||||
EXPECT_EQ(recastMesh->getMesh().getVertices(), std::vector<float>({
|
||||
-3, -3, 0,
|
||||
-3, -2, 0,
|
||||
|
@ -312,7 +311,7 @@ namespace
|
|||
btTransform::getIdentity(),
|
||||
AreaType_ground, mSource, mObjectTransform
|
||||
);
|
||||
const auto recastMesh = std::move(builder).create(mGeneration, mRevision);
|
||||
const auto recastMesh = std::move(builder).create(mVersion);
|
||||
EXPECT_EQ(recastMesh->getMesh().getVertices(), std::vector<float>({
|
||||
-3, -3, 0,
|
||||
-3, -2, 0,
|
||||
|
@ -337,7 +336,7 @@ namespace
|
|||
static_cast<btScalar>(-osg::PI_4))),
|
||||
AreaType_ground, mSource, mObjectTransform
|
||||
);
|
||||
const auto recastMesh = std::move(builder).create(mGeneration, mRevision);
|
||||
const auto recastMesh = std::move(builder).create(mVersion);
|
||||
EXPECT_THAT(recastMesh->getMesh().getVertices(), Pointwise(FloatNear(1e-5f), std::vector<float>({
|
||||
0, -4.24264049530029296875f, 4.44089209850062616169452667236328125e-16f,
|
||||
0, -3.535533905029296875f, -0.707106769084930419921875f,
|
||||
|
@ -362,7 +361,7 @@ namespace
|
|||
static_cast<btScalar>(osg::PI_4))),
|
||||
AreaType_ground, mSource, mObjectTransform
|
||||
);
|
||||
const auto recastMesh = std::move(builder).create(mGeneration, mRevision);
|
||||
const auto recastMesh = std::move(builder).create(mVersion);
|
||||
EXPECT_THAT(recastMesh->getMesh().getVertices(), Pointwise(FloatNear(1e-5f), std::vector<float>({
|
||||
-4.24264049530029296875f, 0, 4.44089209850062616169452667236328125e-16f,
|
||||
-3.535533905029296875f, 0, -0.707106769084930419921875f,
|
||||
|
@ -387,7 +386,7 @@ namespace
|
|||
static_cast<btScalar>(osg::PI_4))),
|
||||
AreaType_ground, mSource, mObjectTransform
|
||||
);
|
||||
const auto recastMesh = std::move(builder).create(mGeneration, mRevision);
|
||||
const auto recastMesh = std::move(builder).create(mVersion);
|
||||
EXPECT_THAT(recastMesh->getMesh().getVertices(), Pointwise(FloatNear(1e-5f), std::vector<float>({
|
||||
-1.41421353816986083984375f, -1.1102230246251565404236316680908203125e-16f, 0,
|
||||
1.1102230246251565404236316680908203125e-16f, -1.41421353816986083984375f, 0,
|
||||
|
@ -416,7 +415,7 @@ namespace
|
|||
btTransform::getIdentity(),
|
||||
AreaType_null, mSource, mObjectTransform
|
||||
);
|
||||
const auto recastMesh = std::move(builder).create(mGeneration, mRevision);
|
||||
const auto recastMesh = std::move(builder).create(mVersion);
|
||||
EXPECT_EQ(recastMesh->getMesh().getVertices(), std::vector<float>({
|
||||
-3, -3, 0,
|
||||
-3, -2, 0,
|
||||
|
@ -433,7 +432,7 @@ namespace
|
|||
{
|
||||
RecastMeshBuilder builder(mBounds);
|
||||
builder.addWater(osg::Vec2i(1, 2), Water {1000, 300.0f});
|
||||
const auto recastMesh = std::move(builder).create(mGeneration, mRevision);
|
||||
const auto recastMesh = std::move(builder).create(mVersion);
|
||||
EXPECT_EQ(recastMesh->getWater(), std::vector<CellWater>({
|
||||
CellWater {osg::Vec2i(1, 2), Water {1000, 300.0f}}
|
||||
}));
|
||||
|
@ -448,7 +447,7 @@ namespace
|
|||
|
||||
RecastMeshBuilder builder(mBounds);
|
||||
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity(), AreaType_ground, mSource, mObjectTransform);
|
||||
const auto recastMesh = std::move(builder).create(mGeneration, mRevision);
|
||||
const auto recastMesh = std::move(builder).create(mVersion);
|
||||
EXPECT_EQ(recastMesh->getMesh().getVertices(), std::vector<float>({
|
||||
-1, -1, 0,
|
||||
-1, 1, 0,
|
||||
|
@ -467,7 +466,7 @@ namespace
|
|||
mBounds.mMin = osg::Vec2f(100, 100);
|
||||
RecastMeshBuilder builder(mBounds);
|
||||
builder.addHeightfield(cellPosition, cellSize, height);
|
||||
const auto recastMesh = std::move(builder).create(mGeneration, mRevision);
|
||||
const auto recastMesh = std::move(builder).create(mVersion);
|
||||
EXPECT_EQ(recastMesh->getFlatHeightfields(), std::vector<FlatHeightfield>({
|
||||
FlatHeightfield {cellPosition, cellSize, height},
|
||||
}));
|
||||
|
@ -487,7 +486,7 @@ namespace
|
|||
const float maxHeight = 8;
|
||||
RecastMeshBuilder builder(mBounds);
|
||||
builder.addHeightfield(cellPosition, cellSize, heights.data(), size, minHeight, maxHeight);
|
||||
const auto recastMesh = std::move(builder).create(mGeneration, mRevision);
|
||||
const auto recastMesh = std::move(builder).create(mVersion);
|
||||
Heightfield expected;
|
||||
expected.mCellPosition = cellPosition;
|
||||
expected.mCellSize = cellSize;
|
||||
|
@ -519,7 +518,7 @@ namespace
|
|||
const float maxHeight = 8;
|
||||
RecastMeshBuilder builder(maxCellTileBounds(cellPosition, cellSize));
|
||||
builder.addHeightfield(cellPosition, cellSize, heights.data(), size, minHeight, maxHeight);
|
||||
const auto recastMesh = std::move(builder).create(mGeneration, mRevision);
|
||||
const auto recastMesh = std::move(builder).create(mVersion);
|
||||
Heightfield expected;
|
||||
expected.mCellPosition = cellPosition;
|
||||
expected.mCellSize = cellSize;
|
||||
|
@ -552,7 +551,7 @@ namespace
|
|||
mBounds.mMin = osg::Vec2f(750, 750);
|
||||
RecastMeshBuilder builder(mBounds);
|
||||
builder.addHeightfield(cellPosition, cellSize, heights.data(), size, minHeight, maxHeight);
|
||||
const auto recastMesh = std::move(builder).create(mGeneration, mRevision);
|
||||
const auto recastMesh = std::move(builder).create(mVersion);
|
||||
Heightfield expected;
|
||||
expected.mCellPosition = cellPosition;
|
||||
expected.mCellSize = cellSize;
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include <numeric>
|
||||
#include <set>
|
||||
#include <type_traits>
|
||||
#include <optional>
|
||||
#include <tuple>
|
||||
|
||||
namespace DetourNavigator
|
||||
{
|
||||
|
@ -31,15 +33,22 @@ namespace DetourNavigator
|
|||
return std::abs(lhs.x() - rhs.x()) + std::abs(lhs.y() - rhs.y());
|
||||
}
|
||||
|
||||
int getMinDistanceTo(const TilePosition& position, int maxDistance,
|
||||
const std::set<std::tuple<AgentBounds, TilePosition>>& pushedTiles,
|
||||
const std::set<std::tuple<AgentBounds, TilePosition>>& presentTiles)
|
||||
bool isAbsentTileTooClose(const TilePosition& position, int distance,
|
||||
const std::set<std::tuple<AgentBounds, TilePosition>>& pushedTiles,
|
||||
const std::set<std::tuple<AgentBounds, TilePosition>>& presentTiles,
|
||||
const Misc::ScopeGuarded<std::set<std::tuple<AgentBounds, TilePosition>>>& processingTiles)
|
||||
{
|
||||
int result = maxDistance;
|
||||
for (const auto& [agentBounds, tile] : pushedTiles)
|
||||
if (presentTiles.find(std::tie(agentBounds, tile)) == presentTiles.end())
|
||||
result = std::min(result, getManhattanDistance(position, tile));
|
||||
return result;
|
||||
const auto isAbsentAndCloserThan = [&] (const std::tuple<AgentBounds, TilePosition>& v)
|
||||
{
|
||||
return presentTiles.find(v) == presentTiles.end()
|
||||
&& getManhattanDistance(position, std::get<1>(v)) < distance;
|
||||
};
|
||||
if (std::any_of(pushedTiles.begin(), pushedTiles.end(), isAbsentAndCloserThan))
|
||||
return true;
|
||||
if (const auto locked = processingTiles.lockConst();
|
||||
std::any_of(locked->begin(), locked->end(), isAbsentAndCloserThan))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto getPriority(const Job& job) noexcept
|
||||
|
@ -125,7 +134,7 @@ namespace DetourNavigator
|
|||
case JobStatus::Fail: return stream << "JobStatus::Fail";
|
||||
case JobStatus::MemoryCacheMiss: return stream << "JobStatus::MemoryCacheMiss";
|
||||
}
|
||||
return stream << "JobStatus::" << static_cast<std::underlying_type_t<JobState>>(value);
|
||||
return stream << "JobStatus::" << static_cast<std::underlying_type_t<JobStatus>>(value);
|
||||
}
|
||||
|
||||
Job::Job(const AgentBounds& agentBounds, std::weak_ptr<GuardedNavMeshCacheItem> navMeshCacheItem,
|
||||
|
@ -247,28 +256,25 @@ namespace DetourNavigator
|
|||
|
||||
void AsyncNavMeshUpdater::waitUntilJobsDoneForNotPresentTiles(Loading::Listener& listener)
|
||||
{
|
||||
const int maxDistanceToPlayer = mSettings.get().mWaitUntilMinDistanceToPlayer;
|
||||
if (maxDistanceToPlayer <= 0)
|
||||
return;
|
||||
const std::size_t initialJobsLeft = getTotalJobs();
|
||||
std::size_t maxProgress = initialJobsLeft + mThreads.size();
|
||||
std::size_t maxProgress = initialJobsLeft;
|
||||
std::size_t prevJobsLeft = initialJobsLeft;
|
||||
std::size_t jobsDone = 0;
|
||||
std::size_t jobsLeft = 0;
|
||||
const int maxDistanceToPlayer = mSettings.get().mWaitUntilMinDistanceToPlayer;
|
||||
const TilePosition playerPosition = *mPlayerTile.lockConst();
|
||||
int minDistanceToPlayer = 0;
|
||||
const auto isDone = [&]
|
||||
{
|
||||
jobsLeft = mJobs.size();
|
||||
if (jobsLeft == 0)
|
||||
{
|
||||
minDistanceToPlayer = 0;
|
||||
return true;
|
||||
}
|
||||
minDistanceToPlayer = getMinDistanceTo(playerPosition, maxDistanceToPlayer, mPushed, mPresentTiles);
|
||||
return minDistanceToPlayer >= maxDistanceToPlayer;
|
||||
return !isAbsentTileTooClose(playerPosition, maxDistanceToPlayer, mPushed, mPresentTiles, mProcessingTiles);
|
||||
};
|
||||
std::unique_lock<std::mutex> lock(mMutex);
|
||||
if (getMinDistanceTo(playerPosition, maxDistanceToPlayer, mPushed, mPresentTiles) >= maxDistanceToPlayer
|
||||
|| (mJobs.empty() && mProcessingTiles.lockConst()->empty()))
|
||||
if (!isAbsentTileTooClose(playerPosition, maxDistanceToPlayer, mPushed, mPresentTiles, mProcessingTiles)
|
||||
|| mJobs.empty())
|
||||
return;
|
||||
Loading::ScopedLoad load(&listener);
|
||||
listener.setLabel("#{Navigation:BuildingNavigationMesh}");
|
||||
|
@ -277,7 +283,7 @@ namespace DetourNavigator
|
|||
{
|
||||
if (maxProgress < jobsLeft)
|
||||
{
|
||||
maxProgress = jobsLeft + mThreads.size();
|
||||
maxProgress = jobsLeft;
|
||||
listener.setProgressRange(maxProgress);
|
||||
listener.setProgress(jobsDone);
|
||||
}
|
||||
|
@ -289,12 +295,6 @@ namespace DetourNavigator
|
|||
listener.increaseProgress(newJobsDone);
|
||||
}
|
||||
}
|
||||
lock.unlock();
|
||||
if (minDistanceToPlayer < maxDistanceToPlayer)
|
||||
{
|
||||
mProcessingTiles.wait(mProcessed, [] (const auto& v) { return v.empty(); });
|
||||
listener.setProgress(maxProgress);
|
||||
}
|
||||
}
|
||||
|
||||
void AsyncNavMeshUpdater::waitUntilAllJobsDone()
|
||||
|
@ -513,9 +513,7 @@ namespace DetourNavigator
|
|||
const Job& job, const GuardedNavMeshCacheItem& navMeshCacheItem, const RecastMesh& recastMesh)
|
||||
{
|
||||
const Version navMeshVersion = navMeshCacheItem.lockConst()->getVersion();
|
||||
mRecastMeshManager.get().reportNavMeshChange(job.mChangedTile,
|
||||
Version {recastMesh.getGeneration(), recastMesh.getRevision()},
|
||||
navMeshVersion);
|
||||
mRecastMeshManager.get().reportNavMeshChange(job.mChangedTile, recastMesh.getVersion(), navMeshVersion);
|
||||
|
||||
if (status == UpdateNavMeshStatus::removed || status == UpdateNavMeshStatus::lost)
|
||||
{
|
||||
|
|
|
@ -97,9 +97,4 @@ namespace DetourNavigator
|
|||
{
|
||||
mImpl.reportNavMeshChange(recastMeshVersion, navMeshVersion);
|
||||
}
|
||||
|
||||
Version CachedRecastMeshManager::getVersion() const
|
||||
{
|
||||
return mImpl.getVersion();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace DetourNavigator
|
|||
|
||||
void reportNavMeshChange(const Version& recastMeshVersion, const Version& navMeshVersion);
|
||||
|
||||
Version getVersion() const;
|
||||
Version getVersion() const { return mImpl.getVersion(); }
|
||||
|
||||
private:
|
||||
RecastMeshManager mImpl;
|
||||
|
|
|
@ -154,8 +154,7 @@ namespace DetourNavigator
|
|||
|
||||
void NavigatorImpl::wait(Loading::Listener& listener, WaitConditionType waitConditionType)
|
||||
{
|
||||
if (mSettings.mWaitUntilMinDistanceToPlayer > 0)
|
||||
mNavMeshManager.wait(listener, waitConditionType);
|
||||
mNavMeshManager.wait(listener, waitConditionType);
|
||||
}
|
||||
|
||||
SharedNavMeshCacheItem NavigatorImpl::getNavMesh(const AgentBounds& agentBounds) const
|
||||
|
|
|
@ -177,16 +177,8 @@ namespace DetourNavigator
|
|||
const auto locked = cached->lockConst();
|
||||
const auto& navMesh = locked->getImpl();
|
||||
for (const auto& [tilePosition, changeType] : changedTiles)
|
||||
{
|
||||
if (navMesh.getTileAt(tilePosition.x(), tilePosition.y(), 0))
|
||||
{
|
||||
auto tileToPost = tilesToPost.find(tilePosition);
|
||||
if (tileToPost == tilesToPost.end())
|
||||
tilesToPost.emplace(tilePosition, changeType);
|
||||
else
|
||||
tileToPost->second = addChangeType(tileToPost->second, changeType);
|
||||
}
|
||||
}
|
||||
tilesToPost.emplace(tilePosition, changeType);
|
||||
const auto maxTiles = std::min(mSettings.mMaxTilesNumber, navMesh.getParams()->maxTiles);
|
||||
mRecastMeshManager.forEachTile([&] (const TilePosition& tile, CachedRecastMeshManager& recastMeshManager)
|
||||
{
|
||||
|
|
|
@ -18,11 +18,10 @@ namespace DetourNavigator
|
|||
mAreaTypes = std::move(areaTypes);
|
||||
}
|
||||
|
||||
RecastMesh::RecastMesh(std::size_t generation, std::size_t revision, Mesh mesh, std::vector<CellWater> water,
|
||||
RecastMesh::RecastMesh(const Version& version, Mesh mesh, std::vector<CellWater> water,
|
||||
std::vector<Heightfield> heightfields, std::vector<FlatHeightfield> flatHeightfields,
|
||||
std::vector<MeshSource> meshSources)
|
||||
: mGeneration(generation)
|
||||
, mRevision(revision)
|
||||
: mVersion(version)
|
||||
, mMesh(std::move(mesh))
|
||||
, mWater(std::move(water))
|
||||
, mHeightfields(std::move(heightfields))
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "areatype.hpp"
|
||||
#include "objecttransform.hpp"
|
||||
#include "version.hpp"
|
||||
|
||||
#include <components/bullethelpers/operators.hpp>
|
||||
#include <components/resource/bulletshape.hpp>
|
||||
|
@ -129,19 +130,11 @@ namespace DetourNavigator
|
|||
class RecastMesh
|
||||
{
|
||||
public:
|
||||
RecastMesh(std::size_t generation, std::size_t revision, Mesh mesh, std::vector<CellWater> water,
|
||||
explicit RecastMesh(const Version& version, Mesh mesh, std::vector<CellWater> water,
|
||||
std::vector<Heightfield> heightfields, std::vector<FlatHeightfield> flatHeightfields,
|
||||
std::vector<MeshSource> sources);
|
||||
|
||||
std::size_t getGeneration() const
|
||||
{
|
||||
return mGeneration;
|
||||
}
|
||||
|
||||
std::size_t getRevision() const
|
||||
{
|
||||
return mRevision;
|
||||
}
|
||||
const Version& getVersion() const noexcept { return mVersion; }
|
||||
|
||||
const Mesh& getMesh() const noexcept { return mMesh; }
|
||||
|
||||
|
@ -163,8 +156,7 @@ namespace DetourNavigator
|
|||
const std::vector<MeshSource>& getMeshSources() const noexcept { return mMeshSources; }
|
||||
|
||||
private:
|
||||
std::size_t mGeneration;
|
||||
std::size_t mRevision;
|
||||
Version mVersion;
|
||||
Mesh mMesh;
|
||||
std::vector<CellWater> mWater;
|
||||
std::vector<Heightfield> mHeightfields;
|
||||
|
|
|
@ -272,13 +272,13 @@ namespace DetourNavigator
|
|||
mHeightfields.push_back(std::move(heightfield));
|
||||
}
|
||||
|
||||
std::shared_ptr<RecastMesh> RecastMeshBuilder::create(std::size_t generation, std::size_t revision) &&
|
||||
std::shared_ptr<RecastMesh> RecastMeshBuilder::create(const Version& version) &&
|
||||
{
|
||||
mTriangles.erase(std::remove_if(mTriangles.begin(), mTriangles.end(), isNan), mTriangles.end());
|
||||
std::sort(mTriangles.begin(), mTriangles.end());
|
||||
std::sort(mWater.begin(), mWater.end());
|
||||
Mesh mesh = makeMesh(std::move(mTriangles));
|
||||
return std::make_shared<RecastMesh>(generation, revision, std::move(mesh), std::move(mWater),
|
||||
return std::make_shared<RecastMesh>(version, std::move(mesh), std::move(mWater),
|
||||
std::move(mHeightfields), std::move(mFlatHeightfields),
|
||||
std::move(mSources));
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace DetourNavigator
|
|||
void addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const float* heights, std::size_t size,
|
||||
float minHeight, float maxHeight);
|
||||
|
||||
std::shared_ptr<RecastMesh> create(std::size_t generation, std::size_t revision) &&;
|
||||
std::shared_ptr<RecastMesh> create(const Version& version) &&;
|
||||
|
||||
private:
|
||||
const TileBounds mBounds;
|
||||
|
|
|
@ -143,7 +143,7 @@ namespace DetourNavigator
|
|||
}
|
||||
for (const auto& [instance, objectTransform, shape, transform, areaType] : objects)
|
||||
builder.addObject(shape, transform, areaType, instance->getSource(), objectTransform);
|
||||
return std::move(builder).create(mGeneration, revision);
|
||||
return std::move(builder).create(Version {.mGeneration = mGeneration, .mRevision = revision});
|
||||
}
|
||||
|
||||
bool RecastMeshManager::isEmpty() const
|
||||
|
@ -164,9 +164,4 @@ namespace DetourNavigator
|
|||
|| mLastNavMeshReportedChange->mNavMeshVersion < mLastNavMeshReport->mNavMeshVersion)
|
||||
mLastNavMeshReportedChange = mLastNavMeshReport;
|
||||
}
|
||||
|
||||
Version RecastMeshManager::getVersion() const
|
||||
{
|
||||
return Version {mGeneration, mRevision};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ namespace DetourNavigator
|
|||
|
||||
void reportNavMeshChange(const Version& recastMeshVersion, const Version& navMeshVersion);
|
||||
|
||||
Version getVersion() const;
|
||||
Version getVersion() const { return Version {mGeneration, mRevision}; }
|
||||
|
||||
private:
|
||||
struct Report
|
||||
|
|
Loading…
Reference in a new issue