diff --git a/src/osgEarth/CMakeLists.txt b/src/osgEarth/CMakeLists.txt index 294919d0d5..ce83d6063a 100644 --- a/src/osgEarth/CMakeLists.txt +++ b/src/osgEarth/CMakeLists.txt @@ -114,6 +114,7 @@ SET(LIB_PUBLIC_HEADERS ColorFilter Common Composite + CompositeTiledModelLayer Config Containers Coverage @@ -260,7 +261,6 @@ SET(LIB_PUBLIC_HEADERS TileHandler TileMesher TileRasterizer - TiledFeatureModelGraph TiledFeatureModelLayer TiledModelLayer TileSource @@ -283,7 +283,6 @@ SET(LIB_PUBLIC_HEADERS WMS XmlUtils XYZ - XYZModelGraph XYZModelLayer ActivityMonitorTool @@ -551,6 +550,7 @@ set(TARGET_SRC Color.cpp ColorFilter.cpp Composite.cpp + CompositeTiledModelLayer.cpp Compressors.cpp Config.cpp CoverageLayer.cpp @@ -676,7 +676,6 @@ set(TARGET_SRC TileHandler.cpp TileMesher.cpp TileRasterizer.cpp - TiledFeatureModelGraph.cpp TiledFeatureModelLayer.cpp TiledModelLayer.cpp TileVisitor.cpp @@ -699,7 +698,6 @@ set(TARGET_SRC WMS.cpp XmlUtils.cpp XYZ.cpp - XYZModelGraph.cpp XYZModelLayer.cpp ActivityMonitorTool.cpp diff --git a/src/osgEarth/CompositeTiledModelLayer b/src/osgEarth/CompositeTiledModelLayer new file mode 100644 index 0000000000..05650aeeda --- /dev/null +++ b/src/osgEarth/CompositeTiledModelLayer @@ -0,0 +1,95 @@ +/* -*-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 + */ +#ifndef OSGEARTH_COMPOSITE_TILED_MODEL_LAYER +#define OSGEARTH_COMPOSITE_TILED_MODEL_LAYER 1 + +#include +#include +#include + +namespace osgEarth { + class Map; +} + +namespace osgEarth +{ + class OSGEARTH_EXPORT CompositeTiledModelLayer : public TiledModelLayer + { + public: // serialization + struct OSGEARTH_EXPORT Options : public TiledModelLayer::Options + { + META_LayerOptions(osgEarth, Options, TiledModelLayer::Options); + OE_OPTION(ProfileOptions, profile); + + OE_OPTION_VECTOR(ConfigOptions, layers); + + Config getConfig() const override; + void fromConfig(const Config& conf); + }; + + public: + META_Layer(osgEarth, CompositeTiledModelLayer, Options, TiledModelLayer, CompositeTiledModel); + + //! Tiling profile (required) + void setProfile(const Profile* profile); + const Profile* getProfile() const override { return _profile.get(); } + + unsigned getMinLevel() const override; + + //! Maximum level of detail to access + unsigned getMaxLevel() const override; + + public: // Layer + + //! opens the layer and returns the status + Status openImplementation() override; + + //! Serialization + Config getConfig() const override; + + public: // Layer + + //! called by the map when this layer is added + void addedToMap(const Map*) override; + + //! called by the map when this layer is removed + void removedFromMap(const Map*) override; + + protected: // TiledModelLayer + + //! Creates an OSG node from a tile key. + osg::ref_ptr createTileImplementation(const TileKey&, ProgressCallback*) const override; + + protected: + + virtual ~CompositeTiledModelLayer(); + + private: + osg::ref_ptr _profile; + osg::observer_ptr< const Map > _map; + + unsigned int _minLevel = 0; + unsigned int _maxLevel = 0; + + std::vector< osg::ref_ptr< TiledModelLayer > > _layers; + }; + +} // namespace osgEarth + +#endif // OSGEARTH_COMPOSITE_TILED_MODEL_LAYER diff --git a/src/osgEarth/CompositeTiledModelLayer.cpp b/src/osgEarth/CompositeTiledModelLayer.cpp new file mode 100644 index 0000000000..27893dc637 --- /dev/null +++ b/src/osgEarth/CompositeTiledModelLayer.cpp @@ -0,0 +1,191 @@ +/* -*-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 + */ +#include +#include +#include + +#include + +using namespace osgEarth; + +#define LC "[CompositeTiledModelLayer] " + +#define OE_TEST OE_NULL + +REGISTER_OSGEARTH_LAYER(CompositeTiledModel, CompositeTiledModelLayer); + +void CompositeTiledModelLayer::Options::fromConfig(const Config& conf) +{ + conf.get("profile", profile()); + + const ConfigSet& layers = conf.child("layers").children(); + for (ConfigSet::const_iterator i = layers.begin(); i != layers.end(); ++i) + { + _layers.push_back(ConfigOptions(*i)); + } +} + +Config +CompositeTiledModelLayer::Options::getConfig() const +{ + Config conf = TiledModelLayer::Options::getConfig(); + conf.set("profile", profile()); + + if (_layers.empty() == false) + { + Config layersConf("layers"); + for (std::vector::const_iterator i = _layers.begin(); i != _layers.end(); ++i) + { + layersConf.add(i->getConfig()); + } + conf.set(layersConf); + } + + return conf; +} + +//........................................................................... + +CompositeTiledModelLayer::~CompositeTiledModelLayer() +{ + //NOP +} + +void CompositeTiledModelLayer::setProfile(const Profile* profile) +{ + _profile = profile; + if (_profile) + { + options().profile() = profile->toProfileOptions(); + } +} + +Config +CompositeTiledModelLayer::getConfig() const +{ + Config conf = TiledModelLayer::getConfig(); + return conf; +} + +Status +CompositeTiledModelLayer::openImplementation() +{ + Status parent = super::openImplementation(); + if (parent.isError()) + return parent; + + _profile = Profile::create(*options().profile()); + + // Open all the layers + for (auto& layerConf : options().layers()) + { + osg::ref_ptr< Layer > layer = Layer::create(layerConf); + TiledModelLayer* tiledLayer = dynamic_cast(layer.get()); + if (tiledLayer) + { + tiledLayer->open(); + tiledLayer->setReadOptions(getReadOptions()); + _layers.push_back(tiledLayer); + } + else + { + OE_WARN << LC << "Layer is not a TiledModelLayer" << std::endl; + } + } + + return Status::NoError; +} + +void +CompositeTiledModelLayer::addedToMap(const Map* map) +{ + for (auto& layer : _layers) + { + layer->addedToMap(map); + } + + // Check to make sure the layers are all using the same profile + for (auto& layer : _layers) + { + if (!layer->getProfile()->isEquivalentTo(_profile)) + { + OE_WARN << LC << "Layer " << layer->getName() << " does not have the same profile as the composite layer" << std::endl; + } + } + + // Compute the min and max levels + if (!_layers.empty()) + { + _minLevel = 1000; + _maxLevel = 0; + for (auto& layer : _layers) + { + if (layer->getMinLevel() < _minLevel) + { + _minLevel = layer->getMinLevel(); + } + if (layer->getMaxLevel() > _maxLevel) + { + _maxLevel = layer->getMaxLevel(); + } + } + } + + super::addedToMap(map); +} + +void +CompositeTiledModelLayer::removedFromMap(const Map* map) +{ + super::removedFromMap(map); + + for (auto& layer : _layers) + { + layer->removedFromMap(map); + } +} + +osg::ref_ptr +CompositeTiledModelLayer::createTileImplementation(const TileKey& key, ProgressCallback* progress) const +{ + osg::ref_ptr group = new osg::Group(); + + for (unsigned int i = 0; i < this->_layers.size(); i++) + { + osg::ref_ptr node = this->_layers[i]->createTile(key, progress); + if (node.valid()) + { + group->addChild(node); + } + } + return group; +} + +unsigned +CompositeTiledModelLayer::getMinLevel() const +{ + return _minLevel; +} + +unsigned +CompositeTiledModelLayer::getMaxLevel() const +{ + return _maxLevel; +} + diff --git a/src/osgEarth/TiledFeatureModelGraph.cpp b/src/osgEarth/TiledFeatureModelGraph.cpp deleted file mode 100644 index 1c95007d64..0000000000 --- a/src/osgEarth/TiledFeatureModelGraph.cpp +++ /dev/null @@ -1,231 +0,0 @@ -/* -*-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 - */ -#include -#include -#include -#include -#include - -using namespace osgEarth; - -TiledFeatureModelGraph::TiledFeatureModelGraph(const osgEarth::Map* map, - FeatureSource* features, - StyleSheet* styleSheet, - Session* session) : - SimplePager(map, (features && features->getFeatureProfile()) ? features->getFeatureProfile()->getTilingProfile() : nullptr), - _features(features), - _styleSheet(styleSheet), - _session(session) -{ - setMinLevel(features->getFeatureProfile()->getFirstLevel()); - setMaxLevel(features->getFeatureProfile()->getMaxLevel()); - - _session->setResourceCache(new ResourceCache()); - - - FeatureSourceIndexOptions indexOptions; - indexOptions.enabled() = true; - - _featureIndex = new FeatureSourceIndex( - features, - Registry::objectIndex(), - indexOptions); -} - -void -TiledFeatureModelGraph::setFilterChain(FeatureFilterChain* chain) -{ - _filterChain = chain; -} - -void -TiledFeatureModelGraph::setOwnerName(const std::string& value) -{ - _ownerName = value; -} - - -FeatureCursor* -TiledFeatureModelGraph::createCursor(FeatureSource* fs, FilterContext& cx, const Query& query, ProgressCallback* progress) const -{ - NetworkMonitor::ScopedRequestLayer layerRequest(_ownerName); - FeatureCursor* cursor = fs->createFeatureCursor(query, progress); - if (cursor && _filterChain.valid()) - { - cursor = new FilteredFeatureCursor(cursor, _filterChain.get(), &cx); - } - return cursor; -} - -osg::ref_ptr -TiledFeatureModelGraph::createNode(const TileKey& key, ProgressCallback* progress) -{ - if (progress && progress->isCanceled()) - return nullptr; - - NetworkMonitor::ScopedRequestLayer layerRequest(_ownerName); - // Get features for this key - Query query; - query.tileKey() = key; - - GeoExtent dataExtent = key.getExtent(); - - // set up for feature indexing if appropriate: - osg::ref_ptr< FeatureSourceIndexNode > index = 0L; - - if (_featureIndex.valid()) - { - index = new FeatureSourceIndexNode(_featureIndex.get()); - } - - FilterContext fc(_session.get(), new FeatureProfile(dataExtent), dataExtent, index); - - GeometryCompilerOptions options; - options.instancing() = true; - //options.mergeGeometry() = true; - GeometryCompiler gc(options); - - GeomFeatureNodeFactory factory(options); - - if (progress && progress->isCanceled()) - return nullptr; - - osg::ref_ptr< FeatureCursor > cursor = _features->createFeatureCursor( - query, - _filterChain.get(), - &fc, - progress); - - osg::ref_ptr node = new osg::Group; - if (cursor) - { - if (progress && progress->isCanceled()) - return nullptr; - - FeatureList features; - cursor->fill(features); - - if (_styleSheet->getSelectors().size() > 0) - { - osg::Group* group = new osg::Group; - - for (StyleSelectors::const_iterator i = _styleSheet->getSelectors().begin(); - i != _styleSheet->getSelectors().end(); - ++i) - { - typedef std::map< std::string, FeatureList > StyleToFeaturesMap; - StyleToFeaturesMap styleToFeatures; - - // pull the selected style... - const StyleSelector& sel = i->second; - - if (sel.styleExpression().isSet()) - { - // establish the working bounds and a context: - StringExpression styleExprCopy(sel.styleExpression().get()); - for (FeatureList::iterator itr = features.begin(); itr != features.end(); ++itr) - { - Feature* feature = itr->get(); - - feature->set("level", (long long)key.getLevelOfDetail()); - - const std::string& styleString = feature->eval(styleExprCopy, &fc); - if (!styleString.empty() && styleString != "null") - { - styleToFeatures[styleString].push_back(feature); - } - - if (progress && progress->isCanceled()) - return nullptr; - } - } - - std::unordered_map literal_styles; - - for (StyleToFeaturesMap::iterator itr = styleToFeatures.begin(); itr != styleToFeatures.end(); ++itr) - { - const std::string& styleString = itr->first; - Style* style = nullptr; - - if (styleString.length() > 0 && styleString[0] == '{') - { - Config conf("style", styleString); - conf.setReferrer(sel.styleExpression().get().uriContext().referrer()); - conf.set("type", "text/css"); - Style& literal_style = literal_styles[conf.toJSON()]; - if (literal_style.empty()) - literal_style = Style(conf); - style = &literal_style; - } - else - { - style = _styleSheet->getStyle(styleString); - } - - if (style) - { - osg::Group* styleGroup = factory.getOrCreateStyleGroup(*style, _session.get()); - osg::ref_ptr< osg::Node> styleNode; - osg::ref_ptr< FeatureListCursor> cursor = new FeatureListCursor(itr->second); - Query query; - factory.createOrUpdateNode(cursor.get(), *style, fc, styleNode, query); - if (styleNode.valid()) - { - styleGroup->addChild(styleNode); - if (!group->containsNode(styleGroup)) - { - group->addChild(styleGroup); - } - } - } - } - } - - - node = group; - } - else if (_styleSheet->getDefaultStyle()) - { - osg::ref_ptr< FeatureListCursor> cursor = new FeatureListCursor(features); - osg::ref_ptr< osg::Group > group = new osg::Group; - osg::ref_ptr< osg::Group > styleGroup = factory.getOrCreateStyleGroup(*_styleSheet->getDefaultStyle(), _session.get()); - osg::ref_ptr< osg::Node> styleNode; - factory.createOrUpdateNode(cursor.get(), *_styleSheet->getDefaultStyle(), fc, styleNode, query); - if (styleNode.valid()) - { - group->addChild(styleGroup); - styleGroup->addChild(styleNode); - node = group; - } - } - } - - if (!node->getBound().valid()) - { - return nullptr; - } - - if (index.valid()) - { - index->addChild(node); - return index; - } - - return node; -} \ No newline at end of file diff --git a/src/osgEarth/TiledFeatureModelLayer b/src/osgEarth/TiledFeatureModelLayer index b4a3f938af..09549c504c 100644 --- a/src/osgEarth/TiledFeatureModelLayer +++ b/src/osgEarth/TiledFeatureModelLayer @@ -51,8 +51,7 @@ namespace osgEarth // constructors Options(); Options(const ConfigOptions& options); - OE_OPTION_LAYER(FeatureSource, featureSource); - OE_OPTION(bool, additive); + OE_OPTION_LAYER(FeatureSource, featureSource); Config getConfig() const override; protected: // LayerOptions void mergeConfig(const Config& conf) override; @@ -79,13 +78,6 @@ namespace osgEarth void setEnableLighting(const bool& value); const bool& getEnableLighting() const; - //! Whether new LODs should be added to the scene (true) or replace existing ones (false) - void setAdditive(const bool& value); - const bool& getAdditive() const; - - //! Forces a rebuild on this FeatureModelLayer. - void dirty(); - public: // Layer // opens the layer and returns the status @@ -94,9 +86,6 @@ namespace osgEarth // closes the layer Status closeImplementation() override; - // The Node representing this layer. - osg::Node* getNode() const override; - //! Extent of the feature layer, if available (INVALID if not) const GeoExtent& getExtent() const override; @@ -136,10 +125,8 @@ namespace osgEarth private: osg::ref_ptr _session; - osg::ref_ptr _root; - bool _graphDirty; - - void create(); + osg::ref_ptr _filters; + osg::ref_ptr< FeatureSourceIndex > _featureIndex; }; } // namespace osgEarth diff --git a/src/osgEarth/TiledFeatureModelLayer.cpp b/src/osgEarth/TiledFeatureModelLayer.cpp index e0aca4c4cc..86ed286c5a 100644 --- a/src/osgEarth/TiledFeatureModelLayer.cpp +++ b/src/osgEarth/TiledFeatureModelLayer.cpp @@ -17,7 +17,8 @@ * along with this program. If not, see */ #include -#include +#include +#include using namespace osgEarth; @@ -47,8 +48,6 @@ TiledFeatureModelLayer::Options::Options(const ConfigOptions& options) : void TiledFeatureModelLayer::Options::fromConfig(const Config& conf) { - additive().setDefault(false); - conf.get("additive", additive()); featureSource().get(conf, "features"); } @@ -63,8 +62,6 @@ TiledFeatureModelLayer::Options::getConfig() const Config gcConf = GeometryCompilerOptions::getConfig(); conf.merge(gcConf); - conf.set("additive", additive()); - featureSource().set(conf, "features"); return conf; @@ -80,7 +77,6 @@ void TiledFeatureModelLayer::Options::mergeConfig(const Config& conf) OE_LAYER_PROPERTY_IMPL(TiledFeatureModelLayer, bool, AlphaBlending, alphaBlending); OE_LAYER_PROPERTY_IMPL(TiledFeatureModelLayer, bool, EnableLighting, enableLighting); -OE_LAYER_PROPERTY_IMPL(TiledFeatureModelLayer, bool, Additive, additive); TiledFeatureModelLayer::~TiledFeatureModelLayer() { @@ -91,26 +87,6 @@ void TiledFeatureModelLayer::init() { TiledModelLayer::init(); - - _root = new osg::Group(); - - // Assign the layer's state set to the root node: - _root->setStateSet(this->getOrCreateStateSet()); - - // Graph needs rebuilding - _graphDirty = true; - - // Depth sorting by default - getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); -} - -void TiledFeatureModelLayer::dirty() -{ - // feature source changed, so the graph needs rebuilding - _graphDirty = true; - - // create the scene graph - create(); } Config @@ -159,12 +135,6 @@ TiledFeatureModelLayer::getStyleSheet() const return options().styleSheet().getLayer(); } -osg::Node* -TiledFeatureModelLayer::getNode() const -{ - return _root.get(); -} - Status TiledFeatureModelLayer::openImplementation() { @@ -186,9 +156,9 @@ TiledFeatureModelLayer::openImplementation() Status TiledFeatureModelLayer::closeImplementation() { + super::closeImplementation(); options().featureSource().close(); options().styleSheet().close(); - _graphDirty = true; return getStatus(); } @@ -207,7 +177,7 @@ void TiledFeatureModelLayer::addedToMap(const Map* map) { OE_TEST << LC << "addedToMap" << std::endl; - TiledModelLayer::addedToMap(map); + options().featureSource().addedToMap(map); options().styleSheet().addedToMap(map); @@ -222,29 +192,36 @@ TiledFeatureModelLayer::addedToMap(const Map* map) getFeatureSource(), getReadOptions()); - // re-create the graph if necessary. - create(); + // connect the session to the features: + _session->setFeatureSource(getFeatureSource()); + _session->setResourceCache(new ResourceCache()); + + FeatureSourceIndexOptions indexOptions; + indexOptions.enabled() = true; + + _featureIndex = new FeatureSourceIndex( + getFeatureSource(), + Registry::objectIndex(), + indexOptions); } + + _filters = FeatureFilterChain::create(options().filters(), getReadOptions()); + + TiledModelLayer::addedToMap(map); } void TiledFeatureModelLayer::removedFromMap(const Map* map) { - TiledModelLayer::removedFromMap(map); + super::removedFromMap(map); options().featureSource().removedFromMap(map); options().styleSheet().removedFromMap(map); - if (_root.valid()) - { - osg::ref_ptr tfmg = findTopMostNodeOfType(_root.get()); - if (tfmg.valid()) tfmg->setDone(); - _root->removeChildren(0, _root->getNumChildren()); - } - _session = 0L; } +#if 0 void TiledFeatureModelLayer::create() { @@ -266,6 +243,7 @@ TiledFeatureModelLayer::create() fmg->setOwnerName(getName()); fmg->setFilterChain(chain.get()); fmg->setAdditive(*_options->additive()); + fmg->setRangeFactor(*_options->rangeFactor()); fmg->build(); _root->removeChildren(0, _root->getNumChildren()); @@ -279,36 +257,179 @@ TiledFeatureModelLayer::create() } } } +#endif osg::ref_ptr TiledFeatureModelLayer::createTileImplementation(const TileKey& key, ProgressCallback* progress) const { - osg::ref_ptr result; - auto fmg = osgEarth::findTopMostNodeOfType(_root.get()); - if (fmg) + if (progress && progress->isCanceled()) + return nullptr; + + NetworkMonitor::ScopedRequestLayer layerRequest(getName()); + // Get features for this key + Query query; + query.tileKey() = key; + + GeoExtent dataExtent = key.getExtent(); + + // set up for feature indexing if appropriate: + osg::ref_ptr< FeatureSourceIndexNode > index = 0L; + + if (_featureIndex.valid()) + { + index = new FeatureSourceIndexNode(_featureIndex.get()); + } + + FilterContext fc(_session.get(), new FeatureProfile(dataExtent), dataExtent, index); + + GeometryCompilerOptions options; + options.instancing() = true; + //options.mergeGeometry() = true; + GeometryCompiler gc(options); + + GeomFeatureNodeFactory factory(options); + + if (progress && progress->isCanceled()) + return nullptr; + + osg::ref_ptr< FeatureCursor > cursor = getFeatureSource()->createFeatureCursor( + query, + _filters.get(), + &fc, + progress); + + osg::ref_ptr node = new osg::Group; + if (cursor) + { + if (progress && progress->isCanceled()) + return nullptr; + + FeatureList features; + cursor->fill(features); + + if (getStyleSheet()->getSelectors().size() > 0) + { + osg::Group* group = new osg::Group; + + for (StyleSelectors::const_iterator i = getStyleSheet()->getSelectors().begin(); + i != getStyleSheet()->getSelectors().end(); + ++i) + { + typedef std::map< std::string, FeatureList > StyleToFeaturesMap; + StyleToFeaturesMap styleToFeatures; + + // pull the selected style... + const StyleSelector& sel = i->second; + + if (sel.styleExpression().isSet()) + { + // establish the working bounds and a context: + StringExpression styleExprCopy(sel.styleExpression().get()); + for (FeatureList::iterator itr = features.begin(); itr != features.end(); ++itr) + { + Feature* feature = itr->get(); + + feature->set("level", (long long)key.getLevelOfDetail()); + + const std::string& styleString = feature->eval(styleExprCopy, &fc); + if (!styleString.empty() && styleString != "null") + { + styleToFeatures[styleString].push_back(feature); + } + + if (progress && progress->isCanceled()) + return nullptr; + } + } + + std::unordered_map literal_styles; + + for (StyleToFeaturesMap::iterator itr = styleToFeatures.begin(); itr != styleToFeatures.end(); ++itr) + { + const std::string& styleString = itr->first; + Style* style = nullptr; + + if (styleString.length() > 0 && styleString[0] == '{') + { + Config conf("style", styleString); + conf.setReferrer(sel.styleExpression().get().uriContext().referrer()); + conf.set("type", "text/css"); + Style& literal_style = literal_styles[conf.toJSON()]; + if (literal_style.empty()) + literal_style = Style(conf); + style = &literal_style; + } + else + { + style = getStyleSheet()->getStyle(styleString); + } + + if (style) + { + osg::Group* styleGroup = factory.getOrCreateStyleGroup(*style, _session.get()); + osg::ref_ptr< osg::Node> styleNode; + osg::ref_ptr< FeatureListCursor> cursor = new FeatureListCursor(itr->second); + Query query; + factory.createOrUpdateNode(cursor.get(), *style, fc, styleNode, query); + if (styleNode.valid()) + { + styleGroup->addChild(styleNode); + if (!group->containsNode(styleGroup)) + { + group->addChild(styleGroup); + } + } + } + } + } + + + node = group; + } + else if (getStyleSheet()->getDefaultStyle()) + { + osg::ref_ptr< FeatureListCursor> cursor = new FeatureListCursor(features); + osg::ref_ptr< osg::Group > group = new osg::Group; + osg::ref_ptr< osg::Group > styleGroup = factory.getOrCreateStyleGroup(*getStyleSheet()->getDefaultStyle(), _session.get()); + osg::ref_ptr< osg::Node> styleNode; + factory.createOrUpdateNode(cursor.get(), *getStyleSheet()->getDefaultStyle(), fc, styleNode, query); + if (styleNode.valid()) + { + group->addChild(styleGroup); + styleGroup->addChild(styleNode); + node = group; + } + } + } + + if (!node->getBound().valid()) { - result = fmg->createNode(key, progress); + return nullptr; } - return result; + + if (index.valid()) + { + index->addChild(node); + return index; + } + + return node; } const Profile* TiledFeatureModelLayer::getProfile() const { - auto fmg = osgEarth::findTopMostNodeOfType(_root.get()); - return fmg ? fmg->getProfile() : nullptr; + return getFeatureSource()->getFeatureProfile()->getTilingProfile(); } unsigned TiledFeatureModelLayer::getMinLevel() const { - auto fmg = osgEarth::findTopMostNodeOfType(_root.get()); - return fmg ? fmg->getMinLevel() : 0u; + return getFeatureSource()->getFeatureProfile()->getFirstLevel(); } unsigned TiledFeatureModelLayer::getMaxLevel() const { - auto fmg = osgEarth::findTopMostNodeOfType(_root.get()); - return fmg ? fmg->getMaxLevel() : 99u; + return getFeatureSource()->getFeatureProfile()->getMaxLevel(); } diff --git a/src/osgEarth/TiledModelLayer b/src/osgEarth/TiledModelLayer index 4750ee0ca4..66a6ca5336 100644 --- a/src/osgEarth/TiledModelLayer +++ b/src/osgEarth/TiledModelLayer @@ -37,6 +37,8 @@ namespace osgEarth struct OSGEARTH_EXPORT Options : public VisibleLayer::Options { META_LayerOptions(osgEarth, Options, VisibleLayer::Options); + OE_OPTION(bool, additive); + OE_OPTION(float, rangeFactor); virtual Config getConfig() const; void fromConfig(const Config& conf); }; @@ -58,10 +60,41 @@ namespace osgEarth //! Maximum available LOD of the underlying tiled data source. virtual unsigned getMaxLevel() const = 0; + //! Whether new LODs should be added to the scene (true) or replace existing ones (false) + void setAdditive(const bool& value); + const bool& getAdditive() const; + + //! The range factor. Default is 6 + void setRangeFactor(const float &value); + const float& getRangeFactor() const; + + //! Forces a rebuild on this layer. + void dirty(); + + public: // Layer + + // The Node representing this layer. + osg::Node* getNode() const override; + + // called by the map when this layer is added + void addedToMap(const Map*) override; + + // called by the map when this layer is removed + void removedFromMap(const Map*) override; + + // post-ctor initialization + void init() override; + protected: //! Subclasses must implement this to create a tile. //! @param key The tile key, in the underlying tiled data source's profile. //! @param progress A progress callback that can be checked for user cancellation. virtual osg::ref_ptr createTileImplementation(const TileKey& key, ProgressCallback* progress) const = 0; + + private: + osg::observer_ptr< const Map > _map; + osg::ref_ptr< osg::Group > _root; + bool _graphDirty; + void create(); }; } diff --git a/src/osgEarth/TiledModelLayer.cpp b/src/osgEarth/TiledModelLayer.cpp index 4a791c994a..4904ffd844 100644 --- a/src/osgEarth/TiledModelLayer.cpp +++ b/src/osgEarth/TiledModelLayer.cpp @@ -17,27 +17,49 @@ * along with this program. If not, see */ #include "TiledModelLayer" +#include +#include using namespace osgEarth; -void TiledModelLayer::Options::fromConfig(const Config& conf) + +class TiledModelLayerPager : public SimplePager { - //minLevel().setDefault(0u); - //maxLevel().setDefault(99u); +public: + TiledModelLayerPager(const Map* map, TiledModelLayer* layer): + SimplePager(map, layer->getProfile()), + _layer(layer) + { + } - //conf.get("min_level", minLevel()); - //conf.get("max_level", maxLevel()); + virtual osg::ref_ptr createNode(const TileKey& key, ProgressCallback* progress) override + { + return _layer->createTile(key, progress); + } + + osg::observer_ptr< TiledModelLayer > _layer; +}; + +void TiledModelLayer::Options::fromConfig(const Config& conf) +{ + additive().setDefault(false); + rangeFactor().setDefault(6.0); + conf.get("additive", additive()); + conf.get("range_factor", rangeFactor()); } Config TiledModelLayer::Options::getConfig() const { Config conf = VisibleLayer::Options::getConfig(); - //conf.set("min_level", minLevel()); - //conf.set("max_level", maxLevel()); + conf.set("additive", additive()); + conf.set("range_factor", rangeFactor()); return conf; } +OE_LAYER_PROPERTY_IMPL(TiledModelLayer, bool, Additive, additive); +OE_LAYER_PROPERTY_IMPL(TiledModelLayer, float, RangeFactor, rangeFactor); + osg::ref_ptr TiledModelLayer::createTile(const TileKey& key, ProgressCallback* progress) const { @@ -77,3 +99,82 @@ TiledModelLayer::createTile(const TileKey& key, ProgressCallback* progress) cons return group; } } + +// The Node representing this layer. +osg::Node* TiledModelLayer::getNode() const +{ + return _root.get(); +} + +// called by the map when this layer is added +void +TiledModelLayer::addedToMap(const Map* map) +{ + super::addedToMap(map); + + _map = map; + + _graphDirty = true; + + // re-create the graph if necessary. + create(); +} + +// called by the map when this layer is removed +void +TiledModelLayer::removedFromMap(const Map* map) +{ + super::removedFromMap(map); + + if (_root.valid()) + { + osg::ref_ptr node = findTopMostNodeOfType(_root.get()); + if (node.valid()) node->setDone(); + _root->removeChildren(0, _root->getNumChildren()); + } +} + +void TiledModelLayer::dirty() +{ + _graphDirty = true; + + // create the scene graph + create(); +} + +// post-ctor initialization +void TiledModelLayer::init() +{ + super::init(); + + // Create the container group + + _root = new osg::Group(); + + // Assign the layer's state set to the root node: + _root->setStateSet(this->getOrCreateStateSet()); + + // Graph needs rebuilding + _graphDirty = true; + + // Depth sorting by default + getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); +} + +void TiledModelLayer::create() +{ + if (_map.valid() && _graphDirty) + { + _root->removeChildren(0, _root->getNumChildren()); + + TiledModelLayerPager* pager = new TiledModelLayerPager(_map.get(), this); + pager->setAdditive(this->getAdditive()); + pager->setRangeFactor(this->getRangeFactor()); + pager->setMinLevel(this->getMinLevel()); + pager->setMaxLevel(this->getMaxLevel()); + pager->build(); + // TODO: NVGL + _root->addChild(pager); + _graphDirty = false; + } +} \ No newline at end of file diff --git a/src/osgEarth/XYZModelGraph b/src/osgEarth/XYZModelGraph deleted file mode 100644 index a024ea51d8..0000000000 --- a/src/osgEarth/XYZModelGraph +++ /dev/null @@ -1,63 +0,0 @@ -/* --*-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 - */ - -#ifndef OSGEARTH_XYZ_MODEL_GRAPH_H -#define OSGEARTH_XYZ_MODEL_GRAPH_H 1 - -#include -#include -#include -#include -#include - -#include -#include - -namespace osgEarth { - - /** - * A scene graph node that loads pre-tiled quadtree model data. - */ - class OSGEARTH_EXPORT XYZModelGraph : public SimplePager - { - public: - XYZModelGraph(const osgEarth::Map* map, const Profile* profile, const URI& url, bool invertY, const osgDB::Options* options); - - void setOwnerName(const std::string& value); - - //! Whether to attempt to use NVGL extensions - void setUseNVGL(bool value); - - public: // SimplePager - - virtual osg::ref_ptr createNode(const TileKey& key, ProgressCallback* progress) override; - - private: - std::string _ownerName; - URI _url; - bool _invertY; - osg::ref_ptr< osgEarth::StateSetCache > _statesetCache; - osg::ref_ptr< osgDB::Options > _options; - osg::ref_ptr< TextureArena > _textures; - mutable std::vector _texturesCache; - mutable std::mutex _texturesCacheMutex; - }; -} - -#endif // OSGEARTH_XYZ_MODEL_GRAPH_H diff --git a/src/osgEarth/XYZModelGraph.cpp b/src/osgEarth/XYZModelGraph.cpp deleted file mode 100644 index 2563310146..0000000000 --- a/src/osgEarth/XYZModelGraph.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* -*-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 - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace osgEarth; - -XYZModelGraph::XYZModelGraph(const osgEarth::Map* map, const Profile* profile, const URI& url, bool invertY, const osgDB::Options* options) : - SimplePager(map, profile), - _url(url), - _invertY(invertY) -{ - _options = osgEarth::Registry::instance()->cloneOrCreateOptions(options); - _options->setObjectCacheHint(osgDB::Options::CACHE_IMAGES); - - _statesetCache = new StateSetCache(); -} - -void -XYZModelGraph::setUseNVGL(bool value) -{ - if (value == true && GLUtils::useNVGL() && !_textures.valid()) - { - _textures = new TextureArena(); - getOrCreateStateSet()->setAttribute(_textures, 1); - - // auto release requires that we install this update callback! - _textures->setAutoRelease(true); - - addUpdateCallback(new LambdaCallback<>([this](osg::NodeVisitor& nv) - { - _textures->update(nv); - return true; - })); - - getOrCreateStateSet()->setAttributeAndModes( - new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA), - osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); - } -} - -void -XYZModelGraph::setOwnerName(const std::string& value) -{ - _ownerName = value; -} - -osg::ref_ptr -XYZModelGraph::createNode(const TileKey& key, ProgressCallback* progress) -{ - OE_PROFILING_ZONE; - if (progress && progress->isCanceled()) - return nullptr; - - NetworkMonitor::ScopedRequestLayer layerRequest(_ownerName); - - unsigned x, y; - key.getTileXY(x, y); - unsigned cols = 0, rows = 0; - key.getProfile()->getNumTiles(key.getLevelOfDetail(), cols, rows); - unsigned inverted_y = rows - y - 1; - - if (_invertY == true) - { - y = inverted_y; - } - - std::string location = _url.full(); - - // support OpenLayers template style: - replaceIn(location, "${x}", Stringify() << x); - replaceIn(location, "${y}", Stringify() << y); - replaceIn(location, "${-y}", Stringify() << inverted_y); - replaceIn(location, "${z}", Stringify() << key.getLevelOfDetail()); - - - // failing that, legacy osgearth style: - replaceIn(location, "{x}", Stringify() << x); - replaceIn(location, "{y}", Stringify() << y); - replaceIn(location, "{-y}", Stringify() << inverted_y); - replaceIn(location, "{z}", Stringify() << key.getLevelOfDetail()); - - URI myUri(location, _url.context()); - - osg::ref_ptr< osg::Node > node = myUri.readNode(_options.get()).getNode(); - if (node.valid()) - { - if (_textures.valid()) - { - auto xform = findTopMostNodeOfType(node.get()); - - // Convert the geometry into chonks - ChonkFactory factory(_textures); - - factory.setGetOrCreateFunction( - ChonkFactory::getWeakTextureCacheFunction( - _texturesCache, _texturesCacheMutex)); - - osg::ref_ptr drawable = new ChonkDrawable(); - - if (xform) - { - for (unsigned i = 0; i < xform->getNumChildren(); ++i) - { - drawable->add(xform->getChild(i), factory); - } - xform->removeChildren(0, xform->getNumChildren()); - xform->addChild(drawable); - node = xform; - } - else - { - if (drawable->add(node.get(), factory)) - { - node = drawable; - } - } - } - else - { - osgEarth::Registry::shaderGenerator().run(node.get(), _statesetCache); - } - return node.release(); - } - return nullptr; -} \ No newline at end of file diff --git a/src/osgEarth/XYZModelLayer b/src/osgEarth/XYZModelLayer index 6aec9842bc..4714e167f2 100644 --- a/src/osgEarth/XYZModelLayer +++ b/src/osgEarth/XYZModelLayer @@ -23,28 +23,30 @@ #include #include #include +#include +#include + namespace osgEarth { class Map; } namespace osgEarth -{ +{ /** * Layer that loads a pregenerated quadtree of model files */ class OSGEARTH_EXPORT XYZModelLayer : public TiledModelLayer { public: // serialization - struct OSGEARTH_EXPORT Options : public TiledModelLayer::Options + struct OSGEARTH_EXPORT Options : public TiledModelLayer::Options { META_LayerOptions(osgEarth, Options, TiledModelLayer::Options); OE_OPTION(URI, url); - OE_OPTION(bool, additive); OE_OPTION(bool, invertY); OE_OPTION(int, minLevel); OE_OPTION(int, maxLevel); - OE_OPTION(float, rangeFactor); + OE_OPTION(ProfileOptions, profile); Config getConfig() const override; void fromConfig(const Config& conf); @@ -78,36 +80,17 @@ namespace osgEarth void setMaxLevel(unsigned value); unsigned getMaxLevel() const override; - //! The range factor. Default is 6 - void setRangeFactor(float value); - float getRangeFactor() const; - - //! Forces a rebuild on this layer. - void dirty(); - public: // Layer //! opens the layer and returns the status Status openImplementation() override; - //! closes the layer - Status closeImplementation() override; - - //! The Node representing this layer. - osg::Node* getNode() const override; + void addedToMap(const Map* map) override; //! Serialization Config getConfig() const override; - public: // Layer - - //! called by the map when this layer is added - void addedToMap(const Map*) override; - - //! called by the map when this layer is removed - void removedFromMap(const Map*) override; - - //! post-ctor initialization + // post-ctor initialization void init() override; protected: // TiledModelLayer @@ -120,12 +103,13 @@ namespace osgEarth virtual ~XYZModelLayer(); private: - osg::ref_ptr _root; osg::ref_ptr _profile; - osg::observer_ptr< const Map > _map; - bool _graphDirty; - - void create(); + + osg::ref_ptr< osgEarth::StateSetCache > _statesetCache; + osg::ref_ptr< osgDB::Options > _readOptions; + osg::ref_ptr< TextureArena > _textures; + mutable std::vector _texturesCache; + mutable std::mutex _texturesCacheMutex; }; } // namespace osgEarth diff --git a/src/osgEarth/XYZModelLayer.cpp b/src/osgEarth/XYZModelLayer.cpp index e4e7e3b13f..fdcd6a6678 100644 --- a/src/osgEarth/XYZModelLayer.cpp +++ b/src/osgEarth/XYZModelLayer.cpp @@ -17,8 +17,14 @@ * along with this program. If not, see */ #include -#include #include +#include +#include +#include +#include +#include +#include +#include using namespace osgEarth; @@ -32,15 +38,10 @@ REGISTER_OSGEARTH_LAYER(XYZModel, XYZModelLayer); void XYZModelLayer::Options::fromConfig(const Config& conf) { - invertY().setDefault(false); - additive().setDefault(false); - rangeFactor().setDefault(6.0); - - conf.get("additive", additive()); + invertY().setDefault(false); conf.get("url", url()); conf.get("min_level", minLevel()); - conf.get("max_level", maxLevel()); - conf.get("range_factor", rangeFactor()); + conf.get("max_level", maxLevel()); conf.get("profile", profile()); } @@ -48,12 +49,10 @@ Config XYZModelLayer::Options::getConfig() const { Config conf = TiledModelLayer::Options::getConfig(); - conf.set("additive", additive()); conf.set("url", url()); conf.set("min_level", minLevel()); conf.set("max_level", maxLevel()); conf.set("profile", profile()); - conf.set("range_factor", rangeFactor()); return conf; } @@ -61,7 +60,6 @@ XYZModelLayer::Options::getConfig() const //........................................................................... OE_LAYER_PROPERTY_IMPL(XYZModelLayer, URI, URL, url); -OE_LAYER_PROPERTY_IMPL(XYZModelLayer, bool, Additive, additive); void XYZModelLayer::setMinLevel(unsigned value) { @@ -83,18 +81,39 @@ XYZModelLayer::getMaxLevel() const { return options().maxLevel().get(); } -void -XYZModelLayer::setRangeFactor(float value) +void XYZModelLayer::init() { - options().rangeFactor() = value; + super::init(); } -float -XYZModelLayer::getRangeFactor() const +void XYZModelLayer::addedToMap(const Map* map) { - return options().rangeFactor().get(); -} + _readOptions = osgEarth::Registry::instance()->cloneOrCreateOptions(getReadOptions()); + _readOptions->setObjectCacheHint(osgDB::Options::CACHE_IMAGES); + + _statesetCache = new StateSetCache(); + + if (*options().useNVGL() == true && GLUtils::useNVGL() && !_textures.valid()) + { + _textures = new TextureArena(); + getOrCreateStateSet()->setAttribute(_textures, 1); + + // auto release requires that we install this update callback! + _textures->setAutoRelease(true); + getNode()->addUpdateCallback(new LambdaCallback<>([this](osg::NodeVisitor& nv) + { + _textures->update(nv); + return true; + })); + + getOrCreateStateSet()->setAttributeAndModes( + new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA), + osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); + } + + super::addedToMap(map); +} XYZModelLayer::~XYZModelLayer() { @@ -110,31 +129,6 @@ void XYZModelLayer::setProfile(const Profile* profile) } } -void -XYZModelLayer::init() -{ - super::init(); - - _root = new osg::Group(); - - // Assign the layer's state set to the root node: - _root->setStateSet(this->getOrCreateStateSet()); - - // Graph needs rebuilding - _graphDirty = true; - - // Depth sorting by default - getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); -} - -void XYZModelLayer::dirty() -{ - _graphDirty = true; - - // create the scene graph - create(); -} - Config XYZModelLayer::getConfig() const { @@ -142,12 +136,6 @@ XYZModelLayer::getConfig() const return conf; } -osg::Node* -XYZModelLayer::getNode() const -{ - return _root.get(); -} - Status XYZModelLayer::openImplementation() { @@ -160,73 +148,82 @@ XYZModelLayer::openImplementation() return Status::NoError; } -Status -XYZModelLayer::closeImplementation() +osg::ref_ptr +XYZModelLayer::createTileImplementation(const TileKey& key, ProgressCallback* progress) const { - _graphDirty = true; - return getStatus(); -} + OE_PROFILING_ZONE; + if (progress && progress->isCanceled()) + return nullptr; -void -XYZModelLayer::addedToMap(const Map* map) -{ - OE_TEST << LC << "addedToMap" << std::endl; - super::addedToMap(map); + NetworkMonitor::ScopedRequestLayer layerRequest(getName()); - _map = map; + unsigned x, y; + key.getTileXY(x, y); + unsigned cols = 0, rows = 0; + key.getProfile()->getNumTiles(key.getLevelOfDetail(), cols, rows); + unsigned inverted_y = rows - y - 1; - _graphDirty = true; + if (*options().invertY() == true) + { + y = inverted_y; + } - // re-create the graph if necessary. - create(); -} + std::string location = options().url()->full(); -void -XYZModelLayer::removedFromMap(const Map* map) -{ - super::removedFromMap(map); + // support OpenLayers template style: + replaceIn(location, "${x}", Stringify() << x); + replaceIn(location, "${y}", Stringify() << y); + replaceIn(location, "${-y}", Stringify() << inverted_y); + replaceIn(location, "${z}", Stringify() << key.getLevelOfDetail()); - if (_root.valid()) - { - osg::ref_ptr node = findTopMostNodeOfType(_root.get()); - if (node.valid()) node->setDone(); - _root->removeChildren(0, _root->getNumChildren()); - } -} -void -XYZModelLayer::create() -{ - OE_TEST << LC << "create" << std::endl; - - if (_graphDirty && _profile) - { - osg::ref_ptr xyzGraph = new XYZModelGraph(_map.get(), _profile.get(), *_options->url(), *_options->invertY(), getReadOptions()); - xyzGraph->setOwnerName(getName()); - xyzGraph->setAdditive(*_options->additive()); - xyzGraph->setMinLevel(*_options->minLevel()); - xyzGraph->setMaxLevel(*_options->maxLevel()); - xyzGraph->setRangeFactor(*_options->rangeFactor()); - xyzGraph->setSceneGraphCallbacks(getSceneGraphCallbacks()); - xyzGraph->setUseNVGL(options().useNVGL().get()); - xyzGraph->build(); - - _root->removeChildren(0, _root->getNumChildren()); - _root->addChild(xyzGraph.get()); - - // clear the dirty flag. - _graphDirty = false; - - setStatus(Status::OK()); - } -} + // failing that, legacy osgearth style: + replaceIn(location, "{x}", Stringify() << x); + replaceIn(location, "{y}", Stringify() << y); + replaceIn(location, "{-y}", Stringify() << inverted_y); + replaceIn(location, "{z}", Stringify() << key.getLevelOfDetail()); -osg::ref_ptr -XYZModelLayer::createTileImplementation(const TileKey& key, ProgressCallback* progress) const -{ - auto pager = osgEarth::findTopMostNodeOfType(_root.get()); - if (pager) - return pager->createNode(key, progress); - else - return {}; + URI myUri(location, options().url()->context()); + + osg::ref_ptr< osg::Node > node = myUri.readNode(_readOptions.get()).getNode(); + if (node.valid()) + { + if (_textures.valid()) + { + auto xform = findTopMostNodeOfType(node.get()); + + // Convert the geometry into chonks + ChonkFactory factory(_textures); + + factory.setGetOrCreateFunction( + ChonkFactory::getWeakTextureCacheFunction( + _texturesCache, _texturesCacheMutex)); + + osg::ref_ptr drawable = new ChonkDrawable(); + + if (xform) + { + for (unsigned i = 0; i < xform->getNumChildren(); ++i) + { + drawable->add(xform->getChild(i), factory); + } + xform->removeChildren(0, xform->getNumChildren()); + xform->addChild(drawable); + node = xform; + } + else + { + if (drawable->add(node.get(), factory)) + { + node = drawable; + } + } + } + else + { + osgEarth::Registry::shaderGenerator().run(node.get(), _statesetCache); + } + return node.release(); + } + return nullptr; } diff --git a/src/osgEarthCesium/TaskProcessor.cpp b/src/osgEarthCesium/TaskProcessor.cpp index 30f92120ce..7b9d5826de 100644 --- a/src/osgEarthCesium/TaskProcessor.cpp +++ b/src/osgEarthCesium/TaskProcessor.cpp @@ -21,6 +21,7 @@ */ #include "TaskProcessor" #include +#include using namespace osgEarth; using namespace osgEarth::Threading; @@ -51,7 +52,7 @@ void TaskProcessor::shutdown() void TaskProcessor::startTask(std::function f) { - auto task = [this, f](Cancelable&) { + auto task = [this, f]() { f(); return true; };