一般多视图、视口在CAD、仿真领域里用的比较多,游戏里用的相对较少。尤其是CAD,要求在多视口内用不同的渲染模式来显示零件。比如,在单视图内用多视口方式,分别用着色模式,线框消隐模式来绘制显示模型。
这里提到视口,视图,在不同的软件中因其定义实现的方式不同,显得比较混乱,有时两者不同,有时两者又等价!按我自己理解,一个窗口内划分成几个部分,如果每个子区域包括业务处理逻辑(如事件处理,在子区域内平移、旋转、缩放对象,其它区域不受影响),这个子区域可以看成是视图;如果子区域只负责显示模型,不负责事件处理,该子区域可以看成视口,也就是说将视口看成功能弱于视图的子显示区域。这只是个人看法,你完全可以将子显示区域都定义为视口,例如 AutoCAD。
OSG视图显示关键几个类:
osg::View
该类为视图组织管理最基础的类,管理主、从相机,光照模式(天光,头顶光,无光照)。
osgViewer::View : public osg::View, public osgGA::GUIActionAdapter
该类扩展了基础视图类,加入了场景数据、窗口事件、视图配置的管理功能,渲染器(Renderer)也在此创建。
osgViewer::ViewerBase
该类为更高层的视图管类,使视图具有多线程渲染的能力,并管理渲染设备上下文的初始化,渲染线程的管理、调度,视图更新的三个阶段:事件更新过程【eventTraversal()】,状态更新过程【updateTraversal()】,及渲染更新过程【renderingTraversals()】。
ViewerBase 派生出两个子类:单视图视景器 osgViewer::Viewer, 多视图视景器 osgViewer::CompositeViewer。
osgViewer::Viewer : public ViewerBase, public osgViewer::View
osgViewer::CompositeViewer : public ViewerBase
从上面两类继承关系,我们可以看出,osgViewer::CompositeViewer 是没有渲染能力但具有上下文管理,线程调度管理的Viewer 的容器类, 渲染内容的输出由osgViewer::Viewer 来完成。
从以上视图相关类的继承关系可以看出,有三种方式可以实现多视图:
如果需要子视图功能完备,能够处理自己的交互事件,我们就用CompositeViewer 来作为主视图,再添加Viewer来呈现不同的内容。
如果只需要在视图内,以不同的视角观察模型,我们用osgViewer::Viewer 来作为主视图,在添加不同的slave camera来实现。
如果创建一个主窗口,再创建多个windows窗口,用splitecontainer控件分割,每个子窗口用osgViewer::Viewer 做为主视图,也可以实现多视图。但这种方式,需要消耗更多的硬件资源,且OpenGL 层面的显示数据不能公用。
多视图的实现涉及到几个细节方面的问题:
模型数据的复用?
对象显示状态如何分离?
例如,你在一个视图内高亮一个对象,因为模型及模型显示属性数据是复用的,另一个视图内相关的对象也会高亮。这在模型显示属性在不同视图内一致时没有问题,而且是我们想要的显示效果。但当不同视图内对象显示状态不一致时,就不合适了。例如对象在一个子窗口内是可见的,另一个窗口内是不可见的。
osg 要求当前上下文一定要有一个View, 否则停止渲染。