From 69084139aaf2c4711061dd62a84666d6f34c6d10 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 14 Apr 2013 17:58:21 -0700 Subject: [PATCH] Use an array of objectlists, instead of one base objectlist and an array of 'animation sources' --- apps/openmw/mwrender/activatoranimation.cpp | 10 +- apps/openmw/mwrender/animation.cpp | 136 +++++++------------- apps/openmw/mwrender/animation.hpp | 14 +- apps/openmw/mwrender/creatureanimation.cpp | 21 ++- apps/openmw/mwrender/npcanimation.cpp | 27 ++-- 5 files changed, 75 insertions(+), 133 deletions(-) diff --git a/apps/openmw/mwrender/activatoranimation.cpp b/apps/openmw/mwrender/activatoranimation.cpp index 4630208b4b..27ddce339d 100644 --- a/apps/openmw/mwrender/activatoranimation.cpp +++ b/apps/openmw/mwrender/activatoranimation.cpp @@ -27,9 +27,9 @@ ActivatorAnimation::ActivatorAnimation(const MWWorld::Ptr &ptr) std::string mesh = "meshes\\" + ref->mBase->mModel; createObjectList(mPtr.getRefData().getBaseNode(), mesh); - for(size_t i = 0;i < mObjectList.mEntities.size();i++) + for(size_t i = 0;i < mObjectLists[0].mEntities.size();i++) { - Ogre::Entity *ent = mObjectList.mEntities[i]; + Ogre::Entity *ent = mObjectLists[0].mEntities[i]; ent->setVisibilityFlags(RV_Misc); for(unsigned int j=0; j < ent->getNumSubEntities(); ++j) @@ -38,14 +38,12 @@ ActivatorAnimation::ActivatorAnimation(const MWWorld::Ptr &ptr) subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main); } } - for(size_t i = 0;i < mObjectList.mParticles.size();i++) + for(size_t i = 0;i < mObjectLists[0].mParticles.size();i++) { - Ogre::ParticleSystem *part = mObjectList.mParticles[i]; + Ogre::ParticleSystem *part = mObjectLists[0].mParticles[i]; part->setVisibilityFlags(RV_Misc); - part->setRenderQueueGroup(RQG_Alpha); } - setAnimationSource(mesh); } } diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index d6f762ab76..30bcd3c4c3 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -55,68 +55,45 @@ Animation::~Animation() if(mInsert) { Ogre::SceneManager *sceneMgr = mInsert->getCreator(); - destroyObjectList(sceneMgr, mObjectList); - - for(size_t i = 0;i < mAnimationSources.size();i++) - destroyObjectList(sceneMgr, mAnimationSources[i]); - mAnimationSources.clear(); + for(size_t i = 0;i < mObjectLists.size();i++) + destroyObjectList(sceneMgr, mObjectLists[i]); + mObjectLists.clear(); } } -void Animation::setAnimationSources(const std::vector &names) +void Animation::createObjectList(Ogre::SceneNode *node, const std::string &model) { - if(!mSkelBase) - return; - Ogre::SceneManager *sceneMgr = mInsert->getCreator(); + assert(!mInsert); + mInsert = node->createChildSceneNode(); + assert(mInsert); - mCurrentControllers = &mObjectList.mControllers; - mCurrentAnim = NULL; - mCurrentKeys = NULL; - mAnimVelocity = 0.0f; - mAccumRoot = NULL; - mNonAccumRoot = NULL; - mTextKeys.clear(); - for(size_t i = 0;i < mAnimationSources.size();i++) - destroyObjectList(sceneMgr, mAnimationSources[i]); - mAnimationSources.clear(); + mObjectLists.resize(1); - Ogre::SharedPtr > ctrlval(OGRE_NEW AnimationValue(this)); - Ogre::SkeletonInstance *skelinst = mSkelBase->getSkeleton(); - std::vector::const_iterator nameiter; - for(nameiter = names.begin();nameiter != names.end();nameiter++) + mObjectLists[0] = NifOgre::Loader::createObjects(mInsert, model); + if(mObjectLists[0].mSkelBase) { - mAnimationSources.push_back(NifOgre::Loader::createObjectBase(sceneMgr, *nameiter)); - if(!mAnimationSources.back().mSkelBase) + mSkelBase = mObjectLists[0].mSkelBase; + + Ogre::AnimationStateSet *aset = mObjectLists[0].mSkelBase->getAllAnimationStates(); + Ogre::AnimationStateIterator asiter = aset->getAnimationStateIterator(); + while(asiter.hasMoreElements()) { - std::cerr<< "Failed to get skeleton source "<<*nameiter < *dstval = dynamic_cast*>(objects.mControllers[i].getDestination().getPointer()); - if(!dstval) continue; - - const Ogre::String &trgtname = dstval->getNode()->getName(); - if(!skelinst->hasBone(trgtname)) continue; - - Ogre::Bone *bone = skelinst->getBone(trgtname); - dstval->setNode(bone); + Ogre::AnimationState *state = asiter.getNext(); + state->setEnabled(false); + state->setLoop(false); } - for(size_t i = 0;i < objects.mControllers.size();i++) - { - if(objects.mControllers[i].getSource().isNull()) - objects.mControllers[i].setSource(ctrlval); - } + // Set the bones as manually controlled since we're applying the + // transformations manually (needed if we want to apply an animation + // from one skeleton onto another). + Ogre::SkeletonInstance *skelinst = mObjectLists[0].mSkelBase->getSkeleton(); + Ogre::Skeleton::BoneIterator boneiter = skelinst->getBoneIterator(); + while(boneiter.hasMoreElements()) + boneiter.getNext()->setManuallyControlled(true); - Ogre::Entity *ent = objects.mSkelBase; - Ogre::SkeletonPtr skel = Ogre::SkeletonManager::getSingleton().getByName(ent->getSkeleton()->getName()); - Ogre::Skeleton::BoneIterator boneiter = skel->getBoneIterator(); + Ogre::SkeletonPtr skel = Ogre::SkeletonManager::getSingleton().getByName(skelinst->getName()); + boneiter = skel->getBoneIterator(); while(boneiter.hasMoreElements()) { Ogre::Bone *bone = boneiter.getNext(); @@ -143,43 +120,14 @@ void Animation::setAnimationSources(const std::vector &names) break; } } -} - -void Animation::createObjectList(Ogre::SceneNode *node, const std::string &model) -{ - mInsert = node->createChildSceneNode(); - assert(mInsert); - - mObjectList = NifOgre::Loader::createObjects(mInsert, model); - if(mObjectList.mSkelBase) - { - mSkelBase = mObjectList.mSkelBase; - - Ogre::AnimationStateSet *aset = mSkelBase->getAllAnimationStates(); - Ogre::AnimationStateIterator asiter = aset->getAnimationStateIterator(); - while(asiter.hasMoreElements()) - { - Ogre::AnimationState *state = asiter.getNext(); - state->setEnabled(false); - state->setLoop(false); - } - - // Set the bones as manually controlled since we're applying the - // transformations manually (needed if we want to apply an animation - // from one skeleton onto another). - Ogre::SkeletonInstance *skelinst = mSkelBase->getSkeleton(); - Ogre::Skeleton::BoneIterator boneiter = skelinst->getBoneIterator(); - while(boneiter.hasMoreElements()) - boneiter.getNext()->setManuallyControlled(true); - } Ogre::SharedPtr > ctrlval(OGRE_NEW AnimationValue(this)); - for(size_t i = 0;i < mObjectList.mControllers.size();i++) + for(size_t i = 0;i < mObjectLists[0].mControllers.size();i++) { - if(mObjectList.mControllers[i].getSource().isNull()) - mObjectList.mControllers[i].setSource(ctrlval); + if(mObjectLists[0].mControllers[i].getSource().isNull()) + mObjectLists[0].mControllers[i].setSource(ctrlval); } - mCurrentControllers = &mObjectList.mControllers; + mCurrentControllers = &mObjectLists[0].mControllers; } @@ -197,9 +145,9 @@ Ogre::Node *Animation::getNode(const std::string &name) bool Animation::hasAnimation(const std::string &anim) { - for(std::vector::const_iterator iter(mAnimationSources.begin());iter != mAnimationSources.end();iter++) + for(std::vector::const_iterator iter(mObjectLists.begin());iter != mObjectLists.end();iter++) { - if(iter->mSkelBase->hasAnimationState(anim)) + if(iter->mSkelBase && iter->mSkelBase->hasAnimationState(anim)) return true; } return false; @@ -449,7 +397,7 @@ void Animation::play(const std::string &groupname, const std::string &start, con try { bool found = false; /* Look in reverse; last-inserted source has priority. */ - for(std::vector::reverse_iterator iter(mAnimationSources.rbegin());iter != mAnimationSources.rend();iter++) + for(std::vector::reverse_iterator iter(mObjectLists.rbegin());iter != mObjectLists.rend();iter++) { if(iter->mSkelBase->hasAnimationState(groupname)) { @@ -513,9 +461,19 @@ Ogre::Vector3 Animation::runAnimation(float timepassed) if(mSkelBase) { - // HACK: Dirty the animation state set so that Ogre will apply the - // transformations to entities this skeleton instance is shared with. - mSkelBase->getAllAnimationStates()->_notifyDirty(); + const Ogre::SkeletonInstance *skelsrc = mSkelBase->getSkeleton(); + for(size_t i = 0;i < mObjectLists.size();i++) + { + Ogre::Entity *ent = mObjectLists[i].mSkelBase; + if(!ent) continue; + + Ogre::SkeletonInstance *skeldst = ent->getSkeleton(); + if(skelsrc != skeldst) + updateSkeletonInstance(skelsrc, skeldst); + // HACK: Dirty the animation state set so that Ogre will apply the + // transformations to entities this skeleton instance is shared with. + ent->getAllAnimationStates()->_notifyDirty(); + } } return movement; diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 32344a2c02..3c7433db98 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -44,15 +44,13 @@ protected: Ogre::SceneNode *mInsert; Ogre::Entity *mSkelBase; - NifOgre::ObjectList mObjectList; + std::vector mObjectLists; std::map mTextKeys; Ogre::Node *mAccumRoot; Ogre::Bone *mNonAccumRoot; Ogre::Vector3 mAccumulate; Ogre::Vector3 mLastPosition; - std::vector mAnimationSources; - std::vector > *mCurrentControllers; NifOgre::TextKeyMap *mCurrentKeys; NifOgre::TextKeyMap::const_iterator mNextKey; @@ -83,16 +81,6 @@ protected: bool handleEvent(float time, const std::string &evt); - /* Specifies a list of skeleton names to use as animation sources. */ - void setAnimationSources(const std::vector &names); - - /* Specifies a single skeleton name to use as an animation source. */ - void setAnimationSource(const std::string &name) - { - std::vector names(1, name); - setAnimationSources(names); - } - void createObjectList(Ogre::SceneNode *node, const std::string &model); static void destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList &objects); diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index c714a2372a..7084974b8c 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -26,10 +26,15 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr) { std::string model = "meshes\\"+ref->mBase->mModel; - createObjectList(mPtr.getRefData().getBaseNode(), model); - for(size_t i = 0;i < mObjectList.mEntities.size();i++) + std::vector names; + if((ref->mBase->mFlags&ESM::Creature::Biped)) + names.push_back("meshes\\base_anim.nif"); + names.push_back(model); + + createObjectList(mPtr.getRefData().getBaseNode(), model/*names*/); + for(size_t i = 0;i < mObjectLists[0].mEntities.size();i++) { - Ogre::Entity *ent = mObjectList.mEntities[i]; + Ogre::Entity *ent = mObjectLists[0].mEntities[i]; ent->setVisibilityFlags(RV_Actors); for(unsigned int j=0; j < ent->getNumSubEntities(); ++j) @@ -38,19 +43,13 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr) subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main); } } - for(size_t i = 0;i < mObjectList.mParticles.size();i++) + for(size_t i = 0;i < mObjectLists[0].mParticles.size();i++) { - Ogre::ParticleSystem *part = mObjectList.mParticles[i]; + Ogre::ParticleSystem *part = mObjectLists[0].mParticles[i]; part->setVisibilityFlags(RV_Actors); part->setRenderQueueGroup(RQG_Alpha); } - - std::vector names; - if((ref->mBase->mFlags&ESM::Creature::Biped)) - names.push_back("meshes\\base_anim.nif"); - names.push_back(model); - setAnimationSources(names); } } diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index a2446b8671..a713ae79e1 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -96,10 +96,18 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0; std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif"); - createObjectList(node, smodel); - for(size_t i = 0;i < mObjectList.mEntities.size();i++) + std::vector skelnames(1, smodel); + if(!mNpc->isMale() && !isBeast) + skelnames.push_back("meshes\\base_anim_female.nif"); + else if(mBodyPrefix.find("argonian") != std::string::npos) + skelnames.push_back("meshes\\argonian_swimkna.nif"); + if(mNpc->mModel.length() > 0) + skelnames.push_back("meshes\\"+Misc::StringUtils::lowerCase(mNpc->mModel)); + + createObjectList(node, smodel/*skelnames*/); + for(size_t i = 0;i < mObjectLists[0].mEntities.size();i++) { - Ogre::Entity *base = mObjectList.mEntities[i]; + Ogre::Entity *base = mObjectLists[0].mEntities[i]; base->getUserObjectBindings().setUserAny(Ogre::Any(-1)); if (mVisibilityFlags != 0) @@ -111,9 +119,9 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main); } } - for(size_t i = 0;i < mObjectList.mParticles.size();i++) + for(size_t i = 0;i < mObjectLists[0].mParticles.size();i++) { - Ogre::ParticleSystem *part = mObjectList.mParticles[i]; + Ogre::ParticleSystem *part = mObjectLists[0].mParticles[i]; part->getUserObjectBindings().setUserAny(Ogre::Any(-1)); if(mVisibilityFlags != 0) @@ -121,15 +129,6 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor part->setRenderQueueGroup(RQG_Alpha); } - std::vector skelnames(1, smodel); - if(!mNpc->isMale() && !isBeast) - skelnames.push_back("meshes\\base_anim_female.nif"); - else if(mBodyPrefix.find("argonian") != std::string::npos) - skelnames.push_back("meshes\\argonian_swimkna.nif"); - if(mNpc->mModel.length() > 0) - skelnames.push_back("meshes\\"+Misc::StringUtils::lowerCase(mNpc->mModel)); - setAnimationSources(skelnames); - forceUpdate(); }