1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-05-17 19:41:28 +00:00

Add raw water data to navigator

This commit is contained in:
elsid 2021-11-04 02:48:32 +01:00
parent f4f4458d01
commit 8571c317d8
No known key found for this signature in database
GPG key ID: B845CB9FEE18AB40
24 changed files with 150 additions and 99 deletions

View file

@ -89,10 +89,11 @@ namespace
template <typename OutputIterator, typename Random> template <typename OutputIterator, typename Random>
void generateWater(OutputIterator out, std::size_t count, Random& random) void generateWater(OutputIterator out, std::size_t count, Random& random)
{ {
std::uniform_real_distribution<float> distribution(0.0, 1.0); std::uniform_real_distribution<float> floatDistribution(0.0, 1.0);
std::uniform_int_distribution<int> intDistribution(-10, 10);
std::generate_n(out, count, [&] { std::generate_n(out, count, [&] {
const osg::Vec3f shift(distribution(random), distribution(random), distribution(random)); const osg::Vec2i cellPosition(intDistribution(random), intDistribution(random));
return Cell {1, shift}; return CellWater {cellPosition, Water {8196, floatDistribution(random)}};
}); });
} }
@ -148,7 +149,7 @@ namespace
const std::size_t generation = std::uniform_int_distribution<std::size_t>(0, 100)(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 std::size_t revision = std::uniform_int_distribution<std::size_t>(0, 10000)(random);
Mesh mesh = generateMesh(triangles, random); Mesh mesh = generateMesh(triangles, random);
std::vector<Cell> water; std::vector<CellWater> water;
generateWater(std::back_inserter(water), 1, random); generateWater(std::back_inserter(water), 1, random);
RecastMesh recastMesh(generation, revision, std::move(mesh), std::move(water), RecastMesh recastMesh(generation, revision, std::move(mesh), std::move(water),
{generateHeightfield(random)}, {generateFlatHeightfield(random)}); {generateHeightfield(random)}, {generateFlatHeightfield(random)});

View file

@ -434,18 +434,11 @@ namespace MWWorld
if (cell->getCell()->isExterior()) if (cell->getCell()->isExterior())
{ {
if (const auto heightField = mPhysics->getHeightField(cellX, cellY)) if (const auto heightField = mPhysics->getHeightField(cellX, cellY))
{ mNavigator.addWater(osg::Vec2i(cellX, cellY), ESM::Land::REAL_SIZE, waterLevel);
const btTransform& transform =heightField->getCollisionObject()->getWorldTransform();
mNavigator.addWater(osg::Vec2i(cellX, cellY), ESM::Land::REAL_SIZE,
osg::Vec3f(static_cast<float>(transform.getOrigin().x()),
static_cast<float>(transform.getOrigin().y()),
waterLevel));
}
} }
else else
{ {
mNavigator.addWater(osg::Vec2i(cellX, cellY), std::numeric_limits<int>::max(), mNavigator.addWater(osg::Vec2i(cellX, cellY), std::numeric_limits<int>::max(), waterLevel);
osg::Vec3f(0, 0, waterLevel));
} }
} }
else else

View file

@ -548,7 +548,7 @@ namespace
const osg::Vec3f shift = getHeightfieldShift(mCellPosition, cellSize, surface.mMinHeight, surface.mMaxHeight); const osg::Vec3f shift = getHeightfieldShift(mCellPosition, cellSize, surface.mMinHeight, surface.mMaxHeight);
mNavigator->addAgent(mAgentHalfExtents); mNavigator->addAgent(mAgentHalfExtents);
mNavigator->addWater(mCellPosition, cellSize, osg::Vec3f(shift.x(), shift.y(), 300)); mNavigator->addWater(mCellPosition, cellSize, 300);
mNavigator->addHeightfield(mCellPosition, cellSize, shift, surface); mNavigator->addHeightfield(mCellPosition, cellSize, shift, surface);
mNavigator->update(mPlayerPosition); mNavigator->update(mPlayerPosition);
mNavigator->wait(mListener, WaitConditionType::allJobsDone); mNavigator->wait(mListener, WaitConditionType::allJobsDone);
@ -597,7 +597,7 @@ namespace
const osg::Vec3f shift = getHeightfieldShift(mCellPosition, cellSize, surface.mMinHeight, surface.mMaxHeight); const osg::Vec3f shift = getHeightfieldShift(mCellPosition, cellSize, surface.mMinHeight, surface.mMaxHeight);
mNavigator->addAgent(mAgentHalfExtents); mNavigator->addAgent(mAgentHalfExtents);
mNavigator->addWater(mCellPosition, cellSize, osg::Vec3f(shift.x(), shift.y(), -25)); mNavigator->addWater(mCellPosition, cellSize, -25);
mNavigator->addHeightfield(mCellPosition, cellSize, shift, surface); mNavigator->addHeightfield(mCellPosition, cellSize, shift, surface);
mNavigator->update(mPlayerPosition); mNavigator->update(mPlayerPosition);
mNavigator->wait(mListener, WaitConditionType::allJobsDone); mNavigator->wait(mListener, WaitConditionType::allJobsDone);
@ -645,7 +645,7 @@ namespace
mNavigator->addAgent(mAgentHalfExtents); mNavigator->addAgent(mAgentHalfExtents);
mNavigator->addHeightfield(mCellPosition, cellSize, shift, surface); mNavigator->addHeightfield(mCellPosition, cellSize, shift, surface);
mNavigator->addWater(mCellPosition, std::numeric_limits<int>::max(), osg::Vec3f(shift.x(), shift.y(), -25)); mNavigator->addWater(mCellPosition, std::numeric_limits<int>::max(), -25);
mNavigator->update(mPlayerPosition); mNavigator->update(mPlayerPosition);
mNavigator->wait(mListener, WaitConditionType::allJobsDone); mNavigator->wait(mListener, WaitConditionType::allJobsDone);
@ -691,7 +691,7 @@ namespace
const osg::Vec3f shift = getHeightfieldShift(mCellPosition, cellSize, surface.mMinHeight, surface.mMaxHeight); const osg::Vec3f shift = getHeightfieldShift(mCellPosition, cellSize, surface.mMinHeight, surface.mMaxHeight);
mNavigator->addAgent(mAgentHalfExtents); mNavigator->addAgent(mAgentHalfExtents);
mNavigator->addWater(mCellPosition, cellSize, osg::Vec3f(shift.x(), shift.y(), -25)); mNavigator->addWater(mCellPosition, cellSize, -25);
mNavigator->addHeightfield(mCellPosition, cellSize, shift, surface); mNavigator->addHeightfield(mCellPosition, cellSize, shift, surface);
mNavigator->update(mPlayerPosition); mNavigator->update(mPlayerPosition);
mNavigator->wait(mListener, WaitConditionType::allJobsDone); mNavigator->wait(mListener, WaitConditionType::allJobsDone);

