diff options
author | Mikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com> | 2020-01-20 16:55:57 +0200 |
---|---|---|
committer | Mikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com> | 2020-01-22 14:30:26 +0200 |
commit | a9d04d7b1ad1ac070f45a3367bec24e9cd4ef074 (patch) | |
tree | 961e547f49eec7b3a60241deb4ccaf10734a5bc8 /src/mbgl/text | |
parent | 4dac2f61c244b6ac3859510e21b2c80c83f25841 (diff) | |
download | qtlocation-mapboxgl-a9d04d7b1ad1ac070f45a3367bec24e9cd4ef074.tar.gz |
[core] Do not index and place the off-screen symbols for overscaled tiles
For overscaled tiles the viewport might be showing only a small part of the
tile, so we filter out the off-screen symbols to improve the performance.
Diffstat (limited to 'src/mbgl/text')
-rw-r--r-- | src/mbgl/text/cross_tile_symbol_index.cpp | 44 | ||||
-rw-r--r-- | src/mbgl/text/cross_tile_symbol_index.hpp | 5 | ||||
-rw-r--r-- | src/mbgl/text/placement.cpp | 11 |
3 files changed, 47 insertions, 13 deletions
diff --git a/src/mbgl/text/cross_tile_symbol_index.cpp b/src/mbgl/text/cross_tile_symbol_index.cpp index 5b9d6ae69c..f806c652e1 100644 --- a/src/mbgl/text/cross_tile_symbol_index.cpp +++ b/src/mbgl/text/cross_tile_symbol_index.cpp @@ -12,6 +12,7 @@ TileLayerIndex::TileLayerIndex(OverscaledTileID coord_, std::string bucketLeaderId_) : coord(coord_), bucketInstanceId(bucketInstanceId_), bucketLeaderId(std::move(bucketLeaderId_)) { for (SymbolInstance& symbolInstance : symbolInstances) { + if (symbolInstance.crossTileID == SymbolInstance::invalidCrossTileID()) continue; indexedSymbolInstances[symbolInstance.key].emplace_back(symbolInstance.crossTileID, getScaledCoordinates(symbolInstance, coord)); } @@ -95,11 +96,29 @@ void CrossTileSymbolLayerIndex::handleWrapJump(float newLng) { lng = newLng; } -bool CrossTileSymbolLayerIndex::addBucket(const OverscaledTileID& tileID, SymbolBucket& bucket) { +namespace { + +bool isInVewport(const mat4& posMatrix, const Point<float>& point) { + vec4 p = {{point.x, point.y, 0, 1}}; + matrix::transformMat4(p, p, posMatrix); + + // buffer covers area of the next zoom level (current zoom - 1 covered area). + constexpr float buffer = 1.0f; + constexpr float edge = 1.0f + buffer; + float x = p[0] / p[3]; + float y = p[1] / p[3]; + return (x > -edge && y > -edge && x < edge && y < edge); +} + +} // namespace + +bool CrossTileSymbolLayerIndex::addBucket(const OverscaledTileID& tileID, + const mat4& tileMatrix, + SymbolBucket& bucket) { auto& thisZoomIndexes = indexes[tileID.overscaledZ]; auto previousIndex = thisZoomIndexes.find(tileID); if (previousIndex != thisZoomIndexes.end()) { - if (previousIndex->second.bucketInstanceId == bucket.bucketInstanceId) { + if (previousIndex->second.bucketInstanceId == bucket.bucketInstanceId && !bucket.hasUninitializedSymbols) { return false; } else { // We're replacing this bucket with an updated version @@ -110,8 +129,23 @@ bool CrossTileSymbolLayerIndex::addBucket(const OverscaledTileID& tileID, Symbol } } - for (auto& symbolInstance: bucket.symbolInstances) { - symbolInstance.crossTileID = 0; + bucket.hasUninitializedSymbols = false; + + if (tileID.overscaleFactor() > 1u) { + // For overscaled tiles the viewport might be showing only a small part of the tile, + // so we filter out the off-screen symbols to improve the performance. + for (auto& symbolInstance : bucket.symbolInstances) { + if (isInVewport(tileMatrix, symbolInstance.anchor.point)) { + symbolInstance.crossTileID = 0u; + } else { + symbolInstance.crossTileID = SymbolInstance::invalidCrossTileID(); + bucket.hasUninitializedSymbols = true; + } + } + } else { + for (auto& symbolInstance : bucket.symbolInstances) { + symbolInstance.crossTileID = 0u; + } } auto& thisZoomUsedCrossTileIDs = usedCrossTileIDs[tileID.overscaledZ]; @@ -195,7 +229,7 @@ auto CrossTileSymbolIndex::addLayer(const RenderLayer& layer, float lng) -> AddL for (const auto& item : layer.getPlacementData()) { const RenderTile& renderTile = item.tile; Bucket& bucket = item.bucket; - auto pair = bucket.registerAtCrossTileIndex(layerIndex, renderTile.getOverscaledTileID()); + auto pair = bucket.registerAtCrossTileIndex(layerIndex, renderTile); assert(pair.first != 0u); if (pair.second) result |= AddLayerResult::BucketsAdded; currentBucketIDs.insert(pair.first); diff --git a/src/mbgl/text/cross_tile_symbol_index.hpp b/src/mbgl/text/cross_tile_symbol_index.hpp index 3b7c367726..8dfdb8466f 100644 --- a/src/mbgl/text/cross_tile_symbol_index.hpp +++ b/src/mbgl/text/cross_tile_symbol_index.hpp @@ -2,8 +2,9 @@ #include <mbgl/tile/tile_id.hpp> #include <mbgl/util/bitmask_operations.hpp> -#include <mbgl/util/geometry.hpp> #include <mbgl/util/constants.hpp> +#include <mbgl/util/geometry.hpp> +#include <mbgl/util/mat4.hpp> #include <mbgl/util/optional.hpp> #include <map> @@ -48,7 +49,7 @@ public: class CrossTileSymbolLayerIndex { public: CrossTileSymbolLayerIndex(uint32_t& maxCrossTileID); - bool addBucket(const OverscaledTileID&, SymbolBucket&); + bool addBucket(const OverscaledTileID&, const mat4& tileMatrix, SymbolBucket&); bool removeStaleBuckets(const std::unordered_set<uint32_t>& currentIDs); void handleWrapJump(float newLng); private: diff --git a/src/mbgl/text/placement.cpp b/src/mbgl/text/placement.cpp index 43d9713717..32edf679e8 100644 --- a/src/mbgl/text/placement.cpp +++ b/src/mbgl/text/placement.cpp @@ -157,10 +157,7 @@ void Placement::placeBucket(const SymbolBucket& bucket, const bool rotateIconWithMap = layout.get<style::IconRotationAlignment>() == style::AlignmentType::Map; const bool pitchIconWithMap = layout.get<style::IconPitchAlignment>() == style::AlignmentType::Map; - mat4 posMatrix; - const auto& projMatrix = state.getProjectionMatrix(); - state.matrixFor(posMatrix, renderTile.id); - matrix::multiply(posMatrix, projMatrix, posMatrix); + const mat4& posMatrix = renderTile.matrix; mat4 textLabelPlaneMatrix = getLabelPlaneMatrix(posMatrix, pitchTextWithMap, rotateTextWithMap, state, pixelsToTileUnits); @@ -212,8 +209,10 @@ void Placement::placeBucket(const SymbolBucket& bucket, std::vector<ProjectedCollisionBox> textBoxes; std::vector<ProjectedCollisionBox> iconBoxes; - auto placeSymbol = [&] (const SymbolInstance& symbolInstance) { - if (seenCrossTileIDs.count(symbolInstance.crossTileID) != 0u) return; + auto placeSymbol = [&](const SymbolInstance& symbolInstance) { + if (symbolInstance.crossTileID == SymbolInstance::invalidCrossTileID() || + seenCrossTileIDs.count(symbolInstance.crossTileID) != 0u) + return; if (renderTile.holdForFade()) { // Mark all symbols from this tile as "not placed", but don't add to seenCrossTileIDs, because we don't |