summaryrefslogtreecommitdiff
path: root/src/mbgl/text
diff options
context:
space:
mode:
authorMikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com>2020-01-20 16:55:57 +0200
committerMikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com>2020-01-22 14:30:26 +0200
commita9d04d7b1ad1ac070f45a3367bec24e9cd4ef074 (patch)
tree961e547f49eec7b3a60241deb4ccaf10734a5bc8 /src/mbgl/text
parent4dac2f61c244b6ac3859510e21b2c80c83f25841 (diff)
downloadqtlocation-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.cpp44
-rw-r--r--src/mbgl/text/cross_tile_symbol_index.hpp5
-rw-r--r--src/mbgl/text/placement.cpp11
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