[osg-users] Some overview of OSG and VPB databases

Chris 'Xenon' Hanson xenon at alphapixel.com
Wed Nov 25 12:08:21 PST 2009


  I've accumulated some notes over time about how OSG and VPB databases works, and I
thought I'd share them here for others' enlightenment, and also to ask for corrections. I
don't guarantee this is correct, it just seems to be correct based on my understanding.

  Perhaps someday this might make it into some sort of OSG Terrain Guide or something.




Structure of a typical VirtualPlanetBuilder/OSGDEM terrain database

Root OSG file looks like:
CoordinateSystemNode: Top-level, defines ellipsoid shape of globe
	PagedLOD
		Child0:TerrainTile (lowest LOD of terrain model)
		Child1:Basename_root_L0_X0_Y0/Basename_L0_X0_Y0_subtile.osg
			(file containing LODs that cover the same extent as Child 0)


A VPB TerrainTile (for example, L0_X0_Y0) looks like:
TerrainTile (lowest LOD of terrain model)
	Locator (defines Coordinate System and Transform of TerrainTile)
	ElevationLayer
		HeightFieldLayer
			HeightField: UniqueID, Origin, X/Y Interval, SkirtHeight, Heights [Array]
	ColorLayer
		ImageLayer
			file Basename_L0_X0_Y0.dds


SubTile Basename_root_L0_X0_Y0/Basename_L0_X0_Y0_subtile.osg looks like:
Group
	PagedLOD
		Child0: TerrainTile
		Child1: Basename_L1_X0_Y0_subtile.osg (Another subtile like this one)
	PagedLOD
		Child0: TerrainTile
		Child1: Basename_L1_X1_Y0_subtile.osg
	...more, similar PagedLODs may exist here...


In operation, the Root OSG file is loaded by the caller. This file contains a TerrainTile
with Color and Elevation data, so as soon as the initial root load is complete, there is a
lo-resolution terrain surface visisble. OSG immediately begins cull traversal of this
scene graph. During cull traversal, the PagedLOD node probably discovers that the
currently visible child (child 0, with the TerrainTile) is insufficient LOD for the
current view. The only alternate LOD is Child1, which is an external file. PagedLOD
informs the DatabasePager to begin loading this external file and continues on the cull.
The load operation has a priority level that hints to the DatabasePager how important this
node is, allowing multiple loads to be queued according to how close each one is to the
viewer.

After the first cull operation is complete, a number of cull/draw cycles may execute while
the DatabasePager thread completes loading and possibly compiling the loaded data for use
in the scenegraph. During each cull operation that the loaded external child is not yet
available, the PagedLOD re-requests the child node to be loaded. This allows the priority
of the node in the queue to adjust if the viewpoint moves prior to the node getting loaded.

When ready, the DatabasePager inserts the loaded subgraph (see structure of
Basename_L0_X0_Y0_subtile.osg) into the scenegraph. At this point, the top PagedLOD is
satisfied that it has an appropriate LOD, and subsequent cull operations will traverse the
Child1 of the top PagedLOD Node.

Child1 itself contains a non-trivial subgraph. At the top of the subgraph are several
PagedLOD nodes. Each of these contains its own Child0 LOD, which is not an external file
but a TerrainTile complete with ElevationLayer and ColorLayer already loaded in and
compiled as part of the Basename_L0_X0_Y0_subtile. So, when the Root-level Child0
TerrainTile is replaced with the root-level Child1 external file, the
Basename_L0_X0_Y0_subtile's Child0s immediately cover the exact same visual extent of
terrain without any more loading delay.

As soon as the Basename_L0_X0_Y0_subtile subgraph is merged into the scenegraph and
traversed by cull, the PagedLODs in L0_X0_Y0 will evaluate their LOD criteria (typically
expressed not as actual distance, but in realtive-apparent-size-on-screen) and most likely
discover they too, are insufficient for the current view. At this point, each of the
PagedLODs will decide to load their next LOD child (Child1). Because each of these
children will be located at different locations with respect to the viewer, they will each
individually determine a different priority, which the DatabasePager will respect when
queuing the DatabaseRequest.

PagedLOD class has several conditions. The base LOD class and the Group class beneath that
require that the container (a std::vector) that contains the actual LODs must be
contiguous – no empty slots are permitted in the container. The PagedLOD class defines a
parallel container called PerRangeDataList, which is also a vector holding the LOD ranges
and external filenames for each child that can be loaded. The contents of these two
containers are associated only by the subscript of their contents. What this means in
practice is that the LOD children in the Group must be loaded contiguously – no higher LOD
can be loaded if a lower LOD is not already loaded.

PagedLOD will always load LOD #0 first. If that LOD is insufficient, it will load #1. It
will continue loading LODs, in order, one at a time, until it reaches one that is
sufficient. This is because the LOD and Group classes cannot permit "gaps" in the
container of Group children, and the PagedLOD PerRangeDataList must load children into the
Group chihld slot corresponding with the PerRangeData.

VPB-created databases never have PagedLODs with more than two children. The first (Child
0) is always an "internal" TerrainTile that is loaded completely along with the PagedLOD
itself. It has a blank "external" filename in its PerRangeData (to keep the order of
PerRangeDataList and the Group child container in sync). The second child (Child1)
supplies no "internal" representation. It has an external filename that is loaded by the
DatabasePager.

Lower LODs are not ever unloaded because LOD class wants to be able to immediately switch
to a lower (and faster-performing) LOD without needing to wait for loading the lower LOD.
This is the conservative approach so that OSG won't have both a high-detail tile just
loaded, but still be showing a different, too-high-detail tile elsewhere while it waits
for a lower detail tile to load. Having too much unintended simultaneous detail loaded at
once could cause degraded redraw performance and break frame.

Child #0 cannot be unloaded or reloaded because it is not an external file. In order to
unload it, the actual PagedLOD it is embedded within (and possibly the file that PagedLOD
is contained within, which might itself contain several other PagedLODs) would need to be
unloaded/reloaded.



  Corrections, suggestions or comments very welcomed.

-- 
Chris 'Xenon' Hanson, omo sanza lettere                  Xenon AlphaPixel.com
PixelSense Landsat processing now available! http://www.alphapixel.com/demos/
"There is no Truth. There is only Perception. To Perceive is to Exist." - Xen


More information about the osg-users mailing list