diff options
author | Aleksandar Stojiljkovic <aleksandar.stojiljkovic@mapbox.com> | 2019-07-23 17:19:52 +0300 |
---|---|---|
committer | Aleksandar Stojiljkovic <aleksandar.stojiljkovic@mapbox.com> | 2019-08-01 09:28:36 +0300 |
commit | 73d9f26d03810854c36a96b252885353f8ba81ce (patch) | |
tree | f7ed24fc8677192075fda78724c1a1a83da86acd /src/mbgl/map/transform.cpp | |
parent | 375c3131afcdcedb5a2dfbb19eec29625c44494d (diff) | |
download | qtlocation-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.cpp')
-rw-r--r-- | src/mbgl/map/transform.cpp | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp index a51d4dd4ff..e360150cc2 100644 --- a/src/mbgl/map/transform.cpp +++ b/src/mbgl/map/transform.cpp @@ -138,9 +138,6 @@ void Transform::easeTo(const CameraOptions& camera, const AnimationOptions& anim if (bearing != startBearing) { state.bearing = util::wrap(util::interpolate(startBearing, bearing, t), -M_PI, M_PI); } - if (pitch != startPitch) { - state.pitch = util::interpolate(startPitch, pitch, t); - } if (padding != startEdgeInsets) { // Interpolate edge insets state.edgeInsets = { @@ -150,6 +147,10 @@ void Transform::easeTo(const CameraOptions& camera, const AnimationOptions& anim util::interpolate(startEdgeInsets.right(), padding.right(), t) }; } + auto maxPitch = getMaxPitchForEdgeInsets(state.edgeInsets); + if (pitch != startPitch || maxPitch < startPitch) { + state.pitch = std::min(maxPitch, util::interpolate(startPitch, pitch, t)); + } }, duration); } @@ -302,9 +303,6 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima if (bearing != startBearing) { state.bearing = util::wrap(util::interpolate(startBearing, bearing, k), -M_PI, M_PI); } - if (pitch != startPitch) { - state.pitch = util::interpolate(startPitch, pitch, k); - } if (padding != startEdgeInsets) { // Interpolate edge insets state.edgeInsets = { @@ -314,6 +312,10 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima util::interpolate(startEdgeInsets.right(), padding.right(), us) }; } + auto maxPitch = getMaxPitchForEdgeInsets(state.edgeInsets); + if (pitch != startPitch || maxPitch < startPitch) { + state.pitch = std::min(maxPitch, util::interpolate(startPitch, pitch, k)); + } }, duration); } @@ -576,4 +578,21 @@ LatLng Transform::screenCoordinateToLatLng(const ScreenCoordinate& point, LatLng return state.screenCoordinateToLatLng(flippedPoint, wrapMode); } +double Transform::getMaxPitchForEdgeInsets(const EdgeInsets &insets) const +{ + double centerOffsetY = 0.5 * (insets.top() - insets.bottom()); // See TransformState::getCenterOffset. + + const auto height = state.size.height; + assert(height); + // For details, see description at https://github.com/mapbox/mapbox-gl-native/pull/15195 + // The definition of half of TransformState::fov with no inset, is: fov = arctan((height / 2) / (height * 1.5)). + // We use half of fov, as it is field of view above perspective center. + // With inset, this angle changes and tangentOfFovAboveCenterAngle = (h/2 + centerOffsetY) / (height * 1.5). + // 1.03 is a bit extra added to prevent parallel ground to viewport clipping plane. + const double tangentOfFovAboveCenterAngle = 1.03 * (height / 2.0 + centerOffsetY) / (1.5 * height); + const double fovAboveCenter = std::atan(tangentOfFovAboveCenterAngle); + return M_PI * 0.5 - fovAboveCenter; + // e.g. Maximum pitch of 60 degrees is when perspective center's offset from the top is 84% of screen height. +} + } // namespace mbgl |