Merge branch 'navigator_check_agent_bounds' into 'master'

Check agent bounds on adding agent to navigator

See merge request OpenMW/openmw!2629
7220-lua-add-a-general-purpose-lexical-parser
psi29a 2 years ago
commit fbeacc1e0f

@ -8,6 +8,7 @@
#include <components/debug/debuglog.hpp>
#include <components/detournavigator/agentbounds.hpp>
#include <components/detournavigator/debug.hpp>
#include <components/detournavigator/heightfieldshape.hpp>
#include <components/detournavigator/navigator.hpp>
#include <components/detournavigator/navigatorimpl.hpp>
@ -184,7 +185,9 @@ namespace
}
else if (physics.getActor(ptr))
{
navigator.addAgent(world.getPathfindingAgentBounds(ptr));
const DetourNavigator::AgentBounds agentBounds = world.getPathfindingAgentBounds(ptr);
if (!navigator.addAgent(agentBounds))
Log(Debug::Warning) << "Agent bounds are not supported by navigator: " << agentBounds;
}
}

@ -40,6 +40,7 @@
#include <components/sceneutil/workqueue.hpp>
#include <components/detournavigator/agentbounds.hpp>
#include <components/detournavigator/debug.hpp>
#include <components/detournavigator/navigator.hpp>
#include <components/detournavigator/navigatorimpl.hpp>
#include <components/detournavigator/settings.hpp>
@ -1269,7 +1270,11 @@ namespace MWWorld
mWorldScene->updateObjectScale(ptr);
if (mPhysics->getActor(ptr))
mNavigator->addAgent(getPathfindingAgentBounds(ptr));
{
const DetourNavigator::AgentBounds agentBounds = getPathfindingAgentBounds(ptr);
if (!mNavigator->addAgent(agentBounds))
Log(Debug::Warning) << "Scaled agent bounds are not supported by navigator: " << agentBounds;
}
else if (const auto object = mPhysics->getObject(ptr))
updateNavigatorObject(*object);
}
@ -2435,7 +2440,9 @@ namespace MWWorld
applyLoopingParticles(player);
mNavigator->addAgent(getPathfindingAgentBounds(getPlayerConstPtr()));
const DetourNavigator::AgentBounds agentBounds = getPathfindingAgentBounds(getPlayerConstPtr());
if (!mNavigator->addAgent(agentBounds))
Log(Debug::Warning) << "Player agent bounds are not supported by navigator: " << agentBounds;
}
World::RestPermitted World::canRest() const

