mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-18 13:12:50 +00:00
Merge branch 'navigator_check_agent_bounds' into 'master'
Check agent bounds on adding agent to navigator See merge request OpenMW/openmw!2629
This commit is contained in:
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…
x
Reference in New Issue
Block a user