diff options
-rw-r--r-- | include/mbgl/tile/tile_id.hpp | 9 | ||||
-rw-r--r-- | src/mbgl/renderer/render_tile.hpp | 2 | ||||
-rw-r--r-- | src/mbgl/renderer/tile_pyramid.cpp | 40 | ||||
-rw-r--r-- | src/mbgl/renderer/tile_pyramid.hpp | 4 | ||||
-rw-r--r-- | src/mbgl/tile/tile.hpp | 2 |
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; |