mirror of
https://github.com/OpenMW/openmw.git
synced 2025-03-01 03:39:42 +00:00
Check agent bounds on adding agent to navigator
Do not add agent bounds which are not supported by recastnavigation with given settings and log such events. To avoid reaching navmesh tile generation to find out it can't be generated for such agent bounds.
This commit is contained in:
parent
a7e37509de
commit
cf1d8544e3
9 changed files with 113 additions and 65 deletions
|
@ -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…
Reference in a new issue