View file

@ -144,14 +144,14 @@ namespace
const std::size_t mGeneration = 0; const std::size_t mGeneration = 0;
const std::size_t mRevision = 0; const std::size_t mRevision = 0;
const Mesh mMesh {makeMesh()}; const Mesh mMesh {makeMesh()};
const std::vector<Cell> mWater {}; const std::vector<CellWater> mWater {};
const std::vector<Heightfield> mHeightfields {}; const std::vector<Heightfield> mHeightfields {};
const std::vector<FlatHeightfield> mFlatHeightfields {}; const std::vector<FlatHeightfield> mFlatHeightfields {};
const RecastMesh mRecastMesh {mGeneration, mRevision, mMesh, mWater, mHeightfields, mFlatHeightfields}; const RecastMesh mRecastMesh {mGeneration, mRevision, mMesh, mWater, mHeightfields, mFlatHeightfields};
std::unique_ptr<PreparedNavMeshData> mPreparedNavMeshData {makePeparedNavMeshData(3)}; std::unique_ptr<PreparedNavMeshData> mPreparedNavMeshData {makePeparedNavMeshData(3)};
const std::size_t mRecastMeshSize = sizeof(mRecastMesh) + getSize(mRecastMesh); const std::size_t mRecastMeshSize = sizeof(mRecastMesh) + getSize(mRecastMesh);
const std::size_t mRecastMeshWithWaterSize = mRecastMeshSize + sizeof(Cell); const std::size_t mRecastMeshWithWaterSize = mRecastMeshSize + sizeof(CellWater);
const std::size_t mPreparedNavMeshDataSize = sizeof(*mPreparedNavMeshData) + getSize(*mPreparedNavMeshData); const std::size_t mPreparedNavMeshDataSize = sizeof(*mPreparedNavMeshData) + getSize(*mPreparedNavMeshData);
}; };
@ -234,7 +234,7 @@ namespace
{ {
const std::size_t maxSize = 1; const std::size_t maxSize = 1;
NavMeshTilesCache cache(maxSize); NavMeshTilesCache cache(maxSize);
const std::vector<Cell> water {1, Cell {1, osg::Vec3f()}}; const std::vector<CellWater> water(1, CellWater {osg::Vec2i(), Water {1, 0.0f}});
const RecastMesh unexistentRecastMesh {mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields}; const RecastMesh unexistentRecastMesh {mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields};
cache.set(mAgentHalfExtents, mTilePosition, mRecastMesh, std::move(mPreparedNavMeshData)); cache.set(mAgentHalfExtents, mTilePosition, mRecastMesh, std::move(mPreparedNavMeshData));
@ -246,7 +246,7 @@ namespace
const std::size_t maxSize = mRecastMeshWithWaterSize + mPreparedNavMeshDataSize; const std::size_t maxSize = mRecastMeshWithWaterSize + mPreparedNavMeshDataSize;
NavMeshTilesCache cache(maxSize); NavMeshTilesCache cache(maxSize);
const std::vector<Cell> water {1, Cell {1, osg::Vec3f()}}; const std::vector<CellWater> water(1, CellWater {osg::Vec2i(), Water {1, 0.0f}});
const RecastMesh anotherRecastMesh {mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields}; const RecastMesh anotherRecastMesh {mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields};
auto anotherPreparedNavMeshData = makePeparedNavMeshData(3); auto anotherPreparedNavMeshData = makePeparedNavMeshData(3);
const auto copy = clone(*anotherPreparedNavMeshData); const auto copy = clone(*anotherPreparedNavMeshData);
@ -264,7 +264,7 @@ namespace
const std::size_t maxSize = mRecastMeshWithWaterSize + mPreparedNavMeshDataSize; const std::size_t maxSize = mRecastMeshWithWaterSize + mPreparedNavMeshDataSize;
NavMeshTilesCache cache(maxSize); NavMeshTilesCache cache(maxSize);
const std::vector<Cell> water {1, Cell {1, osg::Vec3f()}}; const std::vector<CellWater> water(1, CellWater {osg::Vec2i(), Water {1, 0.0f}});
const RecastMesh anotherRecastMesh {mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields}; const RecastMesh anotherRecastMesh {mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields};
auto anotherPreparedNavMeshData = makePeparedNavMeshData(3); auto anotherPreparedNavMeshData = makePeparedNavMeshData(3);
@ -280,12 +280,12 @@ namespace
NavMeshTilesCache cache(maxSize); NavMeshTilesCache cache(maxSize);
const auto copy = clone(*mPreparedNavMeshData); const auto copy = clone(*mPreparedNavMeshData);
const std::vector<Cell> leastRecentlySetWater {1, Cell {1, osg::Vec3f()}}; const std::vector<CellWater> leastRecentlySetWater(1, CellWater {osg::Vec2i(), Water {1, 0.0f}});
const RecastMesh leastRecentlySetRecastMesh {mGeneration, mRevision, mMesh, leastRecentlySetWater, const RecastMesh leastRecentlySetRecastMesh {mGeneration, mRevision, mMesh, leastRecentlySetWater,
mHeightfields, mFlatHeightfields}; mHeightfields, mFlatHeightfields};
auto leastRecentlySetData = makePeparedNavMeshData(3); auto leastRecentlySetData = makePeparedNavMeshData(3);
const std::vector<Cell> mostRecentlySetWater {1, Cell {2, osg::Vec3f()}}; const std::vector<CellWater> mostRecentlySetWater(1, CellWater {osg::Vec2i(), Water {2, 0.0f}});
const RecastMesh mostRecentlySetRecastMesh {mGeneration, mRevision, mMesh, mostRecentlySetWater, const RecastMesh mostRecentlySetRecastMesh {mGeneration, mRevision, mMesh, mostRecentlySetWater,
mHeightfields, mFlatHeightfields}; mHeightfields, mFlatHeightfields};
auto mostRecentlySetData = makePeparedNavMeshData(3); auto mostRecentlySetData = makePeparedNavMeshData(3);
@ -308,13 +308,13 @@ namespace
const std::size_t maxSize = 2 * (mRecastMeshWithWaterSize + mPreparedNavMeshDataSize); const std::size_t maxSize = 2 * (mRecastMeshWithWaterSize + mPreparedNavMeshDataSize);
NavMeshTilesCache cache(maxSize); NavMeshTilesCache cache(maxSize);
const std::vector<Cell> leastRecentlyUsedWater {1, Cell {1, osg::Vec3f()}}; const std::vector<CellWater> leastRecentlyUsedWater(1, CellWater {osg::Vec2i(), Water {1, 0.0f}});
const RecastMesh leastRecentlyUsedRecastMesh {mGeneration, mRevision, mMesh, leastRecentlyUsedWater, const RecastMesh leastRecentlyUsedRecastMesh {mGeneration, mRevision, mMesh, leastRecentlyUsedWater,
mHeightfields, mFlatHeightfields}; mHeightfields, mFlatHeightfields};
auto leastRecentlyUsedData = makePeparedNavMeshData(3); auto leastRecentlyUsedData = makePeparedNavMeshData(3);
const auto leastRecentlyUsedCopy = clone(*leastRecentlyUsedData); const auto leastRecentlyUsedCopy = clone(*leastRecentlyUsedData);
const std::vector<Cell> mostRecentlyUsedWater {1, Cell {2, osg::Vec3f()}}; const std::vector<CellWater> mostRecentlyUsedWater(1, CellWater {osg::Vec2i(), Water {2, 0.0f}});
const RecastMesh mostRecentlyUsedRecastMesh {mGeneration, mRevision, mMesh, mostRecentlyUsedWater, const RecastMesh mostRecentlyUsedRecastMesh {mGeneration, mRevision, mMesh, mostRecentlyUsedWater,
mHeightfields, mFlatHeightfields}; mHeightfields, mFlatHeightfields};
auto mostRecentlyUsedData = makePeparedNavMeshData(3); auto mostRecentlyUsedData = makePeparedNavMeshData(3);
@ -349,7 +349,7 @@ namespace
const std::size_t maxSize = 2 * (mRecastMeshWithWaterSize + mPreparedNavMeshDataSize); const std::size_t maxSize = 2 * (mRecastMeshWithWaterSize + mPreparedNavMeshDataSize);
NavMeshTilesCache cache(maxSize); NavMeshTilesCache cache(maxSize);
const std::vector<Cell> water {1, Cell {1, osg::Vec3f()}}; const std::vector<CellWater> water(1, CellWater {osg::Vec2i(), Water {1, 0.0f}});
const RecastMesh tooLargeRecastMesh {mGeneration, mRevision, mMesh, water, const RecastMesh tooLargeRecastMesh {mGeneration, mRevision, mMesh, water,
mHeightfields, mFlatHeightfields}; mHeightfields, mFlatHeightfields};
auto tooLargeData = makePeparedNavMeshData(10); auto tooLargeData = makePeparedNavMeshData(10);
@ -364,12 +364,12 @@ namespace
const std::size_t maxSize = 2 * (mRecastMeshWithWaterSize + mPreparedNavMeshDataSize); const std::size_t maxSize = 2 * (mRecastMeshWithWaterSize + mPreparedNavMeshDataSize);
NavMeshTilesCache cache(maxSize); NavMeshTilesCache cache(maxSize);
const std::vector<Cell> anotherWater {1, Cell {1, osg::Vec3f()}}; const std::vector<CellWater> anotherWater(1, CellWater {osg::Vec2i(), Water {1, 0.0f}});
const RecastMesh anotherRecastMesh {mGeneration, mRevision, mMesh, anotherWater, const RecastMesh anotherRecastMesh {mGeneration, mRevision, mMesh, anotherWater,
mHeightfields, mFlatHeightfields}; mHeightfields, mFlatHeightfields};
auto anotherData = makePeparedNavMeshData(3); auto anotherData = makePeparedNavMeshData(3);
const std::vector<Cell> tooLargeWater {1, Cell {2, osg::Vec3f()}}; const std::vector<CellWater> tooLargeWater(1, CellWater {osg::Vec2i(), Water {2, 0.0f}});
const RecastMesh tooLargeRecastMesh {mGeneration, mRevision, mMesh, tooLargeWater, const RecastMesh tooLargeRecastMesh {mGeneration, mRevision, mMesh, tooLargeWater,
mHeightfields, mFlatHeightfields}; mHeightfields, mFlatHeightfields};
auto tooLargeData = makePeparedNavMeshData(10); auto tooLargeData = makePeparedNavMeshData(10);
@ -390,7 +390,7 @@ namespace
const std::size_t maxSize = mRecastMeshWithWaterSize + mPreparedNavMeshDataSize; const std::size_t maxSize = mRecastMeshWithWaterSize + mPreparedNavMeshDataSize;
NavMeshTilesCache cache(maxSize); NavMeshTilesCache cache(maxSize);
const std::vector<Cell> water {1, Cell {1, osg::Vec3f()}}; const std::vector<CellWater> water(1, CellWater {osg::Vec2i(), Water {1, 0.0f}});
const RecastMesh anotherRecastMesh {mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields}; const RecastMesh anotherRecastMesh {mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields};
auto anotherData = makePeparedNavMeshData(3); auto anotherData = makePeparedNavMeshData(3);
@ -409,7 +409,7 @@ namespace
const std::size_t maxSize = mRecastMeshWithWaterSize + mPreparedNavMeshDataSize; const std::size_t maxSize = mRecastMeshWithWaterSize + mPreparedNavMeshDataSize;
NavMeshTilesCache cache(maxSize); NavMeshTilesCache cache(maxSize);
const std::vector<Cell> water {1, Cell {1, osg::Vec3f()}}; const std::vector<CellWater> water(1, CellWater {osg::Vec2i(), Water {1, 0.0f}});
const RecastMesh anotherRecastMesh {mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields}; const RecastMesh anotherRecastMesh {mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields};
auto anotherData = makePeparedNavMeshData(3); auto anotherData = makePeparedNavMeshData(3);

View file

@ -28,6 +28,18 @@ namespace DetourNavigator
return lhs.mSize == rhs.mSize && lhs.mShift == rhs.mShift; return lhs.mSize == rhs.mSize && lhs.mShift == rhs.mShift;
} }
static inline bool operator ==(const Water& lhs, const Water& rhs)
{
const auto tie = [] (const Water& v) { return std::tie(v.mCellSize, v.mLevel); };
return tie(lhs) == tie(rhs);
}
static inline bool operator ==(const CellWater& lhs, const CellWater& rhs)
{
const auto tie = [] (const CellWater& v) { return std::tie(v.mCellPosition, v.mWater); };
return tie(lhs) == tie(rhs);
}
static inline bool operator==(const Heightfield& lhs, const Heightfield& rhs) static inline bool operator==(const Heightfield& lhs, const Heightfield& rhs)
{ {
return makeTuple(lhs) == makeTuple(rhs); return makeTuple(lhs) == makeTuple(rhs);
@ -38,6 +50,16 @@ namespace DetourNavigator
return std::tie(lhs.mBounds, lhs.mHeight) == std::tie(rhs.mBounds, rhs.mHeight); return std::tie(lhs.mBounds, lhs.mHeight) == std::tie(rhs.mBounds, rhs.mHeight);
} }
static inline std::ostream& operator<<(std::ostream& s, const Water& v)
{
return s << "Water {" << v.mCellSize << ", " << v.mLevel << "}";
}
static inline std::ostream& operator<<(std::ostream& s, const CellWater& v)
{
return s << "CellWater {" << v.mCellPosition << ", " << v.mWater << "}";
}
static inline std::ostream& operator<<(std::ostream& s, const FlatHeightfield& v) static inline std::ostream& operator<<(std::ostream& s, const FlatHeightfield& v)
{ {
return s << "FlatHeightfield {" << v.mBounds << ", " << v.mHeight << "}"; return s << "FlatHeightfield {" << v.mBounds << ", " << v.mHeight << "}";
@ -435,10 +457,10 @@ namespace
TEST_F(DetourNavigatorRecastMeshBuilderTest, add_water_then_get_water_should_return_it) TEST_F(DetourNavigatorRecastMeshBuilderTest, add_water_then_get_water_should_return_it)
{ {
RecastMeshBuilder builder(mBounds); RecastMeshBuilder builder(mBounds);
builder.addWater(1000, osg::Vec3f(100, 200, 300)); 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(mGeneration, mRevision);
EXPECT_EQ(recastMesh->getWater(), std::vector<Cell>({ EXPECT_EQ(recastMesh->getWater(), std::vector<CellWater>({
Cell {1000, osg::Vec3f(100, 200, 300)} CellWater {osg::Vec2i(1, 2), Water {1000, 300.0f}}
})); }));
} }

View file

@ -264,7 +264,7 @@ namespace
TileCachedRecastMeshManager manager(mSettings); TileCachedRecastMeshManager manager(mSettings);
const osg::Vec2i cellPosition(0, 0); const osg::Vec2i cellPosition(0, 0);
const int cellSize = 8192; const int cellSize = 8192;
EXPECT_TRUE(manager.addWater(cellPosition, cellSize, osg::Vec3f())); EXPECT_TRUE(manager.addWater(cellPosition, cellSize, 0.0f));
} }
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, add_water_for_not_max_int_should_add_new_tiles) TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, add_water_for_not_max_int_should_add_new_tiles)
@ -272,9 +272,9 @@ namespace
TileCachedRecastMeshManager manager(mSettings); TileCachedRecastMeshManager manager(mSettings);
const osg::Vec2i cellPosition(0, 0); const osg::Vec2i cellPosition(0, 0);
const int cellSize = 8192; const int cellSize = 8192;
ASSERT_TRUE(manager.addWater(cellPosition, cellSize, osg::Vec3f())); ASSERT_TRUE(manager.addWater(cellPosition, cellSize, 0.0f));
for (int x = -6; x < 6; ++x) for (int x = -1; x < 12; ++x)
for (int y = -6; y < 6; ++y) for (int y = -1; y < 12; ++y)
ASSERT_NE(manager.getMesh(TilePosition(x, y)), nullptr); ASSERT_NE(manager.getMesh(TilePosition(x, y)), nullptr);
} }
@ -286,7 +286,7 @@ namespace
ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground)); ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground));
const osg::Vec2i cellPosition(0, 0); const osg::Vec2i cellPosition(0, 0);
const int cellSize = std::numeric_limits<int>::max(); const int cellSize = std::numeric_limits<int>::max();
ASSERT_TRUE(manager.addWater(cellPosition, cellSize, osg::Vec3f())); ASSERT_TRUE(manager.addWater(cellPosition, cellSize, 0.0f));
for (int x = -6; x < 6; ++x) for (int x = -6; x < 6; ++x)
for (int y = -6; y < 6; ++y) for (int y = -6; y < 6; ++y)
ASSERT_EQ(manager.getMesh(TilePosition(x, y)) != nullptr, -1 <= x && x <= 0 && -1 <= y && y <= 0); ASSERT_EQ(manager.getMesh(TilePosition(x, y)) != nullptr, -1 <= x && x <= 0 && -1 <= y && y <= 0);
@ -303,10 +303,10 @@ namespace
TileCachedRecastMeshManager manager(mSettings); TileCachedRecastMeshManager manager(mSettings);
const osg::Vec2i cellPosition(0, 0); const osg::Vec2i cellPosition(0, 0);
const int cellSize = 8192; const int cellSize = 8192;
ASSERT_TRUE(manager.addWater(cellPosition, cellSize, osg::Vec3f())); ASSERT_TRUE(manager.addWater(cellPosition, cellSize, 0.0f));
const auto result = manager.removeWater(cellPosition); const auto result = manager.removeWater(cellPosition);
ASSERT_TRUE(result.has_value()); ASSERT_TRUE(result.has_value());
EXPECT_EQ(result->mSize, cellSize); EXPECT_EQ(result->mCellSize, cellSize);
} }
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, remove_water_for_existing_cell_should_remove_empty_tiles) TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, remove_water_for_existing_cell_should_remove_empty_tiles)
@ -314,7 +314,7 @@ namespace
TileCachedRecastMeshManager manager(mSettings); TileCachedRecastMeshManager manager(mSettings);
const osg::Vec2i cellPosition(0, 0); const osg::Vec2i cellPosition(0, 0);
const int cellSize = 8192; const int cellSize = 8192;
ASSERT_TRUE(manager.addWater(cellPosition, cellSize, osg::Vec3f())); ASSERT_TRUE(manager.addWater(cellPosition, cellSize, 0.0f));
ASSERT_TRUE(manager.removeWater(cellPosition)); ASSERT_TRUE(manager.removeWater(cellPosition));
for (int x = -6; x < 6; ++x) for (int x = -6; x < 6; ++x)
for (int y = -6; y < 6; ++y) for (int y = -6; y < 6; ++y)
@ -329,7 +329,7 @@ namespace
ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground)); ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground));
const osg::Vec2i cellPosition(0, 0); const osg::Vec2i cellPosition(0, 0);
const int cellSize = 8192; const int cellSize = 8192;
ASSERT_TRUE(manager.addWater(cellPosition, cellSize, osg::Vec3f())); ASSERT_TRUE(manager.addWater(cellPosition, cellSize, 0.0f));
ASSERT_TRUE(manager.removeWater(cellPosition)); ASSERT_TRUE(manager.removeWater(cellPosition));
for (int x = -6; x < 6; ++x) for (int x = -6; x < 6; ++x)
for (int y = -6; y < 6; ++y) for (int y = -6; y < 6; ++y)
@ -344,10 +344,10 @@ namespace
const btBoxShape boxShape(btVector3(20, 20, 100)); const btBoxShape boxShape(btVector3(20, 20, 100));
const CollisionShape shape(nullptr, boxShape); const CollisionShape shape(nullptr, boxShape);
ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground)); ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground));
ASSERT_TRUE(manager.addWater(cellPosition, cellSize, osg::Vec3f())); ASSERT_TRUE(manager.addWater(cellPosition, cellSize, 0.0f));
ASSERT_TRUE(manager.removeObject(ObjectId(&boxShape))); ASSERT_TRUE(manager.removeObject(ObjectId(&boxShape)));
for (int x = -6; x < 6; ++x) for (int x = -1; x < 12; ++x)
for (int y = -6; y < 6; ++y) for (int y = -1; y < 12; ++y)
ASSERT_NE(manager.getMesh(TilePosition(x, y)), nullptr); ASSERT_NE(manager.getMesh(TilePosition(x, y)), nullptr);
} }
} }

