Under the hood of Canvas: Difference between revisions

Jump to navigation Jump to search
no edit summary
No edit summary
No edit summary
Line 52: Line 52:
In summary, the Canvas system really is a scenegraph - so if you have something that you'd like to be able to hide/show, clear or change selectively, just put it into a separate group and use that group as the "handle" to deal with the whole shebang (it really is a osg::Group under the hood, i.e. an osg::Transform IIRC, which is a child class inheriting from ::Group)<ref>{{cite web
In summary, the Canvas system really is a scenegraph - so if you have something that you'd like to be able to hide/show, clear or change selectively, just put it into a separate group and use that group as the "handle" to deal with the whole shebang (it really is a osg::Group under the hood, i.e. an osg::Transform IIRC, which is a child class inheriting from ::Group)<ref>{{cite web
   |url    =  https://forum.flightgear.org/viewtopic.php?p=297688#p297688  
   |url    =  https://forum.flightgear.org/viewtopic.php?p=297688#p297688  
  |title  =  <nowiki> Re: Nasal must go </nowiki>
  |author =  <nowiki> Hooray </nowiki>
  |date  =  Oct 29th, 2016
  |added  =  Oct 29th, 2016
  |script_version = 0.40
  }}</ref>
The point of my suggestions is to minimie internal state changes: Canvas is primarily a subsystem that works in terms of listeners, each element added to a Canvas, and all their child elements will monitor the tree for "events", i.e. property accesses/updates.
It basically maps a tiny subset of the property tree to OSG primitives, so is a property-driven state machine.
This may result in hundreds, or even thousands, of callbacks to be invoked recursively to propagate events properly.
Whenever an element-specific property is updated (think a color, translation etc changed), this results in the element-specific geode to be marked as "dirty", so that the geode is updated.
These updates can be minimized by not setting/updating certain properties, e.g. those of invariant canvas elements that will basically stay the same in between multiple frames - in such cases, the corresponding group/element-specific osg::Geode from the previous frame can be reused "as is" - which is not specific to Canvas, it's a general scenegraph thing to minimize unnecessary scenegraph traversals.
So, regarding your comment quoted above, imagine how the workload of the Canvas system can be reduced if the spacecraft is stationary, even though we are still updating things per frame that never really change (orientation, altitude etc).
If you really have to/want to use removeAllChildren(), don't use it per instrument, but only for those instrument parts that are variable - and put everything else into a static group that you never touch (think background images etc), and even then, consider if reusing the underlying data structures makes more sense to clearing out everything and re-allocating those from scratch.
The Canvas-specific thing is that all this happening via listeners comes at a cost, which is why it is generally a good idea to check if reusing previously allocated '''data structures''' (as in, the elements/groups forming the geometry) can be reused, instead of clearing out the geometry and re-creating it from scratch - because at that point, you are throwing all optimization opportunities out of the window, because that will inevitably cause all code to re-run - whereas reusing parts of the scenegraph in the next frame, can simplify the workload tremendously - e.g. that is why we marked certain NavDisplay geometry as "static" and rendered that to a separate Canvas texture which we are treating as a texture map to get out relevant bits, at that point, it's just dealing with textured quads only - and no longer has to run any Canvas::Path or ShivaVG code to actually render the geometry.<ref>{{cite web
  |url    =  https://forum.flightgear.org/viewtopic.php?p=297686#p297686
   |title  =  <nowiki> Re: Nasal must go </nowiki>  
   |title  =  <nowiki> Re: Nasal must go </nowiki>  
   |author =  <nowiki> Hooray </nowiki>  
   |author =  <nowiki> Hooray </nowiki>  

Navigation menu