博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
OSG:从源码看Viewer::run() 一
阅读量:6699 次
发布时间:2019-06-25

本文共 3720 字,大约阅读时间需要 12 分钟。

刚刚入门OSG不久,一直弄不清楚它到底是如何显示一副图片的,简单从源码看下。

:所用OSG的版本为3.4 release版!

1、前言

在OSG程序中,简单展示一副图片用:

osg::ref_ptr
viewer = new osgViewer::Viewer; osg::ref_ptr
node = osgDB::readNodeFile("glider.osg"); viewer->setSceneData(node); return viewer->run();

然后在我们的计算机显示器(屏幕中心)上就会展现滑翔机的图片,并且移动鼠标、滚轮等设备还能实现对该滑翔机的旋转、缩放、平移等一系列的操作。在OpenGL中我们知道,要实现对模型的旋转缩放等功能,需要设置相机的各种参数(相机位恣,旋转角度、平移步长、转动速率等等)。osg中简简单单的几行代码,就实现了如此之多的功能,不禁要问:run()函数里边到底发生了什么。

2、第一步

打开OSG的源码,在Viewer.cpp文件中找到Viewer::run()函数的定义:

int Viewer::run(){    if (!getCameraManipulator() && getCamera()->getAllowEventFocus())    {        setCameraManipulator(new osgGA::TrackballManipulator());    }    setReleaseContextAtEndOfFrameHint(false);    return ViewerBase::run();}

可见,将一副图片的节点读入osg的场景中后,在场景的run中首先会判断该场景中有没有漫游器(getCameraManipulator返回一个osgGA::CameraManipulator),如果该场景中不存在漫游器,则调用函数setCameraManipulator创建一个跟踪球 TrackballManipulator的场景漫游器。关键来看默认的漫游器osgGA::TrackballManipulator()做了什么!

2.1 默认漫游器

先看osgGA::TrackballManipulator()的默认构造函数:

TrackballManipulator::TrackballManipulator( int flags )   : inherited( flags ){    setVerticalAxisFixed( false );}

将该类当做参数传递给了setCameraManipulator,重点来看setCameraManipulator干了什么,源码:

void View::setCameraManipulator(osgGA::CameraManipulator* manipulator, bool resetPosition){    _cameraManipulator = manipulator;    if (_cameraManipulator.valid())    {        _cameraManipulator->setCoordinateFrameCallback(new ViewerCoordinateFrameCallback(this));        if (getSceneData()) _cameraManipulator->setNode(getSceneData());        if (resetPosition)        {            osg::ref_ptr
dummyEvent = _eventQueue->createEvent(); _cameraManipulator->home(*dummyEvent, *this); } }}

可以看出,该函数主要设置了当前场景的主相机的动作,设置了当前场景节点的坐标系以及场景中的数据,同时通过设置home--漫游器初始位置。

紧接着通过setReleaseContextAtEndOfFrameHint()设置了渲染场景的上下文关系。

3、再看 ViewerBase::run()

源码:

int ViewerBase::run(){    if (!isRealized())    {        realize();    }    const char* run_frame_count_str = getenv("OSG_RUN_FRAME_COUNT"); //getenv()从环境变量中去字符串    unsigned int runTillFrameNumber = run_frame_count_str==0 ? osg::UNINITIALIZED_FRAME_NUMBER : atoi(run_frame_count_str);    while(!done() && (run_frame_count_str==0 || getViewerFrameStamp()->getFrameNumber()
0.0 ? 1.0/_runMaxFrameRate : 0.0; osg::Timer_t startFrameTick = osg::Timer::instance()->tick(); if (_runFrameScheme==ON_DEMAND) { if (checkNeedToDoFrame()) { frame(); } else { // we don't need to render a frame but we don't want to spin the run loop so make sure the minimum // loop time is 1/100th of second, if not otherwise set, so enabling the frame microSleep below to // avoid consume excessive CPU resources. if (minFrameTime==0.0) minFrameTime=0.01; } } else { frame(); } // work out if we need to force a sleep to hold back the frame rate osg::Timer_t endFrameTick = osg::Timer::instance()->tick(); double frameTime = osg::Timer::instance()->delta_s(startFrameTick, endFrameTick); if (frameTime < minFrameTime) OpenThreads::Thread::microSleep(static_cast
(1000000.0*(minFrameTime-frameTime))); } return 0;}

在该函数中,实现了每一帧的渲染、计算帧率等。

frame()中:

void ViewerBase::frame(double simulationTime){    if (_done) return;    // OSG_NOTICE<
<<"CompositeViewer::frame()"<
<

可见,在osg的每一帧的绘制中,实现了对事件的遍历(eventTraversal())、更新( updateTraversal())和渲染(renderingTraversals()),同时这也是漫游器真正被添加进来起作用的地方。至于每一帧中到底如何处理事件的(eventTraversal()函数作用),可参看源码文件Viewer.cpp中void Viewer::eventTraversal()的具体定义。

主要参考文章:

未完 待续。。。

转载地址:http://fomoo.baihongyu.com/

你可能感兴趣的文章
白盒测试不是测试,更不高级
查看>>
mysql query cache
查看>>
win7在未关闭vmware情况下直接关机,导致虚拟机无法克隆
查看>>
LAMP架构,纯文本作品
查看>>
幽幽的灵光射不出你想要的疯狂
查看>>
Servlet与JSP间的传值问题
查看>>
C#获取硬件信息
查看>>
正则表达式匹配多个字符串中的一个
查看>>
root用户登录mysql后新建用户提示1045错误
查看>>
iOS面试题(三)
查看>>
更改Docker默认的images存储位置
查看>>
Sublime Text3中文环境设置
查看>>
Mobius反演的套路
查看>>
u-boot文件夹
查看>>
SecureCRT:保存输出日志的方法
查看>>
vueX的使用
查看>>
Android的TextView在显示文字的时候,如果有段中文有英文,有中文,有中文标点符号,你会发现,当要换行的时候遇到中文标点, 这一行就会空出很多空格出来...
查看>>
bupt summer training for 16 #3 ——构造
查看>>
github 如何设置项目的语言显示
查看>>
树莓派(Raspberry Pi):完美的家用服务器
查看>>