2.3 Scene Graph



The scene graph is built at the beginning of the application and Inventor maintaines it after that. Nodes are added and removed, and their data is altered by the application after the graph is built, but the basic architecture remains the same.

Main is the entry point into the code and calls every other function in the program (excluding the event driven functions). Main simply gets an application context using the base class method SoXt::init(). SoXt::init is only a wrappler for the simple Xt call getAppContext. The next call is to makePixmaps. MakePixmaps takes the bitmaps and uses the X call XCreatePixmapFromBitmapData to convert them into similar Xt style pixmaps so they can be used as background on the buttons of the VCR interface.

Next the scenegraph root is declared. The root node is a separator node By default, Inventor builds a cache at each separator node in a scene graph. The cache represents all of the scene database that falls below it. The Inventor database has internal sensors that it attaches to each data field in each node in the graph. When the Inventor database detects that a data field has changed below a separator node containing a cache, It rebuilds the smallest necessary portion of the cache before forcing a redraw of the scene. The first implementation of this application used the default `true' values for the caching and pick culling fields in the root and subsequent separator nodes. Because the geometry below nearly all of these separator nodes was being changed at nearly every time step, Inventor was having to rebuild its database cache at every time step dramatically increasing the time between the display of sucessive steps. After experimentation it was discovered that the best scheme was to explicitly turn off the render caching and pick culling at each separator node to maximize performance. The scenegraph is built with a call to makeSceneGraph.

MakeSceneGraph builds a scenegraph that is modeled by the following diagram:


Figure 4 -- Inventor Scene Graph Diagram

Inventor traverses the graph depth first from left to right. All of the Open GL state variables and the Inventor environment variables are pushed onto a stack when the separator nodes are traversed. As a consequence, the nodes in the graph above and adjacent to a separator node do not inheret the states and environment that are altered below a separator node. As discussed above, Inventor checks to see if caching is turned on or off at each separator. If it is turned on, the cache is updated every time a field in any of the nodes in the subgraph changes. Since the coordinates for each of the meshes are at the leaf level in the graph (and three Separator nodes deep) nearly all of the Separator caches would have to be updated on every timestep. Obviously this destroys all of the desireable attributes of using the cache -- It is the worst case for a cache! Caching is turned off at each Separator node.

The meshBindin and meshHints nodes are help speed up rendering by explicitly telling inventor some information about the scenegraph so it does not have to figure it out its self. The nodes labeled [0]meshSep to [NCPOPS-1]meshSep (implicit) are subgraphs representing each cell population. There are 15 cell populations in this simulation. Each population is translated to a predetermined position with the meshMove node. Each population is represented by three distinct graphical entities set off by Separator nodes.

PopSep1 is the top of the subgraph that represents the threshold object. The threshold object consists of an SoCoordinate node, meshCoords1; and an SoQuadMesh node, mesh1. All of the state changes above and to the left of popSep1 that are not preceeded by a Separator node are inhereted by mesh1. The values for the 3-vector coordinates in meshCoords1 are supplied from a static array defined at design time. The appropriate x and y values are assigned so as to build a square two dimensional 10x10 grid defined on integer points. The z values are zeroed out when the graph is built. Mesh1 is an SoQuadMesh node that actually builds the geometry of the surface to represent the threshold levels of the population. It is built from triangle strips which are in turn built from triangles. The graphics hardware on the Silicon Graphics Indigo 2's makes the triangle rendering very fast. Mesh1 is assigned the coordinates from meshCoords1 and defines its grid to be 10x10. As the values in the coordinate node are changed, mesh1 uses a high priority sensor to detect the change in the field and automatically updates its image. The graph for mesh1 (threshold mesh) is shown in figure 5.


Figure 5 -- Mesh 1 Graph, Threshold Mesh

Popsep2 is the top of the subgraph that represents the potential object. The potential object consists of an SoMaterial node, meshMat2; an SoCoordinate node, meshCoords2; and an SoQuadMesh node, mesh2. all of the state changes above and to the left of popSep2 that are not preceeded by a Separator node are inhereted by mesh2. The meshMat2 node changes the color of the potential mesh so that it is discernable from the others. The values for the 3-vector coordinates in meshCoords2 are supplied from a static array defined at design time. The appropriate x and y values are assigned so as to build a square two dimensional 10x10 grid defined on integer points. The z values are zeroed out when the graph is built. Mesh2 is also an SoQuadMesh node. Mesh2 is assigned the coordinates from meshCoords2 and defines its grid to be 10x10. As the values in the coordinate node are changed, mesh2 detects the change in the field and automatically updates its image. The graph for mesh2 (the potential mesh) is shown in figure 6.


Figure 6 -- Mesh2 Graph -- Threshold Mesh

Popsep3 is the top of the subgraph that represents the spike object. The spike object consists of an SoTransform node, spikeMove; an SoSeparator node, labelSep (The label graph is described in detail later); an SoMaterial node, meshMat3; an SoCoordinate node, meshCoords3; and an SoQuadMesh node, mesh3. All of the state changes above and to the left of popSep3 that are not preceeded by a Separator node are inhereted by mesh3. The spikeMove node translates the spike object in the z direction so that its activity can be observed apart from the threshold and potential meshes. The meshMat3 node changes the color of the spike mesh so that it is discernable from the others. The values for the 3-vector coordinates in meshCoords3 are supplied from a static array defined at design time. The appropriate x and y values are assigned so as to build a square two dimensional 10x10 grid defined on integer points. The z values are zeroed out when the graph is built. Mesh3 is an SoQuadMesh node that actually builds the geometry of the surface to represent the firing of cells in the population. Mesh3 is assigned the coordinates from meshCoords3 and defines its grid to be 10x10. As the values in the coordinate node are changed, mesh1 detects the change in the field and automatically updates its image. The graph for mesh (the spike mesh) is shown in figure 7.


Figure 7 -- Mesh3 Graph, The Spike Mesh

PopSep3 also has a label object to identify the appropriate cell population on the drawing area. The label subgraph begins with an SoSeparator node, labelSep, whose parent is popSep3. The label object contains an SoFont node, labelFonr; an SoTransform node, labelMove; and an SoText3 node, label. The font node uses the default font and changes the state font size variable to 4.0. LabelMove translates the label above the cell population so it is not hidden by the meshes. Incidentally, the label object is placed at the z level of the spike mesh by inhereting the spikeMove translation. This allows the labels to be seen when the other meshes are being translated in three dimensional space. The label is a three dimensional text object with its field set to the appropriate identifier for its corresponding cell population. The two dimensional text object would have appeared in a seperate plane at the closest point on the viewing volume. It would give disturbing results when the scene was transformed in any way from the origional position. With three dimensional text, the z value of the text3 node is simply set to zero. As a consequence, the text simply disappears when its angle with the viewer grows greater than ninety degrees (eliminating any unwanted results from the prospective projection). The graph for the labels is shown in figure 8.


Figure 8 -- Label Graph

The nodes labeled [NCPOPS]meshSep to [NTPOPS-1]meshSep are each subgraphs representing a fiber population. There are 7 fiber populations in this simulation. Each population is translated to a predetermined position with the meshMove node. Each population is represented by one subgraph in the form of a fiber spike object.

Popsep3 is the top of the subgraph that represents the fiber spike object. The fiber spike object consists of an SoTransform node, spikeMove; an SoMaterial node, meshMat3; an SoCoordinate node, meshCoords3; and an SoQuadMesh node, mesh3. all of the state changes above and to the left of popSep3 that are not preceeded by a Separator node are inhereted by mesh1. The spikeMove node translates the spike object in the z direction so that its activity can be observed apart from the threshold and potential meshes. The meshMat3 node changes the color of the spike mesh so that it is discernable from the others. The values for the 3-vector coordinates in meshCoords3 are supplied from a static array defined at design time. The appropriate x and y values are assigned so as to build a square two dimensional 10x10 grid defined on integer points. The z values are zeroed out when the graph is built. Mesh3 is an SoQuadMesh node that actually builds the geometry of the surface to represent the firing of cells in the population. Mesh3 is assigned the coordinates from meshCoords3 and defines its grid to be 10x10. As the values in the coordinate node are changed, mesh1 detects the change in the field and automatically updates its image. The graph for the fiber spike object is shown again in figure 9.


Figure 9 -- Fiber Spike Object

Back to the Table of Contents
Next Section ->