1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-27 03:35:27 +00:00

Eliminate string lookups in AnimationTime

This commit is contained in:
scrawl 2015-05-14 16:33:41 +02:00
parent b6cb73e6e8
commit 4ad0b83aa5
2 changed files with 53 additions and 46 deletions

View File

@ -326,7 +326,7 @@ namespace MWRender
mStates.clear(); mStates.clear();
for(size_t i = 0;i < sNumGroups;i++) for(size_t i = 0;i < sNumGroups;i++)
mAnimationTimePtr[i]->setAnimName(std::string()); mAnimationTimePtr[i]->setTimePtr(boost::shared_ptr<float>());
mAccumCtrl = NULL; mAccumCtrl = NULL;
@ -433,32 +433,32 @@ namespace MWRender
state.mSource = *iter; state.mSource = *iter;
state.mSpeedMult = speedmult; state.mSpeedMult = speedmult;
state.mLoopCount = loops; state.mLoopCount = loops;
state.mPlaying = (state.mTime < state.mStopTime); state.mPlaying = (state.getTime() < state.mStopTime);
state.mPriority = priority; state.mPriority = priority;
state.mGroups = groups; state.mGroups = groups;
state.mAutoDisable = autodisable; state.mAutoDisable = autodisable;
mStates[groupname] = state; mStates[groupname] = state;
NifOsg::TextKeyMap::const_iterator textkey(textkeys.lower_bound(state.mTime)); NifOsg::TextKeyMap::const_iterator textkey(textkeys.lower_bound(state.getTime()));
if (state.mPlaying) if (state.mPlaying)
{ {
while(textkey != textkeys.end() && textkey->first <= state.mTime) while(textkey != textkeys.end() && textkey->first <= state.getTime())
{ {
handleTextKey(state, groupname, textkey, textkeys); handleTextKey(state, groupname, textkey, textkeys);
++textkey; ++textkey;
} }
} }
if(state.mTime >= state.mLoopStopTime && state.mLoopCount > 0) if(state.getTime() >= state.mLoopStopTime && state.mLoopCount > 0)
{ {
state.mLoopCount--; state.mLoopCount--;
state.mTime = state.mLoopStartTime; state.setTime(state.mLoopStartTime);
state.mPlaying = true; state.mPlaying = true;
if(state.mTime >= state.mLoopStopTime) if(state.getTime() >= state.mLoopStopTime)
break; break;
NifOsg::TextKeyMap::const_iterator textkey(textkeys.lower_bound(state.mTime)); NifOsg::TextKeyMap::const_iterator textkey(textkeys.lower_bound(state.getTime()));
while(textkey != textkeys.end() && textkey->first <= state.mTime) while(textkey != textkeys.end() && textkey->first <= state.getTime())
{ {
handleTextKey(state, groupname, textkey, textkeys); handleTextKey(state, groupname, textkey, textkeys);
++textkey; ++textkey;
@ -527,11 +527,11 @@ namespace MWRender
} }
state.mStopTime = stopkey->first; state.mStopTime = stopkey->first;
state.mTime = state.mStartTime + ((state.mStopTime - state.mStartTime) * startpoint); state.setTime(state.mStartTime + ((state.mStopTime - state.mStartTime) * startpoint));
// mLoopStartTime and mLoopStopTime normally get assigned when encountering these keys while playing the animation // mLoopStartTime and mLoopStopTime normally get assigned when encountering these keys while playing the animation
// (see handleTextKey). But if startpoint is already past these keys, we need to assign them now. // (see handleTextKey). But if startpoint is already past these keys, we need to assign them now.
if(state.mTime > state.mStartTime) if(state.getTime() > state.mStartTime)
{ {
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";
@ -539,7 +539,7 @@ namespace MWRender
NifOsg::TextKeyMap::const_reverse_iterator key(groupend); NifOsg::TextKeyMap::const_reverse_iterator key(groupend);
for (; key != startkey && key != keys.rend(); ++key) for (; key != startkey && key != keys.rend(); ++key)
{ {
if (key->first > state.mTime) if (key->first > state.getTime())
continue; continue;
if (key->second == loopstarttag) if (key->second == loopstarttag)
@ -587,8 +587,7 @@ namespace MWRender
active = state; active = state;
} }
mAnimationTimePtr[grp]->setAnimName((active == mStates.end()) ? mAnimationTimePtr[grp]->setTimePtr(active == mStates.end() ? boost::shared_ptr<float>() : active->second.mTime);
std::string() : active->first);
// add external controllers for the AnimSource active in this group // add external controllers for the AnimSource active in this group
if (active != mStates.end()) if (active != mStates.end())
@ -671,7 +670,7 @@ namespace MWRender
if(complete) if(complete)
{ {
if(iter->second.mStopTime > iter->second.mStartTime) if(iter->second.mStopTime > iter->second.mStartTime)
*complete = (iter->second.mTime - iter->second.mStartTime) / *complete = (iter->second.getTime() - iter->second.mStartTime) /
(iter->second.mStopTime - iter->second.mStartTime); (iter->second.mStopTime - iter->second.mStartTime);
else else
*complete = (iter->second.mPlaying ? 0.0f : 1.0f); *complete = (iter->second.mPlaying ? 0.0f : 1.0f);
@ -686,7 +685,7 @@ namespace MWRender
if(iter == mStates.end()) if(iter == mStates.end())
return -1.f; return -1.f;
return iter->second.mTime; return iter->second.getTime();
} }
void Animation::disable(const std::string &groupname) void Animation::disable(const std::string &groupname)
@ -767,54 +766,54 @@ namespace MWRender
{ {
AnimState &state = stateiter->second; AnimState &state = stateiter->second;
const NifOsg::TextKeyMap &textkeys = state.mSource->getTextKeys(); const NifOsg::TextKeyMap &textkeys = state.mSource->getTextKeys();
NifOsg::TextKeyMap::const_iterator textkey(textkeys.upper_bound(state.mTime)); NifOsg::TextKeyMap::const_iterator textkey(textkeys.upper_bound(state.getTime()));
float timepassed = duration * state.mSpeedMult; float timepassed = duration * state.mSpeedMult;
while(state.mPlaying) while(state.mPlaying)
{ {
float targetTime; float targetTime;
if(state.mTime >= state.mLoopStopTime && state.mLoopCount > 0) if(state.getTime() >= state.mLoopStopTime && state.mLoopCount > 0)
goto handle_loop; goto handle_loop;
targetTime = state.mTime + timepassed; targetTime = state.getTime() + timepassed;
if(textkey == textkeys.end() || textkey->first > targetTime) if(textkey == textkeys.end() || textkey->first > targetTime)
{ {
if(mAccumCtrl && stateiter->first == mAnimationTimePtr[0]->getAnimName()) if(mAccumCtrl && state.mTime == mAnimationTimePtr[0]->getTimePtr())
updatePosition(state.mTime, targetTime, movement); updatePosition(state.getTime(), targetTime, movement);
state.mTime = std::min(targetTime, state.mStopTime); state.setTime(std::min(targetTime, state.mStopTime));
} }
else else
{ {
if(mAccumCtrl && stateiter->first == mAnimationTimePtr[0]->getAnimName()) if(mAccumCtrl && state.mTime == mAnimationTimePtr[0]->getTimePtr())
updatePosition(state.mTime, textkey->first, movement); updatePosition(state.getTime(), textkey->first, movement);
state.mTime = textkey->first; state.setTime(textkey->first);
} }
state.mPlaying = (state.mTime < state.mStopTime); state.mPlaying = (state.getTime() < state.mStopTime);
timepassed = targetTime - state.mTime; timepassed = targetTime - state.getTime();
while(textkey != textkeys.end() && textkey->first <= state.mTime) while(textkey != textkeys.end() && textkey->first <= state.getTime())
{ {
handleTextKey(state, stateiter->first, textkey, textkeys); handleTextKey(state, stateiter->first, textkey, textkeys);
++textkey; ++textkey;
} }
if(state.mTime >= state.mLoopStopTime && state.mLoopCount > 0) if(state.getTime() >= state.mLoopStopTime && state.mLoopCount > 0)
{ {
handle_loop: handle_loop:
state.mLoopCount--; state.mLoopCount--;
state.mTime = state.mLoopStartTime; state.setTime(state.mLoopStartTime);
state.mPlaying = true; state.mPlaying = true;
textkey = textkeys.lower_bound(state.mTime); textkey = textkeys.lower_bound(state.getTime());
while(textkey != textkeys.end() && textkey->first <= state.mTime) while(textkey != textkeys.end() && textkey->first <= state.getTime())
{ {
handleTextKey(state, stateiter->first, textkey, textkeys); handleTextKey(state, stateiter->first, textkey, textkeys);
++textkey; ++textkey;
} }
if(state.mTime >= state.mLoopStopTime) if(state.getTime() >= state.mLoopStopTime)
break; break;
} }
@ -1090,11 +1089,9 @@ namespace MWRender
float Animation::AnimationTime::getValue(osg::NodeVisitor*) float Animation::AnimationTime::getValue(osg::NodeVisitor*)
{ {
// FIXME: hold a pointer instead of searching every frame if (mTimePtr)
AnimStateMap::const_iterator iter = mAnimation->mStates.find(mAnimationName); return *mTimePtr;
if(iter != mAnimation->mStates.end()) return 0.f;
return iter->second.mTime;
return 0.0f;
} }
float EffectAnimationTime::getValue(osg::NodeVisitor*) float EffectAnimationTime::getValue(osg::NodeVisitor*)

View File

@ -62,17 +62,17 @@ protected:
{ {
private: private:
Animation *mAnimation; Animation *mAnimation;
std::string mAnimationName; boost::shared_ptr<float> mTimePtr;
public: public:
AnimationTime(Animation *anim) AnimationTime(Animation *anim)
: mAnimation(anim) : mAnimation(anim)
{ } { }
void setAnimName(const std::string &name) void setTimePtr(boost::shared_ptr<float> time)
{ mAnimationName = name; } { mTimePtr = time; }
const std::string &getAnimName() const boost::shared_ptr<float> getTimePtr() const
{ return mAnimationName; } { return mTimePtr; }
virtual float getValue(osg::NodeVisitor* nv); virtual float getValue(osg::NodeVisitor* nv);
}; };
@ -104,7 +104,8 @@ protected:
float mLoopStopTime; float mLoopStopTime;
float mStopTime; float mStopTime;
float mTime; typedef boost::shared_ptr<float> TimePtr;
TimePtr mTime;
float mSpeedMult; float mSpeedMult;
bool mPlaying; bool mPlaying;
@ -115,9 +116,18 @@ protected:
bool mAutoDisable; bool mAutoDisable;
AnimState() : mStartTime(0.0f), mLoopStartTime(0.0f), mLoopStopTime(0.0f), mStopTime(0.0f), AnimState() : mStartTime(0.0f), mLoopStartTime(0.0f), mLoopStopTime(0.0f), mStopTime(0.0f),
mTime(0.0f), mSpeedMult(1.0f), mPlaying(false), mLoopCount(0), mTime(new float), mSpeedMult(1.0f), mPlaying(false), mLoopCount(0),
mPriority(0), mGroups(0), mAutoDisable(true) mPriority(0), mGroups(0), mAutoDisable(true)
{ } {
}
float getTime() const
{
return *mTime;
}
void setTime(float time)
{
*mTime = time;
}
}; };
typedef std::map<std::string,AnimState> AnimStateMap; typedef std::map<std::string,AnimState> AnimStateMap;
AnimStateMap mStates; AnimStateMap mStates;