Use template function for interpolation

pull/638/head
scrawl 10 years ago
parent 00ab474188
commit ab3c28eb96

@ -16,57 +16,6 @@
namespace NifOsg namespace NifOsg
{ {
float ValueInterpolator::interpKey(const Nif::FloatKeyMap::MapType &keys, float time, float def) const
{
if (keys.size() == 0)
return def;
if(time <= keys.begin()->first)
return keys.begin()->second.mValue;
Nif::FloatKeyMap::MapType::const_iterator it = keys.lower_bound(time);
if (it != keys.end())
{
float aTime = it->first;
const Nif::FloatKey* aKey = &it->second;
assert (it != keys.begin()); // Shouldn't happen, was checked at beginning of this function
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);
}
else
return keys.rbegin()->second.mValue;
}
osg::Vec3f ValueInterpolator::interpKey(const Nif::Vector3KeyMap::MapType &keys, float time) const
{
if(time <= keys.begin()->first)
return keys.begin()->second.mValue;
Nif::Vector3KeyMap::MapType::const_iterator it = keys.lower_bound(time);
if (it != keys.end())
{
float aTime = it->first;
const Nif::KeyT<osg::Vec3f>* aKey = &it->second;
assert (it != keys.begin()); // Shouldn't happen, was checked at beginning of this function
Nif::Vector3KeyMap::MapType::const_iterator last = --it;
float aLastTime = last->first;
const Nif::KeyT<osg::Vec3f>* aLastKey = &last->second;
float a = (time - aLastTime) / (aTime - aLastTime);
return aLastKey->mValue + ((aKey->mValue - aLastKey->mValue) * a);
}
else
return keys.rbegin()->second.mValue;
}
ControllerFunction::ControllerFunction(const Nif::Controller *ctrl, bool deltaInput) ControllerFunction::ControllerFunction(const Nif::Controller *ctrl, bool deltaInput)
: mDeltaInput(deltaInput) : mDeltaInput(deltaInput)
, mFrequency(ctrl->frequency) , mFrequency(ctrl->frequency)

@ -42,9 +42,33 @@ namespace NifOsg
class ValueInterpolator class ValueInterpolator
{ {
protected: protected:
float interpKey(const Nif::FloatKeyMap::MapType &keys, float time, float def=0.f) const; template <typename T>
T interpKey (const std::map< float, Nif::KeyT<T> >& keys, float time, T defaultValue = T()) const
{
if (keys.size() == 0)
return defaultValue;
if(time <= keys.begin()->first)
return keys.begin()->second.mValue;
typename std::map< float, Nif::KeyT<T> >::const_iterator it = keys.lower_bound(time);
if (it != keys.end())
{
float aTime = it->first;
const Nif::KeyT<T>* aKey = &it->second;
osg::Vec3f interpKey(const Nif::Vector3KeyMap::MapType &keys, float time) const; assert (it != keys.begin()); // Shouldn't happen, was checked at beginning of this function
typename std::map< float, Nif::KeyT<T> >::const_iterator last = --it;
float aLastTime = last->first;
const Nif::KeyT<T>* aLastKey = &last->second;
float a = (time - aLastTime) / (aTime - aLastTime);
return aLastKey->mValue + ((aKey->mValue - aLastKey->mValue) * a);
}
else
return keys.rbegin()->second.mValue;
}
}; };
// FIXME: Should not be here. We might also want to use this for non-NIF model formats // FIXME: Should not be here. We might also want to use this for non-NIF model formats

@ -45,11 +45,10 @@ ParticleShooter::ParticleShooter(const osgParticle::Shooter &copy, const osg::Co
void ParticleShooter::shoot(osgParticle::Particle *particle) const void ParticleShooter::shoot(osgParticle::Particle *particle) const
{ {
// NOTE: We do not use mDirection/mAngle for the initial direction.
float hdir = mHorizontalDir + mHorizontalAngle * (2.f * (std::rand() / static_cast<double>(RAND_MAX)) - 1.f); float hdir = mHorizontalDir + mHorizontalAngle * (2.f * (std::rand() / static_cast<double>(RAND_MAX)) - 1.f);
float vdir = mVerticalDir + mVerticalAngle * (2.f * (std::rand() / static_cast<double>(RAND_MAX)) - 1.f); float vdir = mVerticalDir + mVerticalAngle * (2.f * (std::rand() / static_cast<double>(RAND_MAX)) - 1.f);
osg::Vec3f dir = osg::Quat(hdir, osg::Vec3f(0,0,1)) * osg::Quat(vdir, osg::Vec3f(1,0,0)) float vdir2 = mVerticalDir + mVerticalAngle * (2.f * (std::rand() / static_cast<double>(RAND_MAX)) - 1.f);
// ^ Vec3f(0,1,0) according to nifskope, TODO: test in mw osg::Vec3f dir = osg::Quat(hdir, osg::Vec3f(0,0,1)) * osg::Quat(vdir, osg::Vec3f(0,1,0)) * osg::Quat(vdir2, osg::Vec3f(1,0,0))
* osg::Vec3f(0,0,1); * osg::Vec3f(0,0,1);
float vel = mMinSpeed + (mMaxSpeed - mMinSpeed) * std::rand() / static_cast<float>(RAND_MAX); float vel = mMinSpeed + (mMaxSpeed - mMinSpeed) * std::rand() / static_cast<float>(RAND_MAX);
@ -111,34 +110,10 @@ ParticleColorAffector::ParticleColorAffector(const ParticleColorAffector &copy,
*this = copy; *this = copy;
} }
osg::Vec4f ParticleColorAffector::interpolate(const float time, const Nif::Vector4KeyMap::MapType &keys)
{
if(time <= keys.begin()->first)
return keys.begin()->second.mValue;
Nif::Vector4KeyMap::MapType::const_iterator it = keys.lower_bound(time);
if (it != keys.end())
{
float aTime = it->first;
const Nif::KeyT<osg::Vec4f>* aKey = &it->second;
assert (it != keys.begin()); // Shouldn't happen, was checked at beginning of this function
Nif::Vector4KeyMap::MapType::const_iterator last = --it;
float aLastTime = last->first;
const Nif::KeyT<osg::Vec4f>* aLastKey = &last->second;
float a = (time - aLastTime) / (aTime - aLastTime);
return aLastKey->mValue + ((aKey->mValue - aLastKey->mValue) * a);
}
else
return keys.rbegin()->second.mValue;
}
void ParticleColorAffector::operate(osgParticle::Particle* particle, double /* dt */) void ParticleColorAffector::operate(osgParticle::Particle* particle, double /* dt */)
{ {
float time = static_cast<float>(particle->getAge()/particle->getLifeTime()); float time = static_cast<float>(particle->getAge()/particle->getLifeTime());
osg::Vec4f color = interpolate(time, mData.mKeyMap.mKeys); osg::Vec4f color = interpKey(mData.mKeyMap.mKeys, time, osg::Vec4f(1,1,1,1));
particle->setColorRange(osgParticle::rangev4(color, color)); particle->setColorRange(osgParticle::rangev4(color, color));
} }

@ -10,6 +10,8 @@
#include <components/nif/nifkey.hpp> #include <components/nif/nifkey.hpp>
#include <components/nif/data.hpp> #include <components/nif/data.hpp>
#include "controller.hpp" // ValueInterpolator
namespace Nif namespace Nif
{ {
class NiGravity; class NiGravity;
@ -90,7 +92,7 @@ namespace NifOsg
float mCachedDefaultSize; float mCachedDefaultSize;
}; };
class ParticleColorAffector : public osgParticle::Operator class ParticleColorAffector : public osgParticle::Operator, public ValueInterpolator
{ {
public: public:
ParticleColorAffector(const Nif::NiColorData* clrdata); ParticleColorAffector(const Nif::NiColorData* clrdata);

Loading…
Cancel
Save