@ -135,7 +135,7 @@ namespace
TEST_F(DetourNavigatorNavigatorTest, find_path_for_existing_agent_with_no_navmesh_should_throw_exception)
{
mNavigator->addAgent(mAgentBounds);
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
EXPECT_EQ(
findPath(*mNavigator, mAgentBounds, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut),
Status::StartPolygonNotFound);
@ -143,8 +143,8 @@ namespace
TEST_F(DetourNavigatorNavigatorTest, add_agent_should_count_each_agent)
{
mNavigator->addAgent(mAgentBounds);
mNavigator->addAgent(mAgentBounds);
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
mNavigator->removeAgent(mAgentBounds);
EXPECT_EQ(
findPath(*mNavigator, mAgentBounds, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut),
@ -163,7 +163,7 @@ namespace
const HeightfieldSurface surface = makeSquareHeightfieldSurface(heightfieldData);
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
mNavigator->addAgent(mAgentBounds);
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
auto updateGuard = mNavigator->makeUpdateGuard();
mNavigator->addHeightfield(mCellPosition, cellSize, surface, updateGuard.get());
mNavigator->update(mPlayerPosition, updateGuard.get());
@ -220,7 +220,7 @@ namespace
compound.shape().addChildShape(
btTransform(btMatrix3x3::getIdentity(), btVector3(0, 0, 0)), new btBoxShape(btVector3(20, 20, 100)));
mNavigator->addAgent(mAgentBounds);
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
mNavigator->update(mPlayerPosition, nullptr);
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
@ -311,7 +311,7 @@ namespace
compound.shape().addChildShape(
btTransform(btMatrix3x3::getIdentity(), btVector3(0, 0, 0)), new btBoxShape(btVector3(20, 20, 100)));
mNavigator->addAgent(mAgentBounds);
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
mNavigator->addObject(
ObjectId(&compound.shape()), ObjectShapes(compound.instance(), mObjectTransform), mTransform, nullptr);
@ -409,7 +409,7 @@ namespace
CollisionShapeInstance heightfield2(makeSquareHeightfieldTerrainShape(heightfieldData2));
heightfield2.shape().setLocalScaling(btVector3(128, 128, 1));
mNavigator->addAgent(mAgentBounds);
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
mNavigator->addObject(ObjectId(&heightfield1.shape()), ObjectShapes(heightfield1.instance(), mObjectTransform),
mTransform, nullptr);
mNavigator->addObject(ObjectId(&heightfield2.shape()), ObjectShapes(heightfield2.instance(), mObjectTransform),
@ -469,7 +469,7 @@ namespace
const HeightfieldSurface surface2 = makeSquareHeightfieldSurface(heightfieldData2);
const int cellSize2 = mHeightfieldTileSize * (surface2.mSize - 1);
mNavigator->addAgent(mAgentBounds);
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
mNavigator->addHeightfield(mCellPosition, cellSize1, surface1, nullptr);
mNavigator->update(mPlayerPosition, nullptr);
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
@ -512,7 +512,7 @@ namespace
osg::ref_ptr<const Resource::BulletShapeInstance> instance(new Resource::BulletShapeInstance(bulletShape));
mNavigator->addAgent(mAgentBounds);
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
mNavigator->addObject(
ObjectId(instance->mCollisionShape.get()), ObjectShapes(instance, mObjectTransform), mTransform, nullptr);
mNavigator->update(mPlayerPosition, nullptr);
@ -561,7 +561,7 @@ namespace
const HeightfieldSurface surface = makeSquareHeightfieldSurface(heightfieldData);
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
mNavigator->addAgent(mAgentBounds);
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
mNavigator->addWater(mCellPosition, cellSize, 300, nullptr);
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
mNavigator->update(mPlayerPosition, nullptr);
@ -605,7 +605,7 @@ namespace
const HeightfieldSurface surface = makeSquareHeightfieldSurface(heightfieldData);
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
mNavigator->addAgent(mAgentBounds);
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
mNavigator->addWater(mCellPosition, cellSize, -25, nullptr);
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
mNavigator->update(mPlayerPosition, nullptr);
@ -648,7 +648,7 @@ namespace
const HeightfieldSurface surface = makeSquareHeightfieldSurface(heightfieldData);
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
mNavigator->addAgent(mAgentBounds);
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
mNavigator->addWater(mCellPosition, std::numeric_limits<int>::max(), -25, nullptr);
mNavigator->update(mPlayerPosition, nullptr);
@ -690,7 +690,7 @@ namespace
const HeightfieldSurface surface = makeSquareHeightfieldSurface(heightfieldData);
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
mNavigator->addAgent(mAgentBounds);
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
mNavigator->addWater(mCellPosition, cellSize, -25, nullptr);
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
mNavigator->update(mPlayerPosition, nullptr);
@ -730,7 +730,7 @@ namespace
CollisionShapeInstance heightfield(makeSquareHeightfieldTerrainShape(heightfieldData));
heightfield.shape().setLocalScaling(btVector3(128, 128, 1));
mNavigator->addAgent(mAgentBounds);
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
mNavigator->addObject(ObjectId(&heightfield.shape()), ObjectShapes(heightfield.instance(), mObjectTransform),
mTransform, nullptr);
mNavigator->update(mPlayerPosition, nullptr);
@ -787,7 +787,7 @@ namespace
const HeightfieldSurface surface = makeSquareHeightfieldSurface(heightfieldData);
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
mNavigator->addAgent(mAgentBounds);
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
mNavigator->update(mPlayerPosition, nullptr);
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
@ -843,7 +843,7 @@ namespace
const HeightfieldSurface surface = makeSquareHeightfieldSurface(heightfieldData);
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
mNavigator->addAgent(mAgentBounds);
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
mNavigator->update(mPlayerPosition, nullptr);
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
@ -882,7 +882,7 @@ namespace
std::generate_n(
std::back_inserter(boxes), 100, [] { return std::make_unique<btBoxShape>(btVector3(20, 20, 100)); });
mNavigator->addAgent(mAgentBounds);
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
@ -944,7 +944,7 @@ namespace
std::generate_n(
std::back_inserter(shapes), 100, [] { return std::make_unique<btBoxShape>(btVector3(64, 64, 64)); });
mNavigator->addAgent(mAgentBounds);
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
for (std::size_t i = 0; i < shapes.size(); ++i)
{
@ -992,7 +992,7 @@ namespace
const HeightfieldSurface surface = makeSquareHeightfieldSurface(heightfieldData);
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
mNavigator->addAgent(mAgentBounds);
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
mNavigator->update(mPlayerPosition, nullptr);
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
@ -1022,7 +1022,7 @@ namespace
const btVector3 oscillatingBoxShapePosition(288, 288, 400);
CollisionShapeInstance borderBox(std::make_unique<btBoxShape>(btVector3(50, 50, 50)));
mNavigator->addAgent(mAgentBounds);
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
mNavigator->addObject(ObjectId(&oscillatingBox.shape()),
ObjectShapes(oscillatingBox.instance(), mObjectTransform),
@ -1058,7 +1058,7 @@ namespace
const HeightfieldPlane plane{ 100 };
const int cellSize = mHeightfieldTileSize * 4;
mNavigator->addAgent(mAgentBounds);
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
mNavigator->addHeightfield(mCellPosition, cellSize, plane, nullptr);
mNavigator->update(mPlayerPosition, nullptr);
mNavigator->wait(WaitConditionType::requiredTilesPresent, &mListener);
@ -1109,7 +1109,7 @@ namespace
compound.shape().addChildShape(btTransform(btMatrix3x3::getIdentity(), btVector3(204, -204, 0)),
new btBoxShape(btVector3(200, 200, 1000)));
mNavigator->addAgent(mAgentBounds);
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
mNavigator->addObject(
ObjectId(&compound.shape()), ObjectShapes(compound.instance(), mObjectTransform), mTransform, nullptr);
@ -1150,7 +1150,7 @@ namespace
compound.shape().addChildShape(btTransform(btMatrix3x3::getIdentity(), btVector3(204, -204, 0)),
new btBoxShape(btVector3(100, 100, 1000)));
mNavigator->addAgent(mAgentBounds);
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
mNavigator->addObject(
ObjectId(&compound.shape()), ObjectShapes(compound.instance(), mObjectTransform), mTransform, nullptr);
@ -1192,7 +1192,7 @@ namespace
const int cellSize2 = 200;
const float level2 = 2;
mNavigator->addAgent(mAgentBounds);
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
mNavigator->addWater(mCellPosition, cellSize1, level1, nullptr);
mNavigator->update(mPlayerPosition, nullptr);
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
@ -1206,31 +1206,6 @@ namespace
EXPECT_EQ(mNavigator->getNavMesh(mAgentBounds)->lockConst()->getVersion(), version);
}
TEST_F(DetourNavigatorNavigatorTest, add_agent_with_zero_coordinate_should_not_have_nav_mesh)
{
constexpr std::array<float, 5 * 5> heightfieldData{ {
0, 0, 0, 0, 0, // row 0
0, -25, -25, -25, -25, // row 1
0, -25, -100, -100, -100, // row 2
0, -25, -100, -100, -100, // row 3
0, -25, -100, -100, -100, // row 4
} };
const HeightfieldSurface surface = makeSquareHeightfieldSurface(heightfieldData);
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
const AgentBounds agentBounds{ CollisionShapeType::RotatingBox, { 0, 1, 1 } };
mNavigator->addAgent(agentBounds);
auto updateGuard = mNavigator->makeUpdateGuard();
mNavigator->addHeightfield(mCellPosition, cellSize, surface, updateGuard.get());
mNavigator->update(mPlayerPosition, updateGuard.get());
updateGuard.reset();
mNavigator->wait(WaitConditionType::requiredTilesPresent, &mListener);
EXPECT_EQ(
findPath(*mNavigator, agentBounds, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut),
Status::NavMeshNotFound);
}
TEST_F(DetourNavigatorNavigatorTest, update_for_very_big_object_should_be_limited)
{
const float size = static_cast<float>(2 * static_cast<std::int64_t>(std::numeric_limits<int>::max()) - 1);
@ -1241,7 +1216,7 @@ namespace
};
mNavigator->updateBounds(mPlayerPosition, nullptr);
mNavigator->addAgent(mAgentBounds);
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
mNavigator->addObject(ObjectId(&bigBox.shape()), ObjectShapes(bigBox.instance(), objectTransform),
btTransform::getIdentity(), nullptr);
@ -1275,4 +1250,36 @@ namespace
navMesh->lockConst()->forEachUsedTile([&](const auto&...) { ++usedNavMeshTiles; });
EXPECT_EQ(usedNavMeshTiles, 509);
}
struct DetourNavigatorNavigatorNotSupportedAgentBoundsTest : TestWithParam<AgentBounds>
{
};
TEST_P(DetourNavigatorNavigatorNotSupportedAgentBoundsTest, on_add_agent)
{
const Settings settings = makeSettings();
NavigatorImpl navigator(settings, nullptr);
EXPECT_FALSE(navigator.addAgent(GetParam()));
}
const std::array notSupportedAgentBounds = {
AgentBounds{ .mShapeType = CollisionShapeType::Aabb, .mHalfExtents = osg::Vec3f(0, 0, 0) },
AgentBounds{ .mShapeType = CollisionShapeType::RotatingBox, .mHalfExtents = osg::Vec3f(0, 0, 0) },
AgentBounds{ .mShapeType = CollisionShapeType::Cylinder, .mHalfExtents = osg::Vec3f(0, 0, 0) },
AgentBounds{ .mShapeType = CollisionShapeType::Aabb, .mHalfExtents = osg::Vec3f(0, 0, 11.34f) },
AgentBounds{ .mShapeType = CollisionShapeType::RotatingBox, .mHalfExtents = osg::Vec3f(0, 11.34f, 11.34f) },
AgentBounds{ .mShapeType = CollisionShapeType::Cylinder, .mHalfExtents = osg::Vec3f(0, 0, 11.34f) },
AgentBounds{ .mShapeType = CollisionShapeType::Aabb, .mHalfExtents = osg::Vec3f(1, 1, 0) },
AgentBounds{ .mShapeType = CollisionShapeType::RotatingBox, .mHalfExtents = osg::Vec3f(1, 1, 0) },
AgentBounds{ .mShapeType = CollisionShapeType::Cylinder, .mHalfExtents = osg::Vec3f(1, 1, 0) },
AgentBounds{ .mShapeType = CollisionShapeType::Aabb, .mHalfExtents = osg::Vec3f(1, 1, 11.33f) },
AgentBounds{ .mShapeType = CollisionShapeType::RotatingBox, .mHalfExtents = osg::Vec3f(1, 1, 11.33f) },
AgentBounds{ .mShapeType = CollisionShapeType::Cylinder, .mHalfExtents = osg::Vec3f(1, 1, 11.33f) },
AgentBounds{ .mShapeType = CollisionShapeType::Aabb, .mHalfExtents = osg::Vec3f(2043.54f, 2043.54f, 11.34f) },
AgentBounds{ .mShapeType = CollisionShapeType::RotatingBox, .mHalfExtents = osg::Vec3f(2890, 1, 11.34f) },
AgentBounds{ .mShapeType = CollisionShapeType::Cylinder, .mHalfExtents = osg::Vec3f(2890, 2890, 11.34f) },
};
INSTANTIATE_TEST_SUITE_P(NotSupportedAgentBounds, DetourNavigatorNavigatorNotSupportedAgentBoundsTest,
ValuesIn(notSupportedAgentBounds));
}

@ -31,6 +31,8 @@ namespace DetourNavigator
{
namespace
{
constexpr int walkableRadiusUpperLimit = 255;
struct Rectangle
{
TileBounds mBounds;
@ -114,6 +116,16 @@ namespace DetourNavigator
return waterLevel - settings.mSwimHeightScale * agentHalfExtentsZ - agentHalfExtentsZ;
}
int getWalkableHeight(const RecastSettings& settings, const AgentBounds& agentBounds)
{
return static_cast<int>(std::ceil(getHeight(settings, agentBounds) / settings.mCellHeight));
}
int getWalkableRadius(const RecastSettings& settings, const AgentBounds& agentBounds)
{
return static_cast<int>(std::ceil(getRadius(settings, agentBounds) / settings.mCellSize));
}
struct RecastParams
{
float mSampleDist = 0;
@ -128,10 +140,9 @@ namespace DetourNavigator
{
RecastParams result;
result.mWalkableHeight
= static_cast<int>(std::ceil(getHeight(settings, agentBounds) / settings.mCellHeight));
result.mWalkableHeight = getWalkableHeight(settings, agentBounds);
result.mWalkableClimb = static_cast<int>(std::floor(getMaxClimb(settings) / settings.mCellHeight));
result.mWalkableRadius = static_cast<int>(std::ceil(getRadius(settings, agentBounds) / settings.mCellSize));
result.mWalkableRadius = getWalkableRadius(settings, agentBounds);
result.mMaxEdgeLen
= static_cast<int>(std::round(static_cast<float>(settings.mMaxEdgeLen) / settings.mCellSize));
result.mSampleDist
@ -288,10 +299,15 @@ namespace DetourNavigator
context, realTileBounds, recastMesh.getFlatHeightfields(), settings, params, solid);
}
bool isValidWalkableHeight(int value)
{
return value >= 3;
}
[[nodiscard]] bool buildCompactHeightfield(RecastContext& context, const int walkableHeight,
const int walkableClimb, rcHeightfield& solid, rcCompactHeightfield& compact)
{
if (walkableHeight < 3)
if (!isValidWalkableHeight(walkableHeight))
{
Log(Debug::Warning) << context.getPrefix()
<< "Invalid walkableHeight to build compact heightfield: " << walkableHeight;
@ -308,9 +324,14 @@ namespace DetourNavigator
return rcBuildCompactHeightfield(&context, walkableHeight, walkableClimb, solid, compact);
}
bool isValidWalkableRadius(int value)
{
return 0 < value && value < walkableRadiusUpperLimit;
}
[[nodiscard]] bool erodeWalkableArea(RecastContext& context, int walkableRadius, rcCompactHeightfield& compact)
{
if (walkableRadius <= 0 || 255 <= walkableRadius)
if (!isValidWalkableRadius(walkableRadius))
{
Log(Debug::Warning) << context.getPrefix()
<< "Invalid walkableRadius to erode walkable area: " << walkableRadius;
@ -614,4 +635,10 @@ namespace DetourNavigator
return navMesh;
}
bool isSupportedAgentBounds(const RecastSettings& settings, const AgentBounds& agentBounds)
{
return isValidWalkableHeight(getWalkableHeight(settings, agentBounds))
&& isValidWalkableRadius(getWalkableRadius(settings, agentBounds));
}
}

@ -50,6 +50,8 @@ namespace DetourNavigator
const TilePosition& tile, const RecastSettings& settings);
NavMeshPtr makeEmptyNavMesh(const Settings& settings);
bool isSupportedAgentBounds(const RecastSettings& settings, const AgentBounds& agentBounds);
}
#endif

@ -77,8 +77,9 @@ namespace DetourNavigator
* @brief addAgent should be called for each agent even if all of them has same half extents.
* @param agentBounds allows to setup bounding cylinder for each agent, for each different half extents
* there is different navmesh.
* @return true if agent is successfully added or false if agent bounds are not supported.
*/
virtual void addAgent(const AgentBounds& agentBounds) = 0;
virtual bool addAgent(const AgentBounds& agentBounds) = 0;
/**
* @brief removeAgent should be called for each agent even if all of them has same half extents

@ -1,4 +1,5 @@
#include "navigatorimpl.hpp"
#include "makenavmesh.hpp"
#include "settingsutils.hpp"
#include "stats.hpp"
@ -15,13 +16,13 @@ namespace DetourNavigator
{
}
void NavigatorImpl::addAgent(const AgentBounds& agentBounds)
bool NavigatorImpl::addAgent(const AgentBounds& agentBounds)
{
if (agentBounds.mHalfExtents.x() == 0.f || agentBounds.mHalfExtents.y() == 0.f
|| agentBounds.mHalfExtents.z() == 0.f)
return;
if (!isSupportedAgentBounds(mSettings.mRecast, agentBounds))
return false;
++mAgents[agentBounds];
mNavMeshManager.addAgent(agentBounds);
return true;
}
void NavigatorImpl::removeAgent(const AgentBounds& agentBounds)

@ -23,7 +23,7 @@ namespace DetourNavigator
return std::make_unique<const UpdateGuard>(*this);
}
void addAgent(const AgentBounds& agentBounds) override;
bool addAgent(const AgentBounds& agentBounds) override;
void removeAgent(const AgentBounds& agentBounds) override;

@ -19,7 +19,7 @@ namespace DetourNavigator
std::unique_ptr<const UpdateGuard> makeUpdateGuard() override { return nullptr; }
void addAgent(const AgentBounds& /*agentBounds*/) override {}
bool addAgent(const AgentBounds& /*agentBounds*/) override { return true; }
void removeAgent(const AgentBounds& /*agentBounds*/) override {}

Loading…
Cancel
Save