diff options
author | Ansis Brammanis <ansis@mapbox.com> | 2017-11-02 09:37:56 -0400 |
---|---|---|
committer | Ansis Brammanis <ansis@mapbox.com> | 2017-11-02 09:53:34 -0400 |
commit | bdf9cf23ec197e8d83f9714b2336e4d17881d719 (patch) | |
tree | c837e7bae545b1880a69c03cbe42b1d82c922abd | |
parent | 6c575d0559c9b9304d88187e9518a873aaee7c55 (diff) | |
download | qtlocation-mapboxgl-bdf9cf23ec197e8d83f9714b2336e4d17881d719.tar.gz |
crosstile fading
-rw-r--r-- | src/mbgl/layout/symbol_instance.cpp | 1 | ||||
-rw-r--r-- | src/mbgl/layout/symbol_instance.hpp | 1 | ||||
-rw-r--r-- | src/mbgl/renderer/buckets/symbol_bucket.hpp | 2 | ||||
-rw-r--r-- | src/mbgl/renderer/renderer_impl.cpp | 8 | ||||
-rw-r--r-- | src/mbgl/renderer/renderer_impl.hpp | 2 | ||||
-rw-r--r-- | src/mbgl/text/cross_tile_symbol_index.cpp | 150 | ||||
-rw-r--r-- | src/mbgl/text/cross_tile_symbol_index.hpp | 31 | ||||
-rw-r--r-- | src/mbgl/text/placement.cpp | 7 | ||||
-rw-r--r-- | src/mbgl/text/placement.hpp | 1 |
9 files changed, 100 insertions, 103 deletions
diff --git a/src/mbgl/layout/symbol_instance.cpp b/src/mbgl/layout/symbol_instance.cpp index b396c05f4e..9e0c939da1 100644 --- a/src/mbgl/layout/symbol_instance.cpp +++ b/src/mbgl/layout/symbol_instance.cpp @@ -26,6 +26,7 @@ SymbolInstance::SymbolInstance(Anchor& anchor_, const std::size_t featureIndex_, const std::u16string& key_) : anchor(anchor_), + insideTileBoundaries(0 <= anchor.point.x && 0 <= anchor.point.y && anchor.point.x < util::EXTENT && anchor.point.y < util::EXTENT), line(line_), index(index_), hasText(shapedTextOrientations.first || shapedTextOrientations.second), diff --git a/src/mbgl/layout/symbol_instance.hpp b/src/mbgl/layout/symbol_instance.hpp index 231d1ca079..e8006e37b6 100644 --- a/src/mbgl/layout/symbol_instance.hpp +++ b/src/mbgl/layout/symbol_instance.hpp @@ -35,6 +35,7 @@ public: const std::u16string& key); Anchor anchor; + bool insideTileBoundaries; GeometryCoordinates line; uint32_t index; bool hasText; diff --git a/src/mbgl/renderer/buckets/symbol_bucket.hpp b/src/mbgl/renderer/buckets/symbol_bucket.hpp index 39d8dbf804..5fc3fae8a9 100644 --- a/src/mbgl/renderer/buckets/symbol_bucket.hpp +++ b/src/mbgl/renderer/buckets/symbol_bucket.hpp @@ -128,6 +128,8 @@ public: gl::IndexVector<gl::Triangles> triangles; optional<gl::IndexBuffer<gl::Triangles>> indexBuffer; } collisionCircle; + + uint32_t bucketInstanceId = 0; }; } // namespace mbgl diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index c8bf0f9739..2801fb5d90 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -23,6 +23,7 @@ #include <mbgl/style/source_impl.hpp> #include <mbgl/style/transition_options.hpp> #include <mbgl/text/glyph_manager.hpp> +#include <mbgl/text/cross_tile_symbol_index.hpp> #include <mbgl/tile/tile.hpp> #include <mbgl/util/math.hpp> #include <mbgl/util/string.hpp> @@ -57,6 +58,7 @@ Renderer::Impl::Impl(RendererBackend& backend_, , sourceImpls(makeMutable<std::vector<Immutable<style::Source::Impl>>>()) , layerImpls(makeMutable<std::vector<Immutable<style::Layer::Impl>>>()) , renderLight(makeMutable<Light::Impl>()) + , crossTileSymbolIndex(std::make_unique<CrossTileSymbolIndex>()) , placement(std::make_unique<Placement>(TransformState{}, MapMode::Still)) { glyphManager->setObserver(this); } @@ -364,6 +366,12 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) { order.emplace_back(RenderItem { *layer, source }); } + for (auto it = order.rbegin(); it != order.rend(); ++it) { + if (it->layer.is<RenderSymbolLayer>()) { + crossTileSymbolIndex->addLayer(*it->layer.as<RenderSymbolLayer>()); + } + } + auto newPlacement = std::make_unique<Placement>(parameters.state, parameters.mapMode); for (auto it = order.rbegin(); it != order.rend(); ++it) { if (it->layer.is<RenderSymbolLayer>()) { diff --git a/src/mbgl/renderer/renderer_impl.hpp b/src/mbgl/renderer/renderer_impl.hpp index e0252e748d..dc19e84995 100644 --- a/src/mbgl/renderer/renderer_impl.hpp +++ b/src/mbgl/renderer/renderer_impl.hpp @@ -31,6 +31,7 @@ class Scheduler; class GlyphManager; class ImageManager; class LineAtlas; +class CrossTileSymbolIndex; class Renderer::Impl : public GlyphManagerObserver, public RenderSourceObserver{ @@ -104,6 +105,7 @@ private: std::unordered_map<std::string, std::unique_ptr<RenderLayer>> renderLayers; RenderLight renderLight; + std::unique_ptr<CrossTileSymbolIndex> crossTileSymbolIndex; std::unique_ptr<Placement> placement; bool contextLost = false; diff --git a/src/mbgl/text/cross_tile_symbol_index.cpp b/src/mbgl/text/cross_tile_symbol_index.cpp index 8047eaec0d..316c3505dc 100644 --- a/src/mbgl/text/cross_tile_symbol_index.cpp +++ b/src/mbgl/text/cross_tile_symbol_index.cpp @@ -1,29 +1,22 @@ #include <mbgl/text/cross_tile_symbol_index.hpp> #include <mbgl/layout/symbol_instance.hpp> +#include <mbgl/renderer/buckets/symbol_bucket.hpp> +#include <mbgl/renderer/render_tile.hpp> +#include <mbgl/tile/tile.hpp> namespace mbgl { -TileLayerIndex::TileLayerIndex(OverscaledTileID coord_, std::shared_ptr<std::vector<SymbolInstance>> symbolInstances_) - : coord(coord_), symbolInstances(symbolInstances_) { - for (SymbolInstance& symbolInstance : *symbolInstances) { - if (indexedSymbolInstances.find(symbolInstance.key) == indexedSymbolInstances.end()) { - indexedSymbolInstances.emplace(symbolInstance.key, std::vector<IndexedSymbolInstance>()); +TileLayerIndex::TileLayerIndex(OverscaledTileID coord_, std::vector<SymbolInstance>& symbolInstances) + : coord(coord_) { + for (SymbolInstance& symbolInstance : symbolInstances) { + if (symbolInstance.insideTileBoundaries) { + indexedSymbolInstances[symbolInstance.key].emplace_back(symbolInstance.crossTileID, getScaledCoordinates(symbolInstance, coord)); } - - indexedSymbolInstances.at(symbolInstance.key).emplace_back(symbolInstance, getScaledCoordinates(symbolInstance, coord)); - - symbolInstance.isDuplicate = false; - // symbolInstance.isDuplicate = false; - // If we don't pick up an opacity from our parent or child tiles - // Reset so that symbols in cached tiles fade in the same - // way as freshly loaded tiles - //symbolInstance.textOpacityState = OpacityState(); - //symbolInstance.iconOpacityState = OpacityState(); } } -Point<double> TileLayerIndex::getScaledCoordinates(SymbolInstance& symbolInstance, OverscaledTileID& childTileCoord) { +Point<double> TileLayerIndex::getScaledCoordinates(SymbolInstance& symbolInstance, const OverscaledTileID& childTileCoord) { // Round anchor positions to roughly 4 pixel grid const double roundingFactor = 512.0 / util::EXTENT / 2.0; const double scale = roundingFactor / std::pow(2, childTileCoord.canonical.z - coord.canonical.z); @@ -33,28 +26,41 @@ Point<double> TileLayerIndex::getScaledCoordinates(SymbolInstance& symbolInstanc }; } -optional<SymbolInstance> TileLayerIndex::getMatchingSymbol(SymbolInstance& childTileSymbol, OverscaledTileID& childTileCoord) { - auto it = indexedSymbolInstances.find(childTileSymbol.key); - if (it == indexedSymbolInstances.end()) return {}; +void TileLayerIndex::findMatches(std::vector<SymbolInstance>& symbolInstances, const OverscaledTileID& newCoord) { + float tolerance = coord.canonical.z < newCoord.canonical.z ? 1 : std::pow(2, coord.canonical.z - newCoord.canonical.z); + tolerance = 100; + + for (auto& symbolInstance : symbolInstances) { + // already has a match, skip + if (symbolInstance.crossTileID) continue; + + auto it = indexedSymbolInstances.find(symbolInstance.key); + if (it == indexedSymbolInstances.end()) continue; - Point<double> childTileSymbolCoord = getScaledCoordinates(childTileSymbol, childTileCoord); + Point<double> scaledSymbolCoord = getScaledCoordinates(symbolInstance, newCoord); - for (IndexedSymbolInstance& thisTileSymbol: it->second) { - // Return any symbol with the same keys whose coordinates are within 1 - // grid unit. (with a 4px grid, this covers a 12px by 12px area) - if (std::fabs(thisTileSymbol.coord.x - childTileSymbolCoord.x) <= 1 && - std::fabs(thisTileSymbol.coord.y - childTileSymbolCoord.y) <= 1) { - return { thisTileSymbol.instance }; + for (IndexedSymbolInstance& thisTileSymbol: it->second) { + // Return any symbol with the same keys whose coordinates are within 1 + // grid unit. (with a 4px grid, this covers a 12px by 12px area) + if (std::fabs(thisTileSymbol.coord.x - scaledSymbolCoord.x) <= tolerance && + std::fabs(thisTileSymbol.coord.y - scaledSymbolCoord.y) <= tolerance) { + + symbolInstance.crossTileID = thisTileSymbol.crossTileID; + break; + } } } - - return {}; } CrossTileSymbolLayerIndex::CrossTileSymbolLayerIndex() { } -void CrossTileSymbolLayerIndex::addTile(const OverscaledTileID& coord, std::shared_ptr<std::vector<SymbolInstance>> symbolInstances) { +uint32_t CrossTileSymbolLayerIndex::maxCrossTileID = 0; + +void CrossTileSymbolLayerIndex::addBucket(const OverscaledTileID& coord, SymbolBucket& bucket) { + if (bucket.bucketInstanceId) return; + bucket.bucketInstanceId = ++maxBucketInstanceId; + uint8_t minZoom = 25; uint8_t maxZoom = 0; for (auto& it : indexes) { @@ -63,42 +69,42 @@ void CrossTileSymbolLayerIndex::addTile(const OverscaledTileID& coord, std::shar maxZoom = std::max(maxZoom, z); } - TileLayerIndex tileIndex(coord, symbolInstances); // make all higher-res child tiles block duplicate labels in this tile for (auto z = maxZoom; z > coord.overscaledZ; z--) { - auto zoomIndexes = indexes.find(coord.overscaledZ); + auto zoomIndexes = indexes.find(z); if (zoomIndexes != indexes.end()) { for (auto& childIndex : zoomIndexes->second) { if (!childIndex.second.coord.isChildOf(coord)) continue; - // Mark labels in this tile blocked, and don't copy opacity state - // into this tile - blockLabels(childIndex.second, tileIndex, false); + childIndex.second.findMatches(bucket.symbolInstances, coord); } } } // make this tile block duplicate labels in lower-res parent tiles - for (auto z = coord.overscaledZ - 1; z >= minZoom; z--) { + for (auto z = coord.overscaledZ; z >= minZoom; z--) { auto parentCoord = coord.scaledTo(z); auto zoomIndexes = indexes.find(z); if (zoomIndexes != indexes.end()) { auto parentIndex = zoomIndexes->second.find(parentCoord); if (parentIndex != zoomIndexes->second.end()) { - // Mark labels in the parent tile blocked, and copy opacity state - // into this tile - blockLabels(tileIndex, parentIndex->second, true); + parentIndex->second.findMatches(bucket.symbolInstances, coord); } } } - if (indexes.find(coord.overscaledZ) == indexes.end()) { - indexes.emplace(coord.overscaledZ, std::map<OverscaledTileID,TileLayerIndex>()); + for (auto& symbolInstance : bucket.symbolInstances) { + if (!symbolInstance.crossTileID && symbolInstance.insideTileBoundaries) { + // symbol did not match any known symbol, assign a new id + symbolInstance.crossTileID = ++maxCrossTileID; + } } - indexes.at(coord.overscaledZ).emplace(coord, std::move(tileIndex)); + TileLayerIndex tileIndex(coord, bucket.symbolInstances); + indexes[coord.overscaledZ].emplace(coord, std::move(tileIndex)); } +/* void CrossTileSymbolLayerIndex::removeTile(const OverscaledTileID& coord) { auto removedIndex = indexes.at(coord.overscaledZ).at(coord); @@ -125,51 +131,30 @@ void CrossTileSymbolLayerIndex::removeTile(const OverscaledTileID& coord) { indexes.erase(coord.overscaledZ); } } +*/ -void CrossTileSymbolLayerIndex::blockLabels(TileLayerIndex& childIndex, TileLayerIndex& parentIndex, bool copyParentOpacity) { - for (auto& symbolInstance : *childIndex.symbolInstances) { - // only non-duplicate labels can block other labels - if (!symbolInstance.isDuplicate) { - auto parentSymbolInstance = parentIndex.getMatchingSymbol(symbolInstance, childIndex.coord); - if (parentSymbolInstance) { - // if the parent label was previously non-duplicate, make it duplicate because it's now blocked - if (!parentSymbolInstance->isDuplicate) { - parentSymbolInstance->isDuplicate = true; - - // If the child label is the one being added to the index, - // copy the parent's opacity to the child - if (copyParentOpacity) { - //symbolInstance.textOpacityState = parentSymbolInstance->textOpacityState; - //symbolInstance.iconOpacityState = parentSymbolInstance->iconOpacityState; - } - } - } - } - } -} +CrossTileSymbolIndex::CrossTileSymbolIndex() {} -void CrossTileSymbolLayerIndex::unblockLabels(TileLayerIndex& childIndex, TileLayerIndex& parentIndex) { - assert(childIndex.coord.overscaledZ > parentIndex.coord.overscaledZ); - for (auto& symbolInstance : *childIndex.symbolInstances) { - // only non-duplicate labels were blocking other labels - if (!symbolInstance.isDuplicate) { - auto parentSymbolInstance = parentIndex.getMatchingSymbol(symbolInstance, childIndex.coord); - if (parentSymbolInstance) { - // this label is now unblocked, copy its opacity state - parentSymbolInstance->isDuplicate = false; - //parentSymbolInstance->textOpacityState = symbolInstance.textOpacityState; - //parentSymbolInstance->iconOpacityState = symbolInstance.iconOpacityState; - - // mark child as duplicate so that it doesn't unblock further tiles at lower res - // in the remaining calls to unblockLabels before it's fully removed - symbolInstance.isDuplicate = true; - } - } - } -} +void CrossTileSymbolIndex::addLayer(RenderSymbolLayer& symbolLayer) { -CrossTileSymbolIndex::CrossTileSymbolIndex() {} + auto& layerIndex = layerIndexes[symbolLayer.getID()]; + + for (RenderTile& renderTile : symbolLayer.renderTiles) { + if (!renderTile.tile.isRenderable()) { + continue; + } + + + + auto bucket = renderTile.tile.getBucket(*symbolLayer.baseImpl); + assert(dynamic_cast<SymbolBucket*>(bucket)); + SymbolBucket& symbolBucket = *reinterpret_cast<SymbolBucket*>(bucket); + + layerIndex.addBucket(renderTile.tile.id, symbolBucket); + } +} +/* void CrossTileSymbolIndex::addTileLayer(std::string& layerId, const OverscaledTileID& coord, std::shared_ptr<std::vector<SymbolInstance>> symbolInstances) { if (layerIndexes.find(layerId) == layerIndexes.end()) { layerIndexes.emplace(layerId, CrossTileSymbolLayerIndex()); @@ -185,4 +170,5 @@ void CrossTileSymbolIndex::removeTileLayer(std::string& layerId, const Overscale it->second.removeTile(coord); } } +*/ } // namespace mbgl diff --git a/src/mbgl/text/cross_tile_symbol_index.hpp b/src/mbgl/text/cross_tile_symbol_index.hpp index 6cb2ec8707..187149429b 100644 --- a/src/mbgl/text/cross_tile_symbol_index.hpp +++ b/src/mbgl/text/cross_tile_symbol_index.hpp @@ -13,45 +13,48 @@ namespace mbgl { class SymbolInstance; +class RenderSymbolLayer; +class SymbolBucket; + +class IndexEntry { + Point<float> anchorPoint; + +}; class IndexedSymbolInstance { public: - IndexedSymbolInstance(SymbolInstance& symbolInstance, Point<double> coord_) - : instance(symbolInstance), coord(std::move(coord_)) {}; - SymbolInstance& instance; + IndexedSymbolInstance(uint32_t crossTileID_, Point<double> coord_) + : crossTileID(crossTileID_), coord(coord_) {}; + uint32_t crossTileID; Point<double> coord; }; class TileLayerIndex { public: - TileLayerIndex(OverscaledTileID coord, std::shared_ptr<std::vector<SymbolInstance>>); + TileLayerIndex(OverscaledTileID coord, std::vector<SymbolInstance>&); - Point<double> getScaledCoordinates(SymbolInstance&, OverscaledTileID&); - optional<SymbolInstance> getMatchingSymbol(SymbolInstance& childTileSymbol, OverscaledTileID& childTileCoord); + Point<double> getScaledCoordinates(SymbolInstance&, const OverscaledTileID&); + void findMatches(std::vector<SymbolInstance>&, const OverscaledTileID&); OverscaledTileID coord; std::map<std::u16string,std::vector<IndexedSymbolInstance>> indexedSymbolInstances; - std::shared_ptr<std::vector<SymbolInstance>> symbolInstances; }; class CrossTileSymbolLayerIndex { public: CrossTileSymbolLayerIndex(); - - void addTile(const OverscaledTileID&, std::shared_ptr<std::vector<SymbolInstance>>); - void removeTile(const OverscaledTileID&); - void blockLabels(TileLayerIndex& childIndex, TileLayerIndex& parentIndex, bool copyParentOpacity); - void unblockLabels(TileLayerIndex& childIndex, TileLayerIndex& parentIndex); + void addBucket(const OverscaledTileID&, SymbolBucket&); private: std::map<uint8_t,std::map<OverscaledTileID,TileLayerIndex>> indexes; + uint32_t maxBucketInstanceId = 0; + static uint32_t maxCrossTileID; }; class CrossTileSymbolIndex { public: CrossTileSymbolIndex(); - void addTileLayer(std::string& layerId, const OverscaledTileID&, std::shared_ptr<std::vector<SymbolInstance>>); - void removeTileLayer(std::string& layerId, const OverscaledTileID&); + void addLayer(RenderSymbolLayer&); private: std::map<std::string,CrossTileSymbolLayerIndex> layerIndexes; }; diff --git a/src/mbgl/text/placement.cpp b/src/mbgl/text/placement.cpp index 8fdc26f49a..ca067e6227 100644 --- a/src/mbgl/text/placement.cpp +++ b/src/mbgl/text/placement.cpp @@ -30,8 +30,6 @@ bool JointOpacityState::isHidden() const { return icon.isHidden() && text.isHidden(); } -uint32_t Placement::maxCrossTileID = 0; - Placement::Placement(const TransformState& state_, MapMode mapMode_) : collisionIndex(state_) , state(state_) @@ -150,10 +148,7 @@ void Placement::placeLayerBucket( collisionIndex.insertFeature(symbolInstance.iconCollisionFeature, bucket.layout.get<IconIgnorePlacement>()); } - if (symbolInstance.crossTileID == 0) { - // TODO properly assign these - symbolInstance.crossTileID = ++maxCrossTileID; - } + assert(symbolInstance.crossTileID != 0); placements.emplace(symbolInstance.crossTileID, PlacementPair(placeText, placeIcon)); } diff --git a/src/mbgl/text/placement.hpp b/src/mbgl/text/placement.hpp index dee7c13dc7..40c46fd103 100644 --- a/src/mbgl/text/placement.hpp +++ b/src/mbgl/text/placement.hpp @@ -66,7 +66,6 @@ namespace mbgl { MapMode mapMode; TimePoint commitTime; - static uint32_t maxCrossTileID; // TODO remove std::unordered_map<uint32_t,PlacementPair> placements; std::unordered_map<uint32_t,JointOpacityState> opacities; }; |