void Map::clear() { ImageLayerVector imageLayersRemoved; ElevationLayerVector elevLayersRemoved; ModelLayerVector modelLayersRemoved; MaskLayerVector maskLayersRemoved; Revision newRevision; { Threading::ScopedWriteLock lock( _mapDataMutex ); imageLayersRemoved.swap( _imageLayers ); elevLayersRemoved.swap ( _elevationLayers ); modelLayersRemoved.swap( _modelLayers ); // calculate a new revision. newRevision = ++_dataModelRevision; } // a separate block b/c we don't need the mutex for( MapCallbackList::iterator i = _mapCallbacks.begin(); i != _mapCallbacks.end(); i++ ) { for( ImageLayerVector::iterator k = imageLayersRemoved.begin(); k != imageLayersRemoved.end(); ++k ) i->get()->onMapModelChanged( MapModelChange(MapModelChange::REMOVE_IMAGE_LAYER, newRevision, k->get()) ); for( ElevationLayerVector::iterator k = elevLayersRemoved.begin(); k != elevLayersRemoved.end(); ++k ) i->get()->onMapModelChanged( MapModelChange(MapModelChange::REMOVE_ELEVATION_LAYER, newRevision, k->get()) ); for( ModelLayerVector::iterator k = modelLayersRemoved.begin(); k != modelLayersRemoved.end(); ++k ) i->get()->onMapModelChanged( MapModelChange(MapModelChange::REMOVE_MODEL_LAYER, newRevision, k->get()) ); } }
Revision Map::getModelLayers( ModelLayerVector& out_list ) const { out_list.reserve( _modelLayers.size() ); Threading::ScopedReadLock lock( const_cast<Map*>(this)->_mapDataMutex ); for( ModelLayerVector::const_iterator i = _modelLayers.begin(); i != _modelLayers.end(); ++i ) out_list.push_back( i->get() ); return _dataModelRevision; }
MapNode::~MapNode() { _map->removeMapCallback( _mapCallback.get() ); ModelLayerVector modelLayers; _map->getModelLayers( modelLayers ); //Remove our model callback from any of the model layers in the map for (osgEarth::ModelLayerVector::iterator itr = modelLayers.begin(); itr != modelLayers.end(); ++itr) { this->onModelLayerRemoved( itr->get() ); } }
void ElevationQuery::gatherPatchLayers() { // cache a vector of terrain patch models. _patchLayers.clear(); ModelLayerVector modelLayers; _mapf.getLayers(modelLayers); for(ModelLayerVector::const_iterator i = modelLayers.begin(); i != modelLayers.end(); ++i) { if ( i->get()->isTerrainPatch() ) _patchLayers.push_back( i->get() ); } }
void dirtyModelLayers() { ModelLayerVector modelLayers; s_activeMap->getLayers(modelLayers); for(unsigned i=0; i<modelLayers.size(); ++i) { ModelSource* ms = modelLayers.at(i)->getModelSource(); if ( ms ) { ms->dirty(); } else { OE_NOTICE << modelLayers.at(i)->getName() << " has no model source.\n"; } } }
void Map::setLayersFromMap( const Map* map ) { this->clear(); if ( map ) { ImageLayerVector newImages; map->getImageLayers( newImages ); for( ImageLayerVector::iterator i = newImages.begin(); i != newImages.end(); ++i ) addImageLayer( i->get() ); ElevationLayerVector newElev; map->getElevationLayers( newElev ); for( ElevationLayerVector::iterator i = newElev.begin(); i != newElev.end(); ++i ) addElevationLayer( i->get() ); ModelLayerVector newModels; map->getModelLayers( newModels ); for( ModelLayerVector::iterator i = newModels.begin(); i != newModels.end(); ++i ) addModelLayer( i->get() ); } }
void MapNode::init() { // Take a reference to this object so that it doesn't get inadvertently // deleting during startup. It is possible that during startup, a driver // will load that will take a reference to the MapNode (like in a // ModelSource node operation) and we don't want that deleting the MapNode // out from under us. // This is paired by an unref_nodelete() at the end of this method. this->ref(); // Protect the MapNode from the Optimizer setDataVariance(osg::Object::DYNAMIC); // initialize 0Ls _terrainEngine = 0L; _terrainEngineContainer = 0L; _overlayDecorator = 0L; setName( "osgEarth::MapNode" ); // Since we have global uniforms in the stateset, mark it dynamic so it is immune to // multi-threaded overlap // TODO: do we need this anymore? there are no more global uniforms in here.. gw getOrCreateStateSet()->setDataVariance(osg::Object::DYNAMIC); _modelLayerCallback = new MapModelLayerCallback(this); _maskLayerNode = 0L; _lastNumBlacklistedFilenames = 0; // Set the global proxy settings // TODO: this should probably happen elsewhere, like in the registry? if ( _mapNodeOptions.proxySettings().isSet() ) { HTTPClient::setProxySettings( _mapNodeOptions.proxySettings().get() ); } // establish global driver options. These are OSG reader-writer options that // will make their way to any read* calls down the pipe const osgDB::Options* global_options = _map->getGlobalOptions(); osg::ref_ptr<osgDB::Options> local_options = global_options ? Registry::instance()->cloneOrCreateOptions( global_options ) : NULL; if ( local_options.valid() ) { OE_INFO << LC << "Options string = " << (local_options.valid()? local_options->getOptionString() : "<empty>") << std::endl; } // TODO: not sure why we call this here _map->setGlobalOptions( local_options.get() ); // load and attach the terrain engine, but don't initialize it until we need it const TerrainOptions& terrainOptions = _mapNodeOptions.getTerrainOptions(); _terrainEngine = TerrainEngineNodeFactory::create( _map.get(), terrainOptions ); _terrainEngineInitialized = false; // the engine needs a container so we can set lighting state on the container and // not on the terrain engine itself. Setting the dynamic variance will prevent // an optimizer from collapsing the empty group node. _terrainEngineContainer = new osg::Group(); _terrainEngineContainer->setDataVariance( osg::Object::DYNAMIC ); this->addChild( _terrainEngineContainer ); // initialize terrain-level lighting: if ( terrainOptions.enableLighting().isSet() ) { _terrainEngineContainer->getOrCreateStateSet()->setMode( GL_LIGHTING, terrainOptions.enableLighting().value() ? 1 : 0 ); } if ( _terrainEngine ) { // inform the terrain engine of the map information now so that it can properly // initialize it's CoordinateSystemNode. This is necessary in order to support // manipulators and to set up the texture compositor prior to frame-loop // initialization. _terrainEngine->preInitialize( _map.get(), terrainOptions ); _terrainEngineContainer->addChild( _terrainEngine ); } else { OE_WARN << "FAILED to create a terrain engine for this map" << std::endl; } // make a group for the model layers. // NOTE: for now, we are going to nullify any shader programs that occur above the model // group, since it does not YET support shader composition. Programs defined INSIDE a // model layer will still work OK though. _models = new osg::Group(); _models->setName( "osgEarth::MapNode.modelsGroup" ); addChild( _models.get() ); // make a group for overlay model layers: _overlayModels = new ObserverGroup(); //osg::Group(); _overlayModels->setName( "osgEarth::MapNode.overlayModelsGroup" ); // a decorator for overlay models: _overlayDecorator = new OverlayDecorator(); _overlayDecorator->setOverlayGraphTraversalMask( terrainOptions.secondaryTraversalMask().value() ); if ( _mapNodeOptions.overlayBlending().isSet() ) _overlayDecorator->setOverlayBlending( *_mapNodeOptions.overlayBlending() ); if ( _mapNodeOptions.overlayTextureSize().isSet() ) _overlayDecorator->setTextureSize( *_mapNodeOptions.overlayTextureSize() ); if ( _mapNodeOptions.overlayMipMapping().isSet() ) _overlayDecorator->setMipMapping( *_mapNodeOptions.overlayMipMapping() ); addTerrainDecorator( _overlayDecorator ); // install any pre-existing model layers: ModelLayerVector modelLayers; _map->getModelLayers( modelLayers ); int modelLayerIndex = 0; for( ModelLayerVector::const_iterator k = modelLayers.begin(); k != modelLayers.end(); k++, modelLayerIndex++ ) { onModelLayerAdded( k->get(), modelLayerIndex ); } _mapCallback = new MapNodeMapCallbackProxy(this); // install a layer callback for processing further map actions: _map->addMapCallback( _mapCallback.get() ); osg::StateSet* ss = getOrCreateStateSet(); if ( _mapNodeOptions.enableLighting().isSet() ) { ss->setMode( GL_LIGHTING, _mapNodeOptions.enableLighting().value() ? 1 : 0 ); } dirtyBound(); // Install top-level shader programs: if ( Registry::capabilities().supportsGLSL() ) { VirtualProgram* vp = new VirtualProgram(); vp->setName( "MapNode" ); vp->installDefaultColoringAndLightingShaders(); ss->setAttributeAndModes( vp, osg::StateAttribute::ON ); } // register for event traversals so we can deal with blacklisted filenames ADJUST_EVENT_TRAV_COUNT( this, 1 ); // remove the temporary reference. this->unref_nodelete(); }
void updateControlPanel() { // erase all child controls and just rebuild them b/c we're lazy. //Rebuild all the image layers s_imageBox->clearControls(); int row = 0; LabelControl* activeLabel = new LabelControl( "Image Layers", 20, osg::Vec4f(1,1,0,1) ); s_imageBox->setControl( 1, row++, activeLabel ); // the active map layers: MapFrame mapf( s_activeMap.get() ); ImageLayerVector imageLayers; mapf.getLayers(imageLayers); int layerNum = imageLayers.size()-1; for( ImageLayerVector::const_reverse_iterator i = imageLayers.rbegin(); i != imageLayers.rend(); ++i ) createLayerItem( s_imageBox, row++, layerNum--, imageLayers.size(), i->get(), true ); MapFrame mapf2( s_inactiveMap.get() ); imageLayers.clear(); mapf2.getLayers(imageLayers); if ( imageLayers.size() > 0 ) { LabelControl* inactiveLabel = new LabelControl( "Removed:", 18, osg::Vec4f(1,1,0,1) ); s_imageBox->setControl( 1, row++, inactiveLabel ); for( unsigned int i=0; i<imageLayers.size(); ++i ) { createLayerItem( s_imageBox, row++, -1, -1, imageLayers[i].get(), false ); } } //Rebuild the elevation layers s_elevationBox->clearControls(); row = 0; activeLabel = new LabelControl( "Elevation Layers", 20, osg::Vec4f(1,1,0,1) ); s_elevationBox->setControl( 1, row++, activeLabel ); // the active map layers: ElevationLayerVector elevationLayers; mapf.getLayers(elevationLayers); layerNum = elevationLayers.size()-1; for( ElevationLayerVector::const_reverse_iterator i = elevationLayers.rbegin(); i != elevationLayers.rend(); ++i ) createLayerItem( s_elevationBox, row++, layerNum--, elevationLayers.size(), i->get(), true ); if ( mapf2.elevationLayers().size() > 0 ) { LabelControl* inactiveLabel = new LabelControl( "Removed:", 18, osg::Vec4f(1,1,0,1) ); s_elevationBox->setControl( 1, row++, inactiveLabel ); for( unsigned int i=0; i<mapf2.elevationLayers().size(); ++i ) { createLayerItem( s_elevationBox, row++, -1, -1, mapf2.elevationLayers().at(i), false ); } } //Rebuild the model layers s_modelBox->clearControls(); row = 0; activeLabel = new LabelControl( "Model Layers", 20, osg::Vec4f(1,1,0,1) ); s_modelBox->setControl( 1, row++, activeLabel ); // the active map layers: ModelLayerVector modelLayers; mapf.getLayers(modelLayers); for( ModelLayerVector::const_reverse_iterator i = modelLayers.rbegin(); i != modelLayers.rend(); ++i ) createModelLayerItem( s_modelBox, row++, i->get(), true ); }
void MapNode::init() { // Take a reference to this object so that it doesn't get inadvertently // deleting during startup. It is possible that during startup, a driver // will load that will take a reference to the MapNode (like in a // ModelSource node operation) and we don't want that deleting the MapNode // out from under us. // This is paired by an unref_nodelete() at the end of this method. this->ref(); // Protect the MapNode from the Optimizer setDataVariance(osg::Object::DYNAMIC); // Protect the MapNode from the ShaderGenerator ShaderGenerator::setIgnoreHint(this, true); // initialize 0Ls _terrainEngine = 0L; _terrainEngineContainer = 0L; _overlayDecorator = 0L; setName( "osgEarth::MapNode" ); _maskLayerNode = 0L; _lastNumBlacklistedFilenames = 0; // Set the global proxy settings // TODO: this should probably happen elsewhere, like in the registry? if ( _mapNodeOptions.proxySettings().isSet() ) { HTTPClient::setProxySettings( _mapNodeOptions.proxySettings().get() ); } // establish global driver options. These are OSG reader-writer options that // will make their way to any read* calls down the pipe const osgDB::Options* global_options = _map->getGlobalOptions(); osg::ref_ptr<osgDB::Options> local_options = global_options ? Registry::instance()->cloneOrCreateOptions( global_options ) : NULL; if ( local_options.valid() ) { OE_INFO << LC << "Options string = " << (local_options.valid()? local_options->getOptionString() : "<empty>") << std::endl; } // TODO: not sure why we call this here _map->setGlobalOptions( local_options.get() ); // load and attach the terrain engine, but don't initialize it until we need it const TerrainOptions& terrainOptions = _mapNodeOptions.getTerrainOptions(); _terrainEngine = TerrainEngineNodeFactory::create( _map.get(), terrainOptions ); _terrainEngineInitialized = false; // the engine needs a container so we can set lighting state on the container and // not on the terrain engine itself. Setting the dynamic variance will prevent // an optimizer from collapsing the empty group node. _terrainEngineContainer = new osg::Group(); _terrainEngineContainer->setDataVariance( osg::Object::DYNAMIC ); this->addChild( _terrainEngineContainer ); // initialize terrain-level lighting: if ( terrainOptions.enableLighting().isSet() ) { _terrainEngineContainer->getOrCreateStateSet()->addUniform( Registry::shaderFactory()->createUniformForGLMode(GL_LIGHTING, *terrainOptions.enableLighting()) ); _terrainEngineContainer->getOrCreateStateSet()->setMode( GL_LIGHTING, terrainOptions.enableLighting().value() ? 1 : 0 ); } if ( _terrainEngine ) { // inform the terrain engine of the map information now so that it can properly // initialize it's CoordinateSystemNode. This is necessary in order to support // manipulators and to set up the texture compositor prior to frame-loop // initialization. _terrainEngine->preInitialize( _map.get(), terrainOptions ); _terrainEngineContainer->addChild( _terrainEngine ); } else { OE_WARN << "FAILED to create a terrain engine for this map" << std::endl; } // make a group for the model layers. // NOTE: for now, we are going to nullify any shader programs that occur above the model // group, since it does not YET support shader composition. Programs defined INSIDE a // model layer will still work OK though. _models = new osg::Group(); _models->setName( "osgEarth::MapNode.modelsGroup" ); _models->getOrCreateStateSet()->setRenderBinDetails(2, "RenderBin"); addChild( _models.get() ); // a decorator for overlay models: _overlayDecorator = new OverlayDecorator(); // install the Draping technique for overlays: { DrapingTechnique* draping = new DrapingTechnique(); const char* envOverlayTextureSize = ::getenv("OSGEARTH_OVERLAY_TEXTURE_SIZE"); if ( _mapNodeOptions.overlayBlending().isSet() ) draping->setOverlayBlending( *_mapNodeOptions.overlayBlending() ); if ( envOverlayTextureSize ) draping->setTextureSize( as<int>(envOverlayTextureSize, 1024) ); else if ( _mapNodeOptions.overlayTextureSize().isSet() ) draping->setTextureSize( *_mapNodeOptions.overlayTextureSize() ); if ( _mapNodeOptions.overlayMipMapping().isSet() ) draping->setMipMapping( *_mapNodeOptions.overlayMipMapping() ); if ( _mapNodeOptions.overlayAttachStencil().isSet() ) draping->setAttachStencil( *_mapNodeOptions.overlayAttachStencil() ); if ( _mapNodeOptions.overlayResolutionRatio().isSet() ) draping->setResolutionRatio( *_mapNodeOptions.overlayResolutionRatio() ); _overlayDecorator->addTechnique( draping ); } // install the Clamping technique for overlays: { _overlayDecorator->addTechnique( new ClampingTechnique() ); } addTerrainDecorator( _overlayDecorator ); // install any pre-existing model layers: ModelLayerVector modelLayers; _map->getModelLayers( modelLayers ); int modelLayerIndex = 0; for( ModelLayerVector::const_iterator k = modelLayers.begin(); k != modelLayers.end(); k++, modelLayerIndex++ ) { onModelLayerAdded( k->get(), modelLayerIndex ); } _mapCallback = new MapNodeMapCallbackProxy(this); // install a layer callback for processing further map actions: _map->addMapCallback( _mapCallback.get() ); osg::StateSet* stateset = getOrCreateStateSet(); if ( _mapNodeOptions.enableLighting().isSet() ) { stateset->addUniform(Registry::shaderFactory()->createUniformForGLMode( GL_LIGHTING, _mapNodeOptions.enableLighting().value() ? 1 : 0)); stateset->setMode( GL_LIGHTING, _mapNodeOptions.enableLighting().value() ? 1 : 0); } // Add in some global uniforms stateset->addUniform( new osg::Uniform("oe_isGeocentric", _map->isGeocentric()) ); if ( _map->isGeocentric() ) { OE_INFO << LC << "Adding ellipsoid uniforms.\n"; // for a geocentric map, use an ellipsoid unit-frame transform and its inverse: osg::Vec3d ellipFrameInverse( _map->getSRS()->getEllipsoid()->getRadiusEquator(), _map->getSRS()->getEllipsoid()->getRadiusEquator(), _map->getSRS()->getEllipsoid()->getRadiusPolar()); stateset->addUniform( new osg::Uniform("oe_ellipsoidFrameInverse", osg::Vec3f(ellipFrameInverse)) ); osg::Vec3d ellipFrame = osg::componentDivide(osg::Vec3d(1.0,1.0,1.0), ellipFrameInverse); stateset->addUniform( new osg::Uniform("oe_ellipsoidFrame", osg::Vec3f(ellipFrame)) ); } // install the default rendermode uniform: stateset->addUniform( new osg::Uniform("oe_isPickCamera", false) ); dirtyBound(); // register for event traversals so we can deal with blacklisted filenames ADJUST_EVENT_TRAV_COUNT( this, 1 ); // remove the temporary reference. this->unref_nodelete(); }
void MapNode::init() { // Protect the MapNode from the Optimizer setDataVariance(osg::Object::DYNAMIC); setName( "osgEarth::MapNode" ); // Since we have global uniforms in the stateset, mark it dynamic so it is immune to // multi-threaded overlap // TODO: do we need this anymore? there are no more global uniforms in here.. gw getOrCreateStateSet()->setDataVariance(osg::Object::DYNAMIC); _modelLayerCallback = new MapModelLayerCallback(this); _maskLayerNode = 0L; _lastNumBlacklistedFilenames = 0; // Set the global proxy settings // TODO: this should probably happen elsewhere, like in the registry? if ( _mapNodeOptions.proxySettings().isSet() ) { HTTPClient::setProxySettings( _mapNodeOptions.proxySettings().get() ); } // establish global driver options. These are OSG reader-writer options that // will make their way to any read* calls down the pipe const osgDB::ReaderWriter::Options* global_options = _map->getGlobalOptions(); osg::ref_ptr<osgDB::ReaderWriter::Options> local_options = global_options ? new osgDB::ReaderWriter::Options( *global_options ) : NULL; if ( local_options.valid() ) { OE_INFO << LC << "Options string = " << (local_options.valid()? local_options->getOptionString() : "<empty>") << std::endl; } // TODO: not sure why we call this here _map->setGlobalOptions( local_options.get() ); // overlays: _pendingOverlayAutoSetTextureUnit = true; // load and attach the terrain engine, but don't initialize it until we need it const TerrainOptions& terrainOptions = _mapNodeOptions.getTerrainOptions(); _terrainEngine = TerrainEngineNodeFactory::create( _map.get(), terrainOptions ); _terrainEngineInitialized = false; // the engine needs a container so we can set lighting state on the container and // not on the terrain engine itself. Setting the dynamic variance will prevent // an optimizer from collapsing the empty group node. _terrainEngineContainer = new osg::Group(); _terrainEngineContainer->setDataVariance( osg::Object::DYNAMIC ); this->addChild( _terrainEngineContainer.get() ); // initialize terrain-level lighting: if ( terrainOptions.enableLighting().isSet() ) { _terrainEngineContainer->getOrCreateStateSet()->setMode( GL_LIGHTING, terrainOptions.enableLighting().value() ? osg::StateAttribute::ON | osg::StateAttribute::PROTECTED : osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED ); } if ( _terrainEngine.valid() ) { // inform the terrain engine of the map information now so that it can properly // initialize it's CoordinateSystemNode. This is necessary in order to support // manipulators and to set up the texture compositor prior to frame-loop // initialization. _terrainEngine->preInitialize( _map.get(), terrainOptions ); _terrainEngineContainer->addChild( _terrainEngine.get() ); } else OE_WARN << "FAILED to create a terrain engine for this map" << std::endl; // make a group for the model layers: _models = new osg::Group(); _models->setName( "osgEarth::MapNode.modelsGroup" ); addChild( _models.get() ); // make a group for overlay model layers: _overlayModels = new osg::Group(); _overlayModels->setName( "osgEarth::MapNode.overlayModelsGroup" ); // a decorator for overlay models: _overlayDecorator = new OverlayDecorator(); if ( _mapNodeOptions.overlayVertexWarping().isSet() ) _overlayDecorator->setVertexWarping( *_mapNodeOptions.overlayVertexWarping() ); if ( _mapNodeOptions.overlayBlending().isSet() ) _overlayDecorator->setOverlayBlending( *_mapNodeOptions.overlayBlending() ); if ( _mapNodeOptions.overlayTextureSize().isSet() ) _overlayDecorator->setTextureSize( *_mapNodeOptions.overlayTextureSize() ); if ( _mapNodeOptions.overlayMipMapping().isSet() ) _overlayDecorator->setMipMapping( *_mapNodeOptions.overlayMipMapping() ); addTerrainDecorator( _overlayDecorator.get() ); // install any pre-existing model layers: ModelLayerVector modelLayers; _map->getModelLayers( modelLayers ); int modelLayerIndex = 0; for( ModelLayerVector::const_iterator k = modelLayers.begin(); k != modelLayers.end(); k++, modelLayerIndex++ ) { onModelLayerAdded( k->get(), modelLayerIndex ); } _mapCallback = new MapNodeMapCallbackProxy(this); // install a layer callback for processing further map actions: _map->addMapCallback( _mapCallback.get() ); osg::StateSet* ss = getOrCreateStateSet(); //ss->setAttributeAndModes( new osg::CullFace() ); //, osg::StateAttribute::ON); //ss->setAttributeAndModes( new osg::PolygonOffset( -1, -1 ) ); if ( _mapNodeOptions.enableLighting().isSet() ) { ss->setMode( GL_LIGHTING, _mapNodeOptions.enableLighting().value() ? osg::StateAttribute::ON | osg::StateAttribute::PROTECTED : osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED ); } dirtyBound(); // register for event traversals so we can deal with blacklisted filenames ADJUST_EVENT_TRAV_COUNT( this, 1 ); }