summaryrefslogtreecommitdiff
path: root/src/mbgl/renderer/tile_pyramid.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/renderer/tile_pyramid.cpp')
-rw-r--r--src/mbgl/renderer/tile_pyramid.cpp40
1 files changed, 40 insertions, 0 deletions
diff --git a/src/mbgl/renderer/tile_pyramid.cpp b/src/mbgl/renderer/tile_pyramid.cpp
index d28e95181b..fd4356ca02 100644
--- a/src/mbgl/renderer/tile_pyramid.cpp
+++ b/src/mbgl/renderer/tile_pyramid.cpp
@@ -90,6 +90,8 @@ void TilePyramid::update(const std::vector<Immutable<style::Layer::Impl>>& layer
return;
}
+ handleWrapJump(parameters.transformState.getLatLng().longitude());
+
// Determine the overzooming/underzooming amounts and required tiles.
int32_t overscaledZoom = util::coveringZoomLevel(parameters.transformState.getZoom(), type, tileSize);
int32_t tileZoom = overscaledZoom;
@@ -238,6 +240,44 @@ void TilePyramid::update(const std::vector<Immutable<style::Layer::Impl>>& layer
}
}
+void TilePyramid::handleWrapJump(float lng) {
+ // On top of the regular z/x/y values, TileIDs have a `wrap` value that specify
+ // which cppy of the world the tile belongs to. For example, at `lng: 10` you
+ // might render z/x/y/0 while at `lng: 370` you would render z/x/y/1.
+ //
+ // When lng values get wrapped (going from `lng: 370` to `long: 10`) you expect
+ // to see the same thing on the screen (370 degrees and 10 degrees is the same
+ // place in the world) but all the TileIDs will have different wrap values.
+ //
+ // In order to make this transition seamless, we calculate the rounded difference of
+ // "worlds" between the last frame and the current frame. If the map panned by
+ // a world, then we can assign all the tiles new TileIDs with updated wrap values.
+ // For example, assign z/x/y/1 a new id: z/x/y/0. It is the same tile, just rendered
+ // in a different position.
+ //
+ // This enables us to reuse the tiles at more ideal locations and prevent flickering.
+
+ const float lngDifference = lng - prevLng;
+ const float worldDifference = lngDifference / 360;
+ const int wrapDelta = ::round(worldDifference);
+ prevLng = lng;
+
+ if (wrapDelta) {
+ std::map<OverscaledTileID, std::unique_ptr<Tile>> newTiles;
+ for (auto& tile : tiles) {
+ auto newID = tile.second->id.unwrapTo(tile.second->id.wrap + wrapDelta);
+ tile.second->id = newID;
+ newTiles.emplace(newID, std::move(tile.second));
+ }
+ tiles = std::move(newTiles);
+
+ for (auto& renderTile : renderTiles) {
+ renderTile.id = renderTile.id.unwrapTo(renderTile.id.wrap + wrapDelta);
+ }
+ }
+}
+
+
std::unordered_map<std::string, std::vector<Feature>> TilePyramid::queryRenderedFeatures(const ScreenLineString& geometry,
const TransformState& transformState,
const std::vector<const RenderLayer*>& layers,