如何判断何时使用CompositeViewer或Viewer,这需要从概念和实际应用两方面来考虑。否则的话,用户可能会在编写程序,或者与他人进行交流时遇到困惑。
我们首先来了解一下这两个视图类的共同之处,以及视图(View)的基本概念。视图相当于是一个观察真实世界的窗口。打个比方来说,如果你从一幢大楼的多个窗户向外看,其中的某一个窗户就相当于一个视图。如果你面前有多个窗户,而你准备向他人介绍一下自己看到的景色,那么你需要选择单一的视图进行讲解——这个时候,其它更多的窗户就显得没有意义了,因为你着重的是场景的某一个“视图”,而非整个窗口,这就是关键所在。
osg::View/osgViewer::View i的作用与此相类似,它即是场景的一个视图。这里所说的“场景”指的是osgViewer::Scene类,它封装了单个场景图形的所有细节。一个视图可以由一个摄像机(Camera类)和与其关联的一个窗口,或者多个摄像机以及分别与它们关联的多个窗口组成。但是无论有单个或多个摄像机存在,视图本身都是一致的——例如,用于显示各个车窗外面景色的视图是作为一个整体进行管理的;当汽车转弯的时候,视图中所有的部分(各个车窗)都会随之改变。一种恰当的实现方法是,安排一台主摄像机(master camera)来管理总体的视图和投影矩阵,其它从摄像机(slave cameras)相对主摄像机各自有所偏移。对于简单的单摄像机/窗口的情况,主摄像机不需要其它摄像机的协助,因此直接将窗口指向该摄像机就可以了。
有的时候我们需要主/从摄像机的关系不那么明确,但是无论什么时候我们都要注意:一个View只能表示一个视图。当我们需要实现一些视图级别的效果,例如失真校正时,我们可能需要打乱上文所述的概念——此时我们也许有一个一致的视图(View),而主摄像机负责的是纹理烘焙(render to texture)之类的工作,其它从摄像机负责执行实际渲染的工作,即,它们为烘焙后的纹理添加效果或执行校正后,再高效地渲染到相应的图形窗口中。此时,从摄像机与主摄像机的视图和投影矩阵无关,也不共享场景图形——从摄像机有自己独立的场景图形,以便执行渲染后处理(post rendering)的工作,例如添加特效,执行失真校正等。虽然这一类视图渲染的情况显得复杂了许多,但我们在应用级别进行控制时,仍然只需要一个视图,并且不必担心有许多个从摄像机各司其职之类的问题。也就是说,我们在前文所述的概念仍然是可行的、一致的,不必担心在实现的过程中会出现混乱的情况。
上面一段的叙述可能很令人困惑,不过我们已经将大部分的工作很好地封装起来。无论是通过插件或者View::setUpViewAcrossAllScreens()方法,还是类同View::setUpViewFor3DSphericalDisplay()之类的方法,都可以完成这类多摄像机/窗口的工作。osgViewer::Viewer/osgViewer::CompositeViewer的内部负责管理所有摄像机和窗口,保证其同步性和执行线程的正确性。
View::setUpViewFor3DSphericalDisplay()方法将在以后用于半球面显示器的工作。
我们已经针对视图(View)进行了深入的讨论,这对于我们理解概念和编写代码都是十分重要的。当你对于上面的内容已经有所了解之后,你应该可以比较轻松地理解CompositeViewer和Viewer的区别和使用时机了。对于使用单一视图来表现场景的用户来说,使用Viewer类是较好的选择。虽然在这个视图中可能存在多个摄像机,但是要明确的是,它们仍然只构成了一个视图而已。
而对于CompositeViewer来说,它内部已经包含了多个视图(View)。使用它来表示一个视图当然是可以的,此时CompositeViewer的作用与标准的Viewer对象并无太大差别,但是比起每次只管理一个视图的情形来说,管理和使用多个视图还是显得略为麻烦了一点。因此我们建议用户在只有一个视图的时候,尽量选择使用Viewer。当然,更多的用户可能需要用到不止一个视图,他们也许需要在多个视口内显示同一视图的内容,例如多数CAD软件;或者同时显示一个3D场景和一幅小地图视图;或者读取多个模型文件并分别独立地进行控制。对于这些程序来说,往往需要在一个或多个场景(Scene)上管理多个视图(View)。此时程序的管理方式要比单独的Viewer情形下复杂得多。事实上,程序的细节程度总是与问题的复杂程度成比例,因此我们有必要在正确的条件下选择正确的实现方式。
两者之间在功能上同样存在了不同,比如场景中抬头显示(HUD)的设置方式。如果用户希望为HUD设置独立的事件处理器和场景漫游器,则HUD也需要独立的视图,因此应建议使用CompositeViewer。如果HUD不必进行处理,那么使用Viewer类中的一个从摄像机就可以了。