View file

@ -32,16 +32,15 @@ namespace DetourNavigator
return object; return object;
} }
bool CachedRecastMeshManager::addWater(const osg::Vec2i& cellPosition, const int cellSize, bool CachedRecastMeshManager::addWater(const osg::Vec2i& cellPosition, int cellSize, float level)
const osg::Vec3f& shift)
{ {
if (!mImpl.addWater(cellPosition, cellSize, shift)) if (!mImpl.addWater(cellPosition, cellSize, level))
return false; return false;
mOutdatedCache = true; mOutdatedCache = true;
return true; return true;
} }
std::optional<Cell> CachedRecastMeshManager::removeWater(const osg::Vec2i& cellPosition) std::optional<Water> CachedRecastMeshManager::removeWater(const osg::Vec2i& cellPosition)
{ {
const auto water = mImpl.removeWater(cellPosition); const auto water = mImpl.removeWater(cellPosition);
if (water) if (water)

View file

@ -23,9 +23,9 @@ namespace DetourNavigator
std::optional<RemovedRecastMeshObject> removeObject(const ObjectId id); std::optional<RemovedRecastMeshObject> removeObject(const ObjectId id);
bool addWater(const osg::Vec2i& cellPosition, const int cellSize, const osg::Vec3f& shift); bool addWater(const osg::Vec2i& cellPosition, int cellSize, float level);
std::optional<Cell> removeWater(const osg::Vec2i& cellPosition); std::optional<Water> removeWater(const osg::Vec2i& cellPosition);
bool addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const osg::Vec3f& shift, bool addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const osg::Vec3f& shift,
const HeightfieldShape& shape); const HeightfieldShape& shape);

