OSG渲染之最长的一帧笔记系列文章
第一章 第一日内容 frame() 函数和 viewerInit() 函数介绍
前言
本系列文章主要是利用王锐老师《最长的一帧》撰写读书笔记,以便更加简洁且有条理地去重复查阅和理解书籍内容。
一、frame()函数
所属模块和文件:osgViewer/ViewerBase.cpp。
frame() 是 ViewerBase类的成员函数,而非 Viewer 类。因此,无论对于单视景器的 Viewer 类,还是多视景器的CompositeViewer 类,frame 函数的内容都是相同的(因为它们都没有再重写这个函数的内容)。
代码如下:
void ViewerBase::frame(double simulationTime)
{
if (_done) return;
// OSG_NOTICE<<std::endl<<"CompositeViewer::frame()"<<std::endl<<std::endl;
//如果这是仿真系统启动后的第一帧
if (_firstFrame)
{
viewerInit();
//此时如果还没有执行 realize()函数,则执行它
if (!isRealized())
{
realize();
}
_firstFrame = false;
}
advance(simulationTime);
/*这个函数将负责处理系统产生的各种事件,诸如鼠标的移动,点击,键盘的响应,窗口的关闭等等,
以及摄像机与场景图形的事件回调(EventCallback)。*/
eventTraversal();
/*这个函数负责遍历所有的更新回调(UpdateCallback);除此之外,它的另一个重要任务就是负责更
新 DatabasePager 与 ImagePager 这两个重要的分页数据处理组件。*/
updateTraversal();
/* 这里将使用较为复杂的线程处理方法,完成场景的筛选(cull)和绘制(draw)工作*/
renderingTraversals();
}
二、Viewer::viewerInit()函数
所属模块和文件:osgViewer/View.cpp。
Viewer::viewerInit 函数只做了一件事,就是调用 View::init()函数,而这个 init 函数的工作似乎也是一目了然的:无非就是完成视景器的初始化工作而已。
代码如下:
void View::init()
{
OSG_INFO<<"View::init()"<<std::endl;
osg::ref_ptr<osgGA::GUIEventAdapter> initEvent = _eventQueue->createEvent();
//随后这个新事件的类型被指定为 FRAME 事件,即每帧都会触发的一个事件。
initEvent->setEventType(osgGA::GUIEventAdapter::FRAME);
if (_cameraManipulator.valid())
{
_cameraManipulator->init(*initEvent, *this);
}
}
1、_eventQueue 它用于储存该视景器的事件队列。OSG中代表事件的类osgGA::GUIEventAdapter,它可以用于表达各种类型的鼠标、键盘、触压笔和窗口事件。在用户程序中,我们往往通过继承 osgGA::GUIEventHandler 类,并重写 handle 函数的方法,获取实时的鼠标 / 键盘输入,并进而实现相应的用户代码(参见osgkeyboardmouse)。
_eventQueue 除了保存一个 GUIEventAdapter 的链表之外,还提供了一系列对链表及其元素的操作函 数,这其中,createEvent 函数的作用是分配和返回一个新的 GUIEventAdapter事件的针。
2、cameraManipulator 是视景器中所用的场景漫游器的实例。通常我们都会使用 setCameraManipulator 来设置这个变量的内容,例如轨迹球漫游器(TrackballManipulator)可以使用鼠标拖动来观察场景,而驾驶漫游器(DriveManipulator)则使用类似于汽车驾驶的效果来实现场景的漫游。
3、上面的代码将新创建的 FRAME 事件和 Viewer 对象本身传递给_cameraManipulator 的init 函数,不同的漫游器(如 TrackballManipulator、DriveManipulator)会重写各自的 init 函数,实现自己所需的初始化工作。如果读者希望自己编写一个场景的漫游器,那么覆写并使用 osgGA::MatrixManipulator::init 就可以灵活地初始化自定义漫游器的功能了,它的调用时机就在这里。
总结
以上就是今天要讲的内容,本文仅仅简单介绍了osgGA::EventQueue::createEvent,osgGA::MatrixManipulator::init,osgViewer::View::init,osgViewer::Viewer::viewerInit的内容。