From 81ce8dbe122db57110a32996975356bb057e0e91 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 21 Jul 2012 14:41:26 -0700 Subject: [PATCH 1/6] Combine animation handling into the base class --- apps/openmw/mwrender/animation.cpp | 29 ++++++++++++++++++++++ apps/openmw/mwrender/animation.hpp | 2 +- apps/openmw/mwrender/creatureanimation.cpp | 25 ++----------------- apps/openmw/mwrender/npcanimation.cpp | 25 +------------------ 4 files changed, 33 insertions(+), 48 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 1f0a99518..88f6cebe6 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -42,4 +42,33 @@ void Animation::skipAnim() mAnimate = 0; } +void Animation::runAnimation(float timepassed) +{ + if(mAnimate != 0) + { + mTime += timepassed; + + if(mEntityList.mSkelBase) + { + Ogre::AnimationStateSet *aset = mEntityList.mSkelBase->getAllAnimationStates(); + Ogre::AnimationStateIterator as = aset->getAnimationStateIterator(); + while(as.hasMoreElements()) + { + Ogre::AnimationState *state = as.getNext(); + state->setTimePosition(mTime); + if(mTime >= state->getLength()) + { + if(mAnimate != -1) + mAnimate--; + //std::cout << "Stopping the animation\n"; + if(mAnimate == 0) + mTime = state->getLength(); + else + mTime = mTime - state->getLength(); + } + } + } + } +} + } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 0ed4545f2..5de314df1 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -36,7 +36,7 @@ public: void playGroup(std::string groupname, int mode, int loops); void skipAnim(); - virtual void runAnimation(float timepassed) = 0; + virtual void runAnimation(float timepassed); }; } diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index ee1fd45ba..9d2a58a1e 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -69,30 +69,9 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, OEngine::Render::O void CreatureAnimation::runAnimation(float timepassed) { - if(mAnimate > 0) - { - mTime += timepassed; + // Placeholder - if(mEntityList.mSkelBase) - { - Ogre::AnimationStateSet *aset = mEntityList.mSkelBase->getAllAnimationStates(); - Ogre::AnimationStateIterator as = aset->getAnimationStateIterator(); - while(as.hasMoreElements()) - { - Ogre::AnimationState *state = as.getNext(); - state->setTimePosition(mTime); - if(state->getTimePosition() >= state->getLength()) - { - mAnimate--; - //std::cout << "Stopping the animation\n"; - if(mAnimate == 0) - mTime = state->getLength(); - else - mTime = mTime - state->getLength(); - } - } - } - } + Animation::runAnimation(timepassed); } } diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index f66ab8403..3cca110e3 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -373,30 +373,7 @@ void NpcAnimation::runAnimation(float timepassed) } timeToChange += timepassed; - if(mAnimate > 0) - { - mTime += timepassed; - - if(mEntityList.mSkelBase) - { - Ogre::AnimationStateSet *aset = mEntityList.mSkelBase->getAllAnimationStates(); - Ogre::AnimationStateIterator as = aset->getAnimationStateIterator(); - while(as.hasMoreElements()) - { - Ogre::AnimationState *state = as.getNext(); - state->setTimePosition(mTime); - if(state->getTimePosition() >= state->getLength()) - { - mAnimate--; - //std::cout << "Stopping the animation\n"; - if(mAnimate == 0) - mTime = state->getLength(); - else - mTime = mTime - state->getLength(); - } - } - } - } + Animation::runAnimation(timepassed); } void NpcAnimation::removeEntities(NifOgre::EntityList &entities) From c5b9098517714827d575166de0163aaed26e1398 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 21 Jul 2012 17:09:16 -0700 Subject: [PATCH 2/6] Remove an unused field from EntityList --- apps/openmw/mwrender/npcanimation.cpp | 1 - components/nifogre/ogre_nif_loader.cpp | 1 - components/nifogre/ogre_nif_loader.hpp | 3 +-- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 3cca110e3..e89122e4b 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -388,7 +388,6 @@ void NpcAnimation::removeEntities(NifOgre::EntityList &entities) } entities.mEntities.clear(); entities.mSkelBase = NULL; - entities.mRootNode = NULL; } void NpcAnimation::removeIndividualPart(int type) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 2aa7cd433..2c5b7e324 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -1027,7 +1027,6 @@ EntityList NIFLoader::createEntities(Ogre::SceneNode *parent, const std::string if(meshes.size() == 0) return entitylist; - entitylist.mRootNode = parent; Ogre::SceneManager *sceneMgr = parent->getCreator(); for(size_t i = 0;i < meshes.size();i++) { diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index 76e94975c..a9195f2fb 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -62,9 +62,8 @@ namespace NifOgre struct EntityList { std::vector mEntities; Ogre::Entity *mSkelBase; - Ogre::SceneNode *mRootNode; - EntityList() : mSkelBase(0), mRootNode(0) + EntityList() : mSkelBase(0) { } }; From e81fc42daaf0adc5ae296b7781aea4270f299b9d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 21 Jul 2012 17:12:41 -0700 Subject: [PATCH 3/6] Remove the beast-race special cases from updateParts The special handling should happen at a much lower level, and prevent the objects from being equipped in the first place. --- apps/openmw/mwrender/npcanimation.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index e89122e4b..415de5859 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -149,7 +149,7 @@ void NpcAnimation::updateParts() { &greaves, MWWorld::InventoryStore::Slot_Greaves }, { &leftpauldron, MWWorld::InventoryStore::Slot_LeftPauldron }, { &rightpauldron, MWWorld::InventoryStore::Slot_RightPauldron }, - { &boots, MWWorld::InventoryStore::Slot_Boots }, // !isBeast + { &boots, MWWorld::InventoryStore::Slot_Boots }, { &leftglove, MWWorld::InventoryStore::Slot_LeftGauntlet }, { &rightglove, MWWorld::InventoryStore::Slot_RightGauntlet }, { &shirt, MWWorld::InventoryStore::Slot_Shirt }, @@ -157,9 +157,6 @@ void NpcAnimation::updateParts() }; for(size_t i = 0;i < sizeof(slotlist)/sizeof(slotlist[0]);i++) { - if(slotlist[i].iter == &boots && isBeast) - continue; - MWWorld::ContainerStoreIterator iter = mInv.getSlot(slotlist[i].slot); if(*slotlist[i].iter != iter) { @@ -235,7 +232,7 @@ void NpcAnimation::updateParts() std::vector parts = armor->parts.parts; addPartGroup(MWWorld::InventoryStore::Slot_RightPauldron, 3, parts); } - if(!isBeast && boots != mInv.end()) + if(boots != mInv.end()) { if(boots->getTypeName() == typeid(ESM::Clothing).name()) { From 77446a0d58fde458f1ba01788f2854e1e2b1b558 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 21 Jul 2012 17:39:57 -0700 Subject: [PATCH 4/6] Fix skipAnim, only skip one animation update --- apps/openmw/mwrender/animation.cpp | 6 ++++-- apps/openmw/mwrender/animation.hpp | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 88f6cebe6..653a506e8 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -16,6 +16,7 @@ Animation::Animation(OEngine::Render::OgreRenderer& _rend) , mRend(_rend) , mTime(0.0f) , mAnimate(0) + , mSkipFrame(false) { } @@ -39,12 +40,12 @@ void Animation::playGroup(std::string groupname, int mode, int loops) void Animation::skipAnim() { - mAnimate = 0; + mSkipFrame = true; } void Animation::runAnimation(float timepassed) { - if(mAnimate != 0) + if(mAnimate != 0 && !mSkipFrame) { mTime += timepassed; @@ -69,6 +70,7 @@ void Animation::runAnimation(float timepassed) } } } + mSkipFrame = false; } } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 5de314df1..ae1477666 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -27,6 +27,7 @@ protected: float mTime; int mAnimate; + bool mSkipFrame; NifOgre::EntityList mEntityList; From d8cb6855437813e1145f213c3cb83f43b0580923 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 21 Jul 2012 18:03:01 -0700 Subject: [PATCH 5/6] Interpolate keyframes when creating them Probably not fully correct, but better than nothing. --- components/nifogre/ogre_nif_loader.cpp | 28 ++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 2c5b7e324..e695cd959 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -306,10 +306,30 @@ void loadResource(Ogre::Resource *resource) Ogre::TransformKeyFrame *kframe; kframe = nodetrack->createNodeKeyFrame(curtime); - // FIXME: These should be interpolated since they don't all fall on the same time - kframe->setRotation(curquat); - kframe->setTranslate(curtrans); - kframe->setScale(curscale); + if(quatiter == quatkeys.mKeys.end() || quatiter == quatkeys.mKeys.begin()) + kframe->setRotation(curquat); + else + { + QuaternionKeyList::VecType::const_iterator last = quatiter-1; + float diff = (curtime-last->mTime) / (quatiter->mTime-last->mTime); + kframe->setRotation(Ogre::Quaternion::nlerp(diff, lastquat, curquat)); + } + if(traniter == trankeys.mKeys.end() || traniter == trankeys.mKeys.begin()) + kframe->setTranslate(curtrans); + else + { + Vector3KeyList::VecType::const_iterator last = traniter-1; + float diff = (curtime-last->mTime) / (traniter->mTime-last->mTime); + kframe->setTranslate(lasttrans + ((curtrans-lasttrans)*diff)); + } + if(scaleiter == scalekeys.mKeys.end() || scaleiter == scalekeys.mKeys.begin()) + kframe->setScale(curscale); + else + { + FloatKeyList::VecType::const_iterator last = scaleiter-1; + float diff = (curtime-last->mTime) / (scaleiter->mTime-last->mTime); + kframe->setScale(lastscale + ((curscale-lastscale)*diff)); + } } } anim->optimise(); From 4035d7370e5288898d1e590030b1aa4f853bad28 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 21 Jul 2012 22:04:05 -0700 Subject: [PATCH 6/6] Fix name/filter comparison --- components/nifogre/ogre_nif_loader.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index e695cd959..c34f69404 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -25,6 +25,8 @@ #include "ogre_nif_loader.hpp" +#include + #include #include #include @@ -1080,6 +1082,11 @@ EntityList NIFLoader::createEntities(Ogre::SceneNode *parent, const std::string return entitylist; } +static bool checklow(const char &a, const char &b) +{ + return ::tolower(a) == ::tolower(b); +} + EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bonename, Ogre::SceneNode *parentNode, const std::string &name, @@ -1099,8 +1106,7 @@ EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bo if(ent->hasSkeleton()) { if(meshes[i].second.length() < filter.length() || - !boost::algorithm::lexicographical_compare(meshes[i].second.substr(0, filter.length()), - filter, boost::algorithm::is_iequal())) + std::mismatch(filter.begin(), filter.end(), meshes[i].second.begin(), checklow).first != filter.end()) { sceneMgr->destroyEntity(ent); meshes.erase(meshes.begin()+i);