From b1ffdf855fbab4df838a86e3f310c876261dc000 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 26 Jan 2013 04:48:53 -0800 Subject: [PATCH] Reset the initial state of animated nodes on the skeleton instances This is so the animation specifies node keyframe data based on the node's parent. This will also be necessary for applying animations from different skeleton sources, as they can have different binding positions (even native .skeleton resources will need to specify animation data this way). --- apps/openmw/mwrender/animation.cpp | 22 +++++++++++++++++++++- components/nifogre/ogre_nif_loader.cpp | 15 ++++++--------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 5a5761faa..a36155dbe 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -78,7 +78,7 @@ void Animation::createEntityList(Ogre::SceneNode *node, const std::string &model mAccumRoot->setManuallyControlled(true); mNonAccumRoot = skelinst->getBone(bone->getHandle()); - mStartPosition = mNonAccumRoot->getPosition(); + mStartPosition = mNonAccumRoot->getInitialPosition(); mLastPosition = mStartPosition; asiter = aset->getAnimationStateIterator(); @@ -93,6 +93,26 @@ void Animation::createEntityList(Ogre::SceneNode *node, const std::string &model break; } + + // Reset initial state of bones that are animated, so the animation correctly applies. + if(skelinst->getNumAnimations() > 0) + { + Ogre::Animation *anim = skelinst->getAnimation(0); + Ogre::Animation::NodeTrackIterator trackiter = anim->getNodeTrackIterator(); + while(trackiter.hasMoreElements()) + { + const Ogre::Node *srcnode = trackiter.getNext()->getAssociatedNode(); + const Ogre::Node *srcbone = dynamic_cast(srcnode); + if(!srcbone || !skelinst->hasBone(srcbone->getName())) + continue; + + Ogre::Bone *bone = skelinst->getBone(srcbone->getName()); + bone->setOrientation(Ogre::Quaternion::IDENTITY); + bone->setPosition(Ogre::Vector3::ZERO); + bone->setScale(Ogre::Vector3(1.0f)); + bone->setInitialState(); + } + } } } diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index adc05f7e7..ce0fb00fc 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -193,19 +193,16 @@ static void buildAnimation(Ogre::Skeleton *skel, const std::string &name, const Ogre::NodeAnimationTrack *nodetrack = anim->hasNodeTrack(bone->getHandle()) ? anim->getNodeTrack(bone->getHandle()) : anim->createNodeTrack(bone->getHandle(), bone); - const Ogre::Quaternion &startquat = bone->getInitialOrientation(); - const Ogre::Vector3 &starttrans = bone->getInitialPosition(); - const Ogre::Vector3 &startscale = bone->getInitialScale(); Ogre::Quaternion lastquat, curquat; Ogre::Vector3 lasttrans(0.0f), curtrans(0.0f); Ogre::Vector3 lastscale(1.0f), curscale(1.0f); if(quatiter != quatkeys.mKeys.end()) - lastquat = curquat = startquat.Inverse() * quatiter->mValue; + lastquat = curquat = quatiter->mValue; if(traniter != trankeys.mKeys.end()) - lasttrans = curtrans = traniter->mValue - starttrans; + lasttrans = curtrans = traniter->mValue; if(scaleiter != scalekeys.mKeys.end()) - lastscale = curscale = Ogre::Vector3(scaleiter->mValue) / startscale; + lastscale = curscale = Ogre::Vector3(scaleiter->mValue); float begTime = std::max(kfc->timeStart, startTime); float endTime = std::min(kfc->timeStop, stopTime); bool didlast = false; @@ -235,19 +232,19 @@ static void buildAnimation(Ogre::Skeleton *skel, const std::string &name, const { lastquat = curquat; if(++quatiter != quatkeys.mKeys.end()) - curquat = startquat.Inverse() * quatiter->mValue; + curquat = quatiter->mValue; } while(traniter != trankeys.mKeys.end() && curtime >= traniter->mTime) { lasttrans = curtrans; if(++traniter != trankeys.mKeys.end()) - curtrans = traniter->mValue - starttrans; + curtrans = traniter->mValue; } while(scaleiter != scalekeys.mKeys.end() && curtime >= scaleiter->mTime) { lastscale = curscale; if(++scaleiter != scalekeys.mKeys.end()) - curscale = Ogre::Vector3(scaleiter->mValue) / startscale; + curscale = Ogre::Vector3(scaleiter->mValue); } Ogre::TransformKeyFrame *kframe;