Esempio n. 1
0
MPGeometry::MPGeometry(const TileKey& key, const MapFrame& frame, int imageUnit) : 
osg::Geometry    ( ),
_frame           ( frame ),
_imageUnit       ( imageUnit )
{
    _supportsGLSL = Registry::capabilities().supportsGLSL();

    unsigned tw, th;
    key.getProfile()->getNumTiles(key.getLOD(), tw, th);
    _tileKeyValue.set( key.getTileX(), th-key.getTileY()-1.0f, key.getLOD(), -1.0f );

    _imageUnitParent = _imageUnit + 1; // temp

    // establish uniform name IDs.
    _tileKeyUniformNameID      = osg::Uniform::getNameID( "oe_tile_key" );
    _birthTimeUniformNameID    = osg::Uniform::getNameID( "oe_tile_birthtime" );
    _uidUniformNameID          = osg::Uniform::getNameID( "oe_layer_uid" );
    _orderUniformNameID        = osg::Uniform::getNameID( "oe_layer_order" );
    _opacityUniformNameID      = osg::Uniform::getNameID( "oe_layer_opacity" );
    _texMatParentUniformNameID = osg::Uniform::getNameID( "oe_layer_parent_matrix" );

    // we will set these later (in TileModelCompiler)
    this->setUseVertexBufferObjects(false);
    this->setUseDisplayList(false);
}
Esempio n. 2
0
bool
TileMap::intersectsKey(const TileKey& tilekey)
{
    osg::Vec3d keyMin, keyMax;

    //double keyMinX, keyMinY, keyMaxX, keyMaxY;

    //Check to see if the key overlaps the bounding box using lat/lon.  This is necessary to check even in 
    //Mercator situations in case the BoundingBox is described using lat/lon coordinates such as those produced by GDAL2Tiles
    //This should be considered a bug on the TMS production side, but we can work around it for now...
    tilekey.getExtent().getBounds(keyMin.x(), keyMin.y(), keyMax.x(), keyMax.y());
    //tilekey.getExtent().getBounds(keyMinX, keyMinY, keyMaxX, keyMaxY);

    bool inter = intersects(_minX, _minY, _maxX, _maxY, keyMin.x(), keyMin.y(), keyMax.x(), keyMax.y() ); //keyMinX, keyMinY, keyMaxX, keyMaxY);

    if (!inter && tilekey.getProfile()->getSRS()->isSphericalMercator())
    {
        tilekey.getProfile()->getSRS()->transform(keyMin, tilekey.getProfile()->getSRS()->getGeographicSRS(), keyMin );
        tilekey.getProfile()->getSRS()->transform(keyMax, tilekey.getProfile()->getSRS()->getGeographicSRS(), keyMax );
        inter = intersects(_minX, _minY, _maxX, _maxY, keyMin.x(), keyMin.y(), keyMax.x(), keyMax.y() );
        //tilekey.getProfile()->getSRS()->transform2D(keyMinX, keyMinY, tilekey.getProfile()->getSRS()->getGeographicSRS(), keyMinX, keyMinY);
        //tilekey.getProfile()->getSRS()->transform2D(keyMaxX, keyMaxY, tilekey.getProfile()->getSRS()->getGeographicSRS(), keyMaxX, keyMaxY);
        //inter = intersects(_minX, _minY, _maxX, _maxY, keyMinX, keyMinY, keyMaxX, keyMaxY);
    }

    return inter;
}
Esempio n. 3
0
bool
OSGTileFactory::createValidGeoImage(ImageLayer* layer,
                                    const TileKey& key,
                                    GeoImage& out_image,
                                    TileKey&  out_actualTileKey,
                                    ProgressCallback* progress)
{
    //TODO:  Redo this to just grab images from the parent TerrainTiles
    //Try to create the image with the given key
    out_actualTileKey = key;

    while (out_actualTileKey.valid())
    {
        if ( layer->isKeyValid(out_actualTileKey) )
        {
            out_image = layer->createImage( out_actualTileKey, progress );
            if ( out_image.valid() )
            {
                return true;
            }
        }
        out_actualTileKey = out_actualTileKey.createParentKey();
    }
    return false;
}
GeoImage
ElevationProxyImageLayer::createImage(const TileKey& key, ProgressCallback* progress)
{
    if ( _mapf.needsSync() )
    {
        Threading::ScopedMutexLock lock(_mapfMutex);
        if ( _mapf.needsSync() )
        {
            _mapf.sync();
        }
    }

    osg::ref_ptr<osg::HeightField> hf = HeightFieldUtils::createReferenceHeightField(key.getExtent(), 257,257, true );

    if ( _mapf.populateHeightField(hf, key, true, 0L) )
    {
        // encode the heightfield as a 16-bit normalized LUNIMANCE image
        osg::Image* image = new osg::Image();
        image->allocateImage(hf->getNumColumns(), hf->getNumRows(), 1, GL_LUMINANCE, GL_UNSIGNED_SHORT);
        image->setInternalTextureFormat( GL_LUMINANCE16 );
        const osg::FloatArray* floats = hf->getFloatArray();
        for( unsigned int i = 0; i < floats->size(); ++i  )
        {
            int col = i % hf->getNumColumns();
            int row = i / hf->getNumColumns();
            *(unsigned short*)image->data( col, row ) = (unsigned short)(32768 + (short)floats->at(i));
        }

        return GeoImage( image, key.getExtent() );
    }
    else
    {
        return GeoImage::INVALID;
    }
}
Esempio n. 5
0
void
LocalGeometryNode::onTileAdded(const TileKey&          key, 
                               osg::Node*              graph, 
                               TerrainCallbackContext& context)
{
    bool needsClamp;

    // This was faster, but less precise and resulted in a lot of unnecessary clamp attempts:
    //if ( _boundingPT.contains(patch->getBound()) )

    // Does the tile key's polytope intersect the world bounds or this object?
    // (taking getParent(0) gives the world-tranformed bounds vs. local bounds)
    if (key.valid())
    {
        osg::Polytope tope;
        key.getExtent().createPolytope(tope);
        needsClamp = tope.contains(this->getParent(0)->getBound());
    }
    else
    {
        // with no key, must clamp no matter what
        needsClamp = true;
    }

    if (needsClamp)
    {    
        clamp(graph, context.getTerrain());
    }
}
Esempio n. 6
0
bool
TerrainLayer::isKeyValid(const TileKey& key) const
{
	if (!key.valid()) return false;
    const TerrainLayerOptions& opt = getTerrainLayerOptions();
	
    //Check to see if explicit levels of detail are set
    if ( opt.minLevel().isSet() && (int)key.getLevelOfDetail() < opt.minLevel().value() ) return false;
	if ( opt.maxLevel().isSet() && (int)key.getLevelOfDetail() > opt.maxLevel().value() ) return false;
    
    //Check to see if levels of detail based on resolution are set
    if (opt.minLevelResolution().isSet())
    {        
        unsigned int minLevel = getProfile()->getLevelOfDetailForHorizResolution( opt.minLevelResolution().value(), getTileSize());
        OE_DEBUG << "Computed min level of " << minLevel << std::endl;
        if (key.getLevelOfDetail() < minLevel) return false;
    }

    if (opt.maxLevelResolution().isSet())
    {        
        unsigned int maxLevel = getProfile()->getLevelOfDetailForHorizResolution( opt.maxLevelResolution().value(), getTileSize());
        OE_DEBUG << "Computed max level of " << maxLevel << std::endl;
        if (key.getLevelOfDetail() > maxLevel) return false;
    }

	return true;
}
Esempio n. 7
0
// This will be called by AnnotationNode when a new terrain tile comes in.
void
FeatureNode::onTileAdded(const TileKey&          key,
                         osg::Node*              graph,
                         TerrainCallbackContext& context)
{
    if (!_clampDirty)
    {
        bool needsClamp;

        if (key.valid())
        {
            osg::Polytope tope;
            key.getExtent().createPolytope(tope);
            needsClamp = tope.contains(this->getBound());
        }
        else
        {
            // without a valid tilekey we don't know the extent of the change,
            // so clamping is required.
            needsClamp = true;
        }

        if (needsClamp)
        {
            _clampDirty = true;
            ADJUST_UPDATE_TRAV_COUNT(this, +1);
            //clamp(graph, context.getTerrain());
        }
    }
}
Esempio n. 8
0
void SelectionShape::Render(ScreenBase const & screen, int zoomLevel, ref_ptr<dp::GpuProgramManager> mng,
                            dp::UniformValuesStorage const & commonUniforms)
{
  ShowHideAnimation::EState state = m_animation.GetState();
  if (state == ShowHideAnimation::STATE_VISIBLE ||
      state == ShowHideAnimation::STATE_SHOW_DIRECTION)
  {
    dp::UniformValuesStorage uniforms = commonUniforms;
    TileKey const key = GetTileKeyByPoint(m_position, ClipTileZoomByMaxDataZoom(zoomLevel));
    math::Matrix<float, 4, 4> mv = key.GetTileBasedModelView(screen);
    uniforms.SetMatrix4x4Value("modelView", mv.m_data);

    m2::PointD const pos = MapShape::ConvertToLocal(m_position, key.GetGlobalRect().Center(), kShapeCoordScalar);
    uniforms.SetFloatValue("u_position", pos.x, pos.y, -m_positionZ);

    float accuracy = m_mapping.GetValue(m_animation.GetT());
    if (screen.isPerspective())
    {
      m2::PointD const pt1 = screen.GtoP(m_position);
      m2::PointD const pt2(pt1.x + 1, pt1.y);
      float const scale = screen.PtoP3d(pt2).x - screen.PtoP3d(pt1).x;
      accuracy /= scale;
    }
    uniforms.SetFloatValue("u_accuracy", accuracy);
    uniforms.SetFloatValue("u_opacity", 1.0f);
    m_renderNode->Render(mng, uniforms);
  }
}
bool
ElevationPool::getTile(const TileKey& key, const ElevationLayerVector& layers, osg::ref_ptr<ElevationPool::Tile>& output)
{   
    OE_START_TIMER(get);

    const double timeout = 30.0;
    osg::ref_ptr<Tile> tile;
    while( tryTile(key, layers, tile) && !tile.valid() && OE_GET_TIMER(get) < timeout)
    {
        // condition: another thread is working on fetching the tile from the map,
        // so wait and try again later. Do this until we succeed or time out.
        OpenThreads::Thread::YieldCurrentThread();
    }

    if ( !tile.valid() && OE_GET_TIMER(get) >= timeout )
    {
        // this means we timed out trying to fetch the map tile.
        OE_TEST << LC << "Timeout fetching tile " << key.str() << std::endl;
    }

    if ( tile.valid() )
    {
        if ( tile->_hf.valid() )
        {
            // got a valid tile, so push it to the query set.
            output = tile.get();
        }
        else
        {
            OE_WARN << LC << "Got a tile with an invalid HF (" << key.str() << ")\n";
        }
    }

    return tile.valid();
}
Esempio n. 10
0
void TMSBackFiller::processKey( const TileKey& key )
{
    if (_verbose) OE_NOTICE << "Processing key " << key.str() << std::endl;

    //Get all of the child tiles for this key, load them and mosaic them into a new tile
    TileKey ulKey = key.createChildKey( 0 );
    TileKey urKey = key.createChildKey( 1 );
    TileKey llKey = key.createChildKey( 2 );
    TileKey lrKey = key.createChildKey( 3 );

    osg::ref_ptr< osg::Image > ul = readTile( ulKey );
    osg::ref_ptr< osg::Image > ur = readTile( urKey );
    osg::ref_ptr< osg::Image > ll = readTile( llKey );
    osg::ref_ptr< osg::Image > lr = readTile( lrKey );

    if (ul.valid() && ur.valid() && ll.valid() && lr.valid())
    {            
        //Merge them together
        ImageMosaic mosaic;
        mosaic.getImages().push_back( TileImage( ul.get(), ulKey ) );
        mosaic.getImages().push_back( TileImage( ur.get(), urKey ) );
        mosaic.getImages().push_back( TileImage( ll.get(), llKey ) );
        mosaic.getImages().push_back( TileImage( lr.get(), lrKey ) );            

        osg::ref_ptr< osg::Image> merged = mosaic.createImage();
        if (merged.valid())
        {
            //Resize the image so it's the same size as one of the input files
            osg::ref_ptr<osg::Image> resized;
            ImageUtils::resizeImage( merged.get(), ul->s(), ul->t(), resized );
            std::string outputFilename = getFilename( key );                
            writeTile( key, resized.get() );
        }
    }                
}    
Esempio n. 11
0
osg::Node*
MPTerrainEngineNode::createUpsampledNode(const TileKey&    key,
                                         ProgressCallback* progress)
{
    // if the engine has been disconnected from the scene graph, bail out and don't
    // create any more tiles
    if ( getNumParents() == 0 )
        return 0L;

    osg::Node* result = 0L;

    // locate the parent tile in the live tile registry.
    TileKey parentKey = key.createParentKey();
    osg::ref_ptr<TileNode> parent;
    if ( _liveTiles->get( parentKey, parent ) )
    {
        osg::ref_ptr<TileModel> upsampledModel = parent->getTileModel()->createQuadrant( key.getQuadrant() );
        if ( upsampledModel.valid() )
        {
            result = getKeyNodeFactory()->getCompiler()->compile( upsampledModel, *_update_mapf );
        }
    }
    else
    {
        OE_WARN << LC << "createUpsampledNode failed b/c parent key " << parentKey.str() << " not found in reg." << std::endl;
    }

    return result;
}
Esempio n. 12
0
GeoImage
ImageLayer::createImageFromTileSource(const TileKey&    key,
                                      ProgressCallback* progress)
{
    TileSource* source = getTileSource();
    if ( !source )
        return GeoImage::INVALID;

    // If the profiles are different, use a compositing method to assemble the tile.
    if ( !key.getProfile()->isHorizEquivalentTo( getProfile() ) )
    {
        return assembleImage( key, progress );
    }

    // Good to go, ask the tile source for an image:
    osg::ref_ptr<TileSource::ImageOperation> op = getOrCreatePreCacheOp();

    // Fail is the image is blacklisted.
    if ( source->getBlacklist()->contains(key) )
    {
        OE_DEBUG << LC << "createImageFromTileSource: blacklisted(" << key.str() << ")" << std::endl;
        return GeoImage::INVALID;
    }

    if (!mayHaveData(key))
    {
        OE_DEBUG << LC << "createImageFromTileSource: mayHaveData(" << key.str() << ") == false" << std::endl;
        return GeoImage::INVALID;
    }

    //if ( !source->hasData( key ) )
    //{
    //    OE_DEBUG << LC << "createImageFromTileSource: hasData(" << key.str() << ") == false" << std::endl;
    //    return GeoImage::INVALID;
    //}

    // create an image from the tile source.
    osg::ref_ptr<osg::Image> result = source->createImage( key, op.get(), progress );   

    // Process images with full alpha to properly support MP blending.    
    if (result.valid() && 
        options().featherPixels() == true)
    {
        ImageUtils::featherAlphaRegions( result.get() );
    }    
    
    // If image creation failed (but was not intentionally canceled and 
    // didn't time out or end for any other recoverable reason), then
    // blacklist this tile for future requests.
    if (result == 0L)
    {
        if ( progress == 0L ||
             ( !progress->isCanceled() && !progress->needsRetry() ) )
        {
            source->getBlacklist()->add( key );
        }
    }

    return GeoImage(result.get(), key.getExtent());
}
Esempio n. 13
0
void
TileModelFactory::buildElevation(const TileKey&    key,
                                 const MapFrame&   frame,
                                 bool              accumulate,
                                 TileModel*        model,
                                 ProgressCallback* progress)
{     
    const MapInfo& mapInfo = frame.getMapInfo();

    const osgEarth::ElevationInterpolation& interp =
        frame.getMapOptions().elevationInterpolation().get();

    // Request a heightfield from the map, falling back on lower resolution tiles
    // if necessary (fallback=true)
    osg::ref_ptr<osg::HeightField> hf;

    bool isFallback = false;

    if (_hfCache->getOrCreateHeightField(frame, key, accumulate, hf, isFallback, SAMPLE_FIRST_VALID, interp, progress))
    {
        model->_elevationData = TileModel::ElevationData(
            hf,
            GeoLocator::createForKey( key, mapInfo ),
            isFallback );

        // Edge normalization: requires adjacency information
        if ( _terrainOptions.normalizeEdges() == true )
        {
            for( int x=-1; x<=1; x++ )
            {
                for( int y=-1; y<=1; y++ )
                {
                    if ( x != 0 || y != 0 )
                    {
                        TileKey nk = key.createNeighborKey(x, y);
                        if ( nk.valid() )
                        {
                            osg::ref_ptr<osg::HeightField> hf;
                            if (_hfCache->getOrCreateHeightField(frame, nk, accumulate, hf, isFallback, SAMPLE_FIRST_VALID, interp, progress) )
                            {
                                model->_elevationData.setNeighbor( x, y, hf.get() );
                            }
                        }
                    }
                }
            }

            // parent too.
            if ( key.getLOD() > 0 )
            {
                osg::ref_ptr<osg::HeightField> hf;
                if ( _hfCache->getOrCreateHeightField(frame, key.createParentKey(), accumulate, hf, isFallback, SAMPLE_FIRST_VALID, interp, progress) )
                {
                    model->_elevationData.setParent( hf.get() );
                }
            }
        }
    }
}
Esempio n. 14
0
void
CacheSeed::processKey(const MapFrame& mapf, const TileKey& key ) const
{
    unsigned int x, y, lod;
    key.getTileXY(x, y);
    lod = key.getLevelOfDetail();

    bool gotData = true;

    if ( _minLevel <= lod && _maxLevel >= lod )
    {
        gotData = cacheTile( mapf, key );
        if (gotData)
        {
        incrementCompleted( 1 );
        }

        if ( _progress.valid() && _progress->isCanceled() )
            return; // Task has been cancelled by user

        if ( _progress.valid() && gotData && _progress->reportProgress(_completed, _total, std::string("Cached tile: ") + key.str()) )
            return; // Canceled
    }

    if ( gotData && lod <= _maxLevel )
    {
        TileKey k0 = key.createChildKey(0);
        TileKey k1 = key.createChildKey(1);
        TileKey k2 = key.createChildKey(2);
        TileKey k3 = key.createChildKey(3); 

        bool intersectsKey = false;
        if (_extents.empty()) intersectsKey = true;
        else
        {
            for (unsigned int i = 0; i < _extents.size(); ++i)
            {
                if (_extents[i].intersects( k0.getExtent() ) ||
                    _extents[i].intersects( k1.getExtent() ) ||
                    _extents[i].intersects( k2.getExtent() ) ||
                    _extents[i].intersects( k3.getExtent() ))
                {
                    intersectsKey = true;
                }

            }
        }

        //Check to see if the bounds intersects ANY of the tile's children.  If it does, then process all of the children
        //for this level
        if (intersectsKey)
        {
            processKey(mapf, k0);
            processKey(mapf, k1);
            processKey(mapf, k2);
            processKey(mapf, k3);
        }
    }
}
Esempio n. 15
0
osg::Node*
MPTerrainEngineNode::createTile( const TileKey& key )
{
    osg::ref_ptr<TileModel> model = new TileModel( _update_mapf->getRevision(), _update_mapf->getMapInfo() );
    model->_tileKey = key;
    model->_tileLocator = GeoLocator::createForKey(key, _update_mapf->getMapInfo());

    // Build the heightfield

    const MapInfo& mapInfo = _update_mapf->getMapInfo();

    const osgEarth::ElevationInterpolation& interp = _update_mapf->getMapOptions().elevationInterpolation().get();

    // Request a heightfield from the map, falling back on lower resolution tiles
    osg::ref_ptr<osg::HeightField> hf;    

    TileKey sampleKey = key;
    bool populated = false;
    if (_update_mapf->elevationLayers().size() > 0)
    {
        while (!populated)
        {
            populated = _update_mapf->populateHeightField(hf, sampleKey, true, SAMPLE_FIRST_VALID);
            if (!populated)
            {
                // Fallback on the parent
                sampleKey = sampleKey.createParentKey();
                if (!sampleKey.valid())
                {
                    return 0;
                }
            }
        }       
    }

    if (!populated)
    {
        // We have no heightfield so just create a reference heightfield.
        hf = HeightFieldUtils::createReferenceHeightField( key.getExtent(), 15, 15 );
        sampleKey = key;
    }

    model->_elevationData = TileModel::ElevationData(
            hf,
            GeoLocator::createForKey( sampleKey, mapInfo ),
            false );        

    bool optimizeTriangleOrientation = getMap()->getMapOptions().elevationInterpolation() != INTERP_TRIANGULATE;

    osg::ref_ptr<TileModelCompiler> compiler = new TileModelCompiler(
            _update_mapf->terrainMaskLayers(),
            _update_mapf->modelLayers(),
            _primaryUnit,
            optimizeTriangleOrientation,
            _terrainOptions );

    return compiler->compile(model.get(), *_update_mapf, 0L);
}
Esempio n. 16
0
void
OSGTileFactory::addPlaceholderHeightfieldLayer(StreamingTile* tile,
                                               StreamingTile* ancestorTile,
                                               GeoLocator*    defaultLocator,
                                               const TileKey& key,
                                               const TileKey& ancestorKey)
{
    osgTerrain::HeightFieldLayer* newHFLayer = 0L;

    if ( ancestorTile && ancestorKey.valid() )
    {
        osg::ref_ptr<osgTerrain::HeightFieldLayer> ancestorLayer;
        {
            Threading::ScopedReadLock sharedLock( ancestorTile->getTileLayersMutex() );
            ancestorLayer = dynamic_cast<osgTerrain::HeightFieldLayer*>(ancestorTile->getElevationLayer());
        }

        if ( ancestorLayer.valid() )
        {
            osg::ref_ptr<osg::HeightField> ancestorHF = ancestorLayer->getHeightField();
            if ( ancestorHF.valid() )
            {
                osg::HeightField* newHF = HeightFieldUtils::createSubSample(
                    ancestorHF.get(),
                    ancestorKey.getExtent(),
                    key.getExtent());

                newHFLayer = new osgTerrain::HeightFieldLayer( newHF );
                newHFLayer->setLocator( defaultLocator );

                // lock to set the elevation layerdata:
                {
                    Threading::ScopedWriteLock exclusiveLock( tile->getTileLayersMutex() );
                    tile->setElevationLayer( newHFLayer );                
                    tile->setElevationLOD( ancestorTile->getElevationLOD() );
                }
            }
        }
    }

    // lock the tile to write the elevation data.
    {
        Threading::ScopedWriteLock exclusiveLock( tile->getTileLayersMutex() );

        if ( !newHFLayer )
        {
            newHFLayer = new osgTerrain::HeightFieldLayer();
            newHFLayer->setHeightField( createEmptyHeightField( key, 8, 8 ) );
            newHFLayer->setLocator( defaultLocator );
            tile->setElevationLOD( -1 );
        }

        if ( newHFLayer )
        {
            tile->setElevationLayer( newHFLayer );
        }
    }
}
Esempio n. 17
0
    void update( float x, float y, osgViewer::View* view )
    {
        bool yes = false;

        // look under the mouse:
        osg::Vec3d world;
        osgUtil::LineSegmentIntersector::Intersections hits;
        if ( view->computeIntersections(x, y, hits) )
        {
            world = hits.begin()->getWorldIntersectPoint();

            // convert to map coords:
            GeoPoint mapPoint;
            mapPoint.fromWorld( s_mapNode->getMapSRS(), world );

            // Depending on the level of detail key you request, you will get a mesh that should line up exactly with the highest resolution mesh that the terrain engine will draw.
            // At level 15 that is a 257x257 heightfield.  If you select a higher lod, the mesh will be less dense.
            TileKey key = s_mapNode->getMap()->getProfile()->createTileKey(mapPoint.x(), mapPoint.y(), 15);
            OE_NOTICE << "Creating tile " << key.str() << std::endl;
            osg::ref_ptr<osg::Node> node = s_mapNode->getTerrainEngine()->createTile(key);
            if (node.valid())
            {
                // Extract the triangles from the node that was created and do our own rendering.  Simulates what you would do when passing in the triangles to a physics engine.
                OE_NOTICE << "Created tile for " << key.str() << std::endl;
                CollectTrianglesVisitor v;
                node->accept(v);
                node = v.buildNode();

                if (_node.valid())
                {
                    s_root->removeChild( _node.get() );
                }

                osg::Group* group = new osg::Group;

                // Show the actual mesh.
                group->addChild( node.get() );

                _node = group;

                // Clamp the marker to the intersection of the triangles created by osgEarth.  This should line up with the mesh that is actually rendered.
                double z = 0.0;
                s_mapNode->getTerrain()->getHeight( node, s_mapNode->getMapSRS(), mapPoint.x(), mapPoint.y(), &z);

                GeoTransform* xform = new GeoTransform();
                xform->setPosition( osgEarth::GeoPoint(s_mapNode->getMapSRS(),mapPoint.x(),  mapPoint.y(), z, ALTMODE_ABSOLUTE) );
                xform->addChild( marker.get() );
                group->addChild( xform );

                s_root->addChild( _node.get() );
            }
            else
            {
                OE_NOTICE << "Failed to create tile for " << key.str() << std::endl;
            }
        }
    }
