任何程序都是有生命的,是生命就需要呼吸。例如普通的windows程序,当运行完main()函数后,就需要进入消息循环,来监听用户的各种操作,以便做出及时的回应。这样的每次循环就像生命的每次呼吸,来维持生命体征。

osg的程序不仅仅需要消息循环来监听用户的鼠标、键盘等操作,同时也得具备了渲染循环。当然随着我们的对osg的深入了解会发现,osg的事件监听和渲染循环是串行的。但是当我们把osg与MFC(QT)等结合时,相应UI上的鼠标,键盘事件的同时也要兼顾可能发生在osg中的效果,所以一般的osg程序起码需要两个并行的线程(例如osg与qt结合使用,为了保持足够灵敏的相应速度就需要把QTUI和osg渲染看成两种生命,分为两个线程)来维持它的正常运行。我们今天就是要解读osg程序赖以生存的每次呼吸。

首先我们得找到osg是用什么呼吸的,就想地球上的一般生物都是用鼻子呼吸,我们又大概得知道鼻子长在生物的那个位置。这样我们才可以开始我们的研究。当然我们肯定得有osg的源码,就像我们研究生物的呼吸先得有这种生物的身体。有了身体我们还得持续的观察一个有生命的生物,所以我们最先得到osg的可运行的程序就是example中的各种程序。其中大部分的程序main()函数的最后部分都是调用一下viewer.run()。

所以我们可以有一个模糊的判断这一类的通过调用viewer类的run函数的程序,他的呼吸系统可能是通过run完成的。但是run()函数是一个单独的一行,按说他执行完毕以后程序就会结束了,所以我们有了新的判断osg的每一帧的调用的入口是在run()函数中的。这是osg程序存在的一种形式(或者叫独立运行模式)。Osg还有另一种存在形式,就是和各种UI混合使用,例如qt与osg结合使用,MFC与osg结合使用等等。我们可以从examples/osgviewerQt 的例子,可以根据上一个的思路,呼吸不是一次性的动作,是只要存活就会一直存在的。所以从osgviewerQt.cpp中根据以前的经验定位到timer (计时器),他每次timeout触发时调用的函数update()中一定包含了osg的每一帧的调用的入口。

根据上面两种osg的存活形式,可以进行进一步的确认,究竟哪里才是维持osg生命体征的位置。Viewer.run()函数(OSG Core/osgViewer/Viewer.cpp)最后会继续调用ViewerBase::run()函数(OSG Core/osgViewer/ViewerBase.cpp),

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

  

//OSG Core/osgViewer/ViewerBase.cpp
int ViewerBase::run()
{if (!isRealized()){realize();}const char* run_frame_count_str = getenv("OSG_RUN_FRAME_COUNT");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()<runTillFrameNumber)){double minFrameTime = _runMaxFrameRate>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 rateosg::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;
}

  

我们在ViewerBase::run()中继续耐心的寻找就会发现有一个特殊的函数frame(),为什么特殊呢?因为frame的英文的意思就是’帧’,而我们学渲染都知道’帧’代表屏幕上一幅画,这和osg库的本质就联系在了一起。Osg就是一个库,一个在计算机屏幕上作画的库。所以ViewerBase::frame()就是我们要找的osg中会呼吸的地方。同样我们在examples/osgviewerQt中也会发现,timer每到设定事件就会调用update()函数,而qt的update()函数在内部就会调用paintEvent()函数,我们在osgviewerQt.cpp的paintEvent()函数中也会发现osg::CompositeViewer的update函数,而osg::CompositeViewer继承自ViewerBase,所以最后也会定位到ViewerBase::frame()。这样我们就可以确定osg这类生物的呼吸的入口是ViewerBase::frame()函数。终于我们打开了通往新世界的大门,下一步就是经历轮回,看看osg这类生物是怎么生存的。

欢迎大家来我的新家看一看 3wwang个人博客-记录走过的技术之路

转载于:https://www.cnblogs.com/wang985850293/p/10419542.html

