Canvas view camera element
|It would make sense to integrate all efforts (CompositeViewer, Canvas and Compositor) to create a Canvas Element that can render an arbitrary view.
Some time ago I wrote what I think are the required steps to get something like cockpit mirrors working: #Roadmap
The main showstopper was having CompositeViewer Support, but since that effort is underway, all the parts are there for someone willing to dive in.
|It might be interesting to try to define the Shuttle arm view (apologies if that's the wrong name) as an SView in its own top-level window. Apart from anything else i'd like to make sure that Sview supports whatever requires; I'd imagine that we would have one Sview step for each hinge/link in the arm for example, and this might need a new Sview step type.
It would also be a useful incentive to getting Canvas views working.
|Description||Rendering arbitrary scene views to a texture/Canvas|
Several aircraft developers have manifested their interest in being able to render scene views to a texture (RTT) and use it inside cockpits as mirrors, external cameras (so called tail cams) and other uses.
With the Compositor framework it's possible to configure custom render pipelines in XML space, which together with Effect schemes allow complete control over how a rendered scene looks. A synthetic terrain can be rendered by assigning an Effect scheme to a scene type pass, which textures all terrain with a brown checkerboard pattern and paints the sky in a solid blue color. All other objects are ignored and aren't rendered, saving a lot of computation time. Custom render distances independent from the main LOD settings can also be used to further optimize the performance of the display.
- Tail Cams (gear view)
- shuttle RMS cam
- Dynamic in-sim view configuration
- On demand creation of views and windows (e.g. FGCamera previews)
- Missile/payload views
- Prototyping/testing HUDs or PFDs requiring synthetic terrain to work properly
- rendering an orthographic view to implement moving maps that render actual FlightGear terrain/DEM
- automated creation/rendering of cockpit GUI dialogs by rendering a perspective-corrected front-view of cockpit elements (MCP, AP, CDU etc) 
Proof of Concept
See Hackathon Proposal: CompositeViewer and Canvas for the main article about this subject.
All the work we did is on branch topics/cvcanvas of the main flightgear, simgear and fgdata repositories:
Originally, FlightGear only used one instance of osg::Viewer, which is used by CameraGroup to manage the slave cameras. Supporting CompositeViewer did require modifying flightgear/src/Viewer/fg_os_osgviewer.cxx to create some kind of wrapper class that manages the CompositeViewer instance and assign a CameraGroup to each osg::View. It's also important to note that currently all FG subsystems assume there is a single instance of CameraGroup.
Standardize the View manager
|Note As of 11/2020, Jules has already created a custom view manager implementation StepView that supports multiple independent instances, so this step might be obsolete by now.|
The first step would be to port the view code to SimGear so it can be used and known by the Compositor and Canvas. The view manager (flightgear/src/Viewer/viewmgr.cxx) currently has some hardcoded assumptions, so it would either need to be rewritten to remove them or a new interface for the Views could be created specifically for the Canvas Camera View.
In FlightGear, the Canvas system (which resides in SimGear) is integrated using the equivalent of a FGCanvasSystemAdapter, which provides all FG APIs to SimGear and makes the Canvas system available inside FG: flightgear/src/Canvas/FGCanvasSystemAdapter.cxx
Instead of using tied properties, the adapted view code would either used propertyObject<> or the propertyBasedMgr abstraction, so that the corresponding canvas element can continue to use well-known conventions to manipulate views: (flightgear/src/Viewer/view.cxx)
Create a Canvas Element subclass
This derived class would require the following configuration:
- Compositor to use.
- Scene graph to use. By default the main scene graph would be used, but an arbitrary XML file can be loaded to render a custom model. A typical use-case would be instruments that need to manipulate/render a 3D object (for which we have working code, too)
- View to use. This could be one of the "main" ones (i.e. the ones on the main property tree), or a locally-defined one that is only known to this Canvas Element (think FLIR).
Several optimization/miscellaneous parameters exposed in the form of properties per element, like:
- texture size/resolution (see Fernando's comments here: Talk:Hackathon_Proposal:_CompositeViewer_and_Canvas#SceneGraph_Cameras_vs._Prerender_Cams )
- OSG rendering mode (continuous vs. lazy/on demand):
setRunFrameScheme( osgViewer::ViewerBase::ON_DEMAND ); 
- framerate cap via something like
view.setRunMaxFrameRate()   (background: https://firstname.lastname@example.org/msg26178.html )
- node masks
- LOD ranges etc. 
- PagedLOD settings for
PIXEL_SIZE_ON_SCREENmode   
- whether or not to enable OSG StatsHandler per view, i.e. for troubleshooting per view
- whether or not to enable event handling: "Extra view windows don't yet handle events so one cannot change the view angle/zoom after creation." 
Note, we can use the view's Camera's LODScale to adjust the which level of LOD child is selected for each view. Another common suggestion is to control the update rate of slave cameras by inserting them into the scene graph as needed, and then use a PostDrawCallback for the camera that removes the camera again when it is no longer needed. Robert (OSG) states that most apps should manage the frame for their own applications and data. The OSG is a general purpose scene graph rather than a domain specific IG. It gives you the tools to do your job, but it doesn't do it all for you. The run() method stuff available in OSG/Viewer is really only for entry level app development. More sophisticated types of frame rate management are well beyond what the viewer convenience methods like run are supposed to handle. People should expect to roll your own frame management for this type of app.
Simplifying a lot, this Canvas Element would be an aggregation of:
- a Compositor instance / effect scheme
- a View
- a pointer to a osg::Group representing the scene graph to render (e.g. alias or filename based).
This setup could be replicated in flightgear/src/Viewer/fg_os_osgviewer.cxx, with the difference of ignoring Canvas and using native windowing features from OSG (see Jules' fgcommands to clone a view and open a dedicated GraphicsContext/window).