1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-04-01 20:36:42 +00:00

Only get the non-accum root's keyframe when updating positions

The actual animation pose is now handled by the controllers, based on the
current animation time.
This commit is contained in:
Chris Robinson 2013-04-07 16:21:45 -07:00
parent 3c633e275e
commit 7baca30a1d
2 changed files with 40 additions and 49 deletions

View file

@ -263,28 +263,6 @@ void Animation::calcAnimVelocity()
} }
} }
void Animation::applyAnimation(const Ogre::Animation *anim, float time, Ogre::SkeletonInstance *skel)
{
Ogre::TimeIndex timeindex = anim->_getTimeIndex(time);
Ogre::Animation::NodeTrackIterator tracks = anim->getNodeTrackIterator();
while(tracks.hasMoreElements())
{
Ogre::NodeAnimationTrack *track = tracks.getNext();
const Ogre::String &targetname = track->getAssociatedNode()->getName();
if(!skel->hasBone(targetname))
continue;
Ogre::Bone *bone = skel->getBone(targetname);
bone->setOrientation(Ogre::Quaternion::IDENTITY);
bone->setPosition(Ogre::Vector3::ZERO);
bone->setScale(Ogre::Vector3::UNIT_SCALE);
track->applyToNode(bone, timeindex);
}
// HACK: Dirty the animation state set so that Ogre will apply the
// transformations to entities this skeleton instance is shared with.
mObjectList.mSkelBase->getAllAnimationStates()->_notifyDirty();
}
static void updateBoneTree(const Ogre::SkeletonInstance *skelsrc, Ogre::Bone *bone) static void updateBoneTree(const Ogre::SkeletonInstance *skelsrc, Ogre::Bone *bone)
{ {
if(skelsrc->hasBone(bone->getName())) if(skelsrc->hasBone(bone->getName()))
@ -323,24 +301,29 @@ void Animation::updateSkeletonInstance(const Ogre::SkeletonInstance *skelsrc, Og
} }
Ogre::Vector3 Animation::updatePosition(float time) Ogre::Vector3 Animation::updatePosition()
{ {
if(mLooping) Ogre::Vector3 posdiff;
mCurrentTime = std::fmod(std::max(time, 0.0f), mCurrentAnim->getLength());
else
mCurrentTime = std::min(mCurrentAnim->getLength(), std::max(time, 0.0f));
applyAnimation(mCurrentAnim, mCurrentTime, mObjectList.mSkelBase->getSkeleton());
Ogre::Vector3 posdiff = Ogre::Vector3::ZERO; Ogre::TransformKeyFrame kf(0, mCurrentTime);
if(mNonAccumRoot) Ogre::Animation::NodeTrackIterator trackiter = mCurrentAnim->getNodeTrackIterator();
while(trackiter.hasMoreElements())
{ {
/* Get the non-accumulation root's difference from the last update. */ const Ogre::NodeAnimationTrack *track = trackiter.getNext();
posdiff = (mNonAccumRoot->getPosition() - mLastPosition) * mAccumulate; if(track->getAssociatedNode()->getName() == mNonAccumRoot->getName())
{
/* Translate the accumulation root back to compensate for the move. */ track->getInterpolatedKeyFrame(mCurrentAnim->_getTimeIndex(mCurrentTime), &kf);
mLastPosition += posdiff; break;
mAccumRoot->setPosition(-mLastPosition); }
} }
/* Get the non-accumulation root's difference from the last update. */
posdiff = (kf.getTranslate() - mLastPosition) * mAccumulate;
/* Translate the accumulation root back to compensate for the move. */
mLastPosition += posdiff;
mAccumRoot->setPosition(-mLastPosition);
return posdiff; return posdiff;
} }
@ -486,11 +469,14 @@ Ogre::Vector3 Animation::runAnimation(float timepassed)
timepassed *= mAnimSpeedMult; timepassed *= mAnimSpeedMult;
while(mCurrentAnim && mPlaying) while(mCurrentAnim && mPlaying)
{ {
float targetTime = std::min(mStopTime, mCurrentTime+timepassed); float targetTime = mCurrentTime + timepassed;
if(mNextKey == mCurrentKeys->end() || mNextKey->first > targetTime) if(mNextKey == mCurrentKeys->end() || mNextKey->first > targetTime)
{ {
movement += updatePosition(targetTime); mCurrentTime = std::min(mStopTime, targetTime);
mPlaying = (mLooping || mStopTime > targetTime); if(mNonAccumRoot)
movement += updatePosition();
mPlaying = (mLooping || mStopTime > mCurrentTime);
timepassed = targetTime - mCurrentTime;
break; break;
} }
@ -498,10 +484,11 @@ Ogre::Vector3 Animation::runAnimation(float timepassed)
const std::string &evt = mNextKey->second; const std::string &evt = mNextKey->second;
mNextKey++; mNextKey++;
movement += updatePosition(time); mCurrentTime = time;
mPlaying = (mLooping || mStopTime > time); if(mNonAccumRoot)
movement += updatePosition();
timepassed = targetTime - time; mPlaying = (mLooping || mStopTime > mCurrentTime);
timepassed = targetTime - mCurrentTime;
if(!handleEvent(time, evt)) if(!handleEvent(time, evt))
break; break;
@ -509,6 +496,13 @@ Ogre::Vector3 Animation::runAnimation(float timepassed)
for(size_t i = 0;i < mCurrentControllers->size();i++) for(size_t i = 0;i < mCurrentControllers->size();i++)
(*mCurrentControllers)[i].update(); (*mCurrentControllers)[i].update();
if(mObjectList.mSkelBase)
{
// HACK: Dirty the animation state set so that Ogre will apply the
// transformations to entities this skeleton instance is shared with.
mObjectList.mSkelBase->getAllAnimationStates()->_notifyDirty();
}
return movement; return movement;
} }

View file

@ -63,16 +63,13 @@ protected:
void calcAnimVelocity(); void calcAnimVelocity();
/* Applies the given animation to the given skeleton instance, using the specified time. */
void applyAnimation(const Ogre::Animation *anim, float time, Ogre::SkeletonInstance *skel);
/* Updates a skeleton instance so that all bones matching the source skeleton (based on /* Updates a skeleton instance so that all bones matching the source skeleton (based on
* bone names) are positioned identically. */ * bone names) are positioned identically. */
void updateSkeletonInstance(const Ogre::SkeletonInstance *skelsrc, Ogre::SkeletonInstance *skel); void updateSkeletonInstance(const Ogre::SkeletonInstance *skelsrc, Ogre::SkeletonInstance *skel);
/* Updates the animation to the specified time, and returns the movement /* Updates the position of the accum root node for the current time, and
* vector since the last update or reset. */ * returns the wanted movement vector from the previous update. */
Ogre::Vector3 updatePosition(float time); Ogre::Vector3 updatePosition();
/* Resets the animation to the time of the specified start marker, without /* Resets the animation to the time of the specified start marker, without
* moving anything, and set the end time to the specified stop marker. If * moving anything, and set the end time to the specified stop marker. If