探索未知种族之osg类生物---起源相关推荐

  1. 类的初始化列表_探索未知种族之osg类生物---渲染遍历之draw函数二

    我们今天今天真是进入SceneView::draw()函数. 1.判断主相机是否为隐藏状态也就是(camera->getNodeMask()==0),隐藏状态就会退出这个draw函数. 2.开始 ...

  2. 退出所有循环_探索未知种族之osg类生物---呼吸分解之事件循环三

    那我们就开始处理这些事件中得到的所有的交互事件,首先我们要判断这些事件是否包含osg的退出事件,那什么情况下会触发这个退出事件呢?如果您运行过osg中example中的小例子的,聪明的你一定就会发现当 ...

  3. osg动态加载模型不显示_探索未知种族之osg类生物---渲染遍历之Renderer::draw()简介...

    我们今天进入上一节的遗留问题Renderer::draw()的探究. 1.从_drawQueue中取出其中一个sceneView对象.SceneView是对scene和view类的封装,通过他可以方便 ...

  4. 探索未知种族之osg类生物---器官初始化一

    我们把ViewerBase::frame()比作osg这类生物的肺,首先我们先来大概的看一下'肺'长什么样子,有哪几部分组成.在这之前得对一些固定的零件进行说明,例如_done代表osg的viewer ...

  5. 探索未知种族之osg类生物---器官初始化四

    上一节我们对完成了对osg生物内部非常重要器官graphicsContext的初始化工作.这样就可保证我们场景中至少有一个graphicContext存在,不至于刚出生就面临夭折.我们根据上一节中os ...

  6. 探索未知种族之osg类生物---呼吸分解之更新循环一

    上节总结 前几天我们大体上介绍完成了osg的事件循环的介绍,总结一下osg的时间循环主要就是得到平台(windows)的所有消息,并遍历所有的node的eventCallback,并对他们进行处理.接 ...

  7. 【乘风破浪的开发者】丁一超:从AI实战营出发探索未知的AI世界

    摘要:从年初的不知不觉进入AI学习的道路,到认识并熟练使用ModelArts平台.虽然只有短短的半年,但这半年的探索学习,让丁一超看清了未来的路在何方. 从招聘网站上输入"人工智能工程技术人 ...

  8. 大学英语(第六册)复习(原文及全文翻译)——Unit 10 - Debating The Unknowable(探索未知世界)

    Unit 10 - Debating The Unknowable Do animals think? How could the earth show so many signs of design ...

  9. Conflux人物志-伍鸣博士:好奇心是我探索未知世界的动力

    江湖人称"伍爷"的伍鸣博士作为Conflux团队的创始成员之一,同时还担任了Conflux CTO的职务.毕业于中国科学技术大学的他,在2007年取得中科院计算所计算机系统结构博士 ...

最新文章

  1. iPhone App开发实战手册学习笔记(5)之IOS常用机制
  2. 一直学不明白的「递归」与「动态规划」原来这么简单
  3. vue 使用element 菜单与tab页联动
  4. C++ leetCode 判断一个整数是否为回文数 9. 回文数 判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
  5. TensorFlow + Docker + PyCharm
  6. 函数:MySQL中字符串匹配函数LOCATE和POSITION使用方法
  7. hdu 3923 Invoker
  8. 【题解】Grape luogu1156改 dp
  9. 30秒清除你电脑中的垃圾
  10. 四元组相加获得target
  11. java 数组转化为arraylist_在Java中怎样把数组转换为ArrayList?
  12. 用python把unix格式转换成windows格式
  13. ARouter 源码历险记 (四)
  14. cart算法 java_决策树学习笔记(三):CART算法,决策树总结
  15. 关于苹果侵权邮件反馈邮件范文
  16. 图片转ICO工具新版本(支持更多图片格式,支持更多分辨率,原生更快)
  17. 网络信息安全从业者,持NISP二级或CISP证书,最高可补贴30000元
  18. 無襯線體(Sans-serif)
  19. 知网、万方paperfree 查重的区别
  20. ESP32(arduino)和声音传感器数据采集并实现连接WiFi进行MQTT通信

热门文章

  1. kubernetes组件
  2. 判断 多选框是否有选择 适用于批量操作
  3. SharePoint 2013的100个新功能之网站管理(二)
  4. avrstudio5 拨码管
  5. civil 3d 计算机配置,Civil 3D 2009安装后无法启动
  6. c java http_[C] 类似于HttpClient的C语言实现Http POST功能如何实现?
  7. rabbitmq消费固定个数消息_SpringBoot+RabbitMQ (保证消息100%投递成功并被消费)
  8. css rem 大屏开发_px和em、rem单元如何选择?
  9. linux谁动了我的服务器,linux系统监控之谁动了我的服务器?
  10. C++知识点54——RTTI(运行时类型识别)