347 lines
12 KiB
C++
347 lines
12 KiB
C++
/* -*-c++-*- */
|
|
/* osgEarth - Geospatial SDK for OpenSceneGraph
|
|
* Copyright 2020 Pelican Mapping
|
|
* http://osgearth.org
|
|
*
|
|
* osgEarth is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
*/
|
|
#pragma once
|
|
|
|
#include <osgEarth/Common>
|
|
#include <osgEarth/Config>
|
|
#include <osgEarth/ColorFilter>
|
|
#include <osgEarth/TileLayer>
|
|
#include <osgEarth/URI>
|
|
#include <osgEarth/Threading>
|
|
#include <osg/Texture2D>
|
|
|
|
namespace osgEarth
|
|
{
|
|
class Profile;
|
|
}
|
|
|
|
namespace osgEarth
|
|
{
|
|
/**
|
|
* Texture paired with a scale/bias matrix defining a sub-window.
|
|
*/
|
|
class OSGEARTH_EXPORT TextureWindow
|
|
{
|
|
public:
|
|
//! Empty/invalid texture window
|
|
TextureWindow() : _texture(0L) { }
|
|
//! Construct a texture window
|
|
TextureWindow(osg::Texture* tex, const osg::Matrix& scalebias) : _texture(tex), _matrix(scalebias) { }
|
|
//! Texture
|
|
osg::Texture* getTexture() const { return _texture.get(); }
|
|
//! Scale bias matrix defining subwindow
|
|
const osg::Matrixf& getMatrix() const { return _matrix; }
|
|
//! Is it valid?
|
|
bool valid() const { return _texture.valid(); }
|
|
|
|
protected:
|
|
osg::ref_ptr<osg::Texture> _texture;
|
|
osg::Matrixf _matrix;
|
|
};
|
|
|
|
/**
|
|
* A map terrain layer containing bitmap image data.
|
|
*/
|
|
class OSGEARTH_EXPORT ImageLayer : public TileLayer
|
|
{
|
|
public: // Serialization
|
|
class OSGEARTH_EXPORT Options : public TileLayer::Options {
|
|
public:
|
|
META_LayerOptions(osgEarth, Options, TileLayer::Options);
|
|
OE_OPTION(URI, noDataImageFilename);
|
|
OE_OPTION(osg::Vec4ub, transparentColor, osg::Vec4ub(0, 0, 0, 0));
|
|
OE_OPTION(ColorFilterChain, colorFilters);
|
|
OE_OPTION(osg::Texture::FilterMode, minFilter, osg::Texture::LINEAR_MIPMAP_LINEAR);
|
|
OE_OPTION(osg::Texture::FilterMode, magFilter, osg::Texture::LINEAR);
|
|
OE_OPTION(std::string, textureCompression);
|
|
OE_OPTION(double, edgeBufferRatio, 0.0);
|
|
OE_OPTION(unsigned, reprojectedTileSize, 256u);
|
|
OE_OPTION(Distance, altitude);
|
|
OE_OPTION(bool, coverage, false);
|
|
OE_OPTION(bool, acceptDraping, false);
|
|
OE_OPTION(bool, async, false);
|
|
OE_OPTION(bool, shared, false);
|
|
OE_OPTION(std::string, shareTexUniformName);
|
|
OE_OPTION(std::string, shareTexMatUniformName);
|
|
virtual Config getConfig() const;
|
|
private:
|
|
void fromConfig(const Config& conf);
|
|
};
|
|
|
|
public:
|
|
META_Layer_Abstract(osgEarth, ImageLayer, Options, TileLayer);
|
|
|
|
//! Layer callbacks
|
|
class OSGEARTH_EXPORT Callback : public osg::Referenced
|
|
{
|
|
public:
|
|
//! Called when a new data is created. This callback fires
|
|
//! before the data is cached, and does NOT fire if the data
|
|
//! was read from a cache.
|
|
//! NOTE: This may be invoked from a worker thread. Use caution.
|
|
virtual void onCreate(const TileKey&, GeoImage&) { }
|
|
};
|
|
|
|
public:
|
|
|
|
//! Convenience function to create an ImageLayer from a ConfigOptions.
|
|
static ImageLayer* create(const ConfigOptions& conf);
|
|
|
|
//! @deprecated
|
|
//! Adds a color filter to the filter chain.
|
|
void addColorFilter(ColorFilter* filter);
|
|
|
|
//! @deprecated
|
|
//! Removes a color filter from the filter chain
|
|
void removeColorFilter(ColorFilter* filter);
|
|
|
|
//! @deprecated
|
|
//! Accesses the color filter chain
|
|
const ColorFilterChain& getColorFilters() const;
|
|
|
|
//! Sets the altitude
|
|
void setAltitude(const Distance& value);
|
|
const Distance& getAltitude() const;
|
|
|
|
//! Sets whether this layer should allow draped overlays
|
|
//! to render on it. This is most applicable to layers with a
|
|
//! non-zero altitude (setAltitude). Default is true.
|
|
void setAcceptDraping(bool value);
|
|
bool getAcceptDraping() const;
|
|
|
|
//! Marks this layer for asynchronous loading.
|
|
//! Usually all layers participating in a tile must load before the
|
|
//! tile is displayed. This flag defers the current layer so it can
|
|
//! load asynchronously and display when it is available. This can
|
|
//! help keep a slow-loading layer from blocking the rest of the tile
|
|
//! from displaying. The trade-off is possible visual artifacts
|
|
//! (flashing, no mipmaps/compression) when the new data appears.
|
|
void setAsyncLoading(bool value);
|
|
bool getAsyncLoading() const;
|
|
|
|
//! Whether this layer is marked for render sharing.
|
|
//! Only set this before opening the layer or adding it to a map.
|
|
void setShared(bool value);
|
|
bool getShared() const;
|
|
bool isShared() const { return getShared(); }
|
|
|
|
//! Whether this layer represents coverage data that should not be subject
|
|
//! to color-space filtering, interpolation, or compression.
|
|
//! Only set this before opening the layer or adding it to a map.
|
|
void setCoverage(bool value);
|
|
bool getCoverage() const;
|
|
bool isCoverage() const { return getCoverage(); }
|
|
|
|
//! When isShared() == true, this will return the name of the uniform holding the
|
|
//! image's texture.
|
|
void setSharedTextureUniformName(const std::string& value);
|
|
const std::string& getSharedTextureUniformName() const;
|
|
|
|
//! When isShared() == true, this will return the name of the uniform holding the
|
|
//! image's texture matrix.
|
|
void setSharedTextureMatrixUniformName(const std::string& value);
|
|
const std::string& getSharedTextureMatrixUniformName() const;
|
|
|
|
//! When isShared() == true, the engine will call this function to bind the
|
|
//! shared layer to a texture image unit.
|
|
optional<int>& sharedImageUnit() { return _shareImageUnit; }
|
|
const optional<int>& sharedImageUnit() const { return _shareImageUnit; }
|
|
|
|
osg::Image* getEmptyImage() const { return _emptyImage.get(); }
|
|
|
|
public: // methods
|
|
|
|
//! Creates an image for the given tile key.
|
|
//! @param key TileKey for which to create an image
|
|
//! @param progress Optional progress/cancelation callback
|
|
GeoImage createImage(const TileKey& key);
|
|
|
|
//! Creates an image for the given tile key.
|
|
//! @param key TileKey for which to create an image
|
|
//! @param progress Optional progress/cancelation callback
|
|
GeoImage createImage(const TileKey& key, ProgressCallback* progress);
|
|
|
|
//! Stores an image in this layer (if writing is enabled).
|
|
//! Returns a status value indicating whether the store succeeded.
|
|
Status writeImage(const TileKey& key, const osg::Image* image, ProgressCallback* progress = 0L);
|
|
|
|
//! Returns the compression method prefered by this layer
|
|
//! that you can pass to ImageUtils::compressImage.
|
|
const std::string getCompressionMethod() const;
|
|
|
|
//! Install a user callback
|
|
void addCallback(Callback* callback);
|
|
|
|
//! Remove a user callback
|
|
void removeCallback(Callback* callback);
|
|
|
|
//! Add a post-processing layer
|
|
void addPostLayer(Layer* layer);
|
|
|
|
|
|
public: // Texture support
|
|
|
|
//! Whether to use createTexture to create data for this layer
|
|
//! instead of createImage and a TileSource driver
|
|
bool useCreateTexture() const { return _useCreateTexture; }
|
|
|
|
//! Override this method to create the texture when useCreateTexture is true
|
|
virtual TextureWindow createTexture(const TileKey& key, ProgressCallback* progress) const
|
|
{
|
|
return TextureWindow();
|
|
}
|
|
|
|
//! Subclass overrides this to generate image data for the key.
|
|
//! The key will always be in the same profile as the layer.
|
|
virtual GeoImage createImageImplementation(const TileKey&, ProgressCallback* progress) const
|
|
{
|
|
return GeoImage::INVALID;
|
|
}
|
|
|
|
protected:
|
|
|
|
//! Subclass can override this to write data for a tile key.
|
|
virtual Status writeImageImplementation(const TileKey&, const osg::Image*, ProgressCallback*) const;
|
|
|
|
//! Modify the bbox if an altitude is set (for culling)
|
|
virtual void modifyTileBoundingBox(const TileKey& key, osg::BoundingBox& box) const;
|
|
|
|
//! Post processing image creation entry points
|
|
GeoImage createImage(
|
|
const GeoImage& canvas,
|
|
const TileKey& key,
|
|
ProgressCallback* progress);
|
|
|
|
//! Override to write an image over top of an existing image
|
|
virtual GeoImage createImageImplementation(
|
|
const GeoImage& canvas,
|
|
const TileKey& key,
|
|
ProgressCallback* progress) const {
|
|
return canvas;
|
|
}
|
|
|
|
//! Override to do something to an image before returning
|
|
//! it from createImage (including a GeoImage read from the cache)
|
|
virtual void postCreateImageImplementation(
|
|
GeoImage& createdImage,
|
|
const TileKey& key,
|
|
ProgressCallback* progress) const { }
|
|
|
|
protected: // Layer
|
|
|
|
virtual void init() override;
|
|
|
|
//! Open the layer for reading.
|
|
virtual Status openImplementation() override;
|
|
|
|
/** dtor */
|
|
virtual ~ImageLayer() { }
|
|
|
|
//! Configure the layer to create textures via createTexture instead of
|
|
//! using a createImage driver
|
|
void setUseCreateTexture();
|
|
|
|
//! Apply a post-processing layers to the image
|
|
virtual GeoImage applyPostLayer(
|
|
const GeoImage& image,
|
|
const TileKey& key,
|
|
Layer* postLayer,
|
|
ProgressCallback* progress) const;
|
|
|
|
osg::ref_ptr<osg::Image> _emptyImage;
|
|
|
|
private:
|
|
|
|
// Creates an image that's in the same profile as the provided key.
|
|
GeoImage createImageInKeyProfile(
|
|
const TileKey& key,
|
|
ProgressCallback* progress);
|
|
|
|
// Fetches multiple images from the TileSource; mosaics/reprojects/crops as necessary, and
|
|
// returns a single tile. This is called by createImageFromTileSource() if the key profile
|
|
// doesn't match the layer profile.
|
|
GeoImage assembleImage(
|
|
const TileKey& key,
|
|
ProgressCallback* progress);
|
|
|
|
// Creates an image that enhances the previous LOD's image
|
|
// using a fractal algorithm.
|
|
GeoImage createFractalUpsampledImage(
|
|
const TileKey& key,
|
|
ProgressCallback* p);
|
|
|
|
optional<int> _shareImageUnit;
|
|
bool _useCreateTexture;
|
|
|
|
void invoke_onCreate(const TileKey&, GeoImage&);
|
|
|
|
typedef std::vector< osg::ref_ptr<Callback> > Callbacks;
|
|
Threading::Mutexed<Callbacks> _callbacks;
|
|
|
|
Mutexed<std::vector<osg::ref_ptr<Layer>>> _postLayers;
|
|
|
|
Gate<TileKey> _sentry;
|
|
|
|
osg::ref_ptr<osg::Image> _nodataImage;
|
|
};
|
|
|
|
typedef std::vector< osg::ref_ptr<ImageLayer> > ImageLayerVector;
|
|
|
|
/**
|
|
* Texture that loads its data asynchronously
|
|
*/
|
|
class OSGEARTH_EXPORT FutureTexture
|
|
{
|
|
public:
|
|
virtual bool doneLoading() { update(); return _resolved; }
|
|
virtual bool succeeded() { update(); return _resolved && !_failed; }
|
|
virtual bool failed() { update(); return _resolved && _failed; }
|
|
|
|
protected:
|
|
FutureTexture() : _resolved(false), _failed(false) { }
|
|
bool _resolved, _failed;
|
|
virtual void update() = 0;
|
|
};
|
|
|
|
class OSGEARTH_EXPORT FutureTexture2D :
|
|
public osg::Texture2D,
|
|
public FutureTexture
|
|
{
|
|
public:
|
|
FutureTexture2D(
|
|
ImageLayer* layer,
|
|
const TileKey& key);
|
|
|
|
protected:
|
|
virtual ~FutureTexture2D() { }
|
|
|
|
void update() override;
|
|
|
|
private:
|
|
TileKey _key;
|
|
osg::ref_ptr<ImageLayer> _layer;
|
|
mutable Future<GeoImage> _result;
|
|
|
|
void dispatch() const;
|
|
};
|
|
|
|
} // namespace osgEarth
|
|
|
|
OSGEARTH_SPECIALIZE_CONFIG(osgEarth::ImageLayer::Options);
|