|
|
|
@ -70,6 +70,22 @@ namespace
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
constexpr std::array<float, 5 * 5> defaultHeightfieldData{ {
|
|
|
|
|
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
|
|
|
|
|
} };
|
|
|
|
|
|
|
|
|
|
constexpr std::array<btScalar, 5 * 5> defaultHeightfieldDataScalar{ {
|
|
|
|
|
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
|
|
|
|
|
} };
|
|
|
|
|
|
|
|
|
|
template <std::size_t size>
|
|
|
|
|
std::unique_ptr<btHeightfieldTerrainShape> makeSquareHeightfieldTerrainShape(
|
|
|
|
|
const std::array<btScalar, size>& values, btScalar heightScale = 1, int upAxis = 2,
|
|
|
|
@ -150,14 +166,7 @@ namespace
|
|
|
|
|
|
|
|
|
|
TEST_F(DetourNavigatorNavigatorTest, update_then_find_path_should_return_path)
|
|
|
|
|
{
|
|
|
|
|
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 HeightfieldSurface surface = makeSquareHeightfieldSurface(defaultHeightfieldData);
|
|
|
|
|
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
|
|
|
|
@ -177,20 +186,31 @@ namespace
|
|
|
|
|
<< mPath;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(DetourNavigatorNavigatorTest, find_path_to_the_start_position_should_contain_single_point)
|
|
|
|
|
{
|
|
|
|
|
const HeightfieldSurface surface = makeSquareHeightfieldSurface(defaultHeightfieldData);
|
|
|
|
|
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
|
|
|
|
|
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, mAgentBounds, mStart, mStart, Flag_walk, mAreaCosts, mEndTolerance, mOut),
|
|
|
|
|
Status::Success);
|
|
|
|
|
|
|
|
|
|
EXPECT_THAT(mPath, ElementsAre(Vec3fEq(56.66666412353515625, 460, 1.99998295307159423828125))) << mPath;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(DetourNavigatorNavigatorTest, add_object_should_change_navmesh)
|
|
|
|
|
{
|
|
|
|
|
mSettings.mWaitUntilMinDistanceToPlayer = 0;
|
|
|
|
|
mNavigator.reset(new NavigatorImpl(
|
|
|
|
|
mSettings, std::make_unique<NavMeshDb>(":memory:", std::numeric_limits<std::uint64_t>::max())));
|
|
|
|
|
|
|
|
|
|
const std::array<float, 5 * 5> heightfieldData{ {
|
|
|
|
|
0, 0, 0, 0, 0, // 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 HeightfieldSurface surface = makeSquareHeightfieldSurface(defaultHeightfieldData);
|
|
|
|
|
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
|
|
|
|
|
|
|
|
|
CollisionShapeInstance compound(std::make_unique<btCompoundShape>());
|
|
|
|
@ -235,14 +255,7 @@ namespace
|
|
|
|
|
|
|
|
|
|
TEST_F(DetourNavigatorNavigatorTest, update_changed_object_should_change_navmesh)
|
|
|
|
|
{
|
|
|
|
|
const 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 HeightfieldSurface surface = makeSquareHeightfieldSurface(defaultHeightfieldData);
|
|
|
|
|
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
|
|
|
|
|
|
|
|
|
CollisionShapeInstance compound(std::make_unique<btCompoundShape>());
|
|
|
|
@ -288,14 +301,7 @@ namespace
|
|
|
|
|
|
|
|
|
|
TEST_F(DetourNavigatorNavigatorTest, for_overlapping_heightfields_objects_should_use_higher)
|
|
|
|
|
{
|
|
|
|
|
const std::array<btScalar, 5 * 5> heightfieldData1{ {
|
|
|
|
|
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
|
|
|
|
|
} };
|
|
|
|
|
CollisionShapeInstance heightfield1(makeSquareHeightfieldTerrainShape(heightfieldData1));
|
|
|
|
|
CollisionShapeInstance heightfield1(makeSquareHeightfieldTerrainShape(defaultHeightfieldDataScalar));
|
|
|
|
|
heightfield1.shape().setLocalScaling(btVector3(128, 128, 1));
|
|
|
|
|
|
|
|
|
|
const std::array<btScalar, 5 * 5> heightfieldData2{ {
|
|
|
|
@ -328,14 +334,7 @@ namespace
|
|
|
|
|
|
|
|
|
|
TEST_F(DetourNavigatorNavigatorTest, only_one_heightfield_per_cell_is_allowed)
|
|
|
|
|
{
|
|
|
|
|
const std::array<float, 5 * 5> heightfieldData1{ {
|
|
|
|
|
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 surface1 = makeSquareHeightfieldSurface(heightfieldData1);
|
|
|
|
|
const HeightfieldSurface surface1 = makeSquareHeightfieldSurface(defaultHeightfieldData);
|
|
|
|
|
const int cellSize1 = mHeightfieldTileSize * (surface1.mSize - 1);
|
|
|
|
|
|
|
|
|
|
const std::array<float, 5 * 5> heightfieldData2{ {
|
|
|
|
@ -366,14 +365,8 @@ namespace
|
|
|
|
|
{
|
|
|
|
|
osg::ref_ptr<Resource::BulletShape> bulletShape(new Resource::BulletShape);
|
|
|
|
|
|
|
|
|
|
std::array<btScalar, 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
|
|
|
|
|
} };
|
|
|
|
|
std::unique_ptr<btHeightfieldTerrainShape> shapePtr = makeSquareHeightfieldTerrainShape(heightfieldData);
|
|
|
|
|
std::unique_ptr<btHeightfieldTerrainShape> shapePtr
|
|
|
|
|
= makeSquareHeightfieldTerrainShape(defaultHeightfieldDataScalar);
|
|
|
|
|
shapePtr->setLocalScaling(btVector3(128, 128, 1));
|
|
|
|
|
bulletShape->mCollisionShape.reset(shapePtr.release());
|
|
|
|
|
|
|
|
|
@ -542,14 +535,7 @@ namespace
|
|
|
|
|
|
|
|
|
|
TEST_F(DetourNavigatorNavigatorTest, update_object_remove_and_update_then_find_path_should_return_path)
|
|
|
|
|
{
|
|
|
|
|
const std::array<btScalar, 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
|
|
|
|
|
} };
|
|
|
|
|
CollisionShapeInstance heightfield(makeSquareHeightfieldTerrainShape(heightfieldData));
|
|
|
|
|
CollisionShapeInstance heightfield(makeSquareHeightfieldTerrainShape(defaultHeightfieldDataScalar));
|
|
|
|
|
heightfield.shape().setLocalScaling(btVector3(128, 128, 1));
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
|
|
|
|
@ -579,14 +565,7 @@ namespace
|
|
|
|
|
|
|
|
|
|
TEST_F(DetourNavigatorNavigatorTest, update_heightfield_remove_and_update_then_find_path_should_return_path)
|
|
|
|
|
{
|
|
|
|
|
const 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 HeightfieldSurface surface = makeSquareHeightfieldSurface(defaultHeightfieldData);
|
|
|
|
|
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
|
|
|
|
@ -649,14 +628,7 @@ namespace
|
|
|
|
|
mNavigator.reset(new NavigatorImpl(
|
|
|
|
|
mSettings, std::make_unique<NavMeshDb>(":memory:", std::numeric_limits<std::uint64_t>::max())));
|
|
|
|
|
|
|
|
|
|
const std::array<float, 5 * 5> heightfieldData{ {
|
|
|
|
|
0, 0, 0, 0, 0, // 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 HeightfieldSurface surface = makeSquareHeightfieldSurface(defaultHeightfieldData);
|
|
|
|
|
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
|
|
|
|
const btVector3 shift = getHeightfieldShift(mCellPosition, cellSize, surface.mMinHeight, surface.mMaxHeight);
|
|
|
|
|
|
|
|
|
@ -745,14 +717,7 @@ namespace
|
|
|
|
|
|
|
|
|
|
TEST_F(DetourNavigatorNavigatorTest, update_then_raycast_should_return_position)
|
|
|
|
|
{
|
|
|
|
|
const 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 HeightfieldSurface surface = makeSquareHeightfieldSurface(defaultHeightfieldData);
|
|
|
|
|
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
|
|
|
|
@ -771,14 +736,7 @@ namespace
|
|
|
|
|
TEST_F(DetourNavigatorNavigatorTest,
|
|
|
|
|
update_for_oscillating_object_that_does_not_change_navmesh_should_not_trigger_navmesh_update)
|
|
|
|
|
{
|
|
|
|
|
const 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 HeightfieldSurface surface = makeSquareHeightfieldSurface(defaultHeightfieldData);
|
|
|
|
|
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
|
|
|
|
|
|
|
|
|
CollisionShapeInstance oscillatingBox(std::make_unique<btBoxShape>(btVector3(20, 20, 20)));
|
|
|
|
@ -837,14 +795,7 @@ namespace
|
|
|
|
|
|
|
|
|
|
TEST_F(DetourNavigatorNavigatorTest, for_not_reachable_destination_find_path_should_provide_partial_path)
|
|
|
|
|
{
|
|
|
|
|
const 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 HeightfieldSurface surface = makeSquareHeightfieldSurface(defaultHeightfieldData);
|
|
|
|
|
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
|
|
|
|
|
|
|
|
|
CollisionShapeInstance compound(std::make_unique<btCompoundShape>());
|
|
|
|
@ -870,14 +821,7 @@ namespace
|
|
|
|
|
|
|
|
|
|
TEST_F(DetourNavigatorNavigatorTest, end_tolerance_should_extent_available_destinations)
|
|
|
|
|
{
|
|
|
|
|
const 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 HeightfieldSurface surface = makeSquareHeightfieldSurface(defaultHeightfieldData);
|
|
|
|
|
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
|
|
|
|
|
|
|
|
|
CollisionShapeInstance compound(std::make_unique<btCompoundShape>());
|
|
|
|
@ -1000,4 +944,58 @@ namespace
|
|
|
|
|
|
|
|
|
|
INSTANTIATE_TEST_SUITE_P(NotSupportedAgentBounds, DetourNavigatorNavigatorNotSupportedAgentBoundsTest,
|
|
|
|
|
ValuesIn(notSupportedAgentBounds));
|
|
|
|
|
|
|
|
|
|
TEST_F(DetourNavigatorNavigatorTest, find_nearest_nav_mesh_position_should_return_nav_mesh_position)
|
|
|
|
|
{
|
|
|
|
|
const HeightfieldSurface surface = makeSquareHeightfieldSurface(defaultHeightfieldData);
|
|
|
|
|
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
|
|
|
|
|
auto updateGuard = mNavigator->makeUpdateGuard();
|
|
|
|
|
mNavigator->addHeightfield(mCellPosition, cellSize, surface, updateGuard.get());
|
|
|
|
|
mNavigator->update(mPlayerPosition, updateGuard.get());
|
|
|
|
|
updateGuard.reset();
|
|
|
|
|
mNavigator->wait(WaitConditionType::requiredTilesPresent, &mListener);
|
|
|
|
|
|
|
|
|
|
const osg::Vec3f position(250, 250, 0);
|
|
|
|
|
const osg::Vec3f searchAreaHalfExtents(1000, 1000, 1000);
|
|
|
|
|
EXPECT_THAT(findNearestNavMeshPosition(*mNavigator, mAgentBounds, position, searchAreaHalfExtents, Flag_walk),
|
|
|
|
|
Optional(Vec3fEq(250, 250, -62.5186)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(DetourNavigatorNavigatorTest, find_nearest_nav_mesh_position_should_return_nullopt_when_too_far)
|
|
|
|
|
{
|
|
|
|
|
const HeightfieldSurface surface = makeSquareHeightfieldSurface(defaultHeightfieldData);
|
|
|
|
|
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
|
|
|
|
|
auto updateGuard = mNavigator->makeUpdateGuard();
|
|
|
|
|
mNavigator->addHeightfield(mCellPosition, cellSize, surface, updateGuard.get());
|
|
|
|
|
mNavigator->update(mPlayerPosition, updateGuard.get());
|
|
|
|
|
updateGuard.reset();
|
|
|
|
|
mNavigator->wait(WaitConditionType::requiredTilesPresent, &mListener);
|
|
|
|
|
|
|
|
|
|
const osg::Vec3f position(250, 250, 250);
|
|
|
|
|
const osg::Vec3f searchAreaHalfExtents(100, 100, 100);
|
|
|
|
|
EXPECT_EQ(findNearestNavMeshPosition(*mNavigator, mAgentBounds, position, searchAreaHalfExtents, Flag_walk),
|
|
|
|
|
std::nullopt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(DetourNavigatorNavigatorTest, find_nearest_nav_mesh_position_should_return_nullopt_when_flags_do_not_match)
|
|
|
|
|
{
|
|
|
|
|
const HeightfieldSurface surface = makeSquareHeightfieldSurface(defaultHeightfieldData);
|
|
|
|
|
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(mNavigator->addAgent(mAgentBounds));
|
|
|
|
|
auto updateGuard = mNavigator->makeUpdateGuard();
|
|
|
|
|
mNavigator->addHeightfield(mCellPosition, cellSize, surface, updateGuard.get());
|
|
|
|
|
mNavigator->update(mPlayerPosition, updateGuard.get());
|
|
|
|
|
updateGuard.reset();
|
|
|
|
|
mNavigator->wait(WaitConditionType::requiredTilesPresent, &mListener);
|
|
|
|
|
|
|
|
|
|
const osg::Vec3f position(250, 250, 0);
|
|
|
|
|
const osg::Vec3f searchAreaHalfExtents(1000, 1000, 1000);
|
|
|
|
|
EXPECT_EQ(findNearestNavMeshPosition(*mNavigator, mAgentBounds, position, searchAreaHalfExtents, Flag_swim),
|
|
|
|
|
std::nullopt);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|