/ Viewer vs CompositeViewer

Programming Guides

Viewer vs CompositeViewer

The goal of this page is to help you decide which viewer class to use in your projects.

Class hierarchy

It may be useful to compare the class diagrams of the two viewer classes. This points out the basic conceptual difference that osgViewer::Viewer "is a" osgViewer::View, whereas osgViewer::CompositeViewer "has a" list of osgViewer::Views. For a more detailed explanation, see Views and Viewers.

Conceptual difference

Basic Explanation

This post explains the conceptual differences between the two viewer classes.

The guide on when to use CompositeViewer or Viewer comes down to both practicalities and conceptual sides, if you don't keep both the practicalities and concepts well in sync you'll find it hard to get working and had to understand and communicate with others.

So lets start with the basic concept that both viewers share, the concept of the a "View". The View corresponds to a view that you have physical world, such as when you look out of one or more windows of building. If you have just one window to look through then you have just one view, also if you have multiple windows then if you were to turn around to someone to explain when you see you'd talk about a single view - the fact that you have multiple windows becomes irrelevant its the view of the scene beyond that is framed by the windows that is important.

The osg::View/osgViewer::View is exactly the same, its one view on one scene. The "Scene" here is the osgViewer::Scene which wraps up the details for a single scene graph. The View can be made up of one bit - a single Camera assigned to a single Window, or multiple Camera's each with their own Windows. In both single and multiple camera cases the overall view is coordinated - for instance the view out of a car windows is all managed as a single over entity if the car turns then all the sub portions of the view change with it. Implementation wise this is where you have a master Camera that provides the overall view and projection matrix and slave cameras which have their own local offsets relative to this master Camera. For the simple single camera/window case the master Camera doesn't need any slaves to help out, so you just assign the window directly to the master.

The are times when you want to mix this slave/master relationship up a little, but importantly for your own sanity you need to keep coming back to the concept that one View represents one physical view. The cases when you might find it useful to mix things up a little is when doing viewer level effects like distortion correction - here you have one coordinated View, but the rendering is actually done by multiple slave Cameras that are reletaive to the master that render to texture, the one or more other slave Camera(s) that effectively render the resultant texture(s) to graphics window applying their own effects/distortion along the way. This second set of slave Camera(s) neither share the master's view and projection matrices, nor the same scene graph - they have their own local scene graphs required for the sole purpose of doing the post rendering effects/distortion correction. Despite this extra internal complexity of how to render the view, its is still one logical view and at the application level one would want to control it as such and not have to worry about the fact their might be 7+ slave cameras under the hood. This is where the practicalities of the implementation and the concepts still hold together in step, so we know we are still on firm ground.

The above might seem rather complicated to get your head around, but... much of it can be wrapped up and encapsulated nicely, either via plugins or methods like View::setUpViewAcrossAllScreens() or View::setUpViewFor3DSphericalDisplay() with support power walls and distorted corrected spherical displays respecitively, all the multiple camera/window setup is done for you. Internally osgViewer::Viewer/osgViewer::CompositeViewer will worry about all the cameras and windows and keep them in sync and threaded correctly.

For a hemi-spherical display you could follow along the lines of View::setUpViewFor3DSphericalDisplay().

OK. Lots of text just on View. Well it is the most important bit to understand, both implementation wise and conceptually. Once you've got your head around the above then its quite easy to go the next step which is to know when and where to use CompositeViewer or Viewer. Its simple, do you have a single view that you are trying to represent? If so then use Viewer as its "is a" single View, the fact that that this single view might take half a dozen cameras to realise it doesn't ever change that fact that is its just for creating a single view.

This leaves the CompositeViewer, it "has a" list of one or more Views. Yes you can use it to do just one view, and it'll behave and perform just like the standard Viewer in this instance, but it's a bit more complicated to use as one has to access a list of View's just rather than just directly accessing a single view that you know is always there as in the case of Viewer. So if you have a single view just use Viewer, most users probably fit in this category. There are still lots of users that need more than just a single view, they want multiple viewpoints all looking on the same view such as in a CAD program, or a 3D scene and a map view, or the want to be able to load multiple models and control them all independently. For these applications having the ability to manage multiple Views on to on or more Scenes is very powerful. While it is more complex to manage than a single View(er) the complexity remains proportional to the problem in hand, in fact the practical implementation details remain in step with the conceptual problem you are solving, so again you know you are on the right track.

There is also the functional differences, for example when setting a HUD displayed over a scene. Do you want separate event handling and camera manipulation on your HUD? If so then since these are manage per View then a CompositeViewer is more appropriate. If however the HUD is largely passive then a slave camera in Viewer would be just fine.

Short Analogy

In the same thread, Mike Weiblen and Robert tried to sum up with this analogy.

On Jan 19, 2008 12:28 AM, Mike Weiblen <mweib...@…> wrote:

1) an immersive car cockpit display: front windscreen, left/right side
windows, inside/outside rearview mirrors.
That indicates Viewer (even though the eye orientations are quiet
different, and also have some mirror flips)

Yep spot on, a clear case of a single conceptual view, as well as all the contributing cameras sharing the scene and being relative to the view's master camera - so both a conceptual fit as well as implementation one.

2) a 3rd-person stealth watching a UAV sensor platform: the UAV is
collecting sensor data from its viewpoint; an operator is watching the
UAV and a wireframe of its sensor volume sweeping the terrain.  That
indicates CompositeViewer (the scene database could be identical, but
the sensor wont see its wireframe nor the UAV)

Yep spot on again, the viewer (the person the viewer as in the English language definition) has two views of a scene so conceptually we have two views of one scene, on the implementation side you'd want to control the viewpoint of these views separately as well as some of the state - so again both a good conceptual fit as well as an implementation one.

Robert.

Example use cases

Please add to these categories to list your own experiences. The more use cases are listed the easier it will be to find something that matches what a particular user wants to do.

osgViewer::Viewer

Application with a single window viewing a single scene
osgViewer::View::setUpViewOnSingleScreen(unsigned int screenNum = 0)
Application with a single scene, but viewed from multiple angles (using slave cameras)
osgViewer::View::setUpViewAcrossAllScreens().

osgViewer::CompositeViewer

Application with multiple scenes