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:
parent
3c633e275e
commit
7baca30a1d
2 changed files with 40 additions and 49 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue