第36.2节 动画-骨骼动画的控制

本节功能

本节实现从一个有骨骼动画的fbx文件中读取,并实现点击n是播放下一个动画,点击s是播放当前动画,点击p是暂停播放当前动画。
在这里插入图片描述
本节的内容在网盘中,目录为/osgChina站长文集/文件中的附件/, 有附件的会根据节的编号存放在该目录:

请使用浏览器打开,平时遇到问题或加群也可以加我微信:13324598743:
【击此打开网盘资源链接】

具体实现

其实一个骨骼动画在osg中有一个类名字叫做:osgAnimation::BasicAnimationManager进行控制,其中的:

  • stopAnimation 负责暂停一个动画
  • playAnimation 负责播放一个动画
  • stopAll 负责停止所有动画
  • getAnimationList 负责得到所有动画的列表
  • isPlaying 判断当前动画是否在播放中

因此我们只需要使用NodeVisitor找到结点中的osgAnimation::BasicAnimationManager即可,我们可以这样写:

osgAnimation::BasicAnimationManager* g_animateManager = NULL;

class FindAnimate : public osg::NodeVisitor
{
public:
	FindAnimate():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN){}
    void apply(osg::Node& node)
    {
        if (node.getUpdateCallback())
        {
            osgAnimation::BasicAnimationManager* apc = dynamic_cast<osgAnimation::BasicAnimationManager*>(node.getUpdateCallback());
            if (NULL != apc)
            {
                g_animateManager = apc;
                return;
            }
        }
        traverse(node);
    }
};

然后再写一个响应事件就可以使用上面所说的方法对动画进行操作了。

全部代码如下

#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osg/NodeVisitor>
#include <osg/Transform>
#include <osg/AnimationPath>
#include <osgGA/GUIEventHandler>

#include <osgAnimation/BasicAnimationManager>

osgAnimation::BasicAnimationManager* g_animateManager = NULL;

class FindAnimate : public osg::NodeVisitor
{
public:
    FindAnimate():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN){}
    void apply(osg::Node& node)
    {
        if (node.getUpdateCallback())
        {
            osgAnimation::BasicAnimationManager* apc = dynamic_cast<osgAnimation::BasicAnimationManager*>(node.getUpdateCallback());
            if (NULL != apc)
            {
                g_animateManager = apc;
                return;
            }
        }
        
        traverse(node);
    }
};

class MyEvent : public osgGA::GUIEventHandler
{
public:
    MyEvent()
    {
        iAnimation = 0;
        g_animateManager->playAnimation(g_animateManager->getAnimationList().at(iAnimation++));
    }

    virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
    {
        if (ea.getEventType() == ea.KEYDOWN)
        {
            if ((ea.getKey() == 'p') || (ea.getKey() == 'P'))
            {
                int currentAnimation = (iAnimation - 1);
                if (currentAnimation < 0) currentAnimation = g_animateManager->getAnimationList().size() - 1;
                g_animateManager->stopAnimation(g_animateManager->getAnimationList().at(currentAnimation));
            }

            if ((ea.getKey() == 's') || (ea.getKey() == 'S'))
            {
                int currentAnimation = (iAnimation - 1);
                if (currentAnimation < 0) currentAnimation = g_animateManager->getAnimationList().size() - 1;
                g_animateManager->playAnimation(g_animateManager->getAnimationList().at(currentAnimation));
            }

            if ((ea.getKey() == 'n') || (ea.getKey() == 'N'))
            {
                if (iAnimation >= g_animateManager->getAnimationList().size()) iAnimation = 0;
                g_animateManager->stopAll();
                g_animateManager->playAnimation(g_animateManager->getAnimationList().at(iAnimation++));
            }
        }

        return false;
    }

    int iAnimation;
};


int main()
{
    osgViewer::Viewer viewer;

    osg::Node* diban = osgDB::readNodeFile("Naruto.fbx");

    FindAnimate fa;
    diban->accept(fa);

    viewer.setSceneData(diban);
    viewer.addEventHandler(new MyEvent);
    return viewer.run();
}

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片