void TerrainEngineNode::preInitialize( const Map* map, const TerrainOptions& options ) { _map = map; // fire up a terrain utility interface _terrainInterface = new Terrain( this, map->getProfile(), map->isGeocentric(), options ); // set up the CSN values _map->getProfile()->getSRS()->populateCoordinateSystemNode( this ); // OSG's CSN likes a NULL ellipsoid to represent projected mode. if ( !_map->isGeocentric() ) this->setEllipsoidModel( NULL ); // install the proper layer composition technique: _texCompositor = new TextureCompositor(); // then register the callback so we can process further map model changes _map->addMapCallback( new TerrainEngineNodeCallbackProxy( this ) ); // enable backface culling osg::StateSet* set = getOrCreateStateSet(); set->setMode( GL_CULL_FACE, 1 ); if ( options.enableMercatorFastPath().isSet() ) { OE_INFO << LC << "Mercator fast path " << (options.enableMercatorFastPath()==true? "enabled" : "DISABLED") << std::endl; } _initStage = INIT_PREINIT_COMPLETE; }
void TerrainEngineNode::setMap(const Map* map, const TerrainOptions& options) { if (!map) return; _map = map; // Create a terrain utility interface. This interface can be used // to query the in-memory terrain graph, subscribe to tile events, etc. _terrainInterface = new Terrain( this, map->getProfile(), map->isGeocentric(), options ); // Set up the CSN values. We support this because some manipulators look for it, // but osgEarth itself doesn't use it. _map->getProfile()->getSRS()->populateCoordinateSystemNode( this ); // OSG's CSN likes a NULL ellipsoid to represent projected mode. if ( !_map->isGeocentric() ) this->setEllipsoidModel( NULL ); // Install an object to manage texture image unit usage: _textureResourceTracker = new TextureCompositor(); std::set<int> offLimits = osgEarth::Registry::instance()->getOffLimitsTextureImageUnits(); for(std::set<int>::const_iterator i = offLimits.begin(); i != offLimits.end(); ++i) _textureResourceTracker->setTextureImageUnitOffLimits( *i ); // Register a callback so we can process further map model changes _map->addMapCallback( new TerrainEngineNodeCallbackProxy(this) ); // Force a render bin if specified in the options if ( options.binNumber().isSet() ) { osg::StateSet* set = getOrCreateStateSet(); set->setRenderBinDetails( options.binNumber().get(), "RenderBin" ); } // This is the object that creates the data model for each terrain tile. _tileModelFactory = new TerrainTileModelFactory(options); // Manually trigger the map callbacks the first time: if (_map->getProfile()) onMapInfoEstablished(MapInfo(_map)); // Create a layer controller. This object affects the uniforms // that control layer appearance properties _imageLayerController = new ImageLayerController(_map, this); // register the layer Controller it with all pre-existing image layers: MapFrame mapf(_map); ImageLayerVector imageLayers; mapf.getLayers(imageLayers); for (ImageLayerVector::const_iterator i = imageLayers.begin(); i != imageLayers.end(); ++i) { i->get()->addCallback(_imageLayerController.get()); } _initStage = INIT_POSTINIT_COMPLETE; }
TextureCompositorMultiTexture::TextureCompositorMultiTexture( bool useGPU, const TerrainOptions& options ) : _lodTransitionTime( *options.lodTransitionTime() ), _enableMipmapping ( *options.enableMipmapping() ), _minFilter ( *options.minFilter() ), _magFilter ( *options.magFilter() ), _useGPU ( useGPU ) { _enableMipmappingOnUpdatedTextures = Registry::capabilities().supportsMipmappedTextureUpdates(); }
void RexTerrainEngineNode::preInitialize( const Map* map, const TerrainOptions& options ) { // Force the mercator fast path off, since REX does not support it yet. TerrainOptions myOptions = options; myOptions.enableMercatorFastPath() = false; TerrainEngineNode::preInitialize( map, myOptions ); }
void TerrainEngineNode::preInitialize( const Map* map, const TerrainOptions& options ) { _map = map; // fire up a terrain utility interface _terrainInterface = new Terrain( this, map->getProfile(), map->isGeocentric(), options ); // set up the CSN values _map->getProfile()->getSRS()->populateCoordinateSystemNode( this ); // OSG's CSN likes a NULL ellipsoid to represent projected mode. if ( !_map->isGeocentric() ) this->setEllipsoidModel( NULL ); // install the proper layer composition technique: _texCompositor = new TextureCompositor( options ); // prime the compositor with pre-existing image layers: MapFrame mapf(map, Map::IMAGE_LAYERS); for( unsigned i=0; i<mapf.imageLayers().size(); ++i ) { _texCompositor->applyMapModelChange( MapModelChange( MapModelChange::ADD_IMAGE_LAYER, mapf.getRevision(), mapf.getImageLayerAt(i), i ) ); } // then register the callback so we can process further map model changes _map->addMapCallback( new TerrainEngineNodeCallbackProxy( this ) ); // enable backface culling osg::StateSet* set = getOrCreateStateSet(); //set->setAttributeAndModes( new osg::CullFace( osg::CullFace::BACK ), osg::StateAttribute::ON ); set->setMode( GL_CULL_FACE, 1 ); // elevation uniform // NOTE: wrong...this should be per-CullVisitor...consider putting in the Culling::CullUserData _cameraElevationUniform = new osg::Uniform( osg::Uniform::FLOAT, "osgearth_CameraElevation" ); _cameraElevationUniform->set( 0.0f ); set->addUniform( _cameraElevationUniform.get() ); set->getOrCreateUniform( "osgearth_ImageLayerAttenuation", osg::Uniform::FLOAT )->set( *options.attentuationDistance() ); if ( options.enableMercatorFastPath().isSet() ) { OE_INFO << LC << "Mercator fast path " << (options.enableMercatorFastPath()==true? "enabled" : "DISABLED") << std::endl; } _initStage = INIT_PREINIT_COMPLETE; }
void TerrainEngineNode::validateTerrainOptions( TerrainOptions& options ) { // make sure all the requested properties are compatible, and fall back as necessary. //const Capabilities& caps = Registry::instance()->getCapabilities(); // warn against mixing multipass technique with preemptive/sequential mode: if (options.compositingTechnique() == TerrainOptions::COMPOSITING_MULTIPASS && options.loadingPolicy()->mode() != LoadingPolicy::MODE_STANDARD ) { OE_WARN << LC << "MULTIPASS compositor is incompatible with preemptive/sequential loading policy; " << "falling back on STANDARD mode" << std::endl; options.loadingPolicy()->mode() = LoadingPolicy::MODE_STANDARD; } }
void TerrainEngineNode::preInitialize( const Map* map, const TerrainOptions& options ) { _map = map; // fire up a terrain utility interface _terrainInterface = new Terrain( this, map->getProfile(), map->isGeocentric(), options ); // set up the CSN values _map->getProfile()->getSRS()->populateCoordinateSystemNode( this ); // OSG's CSN likes a NULL ellipsoid to represent projected mode. if ( !_map->isGeocentric() ) this->setEllipsoidModel( NULL ); // install an object to manage texture image unit usage: _texCompositor = new TextureCompositor(); std::set<int> offLimits = osgEarth::Registry::instance()->getOffLimitsTextureImageUnits(); for(std::set<int>::const_iterator i = offLimits.begin(); i != offLimits.end(); ++i) _texCompositor->setTextureImageUnitOffLimits( *i ); // then register the callback so we can process further map model changes _map->addMapCallback( new TerrainEngineNodeCallbackProxy( this ) ); // apply render bin if necessary if ( options.binNumber().isSet() ) { osg::StateSet* set = getOrCreateStateSet(); set->setRenderBinDetails( options.binNumber().get(), "RenderBin" ); } if ( options.enableMercatorFastPath().isSet() ) { OE_INFO << LC << "Mercator fast path " << (options.enableMercatorFastPath()==true? "enabled" : "DISABLED") << std::endl; } // a default factory - this is the object that creates the data model for // each terrain tile. _tileModelFactory = new TerrainTileModelFactory(options); _initStage = INIT_PREINIT_COMPLETE; }
void MapNodeOptions::setTerrainOptions( const TerrainOptions& options ) { _terrainOptionsConf = options.getConfig(); if ( _terrainOptions ) { delete _terrainOptions; _terrainOptions = 0L; } }
void OSGTerrainEngineNode::preInitialize( const Map* map, const TerrainOptions& options ) { TerrainEngineNode::preInitialize( map, options ); _isStreaming = options.loadingPolicy()->mode() == LoadingPolicy::MODE_PREEMPTIVE || options.loadingPolicy()->mode() == LoadingPolicy::MODE_SEQUENTIAL; // in standard mode, try to set the number of OSG DatabasePager threads to use. if ( options.loadingPolicy().isSet() && !_isStreaming ) { int numThreads = -1; if ( options.loadingPolicy()->numLoadingThreads().isSet() ) { numThreads = osg::maximum( 1, *options.loadingPolicy()->numLoadingThreads() ); } else if ( options.loadingPolicy()->numLoadingThreadsPerCore().isSet() ) { float numThreadsPerCore = *options.loadingPolicy()->numLoadingThreadsPerCore(); numThreads = osg::maximum( (int)1, (int)osg::round( numThreadsPerCore * (float)OpenThreads::GetNumberOfProcessors() ) ); } if ( numThreads > 0 ) { OE_INFO << LC << "Requesting " << numThreads << " database pager threads in STANDARD mode" << std::endl; osg::DisplaySettings::instance()->setNumOfDatabaseThreadsHint( numThreads ); //osg::DisplaySettings::instance()->setNumOfHttpDatabaseThreadsHint( numThreads ); } } }
void TerrainEngineNode::preInitialize( const Map* map, const TerrainOptions& options ) { _map = map; // set up the CSN values _map->getProfile()->getSRS()->populateCoordinateSystemNode( this ); // OSG's CSN likes a NULL ellipsoid to represent projected mode. if ( !_map->isGeocentric() ) this->setEllipsoidModel( NULL ); // install the proper layer composition technique: _texCompositor = new TextureCompositor( options ); // prime the compositor with pre-existing image layers: MapFrame mapf(map, Map::IMAGE_LAYERS); for( unsigned i=0; i<mapf.imageLayers().size(); ++i ) { _texCompositor->applyMapModelChange( MapModelChange( MapModelChange::ADD_IMAGE_LAYER, mapf.getRevision(), mapf.getImageLayerAt(i), i ) ); } // then register the callback so we can process further map model changes _map->addMapCallback( new TerrainEngineNodeCallbackProxy( this ) ); // enable backface culling osg::StateSet* set = getOrCreateStateSet(); set->setAttributeAndModes( new osg::CullFace( osg::CullFace::BACK ), osg::StateAttribute::ON ); // elevation uniform _cameraElevationUniform = new osg::Uniform( osg::Uniform::FLOAT, "osgearth_CameraElevation" ); _cameraElevationUniform->set( 0.0f ); set->addUniform( _cameraElevationUniform.get() ); set->getOrCreateUniform( "osgearth_ImageLayerAttenuation", osg::Uniform::FLOAT )->set( *options.attentuationDistance() ); _initStage = INIT_PREINIT_COMPLETE; }
TextureCompositor::TextureCompositor(const TerrainOptions& options) : osg::Referenced( true ), _tech( options.compositingTechnique().value() ), _options( options ), _forceTech( false ) { // for debugging: if ( _tech == TerrainOptions::COMPOSITING_AUTO && ::getenv( "OSGEARTH_COMPOSITOR_TECH" ) ) { TerrainOptions::CompositingTechnique oldTech = _tech; std::string t( ::getenv( "OSGEARTH_COMPOSITOR_TECH" ) ); if ( t == "TEXTURE_ARRAY" ) _tech = TerrainOptions::COMPOSITING_TEXTURE_ARRAY; else if ( t == "MULTITEXTURE_GPU" ) _tech = TerrainOptions::COMPOSITING_MULTITEXTURE_GPU; else if ( t == "MULTIPASS" ) _tech = TerrainOptions::COMPOSITING_MULTIPASS; if ( oldTech != _tech ) _forceTech = true; } init(); }
void OSGTerrainEngineNode::preInitialize( const Map* map, const TerrainOptions& options ) { TerrainEngineNode::preInitialize( map, options ); _isStreaming = options.loadingPolicy()->mode() == LoadingPolicy::MODE_PREEMPTIVE || options.loadingPolicy()->mode() == LoadingPolicy::MODE_SEQUENTIAL; // in standard mode, try to set the number of OSG DatabasePager threads to use. if ( options.loadingPolicy().isSet() && !_isStreaming ) { int numThreads = -1; if ( options.loadingPolicy()->numLoadingThreads().isSet() ) { numThreads = osg::maximum( 1, *options.loadingPolicy()->numLoadingThreads() ); } else if ( options.loadingPolicy()->numLoadingThreadsPerCore().isSet() ) { float numThreadsPerCore = *options.loadingPolicy()->numLoadingThreadsPerCore(); numThreads = osg::maximum( (int)1, (int)osg::round( numThreadsPerCore * (float)OpenThreads::GetNumberOfProcessors() ) ); } if ( numThreads > 0 ) { // NOTE: this doesn't work. the pager gets created before we ever get here. numThreads = osg::maximum(numThreads, 2); int numHttpThreads = osg::clampBetween( numThreads/2, 1, numThreads-1 ); //OE_INFO << LC << "Requesting pager threads in STANDARD mode: local=" << numThreads << ", http=" << numHttpThreads << std::endl; osg::DisplaySettings::instance()->setNumOfDatabaseThreadsHint( numThreads ); osg::DisplaySettings::instance()->setNumOfHttpDatabaseThreadsHint( numHttpThreads ); } } }
TextureCompositorTexArray::TextureCompositorTexArray( const TerrainOptions& options ) : _lodTransitionTime( *options.lodTransitionTime() ) { //nop }
void GlobePlugin::setupMap() { QSettings settings; QString cacheDirectory = settings.value( "cache/directory", QgsApplication::qgisSettingsDirPath() + "cache" ).toString(); TMSCacheOptions cacheOptions; cacheOptions.setPath( cacheDirectory.toStdString() ); MapOptions mapOptions; mapOptions.cache() = cacheOptions; osgEarth::Map *map = new osgEarth::Map( mapOptions ); //Default image layer GDALOptions driverOptions; driverOptions.url() = QDir::cleanPath( QgsApplication::pkgDataPath() + "/globe/world.tif" ).toStdString(); ImageLayerOptions layerOptions( "world", driverOptions ); layerOptions.cacheEnabled() = false; map->addImageLayer( new osgEarth::ImageLayer( layerOptions ) ); MapNodeOptions nodeOptions; //nodeOptions.proxySettings() = //nodeOptions.enableLighting() = false; //LoadingPolicy loadingPolicy( LoadingPolicy::MODE_SEQUENTIAL ); TerrainOptions terrainOptions; //terrainOptions.loadingPolicy() = loadingPolicy; terrainOptions.compositingTechnique() = TerrainOptions::COMPOSITING_MULTITEXTURE_FFP; nodeOptions.setTerrainOptions( terrainOptions ); // The MapNode will render the Map object in the scene graph. mMapNode = new osgEarth::MapNode( map, nodeOptions ); //prefill cache if ( !QFile::exists( cacheDirectory + "/worldwind_srtm" ) ) { copyFolder( QgsApplication::pkgDataPath() + "/globe/data/worldwind_srtm", cacheDirectory + "/globe/worldwind_srtm" ); } mRootNode = new osg::Group(); mRootNode->addChild( mMapNode ); // Add layers to the map layersChanged(); // model placement utils mElevationManager = new osgEarth::Util::ElevationManager( mMapNode->getMap() ); mElevationManager->setTechnique( osgEarth::Util::ElevationManager::TECHNIQUE_GEOMETRIC ); mElevationManager->setMaxTilesToCache( 50 ); mObjectPlacer = new osgEarth::Util::ObjectPlacer( mMapNode ); // place 3D model on point layer if ( mSettingsDialog.modelLayer() && !mSettingsDialog.modelPath().isEmpty() ) { osg::Node* model = osgDB::readNodeFile( mSettingsDialog.modelPath().toStdString() ); if ( model ) { QgsVectorLayer* layer = mSettingsDialog.modelLayer(); QgsAttributeList fetchAttributes; layer->select( fetchAttributes ); //TODO: select only visible features QgsFeature feature; while ( layer->nextFeature( feature ) ) { QgsPoint point = feature.geometry()->asPoint(); placeNode( model, point.y(), point.x() ); } } } }
void RexTerrainEngineNode::postInitialize( const Map* map, const TerrainOptions& options ) { // Force the mercator fast path off, since REX does not support it yet. TerrainOptions myOptions = options; myOptions.enableMercatorFastPath() = false; TerrainEngineNode::postInitialize( map, myOptions ); // Initialize the map frames. We need one for the update thread and one for the // cull thread. Someday we can detect whether these are actually the same thread // (depends on the viewer's threading mode). _update_mapf = new MapFrame( map, Map::ENTIRE_MODEL ); // A callback for overriding bounding boxes for tiles _modifyBBoxCallback = new ModifyBoundingBoxCallback(*_update_mapf); // merge in the custom options: _terrainOptions.merge( myOptions ); // morphing imagery LODs requires we bind parent textures to their own unit. if ( _terrainOptions.morphImagery() == true ) { _requireParentTextures = true; } // Terrain morphing doesn't work in projected maps: if (map->getSRS()->isProjected()) { _terrainOptions.morphTerrain() = false; } // if the envvar for tile expiration is set, overide the options setting const char* val = ::getenv("OSGEARTH_EXPIRATION_THRESHOLD"); if ( val ) { _terrainOptions.expirationThreshold() = as<unsigned>(val, _terrainOptions.expirationThreshold().get()); OE_INFO << LC << "Expiration threshold set by env var = " << _terrainOptions.expirationThreshold().get() << "\n"; } // if the envvar for hires prioritization is set, override the options setting const char* hiresFirst = ::getenv("OSGEARTH_HIGH_RES_FIRST"); if ( hiresFirst ) { _terrainOptions.highResolutionFirst() = true; } // check for normal map generation (required for lighting). if ( _terrainOptions.normalMaps() == true ) { this->_requireNormalTextures = true; } // A shared registry for tile nodes in the scene graph. Enable revision tracking // if requested in the options. Revision tracking lets the registry notify all // live tiles of the current map revision so they can inrementally update // themselves if necessary. _liveTiles = new TileNodeRegistry("live"); _liveTiles->setMapRevision( _update_mapf->getRevision() ); // A resource releaser that will call releaseGLObjects() on expired objects. _releaser = new ResourceReleaser(); this->addChild(_releaser.get()); // A shared geometry pool. _geometryPool = new GeometryPool( _terrainOptions ); _geometryPool->setReleaser( _releaser.get()); this->addChild( _geometryPool.get() ); // Make a tile loader PagerLoader* loader = new PagerLoader( this ); loader->setNumLODs(_terrainOptions.maxLOD().getOrUse(DEFAULT_MAX_LOD)); loader->setMergesPerFrame( _terrainOptions.mergesPerFrame().get() ); for (std::vector<RexTerrainEngineOptions::LODOptions>::const_iterator i = _terrainOptions.lods().begin(); i != _terrainOptions.lods().end(); ++i) { if (i->_lod.isSet()) { loader->setLODPriorityScale(i->_lod.get(), i->_priorityScale.getOrUse(1.0f)); loader->setLODPriorityOffset(i->_lod.get(), i->_priorityOffset.getOrUse(0.0f)); } } _loader = loader; this->addChild( _loader.get() ); // Make a tile unloader _unloader = new UnloaderGroup( _liveTiles.get() ); _unloader->setThreshold( _terrainOptions.expirationThreshold().get() ); _unloader->setReleaser(_releaser.get()); this->addChild( _unloader.get() ); // handle an already-established map profile: MapInfo mapInfo( map ); if ( _update_mapf->getProfile() ) { // NOTE: this will initialize the map with the startup layers onMapInfoEstablished( mapInfo ); } // install a layer callback for processing further map actions: map->addMapCallback( new RexTerrainEngineNodeMapCallbackProxy(this) ); // Prime with existing layers: _batchUpdateInProgress = true; ElevationLayerVector elevationLayers; map->getLayers( elevationLayers ); for( ElevationLayerVector::const_iterator i = elevationLayers.begin(); i != elevationLayers.end(); ++i ) addElevationLayer( i->get() ); ImageLayerVector imageLayers; map->getLayers( imageLayers ); for( ImageLayerVector::iterator i = imageLayers.begin(); i != imageLayers.end(); ++i ) addTileLayer( i->get() ); _batchUpdateInProgress = false; // set up the initial shaders updateState(); // register this instance to the osgDB plugin can find it. registerEngine( this ); // now that we have a map, set up to recompute the bounds dirtyBound(); }
void GlobePlugin::setupMap() { QSettings settings; /* QString cacheDirectory = settings.value( "cache/directory", QgsApplication::qgisSettingsDirPath() + "cache" ).toString(); TMSCacheOptions cacheOptions; cacheOptions.setPath( cacheDirectory.toStdString() ); */ MapOptions mapOptions; //mapOptions.cache() = cacheOptions; osgEarth::Map *map = new osgEarth::Map( mapOptions ); //Default image layer /* GDALOptions driverOptions; driverOptions.url() = QDir::cleanPath( QgsApplication::pkgDataPath() + "/globe/world.tif" ).toStdString(); ImageLayerOptions layerOptions( "world", driverOptions ); map->addImageLayer( new osgEarth::ImageLayer( layerOptions ) ); */ TMSOptions imagery; imagery.url() = "http://readymap.org/readymap/tiles/1.0.0/7/"; map->addImageLayer( new ImageLayer( "Imagery", imagery ) ); MapNodeOptions nodeOptions; //nodeOptions.proxySettings() = //nodeOptions.enableLighting() = false; //LoadingPolicy loadingPolicy( LoadingPolicy::MODE_SEQUENTIAL ); TerrainOptions terrainOptions; //terrainOptions.loadingPolicy() = loadingPolicy; terrainOptions.compositingTechnique() = TerrainOptions::COMPOSITING_MULTITEXTURE_FFP; //terrainOptions.lodFallOff() = 6.0; nodeOptions.setTerrainOptions( terrainOptions ); // The MapNode will render the Map object in the scene graph. mMapNode = new osgEarth::MapNode( map, nodeOptions ); mRootNode = new osg::Group(); mRootNode->addChild( mMapNode ); // Add layers to the map imageLayersChanged(); elevationLayersChanged(); // model placement utils #ifdef HAVE_OSGEARTH_ELEVATION_QUERY #else mElevationManager = new osgEarth::Util::ElevationManager( mMapNode->getMap() ); mElevationManager->setTechnique( osgEarth::Util::ElevationManager::TECHNIQUE_GEOMETRIC ); mElevationManager->setMaxTilesToCache( 50 ); mObjectPlacer = new osgEarth::Util::ObjectPlacer( mMapNode ); // place 3D model on point layer if ( mSettingsDialog->modelLayer() && !mSettingsDialog->modelPath().isEmpty() ) { osg::Node* model = osgDB::readNodeFile( mSettingsDialog->modelPath().toStdString() ); if ( model ) { QgsVectorLayer* layer = mSettingsDialog->modelLayer(); QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ) ); //TODO: select only visible features QgsFeature feature; while ( fit.nextFeature( feature ) ) { QgsPoint point = feature.geometry()->asPoint(); placeNode( model, point.y(), point.x() ); } } } #endif }