1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-21 12:23:53 +00:00

Merge pull request #2862 from elsid/optimize_has_animation

Optimize MWRender::Animation::hasAnimation
This commit is contained in:
Bret Curtis 2020-05-22 10:33:37 +02:00 committed by GitHub
commit 357a845d00
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 117 additions and 42 deletions

View file

@ -942,7 +942,7 @@ void split(const std::string &s, char delim, std::vector<std::string> &elems) {
} }
} }
void CharacterController::handleTextKey(const std::string &groupname, const std::multimap<float, std::string>::const_iterator &key, const std::multimap<float, std::string> &map) void CharacterController::handleTextKey(const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key, const NifOsg::TextKeyMap& map)
{ {
const std::string &evt = key->second; const std::string &evt = key->second;

View file

@ -238,8 +238,7 @@ public:
CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim); CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim);
virtual ~CharacterController(); virtual ~CharacterController();
virtual void handleTextKey(const std::string &groupname, const std::multimap<float, std::string>::const_iterator &key, virtual void handleTextKey(const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key, const NifOsg::TextKeyMap& map);
const std::multimap<float, std::string>& map);
// Be careful when to call this, see comment in Actors // Be careful when to call this, see comment in Actors
void updateContinuousVfx(); void updateContinuousVfx();

View file

