From b6354c6282785feba4106a919242c491dcea3380 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 30 Jan 2013 09:29:16 -0800 Subject: [PATCH] Don't share skeleton instances between bounded parts on an NPC However, a skeleton instance will still be shared between entities in an entity list. --- apps/openmw/mwrender/animation.cpp | 15 +++++++++++++++ apps/openmw/mwrender/animation.hpp | 5 +++++ apps/openmw/mwrender/npcanimation.cpp | 26 +++++++++++++++++++++++++- components/nifogre/ogre_nif_loader.cpp | 5 ++--- 4 files changed, 47 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 73780a7f0..b63de2f16 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -146,6 +146,21 @@ void Animation::applyAnimation(const Ogre::Animation *anim, float time, Ogre::Sk mEntityList.mSkelBase->getAllAnimationStates()->_notifyDirty(); } +void Animation::updateSkeletonInstance(const Ogre::SkeletonInstance *skelsrc, Ogre::SkeletonInstance *skel) +{ + Ogre::Skeleton::BoneIterator boneiter = skel->getBoneIterator(); + 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()); + } +} + Ogre::Vector3 Animation::updatePosition(float time) { diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 886d967ab..60e524d28 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -37,8 +37,13 @@ protected: float mAnimSpeedMult; + /* 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 + * bone names) are positioned identically. */ + void updateSkeletonInstance(const Ogre::SkeletonInstance *skelsrc, Ogre::SkeletonInstance *skel); + /* Updates the animation to the specified time, and returns the movement * vector since the last update or reset. */ Ogre::Vector3 updatePosition(float time); diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 432a2f526..03fda8982 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -305,6 +305,21 @@ NifOgre::EntityList NpcAnimation::insertBoundedPart(const std::string &mesh, int parts[i]->setVisibilityFlags(mVisibilityFlags); parts[i]->getUserObjectBindings().setUserAny(Ogre::Any(group)); } + if(entities.mSkelBase) + { + Ogre::AnimationStateSet *aset = entities.mSkelBase->getAllAnimationStates(); + Ogre::AnimationStateIterator asiter = aset->getAnimationStateIterator(); + while(asiter.hasMoreElements()) + { + Ogre::AnimationState *state = asiter.getNext(); + state->setEnabled(false); + state->setLoop(false); + } + Ogre::SkeletonInstance *skelinst = entities.mSkelBase->getSkeleton(); + Ogre::Skeleton::BoneIterator boneiter = skelinst->getBoneIterator(); + while(boneiter.hasMoreElements()) + boneiter.getNext()->setManuallyControlled(true); + } return entities; } @@ -317,7 +332,16 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed) } mTimeToChange += timepassed; - return Animation::runAnimation(timepassed); + Ogre::Vector3 ret = Animation::runAnimation(timepassed); + const Ogre::SkeletonInstance *skelsrc = mEntityList.mSkelBase->getSkeleton(); + for(size_t i = 0;i < sPartListSize;i++) + { + Ogre::Entity *ent = (this->*sPartList[i].ents).mSkelBase; + if(!ent) continue; + updateSkeletonInstance(skelsrc, ent->getSkeleton()); + ent->getAllAnimationStates()->_notifyDirty(); + } + return ret; } void NpcAnimation::removeEntities(NifOgre::EntityList &entities) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index d1bf803f1..5444c803b 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -1228,19 +1228,18 @@ EntityList Loader::createEntities(Ogre::Entity *parent, const std::string &bonen if(entitylist.mSkelBase) { - entitylist.mSkelBase->shareSkeletonInstanceWith(parent); parentNode->attachObject(entitylist.mSkelBase); for(size_t i = 0;i < entitylist.mEntities.size();i++) { Ogre::Entity *entity = entitylist.mEntities[i]; if(entity != entitylist.mSkelBase && entity->hasSkeleton()) { - entity->shareSkeletonInstanceWith(parent); + entity->shareSkeletonInstanceWith(entitylist.mSkelBase); parentNode->attachObject(entity); } else if(entity != entitylist.mSkelBase) { - Ogre::TagPoint *tag = parent->attachObjectToBone(bonename, entity); + Ogre::TagPoint *tag = entitylist.mSkelBase->attachObjectToBone(bonename, entity); tag->setScale(scale); } }