summaryrefslogtreecommitdiff
path: root/src/mbgl/map/transform_state.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/map/transform_state.cpp')
-rw-r--r--src/mbgl/map/transform_state.cpp42
1 files changed, 24 insertions, 18 deletions
diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp
index 596ed05195..f1d45c043c 100644
--- a/src/mbgl/map/transform_state.cpp
+++ b/src/mbgl/map/transform_state.cpp
@@ -33,24 +33,36 @@ void TransformState::getProjMatrix(mat4& projMatrix, uint16_t nearZ, bool aligne
return;
}
- // Find the distance from the center point [width/2, height/2] to the
- // center top point [width/2, 0] in Z units, using the law of sines.
+ 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.
// 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 halfFov = getFieldOfView() / 2.0;
+ const double fovAboveCenter = getFieldOfView() * (0.5 + offset.y / size.height);
const double groundAngle = M_PI / 2.0 + getPitch();
- const double topHalfSurfaceDistance = std::sin(halfFov) * getCameraToCenterDistance() / std::sin(M_PI - groundAngle - halfFov);
+ const double aboveCenterSurfaceDistance = std::sin(fovAboveCenter) * cameraToCenterDistance / std::sin(M_PI - groundAngle - fovAboveCenter);
// Calculate z distance of the farthest fragment that should be rendered.
- const double furthestDistance = std::cos(M_PI / 2 - getPitch()) * topHalfSurfaceDistance + getCameraToCenterDistance();
+ const double furthestDistance = std::cos(M_PI / 2 - getPitch()) * aboveCenterSurfaceDistance + cameraToCenterDistance;
// Add a bit extra to avoid precision problems when a fragment's distance is exactly `furthestDistance`
const double farZ = furthestDistance * 1.01;
matrix::perspective(projMatrix, getFieldOfView(), double(size.width) / size.height, nearZ, farZ);
+ // Move the center of perspective to center of specified edgeInsets.
+ // Values are in range [-1, 1] where the upper and lower range values
+ // position viewport center to the screen edges. This is overriden
+ // if using axonometric perspective (not in public API yet, Issue #11882).
+ // TODO(astojilj): Issue #11882 should take edge insets into account, too.
+ projMatrix[8] = -offset.x * 2.0 / size.width;
+ projMatrix[9] = offset.y * 2.0 / size.height;
+
const bool flippedY = viewportMode == ViewportMode::FlippedY;
- matrix::scale(projMatrix, projMatrix, 1, flippedY ? 1 : -1, 1);
+ matrix::scale(projMatrix, projMatrix, 1.0, flippedY ? 1 : -1, 1);
matrix::translate(projMatrix, projMatrix, 0, 0, -getCameraToCenterDistance());
@@ -134,16 +146,8 @@ ViewportMode TransformState::getViewportMode() const {
#pragma mark - Camera options
CameraOptions TransformState::getCameraOptions(const EdgeInsets& padding) const {
- LatLng center;
- if (padding.isFlush()) {
- center = getLatLng();
- } else {
- ScreenCoordinate point = padding.getCenter(size.width, size.height);
- point.y = size.height - point.y;
- center = screenCoordinateToLatLng(point).wrapped();
- }
return CameraOptions()
- .withCenter(center)
+ .withCenter(getLatLng())
.withPadding(padding)
.withZoom(getZoom())
.withBearing(-bearing * util::RAD2DEG)
@@ -222,6 +226,10 @@ double TransformState::getMaxZoom() const {
return scaleZoom(max_scale);
}
+ScreenCoordinate TransformState::getCenterOffset() const {
+ return { 0.5 * (edgeInsets.left() - edgeInsets.right()), 0.5 * (edgeInsets.top() - edgeInsets.bottom()) };
+}
+
#pragma mark - Rotation
float TransformState::getBearing() const {
@@ -240,7 +248,6 @@ float TransformState::getPitch() const {
return pitch;
}
-
#pragma mark - State
bool TransformState::isChanging() const {
@@ -328,8 +335,7 @@ LatLng TransformState::screenCoordinateToLatLng(const ScreenCoordinate& point, L
mat4 TransformState::coordinatePointMatrix() const {
mat4 proj;
getProjMatrix(proj);
- float s = util::tileSize;
- matrix::scale(proj, proj, s, s, 1);
+ matrix::scale(proj, proj, util::tileSize, util::tileSize, 1);
matrix::multiply(proj, getPixelMatrix(), proj);
return proj;
}