mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 15:29:55 +00:00
Refactor AnimBlendControllers
This commit is contained in:
parent
4040bd9231
commit
eb290bebbb
6 changed files with 132 additions and 105 deletions
|
@ -27,7 +27,7 @@ add_openmw_dir (mwrender
|
|||
bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation
|
||||
renderbin actoranimation landmanager navmesh actorspaths recastmesh fogmanager objectpaging groundcover
|
||||
postprocessor pingpongcull luminancecalculator pingpongcanvas transparentpass precipitationocclusion ripples
|
||||
actorutil distortion animationpriority bonegroup blendmask
|
||||
actorutil distortion animationpriority bonegroup blendmask animblendcontroller
|
||||
)
|
||||
|
||||
add_openmw_dir (mwinput
|
||||
|
|
|
@ -60,7 +60,6 @@
|
|||
#include "../mwmechanics/weapontype.hpp"
|
||||
|
||||
#include "actorutil.hpp"
|
||||
#include "animblendcontroller.cpp"
|
||||
#include "rotatecontroller.hpp"
|
||||
#include "util.hpp"
|
||||
#include "vismask.hpp"
|
||||
|
@ -402,8 +401,7 @@ namespace
|
|||
return lightModel;
|
||||
}
|
||||
|
||||
void assignBoneBlendCallbackRecursive(MWRender::BoneAnimBlendController* controller,
|
||||
MWRender::ActiveControllersVector& activeControllers, osg::Node* parent, bool isRoot)
|
||||
void assignBoneBlendCallbackRecursive(MWRender::BoneAnimBlendController* controller, osg::Node* parent, bool isRoot)
|
||||
{
|
||||
// Attempt to cast node to an osgAnimation::Bone
|
||||
if (!isRoot && dynamic_cast<osgAnimation::Bone*>(parent))
|
||||
|
@ -454,7 +452,7 @@ namespace
|
|||
osg::Group* group = parent->asGroup();
|
||||
if (group)
|
||||
for (unsigned int i = 0; i < group->getNumChildren(); ++i)
|
||||
assignBoneBlendCallbackRecursive(controller, activeControllers, group->getChild(i), false);
|
||||
assignBoneBlendCallbackRecursive(controller, group->getChild(i), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1085,31 +1083,31 @@ namespace MWRender
|
|||
return mNodeMap;
|
||||
}
|
||||
|
||||
template <typename ControllerType, typename NodeType>
|
||||
inline osg::Callback* Animation::handleBlendTransform(osg::ref_ptr<osg::Node> node,
|
||||
template <typename ControllerType>
|
||||
inline osg::Callback* Animation::handleBlendTransform(const osg::ref_ptr<osg::Node>& node,
|
||||
osg::ref_ptr<SceneUtil::KeyframeController> keyframeController,
|
||||
std::map<osg::ref_ptr<osg::Node>, osg::ref_ptr<AnimBlendController<NodeType>>>& blendControllers,
|
||||
std::map<osg::ref_ptr<osg::Node>, osg::ref_ptr<ControllerType>>& blendControllers,
|
||||
const AnimBlendStateData& stateData, const osg::ref_ptr<const SceneUtil::AnimBlendRules>& blendRules,
|
||||
const AnimState& active)
|
||||
{
|
||||
osg::ref_ptr<ControllerType> animController;
|
||||
|
||||
if (blendControllers.contains(node))
|
||||
{
|
||||
animController = blendControllers[node];
|
||||
animController = blendControllers.at(node);
|
||||
animController->setKeyframeTrack(keyframeController, stateData, blendRules);
|
||||
}
|
||||
else
|
||||
{
|
||||
animController = new ControllerType(keyframeController, stateData, blendRules);
|
||||
blendControllers[node] = animController;
|
||||
blendControllers.emplace(node, animController);
|
||||
|
||||
if constexpr (std::is_same_v<ControllerType, BoneAnimBlendController>)
|
||||
assignBoneBlendCallbackRecursive(animController, mActiveControllers, node, true);
|
||||
assignBoneBlendCallbackRecursive(animController, node, true);
|
||||
}
|
||||
|
||||
keyframeController->mTime = active.mTime;
|
||||
|
||||
osg::Callback* asCallback = animController->getAsCallback();
|
||||
if constexpr (std::is_same_v<ControllerType, BoneAnimBlendController>)
|
||||
{
|
||||
// IMPORTANT: we must gather all transforms at point of change before next update
|
||||
|
@ -1118,13 +1116,13 @@ namespace MWRender
|
|||
animController->gatherRecursiveBoneTransforms(static_cast<osgAnimation::Bone*>(node.get()));
|
||||
|
||||
// Register blend callback after the initial animation callback
|
||||
node->addUpdateCallback(animController->getAsCallback());
|
||||
mActiveControllers.emplace_back(node, animController->getAsCallback());
|
||||
node->addUpdateCallback(asCallback);
|
||||
mActiveControllers.emplace_back(node, asCallback);
|
||||
|
||||
return keyframeController->getAsCallback();
|
||||
}
|
||||
|
||||
return animController->getAsCallback();
|
||||
return asCallback;
|
||||
}
|
||||
|
||||
void Animation::resetActiveGroups()
|
||||
|
@ -1181,13 +1179,12 @@ namespace MWRender
|
|||
{
|
||||
if (dynamic_cast<NifOsg::MatrixTransform*>(node.get()))
|
||||
{
|
||||
callback = handleBlendTransform<NifAnimBlendController, NifOsg::MatrixTransform>(node,
|
||||
it->second, mAnimBlendControllers, stateData, animsrc->mAnimBlendRules, active->second);
|
||||
callback = handleBlendTransform<NifAnimBlendController>(node, it->second,
|
||||
mAnimBlendControllers, stateData, animsrc->mAnimBlendRules, active->second);
|
||||
}
|
||||
else if (dynamic_cast<osgAnimation::Bone*>(node.get()))
|
||||
{
|
||||
callback
|
||||
= handleBlendTransform<BoneAnimBlendController, osgAnimation::Bone>(node, it->second,
|
||||
callback = handleBlendTransform<BoneAnimBlendController>(node, it->second,
|
||||
mBoneAnimBlendControllers, stateData, animsrc->mAnimBlendRules, active->second);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -306,10 +306,10 @@ namespace MWRender
|
|||
|
||||
void removeFromSceneImpl();
|
||||
|
||||
template <typename ControllerType, typename NodeType>
|
||||
inline osg::Callback* handleBlendTransform(osg::ref_ptr<osg::Node> node,
|
||||
template <typename ControllerType>
|
||||
inline osg::Callback* handleBlendTransform(const osg::ref_ptr<osg::Node>& node,
|
||||
osg::ref_ptr<SceneUtil::KeyframeController> keyframeController,
|
||||
std::map<osg::ref_ptr<osg::Node>, osg::ref_ptr<AnimBlendController<NodeType>>>& blendControllers,
|
||||
std::map<osg::ref_ptr<osg::Node>, osg::ref_ptr<ControllerType>>& blendControllers,
|
||||
const AnimBlendStateData& stateData, const osg::ref_ptr<const SceneUtil::AnimBlendRules>& blendRules,
|
||||
const AnimState& active);
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include <osgAnimation/Bone>
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
@ -90,18 +91,26 @@ namespace MWRender
|
|||
}
|
||||
}
|
||||
|
||||
template <typename NodeClass>
|
||||
AnimBlendController<NodeClass>::AnimBlendController(osg::ref_ptr<SceneUtil::KeyframeController> keyframeTrack,
|
||||
const AnimBlendStateData& newState, osg::ref_ptr<const SceneUtil::AnimBlendRules> blendRules)
|
||||
: mTimeFactor(0.0f)
|
||||
, mInterpFactor(0.0f)
|
||||
AnimBlendController::AnimBlendController(const osg::ref_ptr<SceneUtil::KeyframeController>& keyframeTrack,
|
||||
const AnimBlendStateData& newState, const osg::ref_ptr<const SceneUtil::AnimBlendRules>& blendRules)
|
||||
{
|
||||
setKeyframeTrack(keyframeTrack, newState, blendRules);
|
||||
}
|
||||
|
||||
template <typename NodeClass>
|
||||
void AnimBlendController<NodeClass>::setKeyframeTrack(osg::ref_ptr<SceneUtil::KeyframeController> kft,
|
||||
const AnimBlendStateData& newState, osg::ref_ptr<const SceneUtil::AnimBlendRules> blendRules)
|
||||
NifAnimBlendController::NifAnimBlendController(const osg::ref_ptr<SceneUtil::KeyframeController>& keyframeTrack,
|
||||
const AnimBlendStateData& newState, const osg::ref_ptr<const SceneUtil::AnimBlendRules>& blendRules)
|
||||
: AnimBlendController(keyframeTrack, newState, blendRules)
|
||||
{
|
||||
}
|
||||
|
||||
BoneAnimBlendController::BoneAnimBlendController(const osg::ref_ptr<SceneUtil::KeyframeController>& keyframeTrack,
|
||||
const AnimBlendStateData& newState, const osg::ref_ptr<const SceneUtil::AnimBlendRules>& blendRules)
|
||||
: AnimBlendController(keyframeTrack, newState, blendRules)
|
||||
{
|
||||
}
|
||||
|
||||
void AnimBlendController::setKeyframeTrack(const osg::ref_ptr<SceneUtil::KeyframeController>& kft,
|
||||
const AnimBlendStateData& newState, const osg::ref_ptr<const SceneUtil::AnimBlendRules>& blendRules)
|
||||
{
|
||||
// If animation has changed then start blending
|
||||
if (newState.mGroupname != mAnimState.mGroupname || newState.mStartKey != mAnimState.mStartKey
|
||||
|
@ -139,8 +148,22 @@ namespace MWRender
|
|||
}
|
||||
}
|
||||
|
||||
template <typename NodeClass>
|
||||
void AnimBlendController<NodeClass>::gatherRecursiveBoneTransforms(osgAnimation::Bone* bone, bool isRoot)
|
||||
void AnimBlendController::calculateInterpFactor(float time)
|
||||
{
|
||||
if (mBlendDuration != 0)
|
||||
mTimeFactor = std::min((time - mBlendStartTime) / mBlendDuration, 1.0f);
|
||||
else
|
||||
mTimeFactor = 1;
|
||||
|
||||
mInterpActive = mTimeFactor < 1.0;
|
||||
|
||||
if (mInterpActive)
|
||||
mInterpFactor = mEasingFn(mTimeFactor);
|
||||
else
|
||||
mInterpFactor = 1.0f;
|
||||
}
|
||||
|
||||
void BoneAnimBlendController::gatherRecursiveBoneTransforms(osgAnimation::Bone* bone, bool isRoot)
|
||||
{
|
||||
// Incase group traversal encountered something that isnt a bone
|
||||
if (!bone)
|
||||
|
@ -156,8 +179,7 @@ namespace MWRender
|
|||
}
|
||||
}
|
||||
|
||||
template <typename NodeClass>
|
||||
void AnimBlendController<NodeClass>::applyBoneBlend(osgAnimation::Bone* bone)
|
||||
void BoneAnimBlendController::applyBoneBlend(osgAnimation::Bone* bone)
|
||||
{
|
||||
// If we are done with interpolation then we can safely skip this as the bones are correct
|
||||
if (!mInterpActive)
|
||||
|
@ -200,24 +222,7 @@ namespace MWRender
|
|||
bone->setMatrixInSkeletonSpace(lerpedMatrix);
|
||||
}
|
||||
|
||||
template <typename NodeClass>
|
||||
void AnimBlendController<NodeClass>::calculateInterpFactor(float time)
|
||||
{
|
||||
if (mBlendDuration != 0)
|
||||
mTimeFactor = std::min((time - mBlendStartTime) / mBlendDuration, 1.0f);
|
||||
else
|
||||
mTimeFactor = 1;
|
||||
|
||||
mInterpActive = mTimeFactor < 1.0;
|
||||
|
||||
if (mInterpActive)
|
||||
mInterpFactor = mEasingFn(mTimeFactor);
|
||||
else
|
||||
mInterpFactor = 1.0f;
|
||||
}
|
||||
|
||||
template <typename NodeClass>
|
||||
void AnimBlendController<NodeClass>::operator()(osgAnimation::Bone* node, osg::NodeVisitor* nv)
|
||||
void BoneAnimBlendController::operator()(osgAnimation::Bone* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
// HOW THIS WORKS: This callback method is called only for bones with attached keyframe controllers
|
||||
// such as bip01, bip01 spine1 etc. The child bones of these controllers have their own callback wrapper
|
||||
|
@ -237,11 +242,10 @@ namespace MWRender
|
|||
if (mInterpActive)
|
||||
applyBoneBlend(node);
|
||||
|
||||
SceneUtil::NodeCallback<AnimBlendController<NodeClass>, osgAnimation::Bone*>::traverse(node, nv);
|
||||
SceneUtil::NodeCallback<BoneAnimBlendController, osgAnimation::Bone*>::traverse(node, nv);
|
||||
}
|
||||
|
||||
template <typename NodeClass>
|
||||
void AnimBlendController<NodeClass>::operator()(NifOsg::MatrixTransform* node, osg::NodeVisitor* nv)
|
||||
void NifAnimBlendController::operator()(NifOsg::MatrixTransform* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
// HOW THIS WORKS: The actual retrieval of the bone transformation based on animation is done by the
|
||||
// KeyframeController (mKeyframeTrack). The KeyframeController retreives time data (playback position) every
|
||||
|
@ -303,6 +307,6 @@ namespace MWRender
|
|||
// instantly hide/show objects in which case the scale interpolation is undesirable.
|
||||
node->setScale(*scale);
|
||||
|
||||
SceneUtil::NodeCallback<AnimBlendController<NodeClass>, NifOsg::MatrixTransform*>::traverse(node, nv);
|
||||
SceneUtil::NodeCallback<NifAnimBlendController, NifOsg::MatrixTransform*>::traverse(node, nv);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,49 +27,28 @@ namespace MWRender
|
|||
std::string mStartKey;
|
||||
};
|
||||
|
||||
template <typename NodeClass>
|
||||
class AnimBlendController : public SceneUtil::NodeCallback<AnimBlendController<NodeClass>, NodeClass*>,
|
||||
public SceneUtil::Controller
|
||||
class AnimBlendController : public SceneUtil::Controller
|
||||
{
|
||||
public:
|
||||
AnimBlendController(osg::ref_ptr<SceneUtil::KeyframeController> keyframeTrack,
|
||||
const AnimBlendStateData& animState, osg::ref_ptr<const SceneUtil::AnimBlendRules> blendRules);
|
||||
AnimBlendController(const osg::ref_ptr<SceneUtil::KeyframeController>& keyframeTrack,
|
||||
const AnimBlendStateData& animState, const osg::ref_ptr<const SceneUtil::AnimBlendRules>& blendRules);
|
||||
|
||||
AnimBlendController() {}
|
||||
|
||||
AnimBlendController(const AnimBlendController& other, const osg::CopyOp&)
|
||||
: AnimBlendController(other.mKeyframeTrack, other.mAnimState, other.mAnimBlendRules)
|
||||
{
|
||||
}
|
||||
|
||||
META_Object(MWRender, AnimBlendController<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, const AnimBlendStateData& animState,
|
||||
osg::ref_ptr<const SceneUtil::AnimBlendRules> blendRules);
|
||||
|
||||
osg::Callback* getAsCallback() { return this; }
|
||||
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; }
|
||||
|
||||
void gatherRecursiveBoneTransforms(osgAnimation::Bone* parent, bool isRoot = true);
|
||||
void applyBoneBlend(osgAnimation::Bone* parent);
|
||||
|
||||
private:
|
||||
protected:
|
||||
Easings::EasingFn mEasingFn;
|
||||
float mBlendDuration;
|
||||
float mBlendDuration = 0.0f;
|
||||
float mBlendStartTime = 0.0f;
|
||||
float mTimeFactor = 0.0f;
|
||||
float mInterpFactor = 0.0f;
|
||||
|
||||
bool mBlendTrigger = false;
|
||||
float mBlendStartTime;
|
||||
osg::Quat mBlendStartRot;
|
||||
osg::Vec3f mBlendStartTrans;
|
||||
float mBlendStartScale;
|
||||
|
||||
float mTimeFactor;
|
||||
float mInterpFactor;
|
||||
bool mInterpActive;
|
||||
bool mInterpActive = false;
|
||||
|
||||
AnimBlendStateData mAnimState;
|
||||
osg::ref_ptr<const SceneUtil::AnimBlendRules> mAnimBlendRules;
|
||||
|
@ -80,8 +59,55 @@ namespace MWRender
|
|||
inline void calculateInterpFactor(float time);
|
||||
};
|
||||
|
||||
using NifAnimBlendController = AnimBlendController<NifOsg::MatrixTransform>;
|
||||
using BoneAnimBlendController = AnimBlendController<osgAnimation::Bone>;
|
||||
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
|
||||
|
|
|
@ -187,20 +187,20 @@ namespace SceneUtil
|
|||
mgr->addWrapper(new GeometrySerializer);
|
||||
|
||||
// ignore the below for now to avoid warning spam
|
||||
const char* ignore[] = { "Debug::DebugDrawer", "MWRender::AnimBlendController<NifOsg::MatrixTransform>",
|
||||
"MWRender::AnimBlendController<osgAnimation::Bone>", "MWRender::BoneAnimBlendControllerWrapper",
|
||||
"MWRender::PtrHolder", "Resource::TemplateRef", "Resource::TemplateMultiRef",
|
||||
"SceneUtil::CompositeStateSetUpdater", "SceneUtil::UBOManager", "SceneUtil::LightListCallback",
|
||||
"SceneUtil::LightManagerUpdateCallback", "SceneUtil::FFPLightStateAttribute",
|
||||
"SceneUtil::UpdateRigBounds", "SceneUtil::UpdateRigGeometry", "SceneUtil::LightSource",
|
||||
"SceneUtil::DisableLight", "SceneUtil::MWShadowTechnique", "SceneUtil::TextKeyMapHolder",
|
||||
"Shader::AddedState", "Shader::RemovedAlphaFunc", "NifOsg::FlipController",
|
||||
"NifOsg::KeyframeController", "NifOsg::Emitter", "NifOsg::ParticleColorAffector",
|
||||
"NifOsg::ParticleSystem", "NifOsg::GravityAffector", "NifOsg::ParticleBomb", "NifOsg::GrowFadeAffector",
|
||||
"NifOsg::InverseWorldMatrix", "NifOsg::StaticBoundingBoxCallback", "NifOsg::GeomMorpherController",
|
||||
"NifOsg::UpdateMorphGeometry", "NifOsg::UVController", "NifOsg::VisController", "osgMyGUI::Drawable",
|
||||
"osg::DrawCallback", "osg::UniformBufferObject", "osgOQ::ClearQueriesCallback",
|
||||
"osgOQ::RetrieveQueriesCallback", "osg::DummyObject" };
|
||||
const char* ignore[] = { "Debug::DebugDrawer", "MWRender::NifAnimBlendController",
|
||||
"MWRender::BoneAnimBlendController", "MWRender::BoneAnimBlendControllerWrapper", "MWRender::PtrHolder",
|
||||
"Resource::TemplateRef", "Resource::TemplateMultiRef", "SceneUtil::CompositeStateSetUpdater",
|
||||
"SceneUtil::UBOManager", "SceneUtil::LightListCallback", "SceneUtil::LightManagerUpdateCallback",
|
||||
"SceneUtil::FFPLightStateAttribute", "SceneUtil::UpdateRigBounds", "SceneUtil::UpdateRigGeometry",
|
||||
"SceneUtil::LightSource", "SceneUtil::DisableLight", "SceneUtil::MWShadowTechnique",
|
||||
"SceneUtil::TextKeyMapHolder", "Shader::AddedState", "Shader::RemovedAlphaFunc",
|
||||
"NifOsg::FlipController", "NifOsg::KeyframeController", "NifOsg::Emitter",
|
||||
"NifOsg::ParticleColorAffector", "NifOsg::ParticleSystem", "NifOsg::GravityAffector",
|
||||
"NifOsg::ParticleBomb", "NifOsg::GrowFadeAffector", "NifOsg::InverseWorldMatrix",
|
||||
"NifOsg::StaticBoundingBoxCallback", "NifOsg::GeomMorpherController", "NifOsg::UpdateMorphGeometry",
|
||||
"NifOsg::UVController", "NifOsg::VisController", "osgMyGUI::Drawable", "osg::DrawCallback",
|
||||
"osg::UniformBufferObject", "osgOQ::ClearQueriesCallback", "osgOQ::RetrieveQueriesCallback",
|
||||
"osg::DummyObject" };
|
||||
for (size_t i = 0; i < sizeof(ignore) / sizeof(ignore[0]); ++i)
|
||||
{
|
||||
mgr->addWrapper(makeDummySerializer(ignore[i]));
|
||||
|
|
Loading…
Reference in a new issue