summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mbgl/tile/tile_id.hpp9
-rw-r--r--src/mbgl/renderer/render_tile.hpp2
-rw-r--r--src/mbgl/renderer/tile_pyramid.cpp40
-rw-r--r--src/mbgl/renderer/tile_pyramid.hpp4
-rw-r--r--src/mbgl/tile/tile.hpp2
5 files changed, 53 insertions, 4 deletions
diff --git a/include/mbgl/tile/tile_id.hpp b/include/mbgl/tile/tile_id.hpp
index 3b52596f6c..dd2fba573d 100644
--- a/include/mbgl/tile/tile_id.hpp
+++ b/include/mbgl/tile/tile_id.hpp
@@ -85,9 +85,10 @@ public:
std::array<UnwrappedTileID, 4> children() const;
OverscaledTileID overscaleTo(uint8_t z) const;
float pixelsToTileUnits(float pixelValue, float zoom) const;
+ UnwrappedTileID unwrapTo(int16_t wrap);
- const int16_t wrap;
- const CanonicalTileID canonical;
+ int16_t wrap;
+ CanonicalTileID canonical;
};
::std::ostream& operator<<(::std::ostream& os, const UnwrappedTileID& rhs);
@@ -220,6 +221,10 @@ inline bool UnwrappedTileID::operator<(const UnwrappedTileID& rhs) const {
return std::tie(wrap, canonical) < std::tie(rhs.wrap, rhs.canonical);
}
+inline UnwrappedTileID UnwrappedTileID::unwrapTo(int16_t newWrap) {
+ return { newWrap, canonical };
+}
+
inline bool UnwrappedTileID::isChildOf(const UnwrappedTileID& parent) const {
return wrap == parent.wrap && canonical.isChildOf(parent.canonical);
}
diff --git a/src/mbgl/renderer/render_tile.hpp b/src/mbgl/renderer/render_tile.hpp
index 3db02393d2..bfa695586c 100644
--- a/src/mbgl/renderer/render_tile.hpp
+++ b/src/mbgl/renderer/render_tile.hpp
@@ -22,7 +22,7 @@ public:
RenderTile& operator=(const RenderTile&) = delete;
RenderTile& operator=(RenderTile&&) = default;
- const UnwrappedTileID id;
+ UnwrappedTileID id;
Tile& tile;
ClipID clip;
mat4 matrix;
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,
diff --git a/src/mbgl/renderer/tile_pyramid.hpp b/src/mbgl/renderer/tile_pyramid.hpp
index 0cef9e2c40..4e5f50fd52 100644
--- a/src/mbgl/renderer/tile_pyramid.hpp
+++ b/src/mbgl/renderer/tile_pyramid.hpp
@@ -49,6 +49,8 @@ public:
std::vector<std::reference_wrapper<RenderTile>> getRenderTiles();
Tile* getTile(const OverscaledTileID&);
+ void handleWrapJump(float lng);
+
std::unordered_map<std::string, std::vector<Feature>>
queryRenderedFeatures(const ScreenLineString& geometry,
const TransformState& transformState,
@@ -72,6 +74,8 @@ public:
std::vector<RenderTile> renderTiles;
TileObserver* observer = nullptr;
+
+ float prevLng = 0;
};
} // namespace mbgl
diff --git a/src/mbgl/tile/tile.hpp b/src/mbgl/tile/tile.hpp
index 23d6864205..2182ec722f 100644
--- a/src/mbgl/tile/tile.hpp
+++ b/src/mbgl/tile/tile.hpp
@@ -113,7 +113,7 @@ public:
void dumpDebugLogs() const;
- const OverscaledTileID id;
+ OverscaledTileID id;
optional<Timestamp> modified;
optional<Timestamp> expires;