summaryrefslogtreecommitdiff
path: root/src/mbgl/map/transform_state.cpp
diff options
context:
space:
mode:
authorAleksandar Stojiljkovic <aleksandar.stojiljkovic@mapbox.com>2019-07-23 17:19:52 +0300
committerAleksandar Stojiljkovic <aleksandar.stojiljkovic@mapbox.com>2019-08-01 09:28:36 +0300
commit73d9f26d03810854c36a96b252885353f8ba81ce (patch)
treef7ed24fc8677192075fda78724c1a1a83da86acd /src/mbgl/map/transform_state.cpp
parent375c3131afcdcedb5a2dfbb19eec29625c44494d (diff)
downloadqtlocation-mapboxgl-73d9f26d03810854c36a96b252885353f8ba81ce.tar.gz
[core] Limit pitch based on edge insets. Fix max Z calculation in getProjMatrix.
Patch partly fixes #15163 in a way that it doesn't allow loading tens of thousands of tiles and attempt to show area above horizon: Limit pitch based on edge insets. It is not too bad - current limit of 60 degrees stays active until center of perspective is moved towards the bottom, to 84% of screen height. The plan is to split removal of 60 degrees limit to follow up patch. Fix max Z calculation in getProjMatrix. TransformState::getProjMatrix calculation of farZ was complex with possibility to lead to negative z values. Replacing it with simpler, precise calculation: furthestDistance = cameraToCenterDistance / (1 - tanFovAboveCenter * std::tan(getPitch())); TransformState::getProjMatrix calculation of farZ was an aproximation. Replacing it with simpler, but precise calculation. Related to: #15163
Diffstat (limited to 'src/mbgl/map/transform_state.cpp')
-rw-r--r--src/mbgl/map/transform_state.cpp20
1 files changed, 10 insertions, 10 deletions
diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp
index 92c02d0bc7..77309a2a55 100644
--- a/src/mbgl/map/transform_state.cpp
+++ b/src/mbgl/map/transform_state.cpp
@@ -36,18 +36,18 @@ void TransformState::getProjMatrix(mat4& projMatrix, uint16_t nearZ, bool aligne
const double cameraToCenterDistance = getCameraToCenterDistance();
auto offset = getCenterOffset();
- // Find the distance from the viewport center point
- // [width/2 + offset.x, height/2 + offset.y] to the top edge, to point
- // [width/2 + offset.x, 0] in Z units, using the law of sines.
+ // Find the Z distance from the viewport center point
+ // [width/2 + offset.x, height/2 + offset.y] to the top edge; to point
+ // [width/2 + offset.x, 0] in Z units.
// 1 Z unit is equivalent to 1 horizontal px at the center of the map
// (the distance between[width/2, height/2] and [width/2 + 1, height/2])
- const double fovAboveCenter = getFieldOfView() * (0.5 + offset.y / size.height);
- const double groundAngle = M_PI / 2.0 + getPitch();
- const double aboveCenterSurfaceDistance = std::sin(fovAboveCenter) * cameraToCenterDistance / std::sin(M_PI - groundAngle - fovAboveCenter);
-
-
+ // See https://github.com/mapbox/mapbox-gl-native/pull/15195 for details.
+ // See TransformState::fov description: fov = 2 * arctan((height / 2) / (height * 1.5)).
+ const double tanFovAboveCenter = (size.height * 0.5 + offset.y) / (size.height * 1.5);
+ const double tanMultiple = tanFovAboveCenter * std::tan(getPitch());
+ assert(tanMultiple < 1);
// Calculate z distance of the farthest fragment that should be rendered.
- const double furthestDistance = std::cos(M_PI / 2 - getPitch()) * aboveCenterSurfaceDistance + cameraToCenterDistance;
+ const double furthestDistance = cameraToCenterDistance / (1 - tanMultiple);
// Add a bit extra to avoid precision problems when a fragment's distance is exactly `furthestDistance`
const double farZ = furthestDistance * 1.01;
@@ -64,7 +64,7 @@ void TransformState::getProjMatrix(mat4& projMatrix, uint16_t nearZ, bool aligne
const bool flippedY = viewportMode == ViewportMode::FlippedY;
matrix::scale(projMatrix, projMatrix, 1.0, flippedY ? 1 : -1, 1);
- matrix::translate(projMatrix, projMatrix, 0, 0, -getCameraToCenterDistance());
+ matrix::translate(projMatrix, projMatrix, 0, 0, -cameraToCenterDistance);
using NO = NorthOrientation;
switch (getNorthOrientation()) {