OSG节点更新与事件回调

OSG中的节点主要使用回调(CallBack)来完成用户临时、需要每帧执行的工作。根据回调功能被调用的时机划分为更新回调(Update CallBack)和人机交互事件回调(Event CallBack)。前者在每一帧中系统遍历到当前节点时调用,后者则由交互事件触发,如操作键盘、鼠标、关闭窗口、改变窗口大小等动作。回调类基类

是osg::NodeCallBack(),主要函数如下:

//虚函数,回调函数主要操作在此函数中,子类应当重写,已完成相应操作
void operator()(Node* node, NodeVisitor* nv);

//为当前更新回调添加(删除)一个后继的回调对象
void   addNestedCallback(NodeCallback* nc);
void   removeNestedCallback(NodeCallback* nc);

//直接设置/获取一个最近的回调
void   setNestedCallback(NodeCallback* nc);
NodeCallback*   getNestedCallback();

//调用临近中的下一个更新回调
void traverse(Node* node,NodeVisitor* nv);

节点类中完成回调函数设置和获取:


//设置/获取节点的更新回调
void  setUpdateCallback(NodeCallback* );
NodeCallback* getUpdateCallback();
//设置/获取节点的事件回调
void  setEventCallback(NodeCallback*);
NodeCallback*  getEventCallback();

对于addNestedCallback(……)函数,其源码如下:


inline void addNestedCallback(NodeCallback* nc)
        {
            if (nc)
            {
                if (_nestedCallback.valid())
                {
                    nc->addNestedCallback(_nestedCallback.get());
                    _nestedCallback = nc;
                }
                else
                {
                    _nestedCallback = nc;
                }
            }
        }

在NodeCallback类中用一个ref_ptr _nestedCallback; 来存储下一个回调对象,利用链表构成
一个回调对象序列,当要添加一个临近回调时,即调用addNestedCallback(NodeCallback* nc)时利用递归将两个
(分别以this,nc为连表头的)序列合并,例如:this->callback1->callback2->callback3->null, nc->callback4->callback5->null。合并后新的序列为this->nc->callback1->callback4->callback2->callback5->callback3->null。至于removeNestedCallback(...),比较简单,如下:


inline void addNestedCallback(NodeCallback* nc)
        {
            if (nc)
            {
                if (_nestedCallback.valid())
                {
                    nc->addNestedCallback(_nestedCallback.get());
                    _nestedCallback = nc;
                }
                else
                {
                    _nestedCallback = nc;
                }
            }
        }

在NodeCallback类中用一个ref_ptr _nestedCallback; 来存储下一个回调对象,利用链表构成
一个回调对象序列,当要添加一个临近回调时,即调用addNestedCallback(NodeCallback* nc)时利用递归将两个
(分别以this,nc为连表头的)序列合并,例如:this->callback1->callback2->callback3->null, nc->callback4->callback5->null。合并后新的序列为this->nc->callback1->callback4->callback2->callback5->callback3->null。至于removeNestedCallback(...),比较简单,如下:


inline void removeNestedCallback(NodeCallback* nc)
{
       if (nc)
       {
                if (_nestedCallback==nc)
                {
                    _nestedCallback = _nestedCallback->getNestedCallback();
                }
                else if (_nestedCallback.valid())
                {
                    _nestedCallback->removeNestedCallback(nc);
                }
        }
}

其中traverse()函数,其功能是对当前节点调用下一个临近回调函数,其代码如下:

void NodeCallback::traverse(Node* node,NodeVisitor* nv)
{
    //如果有后续回调对象,则调用, 重载操作符"()"来实现
    if (_nestedCallback.valid())
            (*_nestedCallback)(node,nv);
    //回调操作完成之后,访问该节点   
    else
            nv->traverse(*node);
} 

一个范例:使用回调实现旋转动画

代码

#include <osg/Quat>
#include <osg/PositionAttitudeTransform>
#include <osg/io_utils>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <iostream>

  class RotateCallBack: public osg::NodeCallback
{
 public:
    RotateCallBack():_rotateZ(0.0) {}

    virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
    {
        osg::PositionAttitudeTransform* pat =
            dynamic_cast(node);
        if(pat)
        {
            osg::Vec3 vec(0, 0, 1);
            osg::Quat quat = osg::Quat(osg::DegreesToRadians(_rotateZ), osg::Z_AXIS);
            pat->setAttitude(quat);

            _rotateZ += 0.10;
        }

        traverse(node, nv);
    }

 private:
    double _rotateZ;
};


 class InfoCallBack: public osg::NodeCallback
{
 public:
    virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
    {
        osg::PositionAttitudeTransform* pat =
            dynamic_cast(node);
       
        if(pat)
        {
            double angle = 0.0;
            osg::Vec3 axis;
            pat->getAttitude().getRotate(angle, axis);

            std::cout << "Node is rotate around the axis(" << axis << "), "
                <<osg::RadiansToDegrees(angle) << "degrees" << std::endl;
        }

        traverse(node, nv);
    }
};


int main(int argc, char** argv)
{
    osg::ArgumentParser argument(&argc, argv);
    osg::Node* model = osgDB::readNodeFiles(argument);
    if(!model)
            model = osgDB::readNodeFile("cow.osg") ;

    osg::ref_ptr pat =
            new osg::PositionAttitudeTransform();
    pat->addChild(model);

    pat->setUpdateCallback(new RotateCallBack() );
    pat->addUpdateCallback(new InfoCallBack() );

    osgViewer::Viewer viewer;
    viewer.setSceneData(pat.get() );
    return viewer.run();
}

本文转自:https://www.cnblogs.com/hzhg/archive/2010/12/19/1910340.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值