You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openmw-tes3mp/components/nifosg/controller.hpp

286 lines
7.6 KiB
C++

#ifndef COMPONENTS_NIFOSG_CONTROLLER_H
#define COMPONENTS_NIFOSG_CONTROLLER_H
#include <components/nif/niffile.hpp>
#include <components/nif/nifkey.hpp>
#include <components/nif/controller.hpp>
#include <components/nif/data.hpp>
#include <components/nifcache/nifcache.hpp>
#include <boost/shared_ptr.hpp>
#include <set> //UVController
// FlipController
#include <osg/Image>
#include <osg/ref_ptr>
#include <osg/Timer>
namespace osg
{
class Node;
class StateSet;
}
namespace osgParticle
{
class Emitter;
}
namespace osgAnimation
{
class MorphGeometry;
}
namespace NifOsg
{
// FIXME: Should not be here. We might also want to use this for non-NIF model formats
class ValueInterpolator
{
protected:
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;
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
class ControllerFunction
{
private:
float mFrequency;
float mPhase;
float mStartTime;
bool mDeltaInput;
float mDeltaCount;
public:
float mStopTime;
public:
ControllerFunction(const Nif::Controller *ctrl, bool deltaInput);
float calculate(float value);
};
typedef ControllerFunction DefaultFunction;
class ControllerSource
{
public:
virtual float getValue() const = 0;
};
// FIXME: Should return a dt instead of time
class FrameTimeSource : public ControllerSource
{
public:
virtual float getValue() const
{
return mTimer.time_s();
}
private:
osg::Timer mTimer;
};
class ControllerValue
{
public:
virtual void setValue(float value) = 0;
};
class Controller
{
public:
Controller (boost::shared_ptr<ControllerSource> src, boost::shared_ptr<ControllerValue> dest,
boost::shared_ptr<ControllerFunction> function);
virtual void update();
boost::shared_ptr<ControllerSource> mSource;
boost::shared_ptr<ControllerValue> mDestValue;
// The source value gets passed through this function before it's passed on to the DestValue.
boost::shared_ptr<ControllerFunction> mFunction;
};
// FIXME: Should be with other general extensions.
class NodeTargetValue : public ControllerValue
{
protected:
// TODO: get rid of target pointers, which are incompatible with a copy constructor we will need later
// instead, controllers can be a Node added as child of their target
osg::Node *mNode;
public:
NodeTargetValue(osg::Node *target) : mNode(target)
{ }
virtual osg::Vec3f getTranslation(float value) const = 0;
osg::Node *getNode() const
{ return mNode; }
};
class GeomMorpherControllerValue : public ControllerValue, public ValueInterpolator
{
public:
// FIXME: don't copy the morph data?
GeomMorpherControllerValue(osgAnimation::MorphGeometry* geom, const Nif::NiMorphData *data);
virtual void setValue(float time);
private:
osgAnimation::MorphGeometry* mGeom;
std::vector<Nif::NiMorphData::MorphData> mMorphs;
};
class KeyframeControllerValue : public NodeTargetValue, public ValueInterpolator
{
private:
const Nif::QuaternionKeyMap* mRotations;
const Nif::FloatKeyMap* mXRotations;
const Nif::FloatKeyMap* mYRotations;
const Nif::FloatKeyMap* mZRotations;
const Nif::Vector3KeyMap* mTranslations;
const Nif::FloatKeyMap* mScales;
Nif::NIFFilePtr mNif; // Hold a SharedPtr to make sure key lists stay valid
osg::Quat mInitialQuat;
float mInitialScale;
using ValueInterpolator::interpKey;
osg::Quat interpKey(const Nif::QuaternionKeyMap::MapType &keys, float time);
osg::Quat getXYZRotation(float time) const;
public:
/// @note The NiKeyFrameData must be valid as long as this KeyframeController exists.
KeyframeControllerValue(osg::Node *target, const Nif::NIFFilePtr& nif, const Nif::NiKeyframeData *data,
osg::Quat initialQuat, float initialScale);
virtual osg::Vec3f getTranslation(float time) const;
virtual void setValue(float time);
};
class UVControllerValue : public ControllerValue, ValueInterpolator
{
private:
osg::StateSet* mStateSet;
Nif::FloatKeyMap mUTrans;
Nif::FloatKeyMap mVTrans;
Nif::FloatKeyMap mUScale;
Nif::FloatKeyMap mVScale;
std::set<int> mTextureUnits;
public:
UVControllerValue(osg::StateSet* target, const Nif::NiUVData *data, std::set<int> textureUnits);
virtual void setValue(float value);
};
class VisControllerValue : public NodeTargetValue
{
private:
std::vector<Nif::NiVisData::VisData> mData;
bool calculate(float time) const;
public:
VisControllerValue(osg::Node *target, const Nif::NiVisData *data)
: NodeTargetValue(target)
, mData(data->mVis)
{ }
virtual osg::Vec3f getTranslation(float time) const
{ return osg::Vec3f(); }
virtual void setValue(float time);
};
class AlphaControllerValue : public ControllerValue, public ValueInterpolator
{
private:
osg::StateSet* mTarget;
Nif::FloatKeyMap mData;
public:
AlphaControllerValue(osg::StateSet* target, const Nif::NiFloatData *data);
virtual void setValue(float time);
};
class MaterialColorControllerValue : public ControllerValue, public ValueInterpolator
{
private:
osg::StateSet* mTarget;
Nif::Vector3KeyMap mData;
public:
MaterialColorControllerValue(osg::StateSet* target, const Nif::NiPosData *data);
virtual void setValue(float time);
};
// untested
class FlipControllerValue : public ControllerValue
{
private:
osg::StateSet* mTarget;
int mTexSlot;
float mDelta;
std::vector<osg::ref_ptr<osg::Image> > mTextures;
public:
FlipControllerValue(osg::StateSet* target, const Nif::NiFlipController* ctrl, std::vector<osg::ref_ptr<osg::Image> > textures);
virtual void setValue(float time);
};
class ParticleSystemControllerValue : public ControllerValue
{
public:
ParticleSystemControllerValue(osgParticle::Emitter* emitter, const Nif::NiParticleSystemController* ctrl);
virtual void setValue(float time);
private:
osgParticle::Emitter* mEmitter;
float mEmitStart;
float mEmitStop;
};
}
#endif