1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-30 03:32:36 +00:00
OpenMW/apps/openmw/mwrender/animblendcontroller.hpp
2024-07-25 02:28:07 +03:00

143 lines
4.7 KiB
C++

#ifndef OPENMW_MWRENDER_ANIMBLENDCONTROLLER_H
#define OPENMW_MWRENDER_ANIMBLENDCONTROLLER_H
#include <map>
#include <optional>
#include <string>
#include <unordered_map>
#include <osgAnimation/Bone>
#include <components/nifosg/matrixtransform.hpp>
#include <components/sceneutil/animblendrules.hpp>
#include <components/sceneutil/controller.hpp>
#include <components/sceneutil/keyframe.hpp>
#include <components/sceneutil/nodecallback.hpp>
namespace MWRender
{
typedef float (*EasingFn)(float);
struct AnimBlendStateData
{
std::string mGroupname;
std::string mStartKey;
};
class AnimBlendController : public SceneUtil::Controller
{
public:
AnimBlendController(const osg::ref_ptr<SceneUtil::KeyframeController>& keyframeTrack,
const AnimBlendStateData& animState, const osg::ref_ptr<const SceneUtil::AnimBlendRules>& blendRules);
AnimBlendController();
void setKeyframeTrack(const osg::ref_ptr<SceneUtil::KeyframeController>& kft,
const AnimBlendStateData& animState, const osg::ref_ptr<const SceneUtil::AnimBlendRules>& blendRules);
bool getBlendTrigger() const { return mBlendTrigger; }
protected:
EasingFn mEasingFn;
float mBlendDuration = 0.0f;
float mBlendStartTime = 0.0f;
float mTimeFactor = 0.0f;
float mInterpFactor = 0.0f;
bool mBlendTrigger = false;
bool mInterpActive = false;
AnimBlendStateData mAnimState;
osg::ref_ptr<const SceneUtil::AnimBlendRules> mAnimBlendRules;
osg::ref_ptr<SceneUtil::KeyframeController> mKeyframeTrack;
std::unordered_map<osg::Node*, osg::Matrixf> mBlendBoneTransforms;
inline void calculateInterpFactor(float time);
};
class NifAnimBlendController : public SceneUtil::NodeCallback<NifAnimBlendController, NifOsg::MatrixTransform*>,
public AnimBlendController
{
public:
NifAnimBlendController(const osg::ref_ptr<SceneUtil::KeyframeController>& keyframeTrack,
const AnimBlendStateData& animState, const osg::ref_ptr<const SceneUtil::AnimBlendRules>& blendRules);
NifAnimBlendController() {}
NifAnimBlendController(const NifAnimBlendController& other, const osg::CopyOp&)
: NifAnimBlendController(other.mKeyframeTrack, other.mAnimState, other.mAnimBlendRules)
{
}
META_Object(MWRender, NifAnimBlendController)
void operator()(NifOsg::MatrixTransform* node, osg::NodeVisitor* nv);
osg::Callback* getAsCallback() { return this; }
private:
osg::Quat mBlendStartRot;
osg::Vec3f mBlendStartTrans;
float mBlendStartScale = 0.0f;
};
class BoneAnimBlendController : public SceneUtil::NodeCallback<BoneAnimBlendController, osgAnimation::Bone*>,
public AnimBlendController
{
public:
BoneAnimBlendController(const osg::ref_ptr<SceneUtil::KeyframeController>& keyframeTrack,
const AnimBlendStateData& animState, const osg::ref_ptr<const SceneUtil::AnimBlendRules>& blendRules);
BoneAnimBlendController() {}
BoneAnimBlendController(const BoneAnimBlendController& other, const osg::CopyOp&)
: BoneAnimBlendController(other.mKeyframeTrack, other.mAnimState, other.mAnimBlendRules)
{
}
void gatherRecursiveBoneTransforms(osgAnimation::Bone* parent, bool isRoot = true);
void applyBoneBlend(osgAnimation::Bone* parent);
META_Object(MWRender, BoneAnimBlendController)
void operator()(osgAnimation::Bone* node, osg::NodeVisitor* nv);
osg::Callback* getAsCallback() { return this; }
};
// Assigned to child bones with an instance of AnimBlendController
class BoneAnimBlendControllerWrapper : public osg::Callback
{
public:
BoneAnimBlendControllerWrapper(osg::ref_ptr<BoneAnimBlendController> rootCallback, osgAnimation::Bone* node)
: mRootCallback(std::move(rootCallback))
, mNode(node)
{
}
BoneAnimBlendControllerWrapper() {}
BoneAnimBlendControllerWrapper(const BoneAnimBlendControllerWrapper& copy, const osg::CopyOp&)
: mRootCallback(copy.mRootCallback)
, mNode(copy.mNode)
{
}
META_Object(MWRender, BoneAnimBlendControllerWrapper)
bool run(osg::Object* object, osg::Object* data) override
{
mRootCallback->applyBoneBlend(mNode);
traverse(object, data);
return true;
}
private:
osg::ref_ptr<BoneAnimBlendController> mRootCallback;
osgAnimation::Bone* mNode{ nullptr };
};
}
#endif