FeatureModelGraph::FeatureModelGraph(Session* session, const FeatureModelSourceOptions& options, FeatureNodeFactory* factory ) : _session ( session ), _options ( options ), _factory ( factory ), _dirty ( false ), _pendingUpdate( false ) { _uid = osgEarthFeatureModelPseudoLoader::registerGraph( this ); _postMergeOperations = new RefNodeOperationVector(); // install the stylesheet in the session if it doesn't already have one. if ( !session->styles() ) session->setStyles( _options.styles().get() ); if ( !session->getFeatureSource() ) { OE_WARN << LC << "ILLEGAL: Session must have a feature source" << std::endl; return; } // Calculate the usable extent (in both feature and map coordinates) and bounds. const Profile* mapProfile = session->getMapInfo().getProfile(); const FeatureProfile* featureProfile = session->getFeatureSource()->getFeatureProfile(); // Bail out if the feature profile is bad if ( !featureProfile || !featureProfile->getExtent().isValid() ) { // warn or allow? return; } // the part of the feature extent that will fit on the map (in map coords): _usableMapExtent = mapProfile->clampAndTransformExtent( featureProfile->getExtent(), &_featureExtentClamped ); // same, back into feature coords: _usableFeatureExtent = _usableMapExtent.transform( featureProfile->getSRS() ); // world-space bounds of the feature layer _fullWorldBound = getBoundInWorldCoords( _usableMapExtent, 0L ); // whether to request tiles from the source (if available). if the source is tiled, but the // user manually specified schema levels, don't use the tiles. _useTiledSource = featureProfile->getTiled(); if ( options.layout().isSet() && options.layout()->getNumLevels() > 0 ) { // the user provided a custom levels setup, so don't use the tiled source (which // provides its own levels setup) _useTiledSource = false; // for each custom level, calculate the best LOD match and store it in the level // layout data. We will use this information later when constructing the SG in // the pager. for( unsigned i = 0; i < options.layout()->getNumLevels(); ++i ) { const FeatureLevel* level = options.layout()->getLevel( i ); unsigned lod = options.layout()->chooseLOD( *level, _fullWorldBound.radius() ); _lodmap.resize( lod+1, 0L ); _lodmap[lod] = level; OE_INFO << LC << session->getFeatureSource()->getName() << ": F.Level max=" << level->maxRange() << ", min=" << level->minRange() << ", LOD=" << lod << std::endl; } } // install base shader mains. if ( Registry::instance()->getCapabilities().supportsGLSL() ) { installShaderMains(); } // Set up the state set. // backface culling is ON by default. By the way, this is most definitely // necessary when shading with shadows. osg::StateSet* stateSet = getOrCreateStateSet(); stateSet->setMode( GL_CULL_FACE, 1 ); stateSet->setMode( GL_BLEND, 1 ); if ( _options.enableLighting().isSet() ) stateSet->setMode( GL_LIGHTING, *_options.enableLighting() ? 1 : 0 ); ADJUST_EVENT_TRAV_COUNT( this, 1 ); redraw(); }
FeatureModelGraph::FeatureModelGraph(Session* session, const FeatureModelSourceOptions& options, FeatureNodeFactory* factory, RefNodeOperationVector* postMergeOperations) : _session ( session ), _options ( options ), _factory ( factory ), _postMergeOperations( postMergeOperations ), _dirty ( false ), _pendingUpdate ( false ), _overlayInstalled ( 0L ), _overlayPlaceholder ( 0L ), _clampable ( 0L ), _drapeable ( 0L ), _overlayChange ( OVERLAY_NO_CHANGE ) { _uid = osgEarthFeatureModelPseudoLoader::registerGraph( this ); // an FLC that queues feature data on the high-latency thread. _defaultFileLocationCallback = new HighLatencyFileLocationCallback(); // install the stylesheet in the session if it doesn't already have one. if ( !session->styles() ) session->setStyles( _options.styles().get() ); if ( !session->getFeatureSource() ) { OE_WARN << LC << "ILLEGAL: Session must have a feature source" << std::endl; return; } // set up a shared resource cache for the session. The ResourceCache will make sure // that resources (skin textures, instance models, etc.) only get loaded once. if ( !session->getResourceCache() && _options.sessionWideResourceCache() == true ) { session->setResourceCache( new ResourceCache(session->getDBOptions()) ); } // Calculate the usable extent (in both feature and map coordinates) and bounds. const Profile* mapProfile = session->getMapInfo().getProfile(); const FeatureProfile* featureProfile = session->getFeatureSource()->getFeatureProfile(); // Bail out if the feature profile is bad if ( !featureProfile || !featureProfile->getExtent().isValid() ) { // warn or allow? return; } // the part of the feature extent that will fit on the map (in map coords): _usableMapExtent = mapProfile->clampAndTransformExtent( featureProfile->getExtent(), &_featureExtentClamped ); // same, back into feature coords: _usableFeatureExtent = _usableMapExtent.transform( featureProfile->getSRS() ); // world-space bounds of the feature layer _fullWorldBound = getBoundInWorldCoords( _usableMapExtent, 0L ); // whether to request tiles from the source (if available). if the source is tiled, but the // user manually specified schema levels, don't use the tiles. _useTiledSource = featureProfile->getTiled(); if ( options.layout().isSet() && options.layout()->getNumLevels() > 0 ) { // the user provided a custom levels setup, so don't use the tiled source (which // provides its own levels setup) _useTiledSource = false; // for each custom level, calculate the best LOD match and store it in the level // layout data. We will use this information later when constructing the SG in // the pager. for( unsigned i = 0; i < options.layout()->getNumLevels(); ++i ) { const FeatureLevel* level = options.layout()->getLevel( i ); unsigned lod = options.layout()->chooseLOD( *level, _fullWorldBound.radius() ); _lodmap.resize( lod+1, 0L ); _lodmap[lod] = level; OE_INFO << LC << session->getFeatureSource()->getName() << ": F.Level max=" << level->maxRange() << ", min=" << level->minRange() << ", LOD=" << lod << std::endl; } } // Apply some default state. The options properties let you override the // defaults, but we'll set some reasonable state if they are not set. osg::StateSet* stateSet = getOrCreateStateSet(); // Set up backface culling. If the option is unset, enable it by default // since shadowing requires it and it's a decent general-purpose setting if ( _options.backfaceCulling().isSet() ) stateSet->setMode( GL_CULL_FACE, *_options.backfaceCulling() ? 1 : 0 ); else stateSet->setMode( GL_CULL_FACE, 1 ); // Set up alpha blending. Enable it by default if not specified. if ( _options.alphaBlending().isSet() ) stateSet->setMode( GL_BLEND, *_options.alphaBlending() ? 1 : 0 ); else stateSet->setMode( GL_BLEND, 1 ); // Set up lighting, only if the option is set if ( _options.enableLighting().isSet() ) stateSet->setMode( GL_LIGHTING, *_options.enableLighting() ? 1 : 0 ); // If the user requests fade-in, install a post-merge operation that will set the // proper fade time for paged nodes. if ( _options.fading().isSet() ) { _postMergeOperations->mutex().writeLock(); _postMergeOperations->push_back( new SetupFading() ); _postMergeOperations->mutex().writeUnlock(); OE_INFO << LC << "Added fading post-merge operation" << std::endl; } ADJUST_EVENT_TRAV_COUNT( this, 1 ); redraw(); }