From 617158afcd43efc533fb49e07e736df60fcf6696 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 20 Feb 2013 02:32:48 -0800 Subject: [PATCH] Ensure updated skeleton bone placement matches in world space Objects attached to actors (shirts, robes, etc) do not require the same node hierarchy as the character root. So to ensure proper placement, we need to set the bone target's derived transformation using the source bone's derived transformation (which in turn means we need to work up from the root, to ensure the bone's parents are properly placed). --- apps/openmw/mwrender/animation.cpp | 42 +++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 3300454231..f4b618866a 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -197,19 +197,41 @@ void Animation::applyAnimation(const Ogre::Animation *anim, float time, Ogre::Sk mEntityList.mSkelBase->getAllAnimationStates()->_notifyDirty(); } +static void updateBoneTree(const Ogre::SkeletonInstance *skelsrc, Ogre::Bone *bone) +{ + if(skelsrc->hasBone(bone->getName())) + { + Ogre::Bone *srcbone = skelsrc->getBone(bone->getName()); + if(!srcbone->getParent() || !bone->getParent()) + { + bone->setOrientation(srcbone->getOrientation()); + bone->setPosition(srcbone->getPosition()); + bone->setScale(srcbone->getScale()); + } + else + { + bone->_setDerivedOrientation(srcbone->_getDerivedOrientation()); + bone->_setDerivedPosition(srcbone->_getDerivedPosition()); + bone->setScale(Ogre::Vector3::UNIT_SCALE); + } + } + else + { + // No matching bone in the source. Make sure it stays properly offset + // from its parent. + bone->resetToInitialState(); + } + + Ogre::Node::ChildNodeIterator boneiter = bone->getChildIterator(); + while(boneiter.hasMoreElements()) + updateBoneTree(skelsrc, static_cast(boneiter.getNext())); +} + void Animation::updateSkeletonInstance(const Ogre::SkeletonInstance *skelsrc, Ogre::SkeletonInstance *skel) { - Ogre::Skeleton::BoneIterator boneiter = skel->getBoneIterator(); + Ogre::Skeleton::BoneIterator boneiter = skel->getRootBoneIterator(); while(boneiter.hasMoreElements()) - { - Ogre::Bone *bone = boneiter.getNext(); - if(!skelsrc->hasBone(bone->getName())) - continue; - Ogre::Bone *srcbone = skelsrc->getBone(bone->getName()); - bone->setOrientation(srcbone->getOrientation()); - bone->setPosition(srcbone->getPosition()); - bone->setScale(srcbone->getScale()); - } + updateBoneTree(skelsrc, boneiter.getNext()); }