|Version 9 (modified by osg, 5 years ago)|
osgViewer::Viewer vs osgViewer::CompositeViewer
The goal of this page is to help you decide which viewer class to use in your projects.
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.
TODO: Update this when the doxygen will have been updated, because right now it does not show that Viewer and CompositeViewer both inherit from ViewerBase. I have uploaded the images to this page from my local doxygen for now.
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.
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.
Application with a single window viewing a single scene
- osgviewer when running on a single screen (OSG_SCREEN=0 for example) - set up using osgViewer::View::setUpViewOnSingleScreen(unsigned int screenNum = 0)
Application with a single scene, but viewed from multiple angles (using slave cameras)
- osgviewer when running on all screens (the default if you have multiple displays) - set up using osgViewer::View::setUpViewAcrossAllScreens().
Application with multiple scenes
- 3D view along with a map or a radar/sonar view