DYT/Tool/OpenSceneGraph-3.6.5/include/osgEarth/Layer
2024-12-25 07:49:36 +08:00

585 lines
22 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/Status>
#include <osgEarth/PluginLoader>
#include <osgEarth/Cache>
#include <osgEarth/SceneGraphCallback>
#include <osgEarth/LayerShader>
#include <osgEarth/Revisioning>
#include <osgEarth/IOTypes>
#include <osgEarth/DateTime>
#include <osg/BoundingBox>
#include <osg/Callback>
#include <vector>
namespace osg {
class StateSet;
}
namespace osgDB {
class Options;
}
//! Macro to use when defining a LayerOptions class
#define META_LayerOptions(LIBRARY, MYCLASS, SUPERCLASS) \
protected: \
virtual void mergeConfig(const osgEarth::Config& conf) { \
SUPERCLASS ::mergeConfig(conf); \
fromConfig(conf); \
} \
using super = SUPERCLASS; \
public: \
OE_COMMENT("Construct empty layer options") \
MYCLASS () : SUPERCLASS() { fromConfig(_conf); } \
\
OE_COMMENT("Construct layer options from serialized data") \
MYCLASS (const osgEarth::ConfigOptions& opt) : SUPERCLASS(opt) { fromConfig(_conf); } \
\
osgEarth::Config& _internal() { return _conf; } \
const osgEarth::Config& _internal() const { return _conf; }
//! Macro to use when defining a Layer class
#define META_Layer(LIBRARY, MYCLASS, OPTIONS, SUPERCLASS, SLUG) \
private: \
OPTIONS * _options; \
OPTIONS _optionsConcrete; \
const OPTIONS * _options0; \
const OPTIONS _optionsConcrete0; \
MYCLASS ( const MYCLASS& rhs, const osg::CopyOp& op ) { } \
using super = SUPERCLASS; \
protected: \
OE_COMMENT("Construct a new layer with default options") \
MYCLASS (OPTIONS* optr, const OPTIONS* optr0) : \
SUPERCLASS (optr? optr: &_optionsConcrete, optr0? optr0 : &_optionsConcrete0), \
_options(optr ? optr : &_optionsConcrete), \
_options0(optr0 ? optr0 : &_optionsConcrete0) { } \
public: \
META_Object(LIBRARY, MYCLASS); \
\
OE_COMMENT("Construct a new layer with default options") \
MYCLASS () : \
SUPERCLASS (&_optionsConcrete, &_optionsConcrete0), \
_options(&_optionsConcrete), \
_options0(&_optionsConcrete0) { MYCLASS::init(); } \
\
OE_COMMENT("Construct a new layer with user-defined options") \
MYCLASS (const OPTIONS& o) : \
SUPERCLASS (&_optionsConcrete, &_optionsConcrete0), \
_options(&_optionsConcrete), _optionsConcrete(o), \
_options0(&_optionsConcrete0), _optionsConcrete0(o) { MYCLASS::init(); } \
\
OE_COMMENT("Mutable options for this layer") \
OPTIONS& options() { return *_options; } \
\
OE_COMMENT("Immutable options for this layer") \
const OPTIONS& options() const { return *_options; } \
\
OE_COMMENT("Immutable original (constructor) options for this layer") \
const OPTIONS& options_original() const { return *_options0; } \
\
OE_COMMENT("Configuration key for this layer (e.g. for earth files)") \
virtual const char* getConfigKey() const { return #SLUG ; }
//! Macro for defining a layer with a default Options structure
#define META_LayerNoOptions(LIBRARY, MYCLASS, SUPERCLASS, SLUG) \
public: \
struct Options : public SUPERCLASS::Options { \
META_LayerOptions(LIBRARY, Options, SUPERCLASS::Options); \
private: \
void fromConfig(const osgEarth::Config&) { } \
}; \
META_Layer(LIBRARY, MYCLASS, Options, SUPERCLASS, SLUG)
//! Macro to use when defining a Layer class
#define META_Layer_Abstract(LIBRARY, MYCLASS, OPTIONS, SUPERCLASS) \
private: \
OPTIONS * _options; \
const OPTIONS * _options0; \
MYCLASS ( const MYCLASS& rhs, const osg::CopyOp& op ) { } \
protected: \
OE_COMMENT("Construct a new layer with default options") \
MYCLASS (OPTIONS* optr, const OPTIONS* optr0) : \
SUPERCLASS (optr, optr0), \
_options(optr), \
_options0(optr0) { } \
MYCLASS () : SUPERCLASS () { } \
using super = SUPERCLASS; \
public: \
OE_COMMENT("Mutable options for this layer") \
OPTIONS& options() { return *_options; } \
\
OE_COMMENT("Immutable options for this layer") \
const OPTIONS& options() const { return *_options; } \
\
OE_COMMENT("Immutable original (constructor) options for this layer") \
const OPTIONS& options_original() const { return *_options0; }
//! Templated inline property implementation macro
#define OE_LAYER_PROPERTY_IMPL(CLASS, TYPE, FUNC, OPTION) \
void CLASS ::set ## FUNC (const TYPE & value) { options(). OPTION () = value; }\
const TYPE & CLASS ::get ## FUNC () const { return options(). OPTION ().get(); }
namespace osgEarth
{
class GeoExtent;
class SequenceControl;
class TerrainEngine;
class TerrainResources;
class TileKey;
//! Base class for layer property callbacks
struct LayerCallback : public osg::Referenced
{
virtual void onOpen(class Layer*) { }
virtual void onClose(class Layer*) { }
typedef void (LayerCallback::*MethodPtr)(class Layer* layer);
};
/**
* Base class for all Map layers.
*
* Subclass Layer to create a new layer type. Use the META_Layer macro
* to establish the standard options framework.
*
* When you create a Layer, init() is called. Do all one-time construction
* activity where.
*
* When you add a Layer to a Map, the follow methods are called in order:
*
* setReadOptions() sets OSG options for IO activity;
* open() to initialize any underlying data sources;
* addedToMap() to signal to the layer that it is now a member of a Map.
*/
class OSGEARTH_EXPORT Layer : public osg::Object
{
public:
META_Object(osgEarth, Layer);
/** Layer options for serialization */
class OSGEARTH_EXPORT Options : public ConfigOptions
{
public:
META_LayerOptions(osgEarth, Options, ConfigOptions);
OE_OPTION(std::string, name);
OE_OPTION(bool, openAutomatically, true);
OE_OPTION(bool, terrainPatch, false);
OE_OPTION(std::string, cacheId);
OE_OPTION(CachePolicy, cachePolicy);
OE_OPTION(std::string, shaderDefine);
OE_OPTION(std::string, attribution);
OE_OPTION(ShaderOptions, shader);
OE_OPTION_VECTOR(ShaderOptions, shaders);
OE_OPTION(ProxySettings, proxySettings);
OE_OPTION(std::string, osgOptionString);
OE_OPTION(unsigned, l2CacheSize, 0u);
virtual Config getConfig() const;
private:
void fromConfig(const Config& conf);
};
public:
//! Hints that a layer can set to influence the operation of
//! the map engine
class Hints
{
public:
OE_OPTION(CachePolicy, cachePolicy);
OE_OPTION(unsigned, L2CacheSize);
OE_OPTION(bool, dynamic);
};
public:
//! Constructs a map layer
Layer();
//! This layer's unique ID.
//! This value is generated automatically at runtime and is not
//! guaranteed to be the same from one run to the next.
UID getUID() const { return _uid; }
//! osgDB read options for this Layer.
//! If you set this, do so prior to calling open().
virtual void setReadOptions(const osgDB::Options* options);
//! osgDB read options for this Layer.
const osgDB::Options* getReadOptions() const;
//! Open a layer.
virtual Status open() final;
//! Open a layer. Shortcut for calling setReadOptions() followed by open().
virtual Status open(const osgDB::Options* options) final;
//! Close this layer.
virtual Status close();
//! Whether the layer is open
bool isOpen() const;
//! Status of this layer
const Status& getStatus() const;
//! @deprecated (remove after 2.10)
//! Sequence controller if the layer has one.
virtual SequenceControl* getSequenceControl() { return 0L; }
//! Serialize this layer into a Config object (if applicable)
virtual Config getConfig() const;
//! Whether to automatically open this layer (by calling open) when
//! adding the layer to a Map or when opening a map containing this Layer.
virtual void setOpenAutomatically(bool value);
//! Whether to automatically open this layer (by calling open) when
//! adding the layer to a Map or when opening a map containing this Layer.
virtual bool getOpenAutomatically() const;
//! Cacheing policy. Only set this before opening the layer or adding to a map.
void setCachePolicy(const CachePolicy& value);
const CachePolicy& getCachePolicy() const;
//! Optional scene graph provided by the layer.
//! When this layer is added to a Map, the MapNode will call this method and
//! add the return value to its scene graph; and remove it when the Layer
//! is removed from the Map.
virtual osg::Node* getNode() const { return 0L; }
//! Extent of this layer's data.
//! This method may return GeoExtent::INVALID which means that the
//! extent is unavailable (not necessarily that there is no data).
virtual const GeoExtent& getExtent() const;
//! Temporal extent of this layer's data.
virtual DateTimeExtent getDateTimeExtent() const;
//! Unique caching ID for this layer.
//! Only set this before opening the layer or adding to a map.
//! WARNING: You should be Very Careful when using this. The Layer will
//! automatically generate a cache ID that is sufficient most of the time.
//! Setting your own cache ID will require manual cache invalidation when
//! you change certain properties. Use are your own risk!
void setCacheID(const std::string& value);
virtual std::string getCacheID() const;
//! Callbacks that one can use to detect scene graph changes
SceneGraphCallbacks* getSceneGraphCallbacks() const;
//! Hints that a subclass can set to influence the engine
const Hints& getHints() const;
//! Options string to pass to OpenSceneGraph reader/writers
const std::string& getOsgOptionString() const;
public:
//! Layer's stateset, creating it is necessary
osg::StateSet* getOrCreateStateSet();
//! Layer's stateset, or NULL if none exists
osg::StateSet* getStateSet() const;
//! Stateset that should be applied to an entire terrain traversal
virtual osg::StateSet* getSharedStateSet(osg::NodeVisitor* nv) const { return NULL; }
//! How (and if) to use this layer when rendering terrain tiles.
enum RenderType
{
//! Layer does not draw anything (directly)
RENDERTYPE_NONE,
//! Layer requires a terrain rendering pass that draws terrain tiles with texturing
RENDERTYPE_TERRAIN_SURFACE,
//! Layer requires a terrain rendering pass that emits terrian patches or
//! invokes a custom drawing function
RENDERTYPE_TERRAIN_PATCH,
//! Layer that renders its own node graph or other geometry (no terrain)
RENDERTYPE_CUSTOM = RENDERTYPE_NONE
};
//! Rendering type of this layer
RenderType getRenderType() const { return _renderType; }
//! Rendering type of this layer
void setRenderType(RenderType value) { _renderType = value; }
//! Callback that modifies the layer's bounding box for a given tile key
virtual void modifyTileBoundingBox(const TileKey& key, osg::BoundingBox& box) const;
//! Class type name without namespace. For example if the leaf class type
const char* getTypeName() const;
//! Attribution to be displayed by the application
virtual std::string getAttribution() const;
//! Attribution to be displayed by the application
virtual void setAttribution(const std::string& attribution);
//! Set a serialized user property
void setUserProperty(
const std::string& key,
const std::string& value);
//! Get a serialized user property
template<typename T>
inline T getUserProperty(
const std::string& key,
T fallback) const;
public:
//! Traversal callback
class OSGEARTH_EXPORT TraversalCallback : public osg::Callback
{
public:
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) const =0;
protected:
void traverse(osg::Node* node, osg::NodeVisitor* nv) const;
};
//! Callback invoked by the terrain engine on this layer before applying
//! @deprecated replace with cull() override
void setCullCallback(TraversalCallback* tc);
const TraversalCallback* getCullCallback() const;
//! Called to traverse this layer
//! @deprecated Replace with cull() override
void apply(osg::Node* node, osg::NodeVisitor* nv) const;
//! Called by the terrain engine during the update traversal
virtual void update(osg::NodeVisitor& nv) { }
//! Map will call this function when this Layer is added to a Map.
virtual void addedToMap(const class Map*) { }
//! Map will call this function when this Layer is removed from a Map.
virtual void removedFromMap(const class Map*) { }
public: // osg::Object
virtual void setName(const std::string& name);
virtual void resizeGLObjectBuffers(unsigned maxSize);
virtual void releaseGLObjects(osg::State* state) const;
public: // Public internal methods
//! Creates a layer from serialized data - internal use
static osg::ref_ptr<Layer> create(const ConfigOptions& options);
//! Creates a layer from serialized data and attempt to cast it
//! to a specific type
template<class T>
static osg::ref_ptr<T> create_as(const ConfigOptions& options) {
auto layer = create(options);
return osg::ref_ptr<T>(dynamic_cast<T*>(layer.get()));
}
//! Extracts config options from a DB options - internal use
static const ConfigOptions& getConfigOptions(const osgDB::Options*);
//! Adds a property notification callback to this layer
void addCallback(LayerCallback* cb);
//! Removes a property notification callback from this layer
void removeCallback(LayerCallback* cb);
//! Revision number of this layer
int getRevision() const { return (int)_revision; }
//! Increment the revision number for this layer, which will
//! invalidate caches.
virtual void dirty();
class Options;
public: // deprecated
//! @deprecated - use getOpenAutomatically
bool getEnabled() const;
//! @deprecated - use setOpenAutomatically
void setEnabled(bool value);
protected:
//! Constructs a map layer by deserializing options.
Layer(
Layer::Options* options,
const Layer::Options* options0);
//! DTOR
virtual ~Layer();
//! post-ctor initialization, chain to subclasses.
//! MAKE SURE you call the superclass init() if you override this!
virtual void init();
//! Called by open() to connect to external resources and return a status.
//! MAKE SURE you call superclass openImplementation() if you override this!
//! This is where you will connect to back-end data sources if
//! appropriate. When added to a map, init() is called before open()
//! and addedToMap() is called after open() if it succeeds.
//! By default, returns STATUS_OK.
virtual Status openImplementation();
//! Called by close() to shut down the resources associated with a layer.
virtual Status closeImplementation();
//! Prepares the layer for rendering if necessary.
virtual void prepareForRendering(TerrainEngine*);
//! Sets the status for this layer - internal
const Status& setStatus(const Status& status) const;
//! Sets the status for this layer with a message - internal
const Status& setStatus(const Status::Code& statusCode, const std::string& message) const;
//! invoke layer callbacks
void fireCallback(LayerCallback::MethodPtr);
//! mutable layer hints for the subclass to optionally access
Hints& layerHints();
//! MapNode will call this function when terrain resources are available.
//! @deprecated Implement prepareForRendering instead
virtual void setTerrainResources(TerrainResources*) { }
private:
const std::string& _layerName;
UID _uid;
osg::ref_ptr<osg::StateSet> _stateSet;
RenderType _renderType;
mutable Status _status;
osg::ref_ptr<SceneGraphCallbacks> _sceneGraphCallbacks;
osg::ref_ptr<TraversalCallback> _traversalCallback;
Hints _hints;
std::atomic_int _revision = { 1 };
std::string _runtimeCacheId;
osg::ref_ptr<osgDB::Options> _readOptions;
osg::ref_ptr<CacheSettings> _cacheSettings;
std::vector<osg::ref_ptr<LayerShader> > _shaders;
mutable Threading::ReadWriteMutex _inuse_mutex;
//! Prepares the layer for rendering if necessary.
void invoke_prepareForRendering(TerrainEngine*);
protected:
typedef std::vector<osg::ref_ptr<LayerCallback> > CallbackVector;
CallbackVector _callbacks;
osgDB::Options* getMutableReadOptions() { return _readOptions.get(); }
void bumpRevision();
// subclass can call this to change an option that requires
// a re-opening of the layer.
template<typename T, typename V>
void setOptionThatRequiresReopen(T& target, const V& value);
// subclass can call this to change an option that requires
// a re-opening of the layer.
template<typename T>
void resetOptionThatRequiresReopen(T& target);
//! internal cache information
CacheSettings* getCacheSettings() { return _cacheSettings.get(); }
const CacheSettings* getCacheSettings() const { return _cacheSettings.get(); }
//! subclass access to a mutex that serializes the
//! Layer open and close methods with respect to any asynchronous
//! functions that require the layer to remain open
Threading::ReadWriteMutex& inUseMutex() const { return _inuse_mutex; }
//! Layers that this layer wants to add to the map
std::vector<osg::ref_ptr<Layer>> _sublayers;
public:
Layer::Options& options() { return *_options; }
const Layer::Options& options() const { return *_options; }
const Layer::Options& options_original() const { return *_options0; }
virtual const char* getConfigKey() const { return "layer" ; }
//! A layer can report statistics for debugging by overriding this function
using Stats = std::vector<std::pair<std::string, std::string>>;
virtual Stats reportStats() const { return {}; }
private:
Layer::Options * _options;
Layer::Options _optionsConcrete;
const Layer::Options * _options0;
const Layer::Options _optionsConcrete0;
// no copying
Layer(const Layer& rhs, const osg::CopyOp& op);
// allow the map access to the addedToMap/removedFromMap methods
friend class Map;
friend class MapNode;
};
using LayerVector = std::vector<osg::ref_ptr<Layer>>;
template<typename T, typename V>
void Layer::setOptionThatRequiresReopen(T& target, const V& value) {
if (target != value) {
bool wasOpen = isOpen();
if (wasOpen) close();
target = value;
if (wasOpen) open();
}
}
template<typename T>
void Layer::resetOptionThatRequiresReopen(T& target) {
if (target.isSet()) {
bool wasOpen = isOpen();
if (wasOpen) close();
target.unset();
if (wasOpen) open();
}
}
template<typename T>
T Layer::getUserProperty(const std::string& key, T fallback) const {
return options()._internal().value(key, fallback);
}
#define REGISTER_OSGEARTH_LAYER(NAME,CLASS) \
extern "C" void osgdb_osgearth_##NAME(void) {} \
static osgEarth::RegisterPluginLoader< osgEarth::PluginLoader<CLASS, osgEarth::Layer> > g_proxy_##CLASS_##NAME(OE_STRINGIFY(osgearth_layer_##NAME));
#define USE_OSGEARTH_LAYER(NAME) \
extern "C" void osgdb_osgearth_##NAME(void); \
static osgDB::PluginFunctionProxy proxy_osgearth_layer_##NAME(OE_STRINGIFY(osgdb_osgearth_##NAME));
} // namespace osgEarth