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
{
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<Ogre::Vector3> mVertices;
};
std::vector<MorphData> 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)
{

@ -12,7 +12,6 @@ namespace Nif
template<typename T>
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<Ogre::Vector4> Vector4Key;
typedef KeyT<Ogre::Quaternion> QuaternionKey;
template<typename T, T (NIFStream::*getValue)()>
struct KeyListT {
typedef std::vector< KeyT<T> > VecType;
struct KeyMapT {
typedef std::map< float, KeyT<T> > 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<T> &key)
static void readValue(NIFStream &nif, KeyT<T> &key)
{
key.mTime = nif.getFloat();
key.mValue = (nif.*getValue)();
}
static void readQuadratic(NIFStream &nif, KeyT<Ogre::Quaternion> &key)
{
readTimeAndValue(nif, key);
readValue(nif, key);
}
template <typename U>
static void readQuadratic(NIFStream &nif, KeyT<U> &key)
{
readTimeAndValue(nif, key);
readValue(nif, key);
key.mForwardValue = (nif.*getValue)();
key.mBackwardValue = (nif.*getValue)();
}
static void readTBC(NIFStream &nif, KeyT<T> &key)
{
readTimeAndValue(nif, key);
readValue(nif, key);
key.mTension = nif.getFloat();
key.mBias = nif.getFloat();
key.mContinuity = nif.getFloat();
}
};
typedef KeyListT<float,&NIFStream::getFloat> FloatKeyList;
typedef KeyListT<Ogre::Vector3,&NIFStream::getVector3> Vector3KeyList;
typedef KeyListT<Ogre::Vector4,&NIFStream::getVector4> Vector4KeyList;
typedef KeyListT<Ogre::Quaternion,&NIFStream::getQuaternion> QuaternionKeyList;
typedef KeyMapT<float,&NIFStream::getFloat> FloatKeyMap;
typedef KeyMapT<Ogre::Vector3,&NIFStream::getVector3> Vector3KeyMap;
typedef KeyMapT<Ogre::Vector4,&NIFStream::getVector4> Vector4KeyMap;
typedef KeyMapT<Ogre::Quaternion,&NIFStream::getQuaternion> QuaternionKeyMap;
} // Namespace
#endif //#ifndef OPENMW_COMPONENTS_NIF_NIFKEY_HPP
#endif //#ifndef OPENMW_COMPONENTS_NIF_NIFKEY_HPP

@ -2,6 +2,7 @@
#define COMPONENTS_NIFOGRE_CONTROLLER_H
#include <components/nif/niffile.hpp>
#include <components/nif/nifkey.hpp>
#include <OgreController.h>
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;
}
};

@ -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<Ogre::Real>, 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<size_t>(6, clrdata->mKeyList.mKeys.size());
for(size_t i = 0;i < num_colors;i++)
size_t num_colors = std::min<size_t>(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)

Loading…
Cancel
Save