Implement extrapolation mode in ControllerFunction (Bug #1871)

c++11
scrawl 10 years ago
parent 96d51f0bb7
commit e938fa4a9d

@ -18,50 +18,59 @@
namespace NifOsg
{
ControllerFunction::ControllerFunction(const Nif::Controller *ctrl, bool deltaInput)
: mDeltaInput(deltaInput)
, mFrequency(ctrl->frequency)
ControllerFunction::ControllerFunction(const Nif::Controller *ctrl)
: mFrequency(ctrl->frequency)
, mPhase(ctrl->phase)
, mStartTime(ctrl->timeStart)
, mStopTime(ctrl->timeStop)
, mDeltaCount(0.f)
, mExtrapolationMode(static_cast<ExtrapolationMode>((ctrl->flags&0x6) >> 1))
{
if(mDeltaInput)
mDeltaCount = mPhase;
}
float ControllerFunction::calculate(float value)
{
if(mDeltaInput)
float time = mFrequency * value + mPhase;
if (time >= mStartTime && time <= mStopTime)
return time;
switch (mExtrapolationMode)
{
if (mStopTime - mStartTime == 0.f)
return 0.f;
mDeltaCount += value*mFrequency;
if(mDeltaCount < mStartTime)
mDeltaCount = mStopTime - std::fmod(mStartTime - mDeltaCount,
mStopTime - mStartTime);
mDeltaCount = std::fmod(mDeltaCount - mStartTime,
mStopTime - mStartTime) + mStartTime;
return mDeltaCount;
case Cycle:
{
float delta = mStopTime - mStartTime;
if ( delta <= 0 )
return mStartTime;
float cycles = ( time - mStartTime ) / delta;
float remainder = ( cycles - std::floor( cycles ) ) * delta;
return mStartTime + remainder;
}
case Reverse:
{
float delta = mStopTime - mStartTime;
if ( delta <= 0 )
return mStartTime;
float cycles = ( time - mStartTime ) / delta;
float remainder = ( cycles - std::floor( cycles ) ) * delta;
value = std::min(mStopTime, std::max(mStartTime, value+mPhase));
return value;
// Even number of cycles?
if ( ( static_cast<int>(std::fabs( std::floor( cycles ) )) % 2 ) == 0 )
return mStartTime + remainder;
return mStopTime - remainder;
}
case Constant:
default:
return std::min(mStopTime, std::max(mStartTime, time));
}
}
FrameTimeSource::FrameTimeSource()
: mLastTime(0.0)
{
}
float FrameTimeSource::getValue(osg::NodeVisitor *nv)
{
// TODO: dt could be computed globally instead of once per instance
double time = nv->getFrameStamp()->getReferenceTime();
float dt = static_cast<float>(time - mLastTime);
mLastTime = time;
return dt;
return nv->getFrameStamp()->getReferenceTime();
}
KeyframeController::KeyframeController()

@ -81,17 +81,20 @@ namespace NifOsg
float mFrequency;
float mPhase;
float mStartTime;
bool mDeltaInput;
float mDeltaCount;
public:
float mStopTime;
enum ExtrapolationMode
{
Cycle = 0,
Reverse = 1,
Constant = 2
};
ExtrapolationMode mExtrapolationMode;
public:
ControllerFunction(const Nif::Controller *ctrl, bool deltaInput);
ControllerFunction(const Nif::Controller *ctrl);
float calculate(float value);
};
typedef ControllerFunction DefaultFunction;
class ControllerSource
{
@ -104,8 +107,6 @@ namespace NifOsg
public:
FrameTimeSource();
virtual float getValue(osg::NodeVisitor* nv);
private:
double mLastTime;
};
class Controller

@ -302,7 +302,7 @@ namespace
const Nif::NiKeyframeController* keyframectrl = found->second;
osg::ref_ptr<NifOsg::SourcedKeyframeController> callback(new NifOsg::SourcedKeyframeController(keyframectrl->data.getPtr(), mSourceIndex));
callback->mFunction = boost::shared_ptr<NifOsg::ControllerFunction>(new NifOsg::ControllerFunction(keyframectrl, false));
callback->mFunction = boost::shared_ptr<NifOsg::ControllerFunction>(new NifOsg::ControllerFunction(keyframectrl));
// Insert in front of the callback list, to make sure UpdateBone is last.
// The order of SourcedKeyframeControllers doesn't matter since only one of them should be enabled at a time.
@ -490,7 +490,7 @@ namespace NifOsg
//if (autoPlay)
toSetup->mSource = boost::shared_ptr<ControllerSource>(new FrameTimeSource);
toSetup->mFunction = boost::shared_ptr<ControllerFunction>(new ControllerFunction(ctrl, 1 /*autoPlay*/));
toSetup->mFunction = boost::shared_ptr<ControllerFunction>(new ControllerFunction(ctrl));
}
osg::ref_ptr<osg::Node> handleNode(const Nif::Node* nifNode, bool createSkeleton,

Loading…
Cancel
Save