osgEarth 2.1.1
Classes | Public Member Functions | Private Member Functions | Private Attributes | Friends

DRoamNode Class Reference

List of all members.

Classes

struct  MyCullCallback
struct  MyUpdateCallback

Public Member Functions

 DRoamNode (Map *map=0L)
 DRoamNode (const DRoamNode &rhs, const osg::CopyOp &op=osg::CopyOp::DEEP_COPY_ALL)
 META_Node (osgEarth, DRoamNode)

Private Member Functions

void update (osg::NodeVisitor *nv)
void cull (osg::NodeVisitor *nv)

Private Attributes

osg::ref_ptr< osg::Geode > _geode
osg::ref_ptr< Manifold_manifold
osg::ref_ptr< MeshManager_mesh
osg::ref_ptr< osgEarth::Map_map

Friends

struct MyCullCallback
struct MyUpdateCallback

Detailed Description

D-ROAM: A diamond-based continuous manifold terrain engine.

Initially based on the "diamond structure" concept found in: "Realtime Optimal Adaptation for Planetary Geometry and Texture: 4-8 Tile Hierarchies" by Hwa, Duchaineau, and Joy. [1] http://www.computer.org/portal/web/csdl/doi/10.1109/TVCG.2005.65

The global mesh is comprised of Diamonds. The mesh is primed with a "cube manifold" as described in [1]. The entire mesh shared a single vertex array and a single corresponding normal array (in VBOs). Each Diamond referenced verts in this array, thus ensuring a worldwide, continuous, deformable mesh with no cracks.

The first version of this engine rendered each Diamond at each level with its own primitive set. This worked well, but left us with a problem-- no regular gridded structure on which to easily map textures. The second version addresses this by only rendering "quadtree ancestor" diamonds, i.e, diamonds at every other level (odd-numbered levels). By doing this, the base quads correspond to the faces of the base cube manifold, and all sub-quads fall within these 6 faces. We can then use osgEarth's Cube SRS to map textures directly to these quadtree ancestor geometries.

The final problem was dealing with double precision. osgTerrain localizes each terrain tile to solve this problem. Doing that would break our continuous mesh. So instead we will subdivide the mesh into a fixed number of localized regions, and maintain a geometry per-diamond for each region. We can optimize this when we know that a diamond will never render in a particular region. We select which region to render based on camera position.

NOTE: OSG's stats will report outrageous numbers of verticies for this node. That is due to the shared vertex array. Stats counts the vertex array once for each geometry in the mesh, resulting in an exaggerated count. In fact, the real vertex count should be equal to the primitive count (since there is one vertex per diamond).

Definition at line 60 of file DRoamNode.


Constructor & Destructor Documentation

DRoamNode::DRoamNode ( Map map = 0L)

Definition at line 29 of file DRoamNode.cpp.

                               :
_map( map )
{
    this->setCullCallback( new MyCullCallback );
    this->setUpdateCallback( new MyUpdateCallback );

    // TODO: provide the ellipsoid in the ctor (like with MapNode->Map)
    this->setCoordinateSystem( "EPSG:4326" );
    this->setFormat( "WKT" );
    this->setEllipsoidModel( new osg::EllipsoidModel );

#ifdef USE_GEODETIC_MANIFOLD
    _manifold = new GeodeticManifold();
#else
    _manifold = new CubeManifold();
#endif
    _mesh = new MeshManager( _manifold.get(), _map.get() );

    _mesh->_maxActiveLevel = MAX_ACTIVE_LEVEL;

    this->setInitialBound( _manifold->initialBound() );

    this->addChild( _mesh->_amrGeode.get() );

    this->getOrCreateStateSet()->setMode( GL_LIGHTING, 0 );
}
DRoamNode::DRoamNode ( const DRoamNode rhs,
const osg::CopyOp &  op = osg::CopyOp::DEEP_COPY_ALL 
)

Definition at line 56 of file DRoamNode.cpp.

                                                                :
osg::CoordinateSystemNode( rhs, op ),
_manifold( rhs._manifold.get() )
{
    //nop
}

Member Function Documentation

void DRoamNode::cull ( osg::NodeVisitor *  nv) [private]

Definition at line 64 of file DRoamNode.cpp.

{
    osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>( nv );

    // reset the drawable set list. we will populate it by traversing the
    // manifold and collecting drawables that are visible. The new drawables
    // list does not actually take effect until the next frame. So yes, the culling is
    // one frame out of sync with the draw. We should probably think of a way to fix that.
    //_mesh->_activeDrawables.clear();

    _mesh->_amrDrawList.clear();

    _manifold->cull( static_cast<osgUtil::CullVisitor*>( nv ) );

    // I know is not strictly kosher to modify the scene graph from the CULL traversal. But
    // we need frame-coherence, and both the Geode and all Geometry's are marked with DYNAMIC
    // data variance .. so hopefully this is safe.
    _mesh->_amrGeom->setDrawList( _mesh->_amrDrawList );
    _mesh->_amrGeode->dirtyBound();
}

Here is the caller graph for this function:

DRoamNode::META_Node ( osgEarth  ,
DRoamNode   
)
void DRoamNode::update ( osg::NodeVisitor *  nv) [private]

Definition at line 86 of file DRoamNode.cpp.

{
    _mesh->update();
}

Here is the caller graph for this function:


Friends And Related Function Documentation

friend struct MyCullCallback [friend]

Definition at line 83 of file DRoamNode.

friend struct MyUpdateCallback [friend]

Definition at line 91 of file DRoamNode.


Member Data Documentation

osg::ref_ptr<osg::Geode> DRoamNode::_geode [private]

Definition at line 68 of file DRoamNode.

osg::ref_ptr<Manifold> DRoamNode::_manifold [private]

Definition at line 69 of file DRoamNode.

osg::ref_ptr<osgEarth::Map> DRoamNode::_map [private]

Definition at line 71 of file DRoamNode.

osg::ref_ptr<MeshManager> DRoamNode::_mesh [private]

Definition at line 70 of file DRoamNode.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines