您好,欢迎来到爱go旅游网。
搜索
您的当前位置:首页第一日学习(二)osgViewer/view.cpp————osgViewer::View::init()

第一日学习(二)osgViewer/view.cpp————osgViewer::View::init()

来源:爱go旅游网

这里事先说下,作者在一开始说到了单窗口和多窗口是同样的流程,但是单窗口类不是osgViewer::View,而是osgViewer::viewer,这里要记住。

那么为什么要用到osgviewer::View类?因为osgViewer::viewer派生于osgViewer::View,

类的声明如下:

namespace osgViewer {

class Viewer : public ViewerBase, public osgViewer::View

{

....

};

}

 

原来osgViewer::viewer有两个父类,那么osgViewer::View是干啥的呢?这里稍微看看,


namespace osgViewer {
class View : public osg::View, public osgGA::GUIActionAdapter
{

};

}

从这里可以猜测,如果说viewBase是每帧处理并渲染的,那么osgViewer::View就是人机交互的类

具体是不是,再看下 osg::View类和osgGA::GUIActionAdapter类

namespace osg {

/** View - maintains a master camera view and a list of slave cameras that are relative to this master camera.
  * Note, if no slave cameras are attached to the view then the master camera does both the control and implementation of the rendering of the scene,
  * but if slave cameras are present then the master controls the view onto the scene, while the slaves implement the rendering of the scene.
*/
class OSG_EXPORT View : public virtual osg::Object
{

.....

      virtual osg::GraphicsOperation* createRenderer(osg::Camera*) { return 0; }

        LightingMode                    _lightingMode;
        osg::ref_ptr<osg::Light>        _light;

        osg::ref_ptr<osg::Camera>       _camera;
        
        typedef std::vector<Slave>      Slaves;
        Slaves                          _slaves;

        osg::ref_ptr<osg::FrameStamp>   _frameStamp;

};

}

限于篇幅,没全拷贝过来.可以看到osg::View涉及到了主从摄像机及创建渲染器,以及灯光和帧率。

 

以上只是说明了OsgViewer::view类,以及为什么要分析它,简而言之,也是个单窗口的父类

言归正传,为什么要用到这个函数呢?

再回顾下流程

frame()

{

viewerInit();

isRealized();

realize();

advance(simulationTime);

eventTraversal();

updateTraversal();

renderingTraversals();

}

其中viewerBase::viewerInit()的定义如下:

 virtual void viewerInit() = 0;
是个纯虚函数,

那么在子类单窗口中的viewerInit()是什么呢?

 virtual void viewerInit() { init(); }

这个init()是调用父类osgViewer::view的init()

 

所以终于切题了,这就是要本节分析的内容


void View::init()
{
    osg::notify(osg::INFO)<<"View::init()"<<std::endl;
    

//创建事件
    osg::ref_ptr<osgGA::GUIEventAdapter> initEvent = _eventQueue->createEvent();
    initEvent->setEventType(osgGA::GUIEventAdapter::FRAME);
    //将漫游器与事件和视窗相关联
    if (_cameraManipulator.valid())
    {
        _cameraManipulator->init(*initEvent, *this);
    }
}

这里涉及到了GUIEventhandler,GUIEventAdapter和各种manipulator的关系。GUIEventAdapter是各种交互事件的处理,GUIEventhandler是用户一般使用的人机交互类,Matrixmanipulator派生于GUIEventhandler,其他各种漫游器派生于Matrixmanipulator。

GUIEventHandler和GUIEventAdapter的关系在下面函数handle()中
        /** Handle events, return true if handled, false otherwise. */
        virtual bool handle(const GUIEventAdapter& ea,GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor*) { return handle(ea,aa); }

 

其中osg::ref_ptr<osgGA::EventQueue>         _eventQueue;说明_eventQueue是储存该视景器的事件队列类,关于事件队列类,其实还有个成员变量,也叫做_eventQueue,那个是真正的事件队列,即


        typedef std::list< osg::ref_ptr<GUIEventAdapter> > Events;
        Events                      _eventQueue;

 

可见事件队列类里保存着各种事件。从osgGA::EventQueue里可以看到,除了响应鼠标键盘输入,窗口变化外,还可以响应用户自定义事件。自然也包括事件队列的操作,等同于其他普通链表的操作。在操作时,要上锁,这里用到了openThreads类,成员变量  mutable OpenThreads::Mutex  _eventQueueMutex;使用时,要上锁,比如在添加事件时,


void EventQueue::addEvent(GUIEventAdapter* event)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_eventQueueMutex);
    _eventQueue.push_back(event);
}

那么当前事件时什么呢?肯定有个当前事件的指针,这里也有个成员变量
        osg::ref_ptr<GUIEventAdapter>   _accumulateEventState;
        GUIEventAdapter* getCurrentEventState() { return _accumulateEventState.get(); }

创建事件
GUIEventAdapter* EventQueue::createEvent()
{
    if (_accumulateEventState.valid()) return new GUIEventAdapter(*_accumulateEventState.get());
    else return new GUIEventAdapter();    
}

这个事件是与每帧相关的

initEvent->setEventType(osgGA::GUIEventAdapter::FRAME);

漫游器成员变量
        osg::ref_ptr<osgGA::MatrixManipulator>  _cameraManipulator;

将漫游器与事件和视口相关联

_cameraManipulator->init(*initEvent, *this);

virtual void init(const GUIEventAdapter& ,GUIActionAdapter&) {}

osgGA::MatrixManipulator是个基类,每个派生于它的子类会有各自初始化的函数。

 

总结下这个函数:就是创建帧事件,并将漫游器与事件和视口相关联

 

 

再次总结下:

osgViewer::viewBase:: frame()

{

viewerInit();[

                          //创建帧事件,并将漫游器与事件和视口相关联

                            ->   osgViewer::Viewer::ViewerInit()

                           ->  osgViewer::View::Init();

                          ->(1)osgGA::EventQueue::createEvent();

                            (2)osgGA::MatrixManipulator::Init();

                 ]

isRealized();

realize();

advance(simulationTime);

eventTraversal();

updateTraversal();

renderingTraversals();

}

 

另外说下,在多视口中初始化时,会逐个遍历视口

void CompositeViewer::viewerInit()
{
    osg::notify(osg::INFO)<<"CompositeViewer::init()"<<std::endl;

    for(RefViews::iterator itr = _views.begin();
        itr != _views.end();
        ++itr)
    {
        (*itr)->init();
    }
}

 

 

 

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- igat.cn 版权所有 赣ICP备2024042791号-1

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务