事件循环和更新循环
终于到了我们嘴里经常念叨的事件循环、更新循环以及渲染循环了。首先我们来区分一下事件循环和渲染循环,他们两个首先是两个不同顺序执行的过程,我们有时候会用到任意node的updateCallback函数,这个就是在更新循环的时候遍历所有的node来调用updateCallback函数的;而事件循环是与用户操作和操作系统事件想关联的,以及调用我们设置的事件回调(EventCallback)函数。而事件循环函数(viewer::eventTraversal())是我们现在要探究的内容。
osgViewer::Viewer::eventTraversal()
1
2
3
4
5
6
7
8
9
10
11
12
13
|
if (_done) return ;
double cutOffTime = _frameStamp->getReferenceTime();
double beginEventTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
// OSG_NOTICE<<"Viewer::frameEventTraversal()."<<std::endl; // need to copy events from the GraphicsWindow's into local EventQueue; osgGA::EventQueue::Events events; Contexts contexts; getContexts(contexts); // set done if there are no windows checkWindowStatus(contexts); if (_done) return ;<br><br>
|
进入这个函数,我们发现前几行都是我们以前介绍过的osg器官。首先记录了事件循环的开始时间,这样做的目的是:与这个函数最后记录的时间进行比较,然后记录在_stats记录器中,这样可以帮助开发者了解每一帧当中事件遍历,更新遍历和渲染遍历运行所占用的时间比例,以便对整个程序进行调优工作。然后得到所有的GraphicsContext,保存到contexts中,当contexts为空时,意味着没有最终的画布,osg会结束运行,通过设置_done=true;
然后的主要工作是:事件循环会得到已经发生的所有事件,并进行一定的筛选工作,最后全部都传给各自的事件处理器。所以我们首先对其中一些新成员进行简单的介绍:
- eventState事件队列的目前的状态事件,eventState的设置是通过osgGA::EventQuene::setCurrentEventState函数进行设置的。
- _eventSources 实在osgViewer::View下的成员变量,通过View::addDevice()函数来添加新的设备,他的主要作用就是在每一个帧的事件循环中便利所有的设备,然后得到通过Device :: getEventQueue收集生成的所有的事件。
搬掉了几块绊脚石,那么现在我们就可以继续前行了。osgViewer::viewer::eventTraversal()中第一个for循环的目的就是遍历所有的设备所发生的事件,并保存到viewer::events中。这些设备就包含鼠标,键盘等发生的事件。
1
2
3
4
5
6
7
8
9
10
11
12
|
for (Devices::iterator eitr = _eventSources.begin();
eitr != _eventSources.end();
++eitr)
{
osgGA::Device* es = eitr->get();
if (es->getCapabilities() & osgGA::Device::RECEIVE_EVENTS)
es->checkEvents();
// open question, will we need to reproject mouse coordinates into current view's coordinate frame as is down for GraphicsWindow provided events?
// for now assume now and just get the events directly without any reprojection.
es->getEventQueue()->takeEvents(events, cutOffTime);
}
|
然后再一个for循环,得到所有的GraphicsContext中的event并插入到eventQuene链表中,也就是诸如鼠标的移动,键盘上的按键被按下,窗口的尺寸被改变等动作,都会作为一个新的 GUIEventAdapter 对象插入到链表中,插入事件的方法是由图形窗口GraphicsWindow执行EventQueue类的成员函数 mouseMotion,keyPress和 windowResize,并间接地调用 EventQueue::addEvent 函数。而这些事件之间可能共通的参数和状态就从“状态事件”中读取。然后我们再会对窗口上发生的点击,释放,拖拽,双击和移动事件中的鼠标坐标进行统一的投影变换,使鼠标坐标重新投影到当前视图的坐标系中。
现在我们就主要来讲解一下鼠标坐标到视图坐标系的转换。
当鼠标只是进行单点操作,或者当然的事件的GraphicsContext不是主GraphicsContext时,需要调用generatePointerData函数来对鼠标的坐标进行转换。Viewer::generatePointerData()函数中,在这里我们要普及一点知识osg或者说opengl中屏幕坐标的原点在左下角,而windows的坐标原点在右上角,所以在这个函数中我们首先需要把判断我们所使用的平台的原点和osg的原点是否相同,如果不同则需要把鼠标坐标的y取反一下(gw->getTraits()->height - y)。然后把新的到的坐标点设置回事件信息中,并把Y轴模式改为向上增长(Y_INCREASING_UPWARDS).然后我们得到此时这个GraphicsContext下的所有的正在使用到的相机,并选出目前鼠标事件中的x,y所处在那几个相机的视口中,得到这几个相机作为活动相机。然后根据相机的先后渲染顺序进行排序,因为我们最后渲染的肯定会覆盖先前的,所以我们只需把鼠标坐标投影到最后渲染的相机的视图上就可以了。因为视口的坐标都是以0到1间的数字来表示的,所以鼠标的坐标通过一定的线性变换就可以变换到视口坐标系内
1
|
event.addPointerData( new osgGA::PointerData(camera, (x-viewport->x())/viewport->width()*2.0f-1.0f, -1.0, 1.0,(y-viewport->y())/viewport->height()*2.0f-1.0f, -1.0, 1.0));<br>
|
当然上面所说的适口坐标肯定是主摄像机的视口坐标,如果是目前鼠标是在从相机中移动的,那么再转换到主摄像机坐标系中。这个过程大概可以理解成这样,我们首先要把鼠标的坐标按照从相机的MVP矩阵转换到世界坐标系中,再根据主相机的MVP矩阵把刚刚得到的世界坐标转换到主摄像机的视口中,最后完成了从相机到主相机的坐标转换。
欢迎大家来我的新家看一看 3wwang个人博客-记录走过的技术之路
相关推荐
截止到2020/03/10最新版本的osg和osgEarth开发库,osg版本为3.6.4,osgEarth版本为2.10.2,之前编译了VS2017版本的开发库,有网友反映需要32位的开发库,当时确实没时间专门编译32位的开发库,最近正好有个项目需要...
标题 "osg3.4-osgearth2.8-2015-x64.7z" 暗示了这是一个针对64位Windows系统(x64)的软件包,包含了OpenSceneGraph(osg)3.4版本和osgEarth 2.8版本的相关组件。OpenSceneGraph是一个开源的3D图形库,而osgEarth则...
【osg-windows-binaries-master.zip】是一个包含osg285版本的OpenSceneGraph(简称OSG)库的压缩包,特别针对Windows平台进行了优化。OpenSceneGraph是一个开源的高性能图形库,广泛用于3D图形应用程序开发,如游戏...
【osg-data-master.zip】是一个包含osgEarth相关数据的压缩包,这个名字暗示了它与开源图形库OpenSceneGraph(OSG)的扩展模块osgEarth有关。OpenSceneGraph是一个强大的3D图形编程库,主要用C++编写,广泛应用于...
【osg同心球】是OpenSceneGraph(简称osg)库中的一个特定概念,它涉及3D图形编程和场景图管理。OpenSceneGraph是一个开源的高性能3D图形库,用于创建交互式实时应用程序。在这个上下文中,"同心球"可能指的是一个...
编译osgearth-osgearth-2.5所需要的依赖包 包括以下资源: 3rdParty_VC10_x86_x64.zip curl-7.25.0.zip expat-win32bin-2.0.1.rar gdal181.zip geos-3.2.3.tar.bz2 libzip(vs10).rar OpenSceneGraph-3.0.1.zip ...
《gwaldron-osgearth-osgearth-2.8-0-g449e80a:探索OSGEarth的2.8.0版本》 在IT领域,尤其是在三维地理信息系统(GIS)的世界中,osgEarth是一个备受瞩目的开源项目。这个名为“gwaldron-osgearth-osgearth-2.8-0-...
《OSG2CesiumApp-V1.10:将倾斜摄影osgb数据转换为3DTiles的实用工具》 在现代地理信息系统(GIS)和虚拟现实应用中,3DTiles是一种广泛采用的数据格式,它允许高效地在Web浏览器中加载和展示大规模三维地形和建筑...
osgEarth是基于三维引擎osg开发的三维数字地球引擎库,在osg基础上实现了瓦片调度插件,可选的四叉树调度插件,更多的地理数据加载插件(包括GDAL,ogr,WMS,TMS,VPB,filesystem等),再结合一套地理投影转换插件...
首先,“gwaldron-osgearth”很可能指的是开发者或者项目名,它指向了一个与osgEarth相关的开发工作。osgEarth是一个开源的、基于OpenGL的地理可视化库,用于在3D场景中展示地球数据。接着,“2.7”是版本号,这通常...
在网上看了很多个版本的编译库,感觉不是很符合需求,有些库太老,有些依赖库版本不一致,我特意根据osg3.6.5和gdal3.0.4编译了VS2019版本的osgearth3.1,O基于GL2版本,适用性较强,亲测可用,无异常,同时提交了...
1、OSGEarth2.10源码预编译好的二进制开发包(64位) 2、基于OSG3.6.5版本 3、基于Visual Studio2019编译的64位版本
"OSG转osgb-obj-ive格式工具.rar"是一个专门用于3D模型格式转换的实用程序,主要服务于倾斜摄影模型的处理工作。这个压缩包包含了能够将osg、osgb、ive和obj等格式互相转换的软件工具,这极大地提升了在不同平台和...
场景图(SceneGraph)是OSG的核心概念之一,它以树形结构组织图形世界中的所有对象。每个节点(Node)都是场景图中的一个元素,可以包含几何体、坐标系统、相机等。场景子树(Subgraph)是节点的一种特殊类型,代表...
osgEarth是一个基于OpenSceneGraph(osg)的开源库,用于创建交互式的3D地球应用程序。它提供了丰富的功能,包括地形渲染、遥感图像处理、GPS数据集成以及各种地理数据格式的支持,是地理信息系统(GIS)领域的一个...
截止到2020/03/10最新版本的osg和osgEarth开发库,osg版本为3.6.4,osgEarth版本为2.10.2,之前编译了VS2017版本的开发库,有网友反映需要32位的开发库,当时确实没时间专门编译32位的开发库,最近正好有个项目需要...
在`OSG-Dragger-Dragger.pdf`文档中,读者可以期待找到更多关于`osg::Dragger`类的详细信息,包括如何创建和使用自定义的Dragger,以及如何结合`PointInfo`进行更复杂的交互设计。这份资料将帮助开发者深入理解如何...
osg是一个C++库,它的主要目标是提供一个高效、灵活的框架,用于创建复杂的3D场景和交互式应用。其关键功能包括: 1. **三维几何处理**:osg支持多种几何对象的创建、编辑和渲染,如点、线、面、多边形等,并提供了...
3. **渲染循环**:由于osg有自己的渲染循环,而Qt也有自己的事件处理循环,所以需要协调这两个循环,确保3D视图能够正确更新。 4. **性能优化**:在嵌入osg到Qt时,可能会面临性能问题,因为两个框架都可能有自己的...
osg(OpenSceneGraph)是一个开源的高性能3D图形库,它基于OpenGL,用于构建复杂的实时3D应用。osg的核心是场景图模型,它允许开发者以树形结构组织3D对象和图形状态,使得渲染、动画和交互操作变得简单。osg提供了...