View file

@ -36,29 +36,28 @@ namespace
float mHeight; float mHeight;
}; };
Rectangle getSwimRectangle(const Cell& water, const Settings& settings, Rectangle getSwimRectangle(const CellWater& water, const Settings& settings, const osg::Vec3f& agentHalfExtents)
const osg::Vec3f& agentHalfExtents)
{ {
if (water.mSize == std::numeric_limits<int>::max()) if (water.mWater.mCellSize == std::numeric_limits<int>::max())
{ {
return Rectangle { return Rectangle {
TileBounds { TileBounds {
osg::Vec2f(-std::numeric_limits<float>::max(), -std::numeric_limits<float>::max()), osg::Vec2f(-std::numeric_limits<float>::max(), -std::numeric_limits<float>::max()),
osg::Vec2f(std::numeric_limits<float>::max(), std::numeric_limits<float>::max()) osg::Vec2f(std::numeric_limits<float>::max(), std::numeric_limits<float>::max())
}, },
toNavMeshCoordinates(settings, getSwimLevel(settings, water.mShift.z(), agentHalfExtents.z())) toNavMeshCoordinates(settings, getSwimLevel(settings, water.mWater.mLevel, agentHalfExtents.z()))
}; };
} }
else else
{ {
const osg::Vec2f shift(water.mShift.x(), water.mShift.y()); const osg::Vec2f shift = getWaterShift2d(water.mCellPosition, water.mWater.mCellSize);
const float halfCellSize = water.mSize / 2.0f; const float halfCellSize = water.mWater.mCellSize / 2.0f;
return Rectangle { return Rectangle {
TileBounds{ TileBounds{
toNavMeshCoordinates(settings, shift + osg::Vec2f(-halfCellSize, -halfCellSize)), toNavMeshCoordinates(settings, shift + osg::Vec2f(-halfCellSize, -halfCellSize)),
toNavMeshCoordinates(settings, shift + osg::Vec2f(halfCellSize, halfCellSize)) toNavMeshCoordinates(settings, shift + osg::Vec2f(halfCellSize, halfCellSize))
}, },
toNavMeshCoordinates(settings, getSwimLevel(settings, water.mShift.z(), agentHalfExtents.z())) toNavMeshCoordinates(settings, getSwimLevel(settings, water.mWater.mLevel, agentHalfExtents.z()))
}; };
} }
} }
@ -241,12 +240,12 @@ namespace
); );
} }
bool rasterizeTriangles(rcContext& context, const osg::Vec3f& agentHalfExtents, const std::vector<Cell>& cells, bool rasterizeTriangles(rcContext& context, const osg::Vec3f& agentHalfExtents, const std::vector<CellWater>& water,
const Settings& settings, const rcConfig& config, rcHeightfield& solid) const Settings& settings, const rcConfig& config, rcHeightfield& solid)
{ {
for (const Cell& cell : cells) for (const CellWater& cellWater : water)
{ {
const Rectangle rectangle = getSwimRectangle(cell, settings, agentHalfExtents); const Rectangle rectangle = getSwimRectangle(cellWater, settings, agentHalfExtents);
if (!rasterizeTriangles(context, rectangle, config, AreaType_water, solid)) if (!rasterizeTriangles(context, rectangle, config, AreaType_water, solid))
return false; return false;
} }
@ -404,9 +403,9 @@ namespace
maxZ = std::max(maxZ, vertices[i + 2]); maxZ = std::max(maxZ, vertices[i + 2]);
} }
for (const Cell& water : recastMesh.getWater()) for (const CellWater& water : recastMesh.getWater())
{ {
const float swimLevel = getSwimLevel(settings, water.mShift.z(), agentHalfExtents.z()); const float swimLevel = getSwimLevel(settings, water.mWater.mLevel, agentHalfExtents.z());
minZ = std::min(minZ, swimLevel); minZ = std::min(minZ, swimLevel);
maxZ = std::max(maxZ, swimLevel); maxZ = std::max(maxZ, swimLevel);
} }

