mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-26 18:35:20 +00:00
Implement extrapolation mode in ControllerFunction (Bug #1871)
This commit is contained in:
parent
96d51f0bb7
commit
e938fa4a9d
@ -18,50 +18,59 @@
|
|||||||
namespace NifOsg
|
namespace NifOsg
|
||||||
{
|
{
|
||||||
|
|
||||||
ControllerFunction::ControllerFunction(const Nif::Controller *ctrl, bool deltaInput)
|
ControllerFunction::ControllerFunction(const Nif::Controller *ctrl)
|
||||||
: mDeltaInput(deltaInput)
|
: mFrequency(ctrl->frequency)
|
||||||
, mFrequency(ctrl->frequency)
|
|
||||||
, mPhase(ctrl->phase)
|
, mPhase(ctrl->phase)
|
||||||
, mStartTime(ctrl->timeStart)
|
, mStartTime(ctrl->timeStart)
|
||||||
, mStopTime(ctrl->timeStop)
|
, mStopTime(ctrl->timeStop)
|
||||||
, mDeltaCount(0.f)
|
, mExtrapolationMode(static_cast<ExtrapolationMode>((ctrl->flags&0x6) >> 1))
|
||||||
{
|
{
|
||||||
if(mDeltaInput)
|
|
||||||
mDeltaCount = mPhase;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float ControllerFunction::calculate(float value)
|
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)
|
case Cycle:
|
||||||
return 0.f;
|
{
|
||||||
|
float delta = mStopTime - mStartTime;
|
||||||
mDeltaCount += value*mFrequency;
|
if ( delta <= 0 )
|
||||||
if(mDeltaCount < mStartTime)
|
return mStartTime;
|
||||||
mDeltaCount = mStopTime - std::fmod(mStartTime - mDeltaCount,
|
float cycles = ( time - mStartTime ) / delta;
|
||||||
mStopTime - mStartTime);
|
float remainder = ( cycles - std::floor( cycles ) ) * delta;
|
||||||
mDeltaCount = std::fmod(mDeltaCount - mStartTime,
|
return mStartTime + remainder;
|
||||||
mStopTime - mStartTime) + mStartTime;
|
|
||||||
return mDeltaCount;
|
|
||||||
}
|
}
|
||||||
|
case Reverse:
|
||||||
|
{
|
||||||
|
float delta = mStopTime - mStartTime;
|
||||||
|
if ( delta <= 0 )
|
||||||
|
return mStartTime;
|
||||||
|
|
||||||
value = std::min(mStopTime, std::max(mStartTime, value+mPhase));
|
float cycles = ( time - mStartTime ) / delta;
|
||||||
return value;
|
float remainder = ( cycles - std::floor( cycles ) ) * delta;
|
||||||
|
|
||||||
|
// 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()
|
FrameTimeSource::FrameTimeSource()
|
||||||
: mLastTime(0.0)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
float FrameTimeSource::getValue(osg::NodeVisitor *nv)
|
float FrameTimeSource::getValue(osg::NodeVisitor *nv)
|
||||||
{
|
{
|
||||||
// TODO: dt could be computed globally instead of once per instance
|
return nv->getFrameStamp()->getReferenceTime();
|
||||||
double time = nv->getFrameStamp()->getReferenceTime();
|
|
||||||
float dt = static_cast<float>(time - mLastTime);
|
|
||||||
mLastTime = time;
|
|
||||||
return dt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyframeController::KeyframeController()
|
KeyframeController::KeyframeController()
|
||||||
|
@ -81,17 +81,20 @@ namespace NifOsg
|
|||||||
float mFrequency;
|
float mFrequency;
|
||||||
float mPhase;
|
float mPhase;
|
||||||
float mStartTime;
|
float mStartTime;
|
||||||
bool mDeltaInput;
|
|
||||||
float mDeltaCount;
|
|
||||||
public:
|
|
||||||
float mStopTime;
|
float mStopTime;
|
||||||
|
enum ExtrapolationMode
|
||||||
|
{
|
||||||
|
Cycle = 0,
|
||||||
|
Reverse = 1,
|
||||||
|
Constant = 2
|
||||||
|
};
|
||||||
|
ExtrapolationMode mExtrapolationMode;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ControllerFunction(const Nif::Controller *ctrl, bool deltaInput);
|
ControllerFunction(const Nif::Controller *ctrl);
|
||||||
|
|
||||||
float calculate(float value);
|
float calculate(float value);
|
||||||
};
|
};
|
||||||
typedef ControllerFunction DefaultFunction;
|
|
||||||
|
|
||||||
class ControllerSource
|
class ControllerSource
|
||||||
{
|
{
|
||||||
@ -104,8 +107,6 @@ namespace NifOsg
|
|||||||
public:
|
public:
|
||||||
FrameTimeSource();
|
FrameTimeSource();
|
||||||
virtual float getValue(osg::NodeVisitor* nv);
|
virtual float getValue(osg::NodeVisitor* nv);
|
||||||
private:
|
|
||||||
double mLastTime;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Controller
|
class Controller
|
||||||
|
@ -302,7 +302,7 @@ namespace
|
|||||||
const Nif::NiKeyframeController* keyframectrl = found->second;
|
const Nif::NiKeyframeController* keyframectrl = found->second;
|
||||||
|
|
||||||
osg::ref_ptr<NifOsg::SourcedKeyframeController> callback(new NifOsg::SourcedKeyframeController(keyframectrl->data.getPtr(), mSourceIndex));
|
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.
|
// 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.
|
// 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)
|
//if (autoPlay)
|
||||||
toSetup->mSource = boost::shared_ptr<ControllerSource>(new FrameTimeSource);
|
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,
|
osg::ref_ptr<osg::Node> handleNode(const Nif::Node* nifNode, bool createSkeleton,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user