Store NIF keys mapped by time and use lower_bound for searches

pull/241/head
scrawl 10 years ago
parent 9caff1d800
commit 9809748eba

@ -210,7 +210,7 @@ public:
class NiPosData : public Record class NiPosData : public Record
{ {
public: public:
Vector3KeyList mKeyList; Vector3KeyMap mKeyList;
void read(NIFStream *nif) void read(NIFStream *nif)
{ {
@ -221,7 +221,7 @@ public:
class NiUVData : public Record class NiUVData : public Record
{ {
public: public:
FloatKeyList mKeyList[4]; FloatKeyMap mKeyList[4];
void read(NIFStream *nif) void read(NIFStream *nif)
{ {
@ -233,7 +233,7 @@ public:
class NiFloatData : public Record class NiFloatData : public Record
{ {
public: public:
FloatKeyList mKeyList; FloatKeyMap mKeyList;
void read(NIFStream *nif) void read(NIFStream *nif)
{ {
@ -283,11 +283,11 @@ public:
class NiColorData : public Record class NiColorData : public Record
{ {
public: public:
Vector4KeyList mKeyList; Vector4KeyMap mKeyMap;
void read(NIFStream *nif) void read(NIFStream *nif)
{ {
mKeyList.read(nif); mKeyMap.read(nif);
} }
}; };
@ -388,7 +388,7 @@ public:
struct NiMorphData : public Record struct NiMorphData : public Record
{ {
struct MorphData { struct MorphData {
FloatKeyList mData; FloatKeyMap mData;
std::vector<Ogre::Vector3> mVertices; std::vector<Ogre::Vector3> mVertices;
}; };
std::vector<MorphData> mMorphs; std::vector<MorphData> mMorphs;
@ -411,11 +411,11 @@ struct NiMorphData : public Record
struct NiKeyframeData : public Record struct NiKeyframeData : public Record
{ {
QuaternionKeyList mRotations; QuaternionKeyMap mRotations;
//\FIXME mXYZ_Keys are read, but not used. //\FIXME mXYZ_Keys are read, but not used.
FloatKeyList mXYZ_Keys; FloatKeyMap mXYZ_Keys;
Vector3KeyList mTranslations; Vector3KeyMap mTranslations;
FloatKeyList mScales; FloatKeyMap mScales;
void read(NIFStream *nif) void read(NIFStream *nif)
{ {

@ -12,7 +12,6 @@ namespace Nif
template<typename T> template<typename T>
struct KeyT { struct KeyT {
float mTime;
T mValue; T mValue;
T mForwardValue; // Only for Quadratic interpolation, and never for QuaternionKeyList T mForwardValue; // Only for Quadratic interpolation, and never for QuaternionKeyList
T mBackwardValue; // Only for Quadratic interpolation, and never for QuaternionKeyList T mBackwardValue; // Only for Quadratic interpolation, and never for QuaternionKeyList
@ -26,8 +25,8 @@ typedef KeyT<Ogre::Vector4> Vector4Key;
typedef KeyT<Ogre::Quaternion> QuaternionKey; typedef KeyT<Ogre::Quaternion> QuaternionKey;
template<typename T, T (NIFStream::*getValue)()> template<typename T, T (NIFStream::*getValue)()>
struct KeyListT { struct KeyMapT {
typedef std::vector< KeyT<T> > VecType; typedef std::map< float, KeyT<T> > MapType;
static const unsigned int sLinearInterpolation = 1; static const unsigned int sLinearInterpolation = 1;
static const unsigned int sQuadraticInterpolation = 2; static const unsigned int sQuadraticInterpolation = 2;
@ -35,9 +34,9 @@ struct KeyListT {
static const unsigned int sXYZInterpolation = 4; static const unsigned int sXYZInterpolation = 4;
unsigned int mInterpolationType; 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) //Read in a KeyGroup (see http://niftools.sourceforge.net/doc/nif/NiKeyframeData.html)
void read(NIFStream *nif, bool force=false) void read(NIFStream *nif, bool force=false)
@ -63,24 +62,27 @@ struct KeyListT {
{ {
for(size_t i = 0;i < count;i++) for(size_t i = 0;i < count;i++)
{ {
readTimeAndValue(nifReference, key); float time = nif->getFloat();
mKeys.push_back(key); readValue(nifReference, key);
mKeys[time] = key;
} }
} }
else if(mInterpolationType == sQuadraticInterpolation) else if(mInterpolationType == sQuadraticInterpolation)
{ {
for(size_t i = 0;i < count;i++) for(size_t i = 0;i < count;i++)
{ {
float time = nif->getFloat();
readQuadratic(nifReference, key); readQuadratic(nifReference, key);
mKeys.push_back(key); mKeys[time] = key;
} }
} }
else if(mInterpolationType == sTBCInterpolation) else if(mInterpolationType == sTBCInterpolation)
{ {
for(size_t i = 0;i < count;i++) for(size_t i = 0;i < count;i++)
{ {
float time = nif->getFloat();
readTBC(nifReference, key); readTBC(nifReference, key);
mKeys.push_back(key); mKeys[time] = key;
} }
} }
//XYZ keys aren't actually read here. //XYZ keys aren't actually read here.
@ -104,37 +106,36 @@ struct KeyListT {
} }
private: private:
static void readTimeAndValue(NIFStream &nif, KeyT<T> &key) static void readValue(NIFStream &nif, KeyT<T> &key)
{ {
key.mTime = nif.getFloat();
key.mValue = (nif.*getValue)(); key.mValue = (nif.*getValue)();
} }
static void readQuadratic(NIFStream &nif, KeyT<Ogre::Quaternion> &key) static void readQuadratic(NIFStream &nif, KeyT<Ogre::Quaternion> &key)
{ {
readTimeAndValue(nif, key); readValue(nif, key);
} }
template <typename U> template <typename U>
static void readQuadratic(NIFStream &nif, KeyT<U> &key) static void readQuadratic(NIFStream &nif, KeyT<U> &key)
{ {
readTimeAndValue(nif, key); readValue(nif, key);
key.mForwardValue = (nif.*getValue)(); key.mForwardValue = (nif.*getValue)();
key.mBackwardValue = (nif.*getValue)(); key.mBackwardValue = (nif.*getValue)();
} }
static void readTBC(NIFStream &nif, KeyT<T> &key) static void readTBC(NIFStream &nif, KeyT<T> &key)
{ {
readTimeAndValue(nif, key); readValue(nif, key);
key.mTension = nif.getFloat(); key.mTension = nif.getFloat();
key.mBias = nif.getFloat(); key.mBias = nif.getFloat();
key.mContinuity = nif.getFloat(); key.mContinuity = nif.getFloat();
} }
}; };
typedef KeyListT<float,&NIFStream::getFloat> FloatKeyList; typedef KeyMapT<float,&NIFStream::getFloat> FloatKeyMap;
typedef KeyListT<Ogre::Vector3,&NIFStream::getVector3> Vector3KeyList; typedef KeyMapT<Ogre::Vector3,&NIFStream::getVector3> Vector3KeyMap;
typedef KeyListT<Ogre::Vector4,&NIFStream::getVector4> Vector4KeyList; typedef KeyMapT<Ogre::Vector4,&NIFStream::getVector4> Vector4KeyMap;
typedef KeyListT<Ogre::Quaternion,&NIFStream::getQuaternion> QuaternionKeyList; typedef KeyMapT<Ogre::Quaternion,&NIFStream::getQuaternion> QuaternionKeyMap;
} // Namespace } // Namespace
#endif //#ifndef OPENMW_COMPONENTS_NIF_NIFKEY_HPP #endif //#ifndef OPENMW_COMPONENTS_NIF_NIFKEY_HPP

@ -2,6 +2,7 @@
#define COMPONENTS_NIFOGRE_CONTROLLER_H #define COMPONENTS_NIFOGRE_CONTROLLER_H
#include <components/nif/niffile.hpp> #include <components/nif/niffile.hpp>
#include <components/nif/nifkey.hpp>
#include <OgreController.h> #include <OgreController.h>
namespace NifOgre namespace NifOgre
@ -10,53 +11,55 @@ namespace NifOgre
class ValueInterpolator class ValueInterpolator
{ {
protected: 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) if (keys.size() == 0)
return def; return def;
if(time <= keys.front().mTime) if(time <= keys.begin()->first)
return keys.front().mValue; return keys.begin()->second.mValue;
const Nif::FloatKey* keyArray = keys.data(); Nif::FloatKeyMap::MapType::const_iterator it = keys.lower_bound(time);
size_t size = keys.size(); if (it != keys.end())
for (size_t i = 1; i < size; ++i)
{ {
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) Nif::FloatKeyMap::MapType::const_iterator last = --it;
continue; float aLastTime = last->first;
const Nif::FloatKey* aLastKey = &last->second;
const Nif::FloatKey* aLastKey = &keyArray[i-1]; float a = (time - aLastTime) / (aTime - aLastTime);
float a = (time - aLastKey->mTime) / (aKey->mTime - aLastKey->mTime);
return aLastKey->mValue + ((aKey->mValue - aLastKey->mValue) * a); return aLastKey->mValue + ((aKey->mValue - aLastKey->mValue) * a);
} }
else
return keys.back().mValue; 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) if(time <= keys.begin()->first)
return keys.front().mValue; return keys.begin()->second.mValue;
const Nif::Vector3Key* keyArray = keys.data(); Nif::Vector3KeyMap::MapType::const_iterator it = keys.lower_bound(time);
size_t size = keys.size(); if (it != keys.end())
for (size_t i = 1; i < size; ++i)
{ {
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) Nif::Vector3KeyMap::MapType::const_iterator last = --it;
continue; float aLastTime = last->first;
const Nif::Vector3Key* aLastKey = &last->second;
const Nif::Vector3Key* aLastKey = &keyArray[i-1]; float a = (time - aLastTime) / (aTime - aLastTime);
float a = (time - aLastKey->mTime) / (aKey->mTime - aLastKey->mTime);
return aLastKey->mValue + ((aKey->mValue - aLastKey->mValue) * a); return aLastKey->mValue + ((aKey->mValue - aLastKey->mValue) * a);
} }
else
return keys.back().mValue; return (--keys.end())->second.mValue;
} }
}; };

@ -237,7 +237,7 @@ public:
{ {
private: private:
Ogre::MovableObject* mMovable; Ogre::MovableObject* mMovable;
Nif::FloatKeyList mData; Nif::FloatKeyMap mData;
MaterialControllerManager* mMaterialControllerMgr; MaterialControllerManager* mMaterialControllerMgr;
public: public:
@ -284,7 +284,7 @@ public:
{ {
private: private:
Ogre::MovableObject* mMovable; Ogre::MovableObject* mMovable;
Nif::Vector3KeyList mData; Nif::Vector3KeyMap mData;
MaterialControllerManager* mMaterialControllerMgr; MaterialControllerManager* mMaterialControllerMgr;
public: public:
@ -409,34 +409,35 @@ public:
class Value : public NodeTargetValue<Ogre::Real>, public ValueInterpolator class Value : public NodeTargetValue<Ogre::Real>, public ValueInterpolator
{ {
private: private:
const Nif::QuaternionKeyList* mRotations; const Nif::QuaternionKeyMap* mRotations;
const Nif::Vector3KeyList* mTranslations; const Nif::Vector3KeyMap* mTranslations;
const Nif::FloatKeyList* mScales; const Nif::FloatKeyMap* mScales;
Nif::NIFFilePtr mNif; // Hold a SharedPtr to make sure key lists stay valid Nif::NIFFilePtr mNif; // Hold a SharedPtr to make sure key lists stay valid
using ValueInterpolator::interpKey; 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) if(time <= keys.begin()->first)
return keys.front().mValue; return keys.begin()->second.mValue;
const Nif::QuaternionKey* keyArray = keys.data(); Nif::QuaternionKeyMap::MapType::const_iterator it = keys.lower_bound(time);
size_t size = keys.size(); if (it != keys.end())
for (size_t i = 1; i < size; ++i)
{ {
const Nif::QuaternionKey* aKey = &keyArray[i]; float aTime = it->first;
const Nif::QuaternionKey* aKey = &it->second;
if(aKey->mTime < time) assert (it != keys.begin()); // Shouldn't happen, was checked at beginning of this function
continue;
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 - aLastTime) / (aTime - aLastTime);
float a = (time - aLastKey->mTime) / (aKey->mTime - aLastKey->mTime);
return Ogre::Quaternion::nlerp(a, aLastKey->mValue, aKey->mValue); return Ogre::Quaternion::nlerp(a, aLastKey->mValue, aKey->mValue);
} }
else
return keys.back().mValue; return (--keys.end())->second.mValue;
} }
public: public:
@ -497,10 +498,10 @@ public:
{ {
private: private:
Ogre::MovableObject* mMovable; Ogre::MovableObject* mMovable;
Nif::FloatKeyList mUTrans; Nif::FloatKeyMap mUTrans;
Nif::FloatKeyList mVTrans; Nif::FloatKeyMap mVTrans;
Nif::FloatKeyList mUScale; Nif::FloatKeyMap mUScale;
Nif::FloatKeyList mVScale; Nif::FloatKeyMap mVScale;
MaterialControllerManager* mMaterialControllerMgr; MaterialControllerManager* mMaterialControllerMgr;
public: public:
@ -839,18 +840,19 @@ class NIFObjectLoader
const Nif::NiColorData *clrdata = cl->data.getPtr(); const Nif::NiColorData *clrdata = cl->data.getPtr();
Ogre::ParticleAffector *affector = partsys->addAffector("ColourInterpolator"); Ogre::ParticleAffector *affector = partsys->addAffector("ColourInterpolator");
size_t num_colors = std::min<size_t>(6, clrdata->mKeyList.mKeys.size()); size_t num_colors = std::min<size_t>(6, clrdata->mKeyMap.mKeys.size());
for(size_t i = 0;i < num_colors;i++) 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; Ogre::ColourValue color;
color.r = clrdata->mKeyList.mKeys[i].mValue[0]; color.r = it->second.mValue[0];
color.g = clrdata->mKeyList.mKeys[i].mValue[1]; color.g = it->second.mValue[1];
color.b = clrdata->mKeyList.mKeys[i].mValue[2]; color.b = it->second.mValue[2];
color.a = clrdata->mKeyList.mKeys[i].mValue[3]; color.a = it->second.mValue[3];
affector->setParameter("colour"+Ogre::StringConverter::toString(i), affector->setParameter("colour"+Ogre::StringConverter::toString(i),
Ogre::StringConverter::toString(color)); Ogre::StringConverter::toString(color));
affector->setParameter("time"+Ogre::StringConverter::toString(i), 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) else if(e->recType == Nif::RC_NiParticleRotation)

Loading…
Cancel
Save