解读List
osgViewer::Viewer::viewerInit(调用了View::init函数)
osgViewer::View::init(初始化视景器)
osgGA::EventQueue::createEvent(在View::init调用,并创建了一个FRAME类型的事件)
osgGA::MatrixManipulator::init(在View::init调用,将新创建的FRAME事件和Viewer对象本身为视景器实例进行相应的初始化,通过重写并使用此方法,就能灵活的初始化自定义漫游器的功能--此处应写一个漫游器看看)
OpenSceneGraph3.4.0版本源码解读。(仅对单视景器情况)
跟随王锐大大的最长的一帧之路,慢慢来看看这一帧中发生了什么。
while(!viewer.done())
viewer.frame();
用一个循环结构反复的执行frame( )直到done( )函数的返回值为true为止,每执行一次frame()相当于完成了OSG场景渲染的一帧。
所以首先就来看看这个frame()函数是做了什么
当前类:
osgViewer/ViewerBase.cpp
当前位置:
osgViewer::ViewerBase::frame() 第666行, osgViewer::ViewerBase::frame()
void ViewerBase::frame(double simulationTime)
{
if (_done) return;
// OSG_NOTICE<
绘制一帧的场景,就是通过这个frame()函数,这个函数是ViewerBase的函数,针对单视景器Viewer类和多视景器CompositeViewer类,frame函数的内容都是相同的。
主要工作:
1、
如果为场景第一帧,则执行viewerInit(),实际上通过了这个viewerIt()函数调用了View::init();
判断是否realized了,若没有执行realize()函数,则执行该函数;
2、执行advance()函数;
3、执行eventTraversal()。负责执行处理系统产生的各种事件
4、执行updateTraversal()。负责遍历所有的更新回调,更新DatabasePager和ImagePager这两个分页数据处理组件
5、执行renderingTraversals.使用较复杂的线程处理方法,完成场景的筛选和绘制(cull and draw)
代码之旅主要就是按照这个5个景点的顺序来看的。
这里总结一下这一帧,每一次调用一次frame()函数就是做了以上五个操作,init,realize,advance这些应该都是对场景的初始化,然后再对事件、更新回调进行遍历、处理。最后完成场景的筛选和绘制。
这里是分割线,可以跳过,下面一部分是我自己写的内容。
当前位置:osgViewer/ViewerBase.h
从上面一开始的viewerInit()开始吧,自己太菜,所以就不跳过这个ViewerBase类
virtual void viewerInit() = 0;
这里看到这个viewerInit()函数是一个纯虚函数,也就是说,
a.这个ViewerBase基类只能被继承,不能被实例化。
b.这个viewerInit()方法必须在派生类中被实现。
上图可以看到单视景器类,和多视景器类都继承了这个ViewerBase的基类。这里感觉自己在说废话。
这里只看Viewer类。所以我们转到Viewer类
当前位置 osgViewer/Viewer.h
virtual void viewerInit() { init(); }
这里就是调用了init()函数,再来找这个init()
这里一开始有一点疑惑,没有在Viewer类中找到这个init()方法。实际上这里是调用的父类View类里的init()方法。
这里我明白了,如果子类公有继承父类,可以在子类的成员函数中直接调用父类的公有成员函数。像下面一
#include
using namespace std;
class A
{
public:
void init(){cout << "A.init()" << endl;}
};
class B :public A
{
public:
void Binit(){init();}
};
int _tmain(int argc, _TCHAR* argv[])
{
B b;
b.Binit();
return 0;
}
继续看View::init()
这里是分割线,到王锐大大的了。
当前位置:osgViewer/View.cpp 第257行 osgViewer::View::init()
完成视景器的初始化工作。
void View::init()
{
OSG_INFO<<"View::init()"< initEvent = _eventQueue->createEvent();
initEvent->setEventType(osgGA::GUIEventAdapter::FRAME);
if (_cameraManipulator.valid())
{
_cameraManipulator->init(*initEvent, *this);
}
}
两个重要的类成员变量_eventQueue和_cameraManipulator。
_eventQueue:存储该视景器的事件队列。osgGA::GUIEventAdapter是OSG中的事件的类。
_eventQueue中保存了一个GUIEventAdapter的链表,提供了一系列对链表元素的操作函数。如creatEvent(),setEventType()等
creatEvent(): 分配和返回一个新的GUIEventAdapter事件的指针(ref_ptr),
setEventType(): 设置这个事件的类型为FRAME,即每帧都会触发这个事件。
_cameralManipulator视景器中所用的场景漫游器的实例, 通常使用setCameraManipulator来设置这个变量的内容。
_cameraManipulator->init(*initEvent, *this);
这个代码,将新创建的FRAME事件,和Viewer对象本身传给_cameralManipulator的init函数,不同的漫游器会重写各自的init函数,实现自己所需的初始化工作。(用户也可以这么做,从而得到自定义的场景漫游器)