本文主要是介绍Cover王锐大大——最长的一帧(第二日),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
第一天我们走到了ViewerBase::frame()的viewerInit()这一步,第二天就继续来看看realize()这里做了什么工作。
当前位置:osgViewer/ViewerBase.h
/** set up windows and associated threads.*/virtual void realize() = 0;
又是一个纯虚函数,继续到Viewer里面去找。
当然位置:osgViewer/Viewer.cpp 第473行 osgViewer::Viewer::realize()
realize(),完成窗口和场景的“设置”工作。这里是OSG会自动调用它,因为我对这个函数一点都不熟悉。这个realize()函数不简单的,接近两百行的代码一定完成了很多很多的“设置”工作。
这里王锐大大提到的setCameraWithFocus(0)现在这个版本的OSG已经没有文中的setCameraWithFocus(0)了。所以先忽略掉吧。
Contexts contexts;getContexts(contexts);
这里的Contexts是一个vector<osg::GraphicsContext*>的别名。typedef std::vector<osg::GraphicsContext*> Contexts;
GraphicsContext是图形设备类定义场景渲染所处的设备平台,它可以是一个图形窗口,也可以是一个离屏渲染设备。
contexts变量保存了osg::GraphicsContext指针的向量组,Viewer::getContexts函数的作用是获取所有的图形上下文,这里我不太理解什么是图形上下文,英文就是GraphicsContext,并保存到这个向量组中。
如果要将OSG嵌入到GUI系统中(MFC.QT等)都需要和osg::GraphicsContext打交道。文中讲到了一种常用的嵌入方法,表示还看不懂,只需记住如果要用OSG嵌入Qt,这个类会起到作用。
过程是这样的:
a.设置嵌入窗口的特性(Traits),例如X,Y位置,宽度和高度,以及父窗口的句柄
b.然后根据特性的设置创建一个新的图形设备上下文(GraphicsContext),将其赋予场景所用的摄像机。
当然位置:osgViewer/Viewer.cpp 第1291行 osgViewer::Viewer::getContexts(Contexts& contexts, bool onlyValid)
typedef std::set<osg::GraphicsContext*> ContextSet;
ContextSet contextSet;
contexts.clear();
ContextSet是std::set<osg::GraphicsContext*>的别名,是一个保存图形上下文的关联容器。set是关键字即值,只保存关键字的容器。
vector::clear()方法清掉了向量组中的元素。接着作三个判断,(1)是否有合法的主相机_camera,(2)主相机是否包含一个GraphicsContext(3)且这个图形设备有效
contextSet.insert(_camera->getGraphicsContext());contexts.push_back(_camera->getGraphicsContext());
如果满足上面三个条件,则将主相机获取的GraphicsContext保存进来,插入到contextSet中,添加到contexts中。
接着遍历所有的从相机_slaves(一个视景器可以包含一个主相机,多个从相机),同样的判断从相机是否包含有效的GraphicsContext设备。再类似上面的方法保存所有找到的图形上下文设备。
这里没有看到王锐大大说的使用std::sort来进行排序工作的代码。或许是改版了。
这里需要看一下osgcamera这个例子。明天的时候来看。
继续回到realize()
当然位置:osgViewer/Viewer.cpp 第473行 osgViewer::Viewer::realize()
接下来的一段文字感觉更加不理解了。继续啃吧。这里对图形上下文这个概念真的不是很清楚,这里就暂且理解为绘制图形所需的一些设置参数内容之类的吧。
当程序还没有进入仿真循环,且没有对osgViewer::Viewer进行任何操作,系统是不会存在任何图形上下文的,即使创建一个新的osg::Camera对象,也不会为其自动分配图形上下文。但是,图形上下文GraphicsContext却是场景显示的唯一平台,系统有必要在开始渲染之前完成其创建工作。
—————————————我是分割线,以下是自己结合代码和锐神的说明整理的————————————————————
realize()函数之后的工作应该就是系统尝试创造一个缺省的GraphicsContext设备的工作了。
if (contexts.empty())
这里判断了在进入仿真循环前,用户是否自行创建了新的Camera相机对象,并为其分配了自定义的GraphicsContext设备,并将Camera对象传递给了视景器。这里需要看的例子osgViewerMFC,osgCamera。通常编写与GUI系统嵌和的仿真循环就会这么做,就是前面提到的将OSG嵌入Qt之类的,这些操作应该是在进入仿真循环前的。这个时候,系统已经不需要为图形上下文的创建做更多工作了,就不用进入下面建立缺省GraphicsContext的工作了。此时contexts应该是非空的。
OSG_INFO<<"Viewer::realize() - No valid contexts found, setting up view across all screens."<<std::endl;
// no windows are already set up so set up a default view
接着给出了注释和提示信息,没有找到合法的GraphicsContext,需要设置up view across 全屏渲染。没有已经建立好的窗口,所以建立默认的吧。
下面就是一系列的创建缺省GraphicsContext设备的代码,就不贴出来了。这里锐神给了总结。《最长的一帧》P5
在尝试创建缺省图形上下文设备后,(我为什么一会儿中文一会儿英文),再次执行getContexts,并再次判断,如果还是没有得到任何图形上下文的话,就只有退出程序了。
if (contexts.empty()){OSG_NOTICE<<"Viewer::realize() - failed to set up any windows"<<std::endl;_done = true;return;}
TODO:osgCamera, osg+QT
这篇关于Cover王锐大大——最长的一帧(第二日)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!