场景图形管理-多视图与相机(3)

在OSG中多视图的管理是通过osgViewer::CompositeViewer类来实现的。该类负责多个视图的管理及同步工作,继承自osgViewer;:ViewerBase类,继承关系图如图8-13所示

图8-13 osgViewer::CompositeViewer 的继承关系图

在前面已经讲到,osgViewer:ViewerBase 类主要负责线程管理、设置线程模式、启动线程等工作在多视图渲染时,线程管理一直都是一个令人非常头痛的问题,但这些底层工作在 osgViewer::CompositeViewer类中已经实现了。如果读者想了解得更详细,可参看osgViewer/CompositeViewer.cpp源代码。

对于osgViewer::CompositeViewer ,它内部已经包含了多个视图(osg::View),使用它来表示一个视图当然是可以的,此时osgViewer:CompositeViewer 的作用与标准的osgViewer::Viewer 对象并无太大差别,但是比起每次只管理一个视图的情形来说,管理和使用多个视图还是显得略微麻烦。因此,建议在只有一个视图时尽量选择使用 osgViewer::Viewer 。当然,有时可能需要用到不止一个视图,也可能在多个视口内显示同一视图的内容 (如多数 CAD 软件),或同时显示一个3D场景和一幅小地图视图 ,或读取多个模型文件并分别独立地进行控制。对于这些程序来说,往往需要在一个或多个场景(osgVicwer:Scene)上管理多个视图(osgView)此时程序的管理方式要比单独的osgViewer.:Viewer情形下复杂得多。事实上,程序的细节程度总是与问题的复杂程度成比例的,因此,我们有必要在正确的条件下选择正确的实现方式。

在osgViewer:CompositeViewer中添加视图或移除视图可以用下面的成员函数:

cpp 复制代码
void addView(osgViewer.:View*view)//添加一个视图
void removeView(osgViewer::View*view)//移除一个视图
osgViewer::View *getView(unsigned i) //得到视图的索引
const  osgViewer::View *getView(unsigned i)const//得到视图的索引
unsigned int getNumViews() const//得到视图的个数

在论坛上,有很多人会提问如何来做一个"鹰眼",其实,这是比较简单的实现。用osgViewer.:CompositeViewer类实现多视图管理,让一个小地图HUD显示一个视图,另一个视图染主窗口即可。本书并没有专门提供一个相关的例子,读者可以通过修改本书的例子来自行完成

  1. 多视图相机渲染示例

多视图相机渲染示例的代码如程序清单8-5所示

cpp 复制代码
// 多视图相机渲染示例
void compositeViewer_8_5(const string &strDataFolder)
{
	// 创建CompositeViewer对象
	osg::ref_ptr<osgViewer::CompositeViewer> viewer = new osgViewer::CompositeViewer();

	// 获取牛的模型
	string strDataPath = strDataFolder + "cow.osg";
	osg::ref_ptr<osg::Node> cow = osgDB::readNodeFile(strDataPath);

	// 读取飞机模型
	strDataPath = strDataFolder + "cessna.osg";
	osg::ref_ptr<osg::Node> cessna = osgDB::readNodeFile(strDataPath);

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

	// 设置图形环境特性
	osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits();
	traits->x = 100;
	traits->y = 100;
	traits->width = 900;
	traits->height = 700;
	traits->windowDecoration = true;
	traits->doubleBuffer = true;
	traits->sharedContext = 0;

	// 创建图形环境特性
	osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
	if (gc->valid())
	{
		osg::notify(osg::INFO) << " GraphicsWIndow has been created successfully." << endl;

		// 清除窗口颜色及颜色和深度缓冲
		gc->setClearColor(osg::Vec4f(0.2f, 0.2f, 0.6f, 1.0f));
		gc->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	}
	else
	{
		osg::notify(osg::NOTICE) << " GrraphicsWidnow has not been created successfully." << endl;
	}

	//视图1
	{
		// 创建视图1
		osg::ref_ptr<osgViewer::View> view = new osgViewer::View;
		viewer->addView(view.get());

		// 设置视图场景数据
		view->setSceneData(cow.get());

		// 设置相机视口及图形环境
		view->getCamera()->setViewport(new osg::Viewport(0, 0, traits->width / 2, traits->height / 2));
		view->getCamera()->setGraphicsContext(gc.get());

		// 设置操作器
		view->setCameraManipulator(new osgGA::TrackballManipulator);

		// 添加事件处理
		view->addEventHandler(new osgViewer::StatsHandler);
		view->addEventHandler(new osgViewer::WindowSizeHandler);
		view->addEventHandler(new osgViewer::ThreadingHandler);
		view->addEventHandler(new osgViewer::RecordCameraPathHandler);
	}

	// 视图2
	{
		osg::ref_ptr<osgViewer::View> view = new osgViewer::Viewer;
		viewer->addView(view.get());

		view->setSceneData(cessna.get());
		view->getCamera()->setViewport(new osg::Viewport(traits->width / 2, 0, traits->width / 2, traits->height / 2));
		view->getCamera()->setGraphicsContext(gc.get());

		view->setCameraManipulator(new osgGA::TrackballManipulator);
	}

	// 视图3
	{
		osg::ref_ptr<osgViewer::View> view = new osgViewer::View;
		viewer->addView(view.get());
		view->setSceneData(cessna.get());

		// 根据分辨率确定合适的投影来保证显示的图形不变形
		double fovy, aspectRatio, zNear, zFar;
		view->getCamera()->getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar);
		double newAspectRatio = double(traits->width) / double(traits->height/2);
		double aspectRaitoChange = newAspectRatio / aspectRatio;
		if (aspectRaitoChange != 1.0)
		{
			view->getCamera()->getProjectionMatrix() *= osg::Matrix::scale(1.0 / aspectRaitoChange, 1.0, 1.0);
		}

		view->getCamera()->setViewport(new osg::Viewport(0, traits->height / 2, traits->width, traits->height / 2));
		view->getCamera()->setGraphicsContext(gc.get());
		view->setCameraManipulator(new osgGA::TrackballManipulator);
	}

	viewer->realize();
	viewer->run();
}

运行程序,截图如图8-14所示

图8-14多视图相机渲染示例截图

相关推荐
StrokeAce39 分钟前
linux桌面软件(wps)内嵌到主窗口后的关闭问题
linux·c++·qt·wps·窗口内嵌
家有狸花4 小时前
VSCODE驯服日记(三):配置C++环境
c++·ide·vscode
dengqingrui1234 小时前
【树形DP】AT_dp_p Independent Set 题解
c++·学习·算法·深度优先·图论·dp
C++忠实粉丝4 小时前
前缀和(8)_矩阵区域和
数据结构·c++·线性代数·算法·矩阵
ZZZ_O^O5 小时前
二分查找算法——寻找旋转排序数组中的最小值&点名
数据结构·c++·学习·算法·二叉树
小飞猪Jay7 小时前
C++面试速通宝典——13
jvm·c++·面试
rjszcb8 小时前
一文说完c++全部基础知识,IO流(二)
c++
小字节,大梦想9 小时前
【C++】二叉搜索树
数据结构·c++
吾名招财9 小时前
yolov5-7.0模型DNN加载函数及参数详解(重要)
c++·人工智能·yolo·dnn
我是哈哈hh9 小时前
专题十_穷举vs暴搜vs深搜vs回溯vs剪枝_二叉树的深度优先搜索_算法专题详细总结
服务器·数据结构·c++·算法·机器学习·深度优先·剪枝