From ff0099fa6e89c97f5f269d2f25adc66a5540edfc Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 15 Feb 2013 02:15:39 -0800 Subject: [PATCH] Scale the animation speed based on the animation velocity and movement speed This may not be totoally correct since it takes the whole animation into account, rather than just the looping portion. But it's good enough for now. --- apps/openmw/mwmechanics/character.cpp | 5 ++-- apps/openmw/mwrender/animation.cpp | 33 +++++++++++++++++++++++++++ apps/openmw/mwrender/animation.hpp | 4 ++-- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index b6e96bdf5e..c40fac40aa 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -172,6 +172,7 @@ Ogre::Vector3 CharacterController::update(float duration) { const MWWorld::Class &cls = MWWorld::Class::get(mPtr); const Ogre::Vector3 &vec = cls.getMovementVector(mPtr); + const float speed = cls.getSpeed(mPtr); bool inwater = MWBase::Environment::get().getWorld()->isSwimming(mPtr); bool isrunning = cls.getStance(mPtr, MWWorld::Class::Run); @@ -204,9 +205,7 @@ Ogre::Vector3 CharacterController::update(float duration) Ogre::Vector3 movement = Ogre::Vector3::ZERO; if(mAnimation && !mSkipAnim) { - // FIXME: The speed should actually be determined by the character's - // stance (running, sneaking, etc) and stats - mAnimation->setSpeedMult(1.0f); + mAnimation->setSpeed(speed); movement += mAnimation->runAnimation(duration); } mSkipAnim = false; diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 9d9631ecea..1a606992a2 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -28,6 +28,7 @@ Animation::Animation(const MWWorld::Ptr &ptr) , mCurrentTime(0.0f) , mPlaying(false) , mLooping(false) + , mAnimVelocity(0.0f) , mAnimSpeedMult(1.0f) { } @@ -161,6 +162,13 @@ void Animation::setAccumulation(const Ogre::Vector3 &accum) mAccumulate = accum; } +void Animation::setSpeed(float speed) +{ + mAnimSpeedMult = 1.0f; + if(mAnimVelocity > 1.0f && speed > 0.0f) + mAnimSpeedMult = speed / mAnimVelocity; +} + void Animation::applyAnimation(const Ogre::Animation *anim, float time, Ogre::SkeletonInstance *skel) { @@ -255,6 +263,31 @@ void Animation::play(const std::string &groupname, const std::string &start, boo { mCurrentAnim = (*iter)->getAnimation(groupname); mCurrentKeys = &mTextKeys[groupname]; + mAnimVelocity = 0.0f; + + if(mNonAccumRoot) + { + const Ogre::NodeAnimationTrack *track = 0; + + Ogre::Animation::NodeTrackIterator trackiter = mCurrentAnim->getNodeTrackIterator(); + while(!track && trackiter.hasMoreElements()) + { + const Ogre::NodeAnimationTrack *cur = trackiter.getNext(); + if(cur->getAssociatedNode()->getName() == mNonAccumRoot->getName()) + track = cur; + } + + if(track && track->getNumKeyFrames() > 1) + { + const Ogre::TransformKeyFrame *startkf, *endkf; + startkf = static_cast(track->getKeyFrame(0)); + endkf = static_cast(track->getKeyFrame(track->getNumKeyFrames() - 1)); + + mAnimVelocity = startkf->getTranslate().distance(endkf->getTranslate()) / + mCurrentAnim->getLength(); + } + } + found = true; break; } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index ee73193bf5..fc35c06be6 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -36,6 +36,7 @@ protected: bool mPlaying; bool mLooping; + float mAnimVelocity; float mAnimSpeedMult; /* Applies the given animation to the given skeleton instance, using the specified time. */ @@ -73,8 +74,7 @@ public: // should be on the scale of 0 to 1. void setAccumulation(const Ogre::Vector3 &accum); - void setSpeedMult(float speedmult) - { mAnimSpeedMult = speedmult; } + void setSpeed(float speed); void play(const std::string &groupname, const std::string &start, bool loop); virtual Ogre::Vector3 runAnimation(float timepassed);