diff options
Diffstat (limited to 'src/mbgl/map/transform_state.cpp')
-rw-r--r-- | src/mbgl/map/transform_state.cpp | 42 |
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; } |