View file

@ -122,7 +122,7 @@ namespace DetourNavigator
* at least single object is added to the scene, false if there is already water for given cell or there is no * at least single object is added to the scene, false if there is already water for given cell or there is no
* any other objects. * any other objects.
*/ */
virtual bool addWater(const osg::Vec2i& cellPosition, int cellSize, const osg::Vec3f& shift) = 0; virtual bool addWater(const osg::Vec2i& cellPosition, int cellSize, float level) = 0;
/** /**
* @brief removeWater to make it no more available at the scene. * @brief removeWater to make it no more available at the scene.

View file

@ -97,9 +97,9 @@ namespace DetourNavigator
return result; return result;
} }
bool NavigatorImpl::addWater(const osg::Vec2i& cellPosition, int cellSize, const osg::Vec3f& shift) bool NavigatorImpl::addWater(const osg::Vec2i& cellPosition, int cellSize, float level)
{ {
return mNavMeshManager.addWater(cellPosition, cellSize, shift); return mNavMeshManager.addWater(cellPosition, cellSize, level);
} }
bool NavigatorImpl::removeWater(const osg::Vec2i& cellPosition) bool NavigatorImpl::removeWater(const osg::Vec2i& cellPosition)

View file

@ -31,7 +31,7 @@ namespace DetourNavigator
bool removeObject(const ObjectId id) override; bool removeObject(const ObjectId id) override;
bool addWater(const osg::Vec2i& cellPosition, int cellSize, const osg::Vec3f& shift) override; bool addWater(const osg::Vec2i& cellPosition, int cellSize, float level) override;
bool removeWater(const osg::Vec2i& cellPosition) override; bool removeWater(const osg::Vec2i& cellPosition) override;

View file

@ -44,7 +44,7 @@ namespace DetourNavigator
return false; return false;
} }
bool addWater(const osg::Vec2i& /*cellPosition*/, int /*cellSize*/, const osg::Vec3f& /*shift*/) override bool addWater(const osg::Vec2i& /*cellPosition*/, int /*cellSize*/, float /*level*/) override
{ {
return false; return false;
} }

