mirror of
				https://github.com/TES3MP/openmw-tes3mp.git
				synced 2025-10-31 14:56:44 +00:00 
			
		
		
		
	Store copies of ref_ptr for btCollisionShape wrappers in Navigator
To keep btCollisionShape lifetime.
This commit is contained in:
		
							parent
							
								
									668788a5a2
								
							
						
					
					
						commit
						08b026e907
					
				
					 24 changed files with 276 additions and 198 deletions
				
			
		|  | @ -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 | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ | |||
| #define OPENMW_MWPHYSICS_HEIGHTFIELD_H | ||||
| 
 | ||||
| #include <osg/ref_ptr> | ||||
| #include <osg/Object> | ||||
| 
 | ||||
| #include <LinearMath/btScalar.h> | ||||
| 
 | ||||
|  | @ -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&); | ||||
|     }; | ||||
|  |  | |||
|  | @ -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<HeightField>(heights, x, y, triSize, sqrtVerts, minH, maxH, holdObject, mTaskScheduler.get()); | ||||
|         mHeightFields[std::make_pair(x,y)] = osg::ref_ptr<HeightField>(new HeightField(heights, x, y, triSize, sqrtVerts, minH, maxH, holdObject, mTaskScheduler.get())); | ||||
|     } | ||||
| 
 | ||||
|     void PhysicsSystem::removeHeightField (int x, int y) | ||||
|  |  | |||
|  | @ -276,7 +276,7 @@ namespace MWPhysics | |||
|             using ProjectileMap = std::map<int, std::shared_ptr<Projectile>>; | ||||
|             ProjectileMap mProjectiles; | ||||
| 
 | ||||
|             using HeightFieldMap = std::map<std::pair<int, int>, std::unique_ptr<HeightField>>; | ||||
|             using HeightFieldMap = std::map<std::pair<int, int>, osg::ref_ptr<HeightField>>; | ||||
|             HeightFieldMap mHeightFields; | ||||
| 
 | ||||
|             bool mDebugDrawEnabled; | ||||
|  |  | |||
|  | @ -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()); | ||||
|             } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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; | ||||
|     } | ||||
|  |  | |||
|  | @ -4,6 +4,9 @@ | |||
| #include <components/detournavigator/exceptions.hpp> | ||||
| #include <components/misc/rng.hpp> | ||||
| #include <components/loadinglistener/loadinglistener.hpp> | ||||
| #include <components/resource/bulletshape.hpp> | ||||
| 
 | ||||
| #include <osg/ref_ptr> | ||||
| 
 | ||||
| #include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h> | ||||
| #include <BulletCollision/CollisionShapes/btBoxShape.h> | ||||
|  | @ -14,6 +17,7 @@ | |||
| 
 | ||||
| #include <array> | ||||
| #include <deque> | ||||
| #include <memory> | ||||
| 
 | ||||
| MATCHER_P3(Vec3fEq, x, y, z, "") | ||||
| { | ||||
|  | @ -80,16 +84,38 @@ 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 <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), | ||||
|  | @ -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<btCompoundShape>()); | ||||
|         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<btCompoundShape>()); | ||||
|         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<btScalar, 5 * 5> 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<Resource::BulletShape> bulletShape(new Resource::BulletShape); | ||||
| 
 | ||||
|         std::array<btScalar, 5 * 5> 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<btScalar, 5 * 5> 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<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); | ||||
| 
 | ||||
|  | @ -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<int>::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<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->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<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); | ||||
|  | @ -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<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->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); | ||||
|         } | ||||
|  |  | |||
|  | @ -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, 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())); | ||||
|  |  | |||
|  | @ -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)) | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -9,6 +9,8 @@ | |||
| #include "recastmeshtiles.hpp" | ||||
| #include "waitconditiontype.hpp" | ||||
| 
 | ||||
| #include <components/resource/bulletshape.hpp> | ||||
| 
 | ||||
| namespace ESM | ||||
| { | ||||
|     struct Cell; | ||||
|  | @ -24,11 +26,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) | ||||
|         {} | ||||
|     }; | ||||
| 
 | ||||
|  | @ -37,9 +38,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) | ||||
|         {} | ||||
|  | @ -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<const osg::Object>& 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. | ||||
|  |  | |||
|  | @ -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<const osg::Object>& 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; | ||||
|  |  | |||
|  | @ -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<const osg::Object>& 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; | ||||
|  |  | |||
|  | @ -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<const osg::Object>& /*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; | ||||
|  |  | |||
|  | @ -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, | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -22,15 +22,36 @@ namespace DetourNavigator | |||
|             } | ||||
|             return result; | ||||
|         } | ||||
| 
 | ||||
|         std::vector<RecastMeshObject> makeChildrenObjects(const osg::ref_ptr<const osg::Object>& holder, | ||||
|                                                           const btCompoundShape& shape, const AreaType areaType) | ||||
|         { | ||||
|             std::vector<RecastMeshObject> 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<RecastMeshObject> makeChildrenObjects(const osg::ref_ptr<const osg::Object>& holder, | ||||
|                                                           const btCollisionShape& shape, const AreaType areaType) | ||||
|         { | ||||
|             if (shape.isCompound()) | ||||
|                 return makeChildrenObjects(holder, 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) | ||||
|         : 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<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; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -5,6 +5,9 @@ | |||
| 
 | ||||
| #include <LinearMath/btTransform.h> | ||||
| 
 | ||||
| #include <osg/ref_ptr> | ||||
| #include <osg/Object> | ||||
| 
 | ||||
| #include <functional> | ||||
| #include <vector> | ||||
| 
 | ||||
|  | @ -13,10 +16,26 @@ class btCompoundShape; | |||
| 
 | ||||
| namespace DetourNavigator | ||||
| { | ||||
|     class CollisionShape | ||||
|     { | ||||
|     public: | ||||
|         CollisionShape(osg::ref_ptr<const osg::Object> holder, const btCollisionShape& shape) | ||||
|             : mHolder(std::move(holder)) | ||||
|             , mShape(shape) | ||||
|         {} | ||||
| 
 | ||||
|         const osg::ref_ptr<const osg::Object>& getHolder() const { return mHolder; } | ||||
|         const btCollisionShape& getShape() const { return mShape; } | ||||
| 
 | ||||
|     private: | ||||
|         osg::ref_ptr<const osg::Object> mHolder; | ||||
|         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 +55,13 @@ namespace DetourNavigator | |||
|             } | ||||
| 
 | ||||
|         private: | ||||
|             osg::ref_ptr<const osg::Object> mHolder; | ||||
|             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 | ||||
|  |  | |||
|  | @ -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<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); | ||||
|  | @ -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<TilePosition, CachedRecastMeshManager>& tiles) | ||||
|     { | ||||
|  |  | |||
|  | @ -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 <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); | ||||
|  | @ -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<TilePosition, CachedRecastMeshManager>& 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…
	
		Reference in a new issue