1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-11 15:40:39 +00:00
OpenMW/apps/openmw/mwrender/animblendcontroller.hpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

120 lines
4.0 KiB
C++
Raw Normal View History

#ifndef OPENMW_MWRENDER_ANIMBLENDCONTROLLER_H
#define OPENMW_MWRENDER_ANIMBLENDCONTROLLER_H
#include <map>
#include <optional>
#include <string>
#include <unordered_map>
#include <osgAnimation/Bone>
#include <components/debug/debuglog.hpp>
#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
{
namespace Easings
{
typedef float (*EasingFn)(float);
}
struct AnimBlendStateData
{
std::string mGroupname;
std::string mStartKey;
};
template <typename NodeClass>
class AnimBlendControllerBase : public SceneUtil::NodeCallback<AnimBlendControllerBase<NodeClass>, NodeClass*>,
public SceneUtil::Controller
{
public:
AnimBlendControllerBase(osg::ref_ptr<SceneUtil::KeyframeController> keyframeTrack, AnimBlendStateData animState,
osg::ref_ptr<const SceneUtil::AnimBlendRules> blendRules);
2024-04-26 23:54:21 +01:00
AnimBlendControllerBase() {}
AnimBlendControllerBase(const AnimBlendControllerBase<NodeClass>& copy, const osg::CopyOp&)
: mTimeFactor(0.0f)
, mInterpFactor(0.0f)
{
setKeyframeTrack(copy.getKeyframeTrack(), copy.getAnimState(), copy.getBlendRules());
}
META_Object(MWRender, AnimBlendControllerBase<NodeClass>)
void operator()(NifOsg::MatrixTransform* node, osg::NodeVisitor* nv);
void operator()(osgAnimation::Bone* node, osg::NodeVisitor* nv);
void setKeyframeTrack(osg::ref_ptr<SceneUtil::KeyframeController> kft, AnimBlendStateData animState,
osg::ref_ptr<const SceneUtil::AnimBlendRules> blendRules);
osg::Callback* getAsCallback() { return this; }
bool getBlendTrigger() const { return mBlendTrigger; }
void gatherRecursiveBoneTransforms(osgAnimation::Bone* parent, bool isRoot = true);
void applyBoneBlend(osgAnimation::Bone* parent);
2024-04-26 23:54:21 +01:00
osg::ref_ptr<SceneUtil::KeyframeController> getKeyframeTrack() const { return mKeyframeTrack; }
osg::ref_ptr<const SceneUtil::AnimBlendRules> getBlendRules() const { return mAnimBlendRules; }
AnimBlendStateData getAnimState() const { return mAnimState; }
private:
Easings::EasingFn mEasingFn;
float mBlendDuration;
bool mBlendTrigger = false;
float mBlendStartTime;
osg::Quat mBlendStartRot;
osg::Vec3f mBlendStartTrans;
float mBlendStartScale;
float mTimeFactor;
float mInterpFactor;
bool mInterpActive;
AnimBlendStateData mAnimState;
osg::ref_ptr<const SceneUtil::AnimBlendRules> mAnimBlendRules;
2024-04-26 23:54:21 +01:00
osg::ref_ptr<SceneUtil::KeyframeController> mKeyframeTrack;
std::unordered_map<osg::Node*, osg::Matrixf> mBlendBoneTransforms;
2024-04-26 23:54:21 +01:00
inline void calculateInterpFactor(float time);
};
using AnimBlendController = AnimBlendControllerBase<NifOsg::MatrixTransform>;
using BoneAnimBlendController = AnimBlendControllerBase<osgAnimation::Bone>;
// Assigned to child bones with an instance of AnimBlendControllerBase
class BoneAnimBlendControllerWrapper : public osg::Callback
{
public:
BoneAnimBlendControllerWrapper(osg::ref_ptr<BoneAnimBlendController> rootCallback, osg::Node* node)
{
mRootCallback = rootCallback;
mNode = dynamic_cast<osgAnimation::Bone*>(node);
}
bool run(osg::Object* object, osg::Object* data) override
{
mRootCallback->applyBoneBlend(mNode);
traverse(object, data);
return true;
}
const char* libraryName() const override { return "openmw"; }
const char* className() const override { return "AnimBlendController"; }
private:
osg::ref_ptr<BoneAnimBlendController> mRootCallback;
osgAnimation::Bone* mNode;
};
}
#endif