Scenegraph Design NotesThe scenegraph design follows the traditional structure and names now associated with 3D graphics design. Taking a quick look through the Javadoc should provide a reasonable sense of familiarity.
Base ClassesThe scene graph structure starts with a common base class -
Relationships (parent/child) are defined at the first level of derived nodes:
Both base classes provide explicit rendering call methods that assume a typical rendering pipeline with state sorting. Methods define push and pop states that allow the node to directly call the OpenGL methods needed for rendering. We don't ever expect end users to be making these calls, but there is nothing preventing you from doing so if you manage to obtain a GL context to work with. The idea behind this design descision was that we wanted to keep the data and GL commands as close together as possible. Most other APIs work with a different strategy of having the renderer commands in a separate area (typically named something like RenderBin). There were several aspects of that design path that we didn't like - most principally the idea of being able to quickly extend the scene graph with new features or custom node implementations. Having a centralised renderer object means that adding any new rendering functionality requires modification of that class as well as the class that is representing the node in the scene graph. By containing the data and rendering instructions in a single class, extensibility for the most part is much easier to handle, while the cases where modification to the pipeline and output stages are drastically reduced.
Moving up the class heirarchy in both trees from Node and NodeComponent show
the standard set of nodes that one would expect of a scenegraph. We've mostly
stayed with conventions here, and only done minor deviations. For example,
with textures, we've assumed multitexture support from the start - Using single
or multiple textures uses exactly the same code structure
Structures PermittedAviatrix3D allows the use of Directed Acyclic Graphs. Cycle checks are performed whenever the user adds a node to make sure that circular structures are not created (they cause major headaches for the rendering pipeline). For the most part all structural nodes have a single parent/multiple child strategy.
All classes that derive from
All classes that derive from
Reading/Writing a nodeUpdating the value of an attribute of a scene graph object is one of the most important design decisions in any scene graph API. This point defines how the scene graph interacts with both the rendering pipeline and user code. Important issues like thread-safety, efficiency of bounds updates and so-forth are impacted by the design decisions here.
Our design works on the principle of the scene graph instructing the user code about the appropriate time to update the code. The design principle is to allow reading at any time, but writing only at one very specific time and only to the nodes that the user has marked as needing to be modified. By doing this, we can keep track internally of what has changed and thus provide optimised internal updates.
There are two different types of updates that one can do on the scene graph - those that effect structural information (ie bounds) and those that effect visual or rendering properties. We've made the distinction between the two types of update to provide for internal optimisations. Changing the emmisive colour of an object should not result in the need to change the bounding box values of the parent grouping structures. By providing two separate callbacks we know which nodes need to update bounding information and which do not, thus saving ourselves a lot of CPU cycles that could be otherwise wasted.
Updating the scene graph is a two step process. Firstly application code informs the scene graph that it would like to perform an update, and then at some point in the future the callback is made and the node will update the appropriate details.
Updating the boundsAs one of the core performance determinants, bounds handling are critical to get right and provide optimised performance. We've done our design a little differently to most structures. Reading various texts of scene graph design recommends doing a single pass setup that walks down the scene graph updating local to vworld transformation matrices and then on the return, updating the bounding box information. As we expect our target audience to be mainly creating large scene graph structures (both wide and deep), this approach tends to be quite costly.
The approach we have taken to bounds updating separates the two processes. A lot of the matrix multiplication and transformation updates can be avoided by not updating them until needed, or not even calculating them at all. Our code does not keep a local to v-world transformation matrix at all. If you need these, you calculate them yourself or they are calculated on demand (for example only once the results of a pick operation are successful and the user has requested this information). Bounding box updates work from a bottom-up perspective.
Since we know which nodes of the scene graph had had their bounds altered, we can use this knowledge to optimise the updates without causing unnecessary recalculations for parts of the scene graph that have not changed. Each node that has had it's bounds registered as being changed will be told to update, and it marks it's parent as being dirty. The parent keeps a count of the number of dirty notifications it receives. Once the node has updated the bounds, it then informs the parent to update it's bounds. The parent decrements it's dirty counter. If the counter is non zero, nothing happens because it knows it has more children that are yet to update. Once the counter is zero, the parent updates it's bounds from all the children, then informs it's parent that an update should be made and thus the cycle continues. This method ensures that only parts of the scene graph that have changed need to be recalculated and does so in an efficient manner.
[ Home ]
[ License ]
[ javadoc ]
[ Online Examples ]
[ Download ]
[ j3d.org ] [ Aviatrix3D ] [ Code Repository ] [ Java3D ] [ OpenGL ] [ Books ] [ Contact Us ]
Last Updated: $Date: 2010-05-01 04:20:35 -0700 (Sat, 01 May 2010) $