osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarth/MapNode.cpp

Go to the documentation of this file.
00001 /* -*-c++-*- */
00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
00003 * Copyright 2008-2010 Pelican Mapping
00004 * http://osgearth.org
00005 *
00006 * osgEarth is free software; you can redistribute it and/or modify
00007 * it under the terms of the GNU Lesser General Public License as published by
00008 * the Free Software Foundation; either version 2 of the License, or
00009 * (at your option) any later version.
00010 *
00011 * This program is distributed in the hope that it will be useful,
00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 * GNU Lesser General Public License for more details.
00015 *
00016 * You should have received a copy of the GNU Lesser General Public License
00017 * along with this program.  If not, see <http://www.gnu.org/licenses/>
00018 */
00019 #include <osgEarth/MapNode>
00020 #include <osgEarth/MaskNode>
00021 #include <osgEarth/FindNode>
00022 #include <osgEarth/Registry>
00023 #include <osgEarth/ShaderComposition>
00024 #include <osgEarth/OverlayDecorator>
00025 #include <osg/ArgumentParser>
00026 #include <osg/PagedLOD>
00027 
00028 using namespace osgEarth;
00029 
00030 #define LC "[MapNode] "
00031 
00032 //---------------------------------------------------------------------------
00033 
00034 namespace 
00035 {
00036     // adapter that lets MapNode listen to Map events
00037     struct MapNodeMapCallbackProxy : public MapCallback
00038     {
00039         MapNodeMapCallbackProxy(MapNode* node) : _node(node) { }
00040 
00041         void onModelLayerAdded( ModelLayer* layer, unsigned int index ) {
00042             _node->onModelLayerAdded( layer, index );
00043         }
00044         void onModelLayerRemoved( ModelLayer* layer ) {
00045             _node->onModelLayerRemoved( layer );
00046         }
00047         void onModelLayerMoved( ModelLayer* layer, unsigned int oldIndex, unsigned int newIndex ) {
00048             _node->onModelLayerMoved( layer, oldIndex, newIndex);
00049         }
00050 #if 0
00051         void onMaskLayerAdded( MaskLayer* layer ) {
00052             _node->onMaskLayerAdded( layer );
00053         }
00054         void onMaskLayerRemoved( MaskLayer* layer ) {
00055             _node->onMaskLayerRemoved( layer );
00056         }
00057 #endif
00058 
00059         osg::observer_ptr<MapNode> _node;
00060     };
00061 
00062     // converys overlay property changes to the OverlayDecorator in MapNode.
00063     class MapModelLayerCallback : public ModelLayerCallback
00064     {
00065     public:
00066         MapModelLayerCallback(MapNode* mapNode) : _node(mapNode) { }
00067 
00068         virtual void onOverlayChanged(ModelLayer* layer)
00069         {
00070             _node->onModelLayerOverlayChanged( layer );
00071         }
00072 
00073         osg::observer_ptr<MapNode> _node;
00074     };
00075 }
00076 
00077 //---------------------------------------------------------------------------
00078 
00079 class RemoveBlacklistedFilenamesVisitor : public osg::NodeVisitor
00080 {
00081 public:
00082     RemoveBlacklistedFilenamesVisitor():
00083       osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
00084           _numRemoved(0)
00085       {
00086       }
00087 
00088       virtual void apply(osg::PagedLOD& node)
00089       {        
00090           //The PagedLOD node will contain two filenames, the first is empty and is the actual geometry of the          
00091           //tile and the second is the filename of the next tile.
00092           if (node.getNumFileNames() > 1)
00093           {
00094               //Get the child filename
00095               const std::string &filename = node.getFileName(1);              
00096               if (osgEarth::Registry::instance()->isBlacklisted(filename))
00097               {
00098                   //If the tile is blacklisted, we set the actual geometry, child 0, to always display
00099                   //and the second child to never display
00100                   node.setRange(0, 0, FLT_MAX);
00101                   node.setRange(1, FLT_MAX, FLT_MAX);
00102               }
00103               else
00104               {
00105                   //If the child is not blacklisted, it is possible that it could have been blacklisted previously so reset the
00106                   //ranges of both the first and second children.  This gives the second child another
00107                   //chance to be traversed in case a layer was added that might have data.
00108                   osg::ref_ptr< MapNode::TileRangeData > ranges = static_cast< MapNode::TileRangeData* >(node.getUserData());
00109                   if (ranges)
00110                   {
00111                       node.setRange(0, ranges->_minRange, ranges->_maxRange);
00112                       node.setRange(1, 0, ranges->_minRange);
00113                   }                  
00114               }
00115               
00116           }
00117           traverse(node);
00118       }
00119 
00120       unsigned int _numRemoved;
00121 };
00122 
00123 //---------------------------------------------------------------------------
00124 
00125 MapNode*
00126 MapNode::load(osg::ArgumentParser& args)
00127 {
00128     for( unsigned i=1; i<args.argc(); ++i )
00129     {
00130         if ( args[i] && endsWith(args[i], ".earth") )
00131         {
00132             osg::ref_ptr<osg::Node> output;
00133             if ( HTTPClient::readNodeFile( args[i], output ) == HTTPClient::RESULT_OK )
00134             {
00135                 return dynamic_cast<MapNode*>( output.release() );
00136             }
00137         }
00138     }    
00139     return 0L;
00140 }
00141 
00142 //---------------------------------------------------------------------------
00143 
00144 MapNode::MapNode() :
00145 _map( new Map() )
00146 {
00147     init();
00148 }
00149 
00150 MapNode::MapNode( Map* map ) :
00151 _map( map )
00152 {
00153     init();
00154 }
00155 
00156 MapNode::MapNode( const MapNodeOptions& options ) :
00157 _map( new Map() ),
00158 _mapNodeOptions( options )
00159 {
00160     init();
00161 }
00162 
00163 MapNode::MapNode( Map* map, const MapNodeOptions& options ) :
00164 _map( map? map : new Map() ),
00165 _mapNodeOptions( options )
00166 {
00167     init();
00168 }
00169 
00170 void
00171 MapNode::init()
00172 {
00173         // Protect the MapNode from the Optimizer
00174         setDataVariance(osg::Object::DYNAMIC);
00175 
00176     setName( "osgEarth::MapNode" );
00177 
00178     // Since we have global uniforms in the stateset, mark it dynamic so it is immune to
00179     // multi-threaded overlap
00180     // TODO: do we need this anymore? there are no more global uniforms in here.. gw
00181     getOrCreateStateSet()->setDataVariance(osg::Object::DYNAMIC);
00182 
00183     _modelLayerCallback = new MapModelLayerCallback(this);
00184 
00185     _maskLayerNode = 0L;
00186     _lastNumBlacklistedFilenames = 0;
00187 
00188     // Set the global proxy settings
00189     // TODO: this should probably happen elsewhere, like in the registry?
00190     if ( _mapNodeOptions.proxySettings().isSet() )
00191     {
00192                 HTTPClient::setProxySettings( _mapNodeOptions.proxySettings().get() );
00193     }
00194 
00195     // establish global driver options. These are OSG reader-writer options that
00196     // will make their way to any read* calls down the pipe
00197     const osgDB::ReaderWriter::Options* global_options = _map->getGlobalOptions();
00198     osg::ref_ptr<osgDB::ReaderWriter::Options> local_options = global_options ? 
00199         new osgDB::ReaderWriter::Options( *global_options ) :
00200         NULL;
00201 
00202     if ( local_options.valid() )
00203     {
00204         OE_INFO << LC
00205             << "Options string = " 
00206             << (local_options.valid()? local_options->getOptionString() : "<empty>")
00207             << std::endl;
00208     }
00209 
00210     // TODO: not sure why we call this here
00211     _map->setGlobalOptions( local_options.get() );
00212 
00213     // overlays:
00214     _pendingOverlayAutoSetTextureUnit = true;
00215 
00216     // load and attach the terrain engine, but don't initialize it until we need it
00217     const TerrainOptions& terrainOptions = _mapNodeOptions.getTerrainOptions();
00218 
00219     _terrainEngine = TerrainEngineNodeFactory::create( _map.get(), terrainOptions );
00220     _terrainEngineInitialized = false;
00221 
00222     // the engine needs a container so we can set lighting state on the container and
00223     // not on the terrain engine itself. Setting the dynamic variance will prevent
00224     // an optimizer from collapsing the empty group node.
00225     _terrainEngineContainer = new osg::Group();
00226     _terrainEngineContainer->setDataVariance( osg::Object::DYNAMIC );
00227     this->addChild( _terrainEngineContainer.get() );
00228 
00229     // initialize terrain-level lighting:
00230     if ( terrainOptions.enableLighting().isSet() )
00231     {
00232         _terrainEngineContainer->getOrCreateStateSet()->setMode( GL_LIGHTING, terrainOptions.enableLighting().value() ? 
00233             osg::StateAttribute::ON | osg::StateAttribute::PROTECTED :
00234             osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
00235     }
00236 
00237     if ( _terrainEngine.valid() )
00238     {
00239         // inform the terrain engine of the map information now so that it can properly
00240         // initialize it's CoordinateSystemNode. This is necessary in order to support
00241         // manipulators and to set up the texture compositor prior to frame-loop 
00242         // initialization.
00243         _terrainEngine->preInitialize( _map.get(), terrainOptions );
00244 
00245         _terrainEngineContainer->addChild( _terrainEngine.get() );
00246     }
00247     else
00248         OE_WARN << "FAILED to create a terrain engine for this map" << std::endl;
00249 
00250     // make a group for the model layers:
00251     _models = new osg::Group();
00252     _models->setName( "osgEarth::MapNode.modelsGroup" );
00253     addChild( _models.get() );
00254 
00255     // make a group for overlay model layers:
00256     _overlayModels = new osg::Group();
00257     _overlayModels->setName( "osgEarth::MapNode.overlayModelsGroup" );
00258 
00259     // a decorator for overlay models:
00260     _overlayDecorator = new OverlayDecorator();
00261     if ( _mapNodeOptions.overlayVertexWarping().isSet() )
00262         _overlayDecorator->setVertexWarping( *_mapNodeOptions.overlayVertexWarping() );
00263     if ( _mapNodeOptions.overlayBlending().isSet() )
00264         _overlayDecorator->setOverlayBlending( *_mapNodeOptions.overlayBlending() );
00265     if ( _mapNodeOptions.overlayTextureSize().isSet() )
00266         _overlayDecorator->setTextureSize( *_mapNodeOptions.overlayTextureSize() );
00267     addTerrainDecorator( _overlayDecorator.get() );
00268 
00269     // install any pre-existing model layers:
00270     ModelLayerVector modelLayers;
00271     _map->getModelLayers( modelLayers );
00272     int modelLayerIndex = 0;
00273     for( ModelLayerVector::const_iterator k = modelLayers.begin(); k != modelLayers.end(); k++, modelLayerIndex++ )
00274     {
00275         onModelLayerAdded( k->get(), modelLayerIndex );
00276     }
00277 
00278 #if 0
00279     // install any pre-existing mask layer:
00280     if ( _map->getTerrainMaskLayer() )
00281     {
00282         onMaskLayerAdded( _map->getTerrainMaskLayer() );
00283     }
00284 #endif
00285 
00286     _mapCallback = new MapNodeMapCallbackProxy(this);
00287     // install a layer callback for processing further map actions:
00288     _map->addMapCallback( _mapCallback.get()  );
00289 
00290     osg::StateSet* ss = getOrCreateStateSet();
00291         //ss->setAttributeAndModes( new osg::CullFace() ); //, osg::StateAttribute::ON);
00292     //ss->setAttributeAndModes( new osg::PolygonOffset( -1, -1 ) );
00293 
00294     if ( _mapNodeOptions.enableLighting().isSet() )
00295     {
00296         ss->setMode( GL_LIGHTING, _mapNodeOptions.enableLighting().value() ? 
00297             osg::StateAttribute::ON | osg::StateAttribute::PROTECTED :
00298             osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
00299     }
00300 
00301     dirtyBound();
00302 
00303     // register for event traversals so we can deal with blacklisted filenames
00304     adjustEventTraversalCount( 1 );
00305 }
00306 
00307 MapNode::~MapNode()
00308 {
00309     _map->removeMapCallback( _mapCallback.get() );
00310 
00311     ModelLayerVector modelLayers;
00312     _map->getModelLayers( modelLayers );
00313     //Remove our model callback from any of the model layers in the map    
00314     for (osgEarth::ModelLayerVector::iterator itr = modelLayers.begin(); itr != modelLayers.end(); ++itr)
00315     {
00316         this->onModelLayerRemoved( itr->get() );        
00317     }
00318 }
00319 
00320 osg::BoundingSphere
00321 MapNode::computeBound() const
00322 {
00323     osg::BoundingSphere bs;
00324     if ( getTerrainEngine() )
00325     {
00326         bs.expandBy(  getTerrainEngine()->getBound() );
00327     }
00328     if ( _models.valid() )
00329         bs.expandBy( _models->getBound() );
00330     return bs;
00331 }
00332 
00333 Map*
00334 MapNode::getMap()
00335 {
00336     return _map.get();
00337 }
00338 
00339 TerrainEngineNode*
00340 MapNode::getTerrainEngine() const
00341 {
00342     if ( !_terrainEngineInitialized && _terrainEngine.valid() )
00343     {
00344         _terrainEngine->postInitialize( _map.get(), getMapNodeOptions().getTerrainOptions() );
00345         MapNode* me = const_cast< MapNode* >(this);
00346         me->_terrainEngineInitialized = true;
00347         me->dirtyBound();
00348     }
00349     return _terrainEngine.get();
00350 }
00351 
00352 osg::Group*
00353 MapNode::getModelLayerGroup() const
00354 {
00355     return _models.get();
00356 }
00357 
00358 const MapNodeOptions&
00359 MapNode::getMapNodeOptions() const
00360 {
00361     return _mapNodeOptions;
00362 }
00363 
00364 MapNode*
00365 MapNode::findMapNode( osg::Node* graph )
00366 {
00367     return findTopMostNodeOfType<MapNode>( graph );
00368 }
00369 
00370 bool
00371 MapNode::isGeocentric() const
00372 {
00373     return _map->isGeocentric();
00374 }
00375 
00376 void
00377 MapNode::onModelLayerAdded( ModelLayer* layer, unsigned int index )
00378 {
00379     osg::Node* node = layer->getOrCreateNode();
00380 
00381     layer->addCallback(_modelLayerCallback.get() );
00382 
00383     if ( node )
00384     {
00385         if ( _modelLayerNodes.find( layer ) != _modelLayerNodes.end() )
00386         {
00387             OE_WARN
00388                 << "Illegal: tried to add the name model layer more than once: " 
00389                 << layer->getName()
00390                 << std::endl;
00391         }
00392         else
00393         {
00394             if ( dynamic_cast<TerrainDecorator*>(node) || dynamic_cast<osgSim::OverlayNode*>(node) )
00395             {
00396                 OE_INFO << LC << "Installing overlay node" << std::endl;
00397                 addTerrainDecorator( node->asGroup() );
00398             }
00399             else
00400             {
00401                 if ( layer->getOverlay() )
00402                 {
00403                     _overlayModels->addChild( node ); // todo: index?
00404                     updateOverlayGraph();
00405                 }
00406                 else
00407                 {
00408                     _models->insertChild( index, node );
00409                 }
00410             }
00411 
00412             ModelSource* ms = layer->getModelSource();
00413             if ( ms && ms->getOptions().renderOrder().isSet() )
00414             {
00415                 node->getOrCreateStateSet()->setRenderBinDetails(
00416                     ms->getOptions().renderOrder().value(), "RenderBin" );
00417             }
00418 
00419             _modelLayerNodes[ layer ] = node;
00420         }
00421 
00422         dirtyBound();
00423     }
00424 }
00425 
00426 void
00427 MapNode::onModelLayerRemoved( ModelLayer* layer )
00428 {
00429     if ( layer )
00430     {
00431         layer->removeCallback( _modelLayerCallback.get() );
00432 
00433         // look up the node associated with this model layer.
00434         ModelLayerNodeMap::iterator i = _modelLayerNodes.find( layer );
00435         if ( i != _modelLayerNodes.end() )
00436         {
00437             osg::Node* node = i->second;
00438 
00439             if ( dynamic_cast<TerrainDecorator*>( node ) || dynamic_cast<osgSim::OverlayNode*>( node ) )
00440             {
00441                 removeTerrainDecorator( node->asGroup() );
00442             }
00443             else
00444             {
00445                 if ( layer->getModelLayerOptions().overlay() == true )
00446                 {
00447                     _overlayModels->removeChild( node );
00448                     updateOverlayGraph();
00449                 }
00450                 else
00451                 {
00452                     _models->removeChild( node );
00453                 }
00454             }
00455             
00456             _modelLayerNodes.erase( i );
00457         }
00458         
00459         dirtyBound();
00460     }
00461 }
00462 
00463 void
00464 MapNode::onModelLayerMoved( ModelLayer* layer, unsigned int oldIndex, unsigned int newIndex )
00465 {
00466                 if ( layer )
00467     {
00468         // look up the node associated with this model layer.
00469         ModelLayerNodeMap::iterator i = _modelLayerNodes.find( layer );
00470         if ( i != _modelLayerNodes.end() )
00471         {
00472             osg::Node* node = i->second;
00473             
00474             if ( dynamic_cast<osgSim::OverlayNode*>( node ) )
00475             {
00476                 // treat overlay node as a special case
00477             }
00478             else
00479             {
00480                 _models->removeChild( node );
00481                 _models->insertChild( newIndex, node );
00482             }
00483         }
00484         
00485         dirtyBound();
00486     }
00487 }
00488 
00489 struct MaskNodeFinder : public osg::NodeVisitor {
00490     MaskNodeFinder() : osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN ) { }
00491     void apply( osg::Group& group ) {
00492         if ( dynamic_cast<MaskNode*>( &group ) ) {
00493             _groups.push_back( &group );
00494         }
00495         traverse(group);
00496     }
00497     std::list< osg::Group* > _groups;
00498 };
00499 
00500 void
00501 MapNode::addTerrainDecorator(osg::Group* decorator)
00502 {    
00503     if ( _terrainEngine.valid() )
00504     {
00505         decorator->addChild( _terrainEngine.get() );
00506         _terrainEngine->getParent(0)->replaceChild( _terrainEngine.get(), decorator );
00507         dirtyBound();
00508 
00509         TerrainDecorator* td = dynamic_cast<TerrainDecorator*>( decorator );
00510         if ( td )
00511             td->onInstall( _terrainEngine.get() );
00512     }
00513 }
00514 
00515 void
00516 MapNode::removeTerrainDecorator(osg::Group* decorator)
00517 {
00518     if ( _terrainEngine.valid() )
00519     {
00520         TerrainDecorator* td = dynamic_cast<TerrainDecorator*>( decorator );
00521         if ( td )
00522             td->onUninstall( _terrainEngine.get() );
00523 
00524         osg::Node* child = _terrainEngine.get();
00525         for( osg::Group* g = child->getParent(0); g != _terrainEngineContainer.get(); )
00526         {
00527             if ( g == decorator )
00528             {
00529                 g->getParent(0)->replaceChild( g, child );
00530                 g->removeChild( child );
00531                 break;
00532             }
00533             child = g;
00534             g = g->getParent(0);
00535         }
00536         dirtyBound();
00537     }
00538 }
00539 
00540 void
00541 MapNode::adjustEventTraversalCount( int delta )
00542 {
00543     int oldCount = this->getNumChildrenRequiringEventTraversal();
00544     if ( oldCount + delta >= 0 )
00545         this->setNumChildrenRequiringEventTraversal( (unsigned int)(oldCount + delta) );
00546 }
00547 
00548 void
00549 MapNode::traverse( osg::NodeVisitor& nv )
00550 {
00551     if ( nv.getVisitorType() == osg::NodeVisitor::EVENT_VISITOR )
00552     {
00553         unsigned int numBlacklist = Registry::instance()->getNumBlacklistedFilenames();
00554         if (numBlacklist != _lastNumBlacklistedFilenames)
00555         {
00556             //Only remove the blacklisted filenames if new filenames have been added since last time.
00557             _lastNumBlacklistedFilenames = numBlacklist;
00558             RemoveBlacklistedFilenamesVisitor v;
00559             //accept( v );
00560             _terrainEngine->accept( v );
00561         }
00562     }
00563 
00564     osg::Group::traverse( nv );
00565 }
00566 
00567 void
00568 MapNode::onModelLayerOverlayChanged( ModelLayer* layer )
00569 {
00570     OE_NOTICE << "Overlay changed to "  << layer->getOverlay() << std::endl;
00571     osg::ref_ptr< osg::Group > origParent = layer->getOverlay() ? _models.get() : _overlayModels.get();
00572     osg::ref_ptr< osg::Group > newParent  = layer->getOverlay() ? _overlayModels.get() : _models.get();
00573 
00574     osg::ref_ptr< osg::Node > node = layer->getOrCreateNode();
00575     if (node.valid())
00576     {
00577         //Remove it from the original parent and add it to the new parent
00578         origParent->removeChild( node.get() );
00579         newParent->addChild( node.get() );
00580     }
00581 
00582     updateOverlayGraph();
00583 }
00584 
00585 void
00586 MapNode::updateOverlayGraph()
00587 {
00588     if ( _overlayModels->getNumChildren() > 0 && _overlayDecorator->getOverlayGraph() != _overlayModels.get() )
00589     {
00590         _overlayDecorator->setOverlayGraph( _overlayModels.get() );
00591     }
00592     else if ( _overlayModels->getNumChildren() == 0 && _overlayDecorator->getOverlayGraph() == _overlayModels.get() )
00593     {
00594         _overlayDecorator->setOverlayGraph( 0L );
00595     }
00596 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines