osgEarth 2.1.1
|
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 |
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).
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.
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(); }
DRoamNode::META_Node | ( | osgEarth | , |
DRoamNode | |||
) |
void DRoamNode::update | ( | osg::NodeVisitor * | nv | ) | [private] |
Definition at line 86 of file DRoamNode.cpp.
{ _mesh->update(); }
friend struct MyCullCallback [friend] |
friend struct MyUpdateCallback [friend] |
osg::ref_ptr<osg::Geode> DRoamNode::_geode [private] |
osg::ref_ptr<Manifold> DRoamNode::_manifold [private] |
osg::ref_ptr<osgEarth::Map> DRoamNode::_map [private] |
osg::ref_ptr<MeshManager> DRoamNode::_mesh [private] |