OSG之分页细节层次节点

1,036 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 24 天

1 分页细节层次节点

分页细节层次节点(osg::PagedLOD)继承自 osg::LOD节点,它也是一个细节层次节点,用于实现动态分页加载,根据视点来加载所需要的,分页细节层次节点中还可以包含LOD节点。它与osg::LOD节点的区别是osg::LOD 节点存在于一个文件之中,osg::PagedLOD的每个节点都是磁盘中的文件,可以根据需要来加载这些文件,加载过程中有单独的线程负责实时调度及加载。

分页细节层次节点主要是用来处理大规模的数据,在地形和GIS方面有广泛的应用。可以把模型进行预处理,在渲染场景时,再根据需要来实时加载需要的数据及卸载无用的数据。

在示例程序中,我们会把PagedLOD节点写到磁盘上,以便与上一节的程序输出的LOD节点相比较。通过比较可以看出,osg::LOD节点存在于一个文件中,而PagedLOD节点只提供索引的作用,每个LOD节点存在于磁盘文件中,但不把文件存在一个文件中。

osg::PagedLOD的继承关系图如下图所示。

2.png

2 分页细节层次节点示例

分页细节层次节点(osg::PagedLOD)示例的代码如程序清单所示。

#include <osgViewer/Viewer>

#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>
#include <osg/PagedLOD>
#include <osg/MatrixTransform>

#include <osgDB/ReadFile>
#include <osgDB/WriteFile>

#include <osgUtil/Optimizer>

#include "utility.h"

//创建三级PagedLOD场景
osg::ref_ptr<osg::Group> createPagedLOD()
{
	// 创建PagedLOD对象
	osg::ref_ptr<osg::PagedLOD> page = new osg::PagedLOD;

	// 设置中心位置
	page->setCenter(osg::Vec3(0.0f, 0.0f, 0.0f));

	// 添加节点,设置0级的内容为cow.osg
	page->setFileName(0, GetCurrentPath() + "\\Data\\glider.osg");
	// 设置可视化变化范围0.0f~50.0f
	page->setRange(0, 0.0f, 50.0f);

	//添加节点,设置1级的内容为glider.osg
	//page->setFileName(1, GetCurrentPath() + "\\Data\\glider.osg");
	// 设置可视化变化范围50.0f~100.0f
	page->setRange(1, 50.0f, 100.0f);

	//添加节点,设置2级的内容为cessna.osg
	page->setFileName(2, GetCurrentPath() + "\\Data\\cessna.osg");
	// 设置可视化变化范围50.0f~100.0f
	page->setRange(2, 100.0f, 200.0f);

	return page.get();
}

int main()
{
	// 创建Viewer对象,场景浏览器
	osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();

	// 创建场景组根节点
	osg::ref_ptr<osg::Group> root = new osg::Group();

	// 创建矩阵变换节点
	osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform;
	// 添加子节点
	mt->addChild(createPagedLOD());
	// 旋转,调整到合适的角度
	osg::Matrix m;
	m.makeRotate(60.0f, 0.0f, 0.0f, 1.0f);
	// 设置矩阵
	mt->setMatrix(m);

	// 添加PagedLOD场景
	root->addChild(mt.get());

	// 写入PagedLOD
	osgDB::writeNodeFile(*(root.get()), GetCurrentPath() + "\\Data\\paged.osg");

	// 优化场景数据
	osgUtil::Optimizer optimizer;
	optimizer.optimize(root.get());

	// 设置窗口大小
	setWindowSize(viewer.get(), 600, 400, "PagedLOD");

	// 设置场景数据
	viewer->setSceneData(root.get());
	// 初始化并创建窗口
	viewer->realize();
	// 开始渲染
	viewer->run();

	return 0;
}

效果图

3.png

4.PNG

动态效果图

1.gif

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 24 天