[core] re-assign ids when lng jumps to avoid flicker
This commit is contained in:
committed by
Ansis Brammanis
parent
5e36f669ac
commit
ba07c873aa
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -113,7 +113,7 @@ public:
|
||||
|
||||
void dumpDebugLogs() const;
|
||||
|
||||
const OverscaledTileID id;
|
||||
OverscaledTileID id;
|
||||
optional<Timestamp> modified;
|
||||
optional<Timestamp> expires;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user