View file

@ -73,10 +73,11 @@ namespace DetourNavigator
return true; return true;
} }
bool NavMeshManager::addWater(const osg::Vec2i& cellPosition, const int cellSize, const osg::Vec3f& shift) bool NavMeshManager::addWater(const osg::Vec2i& cellPosition, int cellSize, float level)
{ {
if (!mRecastMeshManager.addWater(cellPosition, cellSize, shift)) if (!mRecastMeshManager.addWater(cellPosition, cellSize, level))
return false; return false;
const osg::Vec3f shift = getWaterShift3d(cellPosition, cellSize, level);
addChangedTiles(cellSize, shift, ChangeType::add); addChangedTiles(cellSize, shift, ChangeType::add);
return true; return true;
} }
@ -86,7 +87,8 @@ namespace DetourNavigator
const auto water = mRecastMeshManager.removeWater(cellPosition); const auto water = mRecastMeshManager.removeWater(cellPosition);
if (!water) if (!water)
return false; return false;
addChangedTiles(water->mSize, water->mShift, ChangeType::remove); const osg::Vec3f shift = getWaterShift3d(cellPosition, water->mCellSize, water->mLevel);
addChangedTiles(water->mCellSize, shift, ChangeType::remove);
return true; return true;
} }

View file

@ -34,7 +34,7 @@ namespace DetourNavigator
void addAgent(const osg::Vec3f& agentHalfExtents); void addAgent(const osg::Vec3f& agentHalfExtents);
bool addWater(const osg::Vec2i& cellPosition, const int cellSize, const osg::Vec3f& shift); bool addWater(const osg::Vec2i& cellPosition, int cellSize, float level);
bool removeWater(const osg::Vec2i& cellPosition); bool removeWater(const osg::Vec2i& cellPosition);

View file

@ -23,7 +23,7 @@ namespace DetourNavigator
struct RecastMeshData struct RecastMeshData
{ {
Mesh mMesh; Mesh mMesh;
std::vector<Cell> mWater; std::vector<CellWater> mWater;
std::vector<Heightfield> mHeightfields; std::vector<Heightfield> mHeightfields;
std::vector<FlatHeightfield> mFlatHeightfields; std::vector<FlatHeightfield> mFlatHeightfields;
}; };

View file

@ -18,7 +18,7 @@ namespace DetourNavigator
mAreaTypes = std::move(areaTypes); mAreaTypes = std::move(areaTypes);
} }
RecastMesh::RecastMesh(std::size_t generation, std::size_t revision, Mesh mesh, std::vector<Cell> water, RecastMesh::RecastMesh(std::size_t generation, std::size_t revision, Mesh mesh, std::vector<CellWater> water,
std::vector<Heightfield> heightfields, std::vector<FlatHeightfield> flatHeightfields) std::vector<Heightfield> heightfields, std::vector<FlatHeightfield> flatHeightfields)
: mGeneration(generation) : mGeneration(generation)
, mRevision(revision) , mRevision(revision)

