Skip to content
This repository was archived by the owner on Aug 8, 2023. It is now read-only.

Commit 8e4bac0

Browse files
committed
[core] Tiles LOD: load and render based on zoom when displayed
Fixes #9037
1 parent 09fe0bb commit 8e4bac0

File tree

6 files changed

+68
-11
lines changed

6 files changed

+68
-11
lines changed

include/mbgl/util/constants.hpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,13 @@ constexpr double LATITUDE_MAX = 85.051128779806604;
3434
constexpr double LONGITUDE_MAX = 180;
3535
constexpr double DEGREES_MAX = 360;
3636
constexpr double PITCH_MIN = 0.0;
37-
constexpr double PITCH_MAX = M_PI / 3;
37+
/*
38+
* Max pitch is limited to 90 deg - TransformState::fov / 2, which evaluates to 71.5 deg, when
39+
* perspective center's offset is 0. When padding is used, and the perspective center moved from
40+
* center of the screen, max pitch is further capped by Transform::getMaxPitchForEdgeInsets.
41+
* We set the max to 70 to keep the limit constant with small padding.
42+
*/
43+
constexpr double PITCH_MAX = 70 * DEG2RAD;
3844
constexpr double MIN_ZOOM = 0.0;
3945
constexpr double MAX_ZOOM = 25.5;
4046
constexpr float MIN_ZOOM_F = MIN_ZOOM;

src/mbgl/map/transform_state.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,10 @@ double TransformState::pixel_y() const {
174174
return center + y;
175175
}
176176

177+
ScreenCoordinate TransformState::getCenterOffset() const {
178+
return { 0.5 * (edgeInsets.left() - edgeInsets.right()), 0.5 * (edgeInsets.top() - edgeInsets.bottom()) };
179+
}
180+
177181
#pragma mark - Zoom
178182

179183
double TransformState::getZoom() const {
@@ -373,10 +377,6 @@ void TransformState::constrain(double& scale_, double& x_, double& y_) const {
373377
}
374378
}
375379

376-
ScreenCoordinate TransformState::getCenterOffset() const {
377-
return { 0.5 * (edgeInsets.left() - edgeInsets.right()), 0.5 * (edgeInsets.top() - edgeInsets.bottom()) };
378-
}
379-
380380
void TransformState::moveLatLng(const LatLng& latLng, const ScreenCoordinate& anchor) {
381381
auto centerCoord = Projection::project(getLatLng(LatLng::Unwrapped), scale);
382382
auto latLngCoord = Projection::project(latLng, scale);

src/mbgl/map/transform_state.hpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ class TransformState {
4949
double pixel_x() const;
5050
double pixel_y() const;
5151

52+
// Viewport center offset, from [size.width / 2, size.height / 2], defined
53+
// by |edgeInsets| in screen coordinates, with top left origin.
54+
ScreenCoordinate getCenterOffset() const;
55+
5256
// Zoom
5357
double getZoom() const;
5458
uint8_t getIntegerZoom() const;
@@ -96,10 +100,6 @@ class TransformState {
96100
bool rotatedNorth() const;
97101
void constrain(double& scale, double& x, double& y) const;
98102

99-
// Viewport center offset, from [size.width / 2, size.height / 2], defined
100-
// by |edgeInsets| in screen coordinates, with top left origin.
101-
ScreenCoordinate getCenterOffset() const;
102-
103103
LatLngBounds bounds;
104104

105105
// Limit the amount of zooming possible on the map.

src/mbgl/renderer/tile_pyramid.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,11 @@ void TilePyramid::update(const std::vector<Immutable<style::LayerProperties>>& l
106106
}
107107

108108
if (panZoom < idealZoom) {
109-
panTiles = util::tileCover(parameters.transformState, panZoom);
109+
panTiles = util::tileCoverWithLOD(parameters.transformState, panZoom, zoomRange.min);
110110
}
111111
}
112112

113-
idealTiles = util::tileCover(parameters.transformState, idealZoom);
113+
idealTiles = util::tileCoverWithLOD(parameters.transformState, idealZoom, zoomRange.min);
114114
}
115115

116116
// Stores a list of all the tiles that we're definitely going to retain. There are two

src/mbgl/util/tile_cover.cpp

+50
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,56 @@ std::vector<UnwrappedTileID> tileCover(const TransformState& state, int32_t z) {
173173
z);
174174
}
175175

176+
std::vector<UnwrappedTileID> tileCoverWithLOD(const TransformState& state, int32_t z, int32_t minZ) {
177+
assert(state.valid());
178+
179+
const double w = state.getSize().width;
180+
const double h = state.getSize().height;
181+
182+
const auto offset = state.getCenterOffset();
183+
constexpr double zoomDiff = 1.0;
184+
constexpr double coefLOD[] = {
185+
0.5 * zoomDiff / (zoomDiff + 1),
186+
0.5 * (zoomDiff + 1) / (zoomDiff + 2),
187+
0.5 * (zoomDiff + 2) / (zoomDiff + 3)
188+
};
189+
// Tangens of field of view above center.
190+
const double tanFov = (h * 0.5 + offset.y) / (1.5 * h);
191+
192+
std::vector<UnwrappedTileID> result;
193+
double top = 0.0;
194+
double bottom = 0.0;
195+
196+
for (size_t i = 0; top < h && i <= std::extent<decltype(coefLOD)>::value; i++, z--) {
197+
if (z == minZ || i == std::extent<decltype(coefLOD)>::value) {
198+
top = h; // final pass, get all to the top.
199+
} else {
200+
const double treshold = state.getPitch() ? h * coefLOD[i] / (tanFov * std::tan(state.getPitch())) : 0.0;
201+
top = std::min(h, treshold + h * 0.5 - offset.y);
202+
}
203+
std::vector<UnwrappedTileID> cover = tileCover(
204+
TileCoordinate::fromScreenCoordinate(state, z, { 0, top }).p,
205+
TileCoordinate::fromScreenCoordinate(state, z, { w, top }).p,
206+
TileCoordinate::fromScreenCoordinate(state, z, { w, bottom }).p,
207+
TileCoordinate::fromScreenCoordinate(state, z, { 0, bottom }).p,
208+
TileCoordinate::fromScreenCoordinate(state, z, { w/2, h/2 }).p,
209+
z);
210+
bottom = top;
211+
if (i == 0) {
212+
if (top == h) {
213+
return cover;
214+
}
215+
std::swap(result, cover);
216+
continue;
217+
}
218+
result.insert(
219+
result.end(),
220+
std::make_move_iterator(cover.begin()),
221+
std::make_move_iterator(cover.end()));
222+
}
223+
return result;
224+
}
225+
176226
std::vector<UnwrappedTileID> tileCover(const Geometry<double>& geometry, int32_t z) {
177227
std::vector<UnwrappedTileID> result;
178228
TileCover tc(geometry, z, true);

src/mbgl/util/tile_cover.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class TileCover {
3434
int32_t coveringZoomLevel(double z, style::SourceType type, uint16_t tileSize);
3535

3636
std::vector<UnwrappedTileID> tileCover(const TransformState&, int32_t z);
37+
std::vector<UnwrappedTileID> tileCoverWithLOD(const TransformState&, int32_t z, int32_t minZLOD);
3738
std::vector<UnwrappedTileID> tileCover(const LatLngBounds&, int32_t z);
3839
std::vector<UnwrappedTileID> tileCover(const Geometry<double>&, int32_t z);
3940

0 commit comments

Comments
 (0)