Esempio n. 18
0
void Dragger::reclamp( const TileKey& key, osg::Node* tile, const Terrain* terrain )
{    
    GeoPoint p;
    _position.transform( key.getExtent().getSRS(), p );
    // first verify that the control position intersects the tile:
    if ( key.getExtent().contains( p.x(), p.y() ) )
    {
        updateTransform( tile );
    }
}
Esempio n. 19
0
void
GeometryPool::createKeyForTileKey(const TileKey&             tileKey,
                                  unsigned                   size,
                                  const MapInfo&             mapInfo,
                                  GeometryPool::GeometryKey& out) const
{
    out.lod  = tileKey.getLOD();
    out.yMin = mapInfo.isGeocentric()? tileKey.getExtent().yMin() : 0.0;
    out.size = size;
}
Esempio n. 20
0
osg::Node*
RexTerrainEngineNode::createTile( const TileKey& key )
{
     // Compute the sample size to use for the key's level of detail that will line up exactly with the tile size of the highest level of subdivision of the rex engine.
    unsigned int sampleSize = computeSampleSize( key.getLevelOfDetail() );    
    OE_INFO << LC << "Computed a sample size of " << sampleSize << " for lod " << key.getLevelOfDetail() << std::endl;

    TileKey sampleKey = key;

    // ALWAYS use 257x257 b/c that is what rex always uses.
    osg::ref_ptr< osg::HeightField > out_hf = HeightFieldUtils::createReferenceHeightField(
            key.getExtent(), 257, 257, 0u, true );

    sampleKey = key;

    bool populated = false;
    while (!populated)
    {
        populated = _update_mapf->populateHeightField(
            out_hf,
            sampleKey,
            true, // convertToHAE
            0 );

        if (!populated)
        {
            // Fallback on the parent
            sampleKey = sampleKey.createParentKey();
            if (!sampleKey.valid())
            {
                return 0;
            }
        }
    }

    // cannot happen (says coverity; see loop above), so commenting this out -gw
#if 0
    if (!populated)
    {
        // We have no heightfield so just create a reference heightfield.
        out_hf = HeightFieldUtils::createReferenceHeightField( key.getExtent(), 257, 257, 0u);
        sampleKey = key;
    }
#endif

    GeoHeightField geoHF( out_hf.get(), sampleKey.getExtent() );    
    if (sampleKey != key)
    {   
        geoHF = geoHF.createSubSample( key.getExtent(), sampleSize, sampleSize, osgEarth::INTERP_BILINEAR);         
    }

    // We should now have a heightfield that matches up exactly with the requested key at the appropriate resolution.
    // Turn it into triangles.
    return renderHeightField( geoHF );      
}
Esempio n. 21
0
bool
TerrainLayer::isCached(const TileKey& key) const
{
    CacheBin* bin = const_cast<TerrainLayer*>(this)->getCacheBin( key.getProfile() );
    if ( !bin )
        return false;

    TimeStamp minTime = this->getCachePolicy().getMinAcceptTime();

    return bin->getRecordStatus( key.str(), minTime ) == CacheBin::STATUS_OK;
}
Esempio n. 22
0
MPGeometry::MPGeometry(const TileKey& key, const MapFrame& frame, int imageUnit) : 
osg::Geometry    ( ),
_frame           ( frame ),
_imageUnit       ( imageUnit ),
_uidUniformNameID(0),
_birthTimeUniformNameID(0u),
_orderUniformNameID(0u),
_opacityUniformNameID(0u),
_texMatParentUniformNameID(0u),
_tileKeyUniformNameID(0u),
_minRangeUniformNameID(0u),
_maxRangeUniformNameID(0u),
_imageUnitParent(0),
_elevUnit(0),
_supportsGLSL(false)
{
    _supportsGLSL = Registry::capabilities().supportsGLSL();
    
    // Encode the tile key in a uniform. Note! The X and Y components are presented
    // modulo 2^16 form so they don't overrun single-precision space.
    unsigned tw, th;
    key.getProfile()->getNumTiles(key.getLOD(), tw, th);

    const double m = pow(2.0, 16.0);

    double x = (double)key.getTileX();
    double y = (double)(th - key.getTileY()-1);

    _tileKeyValue.set(
        (float)fmod(x, m),
        (float)fmod(y, m),
        (float)key.getLOD(),
        -1.0f);

    _imageUnitParent = _imageUnit + 1; // temp

    _elevUnit = _imageUnit + 2; // temp

    // establish uniform name IDs.
    _tileKeyUniformNameID      = osg::Uniform::getNameID( "oe_tile_key" );
    _birthTimeUniformNameID    = osg::Uniform::getNameID( "oe_tile_birthtime" );
    _uidUniformNameID          = osg::Uniform::getNameID( "oe_layer_uid" );
    _orderUniformNameID        = osg::Uniform::getNameID( "oe_layer_order" );
    _opacityUniformNameID      = osg::Uniform::getNameID( "oe_layer_opacity" );
    _texMatParentUniformNameID = osg::Uniform::getNameID( "oe_layer_parent_texmat" );
    _minRangeUniformNameID     = osg::Uniform::getNameID( "oe_layer_minRange" );
    _maxRangeUniformNameID     = osg::Uniform::getNameID( "oe_layer_maxRange" );

    // we will set these later (in TileModelCompiler)
    this->setUseDisplayList(false);
    this->setUseVertexBufferObjects(true);
}
Esempio n. 23
0
bool
ElevationLayer::isKeyValid(const TileKey& key) const
{
    if (!key.valid())
        return false;

    if ( _runtimeOptions.minLevel().isSet() && key.getLOD() < _runtimeOptions.minLevel().value() ) 
    {
        return false;
    }

    return TerrainLayer::isKeyValid(key);
}
unsigned int
CacheEstimator::getNumTiles() const
{
    unsigned int total = 0;

    for (unsigned int level = _minLevel; level <= _maxLevel; level++)
    {
        if (_extents.empty())
        {
            unsigned int wide, high;
            _profile->getNumTiles( level, wide, high );
            total += (wide * high);
        }
        else
        {
            for (std::vector< GeoExtent >::const_iterator itr = _extents.begin(); itr != _extents.end(); ++itr)
            {
                const GeoExtent& extent = *itr;

                TileKey ll = _profile->createTileKey(extent.xMin(), extent.yMin(), level);
                TileKey ur = _profile->createTileKey(extent.xMax(), extent.yMax(), level);

                if (!ll.valid() || !ur.valid()) continue;
                
                int tilesWide = ur.getTileX() - ll.getTileX() + 1;
                int tilesHigh = ll.getTileY() - ur.getTileY() + 1;
                int tilesAtLevel = tilesWide * tilesHigh;                
                total += tilesAtLevel;
            }
        }
    }
    return total;
}
Esempio n. 25
0
GeoImage
ImageLayer::createImageFromTileSource(const TileKey&    key,
                                      ProgressCallback* progress)
{
    TileSource* source = getTileSource();
    if ( !source )
        return GeoImage::INVALID;

    // If the profiles are different, use a compositing method to assemble the tile.
    if ( !key.getProfile()->isHorizEquivalentTo( getProfile() ) )
    {
        return assembleImageFromTileSource( key, progress );
    }

    // Good to go, ask the tile source for an image:
    osg::ref_ptr<TileSource::ImageOperation> op = _preCacheOp;

    // Fail is the image is blacklisted.
    if ( source->getBlacklist()->contains(key) )
    {
        OE_DEBUG << LC << "createImageFromTileSource: blacklisted(" << key.str() << ")" << std::endl;
        return GeoImage::INVALID;
    }
    
    if ( !source->hasData( key ) )
    {
        OE_DEBUG << LC << "createImageFromTileSource: hasData(" << key.str() << ") == false" << std::endl;
        return GeoImage::INVALID;
    }

    // create an image from the tile source.
    osg::ref_ptr<osg::Image> result = source->createImage( key, op.get(), progress );

    // Process images with full alpha to properly support MP blending.    
    if ( result.valid() && *_runtimeOptions.featherPixels())
    {
        ImageUtils::featherAlphaRegions( result.get() );
    }    
    
    // If image creation failed (but was not intentionally canceled),
    // blacklist this tile for future requests.
    if ( result == 0L && (!progress || !progress->isCanceled()) )
    {
        source->getBlacklist()->add( key );
    }

    return GeoImage(result.get(), key.getExtent());
}
Esempio n. 26
0
bool
TerrainLayer::isCached(const TileKey& key) const
{
    // first consult the policy:
    if ( getCachePolicy() == CachePolicy::NO_CACHE )
        return false;
    else if ( getCachePolicy() == CachePolicy::CACHE_ONLY )
        return true;

    // next check for a bin:
    CacheBin* bin = const_cast<TerrainLayer*>(this)->getCacheBin( key.getProfile() );
    if ( !bin )
        return false;
    
    return bin->getRecordStatus( key.str() ) == CacheBin::STATUS_OK;
}
Esempio n. 27
0
    std::string createURL( const TileKey& key ) const
    {
        unsigned int x, y;
        key.getTileXY(x, y);

        unsigned int lod = key.getLevelOfDetail()+1;

        //http://s0.tileservice.worldwindcentral.com/getTile?interface=map&version=1&dataset=bmng.topo.bathy.200401&level=0&x=0&y=0
        return Stringify() 
            << _options.url()->full() << "interface=map&version=1"
            << "&dataset=" << _options.dataset().value()
            << "&level=" << lod
            << "&x=" << x
            << "&y=" << y
            << "&." << _formatToUse; //Add this to trick osg into using the correct loader.
    }
