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

Commit

Permalink
Limit pitch based on edge insets. Fix max Z calculation in getProjMat…
Browse files Browse the repository at this point in the history
…rix.

As we don't want to show horizon, there is a need to limit max pitch based on edge insets.
The limit shouldn't be that bad, as to e.g. have 60 deg pitch, top - bottom insets should be less than 0.732 of screen height.

TransformState::getProjMatrix calculation of farZ was an aproximation. Replacing it with simpler, but precise calculation.

Related to: #15163
  • Loading branch information
astojilj committed Jul 23, 2019
1 parent 1aa4776 commit 89f93a5
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 14 deletions.
2 changes: 1 addition & 1 deletion include/mbgl/util/projection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class Projection {
return Point<double> {
util::LONGITUDE_MAX + latLng.longitude(),
util::LONGITUDE_MAX - util::RAD2DEG * std::log(std::tan(M_PI / 4 + latitude * M_PI / util::DEGREES_MAX))
} * worldSize / util::DEGREES_MAX;
} * (worldSize / util::DEGREES_MAX);
}
};

Expand Down
24 changes: 18 additions & 6 deletions src/mbgl/map/transform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand All @@ -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);
}

Expand Down Expand Up @@ -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 = {
Expand All @@ -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);
}

Expand Down Expand Up @@ -576,4 +578,14 @@ 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;
// See TransformState::fov description: fov = 2 * arctan((height / 2) / (height * 1.5)).
const double fovAboveCenter = std::atan((height * 0.5 + centerOffsetY) / (height * 1.5));
return M_PI * 0.5 - fovAboveCenter - 0.001; // 0.001 prevents parallel ground to viewport clipping plane.
}

} // namespace mbgl
4 changes: 4 additions & 0 deletions src/mbgl/map/transform.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ class Transform : private util::noncopyable {
std::function<void(double)>,
const Duration&);

// We don't want to show horizon: limit max pitch based on edge insets.
// e.g. for 60 deg pitch, top - bottom insets should be less than 0.732 of screen height.
double getMaxPitchForEdgeInsets(const EdgeInsets &insets) const;

TimePoint transitionStart;
Duration transitionDuration;
std::function<bool(const TimePoint)> transitionFrameFn;
Expand Down
13 changes: 6 additions & 7 deletions src/mbgl/map/transform_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,12 @@ void TransformState::getProjMatrix(mat4& projMatrix, uint16_t nearZ, bool aligne
// [width/2 + offset.x, 0] in Z units, using the law of sines.
// 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 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;

Expand All @@ -64,7 +63,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()) {
Expand Down

0 comments on commit 89f93a5

Please sign in to comment.