From 8d22e2bf017c1442a15b1fbe404dff77fb21e8fc Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Fri, 14 Aug 2015 12:41:18 +0300 Subject: [PATCH] port perspective projection matrix from -js --- src/mbgl/map/transform_state.cpp | 21 ++++++++++----------- src/mbgl/map/transform_state.hpp | 11 ++++++++--- src/mbgl/renderer/gl_config.hpp | 1 + src/mbgl/renderer/painter.cpp | 23 +++++++++++++++++++++-- 4 files changed, 40 insertions(+), 16 deletions(-) diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp index 9a5e53092..1cb1d9f82 100644 --- a/src/mbgl/map/transform_state.cpp +++ b/src/mbgl/map/transform_state.cpp @@ -10,19 +10,11 @@ using namespace mbgl; void TransformState::matrixFor(mat4& matrix, const TileID& id, const int8_t z) const { const double tile_scale = std::pow(2, z); - const double tile_size = scale * util::tileSize / tile_scale; + double s = util::tileSize * scale / tile_scale; matrix::identity(matrix); - - matrix::translate(matrix, matrix, 0.5f * (float)width, 0.5f * (float)height, 0); - matrix::rotate_z(matrix, matrix, angle); - matrix::translate(matrix, matrix, -0.5f * (float)width, -0.5f * (float)height, 0); - - matrix::translate(matrix, matrix, pixel_x() + id.x * tile_size, pixel_y() + id.y * tile_size, 0); - - // TODO: Get rid of the 8 (scaling from 4096 to tile size); - float factor = scale / tile_scale / (4096.0f / util::tileSize); - matrix::scale(matrix, matrix, factor, factor, 1); + matrix::translate(matrix, matrix, id.x * s, id.y * s, 0); + matrix::scale(matrix, matrix, s / 4096.0f, s / 4096.0f, 1); } box TransformState::cornersToBox(uint32_t z) const { @@ -154,6 +146,13 @@ float TransformState::getAngle() const { return angle; } +float TransformState::getAltitude() const { + return altitude; +} + +float TransformState::getPitch() const { + return pitch; +} #pragma mark - Projection diff --git a/src/mbgl/map/transform_state.hpp b/src/mbgl/map/transform_state.hpp index 16f2de2f7..3996e6e54 100644 --- a/src/mbgl/map/transform_state.hpp +++ b/src/mbgl/map/transform_state.hpp @@ -49,6 +49,9 @@ public: // Rotation float getAngle() const; + float getAltitude() const; + float getPitch() const; + // Projection const vec2 pixelForLatLng(const LatLng latLng) const; const LatLng latLngForPixel(const vec2 pixel) const; @@ -56,6 +59,9 @@ public: // Changing bool isChanging() const; + double pixel_x() const; + double pixel_y() const; + private: void constrain(double& scale, double& y) const; @@ -63,9 +69,6 @@ private: double min_scale = std::pow(2, 0); double max_scale = std::pow(2, 18); - double pixel_x() const; - double pixel_y() const; - // logical dimensions uint16_t width = 0, height = 0; @@ -80,6 +83,8 @@ private: double x = 0, y = 0; double angle = 0; double scale = 1; + double altitude = 1.5; + double pitch = 0; // cache values for spherical mercator math double Bc = (scale * util::tileSize) / 360; diff --git a/src/mbgl/renderer/gl_config.hpp b/src/mbgl/renderer/gl_config.hpp index 59507f721..2389293a4 100644 --- a/src/mbgl/renderer/gl_config.hpp +++ b/src/mbgl/renderer/gl_config.hpp @@ -117,6 +117,7 @@ struct DepthTest { static const Type Default; inline static void Set(const Type& value) { MBGL_CHECK_ERROR(value ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST)); + MBGL_CHECK_ERROR(glDisable(GL_DEPTH_TEST)); } }; diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index b55b71dcb..4b5503bcc 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -132,8 +132,27 @@ void Painter::lineWidth(float line_width) { } void Painter::changeMatrix() { - // Initialize projection matrix - matrix::ortho(projMatrix, 0, state.getWidth(), state.getHeight(), 0, -1, 1); + + double halfFov = std::atan(0.5 / state.getAltitude()); + double topHalfSurfaceDistance = std::sin(halfFov) * state.getAltitude() / + std::sin(M_PI / 2.0f - state.getPitch() - halfFov); + // Calculate z value of the farthest fragment that should be rendered. + double farZ = std::cos(M_PI / 2.0f - state.getPitch()) * topHalfSurfaceDistance + state.getAltitude(); + + matrix::perspective(projMatrix, 2.0f * std::atan((state.getHeight() / 2.0f) / state.getAltitude()), + double(state.getWidth()) / state.getHeight(), 0.1, farZ); + + matrix::translate(projMatrix, projMatrix, 0, 0, -state.getAltitude()); + + // After the rotateX, z values are in pixel units. Convert them to + // altitude unites. 1 altitude unit = the screen height. + matrix::scale(projMatrix, projMatrix, 1, -1, 1.0f / state.getHeight()); + + matrix::rotate_x(projMatrix, projMatrix, state.getPitch()); + matrix::rotate_z(projMatrix, projMatrix, state.getAngle()); + + matrix::translate(projMatrix, projMatrix, state.pixel_x() - state.getWidth() / 2.0f, + state.pixel_y() - state.getWidth() / 2.0f, 0); // The extrusion matrix. matrix::identity(extrudeMatrix);