Improve NPC loading performance by caching the cleaned objectRoot

pull/177/head
scrawl 8 years ago
parent 058681ad73
commit 4e0011bfc8

@ -1123,6 +1123,32 @@ namespace MWRender
state->second.mLoopingEnabled = enabled;
}
osg::ref_ptr<osg::Node> getModelInstance(Resource::SceneManager* sceneMgr, const std::string& model, bool baseonly)
{
if (baseonly)
{
typedef std::map<std::string, osg::ref_ptr<osg::Node> > Cache;
static Cache cache;
Cache::iterator found = cache.find(model);
if (found == cache.end())
{
osg::ref_ptr<osg::Node> created = sceneMgr->getInstance(model);
RemoveDrawableVisitor removeDrawableVisitor;
created->accept(removeDrawableVisitor);
removeDrawableVisitor.remove();
cache.insert(std::make_pair(model, created));
return sceneMgr->createInstance(created);
}
else
return sceneMgr->createInstance(found->second);
}
else
return sceneMgr->createInstance(model);
}
void Animation::setObjectRoot(const std::string &model, bool forceskeleton, bool baseonly, bool isCreature)
{
osg::ref_ptr<osg::StateSet> previousStateset;
@ -1144,7 +1170,8 @@ namespace MWRender
if (!forceskeleton)
{
osg::ref_ptr<osg::Node> created = mResourceSystem->getSceneManager()->getInstance(model, mInsert);
osg::ref_ptr<osg::Node> created = getModelInstance(mResourceSystem->getSceneManager(), model, baseonly);
mInsert->addChild(created);
mObjectRoot = created->asGroup();
if (!mObjectRoot)
{
@ -1156,7 +1183,7 @@ namespace MWRender
}
else
{
osg::ref_ptr<osg::Node> created = mResourceSystem->getSceneManager()->getInstance(model);
osg::ref_ptr<osg::Node> created = getModelInstance(mResourceSystem->getSceneManager(), model, baseonly);
osg::ref_ptr<SceneUtil::Skeleton> skel = dynamic_cast<SceneUtil::Skeleton*>(created.get());
if (!skel)
{
@ -1171,13 +1198,6 @@ namespace MWRender
if (previousStateset)
mObjectRoot->setStateSet(previousStateset);
if (baseonly)
{
RemoveDrawableVisitor removeDrawableVisitor;
mObjectRoot->accept(removeDrawableVisitor);
removeDrawableVisitor.remove();
}
if (isCreature)
{
RemoveTriBipVisitor removeTriBipVisitor;

@ -538,10 +538,15 @@ namespace Resource
osg::ref_ptr<osg::Node> SceneManager::createInstance(const std::string& name)
{
osg::ref_ptr<const osg::Node> scene = getTemplate(name);
osg::ref_ptr<osg::Node> cloned = osg::clone(scene.get(), SceneUtil::CopyOp());
return createInstance(scene);
}
osg::ref_ptr<osg::Node> SceneManager::createInstance(const osg::Node *base)
{
osg::ref_ptr<osg::Node> cloned = osg::clone(base, SceneUtil::CopyOp());
// add a ref to the original template, to hint to the cache that it's still being used and should be kept in cache
cloned->getOrCreateUserDataContainer()->addUserObject(new TemplateRef(scene));
cloned->getOrCreateUserDataContainer()->addUserObject(new TemplateRef(base));
// we can skip any scene graphs without update callbacks since we know that particle emitters will have an update callback set
if (cloned->getNumChildrenRequiringUpdateTraversal() > 0)

@ -93,6 +93,10 @@ namespace Resource
/// @note Thread safe.
osg::ref_ptr<osg::Node> cacheInstance(const std::string& name);
osg::ref_ptr<osg::Node> createInstance(const std::string& name);
osg::ref_ptr<osg::Node> createInstance(const osg::Node* base);
/// Get an instance of the given scene template
/// @see getTemplate
/// @note Thread safe.
@ -141,8 +145,6 @@ namespace Resource
private:
osg::ref_ptr<osg::Node> createInstance(const std::string& name);
std::auto_ptr<Shader::ShaderManager> mShaderManager;
bool mForceShaders;
bool mClampLighting;

Loading…
Cancel
Save