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:
commit
357a845d00
7 changed files with 117 additions and 42 deletions
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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.
|
||||||
*
|
*
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
87
components/nifosg/textkeymap.hpp
Normal file
87
components/nifosg/textkeymap.hpp
Normal 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
|
Loading…
Reference in a new issue