Add NifFileManager to avoid duplicate parsing of the NIFFile in SceneManager and BulletShapeManager.

openmw-38
scrawl 9 years ago
parent 84305a1297
commit 3d12b2ca9d

@ -636,7 +636,7 @@ namespace MWPhysics
// ---------------------------------------------------------------
PhysicsSystem::PhysicsSystem(Resource::ResourceSystem* resourceSystem, osg::ref_ptr<osg::Group> parentNode)
: mShapeManager(new Resource::BulletShapeManager(resourceSystem->getVFS(), resourceSystem->getSceneManager()))
: mShapeManager(new Resource::BulletShapeManager(resourceSystem->getVFS(), resourceSystem->getSceneManager(), resourceSystem->getNifFileManager()))
, mDebugDrawEnabled(false)
, mTimeAccum(0.0f)
, mWaterHeight(0)

@ -403,6 +403,8 @@ namespace MWWorld
// Delay the map update until scripts have been given a chance to run.
// If we don't do this, objects that should be disabled will still appear on the map.
mNeedMapUpdate = true;
mRendering.getResourceSystem()->clearCache();
}
void Scene::changePlayerCell(CellStore *cell, const ESM::Position &pos, bool adjustPlayerPos)
@ -518,6 +520,8 @@ namespace MWWorld
// Delay the map update until scripts have been given a chance to run.
// If we don't do this, objects that should be disabled will still appear on the map.
mNeedMapUpdate = true;
mRendering.getResourceSystem()->clearCache();
}
void Scene::changeToExteriorCell (const ESM::Position& position, bool adjustPlayerPos)