View file

@ -8,6 +8,7 @@
#include <components/bullethelpers/operators.hpp> #include <components/bullethelpers/operators.hpp>
#include <osg/Vec3f> #include <osg/Vec3f>
#include <osg/Vec2i>
#include <memory> #include <memory>
#include <string> #include <string>
@ -53,6 +54,40 @@ namespace DetourNavigator
osg::Vec3f mShift; osg::Vec3f mShift;
}; };
struct Water
{
int mCellSize;
float mLevel;
};
inline bool operator<(const Water& lhs, const Water& rhs) noexcept
{
const auto tie = [] (const Water& v) { return std::tie(v.mCellSize, v.mLevel); };
return tie(lhs) < tie(rhs);
}
struct CellWater
{
osg::Vec2i mCellPosition;
Water mWater;
};
inline bool operator<(const CellWater& lhs, const CellWater& rhs) noexcept
{
const auto tie = [] (const CellWater& v) { return std::tie(v.mCellPosition, v.mWater); };
return tie(lhs) < tie(rhs);
}
inline osg::Vec2f getWaterShift2d(const osg::Vec2i& cellPosition, int cellSize)
{
return osg::Vec2f((cellPosition.x() + 0.5f) * cellSize, (cellPosition.y() + 0.5f) * cellSize);
}
inline osg::Vec3f getWaterShift3d(const osg::Vec2i& cellPosition, int cellSize, float level)
{
return osg::Vec3f(getWaterShift2d(cellPosition, cellSize), level);
}
struct Heightfield struct Heightfield
{ {
TileBounds mBounds; TileBounds mBounds;
@ -88,7 +123,7 @@ namespace DetourNavigator
class RecastMesh class RecastMesh
{ {
public: public:
RecastMesh(std::size_t generation, std::size_t revision, Mesh mesh, std::vector<Cell> water, RecastMesh(std::size_t generation, std::size_t revision, Mesh mesh, std::vector<CellWater> water,
std::vector<Heightfield> heightfields, std::vector<FlatHeightfield> flatHeightfields); std::vector<Heightfield> heightfields, std::vector<FlatHeightfield> flatHeightfields);
std::size_t getGeneration() const std::size_t getGeneration() const
@ -103,7 +138,7 @@ namespace DetourNavigator
const Mesh& getMesh() const noexcept { return mMesh; } const Mesh& getMesh() const noexcept { return mMesh; }
const std::vector<Cell>& getWater() const const std::vector<CellWater>& getWater() const
{ {
return mWater; return mWater;
} }
@ -122,13 +157,13 @@ namespace DetourNavigator
std::size_t mGeneration; std::size_t mGeneration;
std::size_t mRevision; std::size_t mRevision;
Mesh mMesh; Mesh mMesh;
std::vector<Cell> mWater; std::vector<CellWater> mWater;
std::vector<Heightfield> mHeightfields; std::vector<Heightfield> mHeightfields;
std::vector<FlatHeightfield> mFlatHeightfields; std::vector<FlatHeightfield> mFlatHeightfields;
friend inline std::size_t getSize(const RecastMesh& value) noexcept friend inline std::size_t getSize(const RecastMesh& value) noexcept
{ {
return getSize(value.mMesh) + value.mWater.size() * sizeof(Cell) return getSize(value.mMesh) + value.mWater.size() * sizeof(CellWater)
+ value.mHeightfields.size() * sizeof(Heightfield) + value.mHeightfields.size() * sizeof(Heightfield)
+ std::accumulate(value.mHeightfields.begin(), value.mHeightfields.end(), std::size_t {0}, + std::accumulate(value.mHeightfields.begin(), value.mHeightfields.end(), std::size_t {0},
[] (std::size_t r, const Heightfield& v) { return r + v.mHeights.size() * sizeof(float); }) [] (std::size_t r, const Heightfield& v) { return r + v.mHeights.size() * sizeof(float); })

View file

@ -200,9 +200,9 @@ namespace DetourNavigator
} }
} }
void RecastMeshBuilder::addWater(const int cellSize, const osg::Vec3f& shift) void RecastMeshBuilder::addWater(const osg::Vec2i& cellPosition, const Water& water)
{ {
mWater.push_back(Cell {cellSize, shift}); mWater.push_back(CellWater {cellPosition, water});
} }
void RecastMeshBuilder::addHeightfield(int cellSize, const osg::Vec3f& shift, float height) void RecastMeshBuilder::addHeightfield(int cellSize, const osg::Vec3f& shift, float height)

View file

@ -48,7 +48,7 @@ namespace DetourNavigator
void addObject(const btBoxShape& shape, const btTransform& transform, const AreaType areaType); void addObject(const btBoxShape& shape, const btTransform& transform, const AreaType areaType);
void addWater(const int mCellSize, const osg::Vec3f& shift); void addWater(const osg::Vec2i& cellPosition, const Water& water);
void addHeightfield(int cellSize, const osg::Vec3f& shift, float height); void addHeightfield(int cellSize, const osg::Vec3f& shift, float height);
@ -60,7 +60,7 @@ namespace DetourNavigator
private: private:
const TileBounds mBounds; const TileBounds mBounds;
std::vector<RecastMeshTriangle> mTriangles; std::vector<RecastMeshTriangle> mTriangles;
std::vector<Cell> mWater; std::vector<CellWater> mWater;
std::vector<Heightfield> mHeightfields; std::vector<Heightfield> mHeightfields;
std::vector<FlatHeightfield> mFlatHeightfields; std::vector<FlatHeightfield> mFlatHeightfields;

View file

@ -73,23 +73,23 @@ namespace DetourNavigator
return result; return result;
} }
bool RecastMeshManager::addWater(const osg::Vec2i& cellPosition, const int cellSize, const osg::Vec3f& shift) bool RecastMeshManager::addWater(const osg::Vec2i& cellPosition, int cellSize, float level)
{ {
const std::lock_guard lock(mMutex); const std::lock_guard lock(mMutex);
if (!mWater.emplace(cellPosition, Cell {cellSize, shift}).second) if (!mWater.emplace(cellPosition, Water {cellSize, level}).second)
return false; return false;
++mRevision; ++mRevision;
return true; return true;
} }
std::optional<Cell> RecastMeshManager::removeWater(const osg::Vec2i& cellPosition) std::optional<Water> RecastMeshManager::removeWater(const osg::Vec2i& cellPosition)
{ {
const std::lock_guard lock(mMutex); const std::lock_guard lock(mMutex);
const auto water = mWater.find(cellPosition); const auto water = mWater.find(cellPosition);
if (water == mWater.end()) if (water == mWater.end())
return std::nullopt; return std::nullopt;
++mRevision; ++mRevision;
const Cell result = water->second; Water result = water->second;
mWater.erase(water); mWater.erase(water);
return result; return result;
} }
@ -130,7 +130,7 @@ namespace DetourNavigator
{ {
const std::lock_guard lock(mMutex); const std::lock_guard lock(mMutex);
for (const auto& [k, v] : mWater) for (const auto& [k, v] : mWater)
builder.addWater(v.mSize, v.mShift); builder.addWater(k, v);
for (const auto& [cellPosition, v] : mHeightfields) for (const auto& [cellPosition, v] : mHeightfields)
std::visit(AddHeightfield {v.mCell, builder}, v.mShape); std::visit(AddHeightfield {v.mCell, builder}, v.mShape);
objects.reserve(mObjects.size()); objects.reserve(mObjects.size());

View file

@ -41,9 +41,9 @@ namespace DetourNavigator
std::optional<RemovedRecastMeshObject> removeObject(const ObjectId id); std::optional<RemovedRecastMeshObject> removeObject(const ObjectId id);
bool addWater(const osg::Vec2i& cellPosition, const int cellSize, const osg::Vec3f& shift); bool addWater(const osg::Vec2i& cellPosition, int cellSize, float level);
std::optional<Cell> removeWater(const osg::Vec2i& cellPosition); std::optional<Water> removeWater(const osg::Vec2i& cellPosition);
bool addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const osg::Vec3f& shift, bool addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const osg::Vec3f& shift,
const HeightfieldShape& shape); const HeightfieldShape& shape);
@ -76,7 +76,7 @@ namespace DetourNavigator
mutable std::mutex mMutex; mutable std::mutex mMutex;
std::size_t mRevision = 0; std::size_t mRevision = 0;
std::map<ObjectId, OscillatingRecastMeshObject> mObjects; std::map<ObjectId, OscillatingRecastMeshObject> mObjects;
std::map<osg::Vec2i, Cell> mWater; std::map<osg::Vec2i, Water> mWater;
std::map<osg::Vec2i, Heightfield> mHeightfields; std::map<osg::Vec2i, Heightfield> mHeightfields;
std::optional<Report> mLastNavMeshReportedChange; std::optional<Report> mLastNavMeshReportedChange;
std::optional<Report> mLastNavMeshReport; std::optional<Report> mLastNavMeshReport;

