我是靠谱客的博主 光亮钢笔,最近开发中收集的这篇文章主要介绍OSG 《最长的一帧》 学习笔记-frame(一),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

frame()作为渲染函数,只有简单的一句,但是它的内部到底是怎样的呢,我会跟着《最长的一帧》一起慢慢学习。
///为frame()源码,后面会深入解析每一个变量,每一个函数的源码//
 
 
void ViewerBase::frame()//frame的内部实现
{
    if(_done) return;
    if(_firstFrame)
    {    
     viwerInit();//如果是启动后第一帧,则执行该函数
    }
    if(!isRealised())
     {
     realize();//如果还没有执行realize(),则执行它
    }
    _firstFrame=false;
    advance(simulationTime);
    eventTraversal();//负责处理系统产生的各种事件,诸如鼠标的移动,点击,和键盘的相应,窗口的关闭,以及摄像机与场景图形的时间回调(
    EventCallback) updateTraversal();//负责遍历所有的更新回调(UpdateCallback),负责更新DatabasePager和ImagePager这两个重要分页 数据处理组件
    renderingTraversals();//使用比较负责的线程处理方法,完成场景的筛选(cull)和绘制(draw)工作
}

frame()函数内部执行的上面的几个步骤,但其功能来说,是完成了OSG场景渲染的一帧。

1.viewerInit函数调用了View::init()函数
void View::init()//完成视景器的初始化工作
{
    OSG_INFO<<"View::init()"<<std::endl;

    osg::ref_ptr<osgGA::GUIEventAdapter> initEvent = _eventQueue->createEvent();//
 _eventQueue:视景器的事件队列,代表事件的类:osgGA::GUIEventAdapter,用于表达各种类型的鼠标键盘,触压笔和窗口事件。eventQueue保存了一个GUIEventAdapter链表,还提供了一系列对该链表及元素的操作函数。createEvent作用是分配和返回一个新的GUIEventAdapter事件指针。
      initEvent->setEventType(osgGA::GUIEventAdapter::FRAME);  //指定该事件类型为FRAME事件,即每帧都会触发的一个事件
   if (_cameraManipulator.valid())
  {
     _cameraManipulator->init(*initEvent, *this);//_cammeraMainipulator是视景器中所用的场景漫游器的实例,将当前创建的                                                                                                               FRAME事件和Viewer对象传递给漫游器的初始化函数。
    }
}
//GUI事件处理器:GUI事件适配器(GUIEventAdapter)和GUI动作适配器(GUIEventHandler)后面会写到

2.realize()函数 完成窗口和场景的“设置”工作
///realize()源码///
 

void Viewer::realize()
{ //OSG_INFO<<"Viewer::realize()"<<std::endl;
Contexts contexts;// 保存了osg::GraphicsContext指针的向量组
getContexts(contexts);// 获取所有的图形上下文,并保存在这个向量组中来(osg3.0中,根据函数功能来看,只获取了一个有效的图形上下文设备)
/*图形上下文:在osgViewer::Viewer还没有任何操作的时候,系统不会存在任何图形上下文,创建一个新的osg::Camera对象,也不会为其自动分配图形上下文。图形上下文是场景显示的唯一平台,系统有必要在开始渲染之前完成其创建工作*/
if (contexts.empty())
{ //如果此时contexts还没有得到任何图形上下文设备的花,说明仿真系统还没有合适的显示平台,此时需要创建一个缺省的GraphicsContext设备。
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
const char* ptr = 0;
if ((ptr = getenv("OSG_CONFIG_FILE")) != 0)
{
     readConfiguration(ptr); //如果能够读取用户在该环境变量下定义的文件路径,并用cfg成功解析,调用take,使用配置信息设置当前视景器
 }
else
{
    int screenNum = -1;
    if ((ptr = getenv("OSG_SCREEN")) != 0)
    {
    if (strlen(ptr)!=0)
            screenNum = atoi(ptr);// 读取环境变量中的屏幕个数
    else  screenNum = -1;
}
int x = -1, y = -1, width = -1, height = -1;
if ((ptr = getenv("OSG_WINDOW")) != 0)
{
     std::istringstream iss(ptr);
    iss >> x >> y >> width >> height;// 读取环境变量中的x,y,宽和高
}
if (width>0 && height>0)
{
     if (screenNum>=0)
    setUpViewInWindow(x, y, width, height, screenNum);
    else setUpViewInWindow(x,y,width,height);// 根据窗口信息创建设备
}
else if (screenNum>=0)
{
     setUpViewOnSingleScreen(screenNum);// 根据屏幕数量创建图形窗口,为每一个显示屏创建一个全屏的图形窗口
}
else
{
     setUpViewAcrossAllScreens();// 不满足上面条件时,创建一个全屏显示的图形设备
}
}
getContexts(contexts);
}
if (contexts.empty())
{
     OSG_NOTICE<<"Viewer::realize() - failed to set up any windows"<<std::endl;
    _done = true;
     return;
} //再次执行,如果还没有任何图形上下文的话,就不得不退出程序了 
}

2.1 getContexts()  获取图形上下文设备,并保存在Contexts向量组中



void Viewer::getContexts(Contexts& contexts, bool onlyValid)
{
     typedef std::set<osg::GraphicsContext*> ContextSet;
    ContextSet contextSet;
    contexts.clear();
    if (_camera.valid() && _camera->getGraphicsContext() && (_camera->getGraphicsContext()->valid() || !onlyValid))// 判断场景的主摄像机是否包含了一个有效的GraphicContext设备
    {
         contextSet.insert(_camera->getGraphicsContext());
        contexts.push_back(_camera->getGraphicsContext());// 如果主摄像机包含一个有效的GraphicContext设备,则存入到传入的参数中
    }
for(unsigned int i=0; i<getNumSlaves(); ++i)// 遍历所有的摄像机
{
     Slave& slave = getSlave(i);
    osg::GraphicsContext* sgc = slave._camera.valid() ? slave._camera->getGraphicsContext() : 0;// 如果该相机有效,则定义一个新的图形上下文设备,并将当前的相机所包含的有效GraphicsContest设备赋值给sgc
if (sgc && (sgc->valid() || !onlyValid))
{
    if (contextSet.count(sgc)==0)
    {
          contextSet.insert(sgc); contexts.push_back(sgc);// 查看contextset中有没有图像上下文设备,如果没有就添加给传入的向量数组contexts
    }
}
}
}
总结:函数功能为-为传入的contests向量组中添加一个场景相机中所包含的图形上下文设备。优先添加主摄像机的图形上下文设备。

最后

以上就是光亮钢笔为你收集整理的OSG 《最长的一帧》 学习笔记-frame(一)的全部内容,希望文章能够帮你解决OSG 《最长的一帧》 学习笔记-frame(一)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(39)

评论列表共有 0 条评论

立即
投稿
返回
顶部