@ -151,20 +151,8 @@ namespace
} }
}; };
NifOsg::TextKeyMap::const_iterator findGroupStart(const NifOsg::TextKeyMap &keys, const std::string &groupname) float calcAnimVelocity(const NifOsg::TextKeyMap& keys, NifOsg::KeyframeController *nonaccumctrl,
{ const osg::Vec3f& accum, const std::string &groupname)
NifOsg::TextKeyMap::const_iterator iter(keys.begin());
for(;iter != keys.end();++iter)
{
if(iter->second.compare(0, groupname.size(), groupname) == 0 &&
iter->second.compare(groupname.size(), 2, ": ") == 0)
break;
}
return iter;
}
float calcAnimVelocity(const std::multimap<float, std::string>& keys,
NifOsg::KeyframeController *nonaccumctrl, const osg::Vec3f& accum, const std::string &groupname)
{ {
const std::string start = groupname+": start"; const std::string start = groupname+": start";
const std::string loopstart = groupname+": loop start"; const std::string loopstart = groupname+": loop start";
@ -179,7 +167,7 @@ namespace
// but the animation velocity calculation uses the second one. // but the animation velocity calculation uses the second one.
// As result the animation velocity calculation is not correct, and this incorrect velocity must be replicated, // As result the animation velocity calculation is not correct, and this incorrect velocity must be replicated,
// because otherwise the Creature's Speed (dagoth uthol) would not be sufficient to move fast enough. // because otherwise the Creature's Speed (dagoth uthol) would not be sufficient to move fast enough.
NifOsg::TextKeyMap::const_reverse_iterator keyiter(keys.rbegin()); auto keyiter = keys.rbegin();
while(keyiter != keys.rend()) while(keyiter != keys.rend())
{ {
if(keyiter->second == start || keyiter->second == loopstart) if(keyiter->second == start || keyiter->second == loopstart)
@ -553,7 +541,7 @@ namespace MWRender
ControllerMap mControllerMap[Animation::sNumBlendMasks]; ControllerMap mControllerMap[Animation::sNumBlendMasks];
const std::multimap<float, std::string>& getTextKeys() const; const NifOsg::TextKeyMap& getTextKeys() const;
}; };
void UpdateVfxCallback::operator()(osg::Node* node, osg::NodeVisitor* nv) void UpdateVfxCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
@ -702,7 +690,7 @@ namespace MWRender
return 0; return 0;
} }
const std::multimap<float, std::string> &Animation::AnimSource::getTextKeys() const const NifOsg::TextKeyMap &Animation::AnimSource::getTextKeys() const
{ {
return mKeyframes->mTextKeys; return mKeyframes->mTextKeys;
} }
@ -825,7 +813,7 @@ namespace MWRender
for(;iter != mAnimSources.end();++iter) for(;iter != mAnimSources.end();++iter)
{ {
const NifOsg::TextKeyMap &keys = (*iter)->getTextKeys(); const NifOsg::TextKeyMap &keys = (*iter)->getTextKeys();
if(findGroupStart(keys, anim) != keys.end()) if (keys.hasGroupStart(anim))
return true; return true;
} }
@ -838,7 +826,7 @@ namespace MWRender
{ {
const NifOsg::TextKeyMap &keys = (*iter)->getTextKeys(); const NifOsg::TextKeyMap &keys = (*iter)->getTextKeys();
NifOsg::TextKeyMap::const_iterator found = findGroupStart(keys, groupname); const auto found = keys.findGroupStart(groupname);
if(found != keys.end()) if(found != keys.end())
return found->first; return found->first;
} }
@ -851,7 +839,7 @@ namespace MWRender
{ {
const NifOsg::TextKeyMap &keys = (*iter)->getTextKeys(); const NifOsg::TextKeyMap &keys = (*iter)->getTextKeys();
for(NifOsg::TextKeyMap::const_iterator iterKey(keys.begin()); iterKey != keys.end(); ++iterKey) for(auto iterKey = keys.begin(); iterKey != keys.end(); ++iterKey)
{ {
if(iterKey->second.compare(0, textKey.size(), textKey) == 0) if(iterKey->second.compare(0, textKey.size(), textKey) == 0)
return iterKey->first; return iterKey->first;
@ -861,8 +849,8 @@ namespace MWRender
return -1.f; return -1.f;
} }
void Animation::handleTextKey(AnimState &state, const std::string &groupname, const std::multimap<float, std::string>::const_iterator &key, void Animation::handleTextKey(AnimState &state, const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key,
const std::multimap<float, std::string>& map) const NifOsg::TextKeyMap& map)
{ {
const std::string &evt = key->second; const std::string &evt = key->second;
@ -939,7 +927,7 @@ namespace MWRender
if (state.mPlaying) if (state.mPlaying)
{ {
NifOsg::TextKeyMap::const_iterator textkey(textkeys.lower_bound(state.getTime())); auto textkey = textkeys.lowerBound(state.getTime());
while(textkey != textkeys.end() && textkey->first <= state.getTime()) while(textkey != textkeys.end() && textkey->first <= state.getTime())
{ {
handleTextKey(state, groupname, textkey, textkeys); handleTextKey(state, groupname, textkey, textkeys);
@ -955,7 +943,7 @@ namespace MWRender
if(state.getTime() >= state.mLoopStopTime) if(state.getTime() >= state.mLoopStopTime)
break; break;
NifOsg::TextKeyMap::const_iterator textkey(textkeys.lower_bound(state.getTime())); auto textkey = textkeys.lowerBound(state.getTime());
while(textkey != textkeys.end() && textkey->first <= state.getTime()) while(textkey != textkeys.end() && textkey->first <= state.getTime())
{ {
handleTextKey(state, groupname, textkey, textkeys); handleTextKey(state, groupname, textkey, textkeys);
@ -974,7 +962,7 @@ namespace MWRender
{ {
// Look for text keys in reverse. This normally wouldn't matter, but for some reason undeadwolf_2.nif has two // Look for text keys in reverse. This normally wouldn't matter, but for some reason undeadwolf_2.nif has two
// separate walkforward keys, and the last one is supposed to be used. // separate walkforward keys, and the last one is supposed to be used.
NifOsg::TextKeyMap::const_reverse_iterator groupend(keys.rbegin()); auto groupend = keys.rbegin();
for(;groupend != keys.rend();++groupend) for(;groupend != keys.rend();++groupend)
{ {
if(groupend->second.compare(0, groupname.size(), groupname) == 0 && if(groupend->second.compare(0, groupname.size(), groupname) == 0 &&
@ -983,7 +971,7 @@ namespace MWRender
} }
std::string starttag = groupname+": "+start; std::string starttag = groupname+": "+start;
NifOsg::TextKeyMap::const_reverse_iterator startkey(groupend); auto startkey = groupend;
while(startkey != keys.rend() && startkey->second != starttag) while(startkey != keys.rend() && startkey->second != starttag)
++startkey; ++startkey;
if(startkey == keys.rend() && start == "loop start") if(startkey == keys.rend() && start == "loop start")
@ -997,7 +985,7 @@ namespace MWRender
return false; return false;
const std::string stoptag = groupname+": "+stop; const std::string stoptag = groupname+": "+stop;
NifOsg::TextKeyMap::const_reverse_iterator stopkey(groupend); auto stopkey = groupend;
while(stopkey != keys.rend() while(stopkey != keys.rend()
// We have to ignore extra garbage at the end. // We have to ignore extra garbage at the end.
// The Scrib's idle3 animation has "Idle3: Stop." instead of "Idle3: Stop". // The Scrib's idle3 animation has "Idle3: Stop." instead of "Idle3: Stop".
@ -1030,7 +1018,7 @@ namespace MWRender
const std::string loopstarttag = groupname+": loop start"; const std::string loopstarttag = groupname+": loop start";
const std::string loopstoptag = groupname+": loop stop"; const std::string loopstoptag = groupname+": loop stop";
NifOsg::TextKeyMap::const_reverse_iterator key(groupend); auto key = groupend;
for (; key != startkey && key != keys.rend(); ++key) for (; key != startkey && key != keys.rend(); ++key)
{ {
if (key->first > state.getTime()) if (key->first > state.getTime())
@ -1201,7 +1189,7 @@ namespace MWRender
for(;animsrc != mAnimSources.rend();++animsrc) for(;animsrc != mAnimSources.rend();++animsrc)
{ {
const NifOsg::TextKeyMap &keys = (*animsrc)->getTextKeys(); const NifOsg::TextKeyMap &keys = (*animsrc)->getTextKeys();
if(findGroupStart(keys, groupname) != keys.end()) if (keys.hasGroupStart(groupname))
break; break;
} }
if(animsrc == mAnimSources.rend()) if(animsrc == mAnimSources.rend())
@ -1280,7 +1268,7 @@ namespace MWRender
} }
const NifOsg::TextKeyMap &textkeys = state.mSource->getTextKeys(); const NifOsg::TextKeyMap &textkeys = state.mSource->getTextKeys();
NifOsg::TextKeyMap::const_iterator textkey(textkeys.upper_bound(state.getTime())); auto textkey = textkeys.upperBound(state.getTime());
float timepassed = duration * state.mSpeedMult; float timepassed = duration * state.mSpeedMult;
while(state.mPlaying) while(state.mPlaying)
@ -1316,7 +1304,7 @@ namespace MWRender
state.setTime(state.mLoopStartTime); state.setTime(state.mLoopStartTime);
state.mPlaying = true; state.mPlaying = true;
textkey = textkeys.lower_bound(state.getTime()); textkey = textkeys.lowerBound(state.getTime());
while(textkey != textkeys.end() && textkey->first <= state.getTime()) while(textkey != textkeys.end() && textkey->first <= state.getTime())
{ {
handleTextKey(state, stateiter->first, textkey, textkeys); handleTextKey(state, stateiter->first, textkey, textkeys);

View file

@ -5,6 +5,7 @@
#include <components/sceneutil/controller.hpp> #include <components/sceneutil/controller.hpp>
#include <components/sceneutil/util.hpp> #include <components/sceneutil/util.hpp>
#include <components/nifosg/textkeymap.hpp>
#include <vector> #include <vector>
@ -149,8 +150,8 @@ public:
class TextKeyListener class TextKeyListener
{ {
public: public:
virtual void handleTextKey(const std::string &groupname, const std::multimap<float, std::string>::const_iterator &key, virtual void handleTextKey(const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key,
const std::multimap<float, std::string>& map) = 0; const NifOsg::TextKeyMap& map) = 0;
virtual ~TextKeyListener() = default; virtual ~TextKeyListener() = default;
}; };
@ -297,12 +298,12 @@ protected:
* the marker is not found, or if the markers are the same, it returns * the marker is not found, or if the markers are the same, it returns
* false. * false.
*/ */
bool reset(AnimState &state, const std::multimap<float, std::string> &keys, bool reset(AnimState &state, const NifOsg::TextKeyMap &keys,
const std::string &groupname, const std::string &start, const std::string &stop, const std::string &groupname, const std::string &start, const std::string &stop,
float startpoint, bool loopfallback); float startpoint, bool loopfallback);
void handleTextKey(AnimState &state, const std::string &groupname, const std::multimap<float, std::string>::const_iterator &key, void handleTextKey(AnimState &state, const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key,
const std::multimap<float, std::string>& map); const NifOsg::TextKeyMap& map);
/** Sets the root model of the object. /** Sets the root model of the object.
* *

View file

@ -157,7 +157,8 @@ namespace
nextpos = std::distance(str.begin(), ++last); nextpos = std::distance(str.begin(), ++last);
} }
std::string result = str.substr(pos, nextpos-pos); std::string result = str.substr(pos, nextpos-pos);
textkeys.insert(std::make_pair(tk->list[i].time, Misc::StringUtils::lowerCase(result))); Misc::StringUtils::lowerCaseInPlace(result);
textkeys.emplace(tk->list[i].time, std::move(result));
pos = nextpos; pos = nextpos;
} }

View file

@ -7,6 +7,7 @@
#include <osg/Referenced> #include <osg/Referenced>
#include "controller.hpp" #include "controller.hpp"
#include "textkeymap.hpp"
namespace osg namespace osg
{ {
@ -20,8 +21,6 @@ namespace Resource
namespace NifOsg namespace NifOsg
{ {
typedef std::multimap<float,std::string> TextKeyMap;
struct TextKeyMapHolder : public osg::Object struct TextKeyMapHolder : public osg::Object
{ {
public: public:

View file

@ -0,0 +1,87 @@
#ifndef OPENMW_COMPONENTS_NIFOSG_TEXTKEYMAP
#define OPENMW_COMPONENTS_NIFOSG_TEXTKEYMAP
#include <algorithm>
#include <map>
#include <set>
#include <string>
namespace NifOsg
{
class TextKeyMap
{
public:
using ConstIterator = std::multimap<float, std::string>::const_iterator;
auto begin() const noexcept
{
return mTextKeyByTime.begin();
}
auto end() const noexcept
{
return mTextKeyByTime.end();
}
auto rbegin() const noexcept
{
return mTextKeyByTime.rbegin();
}
auto rend() const noexcept
{
return mTextKeyByTime.rend();
}
auto lowerBound(float time) const
{
return mTextKeyByTime.lower_bound(time);
}
auto upperBound(float time) const
{
return mTextKeyByTime.upper_bound(time);
}
void emplace(float time, std::string&& textKey)
{
const auto separator = textKey.find(": ");
if (separator != std::string::npos)
mGroups.emplace(textKey.substr(0, separator));
mTextKeyByTime.emplace(time, std::move(textKey));
}
bool empty() const noexcept
{
return mTextKeyByTime.empty();
}
auto findGroupStart(const std::string &groupName) const
{
return std::find_if(mTextKeyByTime.begin(), mTextKeyByTime.end(), IsGroupStart{groupName});
}
bool hasGroupStart(const std::string &groupName) const
{
return mGroups.count(groupName) > 0;
}
private:
struct IsGroupStart
{
const std::string &mGroupName;
bool operator ()(const std::multimap<float, std::string>::value_type& value) const
{
return value.second.compare(0, mGroupName.size(), mGroupName) == 0 &&
value.second.compare(mGroupName.size(), 2, ": ") == 0;
}
};
std::set<std::string> mGroups;
std::multimap<float, std::string> mTextKeyByTime;
};
}
#endif