diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 6417968d3..5d0ac1f8f 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -1088,7 +1088,7 @@ namespace MWPhysics void PhysicsSystem::addObject (const MWWorld::Ptr& ptr, const std::string& mesh, int collisionType) { - osg::ref_ptr shapeInstance = mShapeManager->createInstance(mesh); + osg::ref_ptr shapeInstance = mShapeManager->getInstance(mesh); if (!shapeInstance || !shapeInstance->getCollisionShape()) return; @@ -1234,7 +1234,7 @@ namespace MWPhysics } void PhysicsSystem::addActor (const MWWorld::Ptr& ptr, const std::string& mesh) { - osg::ref_ptr shapeInstance = mShapeManager->createInstance(mesh); + osg::ref_ptr shapeInstance = mShapeManager->getInstance(mesh); if (!shapeInstance) return; diff --git a/apps/openmw/mwworld/cellpreloader.cpp b/apps/openmw/mwworld/cellpreloader.cpp index c6fa3b949..047c1e99b 100644 --- a/apps/openmw/mwworld/cellpreloader.cpp +++ b/apps/openmw/mwworld/cellpreloader.cpp @@ -87,7 +87,7 @@ namespace MWWorld //std::cout << "preloading " << mesh << std::endl; mPreloadedNodes.push_back(mSceneManager->cacheInstance(mesh)); - mPreloadedShapes.push_back(mBulletShapeManager->getShape(mesh)); + mPreloadedShapes.push_back(mBulletShapeManager->cacheInstance(mesh)); size_t slashpos = mesh.find_last_of("/\\"); if (slashpos != std::string::npos && slashpos != mesh.size()-1) @@ -123,7 +123,7 @@ namespace MWWorld // keep a ref to the loaded object to make sure it stays loaded as long as this cell is in the preloaded state std::vector > mPreloadedNodes; - std::vector > mPreloadedShapes; + std::vector > mPreloadedShapes; std::vector > mPreloadedKeyframes; }; diff --git a/components/resource/bulletshapemanager.cpp b/components/resource/bulletshapemanager.cpp index cb57d686f..111808e6e 100644 --- a/components/resource/bulletshapemanager.cpp +++ b/components/resource/bulletshapemanager.cpp @@ -14,7 +14,7 @@ #include "scenemanager.hpp" #include "niffilemanager.hpp" #include "objectcache.hpp" - +#include "multiobjectcache.hpp" namespace Resource { @@ -98,6 +98,7 @@ private: BulletShapeManager::BulletShapeManager(const VFS::Manager* vfs, SceneManager* sceneMgr, NifFileManager* nifFileManager) : ResourceManager(vfs) + , mInstanceCache(new MultiObjectCache) , mSceneManager(sceneMgr) , mNifFileManager(nifFileManager) { @@ -151,6 +152,28 @@ osg::ref_ptr BulletShapeManager::getShape(const std::string & return shape; } +osg::ref_ptr BulletShapeManager::cacheInstance(const std::string &name) +{ + std::string normalized = name; + mVFS->normalizeFilename(normalized); + + osg::ref_ptr instance = createInstance(normalized); + mInstanceCache->addEntryToObjectCache(normalized, instance.get()); + return instance; +} + +osg::ref_ptr BulletShapeManager::getInstance(const std::string &name) +{ + std::string normalized = name; + mVFS->normalizeFilename(normalized); + + osg::ref_ptr obj = mInstanceCache->takeFromObjectCache(normalized); + if (obj.get()) + return static_cast(obj.get()); + else + return createInstance(normalized); +} + osg::ref_ptr BulletShapeManager::createInstance(const std::string &name) { osg::ref_ptr shape = getShape(name); @@ -160,4 +183,11 @@ osg::ref_ptr BulletShapeManager::createInstance(const std:: return osg::ref_ptr(); } +void BulletShapeManager::updateCache(double referenceTime) +{ + ResourceManager::updateCache(referenceTime); + + mInstanceCache->removeUnreferencedObjectsInCache(); +} + } diff --git a/components/resource/bulletshapemanager.hpp b/components/resource/bulletshapemanager.hpp index 4c0cb1fd2..14b26962b 100644 --- a/components/resource/bulletshapemanager.hpp +++ b/components/resource/bulletshapemanager.hpp @@ -17,6 +17,8 @@ namespace Resource class BulletShape; class BulletShapeInstance; + class MultiObjectCache; + /// Handles loading, caching and "instancing" of bullet shapes. /// A shape 'instance' is a clone of another shape, with the goal of setting a different scale on this instance. /// @note May be used from any thread. @@ -26,12 +28,24 @@ namespace Resource BulletShapeManager(const VFS::Manager* vfs, SceneManager* sceneMgr, NifFileManager* nifFileManager); ~BulletShapeManager(); + /// @note May return a null pointer if the object has no shape. osg::ref_ptr getShape(const std::string& name); - /// Shorthand for getShape(name)->makeInstance(); - osg::ref_ptr createInstance(const std::string& name); + /// Create an instance of the given shape and cache it for later use, so that future calls to getInstance() can simply return + /// the cached instance instead of having to create a new one. + /// @note The returned ref_ptr may be kept by the caller to ensure that the instance stays in cache for as long as needed. + osg::ref_ptr cacheInstance(const std::string& name); + + /// @note May return a null pointer if the object has no shape. + osg::ref_ptr getInstance(const std::string& name); + + /// @see ResourceManager::updateCache + virtual void updateCache(double referenceTime); private: + osg::ref_ptr createInstance(const std::string& name); + + osg::ref_ptr mInstanceCache; SceneManager* mSceneManager; NifFileManager* mNifFileManager; };