mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 15:29:55 +00:00
Add NifFileManager to avoid duplicate parsing of the NIFFile in SceneManager and BulletShapeManager.
This commit is contained in:
parent
84305a1297
commit
3d12b2ca9d
11 changed files with 153 additions and 16 deletions
|
@ -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;
|
||||
|
|
64
components/resource/niffilemanager.cpp
Normal file
64
components/resource/niffilemanager.cpp
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
45
components/resource/niffilemanager.hpp
Normal file
45
components/resource/niffilemanager.hpp
Normal 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…
Reference in a new issue