@ -37,7 +37,7 @@ add_component_dir (vfs
)
add_component_dir (resource
scenemanager texturemanager resourcesystem bulletshapemanager bulletshape
scenemanager texturemanager resourcesystem bulletshapemanager bulletshape niffilemanager
)
add_component_dir (sceneutil

@ -12,6 +12,7 @@
#include "bulletshape.hpp"
#include "scenemanager.hpp"
#include "niffilemanager.hpp"
namespace Resource
@ -94,9 +95,10 @@ private:
btTriangleMesh* mTriangleMesh;
};
BulletShapeManager::BulletShapeManager(const VFS::Manager* vfs, SceneManager* sceneMgr)
BulletShapeManager::BulletShapeManager(const VFS::Manager* vfs, SceneManager* sceneMgr, NifFileManager* nifFileManager)
: mVFS(vfs)
, mSceneManager(sceneMgr)
, mNifFileManager(nifFileManager)
{
}
@ -115,8 +117,6 @@ osg::ref_ptr<BulletShapeInstance> BulletShapeManager::createInstance(const std::
Index::iterator it = mIndex.find(normalized);
if (it == mIndex.end())
{
Files::IStreamPtr file = mVFS->get(normalized);
size_t extPos = normalized.find_last_of('.');
std::string ext;
if (extPos != std::string::npos && extPos+1 < normalized.size())
@ -126,7 +126,7 @@ osg::ref_ptr<BulletShapeInstance> BulletShapeManager::createInstance(const std::
{
NifBullet::BulletNifLoader loader;
// might be worth sharing NIFFiles with SceneManager in some way
shape = loader.load(Nif::NIFFilePtr(new Nif::NIFFile(file, normalized)));
shape = loader.load(mNifFileManager->get(normalized));
}
else
{

@ -16,6 +16,7 @@ namespace VFS
namespace Resource
{
class SceneManager;
class NifFileManager;
class BulletShape;
class BulletShapeInstance;
@ -23,7 +24,7 @@ namespace Resource
class BulletShapeManager
{
public:
BulletShapeManager(const VFS::Manager* vfs, SceneManager* sceneMgr);
BulletShapeManager(const VFS::Manager* vfs, SceneManager* sceneMgr, NifFileManager* nifFileManager);
~BulletShapeManager();
osg::ref_ptr<BulletShapeInstance> createInstance(const std::string& name);
@ -31,6 +32,7 @@ namespace Resource
private:
const VFS::Manager* mVFS;
SceneManager* mSceneManager;
NifFileManager* mNifFileManager;
typedef std::map<std::string, osg::ref_ptr<BulletShape> > Index;
Index mIndex;

@ -0,0 +1,64 @@
#include "niffilemanager.hpp"
#include <osgDB/ObjectCache>
#include <components/vfs/manager.hpp>
#include <osg/Timer>
namespace Resource
{
class NifFileHolder : public osg::Object
{
public:
NifFileHolder(const Nif::NIFFilePtr& file)
: mNifFile(file)
{
}
NifFileHolder(const NifFileHolder& copy, const osg::CopyOp& copyop)
: mNifFile(copy.mNifFile)
{
}
NifFileHolder()
{
}
META_Object(Resource, NifFileHolder)
Nif::NIFFilePtr mNifFile;
};
NifFileManager::NifFileManager(const VFS::Manager *vfs)
: mVFS(vfs)
{
mCache = new osgDB::ObjectCache;
}
NifFileManager::~NifFileManager()
{
}
void NifFileManager::clearCache()
{
// NIF files aren't needed any more when the converted objects are cached in SceneManager / BulletShapeManager,
// so we'll simply drop all nif files here, unlikely to need them again
mCache->clear();
}
Nif::NIFFilePtr NifFileManager::get(const std::string &name)
{
osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(name);
if (obj)
return static_cast<NifFileHolder*>(obj.get())->mNifFile;
else
{
Nif::NIFFilePtr file (new Nif::NIFFile(mVFS->get(name), name));
obj = new NifFileHolder(file);
mCache->addEntryToObjectCache(name, obj);
return file;
}
}
}

@ -0,0 +1,45 @@
#ifndef OPENMW_COMPONENTS_RESOURCE_NIFFILEMANAGER_H
#define OPENMW_COMPONENTS_RESOURCE_NIFFILEMANAGER_H
#include <osg/ref_ptr>
#include <components/nif/niffile.hpp>
namespace VFS
{
class Manager;
}
namespace osgDB
{
class ObjectCache;
}
namespace Resource
{
/// @brief Handles caching of NIFFiles.
/// @note The NifFileManager is completely thread safe.
class NifFileManager
{
public:
NifFileManager(const VFS::Manager* vfs);
~NifFileManager();
void clearCache();
/// Retrieve a NIF file from the cache, or load it from the VFS if not cached yet.
/// @note For performance reasons the NifFileManager does not handle case folding, needs
/// to be done in advance by other managers accessing the NifFileManager.
Nif::NIFFilePtr get(const std::string& name);
private:
// Use the osgDB::ObjectCache so objects are retrieved in thread safe way
osg::ref_ptr<osgDB::ObjectCache> mCache;
const VFS::Manager* mVFS;
};
}
#endif

@ -2,6 +2,7 @@
#include "scenemanager.hpp"
#include "texturemanager.hpp"
#include "niffilemanager.hpp"
namespace Resource
{
@ -9,8 +10,9 @@ namespace Resource
ResourceSystem::ResourceSystem(const VFS::Manager *vfs)
: mVFS(vfs)
{
mNifFileManager.reset(new NifFileManager(vfs));
mTextureManager.reset(new TextureManager(vfs));
mSceneManager.reset(new SceneManager(vfs, mTextureManager.get()));
mSceneManager.reset(new SceneManager(vfs, mTextureManager.get(), mNifFileManager.get()));
}
ResourceSystem::~ResourceSystem()
@ -28,6 +30,16 @@ namespace Resource
return mTextureManager.get();
}
NifFileManager *ResourceSystem::getNifFileManager()
{
return mNifFileManager.get();
}
void ResourceSystem::clearCache()
{
mNifFileManager->clearCache();
}
const VFS::Manager* ResourceSystem::getVFS() const
{
return mVFS;

@ -13,8 +13,9 @@ namespace Resource
class SceneManager;
class TextureManager;
class NifFileManager;
/// @brief Wrapper class that constructs and provides access to the various resource subsystems.
/// @brief Wrapper class that constructs and provides access to the most commonly used resource subsystems.
/// @par Resource subsystems can be used with multiple OpenGL contexts, just like the OSG equivalents, but
/// are built around the use of a single virtual file system.
class ResourceSystem
@ -25,12 +26,17 @@ namespace Resource
SceneManager* getSceneManager();
TextureManager* getTextureManager();
NifFileManager* getNifFileManager();
/// Indicates to each resource manager to clear the cache, i.e. to drop cached objects that are no longer referenced.
void clearCache();
const VFS::Manager* getVFS() const;
private:
std::auto_ptr<SceneManager> mSceneManager;
std::auto_ptr<TextureManager> mTextureManager;
std::auto_ptr<NifFileManager> mNifFileManager;
const VFS::Manager* mVFS;

@ -21,6 +21,7 @@
#include <components/sceneutil/util.hpp>
#include "texturemanager.hpp"
#include "niffilemanager.hpp"
namespace
{
@ -104,9 +105,10 @@ namespace
namespace Resource
{
SceneManager::SceneManager(const VFS::Manager *vfs, Resource::TextureManager* textureManager)
SceneManager::SceneManager(const VFS::Manager *vfs, Resource::TextureManager* textureManager, Resource::NifFileManager* nifFileManager)
: mVFS(vfs)
, mTextureManager(textureManager)
, mNifFileManager(nifFileManager)
, mParticleSystemMask(~0u)
{
}
@ -150,11 +152,11 @@ namespace Resource
return std::string();
}
osg::ref_ptr<osg::Node> load (Files::IStreamPtr file, const std::string& normalizedFilename, Resource::TextureManager* textureMgr)
osg::ref_ptr<osg::Node> load (Files::IStreamPtr file, const std::string& normalizedFilename, Resource::TextureManager* textureMgr, Resource::NifFileManager* nifFileManager)
{
std::string ext = getFileExtension(normalizedFilename);
if (ext == "nif")
return NifOsg::Loader::load(Nif::NIFFilePtr(new Nif::NIFFile(file, normalizedFilename)), textureMgr);
return NifOsg::Loader::load(nifFileManager->get(normalizedFilename), textureMgr);
else
{
osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension(ext);
@ -195,14 +197,14 @@ namespace Resource
{
Files::IStreamPtr file = mVFS->get(normalized);
loaded = load(file, normalized, mTextureManager);
loaded = load(file, normalized, mTextureManager, mNifFileManager);
}
catch (std::exception& e)
{
std::cerr << "Failed to load '" << name << "': " << e.what() << ", using marker_error.nif instead" << std::endl;
Files::IStreamPtr file = mVFS->get("meshes/marker_error.nif");
normalized = "meshes/marker_error.nif";
loaded = load(file, normalized, mTextureManager);
loaded = load(file, normalized, mTextureManager, mNifFileManager);
}
osgDB::Registry::instance()->getOrCreateSharedStateManager()->share(loaded.get());

@ -10,6 +10,7 @@
namespace Resource
{
class TextureManager;
class NifFileManager;
}
namespace VFS
@ -34,7 +35,7 @@ namespace Resource
class SceneManager
{
public:
SceneManager(const VFS::Manager* vfs, Resource::TextureManager* textureManager);
SceneManager(const VFS::Manager* vfs, Resource::TextureManager* textureManager, Resource::NifFileManager* nifFileManager);
~SceneManager();
/// Get a read-only copy of this scene "template"
@ -66,7 +67,7 @@ namespace Resource
/// Set up an IncrementalCompileOperation for background compiling of loaded scenes.
void setIncrementalCompileOperation(osgUtil::IncrementalCompileOperation* ico);
/// @note If you used SceneManager::attachTo, this was called automatically.
/// @note SceneManager::attachTo calls this method automatically, only needs to be called by users if manually attaching
void notifyAttached(osg::Node* node) const;
const VFS::Manager* getVFS() const;
@ -79,6 +80,7 @@ namespace Resource
private:
const VFS::Manager* mVFS;
Resource::TextureManager* mTextureManager;
Resource::NifFileManager* mNifFileManager;
osg::ref_ptr<osgUtil::IncrementalCompileOperation> mIncrementalCompileOperation;

Loading…
Cancel
Save