From 8ece1885cdc2662ceaefcd4542abdf9970880483 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 9 Feb 2016 16:18:19 +0100 Subject: [PATCH] Animation: don't create the NodeMap if we don't need it --- apps/openmw/mwrender/animation.cpp | 61 +++++++++++++++++------------- apps/openmw/mwrender/animation.hpp | 5 ++- 2 files changed, 39 insertions(+), 27 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 3d4fd11d0..5aea13660 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -95,7 +95,12 @@ namespace class NodeMapVisitor : public osg::NodeVisitor { public: - NodeMapVisitor() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} + typedef std::map > NodeMap; + + NodeMapVisitor(NodeMap& map) + : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) + , mMap(map) + {} void apply(osg::MatrixTransform& trans) { @@ -103,15 +108,8 @@ namespace traverse(trans); } - typedef std::map > NodeMap; - - const NodeMap& getNodeMap() const - { - return mMap; - } - private: - NodeMap mMap; + NodeMap& mMap; }; NifOsg::TextKeyMap::const_iterator findGroupStart(const NifOsg::TextKeyMap &keys, const std::string &groupname) @@ -312,6 +310,7 @@ namespace MWRender Animation::Animation(const MWWorld::Ptr &ptr, osg::ref_ptr parentNode, Resource::ResourceSystem* resourceSystem) : mInsert(parentNode) , mSkeleton(NULL) + , mNodeMapCreated(false) , mPtr(ptr) , mResourceSystem(resourceSystem) , mAccumulate(1.f, 1.f, 0.f) @@ -407,12 +406,14 @@ namespace MWRender if (!animsrc->mKeyframes || animsrc->mKeyframes->mTextKeys.empty() || animsrc->mKeyframes->mKeyframeControllers.empty()) return; + const NodeMap& nodeMap = getNodeMap(); + for (NifOsg::KeyframeHolder::KeyframeControllerMap::const_iterator it = animsrc->mKeyframes->mKeyframeControllers.begin(); it != animsrc->mKeyframes->mKeyframeControllers.end(); ++it) { std::string bonename = Misc::StringUtils::lowerCase(it->first); - NodeMap::const_iterator found = mNodeMap.find(bonename); - if (found == mNodeMap.end()) + NodeMap::const_iterator found = nodeMap.find(bonename); + if (found == nodeMap.end()) { std::cerr << "addAnimSource: can't find bone '" + bonename << "' in " << model << " (referenced by " << kfname << ")" << std::endl; continue; @@ -436,11 +437,11 @@ namespace MWRender if (!mAccumRoot) { - NodeMap::const_iterator found = mNodeMap.find("root bone"); - if (found == mNodeMap.end()) - found = mNodeMap.find("bip01"); + NodeMap::const_iterator found = nodeMap.find("root bone"); + if (found == nodeMap.end()) + found = nodeMap.find("bip01"); - if (found != mNodeMap.end()) + if (found != nodeMap.end()) mAccumRoot = found->second; } } @@ -690,6 +691,17 @@ namespace MWRender mTextKeyListener = listener; } + const Animation::NodeMap &Animation::getNodeMap() const + { + if (!mNodeMapCreated && mObjectRoot) + { + NodeMapVisitor visitor(mNodeMap); + mObjectRoot->accept(visitor); + mNodeMapCreated = true; + } + return mNodeMap; + } + void Animation::resetActiveGroups() { // remove all previous external controllers from the scene graph @@ -729,7 +741,7 @@ namespace MWRender for (AnimSource::ControllerMap::iterator it = animsrc->mControllerMap[blendMask].begin(); it != animsrc->mControllerMap[blendMask].end(); ++it) { - osg::ref_ptr node = mNodeMap.at(it->first); // this should not throw, we already checked for the node existing in addAnimSource + osg::ref_ptr node = getNodeMap().at(it->first); // this should not throw, we already checked for the node existing in addAnimSource node->addUpdateCallback(it->second); mActiveControllers.insert(std::make_pair(node, it->second)); @@ -978,6 +990,7 @@ namespace MWRender mSkeleton = NULL; mNodeMap.clear(); + mNodeMapCreated = false; mActiveControllers.clear(); mAccumRoot = NULL; mAccumCtrl = NULL; @@ -1025,10 +1038,6 @@ namespace MWRender removeTriBipVisitor.remove(); } - NodeMapVisitor visitor; - mObjectRoot->accept(visitor); - mNodeMap = visitor.getNodeMap(); - mObjectRoot->addCullCallback(new SceneUtil::LightListCallback); } @@ -1121,8 +1130,8 @@ namespace MWRender parentNode = mInsert; else { - NodeMap::iterator found = mNodeMap.find(Misc::StringUtils::lowerCase(bonename)); - if (found == mNodeMap.end()) + NodeMap::const_iterator found = getNodeMap().find(Misc::StringUtils::lowerCase(bonename)); + if (found == getNodeMap().end()) throw std::runtime_error("Can't find bone " + bonename); parentNode = found->second; @@ -1222,8 +1231,8 @@ namespace MWRender const osg::Node* Animation::getNode(const std::string &name) const { std::string lowerName = Misc::StringUtils::lowerCase(name); - NodeMap::const_iterator found = mNodeMap.find(lowerName); - if (found == mNodeMap.end()) + NodeMap::const_iterator found = getNodeMap().find(lowerName); + if (found == getNodeMap().end()) return NULL; else return found->second; @@ -1317,8 +1326,8 @@ namespace MWRender if (mPtr.getClass().isBipedal(mPtr)) { - NodeMap::iterator found = mNodeMap.find("bip01 head"); - if (found != mNodeMap.end() && dynamic_cast(found->second.get())) + NodeMap::const_iterator found = getNodeMap().find("bip01 head"); + if (found != getNodeMap().end() && dynamic_cast(found->second.get())) { osg::Node* node = found->second; mHeadController = new RotateController(mObjectRoot.get()); diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index feaf0e16c..1d7930566 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -232,7 +232,8 @@ protected: // Stored in all lowercase for a case-insensitive lookup typedef std::map > NodeMap; - NodeMap mNodeMap; + mutable NodeMap mNodeMap; + mutable bool mNodeMapCreated; MWWorld::Ptr mPtr; @@ -263,6 +264,8 @@ protected: float mAlpha; + const NodeMap& getNodeMap() const; + /* Sets the appropriate animations on the bone groups based on priority. */ void resetActiveGroups();