View file

@ -54,8 +54,7 @@ namespace DetourNavigator
return result; return result;
} }
bool TileCachedRecastMeshManager::addWater(const osg::Vec2i& cellPosition, const int cellSize, bool TileCachedRecastMeshManager::addWater(const osg::Vec2i& cellPosition, int cellSize, float level)
const osg::Vec3f& shift)
{ {
auto& tilesPositions = mWaterTilesPositions[cellPosition]; auto& tilesPositions = mWaterTilesPositions[cellPosition];
@ -66,7 +65,7 @@ namespace DetourNavigator
const auto tiles = mTiles.lock(); const auto tiles = mTiles.lock();
for (auto& tile : *tiles) for (auto& tile : *tiles)
{ {
if (tile.second->addWater(cellPosition, cellSize, shift)) if (tile.second->addWater(cellPosition, cellSize, level))
{ {
tilesPositions.push_back(tile.first); tilesPositions.push_back(tile.first);
result = true; result = true;
@ -75,6 +74,7 @@ namespace DetourNavigator
} }
else else
{ {
const osg::Vec3f shift = getWaterShift3d(cellPosition, cellSize, level);
getTilesPositions(cellSize, shift, mSettings, [&] (const TilePosition& tilePosition) getTilesPositions(cellSize, shift, mSettings, [&] (const TilePosition& tilePosition)
{ {
const auto tiles = mTiles.lock(); const auto tiles = mTiles.lock();
@ -85,7 +85,7 @@ namespace DetourNavigator
tile = tiles->emplace(tilePosition, tile = tiles->emplace(tilePosition,
std::make_shared<CachedRecastMeshManager>(tileBounds, mTilesGeneration)).first; std::make_shared<CachedRecastMeshManager>(tileBounds, mTilesGeneration)).first;
} }
if (tile->second->addWater(cellPosition, cellSize, shift)) if (tile->second->addWater(cellPosition, cellSize, level))
{ {
tilesPositions.push_back(tilePosition); tilesPositions.push_back(tilePosition);
result = true; result = true;
@ -99,12 +99,12 @@ namespace DetourNavigator
return result; return result;
} }
std::optional<Cell> TileCachedRecastMeshManager::removeWater(const osg::Vec2i& cellPosition) std::optional<Water> TileCachedRecastMeshManager::removeWater(const osg::Vec2i& cellPosition)
{ {
const auto object = mWaterTilesPositions.find(cellPosition); const auto object = mWaterTilesPositions.find(cellPosition);
if (object == mWaterTilesPositions.end()) if (object == mWaterTilesPositions.end())
return std::nullopt; return std::nullopt;
std::optional<Cell> result; std::optional<Water> result;
for (const auto& tilePosition : object->second) for (const auto& tilePosition : object->second)
{ {
const auto tiles = mTiles.lock(); const auto tiles = mTiles.lock();

View file

@ -76,9 +76,9 @@ namespace DetourNavigator
std::optional<RemovedRecastMeshObject> removeObject(const ObjectId id); std::optional<RemovedRecastMeshObject> removeObject(const ObjectId id);
bool addWater(const osg::Vec2i& cellPosition, const int cellSize, const osg::Vec3f& shift); bool addWater(const osg::Vec2i& cellPosition, int cellSize, float level);
std::optional<Cell> removeWater(const osg::Vec2i& cellPosition); std::optional<Water> removeWater(const osg::Vec2i& cellPosition);
bool addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const osg::Vec3f& shift, bool addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const osg::Vec3f& shift,
const HeightfieldShape& shape); const HeightfieldShape& shape);