这里事先说下,作者在一开始说到了单窗口和多窗口是同样的流程,但是单窗口类不是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
本站由北京市万商天勤律师事务所王兴未律师提供法律服务