mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-10 03:39:55 +00:00
Merge branch 'navmesh_reduce_lock_wait' into 'master'
Reduce waiting duration on locks when updating navmesh object in the main thread (#6193) Closes #6193 See merge request OpenMW/openmw!1079
This commit is contained in:
commit
e10e9c0005
@ -151,11 +151,9 @@ namespace
|
||||
{
|
||||
if (ptr.getClass().isDoor() && !ptr.getCellRef().getTeleport())
|
||||
{
|
||||
const auto shape = object->getShapeInstance()->getCollisionShape();
|
||||
|
||||
btVector3 aabbMin;
|
||||
btVector3 aabbMax;
|
||||
shape->getAabb(btTransform::getIdentity(), aabbMin, aabbMax);
|
||||
object->getShapeInstance()->getCollisionShape()->getAabb(btTransform::getIdentity(), aabbMin, aabbMax);
|
||||
|
||||
const auto center = (aabbMax + aabbMin) * 0.5f;
|
||||
|
||||
@ -182,12 +180,7 @@ namespace
|
||||
|
||||
navigator.addObject(
|
||||
DetourNavigator::ObjectId(object),
|
||||
DetourNavigator::DoorShapes(
|
||||
*shape,
|
||||
object->getShapeInstance()->getAvoidCollisionShape(),
|
||||
connectionStart,
|
||||
connectionEnd
|
||||
),
|
||||
DetourNavigator::DoorShapes(object->getShapeInstance(), connectionStart, connectionEnd),
|
||||
transform
|
||||
);
|
||||
}
|
||||
@ -195,10 +188,7 @@ namespace
|
||||
{
|
||||
navigator.addObject(
|
||||
DetourNavigator::ObjectId(object),
|
||||
DetourNavigator::ObjectShapes {
|
||||
*object->getShapeInstance()->getCollisionShape(),
|
||||
object->getShapeInstance()->getAvoidCollisionShape()
|
||||
},
|
||||
DetourNavigator::ObjectShapes(object->getShapeInstance()),
|
||||
object->getTransform()
|
||||
);
|
||||
}
|
||||
|
@ -1533,10 +1533,7 @@ namespace MWWorld
|
||||
|
||||
void World::updateNavigatorObject(const MWPhysics::Object& object)
|
||||
{
|
||||
const DetourNavigator::ObjectShapes shapes {
|
||||
*object.getShapeInstance()->getCollisionShape(),
|
||||
object.getShapeInstance()->getAvoidCollisionShape()
|
||||
};
|
||||
const DetourNavigator::ObjectShapes shapes(object.getShapeInstance());
|
||||
mShouldUpdateNavigator = mNavigator->updateObject(DetourNavigator::ObjectId(&object), shapes, object.getTransform())
|
||||
|| mShouldUpdateNavigator;
|
||||
}
|
||||
|
@ -5,6 +5,9 @@
|
||||
#include <components/misc/rng.hpp>
|
||||
#include <components/loadinglistener/loadinglistener.hpp>
|
||||
#include <components/esm/loadland.hpp>
|
||||
#include <components/resource/bulletshape.hpp>
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
|
||||
#include <BulletCollision/CollisionShapes/btBoxShape.h>
|
||||
@ -15,6 +18,7 @@
|
||||
|
||||
#include <array>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
|
||||
MATCHER_P3(Vec3fEq, x, y, z, "")
|
||||
{
|
||||
@ -84,14 +88,15 @@ namespace
|
||||
};
|
||||
|
||||
template <std::size_t size>
|
||||
btHeightfieldTerrainShape makeSquareHeightfieldTerrainShape(const std::array<btScalar, size>& values,
|
||||
std::unique_ptr<btHeightfieldTerrainShape> makeSquareHeightfieldTerrainShape(const std::array<btScalar, size>& values,
|
||||
btScalar heightScale = 1, int upAxis = 2, PHY_ScalarType heightDataType = PHY_FLOAT, bool flipQuadEdges = false)
|
||||
{
|
||||
const int width = static_cast<int>(std::sqrt(size));
|
||||
const btScalar min = *std::min_element(values.begin(), values.end());
|
||||
const btScalar max = *std::max_element(values.begin(), values.end());
|
||||
const btScalar greater = std::max(std::abs(min), std::abs(max));
|
||||
return btHeightfieldTerrainShape(width, width, values.data(), heightScale, -greater, greater, upAxis, heightDataType, flipQuadEdges);
|
||||
return std::make_unique<btHeightfieldTerrainShape>(width, width, values.data(), heightScale, -greater, greater,
|
||||
upAxis, heightDataType, flipQuadEdges);
|
||||
}
|
||||
|
||||
template <std::size_t size>
|
||||
@ -107,6 +112,27 @@ namespace
|
||||
return surface;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
osg::ref_ptr<const Resource::BulletShapeInstance> makeBulletShapeInstance(std::unique_ptr<T>&& shape)
|
||||
{
|
||||
osg::ref_ptr<Resource::BulletShape> bulletShape(new Resource::BulletShape);
|
||||
bulletShape->mCollisionShape = std::move(shape).release();
|
||||
return new Resource::BulletShapeInstance(bulletShape);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class CollisionShapeInstance
|
||||
{
|
||||
public:
|
||||
CollisionShapeInstance(std::unique_ptr<T>&& shape) : mInstance(makeBulletShapeInstance(std::move(shape))) {}
|
||||
|
||||
T& shape() { return static_cast<T&>(*mInstance->mCollisionShape); }
|
||||
const osg::ref_ptr<const Resource::BulletShapeInstance>& instance() const { return mInstance; }
|
||||
|
||||
private:
|
||||
osg::ref_ptr<const Resource::BulletShapeInstance> mInstance;
|
||||
};
|
||||
|
||||
TEST_F(DetourNavigatorNavigatorTest, find_path_for_empty_should_return_empty)
|
||||
{
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut),
|
||||
@ -185,9 +211,8 @@ namespace
|
||||
}};
|
||||
const HeightfieldSurface surface = makeSquareHeightfieldSurface(heightfieldData);
|
||||
|
||||
btBoxShape boxShape(btVector3(20, 20, 100));
|
||||
btCompoundShape compoundShape;
|
||||
compoundShape.addChildShape(btTransform(btMatrix3x3::getIdentity(), btVector3(0, 0, 0)), &boxShape);
|
||||
CollisionShapeInstance compound(std::make_unique<btCompoundShape>());
|
||||
compound.shape().addChildShape(btTransform(btMatrix3x3::getIdentity(), btVector3(0, 0, 0)), new btBoxShape(btVector3(20, 20, 100)));
|
||||
|
||||
mNavigator->addAgent(mAgentHalfExtents);
|
||||
mNavigator->addHeightfield(mCellPosition, mHeightfieldTileSize * (surface.mSize - 1), mShift, surface);
|
||||
@ -221,7 +246,7 @@ namespace
|
||||
Vec3fEq(204, -204, 1.99998295307159423828125)
|
||||
)) << mPath;
|
||||
|
||||
mNavigator->addObject(ObjectId(&compoundShape), compoundShape, btTransform::getIdentity());
|
||||
mNavigator->addObject(ObjectId(&compound.shape()), ObjectShapes(compound.instance()), btTransform::getIdentity());
|
||||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||
|
||||
@ -267,13 +292,12 @@ namespace
|
||||
}};
|
||||
const HeightfieldSurface surface = makeSquareHeightfieldSurface(heightfieldData);
|
||||
|
||||
btBoxShape boxShape(btVector3(20, 20, 100));
|
||||
btCompoundShape compoundShape;
|
||||
compoundShape.addChildShape(btTransform(btMatrix3x3::getIdentity(), btVector3(0, 0, 0)), &boxShape);
|
||||
CollisionShapeInstance compound(std::make_unique<btCompoundShape>());
|
||||
compound.shape().addChildShape(btTransform(btMatrix3x3::getIdentity(), btVector3(0, 0, 0)), new btBoxShape(btVector3(20, 20, 100)));
|
||||
|
||||
mNavigator->addAgent(mAgentHalfExtents);
|
||||
mNavigator->addHeightfield(mCellPosition, mHeightfieldTileSize * (surface.mSize - 1), mShift, surface);
|
||||
mNavigator->addObject(ObjectId(&compoundShape), compoundShape, btTransform::getIdentity());
|
||||
mNavigator->addObject(ObjectId(&compound.shape()), ObjectShapes(compound.instance()), btTransform::getIdentity());
|
||||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||
|
||||
@ -305,9 +329,9 @@ namespace
|
||||
Vec3fEq(204, -204, 1.99998295307159423828125)
|
||||
)) << mPath;
|
||||
|
||||
compoundShape.updateChildTransform(0, btTransform(btMatrix3x3::getIdentity(), btVector3(1000, 0, 0)));
|
||||
compound.shape().updateChildTransform(0, btTransform(btMatrix3x3::getIdentity(), btVector3(1000, 0, 0)));
|
||||
|
||||
mNavigator->updateObject(ObjectId(&compoundShape), compoundShape, btTransform::getIdentity());
|
||||
mNavigator->updateObject(ObjectId(&compound.shape()), ObjectShapes(compound.instance()), btTransform::getIdentity());
|
||||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||
|
||||
@ -350,8 +374,8 @@ namespace
|
||||
0, -25, -100, -100, -100,
|
||||
0, -25, -100, -100, -100,
|
||||
}};
|
||||
btHeightfieldTerrainShape shape = makeSquareHeightfieldTerrainShape(heightfieldData1);
|
||||
shape.setLocalScaling(btVector3(128, 128, 1));
|
||||
CollisionShapeInstance heightfield1(makeSquareHeightfieldTerrainShape(heightfieldData1));
|
||||
heightfield1.shape().setLocalScaling(btVector3(128, 128, 1));
|
||||
|
||||
const std::array<btScalar, 5 * 5> heightfieldData2 {{
|
||||
-25, -25, -25, -25, -25,
|
||||
@ -360,12 +384,12 @@ namespace
|
||||
-25, -25, -25, -25, -25,
|
||||
-25, -25, -25, -25, -25,
|
||||
}};
|
||||
btHeightfieldTerrainShape shape2 = makeSquareHeightfieldTerrainShape(heightfieldData2);
|
||||
shape2.setLocalScaling(btVector3(128, 128, 1));
|
||||
CollisionShapeInstance heightfield2(makeSquareHeightfieldTerrainShape(heightfieldData2));
|
||||
heightfield2.shape().setLocalScaling(btVector3(128, 128, 1));
|
||||
|
||||
mNavigator->addAgent(mAgentHalfExtents);
|
||||
mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity());
|
||||
mNavigator->addObject(ObjectId(&shape2), shape2, btTransform::getIdentity());
|
||||
mNavigator->addObject(ObjectId(&heightfield1.shape()), ObjectShapes(heightfield1.instance()), btTransform::getIdentity());
|
||||
mNavigator->addObject(ObjectId(&heightfield2.shape()), ObjectShapes(heightfield2.instance()), btTransform::getIdentity());
|
||||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||
|
||||
@ -424,6 +448,8 @@ namespace
|
||||
|
||||
TEST_F(DetourNavigatorNavigatorTest, path_should_be_around_avoid_shape)
|
||||
{
|
||||
osg::ref_ptr<Resource::BulletShape> bulletShape(new Resource::BulletShape);
|
||||
|
||||
std::array<btScalar, 5 * 5> heightfieldData {{
|
||||
0, 0, 0, 0, 0,
|
||||
0, -25, -25, -25, -25,
|
||||
@ -431,8 +457,9 @@ namespace
|
||||
0, -25, -100, -100, -100,
|
||||
0, -25, -100, -100, -100,
|
||||
}};
|
||||
btHeightfieldTerrainShape shape = makeSquareHeightfieldTerrainShape(heightfieldData);
|
||||
shape.setLocalScaling(btVector3(128, 128, 1));
|
||||
std::unique_ptr<btHeightfieldTerrainShape> shapePtr = makeSquareHeightfieldTerrainShape(heightfieldData);
|
||||
shapePtr->setLocalScaling(btVector3(128, 128, 1));
|
||||
bulletShape->mCollisionShape = shapePtr.release();
|
||||
|
||||
std::array<btScalar, 5 * 5> heightfieldDataAvoid {{
|
||||
-25, -25, -25, -25, -25,
|
||||
@ -441,11 +468,14 @@ namespace
|
||||
-25, -25, -25, -25, -25,
|
||||
-25, -25, -25, -25, -25,
|
||||
}};
|
||||
btHeightfieldTerrainShape shapeAvoid = makeSquareHeightfieldTerrainShape(heightfieldDataAvoid);
|
||||
shapeAvoid.setLocalScaling(btVector3(128, 128, 1));
|
||||
std::unique_ptr<btHeightfieldTerrainShape> shapeAvoidPtr = makeSquareHeightfieldTerrainShape(heightfieldDataAvoid);
|
||||
shapeAvoidPtr->setLocalScaling(btVector3(128, 128, 1));
|
||||
bulletShape->mAvoidCollisionShape = shapeAvoidPtr.release();
|
||||
|
||||
osg::ref_ptr<const Resource::BulletShapeInstance> instance(new Resource::BulletShapeInstance(bulletShape));
|
||||
|
||||
mNavigator->addAgent(mAgentHalfExtents);
|
||||
mNavigator->addObject(ObjectId(&shape), ObjectShapes {shape, &shapeAvoid}, btTransform::getIdentity());
|
||||
mNavigator->addObject(ObjectId(instance->getCollisionShape()), ObjectShapes(instance), btTransform::getIdentity());
|
||||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||
|
||||
@ -666,19 +696,19 @@ namespace
|
||||
0, -25, -100, -100, -100,
|
||||
0, -25, -100, -100, -100,
|
||||
}};
|
||||
btHeightfieldTerrainShape shape = makeSquareHeightfieldTerrainShape(heightfieldData);
|
||||
shape.setLocalScaling(btVector3(128, 128, 1));
|
||||
CollisionShapeInstance heightfield(makeSquareHeightfieldTerrainShape(heightfieldData));
|
||||
heightfield.shape().setLocalScaling(btVector3(128, 128, 1));
|
||||
|
||||
mNavigator->addAgent(mAgentHalfExtents);
|
||||
mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity());
|
||||
mNavigator->addObject(ObjectId(&heightfield.shape()), ObjectShapes(heightfield.instance()), btTransform::getIdentity());
|
||||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||
|
||||
mNavigator->removeObject(ObjectId(&shape));
|
||||
mNavigator->removeObject(ObjectId(&heightfield.shape()));
|
||||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||
|
||||
mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity());
|
||||
mNavigator->addObject(ObjectId(&heightfield.shape()), ObjectShapes(heightfield.instance()), btTransform::getIdentity());
|
||||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||
|
||||
@ -804,24 +834,25 @@ namespace
|
||||
}};
|
||||
const HeightfieldSurface surface = makeSquareHeightfieldSurface(heightfieldData);
|
||||
|
||||
const std::vector<btBoxShape> boxShapes(100, btVector3(20, 20, 100));
|
||||
std::vector<CollisionShapeInstance<btBoxShape>> boxes;
|
||||
std::generate_n(std::back_inserter(boxes), 100, [] { return std::make_unique<btBoxShape>(btVector3(20, 20, 100)); });
|
||||
|
||||
mNavigator->addAgent(mAgentHalfExtents);
|
||||
|
||||
mNavigator->addHeightfield(mCellPosition, mHeightfieldTileSize * (surface.mSize - 1), mShift, surface);
|
||||
|
||||
for (std::size_t i = 0; i < boxShapes.size(); ++i)
|
||||
for (std::size_t i = 0; i < boxes.size(); ++i)
|
||||
{
|
||||
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(i * 10, i * 10, i * 10));
|
||||
mNavigator->addObject(ObjectId(&boxShapes[i]), boxShapes[i], transform);
|
||||
mNavigator->addObject(ObjectId(&boxes[i].shape()), ObjectShapes(boxes[i].instance()), transform);
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(1));
|
||||
|
||||
for (std::size_t i = 0; i < boxShapes.size(); ++i)
|
||||
for (std::size_t i = 0; i < boxes.size(); ++i)
|
||||
{
|
||||
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(i * 10 + 1, i * 10 + 1, i * 10 + 1));
|
||||
mNavigator->updateObject(ObjectId(&boxShapes[i]), boxShapes[i], transform);
|
||||
mNavigator->updateObject(ObjectId(&boxes[i].shape()), ObjectShapes(boxes[i].instance()), transform);
|
||||
}
|
||||
|
||||
mNavigator->update(mPlayerPosition);
|
||||
@ -858,14 +889,15 @@ namespace
|
||||
|
||||
TEST_F(DetourNavigatorNavigatorTest, update_changed_multiple_times_object_should_delay_navmesh_change)
|
||||
{
|
||||
const std::vector<btBoxShape> shapes(100, btVector3(64, 64, 64));
|
||||
std::vector<CollisionShapeInstance<btBoxShape>> shapes;
|
||||
std::generate_n(std::back_inserter(shapes), 100, [] { return std::make_unique<btBoxShape>(btVector3(64, 64, 64)); });
|
||||
|
||||
mNavigator->addAgent(mAgentHalfExtents);
|
||||
|
||||
for (std::size_t i = 0; i < shapes.size(); ++i)
|
||||
{
|
||||
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(i * 32, i * 32, i * 32));
|
||||
mNavigator->addObject(ObjectId(&shapes[i]), shapes[i], transform);
|
||||
mNavigator->addObject(ObjectId(&shapes[i].shape()), ObjectShapes(shapes[i].instance()), transform);
|
||||
}
|
||||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||
@ -874,7 +906,7 @@ namespace
|
||||
for (std::size_t i = 0; i < shapes.size(); ++i)
|
||||
{
|
||||
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(i * 32 + 1, i * 32 + 1, i * 32 + 1));
|
||||
mNavigator->updateObject(ObjectId(&shapes[i]), shapes[i], transform);
|
||||
mNavigator->updateObject(ObjectId(&shapes[i].shape()), ObjectShapes(shapes[i].instance()), transform);
|
||||
}
|
||||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||
@ -882,7 +914,7 @@ namespace
|
||||
for (std::size_t i = 0; i < shapes.size(); ++i)
|
||||
{
|
||||
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(i * 32 + 2, i * 32 + 2, i * 32 + 2));
|
||||
mNavigator->updateObject(ObjectId(&shapes[i]), shapes[i], transform);
|
||||
mNavigator->updateObject(ObjectId(&shapes[i].shape()), ObjectShapes(shapes[i].instance()), transform);
|
||||
}
|
||||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||
@ -926,16 +958,16 @@ namespace
|
||||
}};
|
||||
const HeightfieldSurface surface = makeSquareHeightfieldSurface(heightfieldData);
|
||||
|
||||
const btBoxShape oscillatingBoxShape(btVector3(20, 20, 20));
|
||||
CollisionShapeInstance oscillatingBox(std::make_unique<btBoxShape>(btVector3(20, 20, 20)));
|
||||
const btVector3 oscillatingBoxShapePosition(32, 32, 400);
|
||||
const btBoxShape boderBoxShape(btVector3(50, 50, 50));
|
||||
CollisionShapeInstance boderBox(std::make_unique<btBoxShape>(btVector3(50, 50, 50)));
|
||||
|
||||
mNavigator->addAgent(mAgentHalfExtents);
|
||||
mNavigator->addHeightfield(mCellPosition, mHeightfieldTileSize * (surface.mSize - 1), mShift, surface);
|
||||
mNavigator->addObject(ObjectId(&oscillatingBoxShape), oscillatingBoxShape,
|
||||
mNavigator->addObject(ObjectId(&oscillatingBox.shape()), ObjectShapes(oscillatingBox.instance()),
|
||||
btTransform(btMatrix3x3::getIdentity(), oscillatingBoxShapePosition));
|
||||
// add this box to make navmesh bound box independent from oscillatingBoxShape rotations
|
||||
mNavigator->addObject(ObjectId(&boderBoxShape), boderBoxShape,
|
||||
mNavigator->addObject(ObjectId(&boderBox.shape()), ObjectShapes(boderBox.instance()),
|
||||
btTransform(btMatrix3x3::getIdentity(), oscillatingBoxShapePosition + btVector3(0, 0, 200)));
|
||||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||
@ -952,7 +984,7 @@ namespace
|
||||
{
|
||||
const btTransform transform(btQuaternion(btVector3(0, 0, 1), n * 2 * osg::PI / 10),
|
||||
oscillatingBoxShapePosition);
|
||||
mNavigator->updateObject(ObjectId(&oscillatingBoxShape), oscillatingBoxShape, transform);
|
||||
mNavigator->updateObject(ObjectId(&oscillatingBox.shape()), ObjectShapes(oscillatingBox.instance()), transform);
|
||||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
||||
}
|
||||
|
@ -14,20 +14,22 @@ namespace
|
||||
|
||||
struct DetourNavigatorRecastMeshObjectTest : Test
|
||||
{
|
||||
btBoxShape mBoxShape {btVector3(1, 2, 3)};
|
||||
btCompoundShape mCompoundShape {true};
|
||||
btBoxShape mBoxShapeImpl {btVector3(1, 2, 3)};
|
||||
CollisionShape mBoxShape {nullptr, mBoxShapeImpl};
|
||||
btCompoundShape mCompoundShapeImpl {true};
|
||||
CollisionShape mCompoundShape {nullptr, mCompoundShapeImpl};
|
||||
btTransform mTransform {btQuaternion(btVector3(1, 2, 3), 1), btVector3(1, 2, 3)};
|
||||
|
||||
DetourNavigatorRecastMeshObjectTest()
|
||||
{
|
||||
mCompoundShape.addChildShape(mTransform, std::addressof(mBoxShape));
|
||||
mCompoundShapeImpl.addChildShape(mTransform, std::addressof(mBoxShapeImpl));
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(DetourNavigatorRecastMeshObjectTest, constructed_object_should_have_shape_and_transform)
|
||||
{
|
||||
const RecastMeshObject object(mBoxShape, mTransform, AreaType_ground);
|
||||
EXPECT_EQ(std::addressof(object.getShape()), std::addressof(mBoxShape));
|
||||
EXPECT_EQ(std::addressof(object.getShape()), std::addressof(mBoxShapeImpl));
|
||||
EXPECT_EQ(object.getTransform(), mTransform);
|
||||
}
|
||||
|
||||
@ -58,14 +60,14 @@ namespace
|
||||
TEST_F(DetourNavigatorRecastMeshObjectTest, update_for_compound_shape_with_same_transform_and_changed_child_transform_should_return_true)
|
||||
{
|
||||
RecastMeshObject object(mCompoundShape, mTransform, AreaType_ground);
|
||||
mCompoundShape.updateChildTransform(0, btTransform::getIdentity());
|
||||
mCompoundShapeImpl.updateChildTransform(0, btTransform::getIdentity());
|
||||
EXPECT_TRUE(object.update(mTransform, AreaType_ground));
|
||||
}
|
||||
|
||||
TEST_F(DetourNavigatorRecastMeshObjectTest, repeated_update_for_compound_shape_without_changes_should_return_false)
|
||||
{
|
||||
RecastMeshObject object(mCompoundShape, mTransform, AreaType_ground);
|
||||
mCompoundShape.updateChildTransform(0, btTransform::getIdentity());
|
||||
mCompoundShapeImpl.updateChildTransform(0, btTransform::getIdentity());
|
||||
object.update(mTransform, AreaType_ground);
|
||||
EXPECT_FALSE(object.update(mTransform, AreaType_ground));
|
||||
}
|
||||
@ -73,7 +75,7 @@ namespace
|
||||
TEST_F(DetourNavigatorRecastMeshObjectTest, update_for_changed_local_scaling_should_return_true)
|
||||
{
|
||||
RecastMeshObject object(mBoxShape, mTransform, AreaType_ground);
|
||||
mBoxShape.setLocalScaling(btVector3(2, 2, 2));
|
||||
mBoxShapeImpl.setLocalScaling(btVector3(2, 2, 2));
|
||||
EXPECT_TRUE(object.update(mTransform, AreaType_ground));
|
||||
}
|
||||
}
|
||||
|
@ -62,22 +62,25 @@ namespace
|
||||
{
|
||||
TileCachedRecastMeshManager manager(mSettings);
|
||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||
EXPECT_TRUE(manager.addObject(ObjectId(&boxShape), boxShape, btTransform::getIdentity(), AreaType::AreaType_ground));
|
||||
const CollisionShape shape(nullptr, boxShape);
|
||||
EXPECT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground));
|
||||
}
|
||||
|
||||
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, add_object_for_existing_object_should_return_false)
|
||||
{
|
||||
TileCachedRecastMeshManager manager(mSettings);
|
||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||
manager.addObject(ObjectId(&boxShape), boxShape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
||||
EXPECT_FALSE(manager.addObject(ObjectId(&boxShape), boxShape, btTransform::getIdentity(), AreaType::AreaType_ground));
|
||||
const CollisionShape shape(nullptr, boxShape);
|
||||
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
||||
EXPECT_FALSE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground));
|
||||
}
|
||||
|
||||
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, add_object_should_add_tiles)
|
||||
{
|
||||
TileCachedRecastMeshManager manager(mSettings);
|
||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||
ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), boxShape, btTransform::getIdentity(), AreaType::AreaType_ground));
|
||||
const CollisionShape shape(nullptr, boxShape);
|
||||
ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground));
|
||||
for (int x = -1; x < 1; ++x)
|
||||
for (int y = -1; y < 1; ++y)
|
||||
ASSERT_TRUE(manager.hasTile(TilePosition(x, y)));
|
||||
@ -88,8 +91,9 @@ namespace
|
||||
TileCachedRecastMeshManager manager(mSettings);
|
||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(getTileSize(mSettings) / mSettings.mRecastScaleFactor, 0, 0));
|
||||
manager.addObject(ObjectId(&boxShape), boxShape, transform, AreaType::AreaType_ground);
|
||||
EXPECT_TRUE(manager.updateObject(ObjectId(&boxShape), boxShape, btTransform::getIdentity(), AreaType::AreaType_ground,
|
||||
const CollisionShape shape(nullptr, boxShape);
|
||||
manager.addObject(ObjectId(&boxShape), shape, transform, AreaType::AreaType_ground);
|
||||
EXPECT_TRUE(manager.updateObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground,
|
||||
[&] (const auto& v) { onChangedTile(v); }));
|
||||
EXPECT_THAT(
|
||||
mChangedTiles,
|
||||
@ -102,8 +106,9 @@ namespace
|
||||
{
|
||||
TileCachedRecastMeshManager manager(mSettings);
|
||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||
manager.addObject(ObjectId(&boxShape), boxShape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
||||
EXPECT_FALSE(manager.updateObject(ObjectId(&boxShape), boxShape, btTransform::getIdentity(), AreaType::AreaType_ground,
|
||||
const CollisionShape shape(nullptr, boxShape);
|
||||
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
||||
EXPECT_FALSE(manager.updateObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground,
|
||||
[&] (const auto& v) { onChangedTile(v); }));
|
||||
EXPECT_EQ(mChangedTiles, std::vector<TilePosition>());
|
||||
}
|
||||
@ -112,7 +117,8 @@ namespace
|
||||
{
|
||||
TileCachedRecastMeshManager manager(mSettings);
|
||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||
manager.addObject(ObjectId(&boxShape), boxShape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
||||
const CollisionShape shape(nullptr, boxShape);
|
||||
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
||||
EXPECT_NE(manager.getMesh(TilePosition(-1, -1)), nullptr);
|
||||
EXPECT_NE(manager.getMesh(TilePosition(-1, 0)), nullptr);
|
||||
EXPECT_NE(manager.getMesh(TilePosition(0, -1)), nullptr);
|
||||
@ -123,7 +129,8 @@ namespace
|
||||
{
|
||||
TileCachedRecastMeshManager manager(mSettings);
|
||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||
manager.addObject(ObjectId(&boxShape), boxShape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
||||
const CollisionShape shape(nullptr, boxShape);
|
||||
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
||||
EXPECT_EQ(manager.getMesh(TilePosition(1, 0)), nullptr);
|
||||
}
|
||||
|
||||
@ -132,14 +139,15 @@ namespace
|
||||
TileCachedRecastMeshManager manager(mSettings);
|
||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(getTileSize(mSettings) / mSettings.mRecastScaleFactor, 0, 0));
|
||||
const CollisionShape shape(nullptr, boxShape);
|
||||
|
||||
manager.addObject(ObjectId(&boxShape), boxShape, transform, AreaType::AreaType_ground);
|
||||
manager.addObject(ObjectId(&boxShape), shape, transform, AreaType::AreaType_ground);
|
||||
EXPECT_NE(manager.getMesh(TilePosition(0, -1)), nullptr);
|
||||
EXPECT_NE(manager.getMesh(TilePosition(0, 0)), nullptr);
|
||||
EXPECT_NE(manager.getMesh(TilePosition(1, 0)), nullptr);
|
||||
EXPECT_NE(manager.getMesh(TilePosition(1, -1)), nullptr);
|
||||
|
||||
manager.updateObject(ObjectId(&boxShape), boxShape, btTransform::getIdentity(), AreaType::AreaType_ground, [] (auto) {});
|
||||
manager.updateObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, [] (auto) {});
|
||||
EXPECT_NE(manager.getMesh(TilePosition(-1, -1)), nullptr);
|
||||
EXPECT_NE(manager.getMesh(TilePosition(-1, 0)), nullptr);
|
||||
EXPECT_NE(manager.getMesh(TilePosition(0, -1)), nullptr);
|
||||
@ -151,12 +159,13 @@ namespace
|
||||
TileCachedRecastMeshManager manager(mSettings);
|
||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(getTileSize(mSettings) / mSettings.mRecastScaleFactor, 0, 0));
|
||||
const CollisionShape shape(nullptr, boxShape);
|
||||
|
||||
manager.addObject(ObjectId(&boxShape), boxShape, transform, AreaType::AreaType_ground);
|
||||
manager.addObject(ObjectId(&boxShape), shape, transform, AreaType::AreaType_ground);
|
||||
EXPECT_EQ(manager.getMesh(TilePosition(-1, -1)), nullptr);
|
||||
EXPECT_EQ(manager.getMesh(TilePosition(-1, 0)), nullptr);
|
||||
|
||||
manager.updateObject(ObjectId(&boxShape), boxShape, btTransform::getIdentity(), AreaType::AreaType_ground, [] (auto) {});
|
||||
manager.updateObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, [] (auto) {});
|
||||
EXPECT_EQ(manager.getMesh(TilePosition(1, 0)), nullptr);
|
||||
EXPECT_EQ(manager.getMesh(TilePosition(1, -1)), nullptr);
|
||||
}
|
||||
@ -165,7 +174,8 @@ namespace
|
||||
{
|
||||
TileCachedRecastMeshManager manager(mSettings);
|
||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||
manager.addObject(ObjectId(&boxShape), boxShape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
||||
const CollisionShape shape(nullptr, boxShape);
|
||||
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
||||
manager.removeObject(ObjectId(&boxShape));
|
||||
EXPECT_EQ(manager.getMesh(TilePosition(-1, -1)), nullptr);
|
||||
EXPECT_EQ(manager.getMesh(TilePosition(-1, 0)), nullptr);
|
||||
@ -177,14 +187,15 @@ namespace
|
||||
{
|
||||
TileCachedRecastMeshManager manager(mSettings);
|
||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||
const CollisionShape shape(nullptr, boxShape);
|
||||
|
||||
manager.addObject(ObjectId(&boxShape), boxShape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
||||
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
||||
EXPECT_NE(manager.getMesh(TilePosition(-1, -1)), nullptr);
|
||||
EXPECT_NE(manager.getMesh(TilePosition(-1, 0)), nullptr);
|
||||
EXPECT_NE(manager.getMesh(TilePosition(0, -1)), nullptr);
|
||||
EXPECT_NE(manager.getMesh(TilePosition(0, 0)), nullptr);
|
||||
|
||||
manager.updateObject(ObjectId(&boxShape), boxShape, btTransform::getIdentity(), AreaType::AreaType_ground, [] (auto) {});
|
||||
manager.updateObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, [] (auto) {});
|
||||
EXPECT_NE(manager.getMesh(TilePosition(-1, -1)), nullptr);
|
||||
EXPECT_NE(manager.getMesh(TilePosition(-1, 0)), nullptr);
|
||||
EXPECT_NE(manager.getMesh(TilePosition(0, -1)), nullptr);
|
||||
@ -196,7 +207,8 @@ namespace
|
||||
TileCachedRecastMeshManager manager(mSettings);
|
||||
const auto initialRevision = manager.getRevision();
|
||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||
manager.addObject(ObjectId(&boxShape), boxShape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
||||
const CollisionShape shape(nullptr, boxShape);
|
||||
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
||||
EXPECT_EQ(manager.getRevision(), initialRevision + 1);
|
||||
}
|
||||
|
||||
@ -204,9 +216,10 @@ namespace
|
||||
{
|
||||
TileCachedRecastMeshManager manager(mSettings);
|
||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||
manager.addObject(ObjectId(&boxShape), boxShape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
||||
const CollisionShape shape(nullptr, boxShape);
|
||||
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
||||
const auto beforeAddRevision = manager.getRevision();
|
||||
manager.addObject(ObjectId(&boxShape), boxShape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
||||
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
||||
EXPECT_EQ(manager.getRevision(), beforeAddRevision);
|
||||
}
|
||||
|
||||
@ -215,9 +228,10 @@ namespace
|
||||
TileCachedRecastMeshManager manager(mSettings);
|
||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(getTileSize(mSettings) / mSettings.mRecastScaleFactor, 0, 0));
|
||||
manager.addObject(ObjectId(&boxShape), boxShape, transform, AreaType::AreaType_ground);
|
||||
const CollisionShape shape(nullptr, boxShape);
|
||||
manager.addObject(ObjectId(&boxShape), shape, transform, AreaType::AreaType_ground);
|
||||
const auto beforeUpdateRevision = manager.getRevision();
|
||||
manager.updateObject(ObjectId(&boxShape), boxShape, btTransform::getIdentity(), AreaType::AreaType_ground, [] (auto) {});
|
||||
manager.updateObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, [] (auto) {});
|
||||
EXPECT_EQ(manager.getRevision(), beforeUpdateRevision + 1);
|
||||
}
|
||||
|
||||
@ -225,9 +239,10 @@ namespace
|
||||
{
|
||||
TileCachedRecastMeshManager manager(mSettings);
|
||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||
manager.addObject(ObjectId(&boxShape), boxShape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
||||
const CollisionShape shape(nullptr, boxShape);
|
||||
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
||||
const auto beforeUpdateRevision = manager.getRevision();
|
||||
manager.updateObject(ObjectId(&boxShape), boxShape, btTransform::getIdentity(), AreaType::AreaType_ground, [] (auto) {});
|
||||
manager.updateObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, [] (auto) {});
|
||||
EXPECT_EQ(manager.getRevision(), beforeUpdateRevision);
|
||||
}
|
||||
|
||||
@ -235,7 +250,8 @@ namespace
|
||||
{
|
||||
TileCachedRecastMeshManager manager(mSettings);
|
||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||
manager.addObject(ObjectId(&boxShape), boxShape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
||||
const CollisionShape shape(nullptr, boxShape);
|
||||
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
||||
const auto beforeRemoveRevision = manager.getRevision();
|
||||
manager.removeObject(ObjectId(&boxShape));
|
||||
EXPECT_EQ(manager.getRevision(), beforeRemoveRevision + 1);
|
||||
@ -272,7 +288,8 @@ namespace
|
||||
{
|
||||
TileCachedRecastMeshManager manager(mSettings);
|
||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||
ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), boxShape, btTransform::getIdentity(), AreaType::AreaType_ground));
|
||||
const CollisionShape shape(nullptr, boxShape);
|
||||
ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground));
|
||||
const osg::Vec2i cellPosition(0, 0);
|
||||
const int cellSize = std::numeric_limits<int>::max();
|
||||
ASSERT_TRUE(manager.addWater(cellPosition, cellSize, osg::Vec3f()));
|
||||
@ -314,7 +331,8 @@ namespace
|
||||
{
|
||||
TileCachedRecastMeshManager manager(mSettings);
|
||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||
ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), boxShape, btTransform::getIdentity(), AreaType::AreaType_ground));
|
||||
const CollisionShape shape(nullptr, boxShape);
|
||||
ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground));
|
||||
const osg::Vec2i cellPosition(0, 0);
|
||||
const int cellSize = 8192;
|
||||
ASSERT_TRUE(manager.addWater(cellPosition, cellSize, osg::Vec3f()));
|
||||
@ -330,7 +348,8 @@ namespace
|
||||
const osg::Vec2i cellPosition(0, 0);
|
||||
const int cellSize = 8192;
|
||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||
ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), boxShape, btTransform::getIdentity(), AreaType::AreaType_ground));
|
||||
const CollisionShape shape(nullptr, boxShape);
|
||||
ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground));
|
||||
ASSERT_TRUE(manager.addWater(cellPosition, cellSize, osg::Vec3f()));
|
||||
ASSERT_TRUE(manager.removeObject(ObjectId(&boxShape)));
|
||||
for (int x = -6; x < 6; ++x)
|
||||
|
@ -8,12 +8,12 @@ namespace DetourNavigator
|
||||
: mImpl(settings, bounds, generation)
|
||||
{}
|
||||
|
||||
bool CachedRecastMeshManager::addObject(const ObjectId id, const btCollisionShape& shape,
|
||||
bool CachedRecastMeshManager::addObject(const ObjectId id, const CollisionShape& shape,
|
||||
const btTransform& transform, const AreaType areaType)
|
||||
{
|
||||
if (!mImpl.addObject(id, shape, transform, areaType))
|
||||
return false;
|
||||
mCached.reset();
|
||||
mCached.lock()->reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ namespace DetourNavigator
|
||||
{
|
||||
if (!mImpl.updateObject(id, transform, areaType))
|
||||
return false;
|
||||
mCached.reset();
|
||||
mCached.lock()->reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@ namespace DetourNavigator
|
||||
{
|
||||
const auto object = mImpl.removeObject(id);
|
||||
if (object)
|
||||
mCached.reset();
|
||||
mCached.lock()->reset();
|
||||
return object;
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ namespace DetourNavigator
|
||||
{
|
||||
if (!mImpl.addWater(cellPosition, cellSize, shift))
|
||||
return false;
|
||||
mCached.reset();
|
||||
mCached.lock()->reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -46,7 +46,7 @@ namespace DetourNavigator
|
||||
{
|
||||
const auto water = mImpl.removeWater(cellPosition);
|
||||
if (water)
|
||||
mCached.reset();
|
||||
mCached.lock()->reset();
|
||||
return water;
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ namespace DetourNavigator
|
||||
{
|
||||
if (!mImpl.addHeightfield(cellPosition, cellSize, shift, shape))
|
||||
return false;
|
||||
mCached.reset();
|
||||
mCached.lock()->reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -63,15 +63,18 @@ namespace DetourNavigator
|
||||
{
|
||||
const auto cell = mImpl.removeHeightfield(cellPosition);
|
||||
if (cell)
|
||||
mCached.reset();
|
||||
mCached.lock()->reset();
|
||||
return cell;
|
||||
}
|
||||
|
||||
std::shared_ptr<RecastMesh> CachedRecastMeshManager::getMesh()
|
||||
{
|
||||
if (!mCached)
|
||||
mCached = mImpl.getMesh();
|
||||
return mCached;
|
||||
std::shared_ptr<RecastMesh> cached = *mCached.lock();
|
||||
if (cached != nullptr)
|
||||
return cached;
|
||||
cached = mImpl.getMesh();
|
||||
*mCached.lock() = cached;
|
||||
return cached;
|
||||
}
|
||||
|
||||
bool CachedRecastMeshManager::isEmpty() const
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include "version.hpp"
|
||||
#include "heightfieldshape.hpp"
|
||||
|
||||
#include <components/misc/guarded.hpp>
|
||||
|
||||
namespace DetourNavigator
|
||||
{
|
||||
class CachedRecastMeshManager
|
||||
@ -12,7 +14,7 @@ namespace DetourNavigator
|
||||
public:
|
||||
CachedRecastMeshManager(const Settings& settings, const TileBounds& bounds, std::size_t generation);
|
||||
|
||||
bool addObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform,
|
||||
bool addObject(const ObjectId id, const CollisionShape& shape, const btTransform& transform,
|
||||
const AreaType areaType);
|
||||
|
||||
bool updateObject(const ObjectId id, const btTransform& transform, const AreaType areaType);
|
||||
@ -38,7 +40,7 @@ namespace DetourNavigator
|
||||
|
||||
private:
|
||||
RecastMeshManager mImpl;
|
||||
std::shared_ptr<RecastMesh> mCached;
|
||||
Misc::ScopeGuarded<std::shared_ptr<RecastMesh>> mCached;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include "waitconditiontype.hpp"
|
||||
#include "heightfieldshape.hpp"
|
||||
|
||||
#include <components/resource/bulletshape.hpp>
|
||||
|
||||
#include <variant>
|
||||
|
||||
namespace ESM
|
||||
@ -27,11 +29,10 @@ namespace DetourNavigator
|
||||
{
|
||||
struct ObjectShapes
|
||||
{
|
||||
const btCollisionShape& mShape;
|
||||
const btCollisionShape* mAvoid;
|
||||
osg::ref_ptr<const Resource::BulletShapeInstance> mShapeInstance;
|
||||
|
||||
ObjectShapes(const btCollisionShape& shape, const btCollisionShape* avoid)
|
||||
: mShape(shape), mAvoid(avoid)
|
||||
ObjectShapes(const osg::ref_ptr<const Resource::BulletShapeInstance>& shapeInstance)
|
||||
: mShapeInstance(shapeInstance)
|
||||
{}
|
||||
};
|
||||
|
||||
@ -40,9 +41,9 @@ namespace DetourNavigator
|
||||
osg::Vec3f mConnectionStart;
|
||||
osg::Vec3f mConnectionEnd;
|
||||
|
||||
DoorShapes(const btCollisionShape& shape, const btCollisionShape* avoid,
|
||||
DoorShapes(const osg::ref_ptr<const Resource::BulletShapeInstance>& shapeInstance,
|
||||
const osg::Vec3f& connectionStart,const osg::Vec3f& connectionEnd)
|
||||
: ObjectShapes(shape, avoid)
|
||||
: ObjectShapes(shapeInstance)
|
||||
, mConnectionStart(connectionStart)
|
||||
, mConnectionEnd(connectionEnd)
|
||||
{}
|
||||
@ -72,15 +73,6 @@ namespace DetourNavigator
|
||||
*/
|
||||
virtual void removeAgent(const osg::Vec3f& agentHalfExtents) = 0;
|
||||
|
||||
/**
|
||||
* @brief addObject is used to add object represented by single btCollisionShape and btTransform.
|
||||
* @param id is used to distinguish different objects.
|
||||
* @param shape must live until object is updated by another shape removed from Navigator.
|
||||
* @param transform allows to setup object geometry according to its world state.
|
||||
* @return true if object is added, false if there is already object with given id.
|
||||
*/
|
||||
virtual bool addObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform) = 0;
|
||||
|
||||
/**
|
||||
* @brief addObject is used to add complex object with allowed to walk and avoided to walk shapes
|
||||
* @param id is used to distinguish different objects
|
||||
@ -99,15 +91,6 @@ namespace DetourNavigator
|
||||
*/
|
||||
virtual bool addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) = 0;
|
||||
|
||||
/**
|
||||
* @brief updateObject replace object geometry by given data.
|
||||
* @param id is used to find object.
|
||||
* @param shape must live until object is updated by another shape removed from Navigator.
|
||||
* @param transform allows to setup objects geometry according to its world state.
|
||||
* @return true if object is updated, false if there is no object with given id.
|
||||
*/
|
||||
virtual bool updateObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform) = 0;
|
||||
|
||||
/**
|
||||
* @brief updateObject replace object geometry by given data.
|
||||
* @param id is used to find object.
|
||||
|
@ -32,18 +32,15 @@ namespace DetourNavigator
|
||||
--it->second;
|
||||
}
|
||||
|
||||
bool NavigatorImpl::addObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform)
|
||||
{
|
||||
return mNavMeshManager.addObject(id, shape, transform, AreaType_ground);
|
||||
}
|
||||
|
||||
bool NavigatorImpl::addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform)
|
||||
{
|
||||
bool result = addObject(id, shapes.mShape, transform);
|
||||
if (shapes.mAvoid)
|
||||
CollisionShape collisionShape {shapes.mShapeInstance, *shapes.mShapeInstance->getCollisionShape()};
|
||||
bool result = mNavMeshManager.addObject(id, collisionShape, transform, AreaType_ground);
|
||||
if (const btCollisionShape* const avoidShape = shapes.mShapeInstance->getAvoidCollisionShape())
|
||||
{
|
||||
const ObjectId avoidId(shapes.mAvoid);
|
||||
if (mNavMeshManager.addObject(avoidId, *shapes.mAvoid, transform, AreaType_null))
|
||||
const ObjectId avoidId(avoidShape);
|
||||
CollisionShape collisionShape {shapes.mShapeInstance, *avoidShape};
|
||||
if (mNavMeshManager.addObject(avoidId, collisionShape, transform, AreaType_null))
|
||||
{
|
||||
updateAvoidShapeId(id, avoidId);
|
||||
result = true;
|
||||
@ -65,18 +62,15 @@ namespace DetourNavigator
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NavigatorImpl::updateObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform)
|
||||
{
|
||||
return mNavMeshManager.updateObject(id, shape, transform, AreaType_ground);
|
||||
}
|
||||
|
||||
bool NavigatorImpl::updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform)
|
||||
{
|
||||
bool result = updateObject(id, shapes.mShape, transform);
|
||||
if (shapes.mAvoid)
|
||||
const CollisionShape collisionShape {shapes.mShapeInstance, *shapes.mShapeInstance->getCollisionShape()};
|
||||
bool result = mNavMeshManager.updateObject(id, collisionShape, transform, AreaType_ground);
|
||||
if (const btCollisionShape* const avoidShape = shapes.mShapeInstance->getAvoidCollisionShape())
|
||||
{
|
||||
const ObjectId avoidId(shapes.mAvoid);
|
||||
if (mNavMeshManager.updateObject(avoidId, *shapes.mAvoid, transform, AreaType_null))
|
||||
const ObjectId avoidId(avoidShape);
|
||||
const CollisionShape collisionShape {shapes.mShapeInstance, *avoidShape};
|
||||
if (mNavMeshManager.updateObject(avoidId, collisionShape, transform, AreaType_null))
|
||||
{
|
||||
updateAvoidShapeId(id, avoidId);
|
||||
result = true;
|
||||
|
@ -21,14 +21,10 @@ namespace DetourNavigator
|
||||
|
||||
void removeAgent(const osg::Vec3f& agentHalfExtents) override;
|
||||
|
||||
bool addObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform) override;
|
||||
|
||||
bool addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) override;
|
||||
|
||||
bool addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) override;
|
||||
|
||||
bool updateObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform) override;
|
||||
|
||||
bool updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) override;
|
||||
|
||||
bool updateObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) override;
|
||||
|
@ -19,11 +19,6 @@ namespace DetourNavigator
|
||||
|
||||
void removeAgent(const osg::Vec3f& /*agentHalfExtents*/) override {}
|
||||
|
||||
bool addObject(const ObjectId /*id*/, const btCollisionShape& /*shape*/, const btTransform& /*transform*/) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool addObject(const ObjectId /*id*/, const ObjectShapes& /*shapes*/, const btTransform& /*transform*/) override
|
||||
{
|
||||
return false;
|
||||
@ -34,11 +29,6 @@ namespace DetourNavigator
|
||||
return false;
|
||||
}
|
||||
|
||||
bool updateObject(const ObjectId /*id*/, const btCollisionShape& /*shape*/, const btTransform& /*transform*/) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool updateObject(const ObjectId /*id*/, const ObjectShapes& /*shapes*/, const btTransform& /*transform*/) override
|
||||
{
|
||||
return false;
|
||||
|
@ -47,16 +47,17 @@ namespace DetourNavigator
|
||||
, mAsyncNavMeshUpdater(settings, mRecastMeshManager, mOffMeshConnectionsManager)
|
||||
{}
|
||||
|
||||
bool NavMeshManager::addObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform,
|
||||
bool NavMeshManager::addObject(const ObjectId id, const CollisionShape& shape, const btTransform& transform,
|
||||
const AreaType areaType)
|
||||
{
|
||||
const btCollisionShape& collisionShape = shape.getShape();
|
||||
if (!mRecastMeshManager.addObject(id, shape, transform, areaType))
|
||||
return false;
|
||||
addChangedTiles(shape, transform, ChangeType::add);
|
||||
addChangedTiles(collisionShape, transform, ChangeType::add);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NavMeshManager::updateObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform,
|
||||
bool NavMeshManager::updateObject(const ObjectId id, const CollisionShape& shape, const btTransform& transform,
|
||||
const AreaType areaType)
|
||||
{
|
||||
return mRecastMeshManager.updateObject(id, shape, transform, areaType,
|
||||
|
@ -24,10 +24,10 @@ namespace DetourNavigator
|
||||
public:
|
||||
NavMeshManager(const Settings& settings);
|
||||
|
||||
bool addObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform,
|
||||
bool addObject(const ObjectId id, const CollisionShape& shape, const btTransform& transform,
|
||||
const AreaType areaType);
|
||||
|
||||
bool updateObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform,
|
||||
bool updateObject(const ObjectId id, const CollisionShape& shape, const btTransform& transform,
|
||||
const AreaType areaType);
|
||||
|
||||
bool removeObject(const ObjectId id);
|
||||
|
@ -35,9 +35,10 @@ namespace DetourNavigator
|
||||
{
|
||||
}
|
||||
|
||||
bool RecastMeshManager::addObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform,
|
||||
bool RecastMeshManager::addObject(const ObjectId id, const CollisionShape& shape, const btTransform& transform,
|
||||
const AreaType areaType)
|
||||
{
|
||||
const std::lock_guard lock(mMutex);
|
||||
const auto object = mObjects.lower_bound(id);
|
||||
if (object != mObjects.end() && object->first == id)
|
||||
return false;
|
||||
@ -49,6 +50,7 @@ namespace DetourNavigator
|
||||
|
||||
bool RecastMeshManager::updateObject(const ObjectId id, const btTransform& transform, const AreaType areaType)
|
||||
{
|
||||
const std::lock_guard lock(mMutex);
|
||||
const auto object = mObjects.find(id);
|
||||
if (object == mObjects.end())
|
||||
return false;
|
||||
@ -62,6 +64,7 @@ namespace DetourNavigator
|
||||
|
||||
std::optional<RemovedRecastMeshObject> RecastMeshManager::removeObject(const ObjectId id)
|
||||
{
|
||||
const std::lock_guard lock(mMutex);
|
||||
const auto object = mObjects.find(id);
|
||||
if (object == mObjects.end())
|
||||
return std::nullopt;
|
||||
@ -73,6 +76,7 @@ namespace DetourNavigator
|
||||
|
||||
bool RecastMeshManager::addWater(const osg::Vec2i& cellPosition, const int cellSize, const osg::Vec3f& shift)
|
||||
{
|
||||
const std::lock_guard lock(mMutex);
|
||||
if (!mWater.emplace(cellPosition, Cell {cellSize, shift}).second)
|
||||
return false;
|
||||
++mRevision;
|
||||
@ -81,6 +85,7 @@ namespace DetourNavigator
|
||||
|
||||
std::optional<Cell> RecastMeshManager::removeWater(const osg::Vec2i& cellPosition)
|
||||
{
|
||||
const std::lock_guard lock(mMutex);
|
||||
const auto water = mWater.find(cellPosition);
|
||||
if (water == mWater.end())
|
||||
return std::nullopt;
|
||||
@ -93,6 +98,7 @@ namespace DetourNavigator
|
||||
bool RecastMeshManager::addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const osg::Vec3f& shift,
|
||||
const HeightfieldShape& shape)
|
||||
{
|
||||
const std::lock_guard lock(mMutex);
|
||||
if (!mHeightfields.emplace(cellPosition, Heightfield {Cell {cellSize, shift}, shape}).second)
|
||||
return false;
|
||||
++mRevision;
|
||||
@ -101,6 +107,7 @@ namespace DetourNavigator
|
||||
|
||||
std::optional<Cell> RecastMeshManager::removeHeightfield(const osg::Vec2i& cellPosition)
|
||||
{
|
||||
const std::lock_guard lock(mMutex);
|
||||
const auto it = mHeightfields.find(cellPosition);
|
||||
if (it == mHeightfields.end())
|
||||
return std::nullopt;
|
||||
@ -116,20 +123,27 @@ namespace DetourNavigator
|
||||
tileBounds.mMin /= mSettings.mRecastScaleFactor;
|
||||
tileBounds.mMax /= mSettings.mRecastScaleFactor;
|
||||
RecastMeshBuilder builder(tileBounds);
|
||||
for (const auto& [k, v] : mWater)
|
||||
builder.addWater(v.mSize, v.mShift);
|
||||
for (const auto& [k, object] : mObjects)
|
||||
std::vector<RecastMeshObject> objects;
|
||||
std::size_t revision;
|
||||
{
|
||||
const RecastMeshObject& v = object.getImpl();
|
||||
builder.addObject(v.getShape(), v.getTransform(), v.getAreaType());
|
||||
const std::lock_guard lock(mMutex);
|
||||
for (const auto& [k, v] : mWater)
|
||||
builder.addWater(v.mSize, v.mShift);
|
||||
for (const auto& [cellPosition, v] : mHeightfields)
|
||||
std::visit(AddHeightfield {v.mCell, builder}, v.mShape);
|
||||
objects.reserve(mObjects.size());
|
||||
for (const auto& [k, object] : mObjects)
|
||||
objects.push_back(object.getImpl());
|
||||
revision = mRevision;
|
||||
}
|
||||
for (const auto& [cellPosition, v] : mHeightfields)
|
||||
std::visit(AddHeightfield {v.mCell, builder}, v.mShape);
|
||||
return std::move(builder).create(mGeneration, mRevision);
|
||||
for (const auto& v : objects)
|
||||
builder.addObject(v.getShape(), v.getTransform(), v.getAreaType());
|
||||
return std::move(builder).create(mGeneration, revision);
|
||||
}
|
||||
|
||||
bool RecastMeshManager::isEmpty() const
|
||||
{
|
||||
const std::lock_guard lock(mMutex);
|
||||
return mObjects.empty() && mWater.empty() && mHeightfields.empty();
|
||||
}
|
||||
|
||||
@ -137,6 +151,7 @@ namespace DetourNavigator
|
||||
{
|
||||
if (recastMeshVersion.mGeneration != mGeneration)
|
||||
return;
|
||||
const std::lock_guard lock(mMutex);
|
||||
if (mLastNavMeshReport.has_value() && navMeshVersion < mLastNavMeshReport->mNavMeshVersion)
|
||||
return;
|
||||
mLastNavMeshReport = {recastMeshVersion.mRevision, navMeshVersion};
|
||||
@ -147,6 +162,7 @@ namespace DetourNavigator
|
||||
|
||||
Version RecastMeshManager::getVersion() const
|
||||
{
|
||||
const std::lock_guard lock(mMutex);
|
||||
return Version {mGeneration, mRevision};
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <memory>
|
||||
#include <variant>
|
||||
#include <tuple>
|
||||
#include <mutex>
|
||||
|
||||
class btCollisionShape;
|
||||
|
||||
@ -35,7 +36,7 @@ namespace DetourNavigator
|
||||
public:
|
||||
RecastMeshManager(const Settings& settings, const TileBounds& bounds, std::size_t generation);
|
||||
|
||||
bool addObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform,
|
||||
bool addObject(const ObjectId id, const CollisionShape& shape, const btTransform& transform,
|
||||
const AreaType areaType);
|
||||
|
||||
bool updateObject(const ObjectId id, const btTransform& transform, const AreaType areaType);
|
||||
@ -73,9 +74,10 @@ namespace DetourNavigator
|
||||
};
|
||||
|
||||
const Settings& mSettings;
|
||||
const std::size_t mGeneration;
|
||||
const TileBounds mTileBounds;
|
||||
mutable std::mutex mMutex;
|
||||
std::size_t mRevision = 0;
|
||||
std::size_t mGeneration;
|
||||
TileBounds mTileBounds;
|
||||
std::map<ObjectId, OscillatingRecastMeshObject> mObjects;
|
||||
std::map<osg::Vec2i, Cell> mWater;
|
||||
std::map<osg::Vec2i, Heightfield> mHeightfields;
|
||||
|
@ -22,15 +22,36 @@ namespace DetourNavigator
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<RecastMeshObject> makeChildrenObjects(const osg::ref_ptr<const Resource::BulletShapeInstance>& instance,
|
||||
const btCompoundShape& shape, const AreaType areaType)
|
||||
{
|
||||
std::vector<RecastMeshObject> result;
|
||||
for (int i = 0, num = shape.getNumChildShapes(); i < num; ++i)
|
||||
{
|
||||
const CollisionShape collisionShape {instance, *shape.getChildShape(i)};
|
||||
result.emplace_back(collisionShape, shape.getChildTransform(i), areaType);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<RecastMeshObject> makeChildrenObjects(const osg::ref_ptr<const Resource::BulletShapeInstance>& instance,
|
||||
const btCollisionShape& shape, const AreaType areaType)
|
||||
{
|
||||
if (shape.isCompound())
|
||||
return makeChildrenObjects(std::move(instance), static_cast<const btCompoundShape&>(shape), areaType);
|
||||
return std::vector<RecastMeshObject>();
|
||||
}
|
||||
}
|
||||
|
||||
RecastMeshObject::RecastMeshObject(const btCollisionShape& shape, const btTransform& transform,
|
||||
RecastMeshObject::RecastMeshObject(const CollisionShape& shape, const btTransform& transform,
|
||||
const AreaType areaType)
|
||||
: mShape(shape)
|
||||
: mShapeInstance(shape.getShapeInstance())
|
||||
, mShape(shape.getShape())
|
||||
, mTransform(transform)
|
||||
, mAreaType(areaType)
|
||||
, mLocalScaling(shape.getLocalScaling())
|
||||
, mChildren(makeChildrenObjects(shape, mAreaType))
|
||||
, mLocalScaling(mShape.get().getLocalScaling())
|
||||
, mChildren(makeChildrenObjects(mShapeInstance, mShape.get(), mAreaType))
|
||||
{
|
||||
}
|
||||
|
||||
@ -57,20 +78,4 @@ namespace DetourNavigator
|
||||
|| result;
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<RecastMeshObject> makeChildrenObjects(const btCollisionShape& shape, const AreaType areaType)
|
||||
{
|
||||
if (shape.isCompound())
|
||||
return makeChildrenObjects(static_cast<const btCompoundShape&>(shape), areaType);
|
||||
else
|
||||
return std::vector<RecastMeshObject>();
|
||||
}
|
||||
|
||||
std::vector<RecastMeshObject> makeChildrenObjects(const btCompoundShape& shape, const AreaType areaType)
|
||||
{
|
||||
std::vector<RecastMeshObject> result;
|
||||
for (int i = 0, num = shape.getNumChildShapes(); i < num; ++i)
|
||||
result.emplace_back(*shape.getChildShape(i), shape.getChildTransform(i), areaType);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,12 @@
|
||||
|
||||
#include "areatype.hpp"
|
||||
|
||||
#include <components/resource/bulletshape.hpp>
|
||||
|
||||
#include <LinearMath/btTransform.h>
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
@ -13,10 +17,26 @@ class btCompoundShape;
|
||||
|
||||
namespace DetourNavigator
|
||||
{
|
||||
class CollisionShape
|
||||
{
|
||||
public:
|
||||
CollisionShape(osg::ref_ptr<const Resource::BulletShapeInstance> instance, const btCollisionShape& shape)
|
||||
: mShapeInstance(std::move(instance))
|
||||
, mShape(shape)
|
||||
{}
|
||||
|
||||
const osg::ref_ptr<const Resource::BulletShapeInstance>& getShapeInstance() const { return mShapeInstance; }
|
||||
const btCollisionShape& getShape() const { return mShape; }
|
||||
|
||||
private:
|
||||
osg::ref_ptr<const Resource::BulletShapeInstance> mShapeInstance;
|
||||
std::reference_wrapper<const btCollisionShape> mShape;
|
||||
};
|
||||
|
||||
class RecastMeshObject
|
||||
{
|
||||
public:
|
||||
RecastMeshObject(const btCollisionShape& shape, const btTransform& transform, const AreaType areaType);
|
||||
RecastMeshObject(const CollisionShape& shape, const btTransform& transform, const AreaType areaType);
|
||||
|
||||
bool update(const btTransform& transform, const AreaType areaType);
|
||||
|
||||
@ -36,16 +56,13 @@ namespace DetourNavigator
|
||||
}
|
||||
|
||||
private:
|
||||
osg::ref_ptr<const Resource::BulletShapeInstance> mShapeInstance;
|
||||
std::reference_wrapper<const btCollisionShape> mShape;
|
||||
btTransform mTransform;
|
||||
AreaType mAreaType;
|
||||
btVector3 mLocalScaling;
|
||||
std::vector<RecastMeshObject> mChildren;
|
||||
};
|
||||
|
||||
std::vector<RecastMeshObject> makeChildrenObjects(const btCollisionShape& shape, const AreaType areaType);
|
||||
|
||||
std::vector<RecastMeshObject> makeChildrenObjects(const btCompoundShape& shape, const AreaType areaType);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -14,14 +14,14 @@ namespace DetourNavigator
|
||||
: mSettings(settings)
|
||||
{}
|
||||
|
||||
bool TileCachedRecastMeshManager::addObject(const ObjectId id, const btCollisionShape& shape,
|
||||
bool TileCachedRecastMeshManager::addObject(const ObjectId id, const CollisionShape& shape,
|
||||
const btTransform& transform, const AreaType areaType)
|
||||
{
|
||||
std::vector<TilePosition> tilesPositions;
|
||||
const auto border = getBorderSize(mSettings);
|
||||
{
|
||||
auto tiles = mTiles.lock();
|
||||
getTilesPositions(shape, transform, mSettings, [&] (const TilePosition& tilePosition)
|
||||
getTilesPositions(shape.getShape(), transform, mSettings, [&] (const TilePosition& tilePosition)
|
||||
{
|
||||
if (addTile(id, shape, transform, areaType, tilePosition, border, tiles.get()))
|
||||
tilesPositions.push_back(tilePosition);
|
||||
@ -69,7 +69,7 @@ namespace DetourNavigator
|
||||
const auto tiles = mTiles.lock();
|
||||
for (auto& tile : *tiles)
|
||||
{
|
||||
if (tile.second.addWater(cellPosition, cellSize, shift))
|
||||
if (tile.second->addWater(cellPosition, cellSize, shift))
|
||||
{
|
||||
tilesPositions.push_back(tile.first);
|
||||
result = true;
|
||||
@ -88,9 +88,9 @@ namespace DetourNavigator
|
||||
tileBounds.mMin -= osg::Vec2f(border, border);
|
||||
tileBounds.mMax += osg::Vec2f(border, border);
|
||||
tile = tiles->insert(std::make_pair(tilePosition,
|
||||
CachedRecastMeshManager(mSettings, tileBounds, mTilesGeneration))).first;
|
||||
std::make_shared<CachedRecastMeshManager>(mSettings, tileBounds, mTilesGeneration))).first;
|
||||
}
|
||||
if (tile->second.addWater(cellPosition, cellSize, shift))
|
||||
if (tile->second->addWater(cellPosition, cellSize, shift))
|
||||
{
|
||||
tilesPositions.push_back(tilePosition);
|
||||
result = true;
|
||||
@ -116,8 +116,8 @@ namespace DetourNavigator
|
||||
const auto tile = tiles->find(tilePosition);
|
||||
if (tile == tiles->end())
|
||||
continue;
|
||||
const auto tileResult = tile->second.removeWater(cellPosition);
|
||||
if (tile->second.isEmpty())
|
||||
const auto tileResult = tile->second->removeWater(cellPosition);
|
||||
if (tile->second->isEmpty())
|
||||
{
|
||||
tiles->erase(tile);
|
||||
++mTilesGeneration;
|
||||
@ -149,9 +149,9 @@ namespace DetourNavigator
|
||||
tileBounds.mMin -= osg::Vec2f(border, border);
|
||||
tileBounds.mMax += osg::Vec2f(border, border);
|
||||
tile = tiles->insert(std::make_pair(tilePosition,
|
||||
CachedRecastMeshManager(mSettings, tileBounds, mTilesGeneration))).first;
|
||||
std::make_shared<CachedRecastMeshManager>(mSettings, tileBounds, mTilesGeneration))).first;
|
||||
}
|
||||
if (tile->second.addHeightfield(cellPosition, cellSize, shift, shape))
|
||||
if (tile->second->addHeightfield(cellPosition, cellSize, shift, shape))
|
||||
{
|
||||
tilesPositions.push_back(tilePosition);
|
||||
result = true;
|
||||
@ -176,8 +176,8 @@ namespace DetourNavigator
|
||||
const auto tile = tiles->find(tilePosition);
|
||||
if (tile == tiles->end())
|
||||
continue;
|
||||
const auto tileResult = tile->second.removeHeightfield(cellPosition);
|
||||
if (tile->second.isEmpty())
|
||||
const auto tileResult = tile->second->removeHeightfield(cellPosition);
|
||||
if (tile->second->isEmpty())
|
||||
{
|
||||
tiles->erase(tile);
|
||||
++mTilesGeneration;
|
||||
@ -192,11 +192,17 @@ namespace DetourNavigator
|
||||
|
||||
std::shared_ptr<RecastMesh> TileCachedRecastMeshManager::getMesh(const TilePosition& tilePosition)
|
||||
{
|
||||
const auto tiles = mTiles.lock();
|
||||
const auto it = tiles->find(tilePosition);
|
||||
if (it == tiles->end())
|
||||
const auto manager = [&] () -> std::shared_ptr<CachedRecastMeshManager>
|
||||
{
|
||||
const auto tiles = mTiles.lock();
|
||||
const auto it = tiles->find(tilePosition);
|
||||
if (it == tiles->end())
|
||||
return nullptr;
|
||||
return it->second;
|
||||
} ();
|
||||
if (manager == nullptr)
|
||||
return nullptr;
|
||||
return it->second.getMesh();
|
||||
return manager->getMesh();
|
||||
}
|
||||
|
||||
bool TileCachedRecastMeshManager::hasTile(const TilePosition& tilePosition)
|
||||
@ -215,12 +221,12 @@ namespace DetourNavigator
|
||||
const auto it = tiles->find(tilePosition);
|
||||
if (it == tiles->end())
|
||||
return;
|
||||
it->second.reportNavMeshChange(recastMeshVersion, navMeshVersion);
|
||||
it->second->reportNavMeshChange(recastMeshVersion, navMeshVersion);
|
||||
}
|
||||
|
||||
bool TileCachedRecastMeshManager::addTile(const ObjectId id, const btCollisionShape& shape,
|
||||
bool TileCachedRecastMeshManager::addTile(const ObjectId id, const CollisionShape& shape,
|
||||
const btTransform& transform, const AreaType areaType, const TilePosition& tilePosition, float border,
|
||||
std::map<TilePosition, CachedRecastMeshManager>& tiles)
|
||||
TilesMap& tiles)
|
||||
{
|
||||
auto tile = tiles.find(tilePosition);
|
||||
if (tile == tiles.end())
|
||||
@ -229,26 +235,26 @@ namespace DetourNavigator
|
||||
tileBounds.mMin -= osg::Vec2f(border, border);
|
||||
tileBounds.mMax += osg::Vec2f(border, border);
|
||||
tile = tiles.insert(std::make_pair(
|
||||
tilePosition, CachedRecastMeshManager(mSettings, tileBounds, mTilesGeneration))).first;
|
||||
tilePosition, std::make_shared<CachedRecastMeshManager>(mSettings, tileBounds, mTilesGeneration))).first;
|
||||
}
|
||||
return tile->second.addObject(id, shape, transform, areaType);
|
||||
return tile->second->addObject(id, shape, transform, areaType);
|
||||
}
|
||||
|
||||
bool TileCachedRecastMeshManager::updateTile(const ObjectId id, const btTransform& transform,
|
||||
const AreaType areaType, const TilePosition& tilePosition, std::map<TilePosition, CachedRecastMeshManager>& tiles)
|
||||
const AreaType areaType, const TilePosition& tilePosition, TilesMap& tiles)
|
||||
{
|
||||
const auto tile = tiles.find(tilePosition);
|
||||
return tile != tiles.end() && tile->second.updateObject(id, transform, areaType);
|
||||
return tile != tiles.end() && tile->second->updateObject(id, transform, areaType);
|
||||
}
|
||||
|
||||
std::optional<RemovedRecastMeshObject> TileCachedRecastMeshManager::removeTile(const ObjectId id,
|
||||
const TilePosition& tilePosition, std::map<TilePosition, CachedRecastMeshManager>& tiles)
|
||||
const TilePosition& tilePosition, TilesMap& tiles)
|
||||
{
|
||||
const auto tile = tiles.find(tilePosition);
|
||||
if (tile == tiles.end())
|
||||
return std::optional<RemovedRecastMeshObject>();
|
||||
const auto tileResult = tile->second.removeObject(id);
|
||||
if (tile->second.isEmpty())
|
||||
const auto tileResult = tile->second->removeObject(id);
|
||||
if (tile->second->isEmpty())
|
||||
{
|
||||
tiles.erase(tile);
|
||||
++mTilesGeneration;
|
||||
|
@ -22,11 +22,11 @@ namespace DetourNavigator
|
||||
public:
|
||||
TileCachedRecastMeshManager(const Settings& settings);
|
||||
|
||||
bool addObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform,
|
||||
bool addObject(const ObjectId id, const CollisionShape& shape, const btTransform& transform,
|
||||
const AreaType areaType);
|
||||
|
||||
template <class OnChangedTile>
|
||||
bool updateObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform,
|
||||
bool updateObject(const ObjectId id, const CollisionShape& shape, const btTransform& transform,
|
||||
const AreaType areaType, OnChangedTile&& onChangedTile)
|
||||
{
|
||||
const auto object = mObjectsTilesPositions.find(id);
|
||||
@ -56,7 +56,7 @@ namespace DetourNavigator
|
||||
changed = true;
|
||||
}
|
||||
};
|
||||
getTilesPositions(shape, transform, mSettings, onTilePosition);
|
||||
getTilesPositions(shape.getShape(), transform, mSettings, onTilePosition);
|
||||
std::sort(newTiles.begin(), newTiles.end());
|
||||
for (const auto& tile : currentTiles)
|
||||
{
|
||||
@ -94,7 +94,7 @@ namespace DetourNavigator
|
||||
void forEachTile(Function&& function)
|
||||
{
|
||||
for (auto& [tilePosition, recastMeshManager] : *mTiles.lock())
|
||||
function(tilePosition, recastMeshManager);
|
||||
function(tilePosition, *recastMeshManager);
|
||||
}
|
||||
|
||||
std::size_t getRevision() const;
|
||||
@ -102,23 +102,24 @@ namespace DetourNavigator
|
||||
void reportNavMeshChange(const TilePosition& tilePosition, Version recastMeshVersion, Version navMeshVersion);
|
||||
|
||||
private:
|
||||
using TilesMap = std::map<TilePosition, std::shared_ptr<CachedRecastMeshManager>>;
|
||||
|
||||
const Settings& mSettings;
|
||||
Misc::ScopeGuarded<std::map<TilePosition, CachedRecastMeshManager>> mTiles;
|
||||
Misc::ScopeGuarded<TilesMap> mTiles;
|
||||
std::unordered_map<ObjectId, std::vector<TilePosition>> mObjectsTilesPositions;
|
||||
std::map<osg::Vec2i, std::vector<TilePosition>> mWaterTilesPositions;
|
||||
std::map<osg::Vec2i, std::vector<TilePosition>> mHeightfieldTilesPositions;
|
||||
std::size_t mRevision = 0;
|
||||
std::size_t mTilesGeneration = 0;
|
||||
|
||||
bool addTile(const ObjectId id, const btCollisionShape& shape, const btTransform& transform,
|
||||
const AreaType areaType, const TilePosition& tilePosition, float border,
|
||||
std::map<TilePosition, CachedRecastMeshManager>& tiles);
|
||||
bool addTile(const ObjectId id, const CollisionShape& shape, const btTransform& transform,
|
||||
const AreaType areaType, const TilePosition& tilePosition, float border, TilesMap& tiles);
|
||||
|
||||
bool updateTile(const ObjectId id, const btTransform& transform, const AreaType areaType,
|
||||
const TilePosition& tilePosition, std::map<TilePosition, CachedRecastMeshManager>& tiles);
|
||||
const TilePosition& tilePosition, TilesMap& tiles);
|
||||
|
||||
std::optional<RemovedRecastMeshObject> removeTile(const ObjectId id, const TilePosition& tilePosition,
|
||||
std::map<TilePosition, CachedRecastMeshManager>& tiles);
|
||||
TilesMap& tiles);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <BulletCollision/CollisionShapes/btBoxShape.h>
|
||||
#include <BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h>
|
||||
#include <BulletCollision/CollisionShapes/btCompoundShape.h>
|
||||
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
|
||||
|
||||
namespace Resource
|
||||
{
|
||||
@ -75,6 +76,9 @@ btCollisionShape* BulletShape::duplicateCollisionShape(const btCollisionShape *s
|
||||
return new btBoxShape(*boxshape);
|
||||
}
|
||||
|
||||
if (shape->getShapeType() == TERRAIN_SHAPE_PROXYTYPE)
|
||||
return new btHeightfieldTerrainShape(static_cast<const btHeightfieldTerrainShape&>(*shape));
|
||||
|
||||
throw std::logic_error(std::string("Unhandled Bullet shape duplication: ")+shape->getName());
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user