mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 21:53:51 +00:00
Implement extrapolation mode in ControllerFunction (Bug #1871)
This commit is contained in:
parent
96d51f0bb7
commit
e938fa4a9d
3 changed files with 44 additions and 34 deletions
|
@ -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;
|
||||
|
||||
value = std::min(mStopTime, std::max(mStartTime, value+mPhase));
|
||||
return value;
|
||||
float cycles = ( time - mStartTime ) / delta;
|
||||
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()
|
||||
: 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…
Reference in a new issue