您现在的位置是:主页 > news > 国家卫生计生委建设监管网站/深圳网络推广平台

国家卫生计生委建设监管网站/深圳网络推广平台

admin2025/5/14 7:17:12news

简介国家卫生计生委建设监管网站,深圳网络推广平台,wordpress flash插件下载,天津做网站排名目录本节功能具体实现存放动画寻找动画播放/暂停复位加速/减速最后用一个事件响应来联接这一切所有代码本节功能 本节后几个章节会介绍和动画有关的课程。 本节实现一个从3DMAX导出的地板破碎的动画的控制,这类动画叫做刚体动画。所谓刚体动画我理解就是仅物体的位…

国家卫生计生委建设监管网站,深圳网络推广平台,wordpress flash插件下载,天津做网站排名目录本节功能具体实现存放动画寻找动画播放/暂停复位加速/减速最后用一个事件响应来联接这一切所有代码本节功能 本节后几个章节会介绍和动画有关的课程。 本节实现一个从3DMAX导出的地板破碎的动画的控制,这类动画叫做刚体动画。所谓刚体动画我理解就是仅物体的位…

目录

  • 本节功能
  • 具体实现
    • 存放动画
    • 寻找动画
    • 播放/暂停
    • 复位
    • 加速/减速
    • 最后用一个事件响应来联接这一切
    • 所有代码

本节功能

本节后几个章节会介绍和动画有关的课程。

本节实现一个从3DMAX导出的地板破碎的动画的控制,这类动画叫做刚体动画。所谓刚体动画我理解就是仅物体的位置、方向、缩放这三者发生变化。

当我们点击P时,动画会暂停,当我们点击S时,动画会播放,点击R时动画会复位。点击+时,动画会快速播放2倍,点击 - 时,动画会慢速播放2倍。

在这里插入图片描述
本节的内容在网盘中,目录为/osgChina站长文集/文件中的附件/, 有附件的会根据节的编号存放在该目录:

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

具体实现

很容易,我们联想到,刚体动画涉及到的变量都是矩阵的变化,它的位置、朝向、缩放发生变化,其实大多数情况下是位置、朝向。而osg中控制矩阵的结点是osg::MatrixTransform,对其设置动画使用的是setUpdateCallback,而刚体动画是osg::AnimationPathCallback,因此我们只需要找到模型中所有结点里的UpdateCallback,判断其是否为AnimationPathCallback就可以了。

存放动画

为此我们申请了一个全局变量:

std::vector<osg::AnimationPathCallback*> g_animateCallback;

这个全局变量是一个向量,里面存放AnimationPathCallback,然后我们使用一个NodeVisitor,来对每一个osg::Transform(因为osg::MatrixTransform继承自osg::Transform,用基类更保险一点),来看它是否有UpdateCallback,如果有的话,是否是AnimationPathCallback,是的话就压入到全局变量中进行控制。现实如下

寻找动画

我们写的NodeVistor类叫做FindAnimate,实现如下:在这里要特别注意的是,在构造函数中我们调用了TRAVERSE_ALL_CHILDREN,代表我们要遍历结点的所有的孩子在apply中,我们调用了traverse(node)代表我们还要向下遍历。

class FindAnimate : public osg::NodeVisitor
{
public:FindAnimate():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN){}void apply(osg::Transform& node){if (node.getUpdateCallback()){osg::AnimationPathCallback* apc = dynamic_cast<osg::AnimationPathCallback*>(node.getUpdateCallback());if (NULL != apc){g_animateCallback.push_back(apc);}}traverse(node);}
};

它的调用是这样的:

    FindAnimate fa;//diban是读取的ivediban->accept(fa);

自此动画都压入到了g_animateCallback中。然后我们再写几个简单的函数即可实现控制:

播放/暂停

AnimationPathCallback中有个setPause函数,直接就可以实现这个功能:

//true是播放动画,false是暂停动画
void play(bool isPlay)
{for (int i = 0; i < g_animateCallback.size(); i++){g_animateCallback.at(i)->setPause(!isPlay);}
}

复位

AnimationPathCallback里有个reset可以实现这个功能:

void reset()
{for (int i = 0; i < g_animateCallback.size(); i++){g_animateCallback.at(i)->reset();g_animateCallback.at(i)->setPause(false);}
}

加速/减速

AnimationPathCallback里有个setTimeMultiplier函数,下面是按+号加速2倍:

if (ea.getKey() == '+')
{for (int i = 0; i < g_animateCallback.size(); i++){g_animateCallback.at(i)->setTimeMultiplier(g_animateCallback.at(i)->getTimeMultiplier()*2.0);}
}

最后用一个事件响应来联接这一切


class MyEvent : public osgGA::GUIEventHandler
{
public:MyEvent(){}virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa){if (ea.getEventType() == ea.KEYDOWN){if ((ea.getKey() == 'r') || (ea.getKey() == 'R')){reset();}if ((ea.getKey() == 'p') || (ea.getKey() == 'P')){play(false);}if ((ea.getKey() == 's') || (ea.getKey() == 'S')){play(true);}if (ea.getKey() == '+'){for (int i = 0; i < g_animateCallback.size(); i++){g_animateCallback.at(i)->setTimeMultiplier(g_animateCallback.at(i)->getTimeMultiplier()*2.0);}}if (ea.getKey() == '-'){for (int i = 0; i < g_animateCallback.size(); i++){g_animateCallback.at(i)->setTimeMultiplier(g_animateCallback.at(i)->getTimeMultiplier() * 0.5);}}}return false;}
};

所有代码

#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osg/NodeVisitor>
#include <osg/Transform>
#include <osg/AnimationPath>
#include <osgGA/GUIEventHandler>std::vector<osg::AnimationPathCallback*> g_animateCallback;class FindAnimate : public osg::NodeVisitor
{
public:FindAnimate():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN){}void apply(osg::Transform& node){if (node.getUpdateCallback()){osg::AnimationPathCallback* apc = dynamic_cast<osg::AnimationPathCallback*>(node.getUpdateCallback());if (NULL != apc){g_animateCallback.push_back(apc);}}traverse(node);}
};//true是播放动画,false是暂停动画
void play(bool isPlay)
{for (int i = 0; i < g_animateCallback.size(); i++){g_animateCallback.at(i)->setPause(!isPlay);}
}void reset()
{for (int i = 0; i < g_animateCallback.size(); i++){g_animateCallback.at(i)->reset();g_animateCallback.at(i)->setPause(false);}
}class MyEvent : public osgGA::GUIEventHandler
{
public:MyEvent(){}virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa){if (ea.getEventType() == ea.KEYDOWN){if ((ea.getKey() == 'r') || (ea.getKey() == 'R')){reset();}if ((ea.getKey() == 'p') || (ea.getKey() == 'P')){play(false);}if ((ea.getKey() == 's') || (ea.getKey() == 'S')){play(true);}if (ea.getKey() == '+'){for (int i = 0; i < g_animateCallback.size(); i++){g_animateCallback.at(i)->setTimeMultiplier(g_animateCallback.at(i)->getTimeMultiplier()*2.0);}}if (ea.getKey() == '-'){for (int i = 0; i < g_animateCallback.size(); i++){g_animateCallback.at(i)->setTimeMultiplier(g_animateCallback.at(i)->getTimeMultiplier() * 0.5);}}}return false;}
};int main()
{osgViewer::Viewer viewer;osg::Node* diban = osgDB::readNodeFile("diban.ive");FindAnimate fa;diban->accept(fa);viewer.setSceneData(diban);viewer.addEventHandler(new MyEvent);return viewer.run();
}