diff --git a/apps/openmw/mwrender/activatoranimation.cpp b/apps/openmw/mwrender/activatoranimation.cpp index 4eb844607c..fc5f88b8af 100644 --- a/apps/openmw/mwrender/activatoranimation.cpp +++ b/apps/openmw/mwrender/activatoranimation.cpp @@ -21,8 +21,8 @@ ActivatorAnimation::ActivatorAnimation(const MWWorld::Ptr &ptr) { const std::string name = "meshes\\"+ref->mBase->mModel; - addObjectList(mPtr.getRefData().getBaseNode(), name, false); - setRenderProperties(mObjects.back().mObjectList, RV_Misc, RQG_Main, RQG_Alpha); + setObjectRoot(mPtr.getRefData().getBaseNode(), name, false); + setRenderProperties(mObjectRoot, RV_Misc, RQG_Main, RQG_Alpha); } } diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index bfffbefdcf..f81c1fe0f7 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -70,10 +70,6 @@ Animation::Animation(const MWWorld::Ptr &ptr) { for(size_t i = 0;i < sMaxLayers;i++) mAnimationValuePtr[i].bind(OGRE_NEW AnimationValue(this, i)); - - /* As long as we remain under 128 active controllers, we can avoid - * reallocations. */ - mActiveCtrls.reserve(128); } Animation::~Animation() @@ -81,34 +77,23 @@ Animation::~Animation() if(mInsert) { Ogre::SceneManager *sceneMgr = mInsert->getCreator(); - for(size_t i = 0;i < mObjects.size();i++) - destroyObjectList(sceneMgr, mObjects[i].mObjectList); - mObjects.clear(); + destroyObjectList(sceneMgr, mObjectRoot); } } -void Animation::addObjectList(Ogre::SceneNode *node, const std::string &model, bool baseonly) +void Animation::setObjectRoot(Ogre::SceneNode *node, const std::string &model, bool baseonly) { - if(!mInsert) + OgreAssert(!mInsert, "Object already has a root!"); + mInsert = node->createChildSceneNode(); + + mObjectRoot = (!baseonly ? NifOgre::Loader::createObjects(mInsert, model) : + NifOgre::Loader::createObjectBase(mInsert, model)); + if(mObjectRoot.mSkelBase) { - mInsert = node->createChildSceneNode(); - assert(mInsert); - } + mSkelBase = mObjectRoot.mSkelBase; - mObjects.push_back(ObjectInfo()); - ObjectInfo &obj = mObjects.back(); - obj.mActiveLayers = 0; - obj.mObjectList = (!baseonly ? NifOgre::Loader::createObjects(mInsert, model) : - NifOgre::Loader::createObjectBase(mInsert, model)); - - NifOgre::ObjectList &objlist = obj.mObjectList; - if(objlist.mSkelBase) - { - if(mObjects.size() == 1) - mSkelBase = objlist.mSkelBase; - - Ogre::AnimationStateSet *aset = objlist.mSkelBase->getAllAnimationStates(); + Ogre::AnimationStateSet *aset = mObjectRoot.mSkelBase->getAllAnimationStates(); Ogre::AnimationStateIterator asiter = aset->getAnimationStateIterator(); while(asiter.hasMoreElements()) { @@ -120,45 +105,22 @@ void Animation::addObjectList(Ogre::SceneNode *node, const std::string &model, b // 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 = objlist.mSkelBase->getSkeleton(); + Ogre::SkeletonInstance *skelinst = mObjectRoot.mSkelBase->getSkeleton(); Ogre::Skeleton::BoneIterator boneiter = skelinst->getBoneIterator(); while(boneiter.hasMoreElements()) boneiter.getNext()->setManuallyControlled(true); - } - if(objlist.mSkelBase && mSkelBase) - { - Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton(); - if(mSkelBase == objlist.mSkelBase) - { - if(objlist.mTextKeys.size() > 0) - { - mAccumRoot = mInsert; - mNonAccumRoot = baseinst->getBone(objlist.mTextKeys.begin()->first); - } - } - else - { - for(size_t i = 0;i < objlist.mControllers.size();i++) - { - NifOgre::NodeTargetValue *dstval; - dstval = dynamic_cast*>(objlist.mControllers[i].getDestination().getPointer()); - if(!dstval) continue; - const Ogre::String &trgtname = dstval->getNode()->getName(); - if(!baseinst->hasBone(trgtname)) continue; - - Ogre::Bone *bone = baseinst->getBone(trgtname); - dstval->setNode(bone); - } + if(mObjectRoot.mTextKeys.size() > 0) + { + mAccumRoot = mInsert; + mNonAccumRoot = skelinst->getBone(mObjectRoot.mTextKeys.begin()->first); } } - for(size_t i = 0;i < objlist.mControllers.size();i++) + for(size_t i = 0;i < mObjectRoot.mControllers.size();i++) { - if(objlist.mControllers[i].getSource().isNull()) - objlist.mControllers[i].setSource(mAnimationValuePtr[0]); + if(mObjectRoot.mControllers[i].getSource().isNull()) + mObjectRoot.mControllers[i].setSource(mAnimationValuePtr[0]); } - - mActiveCtrls.insert(mActiveCtrls.end(), objlist.mControllers.begin(), objlist.mControllers.end()); } void Animation::setRenderProperties(const NifOgre::ObjectList &objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue, Ogre::uint8 transqueue) @@ -186,113 +148,6 @@ void Animation::setRenderProperties(const NifOgre::ObjectList &objlist, Ogre::ui } -void Animation::clearExtraSources() -{ - for(size_t layer = 0;layer < sMaxLayers;layer++) - { - mLayer[layer].mGroupName.clear(); - mLayer[layer].mTextKeys = NULL; - mLayer[layer].mControllers = NULL; - mLayer[layer].mTime = 0.0f; - mLayer[layer].mLoopCount = 0; - mLayer[layer].mPlaying = false; - } - mNonAccumCtrl = NULL; - mAnimVelocity = 0.0f; - - mLastPosition = Ogre::Vector3(0.0f); - if(mAccumRoot) - mAccumRoot->setPosition(mLastPosition); - - if(mObjects.size() > 1) - { - mObjects.resize(1); - mObjects[0].mActiveLayers = 0; - - NifOgre::ObjectList &objlist = mObjects[0].mObjectList; - mActiveCtrls.clear(); - mActiveCtrls.insert(mActiveCtrls.end(), objlist.mControllers.begin(), objlist.mControllers.end()); - } -} - - -void Animation::updateActiveControllers() -{ - mActiveCtrls.clear(); - - /* First, get all controllers that don't target a node, or that target - * nodes that don't belong to any particular layer. - */ - std::vector::iterator obj(mObjects.begin()); - for(;obj != mObjects.end();obj++) - { - std::vector >::const_iterator ctrl(obj->mObjectList.mControllers.begin()); - for(;ctrl != obj->mObjectList.mControllers.end();ctrl++) - { - NifOgre::NodeTargetValue *dstval; - dstval = dynamic_cast*>(ctrl->getDestination().getPointer()); - if(dstval) - { - /*if(getLayerByName(dstval->getNode()->getName()) >= 0)*/ - continue; - } - mActiveCtrls.insert(mActiveCtrls.end(), *ctrl); - } - } - - std::vector > *ctrls = NULL; - size_t layer = 0; - while(layer < sMaxLayers) - { - /* Now get controllers that target nodes that belong to this layer from - * whatever objectlist is active on this layer. - */ - std::vector::iterator obj(mObjects.begin()); - for(;obj != mObjects.end();obj++) - { - if((obj->mActiveLayers&(1<mObjectList.mControllers; - break; - } - } - if(ctrls == NULL) - { - layer++; - continue; - } - - /* Check if any objectlists are active on subsequent layers. Include - * those layers if not. - */ - size_t nextlayer = layer+1; - for(;nextlayer < sMaxLayers;nextlayer++) - { - for(obj = mObjects.begin();obj != mObjects.end();obj++) - { - if((obj->mActiveLayers&(1< >::const_iterator ctrl(ctrls->begin()); - for(;ctrl != ctrls->end();ctrl++) - { - NifOgre::NodeTargetValue *dstval; - dstval = dynamic_cast*>(ctrl->getDestination().getPointer()); - if(dstval) - { - /*ssize_t idx = getLayerByName(dstval->getNode()->getName()); - if(idx >= (ssize_t)layer && idx < (ssize_t)nextlayer)*/ - mActiveCtrls.insert(mActiveCtrls.end(), *ctrl); - } - } - - layer = nextlayer; - } -} - - Ogre::Node *Animation::getNode(const std::string &name) { if(mSkelBase) @@ -323,15 +178,13 @@ bool Animation::hasAnimation(const std::string &anim) if(!mSkelBase) return false; - for(std::vector::const_iterator iter(mObjects.begin());iter != mObjects.end();iter++) + if(mObjectRoot.mTextKeys.size() > 0) { - if(iter->mObjectList.mTextKeys.size() == 0) - continue; - - const NifOgre::TextKeyMap &keys = iter->mObjectList.mTextKeys.begin()->second; + const NifOgre::TextKeyMap &keys = mObjectRoot.mTextKeys.begin()->second; if(findGroupStart(keys, anim) != keys.end()) return true; } + return false; } @@ -561,9 +414,6 @@ bool Animation::play(const std::string &groupname, const std::string &start, con if(!mSkelBase) return false; - for(std::vector::iterator iter(mObjects.begin());iter != mObjects.end();iter++) - iter->mActiveLayers &= ~(1<::reverse_iterator iter(mObjects.rbegin());iter != mObjects.rend();iter++) - { - NifOgre::ObjectList &objlist = iter->mObjectList; + do { + NifOgre::ObjectList &objlist = mObjectRoot; if(objlist.mTextKeys.size() == 0) continue; @@ -617,7 +466,6 @@ bool Animation::play(const std::string &groupname, const std::string &start, con mAnimVelocity = 0.0f; } - iter->mActiveLayers |= (1<::iterator iter(mObjects.begin());iter != mObjects.end();iter++) - iter->mActiveLayers &= ~(1<getSkeleton(); - for(std::vector::iterator iter(mObjects.begin());iter != mObjects.end();iter++) - { - Ogre::Entity *ent = iter->mObjectList.mSkelBase; - if(!ent) continue; - - Ogre::SkeletonInstance *inst = ent->getSkeleton(); - if(baseinst != inst) - updateSkeletonInstance(baseinst, inst); - - // HACK: Dirty the animation state set so that Ogre will apply the - // transformations to entities this skeleton instance is shared with. - ent->getAllAnimationStates()->_notifyDirty(); - } + // HACK: Dirty the animation state set so that Ogre will apply the + // transformations to entities this skeleton instance is shared with. + mSkelBase->getAllAnimationStates()->_notifyDirty(); } return movement; } -void Animation::showWeapons(bool showWeapon){} +void Animation::showWeapons(bool showWeapon) +{ +} } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index b2d4bc6e79..ccab2cb434 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -30,15 +30,6 @@ protected: virtual void setValue(Ogre::Real value); }; - struct ObjectInfo { - NifOgre::ObjectList mObjectList; - /* Bit-field specifying which animation layers this object list is - * explicitly animating on (1 = layer 0, 2 = layer 1, 4 = layer 2. - * etc). - */ - int mActiveLayers; - }; - struct AnimLayer { std::string mGroupName; std::vector > *mControllers; @@ -60,21 +51,19 @@ protected: Ogre::SceneNode *mInsert; Ogre::Entity *mSkelBase; - std::vector mObjects; + NifOgre::ObjectList mObjectRoot; Ogre::Node *mAccumRoot; Ogre::Bone *mNonAccumRoot; NifOgre::NodeTargetValue *mNonAccumCtrl; Ogre::Vector3 mAccumulate; Ogre::Vector3 mLastPosition; - std::vector > mActiveCtrls; - float mAnimVelocity; float mAnimSpeedMult; static const size_t sMaxLayers = 1; AnimLayer mLayer[sMaxLayers]; - Ogre::SharedPtr > mAnimationValuePtr[sMaxLayers]; + Ogre::SharedPtr mAnimationValuePtr[sMaxLayers]; static float calcAnimVelocity(const NifOgre::TextKeyMap &keys, NifOgre::NodeTargetValue *nonaccumctrl, @@ -105,22 +94,16 @@ protected: bool handleTextKey(size_t layeridx, const NifOgre::TextKeyMap::const_iterator &key); - void addObjectList(Ogre::SceneNode *node, const std::string &model, bool baseonly); + void setObjectRoot(Ogre::SceneNode *node, const std::string &model, bool baseonly); + static void destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList &objects); static void setRenderProperties(const NifOgre::ObjectList &objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue, Ogre::uint8 transqueue); - void updateActiveControllers(); - public: Animation(const MWWorld::Ptr &ptr); virtual ~Animation(); - /** Clears all ObjectLists except the first one. As a consequence, any - * playing animations are stopped. - */ - void clearExtraSources(); - void updatePtr(const MWWorld::Ptr &ptr); bool hasAnimation(const std::string &anim); diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index 97c28c0ae4..45c6eb9973 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -21,11 +21,8 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr) { std::string model = "meshes\\"+ref->mBase->mModel; - if((ref->mBase->mFlags&ESM::Creature::Biped)) - addObjectList(mPtr.getRefData().getBaseNode(), "meshes\\base_anim.nif", true); - - addObjectList(mPtr.getRefData().getBaseNode(), model, false); - setRenderProperties(mObjects.back().mObjectList, RV_Actors, RQG_Main, RQG_Alpha); + setObjectRoot(mPtr.getRefData().getBaseNode(), model, false); + setRenderProperties(mObjectRoot, RV_Actors, RQG_Main, RQG_Alpha); } } diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index a92092020a..0cc6846b5e 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -99,26 +99,27 @@ 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"); - - addObjectList(node, smodel, true); + setObjectRoot(node, smodel, true); +#if 0 + addAnimSource(node, smodel); if(mBodyPrefix.find("argonian") != std::string::npos) - addObjectList(node, "meshes\\argonian_swimkna.nif", true); + addAnimSource(node, "meshes\\argonian_swimkna.nif"); else if(!mNpc->isMale() && !isBeast) - addObjectList(node, "meshes\\base_anim_female.nif", true); + addAnimSource(node, "meshes\\base_anim_female.nif"); if(mNpc->mModel.length() > 0) - addObjectList(node, "meshes\\"+mNpc->mModel, true); + addAnimSource(node, "meshes\\"+mNpc->mModel); if(mViewMode == VM_FirstPerson) { /* A bit counter-intuitive, but unlike third-person anims, it seems * beast races get both base_anim.1st.nif and base_animkna.1st.nif. */ - addObjectList(node, "meshes\\base_anim.1st.nif", true); + addAnimSource(node, "meshes\\base_anim.1st.nif"); if(isBeast) - addObjectList(node, "meshes\\base_animkna.1st.nif", true); + addAnimSource(node, "meshes\\base_animkna.1st.nif"); if(!mNpc->isMale() && !isBeast) - addObjectList(node, "meshes\\base_anim_female.1st.nif", true); + addAnimSource(node, "meshes\\base_anim_female.1st.nif"); } - +#endif forceUpdate(); } @@ -132,27 +133,29 @@ void NpcAnimation::setViewMode(NpcAnimation::ViewMode viewMode) const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const ESM::Race *race = store.get().find(mNpc->mRace); bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0; - - clearExtraSources(); + std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif"); +#if 0 + clearAnimSources(); + addAnimSource(node, smodel); if(mBodyPrefix.find("argonian") != std::string::npos) - addObjectList(node, "meshes\\argonian_swimkna.nif", true); + addAnimSource(node, "meshes\\argonian_swimkna.nif"); else if(!mNpc->isMale() && !isBeast) - addObjectList(node, "meshes\\base_anim_female.nif", true); + addAnimSource(node, "meshes\\base_anim_female.nif"); if(mNpc->mModel.length() > 0) - addObjectList(node, "meshes\\"+mNpc->mModel, true); + addAnimSource(node, "meshes\\"+mNpc->mModel); if(mViewMode == VM_FirstPerson) { /* A bit counter-intuitive, but unlike third-person anims, it seems * beast races get both base_anim.1st.nif and base_animkna.1st.nif. */ - addObjectList(node, "meshes\\base_anim.1st.nif", true); + addAnimSource(node, "meshes\\base_anim.1st.nif"); if(isBeast) - addObjectList(node, "meshes\\base_animkna.1st.nif", true); + addAnimSource(node, "meshes\\base_animkna.1st.nif"); if(!mNpc->isMale() && !isBeast) - addObjectList(node, "meshes\\base_anim_female.1st.nif", true); + addAnimSource(node, "meshes\\base_anim_female.1st.nif"); } MWBase::Environment::get().getMechanicsManager()->forceStateUpdate(mPtr); - +#endif for(size_t i = 0;i < sPartListSize;i++) removeIndividualPart(i); forceUpdate();