From 08b026e907f334c23fde5166b19e80cf64980100 Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 1 Aug 2021 01:27:41 +0200 Subject: [PATCH] Store copies of ref_ptr for btCollisionShape wrappers in Navigator To keep btCollisionShape lifetime. --- apps/openmw/mwphysics/heightfield.cpp | 4 + apps/openmw/mwphysics/heightfield.hpp | 7 +- apps/openmw/mwphysics/physicssystem.cpp | 2 +- apps/openmw/mwphysics/physicssystem.hpp | 2 +- apps/openmw/mwworld/scene.cpp | 18 +- apps/openmw/mwworld/worldimp.cpp | 5 +- .../detournavigator/navigator.cpp | 166 +++++++++++------- .../detournavigator/recastmeshobject.cpp | 16 +- .../tilecachedrecastmeshmanager.cpp | 72 +++++--- .../cachedrecastmeshmanager.cpp | 2 +- .../cachedrecastmeshmanager.hpp | 2 +- components/detournavigator/navigator.hpp | 30 ++-- components/detournavigator/navigatorimpl.cpp | 31 ++-- components/detournavigator/navigatorimpl.hpp | 5 +- components/detournavigator/navigatorstub.hpp | 8 +- components/detournavigator/navmeshmanager.cpp | 7 +- components/detournavigator/navmeshmanager.hpp | 4 +- .../detournavigator/recastmeshmanager.cpp | 2 +- .../detournavigator/recastmeshmanager.hpp | 2 +- .../detournavigator/recastmeshobject.cpp | 45 ++--- .../detournavigator/recastmeshobject.hpp | 26 ++- .../tilecachedrecastmeshmanager.cpp | 6 +- .../tilecachedrecastmeshmanager.hpp | 8 +- components/resource/bulletshape.cpp | 4 + 24 files changed, 276 insertions(+), 198 deletions(-) diff --git a/apps/openmw/mwphysics/heightfield.cpp b/apps/openmw/mwphysics/heightfield.cpp index e210bc390..0856d8bb5 100644 --- a/apps/openmw/mwphysics/heightfield.cpp +++ b/apps/openmw/mwphysics/heightfield.cpp @@ -50,6 +50,10 @@ namespace namespace MWPhysics { + HeightField::HeightField() {} + + HeightField::HeightField(const HeightField&, const osg::CopyOp&) {} + HeightField::HeightField(const float* heights, int x, int y, float triSize, float sqrtVerts, float minH, float maxH, const osg::Object* holdObject, PhysicsTaskScheduler* scheduler) : mHoldObject(holdObject) #if BT_BULLET_VERSION < 310 diff --git a/apps/openmw/mwphysics/heightfield.hpp b/apps/openmw/mwphysics/heightfield.hpp index 93b2733f3..007fd12f5 100644 --- a/apps/openmw/mwphysics/heightfield.hpp +++ b/apps/openmw/mwphysics/heightfield.hpp @@ -2,6 +2,7 @@ #define OPENMW_MWPHYSICS_HEIGHTFIELD_H #include +#include #include @@ -20,12 +21,14 @@ namespace MWPhysics { class PhysicsTaskScheduler; - class HeightField + class HeightField : public osg::Object { public: HeightField(const float* heights, int x, int y, float triSize, float sqrtVerts, float minH, float maxH, const osg::Object* holdObject, PhysicsTaskScheduler* scheduler); ~HeightField(); + META_Object(MWPhysics, HeightField) + btCollisionObject* getCollisionObject(); const btCollisionObject* getCollisionObject() const; const btHeightfieldTerrainShape* getShape() const; @@ -40,6 +43,8 @@ namespace MWPhysics PhysicsTaskScheduler* mTaskScheduler; + HeightField(); + HeightField(const HeightField&, const osg::CopyOp&); void operator=(const HeightField&); HeightField(const HeightField&); }; diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 43653c9e5..49cea1394 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -443,7 +443,7 @@ namespace MWPhysics void PhysicsSystem::addHeightField (const float* heights, int x, int y, float triSize, float sqrtVerts, float minH, float maxH, const osg::Object* holdObject) { - mHeightFields[std::make_pair(x,y)] = std::make_unique(heights, x, y, triSize, sqrtVerts, minH, maxH, holdObject, mTaskScheduler.get()); + mHeightFields[std::make_pair(x,y)] = osg::ref_ptr(new HeightField(heights, x, y, triSize, sqrtVerts, minH, maxH, holdObject, mTaskScheduler.get())); } void PhysicsSystem::removeHeightField (int x, int y) diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp index 3d2a3c580..5687e0d61 100644 --- a/apps/openmw/mwphysics/physicssystem.hpp +++ b/apps/openmw/mwphysics/physicssystem.hpp @@ -276,7 +276,7 @@ namespace MWPhysics using ProjectileMap = std::map>; ProjectileMap mProjectiles; - using HeightFieldMap = std::map, std::unique_ptr>; + using HeightFieldMap = std::map, osg::ref_ptr>; HeightFieldMap mHeightFields; bool mDebugDrawEnabled; diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 5467cc747..a1e71f06b 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -137,11 +137,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; @@ -168,12 +166,7 @@ namespace navigator.addObject( DetourNavigator::ObjectId(object), - DetourNavigator::DoorShapes( - *shape, - object->getShapeInstance()->getAvoidCollisionShape(), - connectionStart, - connectionEnd - ), + DetourNavigator::DoorShapes(object->getShapeInstance(), connectionStart, connectionEnd), transform ); } @@ -181,10 +174,7 @@ namespace { navigator.addObject( DetourNavigator::ObjectId(object), - DetourNavigator::ObjectShapes { - *object->getShapeInstance()->getCollisionShape(), - object->getShapeInstance()->getAvoidCollisionShape() - }, + DetourNavigator::ObjectShapes(object->getShapeInstance()), object->getTransform() ); } @@ -400,7 +390,7 @@ namespace MWWorld } if (const auto heightField = mPhysics->getHeightField(cellX, cellY)) - navigator->addObject(DetourNavigator::ObjectId(heightField), *heightField->getShape(), + navigator->addObject(DetourNavigator::ObjectId(heightField), heightField, *heightField->getShape(), heightField->getCollisionObject()->getWorldTransform()); } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 1338781c3..aca8f55ce 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1558,10 +1558,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; } diff --git a/apps/openmw_test_suite/detournavigator/navigator.cpp b/apps/openmw_test_suite/detournavigator/navigator.cpp index b0fec1a1a..38f69e948 100644 --- a/apps/openmw_test_suite/detournavigator/navigator.cpp +++ b/apps/openmw_test_suite/detournavigator/navigator.cpp @@ -4,6 +4,9 @@ #include #include #include +#include + +#include #include #include @@ -14,6 +17,7 @@ #include #include +#include MATCHER_P3(Vec3fEq, x, y, z, "") { @@ -80,16 +84,38 @@ namespace }; template - btHeightfieldTerrainShape makeSquareHeightfieldTerrainShape(const std::array& values, + std::unique_ptr makeSquareHeightfieldTerrainShape(const std::array& values, btScalar heightScale = 1, int upAxis = 2, PHY_ScalarType heightDataType = PHY_FLOAT, bool flipQuadEdges = false) { const int width = static_cast(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(width, width, values.data(), heightScale, -greater, greater, + upAxis, heightDataType, flipQuadEdges); + } + + template + osg::ref_ptr makeBulletShapeInstance(std::unique_ptr&& shape) + { + osg::ref_ptr bulletShape(new Resource::BulletShape); + bulletShape->mCollisionShape = std::move(shape).release(); + return new Resource::BulletShapeInstance(bulletShape); } + template + class CollisionShapeInstance + { + public: + CollisionShapeInstance(std::unique_ptr&& shape) : mInstance(makeBulletShapeInstance(std::move(shape))) {} + + T& shape() { return static_cast(*mInstance->mCollisionShape); } + const osg::ref_ptr& instance() const { return mInstance; } + + private: + osg::ref_ptr mInstance; + }; + TEST_F(DetourNavigatorNavigatorTest, find_path_for_empty_should_return_empty) { EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), @@ -122,11 +148,12 @@ namespace 0, -25, -100, -100, -100, 0, -25, -100, -100, -100, }}; - btHeightfieldTerrainShape shape = makeSquareHeightfieldTerrainShape(heightfieldData); + const auto shapePtr = makeSquareHeightfieldTerrainShape(heightfieldData); + btHeightfieldTerrainShape& shape = *shapePtr; shape.setLocalScaling(btVector3(128, 128, 1)); mNavigator->addAgent(mAgentHalfExtents); - mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity()); + mNavigator->addObject(ObjectId(&shape), nullptr, shape, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::requiredTilesPresent); @@ -167,15 +194,15 @@ namespace 0, -25, -100, -100, -100, 0, -25, -100, -100, -100, }}; - btHeightfieldTerrainShape heightfieldShape = makeSquareHeightfieldTerrainShape(heightfieldData); + const auto heightfieldShapePtr = makeSquareHeightfieldTerrainShape(heightfieldData); + btHeightfieldTerrainShape& heightfieldShape = *heightfieldShapePtr; heightfieldShape.setLocalScaling(btVector3(128, 128, 1)); - btBoxShape boxShape(btVector3(20, 20, 100)); - btCompoundShape compoundShape; - compoundShape.addChildShape(btTransform(btMatrix3x3::getIdentity(), btVector3(0, 0, 0)), &boxShape); + CollisionShapeInstance compound(std::make_unique()); + compound.shape().addChildShape(btTransform(btMatrix3x3::getIdentity(), btVector3(0, 0, 0)), new btBoxShape(btVector3(20, 20, 100))); mNavigator->addAgent(mAgentHalfExtents); - mNavigator->addObject(ObjectId(&heightfieldShape), heightfieldShape, btTransform::getIdentity()); + mNavigator->addObject(ObjectId(&heightfieldShape), nullptr, heightfieldShape, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); @@ -206,7 +233,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); @@ -250,16 +277,16 @@ namespace 0, -25, -100, -100, -100, 0, -25, -100, -100, -100, }}; - btHeightfieldTerrainShape heightfieldShape = makeSquareHeightfieldTerrainShape(heightfieldData); + const auto heightfieldShapePtr = makeSquareHeightfieldTerrainShape(heightfieldData); + btHeightfieldTerrainShape& heightfieldShape = *heightfieldShapePtr; heightfieldShape.setLocalScaling(btVector3(128, 128, 1)); - btBoxShape boxShape(btVector3(20, 20, 100)); - btCompoundShape compoundShape; - compoundShape.addChildShape(btTransform(btMatrix3x3::getIdentity(), btVector3(0, 0, 0)), &boxShape); + CollisionShapeInstance compound(std::make_unique()); + compound.shape().addChildShape(btTransform(btMatrix3x3::getIdentity(), btVector3(0, 0, 0)), new btBoxShape(btVector3(20, 20, 100))); mNavigator->addAgent(mAgentHalfExtents); - mNavigator->addObject(ObjectId(&heightfieldShape), heightfieldShape, btTransform::getIdentity()); - mNavigator->addObject(ObjectId(&compoundShape), compoundShape, btTransform::getIdentity()); + mNavigator->addObject(ObjectId(&heightfieldShape), nullptr, heightfieldShape, btTransform::getIdentity()); + mNavigator->addObject(ObjectId(&compound.shape()), ObjectShapes(compound.instance()), btTransform::getIdentity()); mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); @@ -291,9 +318,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); @@ -336,7 +363,8 @@ namespace 0, -25, -100, -100, -100, 0, -25, -100, -100, -100, }}; - btHeightfieldTerrainShape shape = makeSquareHeightfieldTerrainShape(heightfieldData); + const auto shapePtr = makeSquareHeightfieldTerrainShape(heightfieldData); + btHeightfieldTerrainShape& shape = *shapePtr; shape.setLocalScaling(btVector3(128, 128, 1)); const std::array heightfieldData2 {{ @@ -346,12 +374,13 @@ namespace -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, }}; - btHeightfieldTerrainShape shape2 = makeSquareHeightfieldTerrainShape(heightfieldData2); + const auto shapePtr2 = makeSquareHeightfieldTerrainShape(heightfieldData2); + btHeightfieldTerrainShape& shape2 = *shapePtr2; shape2.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(&shape), nullptr, shape, btTransform::getIdentity()); + mNavigator->addObject(ObjectId(&shape2), nullptr, shape2, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); @@ -385,6 +414,8 @@ namespace TEST_F(DetourNavigatorNavigatorTest, path_should_be_around_avoid_shape) { + osg::ref_ptr bulletShape(new Resource::BulletShape); + std::array heightfieldData {{ 0, 0, 0, 0, 0, 0, -25, -25, -25, -25, @@ -392,8 +423,9 @@ namespace 0, -25, -100, -100, -100, 0, -25, -100, -100, -100, }}; - btHeightfieldTerrainShape shape = makeSquareHeightfieldTerrainShape(heightfieldData); - shape.setLocalScaling(btVector3(128, 128, 1)); + auto shapePtr = makeSquareHeightfieldTerrainShape(heightfieldData); + shapePtr->setLocalScaling(btVector3(128, 128, 1)); + bulletShape->mCollisionShape = shapePtr.release(); std::array heightfieldDataAvoid {{ -25, -25, -25, -25, -25, @@ -402,11 +434,14 @@ namespace -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, }}; - btHeightfieldTerrainShape shapeAvoid = makeSquareHeightfieldTerrainShape(heightfieldDataAvoid); - shapeAvoid.setLocalScaling(btVector3(128, 128, 1)); + auto shapeAvoidPtr = makeSquareHeightfieldTerrainShape(heightfieldDataAvoid); + shapeAvoidPtr->setLocalScaling(btVector3(128, 128, 1)); + bulletShape->mAvoidCollisionShape = shapeAvoidPtr.release(); + + osg::ref_ptr 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); @@ -448,12 +483,13 @@ namespace -50, -100, -150, -100, -100, 0, -50, -100, -100, -100, }}; - btHeightfieldTerrainShape shape = makeSquareHeightfieldTerrainShape(heightfieldData); + const auto shapePtr = makeSquareHeightfieldTerrainShape(heightfieldData); + btHeightfieldTerrainShape& shape = *shapePtr; shape.setLocalScaling(btVector3(128, 128, 1)); mNavigator->addAgent(mAgentHalfExtents); mNavigator->addWater(osg::Vec2i(0, 0), 128 * 4, 300, btTransform::getIdentity()); - mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity()); + mNavigator->addObject(ObjectId(&shape), nullptr, shape, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); @@ -495,12 +531,13 @@ namespace 0, -100, -100, -100, -100, -100, 0, 0, 0, 0, 0, 0, 0, 0, }}; - btHeightfieldTerrainShape shape = makeSquareHeightfieldTerrainShape(heightfieldData); + const auto shapePtr = makeSquareHeightfieldTerrainShape(heightfieldData); + btHeightfieldTerrainShape& shape = *shapePtr; shape.setLocalScaling(btVector3(128, 128, 1)); mNavigator->addAgent(mAgentHalfExtents); mNavigator->addWater(osg::Vec2i(0, 0), 128 * 4, -25, btTransform::getIdentity()); - mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity()); + mNavigator->addObject(ObjectId(&shape), nullptr, shape, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); @@ -541,11 +578,12 @@ namespace 0, -100, -100, -100, -100, -100, 0, 0, 0, 0, 0, 0, 0, 0, }}; - btHeightfieldTerrainShape shape = makeSquareHeightfieldTerrainShape(heightfieldData); + const auto shapePtr = makeSquareHeightfieldTerrainShape(heightfieldData); + btHeightfieldTerrainShape& shape = *shapePtr; shape.setLocalScaling(btVector3(128, 128, 1)); mNavigator->addAgent(mAgentHalfExtents); - mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity()); + mNavigator->addObject(ObjectId(&shape), nullptr, shape, btTransform::getIdentity()); mNavigator->addWater(osg::Vec2i(0, 0), std::numeric_limits::max(), -25, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); @@ -587,12 +625,13 @@ namespace 0, -100, -100, -100, -100, -100, 0, 0, 0, 0, 0, 0, 0, 0, }}; - btHeightfieldTerrainShape shape = makeSquareHeightfieldTerrainShape(heightfieldData); + const auto shapePtr = makeSquareHeightfieldTerrainShape(heightfieldData); + btHeightfieldTerrainShape& shape = *shapePtr; shape.setLocalScaling(btVector3(128, 128, 1)); mNavigator->addAgent(mAgentHalfExtents); mNavigator->addWater(osg::Vec2i(0, 0), 128 * 4, -25, btTransform::getIdentity()); - mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity()); + mNavigator->addObject(ObjectId(&shape), nullptr, shape, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); @@ -631,11 +670,12 @@ namespace 0, -25, -100, -100, -100, 0, -25, -100, -100, -100, }}; - btHeightfieldTerrainShape shape = makeSquareHeightfieldTerrainShape(heightfieldData); + const auto shapePtr = makeSquareHeightfieldTerrainShape(heightfieldData); + btHeightfieldTerrainShape& shape = *shapePtr; shape.setLocalScaling(btVector3(128, 128, 1)); mNavigator->addAgent(mAgentHalfExtents); - mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity()); + mNavigator->addObject(ObjectId(&shape), nullptr, shape, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); @@ -643,7 +683,7 @@ namespace mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); - mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity()); + mNavigator->addObject(ObjectId(&shape), nullptr, shape, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); @@ -684,11 +724,12 @@ namespace 0, -25, -100, -100, -100, 0, -25, -100, -100, -100, }}; - btHeightfieldTerrainShape shape = makeSquareHeightfieldTerrainShape(heightfieldData); + const auto shapePtr = makeSquareHeightfieldTerrainShape(heightfieldData); + btHeightfieldTerrainShape& shape = *shapePtr; shape.setLocalScaling(btVector3(128, 128, 1)); mNavigator->addAgent(mAgentHalfExtents); - mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity()); + mNavigator->addObject(ObjectId(&shape), nullptr, shape, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); @@ -716,27 +757,29 @@ namespace 0, -25, -100, -100, -100, 0, -25, -100, -100, -100, }}; - btHeightfieldTerrainShape heightfieldShape = makeSquareHeightfieldTerrainShape(heightfieldData); + const auto heightfieldShapePtr = makeSquareHeightfieldTerrainShape(heightfieldData); + btHeightfieldTerrainShape& heightfieldShape = *heightfieldShapePtr; heightfieldShape.setLocalScaling(btVector3(128, 128, 1)); - const std::vector boxShapes(100, btVector3(20, 20, 100)); + std::vector> boxes; + std::generate_n(std::back_inserter(boxes), 100, [] { return std::make_unique(btVector3(20, 20, 100)); }); mNavigator->addAgent(mAgentHalfExtents); - mNavigator->addObject(ObjectId(&heightfieldShape), heightfieldShape, btTransform::getIdentity()); + mNavigator->addObject(ObjectId(&heightfieldShape), nullptr, heightfieldShape, btTransform::getIdentity()); - 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); @@ -773,14 +816,15 @@ namespace TEST_F(DetourNavigatorNavigatorTest, update_changed_multiple_times_object_should_delay_navmesh_change) { - const std::vector shapes(100, btVector3(64, 64, 64)); + std::vector> shapes; + std::generate_n(std::back_inserter(shapes), 100, [] { return std::make_unique(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); @@ -789,7 +833,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); @@ -797,7 +841,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); @@ -817,11 +861,12 @@ namespace 0, -25, -100, -100, -100, 0, -25, -100, -100, -100, }}; - btHeightfieldTerrainShape shape = makeSquareHeightfieldTerrainShape(heightfieldData); + const auto shapePtr = makeSquareHeightfieldTerrainShape(heightfieldData); + btHeightfieldTerrainShape& shape = *shapePtr; shape.setLocalScaling(btVector3(128, 128, 1)); mNavigator->addAgent(mAgentHalfExtents); - mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity()); + mNavigator->addObject(ObjectId(&shape), nullptr, shape, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); @@ -840,19 +885,20 @@ namespace 0, -25, -100, -100, -100, 0, -25, -100, -100, -100, }}; - btHeightfieldTerrainShape heightfieldShape = makeSquareHeightfieldTerrainShape(heightfieldData); + const auto heightfieldShapePtr = makeSquareHeightfieldTerrainShape(heightfieldData); + btHeightfieldTerrainShape& heightfieldShape = *heightfieldShapePtr; heightfieldShape.setLocalScaling(btVector3(128, 128, 1)); - const btBoxShape oscillatingBoxShape(btVector3(20, 20, 20)); + CollisionShapeInstance oscillatingBox(std::make_unique(btVector3(20, 20, 20))); const btVector3 oscillatingBoxShapePosition(32, 32, 400); - const btBoxShape boderBoxShape(btVector3(50, 50, 50)); + CollisionShapeInstance boderBox(std::make_unique(btVector3(50, 50, 50))); mNavigator->addAgent(mAgentHalfExtents); - mNavigator->addObject(ObjectId(&heightfieldShape), heightfieldShape, btTransform::getIdentity()); - mNavigator->addObject(ObjectId(&oscillatingBoxShape), oscillatingBoxShape, + mNavigator->addObject(ObjectId(&heightfieldShape), nullptr, heightfieldShape, btTransform::getIdentity()); + 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); @@ -869,7 +915,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); } diff --git a/apps/openmw_test_suite/detournavigator/recastmeshobject.cpp b/apps/openmw_test_suite/detournavigator/recastmeshobject.cpp index 621db51a8..7751d5220 100644 --- a/apps/openmw_test_suite/detournavigator/recastmeshobject.cpp +++ b/apps/openmw_test_suite/detournavigator/recastmeshobject.cpp @@ -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)); } } diff --git a/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp b/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp index fb0f97831..038b1c628 100644 --- a/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp +++ b/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp @@ -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()); } @@ -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::max(); ASSERT_TRUE(manager.addWater(cellPosition, cellSize, btTransform::getIdentity())); @@ -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, btTransform::getIdentity())); diff --git a/components/detournavigator/cachedrecastmeshmanager.cpp b/components/detournavigator/cachedrecastmeshmanager.cpp index 2788b8046..20e2979eb 100644 --- a/components/detournavigator/cachedrecastmeshmanager.cpp +++ b/components/detournavigator/cachedrecastmeshmanager.cpp @@ -8,7 +8,7 @@ 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)) diff --git a/components/detournavigator/cachedrecastmeshmanager.hpp b/components/detournavigator/cachedrecastmeshmanager.hpp index ea55348f7..c00096764 100644 --- a/components/detournavigator/cachedrecastmeshmanager.hpp +++ b/components/detournavigator/cachedrecastmeshmanager.hpp @@ -11,7 +11,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); diff --git a/components/detournavigator/navigator.hpp b/components/detournavigator/navigator.hpp index 0dab7ba6b..d0c747650 100644 --- a/components/detournavigator/navigator.hpp +++ b/components/detournavigator/navigator.hpp @@ -9,6 +9,8 @@ #include "recastmeshtiles.hpp" #include "waitconditiontype.hpp" +#include + namespace ESM { struct Cell; @@ -24,11 +26,10 @@ namespace DetourNavigator { struct ObjectShapes { - const btCollisionShape& mShape; - const btCollisionShape* mAvoid; + osg::ref_ptr mShapeInstance; - ObjectShapes(const btCollisionShape& shape, const btCollisionShape* avoid) - : mShape(shape), mAvoid(avoid) + ObjectShapes(const osg::ref_ptr& shapeInstance) + : mShapeInstance(shapeInstance) {} }; @@ -37,9 +38,9 @@ namespace DetourNavigator osg::Vec3f mConnectionStart; osg::Vec3f mConnectionEnd; - DoorShapes(const btCollisionShape& shape, const btCollisionShape* avoid, + DoorShapes(const osg::ref_ptr& shapeInstance, const osg::Vec3f& connectionStart,const osg::Vec3f& connectionEnd) - : ObjectShapes(shape, avoid) + : ObjectShapes(shapeInstance) , mConnectionStart(connectionStart) , mConnectionEnd(connectionEnd) {} @@ -70,13 +71,15 @@ namespace DetourNavigator virtual void removeAgent(const osg::Vec3f& agentHalfExtents) = 0; /** - * @brief addObject is used to add object represented by single btCollisionShape and btTransform. + * @brief addObject is used to add object represented by single btHeightfieldTerrainShape 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 holder shape wrapper to keep shape lifetime after object is removed. + * @param shape must be wrapped by holder. * @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; + virtual bool addObject(const ObjectId id, const osg::ref_ptr& holder, + const btHeightfieldTerrainShape& shape, const btTransform& transform) = 0; /** * @brief addObject is used to add complex object with allowed to walk and avoided to walk shapes @@ -96,15 +99,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. diff --git a/components/detournavigator/navigatorimpl.cpp b/components/detournavigator/navigatorimpl.cpp index 1aa4768de..70a69405e 100644 --- a/components/detournavigator/navigatorimpl.cpp +++ b/components/detournavigator/navigatorimpl.cpp @@ -31,18 +31,22 @@ namespace DetourNavigator --it->second; } - bool NavigatorImpl::addObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform) + bool NavigatorImpl::addObject(const ObjectId id, const osg::ref_ptr& holder, + const btHeightfieldTerrainShape& shape, const btTransform& transform) { - return mNavMeshManager.addObject(id, shape, transform, AreaType_ground); + const CollisionShape collisionShape {holder, shape}; + return mNavMeshManager.addObject(id, collisionShape, 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) + const 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); + const CollisionShape collisionShape {shapes.mShapeInstance, *avoidShape}; + if (mNavMeshManager.addObject(avoidId, collisionShape, transform, AreaType_null)) { updateAvoidShapeId(id, avoidId); result = true; @@ -64,18 +68,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; diff --git a/components/detournavigator/navigatorimpl.hpp b/components/detournavigator/navigatorimpl.hpp index 80c6957d7..c8f0abc68 100644 --- a/components/detournavigator/navigatorimpl.hpp +++ b/components/detournavigator/navigatorimpl.hpp @@ -21,14 +21,13 @@ 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 osg::ref_ptr& holder, + const btHeightfieldTerrainShape& 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; diff --git a/components/detournavigator/navigatorstub.hpp b/components/detournavigator/navigatorstub.hpp index 0a0881393..a507150ca 100644 --- a/components/detournavigator/navigatorstub.hpp +++ b/components/detournavigator/navigatorstub.hpp @@ -19,7 +19,8 @@ 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 osg::ref_ptr& /*holder*/, + const btHeightfieldTerrainShape& /*shape*/, const btTransform& /*transform*/) override { return false; } @@ -34,11 +35,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; diff --git a/components/detournavigator/navmeshmanager.cpp b/components/detournavigator/navmeshmanager.cpp index de4c21c68..b6524db30 100644 --- a/components/detournavigator/navmeshmanager.cpp +++ b/components/detournavigator/navmeshmanager.cpp @@ -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, diff --git a/components/detournavigator/navmeshmanager.hpp b/components/detournavigator/navmeshmanager.hpp index 760ddb6b3..2402dc3b1 100644 --- a/components/detournavigator/navmeshmanager.hpp +++ b/components/detournavigator/navmeshmanager.hpp @@ -23,10 +23,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); diff --git a/components/detournavigator/recastmeshmanager.cpp b/components/detournavigator/recastmeshmanager.cpp index 563a806c5..d475bff1e 100644 --- a/components/detournavigator/recastmeshmanager.cpp +++ b/components/detournavigator/recastmeshmanager.cpp @@ -10,7 +10,7 @@ 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 auto object = mObjects.lower_bound(id); diff --git a/components/detournavigator/recastmeshmanager.hpp b/components/detournavigator/recastmeshmanager.hpp index 5e40ba492..df629ba79 100644 --- a/components/detournavigator/recastmeshmanager.hpp +++ b/components/detournavigator/recastmeshmanager.hpp @@ -38,7 +38,7 @@ namespace DetourNavigator 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); diff --git a/components/detournavigator/recastmeshobject.cpp b/components/detournavigator/recastmeshobject.cpp index 3f3546278..69ef5db62 100644 --- a/components/detournavigator/recastmeshobject.cpp +++ b/components/detournavigator/recastmeshobject.cpp @@ -22,15 +22,36 @@ namespace DetourNavigator } return result; } + + std::vector makeChildrenObjects(const osg::ref_ptr& holder, + const btCompoundShape& shape, const AreaType areaType) + { + std::vector result; + for (int i = 0, num = shape.getNumChildShapes(); i < num; ++i) + { + const CollisionShape collisionShape {holder, *shape.getChildShape(i)}; + result.emplace_back(collisionShape, shape.getChildTransform(i), areaType); + } + return result; + } + + std::vector makeChildrenObjects(const osg::ref_ptr& holder, + const btCollisionShape& shape, const AreaType areaType) + { + if (shape.isCompound()) + return makeChildrenObjects(holder, static_cast(shape), areaType); + return std::vector(); + } } - RecastMeshObject::RecastMeshObject(const btCollisionShape& shape, const btTransform& transform, + RecastMeshObject::RecastMeshObject(const CollisionShape& shape, const btTransform& transform, const AreaType areaType) - : mShape(shape) + : mHolder(shape.getHolder()) + , mShape(shape.getShape()) , mTransform(transform) , mAreaType(areaType) - , mLocalScaling(shape.getLocalScaling()) - , mChildren(makeChildrenObjects(shape, mAreaType)) + , mLocalScaling(mShape.get().getLocalScaling()) + , mChildren(makeChildrenObjects(mHolder, mShape.get(), mAreaType)) { } @@ -57,20 +78,4 @@ namespace DetourNavigator || result; return result; } - - std::vector makeChildrenObjects(const btCollisionShape& shape, const AreaType areaType) - { - if (shape.isCompound()) - return makeChildrenObjects(static_cast(shape), areaType); - else - return std::vector(); - } - - std::vector makeChildrenObjects(const btCompoundShape& shape, const AreaType areaType) - { - std::vector result; - for (int i = 0, num = shape.getNumChildShapes(); i < num; ++i) - result.emplace_back(*shape.getChildShape(i), shape.getChildTransform(i), areaType); - return result; - } } diff --git a/components/detournavigator/recastmeshobject.hpp b/components/detournavigator/recastmeshobject.hpp index e659300e6..94509a5f9 100644 --- a/components/detournavigator/recastmeshobject.hpp +++ b/components/detournavigator/recastmeshobject.hpp @@ -5,6 +5,9 @@ #include +#include +#include + #include #include @@ -13,10 +16,26 @@ class btCompoundShape; namespace DetourNavigator { + class CollisionShape + { + public: + CollisionShape(osg::ref_ptr holder, const btCollisionShape& shape) + : mHolder(std::move(holder)) + , mShape(shape) + {} + + const osg::ref_ptr& getHolder() const { return mHolder; } + const btCollisionShape& getShape() const { return mShape; } + + private: + osg::ref_ptr mHolder; + std::reference_wrapper 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 +55,13 @@ namespace DetourNavigator } private: + osg::ref_ptr mHolder; std::reference_wrapper mShape; btTransform mTransform; AreaType mAreaType; btVector3 mLocalScaling; std::vector mChildren; }; - - std::vector makeChildrenObjects(const btCollisionShape& shape, const AreaType areaType); - - std::vector makeChildrenObjects(const btCompoundShape& shape, const AreaType areaType); } #endif diff --git a/components/detournavigator/tilecachedrecastmeshmanager.cpp b/components/detournavigator/tilecachedrecastmeshmanager.cpp index 42ae93e80..14e94eac3 100644 --- a/components/detournavigator/tilecachedrecastmeshmanager.cpp +++ b/components/detournavigator/tilecachedrecastmeshmanager.cpp @@ -12,14 +12,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 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); @@ -156,7 +156,7 @@ namespace DetourNavigator 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& tiles) { diff --git a/components/detournavigator/tilecachedrecastmeshmanager.hpp b/components/detournavigator/tilecachedrecastmeshmanager.hpp index 23ecc7763..956c2bcf2 100644 --- a/components/detournavigator/tilecachedrecastmeshmanager.hpp +++ b/components/detournavigator/tilecachedrecastmeshmanager.hpp @@ -21,11 +21,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 - 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); @@ -55,7 +55,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) { @@ -103,7 +103,7 @@ namespace DetourNavigator std::size_t mRevision = 0; std::size_t mTilesGeneration = 0; - bool addTile(const ObjectId id, const btCollisionShape& shape, const btTransform& transform, + bool addTile(const ObjectId id, const CollisionShape& shape, const btTransform& transform, const AreaType areaType, const TilePosition& tilePosition, float border, std::map& tiles); diff --git a/components/resource/bulletshape.cpp b/components/resource/bulletshape.cpp index fc68c5545..f44e5a126 100644 --- a/components/resource/bulletshape.cpp +++ b/components/resource/bulletshape.cpp @@ -6,6 +6,7 @@ #include #include #include +#include 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(*shape)); + throw std::logic_error(std::string("Unhandled Bullet shape duplication: ")+shape->getName()); }