您的位置:首页 > 其它

OSG事件回调

2016-06-27 13:36 330 查看
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: