From 9809748eba2a0514019f99e268d044c5f23ebc8a Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 2 Sep 2014 03:04:38 +0200 Subject: [PATCH] Store NIF keys mapped by time and use lower_bound for searches --- components/nif/data.hpp | 20 ++++----- components/nif/nifkey.hpp | 39 ++++++++--------- components/nifogre/controller.hpp | 59 +++++++++++++------------- components/nifogre/ogrenifloader.cpp | 62 ++++++++++++++-------------- 4 files changed, 93 insertions(+), 87 deletions(-) diff --git a/components/nif/data.hpp b/components/nif/data.hpp index 7fd905f00..34ef3a34e 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -210,7 +210,7 @@ public: class NiPosData : public Record { public: - Vector3KeyList mKeyList; + Vector3KeyMap mKeyList; void read(NIFStream *nif) { @@ -221,7 +221,7 @@ public: class NiUVData : public Record { public: - FloatKeyList mKeyList[4]; + FloatKeyMap mKeyList[4]; void read(NIFStream *nif) { @@ -233,7 +233,7 @@ public: class NiFloatData : public Record { public: - FloatKeyList mKeyList; + FloatKeyMap mKeyList; void read(NIFStream *nif) { @@ -283,11 +283,11 @@ public: class NiColorData : public Record { public: - Vector4KeyList mKeyList; + Vector4KeyMap mKeyMap; void read(NIFStream *nif) { - mKeyList.read(nif); + mKeyMap.read(nif); } }; @@ -388,7 +388,7 @@ public: struct NiMorphData : public Record { struct MorphData { - FloatKeyList mData; + FloatKeyMap mData; std::vector mVertices; }; std::vector mMorphs; @@ -411,11 +411,11 @@ struct NiMorphData : public Record struct NiKeyframeData : public Record { - QuaternionKeyList mRotations; + QuaternionKeyMap mRotations; //\FIXME mXYZ_Keys are read, but not used. - FloatKeyList mXYZ_Keys; - Vector3KeyList mTranslations; - FloatKeyList mScales; + FloatKeyMap mXYZ_Keys; + Vector3KeyMap mTranslations; + FloatKeyMap mScales; void read(NIFStream *nif) { diff --git a/components/nif/nifkey.hpp b/components/nif/nifkey.hpp index 403499e7f..b0db80914 100644 --- a/components/nif/nifkey.hpp +++ b/components/nif/nifkey.hpp @@ -12,7 +12,6 @@ namespace Nif template struct KeyT { - float mTime; T mValue; T mForwardValue; // Only for Quadratic interpolation, and never for QuaternionKeyList T mBackwardValue; // Only for Quadratic interpolation, and never for QuaternionKeyList @@ -26,8 +25,8 @@ typedef KeyT Vector4Key; typedef KeyT QuaternionKey; template -struct KeyListT { - typedef std::vector< KeyT > VecType; +struct KeyMapT { + typedef std::map< float, KeyT > MapType; static const unsigned int sLinearInterpolation = 1; static const unsigned int sQuadraticInterpolation = 2; @@ -35,9 +34,9 @@ struct KeyListT { static const unsigned int sXYZInterpolation = 4; unsigned int mInterpolationType; - VecType mKeys; + MapType mKeys; - KeyListT() : mInterpolationType(sLinearInterpolation) {} + KeyMapT() : mInterpolationType(sLinearInterpolation) {} //Read in a KeyGroup (see http://niftools.sourceforge.net/doc/nif/NiKeyframeData.html) void read(NIFStream *nif, bool force=false) @@ -63,24 +62,27 @@ struct KeyListT { { for(size_t i = 0;i < count;i++) { - readTimeAndValue(nifReference, key); - mKeys.push_back(key); + float time = nif->getFloat(); + readValue(nifReference, key); + mKeys[time] = key; } } else if(mInterpolationType == sQuadraticInterpolation) { for(size_t i = 0;i < count;i++) { + float time = nif->getFloat(); readQuadratic(nifReference, key); - mKeys.push_back(key); + mKeys[time] = key; } } else if(mInterpolationType == sTBCInterpolation) { for(size_t i = 0;i < count;i++) { + float time = nif->getFloat(); readTBC(nifReference, key); - mKeys.push_back(key); + mKeys[time] = key; } } //XYZ keys aren't actually read here. @@ -104,37 +106,36 @@ struct KeyListT { } private: - static void readTimeAndValue(NIFStream &nif, KeyT &key) + static void readValue(NIFStream &nif, KeyT &key) { - key.mTime = nif.getFloat(); key.mValue = (nif.*getValue)(); } static void readQuadratic(NIFStream &nif, KeyT &key) { - readTimeAndValue(nif, key); + readValue(nif, key); } template static void readQuadratic(NIFStream &nif, KeyT &key) { - readTimeAndValue(nif, key); + readValue(nif, key); key.mForwardValue = (nif.*getValue)(); key.mBackwardValue = (nif.*getValue)(); } static void readTBC(NIFStream &nif, KeyT &key) { - readTimeAndValue(nif, key); + readValue(nif, key); key.mTension = nif.getFloat(); key.mBias = nif.getFloat(); key.mContinuity = nif.getFloat(); } }; -typedef KeyListT FloatKeyList; -typedef KeyListT Vector3KeyList; -typedef KeyListT Vector4KeyList; -typedef KeyListT QuaternionKeyList; +typedef KeyMapT FloatKeyMap; +typedef KeyMapT Vector3KeyMap; +typedef KeyMapT Vector4KeyMap; +typedef KeyMapT QuaternionKeyMap; } // Namespace -#endif //#ifndef OPENMW_COMPONENTS_NIF_NIFKEY_HPP \ No newline at end of file +#endif //#ifndef OPENMW_COMPONENTS_NIF_NIFKEY_HPP diff --git a/components/nifogre/controller.hpp b/components/nifogre/controller.hpp index 317447d95..f4d7ac29f 100644 --- a/components/nifogre/controller.hpp +++ b/components/nifogre/controller.hpp @@ -2,6 +2,7 @@ #define COMPONENTS_NIFOGRE_CONTROLLER_H #include +#include #include namespace NifOgre @@ -10,53 +11,55 @@ namespace NifOgre class ValueInterpolator { protected: - float interpKey(const Nif::FloatKeyList::VecType &keys, float time, float def=0.f) const + float interpKey(const Nif::FloatKeyMap::MapType &keys, float time, float def=0.f) const { if (keys.size() == 0) return def; - if(time <= keys.front().mTime) - return keys.front().mValue; + if(time <= keys.begin()->first) + return keys.begin()->second.mValue; - const Nif::FloatKey* keyArray = keys.data(); - size_t size = keys.size(); - - for (size_t i = 1; i < size; ++i) + Nif::FloatKeyMap::MapType::const_iterator it = keys.lower_bound(time); + if (it != keys.end()) { - const Nif::FloatKey* aKey = &keyArray[i]; + float aTime = it->first; + const Nif::FloatKey* aKey = &it->second; + + assert (it != keys.begin()); // Shouldn't happen, was checked at beginning of this function - if(aKey->mTime < time) - continue; + Nif::FloatKeyMap::MapType::const_iterator last = --it; + float aLastTime = last->first; + const Nif::FloatKey* aLastKey = &last->second; - const Nif::FloatKey* aLastKey = &keyArray[i-1]; - float a = (time - aLastKey->mTime) / (aKey->mTime - aLastKey->mTime); + float a = (time - aLastTime) / (aTime - aLastTime); return aLastKey->mValue + ((aKey->mValue - aLastKey->mValue) * a); } - - return keys.back().mValue; + else + return (--keys.end())->second.mValue; } - Ogre::Vector3 interpKey(const Nif::Vector3KeyList::VecType &keys, float time) const + Ogre::Vector3 interpKey(const Nif::Vector3KeyMap::MapType &keys, float time) const { - if(time <= keys.front().mTime) - return keys.front().mValue; + if(time <= keys.begin()->first) + return keys.begin()->second.mValue; - const Nif::Vector3Key* keyArray = keys.data(); - size_t size = keys.size(); - - for (size_t i = 1; i < size; ++i) + Nif::Vector3KeyMap::MapType::const_iterator it = keys.lower_bound(time); + if (it != keys.end()) { - const Nif::Vector3Key* aKey = &keyArray[i]; + float aTime = it->first; + const Nif::Vector3Key* aKey = &it->second; + + assert (it != keys.begin()); // Shouldn't happen, was checked at beginning of this function - if(aKey->mTime < time) - continue; + Nif::Vector3KeyMap::MapType::const_iterator last = --it; + float aLastTime = last->first; + const Nif::Vector3Key* aLastKey = &last->second; - const Nif::Vector3Key* aLastKey = &keyArray[i-1]; - float a = (time - aLastKey->mTime) / (aKey->mTime - aLastKey->mTime); + float a = (time - aLastTime) / (aTime - aLastTime); return aLastKey->mValue + ((aKey->mValue - aLastKey->mValue) * a); } - - return keys.back().mValue; + else + return (--keys.end())->second.mValue; } }; diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 83716764c..531044c26 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -237,7 +237,7 @@ public: { private: Ogre::MovableObject* mMovable; - Nif::FloatKeyList mData; + Nif::FloatKeyMap mData; MaterialControllerManager* mMaterialControllerMgr; public: @@ -284,7 +284,7 @@ public: { private: Ogre::MovableObject* mMovable; - Nif::Vector3KeyList mData; + Nif::Vector3KeyMap mData; MaterialControllerManager* mMaterialControllerMgr; public: @@ -409,34 +409,35 @@ public: class Value : public NodeTargetValue, public ValueInterpolator { private: - const Nif::QuaternionKeyList* mRotations; - const Nif::Vector3KeyList* mTranslations; - const Nif::FloatKeyList* mScales; + const Nif::QuaternionKeyMap* mRotations; + const Nif::Vector3KeyMap* mTranslations; + const Nif::FloatKeyMap* mScales; Nif::NIFFilePtr mNif; // Hold a SharedPtr to make sure key lists stay valid using ValueInterpolator::interpKey; - static Ogre::Quaternion interpKey(const Nif::QuaternionKeyList::VecType &keys, float time) + static Ogre::Quaternion interpKey(const Nif::QuaternionKeyMap::MapType &keys, float time) { - if(time <= keys.front().mTime) - return keys.front().mValue; + if(time <= keys.begin()->first) + return keys.begin()->second.mValue; - const Nif::QuaternionKey* keyArray = keys.data(); - size_t size = keys.size(); - - for (size_t i = 1; i < size; ++i) + Nif::QuaternionKeyMap::MapType::const_iterator it = keys.lower_bound(time); + if (it != keys.end()) { - const Nif::QuaternionKey* aKey = &keyArray[i]; + float aTime = it->first; + const Nif::QuaternionKey* aKey = &it->second; - if(aKey->mTime < time) - continue; + assert (it != keys.begin()); // Shouldn't happen, was checked at beginning of this function + + Nif::QuaternionKeyMap::MapType::const_iterator last = --it; + float aLastTime = last->first; + const Nif::QuaternionKey* aLastKey = &last->second; - const Nif::QuaternionKey* aLastKey = &keyArray[i-1]; - float a = (time - aLastKey->mTime) / (aKey->mTime - aLastKey->mTime); + float a = (time - aLastTime) / (aTime - aLastTime); return Ogre::Quaternion::nlerp(a, aLastKey->mValue, aKey->mValue); } - - return keys.back().mValue; + else + return (--keys.end())->second.mValue; } public: @@ -497,10 +498,10 @@ public: { private: Ogre::MovableObject* mMovable; - Nif::FloatKeyList mUTrans; - Nif::FloatKeyList mVTrans; - Nif::FloatKeyList mUScale; - Nif::FloatKeyList mVScale; + Nif::FloatKeyMap mUTrans; + Nif::FloatKeyMap mVTrans; + Nif::FloatKeyMap mUScale; + Nif::FloatKeyMap mVScale; MaterialControllerManager* mMaterialControllerMgr; public: @@ -839,18 +840,19 @@ class NIFObjectLoader const Nif::NiColorData *clrdata = cl->data.getPtr(); Ogre::ParticleAffector *affector = partsys->addAffector("ColourInterpolator"); - size_t num_colors = std::min(6, clrdata->mKeyList.mKeys.size()); - for(size_t i = 0;i < num_colors;i++) + size_t num_colors = std::min(6, clrdata->mKeyMap.mKeys.size()); + unsigned int i=0; + for (Nif::Vector4KeyMap::MapType::const_iterator it = clrdata->mKeyMap.mKeys.begin(); it != clrdata->mKeyMap.mKeys.end() && i < num_colors; ++it,++i) { Ogre::ColourValue color; - color.r = clrdata->mKeyList.mKeys[i].mValue[0]; - color.g = clrdata->mKeyList.mKeys[i].mValue[1]; - color.b = clrdata->mKeyList.mKeys[i].mValue[2]; - color.a = clrdata->mKeyList.mKeys[i].mValue[3]; + color.r = it->second.mValue[0]; + color.g = it->second.mValue[1]; + color.b = it->second.mValue[2]; + color.a = it->second.mValue[3]; affector->setParameter("colour"+Ogre::StringConverter::toString(i), Ogre::StringConverter::toString(color)); affector->setParameter("time"+Ogre::StringConverter::toString(i), - Ogre::StringConverter::toString(clrdata->mKeyList.mKeys[i].mTime)); + Ogre::StringConverter::toString(it->first)); } } else if(e->recType == Nif::RC_NiParticleRotation)