Esempio n. 28
0
TileNode::TileNode( const TileKey& key, GeoLocator* keyLocator ) :
_key              ( key ),
_locator          ( keyLocator ),
_publicStateSet   ( 0L )
{
    this->setName( key.str() );
}
void
TextureCompositorMultiTexture::applyLayerUpdate(osg::StateSet*       stateSet,
                                                UID                  layerUID,
                                                const GeoImage&      preparedImage,
                                                const TileKey&       tileKey,
                                                const TextureLayout& layout,
                                                osg::StateSet*       parentStateSet) const
{
    osg::Texture2D* tex = s_getTexture( stateSet, layerUID, layout, parentStateSet, _minFilter, _magFilter);
    if ( tex )
    {
        osg::Image* image = preparedImage.getImage();
        image->dirty(); // required for ensure the texture recognizes the image as new data
        tex->setImage( image );

        // set up proper mipmapping filters:
        if (_enableMipmapping &&
            _enableMipmappingOnUpdatedTextures &&
            ImageUtils::isPowerOfTwo( image ) &&
            !(!image->isMipmap() && ImageUtils::isCompressed(image)) )
        {
            if ( tex->getFilter(osg::Texture::MIN_FILTER) != _minFilter )
                tex->setFilter( osg::Texture::MIN_FILTER, _minFilter );
        }
        else if ( tex->getFilter(osg::Texture::MIN_FILTER) != osg::Texture::LINEAR )
        {
            tex->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR );
        }

        bool lodBlending = layout.getSlot(layerUID, 1) >= 0;

        if (_enableMipmapping &&
            _enableMipmappingOnUpdatedTextures &&
            lodBlending )
        {
            int slot = layout.getSlot(layerUID, 0);

            // update the timestamp on the image layer to support blending.
            float now = (float)osg::Timer::instance()->delta_s( osg::Timer::instance()->getStartTick(), osg::Timer::instance()->tick() );
            ArrayUniform stampUniform( "osgearth_SlotStamp", osg::Uniform::FLOAT, stateSet, layout.getMaxUsedSlot() + 1 );
            stampUniform.setElement( slot, now );

            // set the texture matrix to properly position the blend (parent) texture
            osg::Matrix mat;
            if ( parentStateSet != 0L )
            {
                unsigned tileX, tileY;
                tileKey.getTileXY(tileX, tileY);

                mat(0,0) = 0.5f;
                mat(1,1) = 0.5f;
                mat(3,0) = (float)(tileX % 2) * 0.5f;
                mat(3,1) = (float)(1 - tileY % 2) * 0.5f;
            }

            ArrayUniform texMatUniform( "osgearth_TexBlendMatrix", osg::Uniform::FLOAT_MAT4, stateSet, layout.getMaxUsedSlot() + 1 );
            texMatUniform.setElement( slot, mat );
        }
    }
}
void
TerrainTileModelFactory::addNormalMap(TerrainTileModel* model,
                                      const Map* map,
                                      const TileKey&    key,
                                      ProgressCallback* progress)
{
    OE_START_TIMER(fetch_normalmap);

    if (model->elevationModel().valid())
    {
        const osgEarth::ElevationInterpolation& interp =
            map->getMapOptions().elevationInterpolation().get();

        // Can only generate the normal map if the center heightfield was built:
        osg::ref_ptr<osg::Image> image = HeightFieldUtils::convertToNormalMap(
            model->heightFields(),
            key.getProfile()->getSRS() );

        if (image.valid())
        {
            TerrainTileImageLayerModel* layerModel = new TerrainTileImageLayerModel();
            layerModel->setName( "oe_normal_map" );

            // Made an image, so store this as a texture with no matrix.
            osg::Texture* texture = createNormalTexture( image.get() );
            layerModel->setTexture( texture );
            model->normalModel() = layerModel;
        }
    }

    if (progress)
        progress->stats()["fetch_normalmap_time"] += OE_STOP_TIMER(fetch_normalmap);
}