• OSG事件回调


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

    //虚函数,回调函数主要操作在此函数中,子类应当重写,已完成相应操作
    void operator()(Node* node, NodeVisitor* nv);
    //为当前更新回调添加(删除)一个后继的回调对象
    void   addNestedCallback(NodeCallback* nc);
    void   removeNestedCallback(NodeCallback* nc);
    //直接设置/获取一个最近的回调
    void   (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<NodeCallback> _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) {}
    
        virtualvoidoperator()(osg::Node* node, osg::NodeVisitor* nv){
         osg::PositionAttitudeTransform* pat =
         dynamic_cast<osg::PositionAttitudeTransform*>(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:
        virtualvoidoperator()(osg::Node* node, osg::NodeVisitor* nv){
         osg::PositionAttitudeTransform* pat =
         dynamic_cast<osg::PositionAttitudeTransform*>(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<osg::PositionAttitudeTransform> 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();
     }

     转自:http://www.cnblogs.com/hzhg/archive/2010/12/19/1910340.html

  • 相关阅读:
    实现tip浮层
    c++实现冒泡排序
    一天一小段js代码(no.4)
    html5 css3实现图中结构
    html表格相关
    js跨浏览器的事件处理函数
    js实现DOM结构
    CSS3实现鼠标移动到图片上图片变大(缓慢变大,有过渡效果,放大的过程是有动画过渡的,这个过渡的时间可以自定义)
    正则表达式学习笔记
    使用JS与CSS3的翻转实现3D翻牌效果
  • 原文地址:https://www.cnblogs.com/xiaocainiao2hao/p/5619923.html
Copyright © 2020-2023  润新知