mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-05 15:55:45 +00:00
Store NIF keys mapped by time and use lower_bound for searches
This commit is contained in:
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;
|
||||
|
||||
if(aKey->mTime < time)
|
||||
continue;
|
||||
assert (it != keys.begin()); // Shouldn't happen, was checked at beginning of this function
|
||||
|
||||
const Nif::FloatKey* aLastKey = &keyArray[i-1];
|
||||
float a = (time - aLastKey->mTime) / (aKey->mTime - aLastKey->mTime);
|
||||
Nif::FloatKeyMap::MapType::const_iterator last = --it;
|
||||
float aLastTime = last->first;
|
||||
const Nif::FloatKey* aLastKey = &last->second;
|
||||
|
||||
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;
|
||||
|
||||
if(aKey->mTime < time)
|
||||
continue;
|
||||
assert (it != keys.begin()); // Shouldn't happen, was checked at beginning of this function
|
||||
|
||||
const Nif::Vector3Key* aLastKey = &keyArray[i-1];
|
||||
float a = (time - aLastKey->mTime) / (aKey->mTime - aLastKey->mTime);
|
||||
Nif::Vector3KeyMap::MapType::const_iterator last = --it;
|
||||
float aLastTime = last->first;
|
||||
const Nif::Vector3Key* aLastKey = &last->second;
|
||||
|
||||
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
|
||||
|
||||
const Nif::QuaternionKey* aLastKey = &keyArray[i-1];
|
||||
float a = (time - aLastKey->mTime) / (aKey->mTime - aLastKey->mTime);
|
||||
Nif::QuaternionKeyMap::MapType::const_iterator last = --it;
|
||||
float aLastTime = last->first;
|
||||
const Nif::QuaternionKey* aLastKey = &last->second;
|
||||
|
||||
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…
Reference in New Issue
Block a user