Example #1
0
void
createLayerItem( Grid* grid, int gridRow, int layerIndex, int numLayers, TerrainLayer* layer, bool isActive )
{
    // a checkbox to enable/disable the layer:
    CheckBoxControl* enabled = new CheckBoxControl( layer->getVisible() );
    enabled->addEventHandler( new LayerVisibleHandler(layer) );
    grid->setControl( 0, gridRow, enabled );

    // the layer name
    LabelControl* name = new LabelControl( layer->getName() );
    grid->setControl( 1, gridRow, name );

    ImageLayer* imageLayer = dynamic_cast< ImageLayer* > (layer );
    if (imageLayer)
    {
        // an opacity slider
        HSliderControl* opacity = new HSliderControl( 0.0f, 1.0f, imageLayer->getOpacity() );
        opacity->setWidth( 125 );
        opacity->setHeight( 12 );
        opacity->addEventHandler( new LayerOpacityHandler(imageLayer) );
        grid->setControl( 2, gridRow, opacity );
    }

    // move buttons
    if ( layerIndex < numLayers-1 && isActive )
    {
        LabelControl* upButton = new LabelControl( "UP", 14 );
        upButton->setBackColor( .4,.4,.4,1 );
        upButton->setActiveColor( .8,0,0,1 );
        upButton->addEventHandler( new MoveLayerHandler( layer, layerIndex+1 ) );
        grid->setControl( 3, gridRow, upButton );
    }
    if ( layerIndex > 0 && isActive)
    {
        LabelControl* upButton = new LabelControl( "DOWN", 14 );
        upButton->setBackColor( .4,.4,.4,1 );
        upButton->setActiveColor( .8,0,0,1 );
        upButton->addEventHandler( new MoveLayerHandler( layer, layerIndex-1 ) );
        grid->setControl( 4, gridRow, upButton );
    }

    // add/remove button:
    LabelControl* addRemove = new LabelControl( isActive? "REMOVE" : "ADD", 14 );
    addRemove->setHorizAlign( Control::ALIGN_CENTER );
    addRemove->setBackColor( .4,.4,.4,1 );
    addRemove->setActiveColor( .8,0,0,1 );
    if ( isActive )
        addRemove->addEventHandler( new RemoveLayerHandler(layer) );
    else
        addRemove->addEventHandler( new AddLayerHandler(layer) );
    grid->setControl( 5, gridRow, addRemove );
}
Example #2
0
void
TerrainEngineNode::updateImageUniforms()
{
    // don't bother if this is a hurting old card
    if ( !Registry::instance()->getCapabilities().supportsGLSL() )
        return;

    // update the layer uniform arrays:
    osg::StateSet* stateSet = this->getOrCreateStateSet();

    // get a copy of the image layer stack:
    MapFrame mapf( _map.get(), Map::IMAGE_LAYERS );

    _imageLayerController->_layerVisibleUniform.detach();
    _imageLayerController->_layerOpacityUniform.detach();
    _imageLayerController->_layerRangeUniform.detach();
    
    if ( mapf.imageLayers().size() > 0 )
    {
        // the "enabled" uniform is fixed size. this is handy to account for layers that are in flux...i.e., their source
        // layer count has changed, but the shader has not yet caught up. In the future we might use this to disable
        // "ghost" layers that used to exist at a given index, but no longer do.
        
        _imageLayerController->_layerVisibleUniform.attach( "osgearth_ImageLayerVisible", osg::Uniform::BOOL,  stateSet, mapf.imageLayers().size() );
        _imageLayerController->_layerOpacityUniform.attach( "osgearth_ImageLayerOpacity", osg::Uniform::FLOAT, stateSet, mapf.imageLayers().size() );
        _imageLayerController->_layerRangeUniform.attach  ( "osgearth_ImageLayerRange",   osg::Uniform::FLOAT, stateSet, 2 * mapf.imageLayers().size() );

        for( ImageLayerVector::const_iterator i = mapf.imageLayers().begin(); i != mapf.imageLayers().end(); ++i )
        {
            ImageLayer* layer = i->get();
            int index = (int)(i - mapf.imageLayers().begin());

            _imageLayerController->_layerVisibleUniform.setElement( index, layer->getVisible() );
            _imageLayerController->_layerOpacityUniform.setElement( index, layer->getOpacity() );
            _imageLayerController->_layerRangeUniform.setElement( (2*index), layer->getMinVisibleRange() );
            _imageLayerController->_layerRangeUniform.setElement( (2*index)+1, layer->getMaxVisibleRange() );
        }

        // set the remainder of the layers to disabled 
        for( int j=mapf.imageLayers().size(); j<_imageLayerController->_layerVisibleUniform.getNumElements(); ++j)
        {
            _imageLayerController->_layerVisibleUniform.setElement( j, false );
        }
    }

    dirty();
}
osg::Image*
CompositeTileSource::createImage(const TileKey&    key,
                                 ProgressCallback* progress )
{    
    ImageMixVector images;
    images.reserve(_imageLayers.size());

    // Try to get an image from each of the layers for the given key.
    for (ImageLayerVector::const_iterator itr = _imageLayers.begin(); itr != _imageLayers.end(); ++itr)
    {
        ImageLayer* layer = itr->get();
        ImageInfo imageInfo;
        imageInfo.dataInExtents = layer->getTileSource()->hasDataInExtent( key.getExtent() );
        imageInfo.opacity = layer->getOpacity();

        if (imageInfo.dataInExtents)
        {
            GeoImage image = layer->createImage(key, progress);
            if (image.valid())
            {
                imageInfo.image = image.getImage();
            }

            // If the progress got cancelled or it needs a retry then return NULL to prevent this tile from being built and cached with incomplete or partial data.
            if (progress && (progress->isCanceled() || progress->needsRetry()))
            {
                OE_DEBUG << LC << " createImage was cancelled or needs retry for " << key.str() << std::endl;
                return 0L;
            }
        }

        images.push_back(imageInfo);
    }

    // Determine the output texture size to use based on the image that were creatd.
    unsigned numValidImages = 0;
    osg::Vec2s textureSize;
    for (unsigned int i = 0; i < images.size(); i++)
    {
        ImageInfo& info = images[i];
        if (info.image.valid())
        {
            if (numValidImages == 0)
            {
                textureSize.set( info.image->s(), info.image->t());
            }
            numValidImages++;        
        }
    } 

    // Create fallback images if we have some valid data but not for all the layers
    if (numValidImages > 0 && numValidImages < images.size())
    {
        for (unsigned int i = 0; i < images.size(); i++)
        {
            ImageInfo& info = images[i];
            ImageLayer* layer = _imageLayers[i].get();
            if (!info.image.valid() && info.dataInExtents)
            {                      
                TileKey parentKey = key.createParentKey();

                GeoImage image;
                while (!image.valid() && parentKey.valid())
                {
                    image = layer->createImage(parentKey, progress);
                    if (image.valid())
                    {
                        break;
                    }

                    // If the progress got cancelled or it needs a retry then return NULL to prevent this tile from being built and cached with incomplete or partial data.
                    if (progress && (progress->isCanceled() || progress->needsRetry()))
                    {
                        OE_DEBUG << LC << " createImage was cancelled or needs retry for " << key.str() << std::endl;
                        return 0L;
                    }

                    parentKey = parentKey.createParentKey();
                }

                if (image.valid())
                {                                        
                    // TODO:  Bilinear options?
                    bool bilinear = layer->isCoverage() ? false : true;
                    GeoImage cropped = image.crop( key.getExtent(), true, textureSize.x(), textureSize.y(), bilinear);
                    info.image = cropped.getImage();
                }                    
            }
        }
    }

    // Now finally create the output image.
    //Recompute the number of valid images
    numValidImages = 0;
    for (unsigned int i = 0; i < images.size(); i++)
    {
        ImageInfo& info = images[i];
        if (info.image.valid()) numValidImages++;        
    }    

    if ( progress && progress->isCanceled() )
    {
        return 0L;
    }
    else if ( numValidImages == 0 )
    {
        return 0L;
    }
    else if ( numValidImages == 1 )
    {
        //We only have one valid image, so just return it and don't bother with compositing
        for (unsigned int i = 0; i < images.size(); i++)
        {
            ImageInfo& info = images[i];
            if (info.image.valid())
                return info.image.release();
        }
        return 0L;
    }
    else
    {
        osg::Image* result = 0;
        for (unsigned int i = 0; i < images.size(); i++)
        {
            ImageInfo& imageInfo = images[i];
            if (!result)
            {
                if (imageInfo.image.valid())
                {
                    result = new osg::Image( *imageInfo.image.get());
                }
            }
            else
            {
                if (imageInfo.image.valid())
                {
                    ImageUtils::mix( result, imageInfo.image.get(), imageInfo.opacity );
                }
            }            
        }        
        return result;
    }



}