OSG在实际使用过程中会加载大量的场景数据,然而大量数据的加载又对计算机的性能提出了更高的要求,会对计算系统造成极大的负担。
虽然可以通过裁剪等方法可以保证每一帧只用有一部分数据显示或者使用LOD来牺牲一部分显示质量来换取效率的提升,但是这些都不能解决大量数据读入内存的问题。
那么,OSG的数据分页技术就产生了。
数据的分页也就是数据的动态调度机制:在显示当前场景的同时,预判断下一步可能载入的数据,以及卸载那些短时间内不可能被看到的对象,确保内存中始终有限的数据,并且不会造成场景浏览时重要信息的丢失或者过于迟缓。
数据的动态调用加载或者卸载可以使用多线程的方式进行,使数据的冬天调度和实时绘制可以同时进行。由于动态数据的加载卸载会影响场景树的结构,因此这个过程需要在场景更新阶段完成。
动态调度数据分为以下几个功能:
- 删除过期的场景数据:过期数据指的那些长时间没有在用户的视域内,并且有理由认为他们不会短期显现的场景数据。场景的更新遍历函数负责将检索到的过期对象收集到相应的过期对象列表中。过期数据列表中的数据可以在线程中统一予以删除。
- 获取新的数据加载请求:请求加载可能是新的数据信息,也可能是已有的场景数据(曾经从当前页面中剔除,现在有要回到当前页面中)。
- 编译记载的数据:有些数据经过编译后可以有效的提高效率。
- 将加载的数据合并至场景中:不应该有数据线程来操作,应该先将读入的数据保存到一个列表中,并且仿真循环获取或执行合并新节点。
一个动态加载数据的实例:
void createPagerLOD() {
osg::ref_ptr<osg::Group> root = new osg::Group;
for (int i = 0; i < 30;i++) {
for (int j = 0; j < 30; j++) {
osg::ref_ptr<osg::PagedLOD> pageLod = new osg::PagedLOD;
pageLod->setCenter(osg::Vec3(i * 10, j * 10, 0.0));
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(i * 10, j * 10, 0.0),1.0)));
pageLod->addChild(geode, 200, FLT_MAX);
pageLod->setRange(1, 0.0, 200.0);
root->addChild(pageLod);
}
}
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
viewer->addEventHandler(new osgViewer::WindowSizeHandler());
viewer->addEventHandler(new osgViewer::StatsHandler());
viewer->setSceneData(root.get());
viewer->realize();
viewer->run();
}
aaa