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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM