From 4fdffa4e8a2e0253a3da31f6445750192bb3d022 Mon Sep 17 00:00:00 2001 From: Erlend Fagerheim Date: Thu, 13 Aug 2015 13:29:13 +0200 Subject: [PATCH 01/41] added click, longclick, scroll, fling events --- .../com/mapbox/mapboxgl/views/MapView.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java index 20e7dfe56..8c9a9f5b8 100644 --- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java @@ -154,6 +154,24 @@ public class MapView extends FrameLayout implements LocationListener { // Used to manage Event Listeners private ArrayList mOnMapChangedListener; + public interface OnFlingListener { + void onFling(); + } + + public interface OnScrollListener { + void onScroll(); + } + + private OnFlingListener onFlingListener; + private OnScrollListener onScrollListener; + + public void setOnScrollListener(OnScrollListener onScrollListener) { + this.onScrollListener = onScrollListener; + } + + public void setOnFlingListener(OnFlingListener onFlingListener) { + this.onFlingListener = onFlingListener; + } // // Properties @@ -865,6 +883,8 @@ public class MapView extends FrameLayout implements LocationListener { // Cancel any animation mNativeMapView.cancelTransitions(); + performClick(); + return true; } @@ -878,6 +898,7 @@ public class MapView extends FrameLayout implements LocationListener { @Override public void onLongPress(MotionEvent e) { // TODO + performLongClick(); } // Called for flings @@ -905,6 +926,10 @@ public class MapView extends FrameLayout implements LocationListener { mNativeMapView.moveBy(velocityX * duration / 2.0 / mScreenDensity, velocityY * duration / 2.0 / mScreenDensity, (long) (duration * 1000.0f)); + if(onFlingListener != null){ + onFlingListener.onFling(); + } + return true; } @@ -922,6 +947,11 @@ public class MapView extends FrameLayout implements LocationListener { // Scroll the map mNativeMapView.moveBy(-distanceX / mScreenDensity, -distanceY / mScreenDensity); + + if(onScrollListener != null){ + onScrollListener.onScroll(); + } + return true; } } From 86b560e83c4495450a62031539bde84d457f18f4 Mon Sep 17 00:00:00 2001 From: tobrunvannuland Date: Sun, 23 Aug 2015 14:44:19 +0200 Subject: [PATCH 02/41] correction path to JAVA_HOME (Added /Contents/Home --- INSTALL.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index ac5bb8667..72e23f097 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -274,8 +274,8 @@ By default, the SDK will be installed to `/usr/local/opt/android-sdk`. If you op echo "export ANDROID_HOME=`brew --prefix android-sdk`" >> .bash_profile echo "export ANDROID_NDK_PATH=`brew --cellar android-ndk`/r10e" >> .bash_profile - # Replace with something like /Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk - echo "export JAVA_HOME=" >> .bash_profile + # Replace with something like /Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home + echo "export JAVA_HOME=" >> .bash_profile echo "export STUDIO_JDK=$JAVA_HOME" >> .bash_profile Run: From 5636eb86c1b2e5fe9c8533fd795b4dfd107bdd30 Mon Sep 17 00:00:00 2001 From: tobrunvannuland Date: Sun, 23 Aug 2015 14:46:41 +0200 Subject: [PATCH 03/41] Replaced name outdated menu item of Android Studio --- INSTALL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INSTALL.md b/INSTALL.md index 72e23f097..669aba3f9 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -283,7 +283,7 @@ Run: make android open -a Android\ Studio -You can then open `android/java` in Android Studio via "Import Non-Android Studio Project". +You can then open `android/java` in Android Studio via "import project (Eclipse ADT, Gradle, etc.)". ### Setting up Android emulator From d5139107123b3cadcce2c80d4aea0ed3a6256683 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Thu, 13 Aug 2015 15:34:08 +0300 Subject: [PATCH 04/41] port mat4.perspective and mat4.rotate_x --- include/mbgl/util/mat4.hpp | 2 ++ src/mbgl/util/mat4.cpp | 55 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/include/mbgl/util/mat4.hpp b/include/mbgl/util/mat4.hpp index 4279113d2..e59712ed0 100644 --- a/include/mbgl/util/mat4.hpp +++ b/include/mbgl/util/mat4.hpp @@ -33,8 +33,10 @@ namespace matrix { void identity(mat4& out); void ortho(mat4& out, float left, float right, float bottom, float top, float near, float far); +void perspective(mat4& out, float fovy, float aspect, float near, float far); void copy(mat4& out, const mat4& a); void translate(mat4& out, const mat4& a, float x, float y, float z); +void rotate_x(mat4& out, const mat4& a, float rad); void rotate_z(mat4& out, const mat4& a, float rad); void scale(mat4& out, const mat4& a, float x, float y, float z); void multiply(mat4& out, const mat4& a, const mat4& b); diff --git a/src/mbgl/util/mat4.cpp b/src/mbgl/util/mat4.cpp index cabd8e284..d48558dc2 100644 --- a/src/mbgl/util/mat4.cpp +++ b/src/mbgl/util/mat4.cpp @@ -67,6 +67,27 @@ void matrix::ortho(mat4& out, float left, float right, float bottom, float top, out[15] = 1.0f; } +void matrix::perspective(mat4& out, float fovy, float aspect, float near, float far) { + float f = 1.0f / std::tan(fovy / 2.0f), + nf = 1.0f / (near - far); + out[0] = f / aspect; + out[1] = 0.0f; + out[2] = 0.0f; + out[3] = 0.0f; + out[4] = 0.0f; + out[5] = f; + out[6] = 0.0f; + out[7] = 0.0f; + out[8] = 0.0f; + out[9] = 0.0f; + out[10] = (far + near) * nf; + out[11] = -1.0f; + out[12] = 0.0f; + out[13] = 0.0f; + out[14] = (2.0f * far * near) * nf; + out[15] = 0.0f; +} + void matrix::copy(mat4& out, const mat4& a) { out[0] = a[0]; out[1] = a[1]; @@ -112,6 +133,40 @@ void matrix::translate(mat4& out, const mat4& a, float x, float y, float z) { } } +void matrix::rotate_x(mat4& out, const mat4& a, float rad) { + float s = std::sin(rad), + c = std::cos(rad), + a10 = a[4], + a11 = a[5], + a12 = a[6], + a13 = a[7], + a20 = a[8], + a21 = a[9], + a22 = a[10], + a23 = a[11]; + + if (&a != &out) { // If the source and destination differ, copy the unchanged rows + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + } + + // Perform axis-specific matrix multiplication + out[4] = a10 * c + a20 * s; + out[5] = a11 * c + a21 * s; + out[6] = a12 * c + a22 * s; + out[7] = a13 * c + a23 * s; + out[8] = a20 * c - a10 * s; + out[9] = a21 * c - a11 * s; + out[10] = a22 * c - a12 * s; + out[11] = a23 * c - a13 * s; +} + void matrix::rotate_z(mat4& out, const mat4& a, float rad) { float s = std::sin(rad), c = std::cos(rad), From 8d22e2bf017c1442a15b1fbe404dff77fb21e8fc Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Fri, 14 Aug 2015 12:41:18 +0300 Subject: [PATCH 05/41] 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); From 2535e669e2397003d9edb10f2fe3c9645a8551c1 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Fri, 14 Aug 2015 13:27:59 +0300 Subject: [PATCH 06/41] hacks to see stuff --- src/mbgl/map/transform_state.hpp | 2 +- src/mbgl/renderer/gl_config.hpp | 2 +- src/mbgl/shader/plain.vertex.glsl | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mbgl/map/transform_state.hpp b/src/mbgl/map/transform_state.hpp index 3996e6e54..92e2fb809 100644 --- a/src/mbgl/map/transform_state.hpp +++ b/src/mbgl/map/transform_state.hpp @@ -84,7 +84,7 @@ private: double angle = 0; double scale = 1; double altitude = 1.5; - double pitch = 0; + double pitch = 0.001; // 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 2389293a4..b2a2dcb2a 100644 --- a/src/mbgl/renderer/gl_config.hpp +++ b/src/mbgl/renderer/gl_config.hpp @@ -117,7 +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)); + //MBGL_CHECK_ERROR(glDisable(GL_DEPTH_TEST)); } }; diff --git a/src/mbgl/shader/plain.vertex.glsl b/src/mbgl/shader/plain.vertex.glsl index 866c3cd2f..7ccbed12b 100644 --- a/src/mbgl/shader/plain.vertex.glsl +++ b/src/mbgl/shader/plain.vertex.glsl @@ -4,4 +4,5 @@ uniform mat4 u_matrix; void main() { gl_Position = u_matrix * vec4(a_pos, 0, 1); + gl_Position.z = 1.0; } From f0885d36ffac6c5260ab5694cf435946641c47a1 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Fri, 14 Aug 2015 16:13:47 +0300 Subject: [PATCH 07/41] port mat2 from gl-matrix --- src/mbgl/util/mat2.cpp | 52 ++++++++++++++++++++++++++++++++++++++++++ src/mbgl/util/mat2.hpp | 41 +++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 src/mbgl/util/mat2.cpp create mode 100644 src/mbgl/util/mat2.hpp diff --git a/src/mbgl/util/mat2.cpp b/src/mbgl/util/mat2.cpp new file mode 100644 index 000000000..05900d166 --- /dev/null +++ b/src/mbgl/util/mat2.cpp @@ -0,0 +1,52 @@ +// This is an incomplete port of http://glmatrix.net/ +// +// Copyright (c) 2013 Brandon Jones, Colin MacKenzie IV +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the +// use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not claim +// that you wrote the original software. If you use this software in a +// product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. + +#include + +#include + +using namespace mbgl; + +void matrix::identity(mat2& out) { + out[0] = 1.0f; + out[1] = 0.0f; + out[2] = 0.0f; + out[3] = 1.0f; +} + +void matrix::rotate(mat2& out, const mat2& a, float rad) { + float a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], + s = std::sin(rad), + c = std::cos(rad); + out[0] = a0 * c + a2 * s; + out[1] = a1 * c + a3 * s; + out[2] = a0 * -s + a2 * c; + out[3] = a1 * -s + a3 * c; +}; + +void matrix::scale(mat2& out, const mat2& a, float v0, float v1) { + float a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3]; + out[0] = a0 * v0; + out[1] = a1 * v0; + out[2] = a2 * v1; + out[3] = a3 * v1; +} diff --git a/src/mbgl/util/mat2.hpp b/src/mbgl/util/mat2.hpp new file mode 100644 index 000000000..59110bf90 --- /dev/null +++ b/src/mbgl/util/mat2.hpp @@ -0,0 +1,41 @@ +// This is an incomplete port of http://glmatrix.net/ +// +// Copyright (c) 2013 Brandon Jones, Colin MacKenzie IV +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the +// use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not claim +// that you wrote the original software. If you use this software in a +// product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. + +#ifndef MBGL_UTIL_MAT2 +#define MBGL_UTIL_MAT2 + +#include + +namespace mbgl { + +typedef std::array mat2; + +namespace matrix { + +void identity(mat2& out); +void rotate(mat2& out, const mat2& a, float rad); +void scale(mat2& out, const mat2& a, float v0, float v1); + +} +} + +#endif From 3027f8c0aacc81ee82776d98971b49987ba1ba99 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Fri, 14 Aug 2015 16:53:31 +0300 Subject: [PATCH 08/41] port line rendering fixes for perspective views --- src/mbgl/renderer/painter_line.cpp | 22 +++++++++++++++++++--- src/mbgl/shader/line.fragment.glsl | 4 +++- src/mbgl/shader/line.vertex.glsl | 21 ++++++++++++++++----- src/mbgl/shader/line_shader.hpp | 2 ++ src/mbgl/shader/linepattern.vertex.glsl | 2 +- src/mbgl/shader/linesdf.vertex.glsl | 2 +- 6 files changed, 42 insertions(+), 11 deletions(-) diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp index f406c0d8f..cf586c05e 100644 --- a/src/mbgl/renderer/painter_line.cpp +++ b/src/mbgl/renderer/painter_line.cpp @@ -11,6 +11,7 @@ #include #include #include +#include using namespace mbgl; @@ -51,6 +52,19 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const color[2] *= properties.opacity; color[3] *= properties.opacity; + float ratio = state.getScale() / std::pow(2, id.z) / 8.0 * id.overscaling; + + mat2 antialiasingMatrix; + matrix::identity(antialiasingMatrix); + matrix::scale(antialiasingMatrix, antialiasingMatrix, 1.0, std::cos(state.getPitch())); + matrix::rotate(antialiasingMatrix, antialiasingMatrix, state.getAngle()); + + // calculate how much longer the real world distance is at the top of the screen + // than at the middle of the screen. + float topedgelength = std::sqrt(std::pow(state.getHeight(), 2) / 4 * (1 + std::pow(state.getAltitude(), 2))); + float x = state.getHeight() / 2.0f * std::tan(state.getPitch()); + float extra = (topedgelength + x) / topedgelength - 1; + mat4 vtxMatrix = translatedMatrix(matrix, properties.translate, id, properties.translateAnchor); config.depthRange = { strata, 1.0f }; @@ -62,7 +76,7 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const linesdfShader->u_matrix = vtxMatrix; linesdfShader->u_exmatrix = extrudeMatrix; linesdfShader->u_linewidth = {{ outset, inset }}; - linesdfShader->u_ratio = data.pixelRatio; + linesdfShader->u_ratio = ratio; linesdfShader->u_blur = blur; linesdfShader->u_color = color; @@ -97,7 +111,7 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const linepatternShader->u_matrix = vtxMatrix; linepatternShader->u_exmatrix = extrudeMatrix; linepatternShader->u_linewidth = {{ outset, inset }}; - linepatternShader->u_ratio = data.pixelRatio; + linepatternShader->u_ratio = ratio; linepatternShader->u_blur = blur; linepatternShader->u_pattern_size_a = {{imagePosA.size[0] * factor * properties.image.fromScale, imagePosA.size[1]}}; @@ -121,8 +135,10 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const lineShader->u_matrix = vtxMatrix; lineShader->u_exmatrix = extrudeMatrix; lineShader->u_linewidth = {{ outset, inset }}; - lineShader->u_ratio = data.pixelRatio; + lineShader->u_ratio = ratio; lineShader->u_blur = blur; + lineShader->u_extra = extra; + lineShader->u_antialiasingmatrix = antialiasingMatrix; lineShader->u_color = color; diff --git a/src/mbgl/shader/line.fragment.glsl b/src/mbgl/shader/line.fragment.glsl index 717c46e10..e0ef64996 100644 --- a/src/mbgl/shader/line.fragment.glsl +++ b/src/mbgl/shader/line.fragment.glsl @@ -3,6 +3,7 @@ uniform vec4 u_color; uniform float u_blur; varying vec2 v_normal; +varying float v_gamma_scale; void main() { // Calculate the distance of the pixel from the line in pixels. @@ -11,7 +12,8 @@ void main() { // Calculate the antialiasing fade factor. This is either when fading in // the line in case of an offset line (v_linewidth.t) or when fading out // (v_linewidth.s) - float alpha = clamp(min(dist - (u_linewidth.t - u_blur), u_linewidth.s - dist) / u_blur, 0.0, 1.0); + float blur = u_blur * v_gamma_scale; + float alpha = clamp(min(dist - (u_linewidth.t - blur), u_linewidth.s - dist) / blur, 0.0, 1.0); gl_FragColor = u_color * alpha; } diff --git a/src/mbgl/shader/line.vertex.glsl b/src/mbgl/shader/line.vertex.glsl index 1f5432991..f818565cc 100644 --- a/src/mbgl/shader/line.vertex.glsl +++ b/src/mbgl/shader/line.vertex.glsl @@ -9,17 +9,17 @@ attribute vec2 a_pos; attribute vec4 a_data; -// matrix is for the vertex position, exmatrix is for rotating and projecting -// the extrusion vector. uniform mat4 u_matrix; -uniform mat4 u_exmatrix; // shared uniform float u_ratio; uniform vec2 u_linewidth; -uniform vec4 u_color; + +uniform float u_extra; +uniform mat2 u_antialiasingmatrix; varying vec2 v_normal; +varying float v_gamma_scale; void main() { vec2 a_extrude = a_data.xy; @@ -40,5 +40,16 @@ void main() { // model/view matrix. Add the extrusion vector *after* the model/view matrix // because we're extruding the line in pixel space, regardless of the current // tile's zoom level. - gl_Position = u_matrix * vec4(floor(a_pos * 0.5), 0.0, 1.0) + u_exmatrix * dist; + gl_Position = u_matrix * vec4(floor(a_pos * 0.5) + dist.xy / u_ratio, 0.0, 1.0); + + // position of y on the screen + float y = gl_Position.y / gl_Position.w; + + // how much features are squished in the y direction by the tilt + float squish_scale = length(a_extrude) / length(u_antialiasingmatrix * a_extrude); + + // how much features are squished in all directions by the perspectiveness + float perspective_scale = 1.0 / (1.0 - y * u_extra); + + v_gamma_scale = perspective_scale * squish_scale; } diff --git a/src/mbgl/shader/line_shader.hpp b/src/mbgl/shader/line_shader.hpp index 85152d6e0..0572cac88 100644 --- a/src/mbgl/shader/line_shader.hpp +++ b/src/mbgl/shader/line_shader.hpp @@ -18,6 +18,8 @@ public: Uniform> u_linewidth = {"u_linewidth", *this}; Uniform u_ratio = {"u_ratio", *this}; Uniform u_blur = {"u_blur", *this}; + Uniform u_extra = {"u_extra", *this}; + UniformMatrix<2> u_antialiasingmatrix = {"u_antialiasingmatrix", *this}; private: int32_t a_pos = -1; diff --git a/src/mbgl/shader/linepattern.vertex.glsl b/src/mbgl/shader/linepattern.vertex.glsl index ada384a3d..47d551e2e 100644 --- a/src/mbgl/shader/linepattern.vertex.glsl +++ b/src/mbgl/shader/linepattern.vertex.glsl @@ -52,7 +52,7 @@ void main() { // model/view matrix. Add the extrusion vector *after* the model/view matrix // because we're extruding the line in pixel space, regardless of the current // tile's zoom level. - gl_Position = u_matrix * vec4(floor(a_pos / 2.0), 0.0, 1.0) + u_exmatrix * vec4(dist, z, 0.0); + gl_Position = u_matrix * vec4(floor(a_pos / 2.0) + dist.xy / u_ratio, 0.0, 1.0); v_linesofar = a_linesofar;// * u_ratio; diff --git a/src/mbgl/shader/linesdf.vertex.glsl b/src/mbgl/shader/linesdf.vertex.glsl index 7f246ced6..6529fb45c 100644 --- a/src/mbgl/shader/linesdf.vertex.glsl +++ b/src/mbgl/shader/linesdf.vertex.glsl @@ -46,7 +46,7 @@ void main() { // model/view matrix. Add the extrusion vector *after* the model/view matrix // because we're extruding the line in pixel space, regardless of the current // tile's zoom level. - gl_Position = u_matrix * vec4(floor(a_pos * 0.5), 0.0, 1.0) + u_exmatrix * dist; + gl_Position = u_matrix * vec4(floor(a_pos * 0.5) + dist.xy / u_ratio, 0.0, 1.0); v_tex_a = vec2(a_linesofar * u_patternscale_a.x, normal.y * u_patternscale_a.y + u_tex_y_a); v_tex_b = vec2(a_linesofar * u_patternscale_b.x, normal.y * u_patternscale_b.y + u_tex_y_b); From be36ce01983a97dc24125abf97258a6a0a9baa4d Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Fri, 14 Aug 2015 17:14:51 +0300 Subject: [PATCH 09/41] fix fill antialiasing for perspective views --- src/mbgl/shader/outline.vertex.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mbgl/shader/outline.vertex.glsl b/src/mbgl/shader/outline.vertex.glsl index 29c16e3de..f720b8d62 100644 --- a/src/mbgl/shader/outline.vertex.glsl +++ b/src/mbgl/shader/outline.vertex.glsl @@ -6,5 +6,5 @@ varying vec2 v_pos; void main() { gl_Position = u_matrix * vec4(a_pos, 0, 1); - v_pos = (gl_Position.xy + 1.0) / 2.0 * u_world; + v_pos = (gl_Position.xy / gl_Position.w + 1.0) / 2.0 * u_world; } From 494489f9a06b538b900c2da5286ead4ab95805f1 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Fri, 14 Aug 2015 18:06:14 +0300 Subject: [PATCH 10/41] fix symbol rendering in perspective view --- src/mbgl/renderer/painter.cpp | 4 +- src/mbgl/renderer/painter_symbol.cpp | 59 ++++++++++++++++++++++------ src/mbgl/shader/icon.vertex.glsl | 12 +++++- src/mbgl/shader/icon_shader.hpp | 2 + src/mbgl/shader/sdf.fragment.glsl | 4 +- src/mbgl/shader/sdf.vertex.glsl | 18 ++++++++- src/mbgl/shader/sdf_shader.hpp | 2 + 7 files changed, 82 insertions(+), 19 deletions(-) diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index 4b5503bcc..7f06b2345 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -155,9 +155,7 @@ void Painter::changeMatrix() { state.pixel_y() - state.getWidth() / 2.0f, 0); // The extrusion matrix. - matrix::identity(extrudeMatrix); - matrix::multiply(extrudeMatrix, projMatrix, extrudeMatrix); - matrix::rotate_z(extrudeMatrix, extrudeMatrix, state.getAngle()); + matrix::ortho(extrudeMatrix, 0, state.getWidth(), state.getHeight(), 0, 0, -1); // The native matrix is a 1:1 matrix that paints the coordinates at the // same screen position as the vertex specifies. diff --git a/src/mbgl/renderer/painter_symbol.cpp b/src/mbgl/renderer/painter_symbol.cpp index 5c2db7709..c64f32620 100644 --- a/src/mbgl/renderer/painter_symbol.cpp +++ b/src/mbgl/renderer/painter_symbol.cpp @@ -28,25 +28,40 @@ void Painter::renderSDF(SymbolBucket &bucket, { mat4 vtxMatrix = translatedMatrix(matrix, styleProperties.translate, id, styleProperties.translate_anchor); - mat4 exMatrix; - matrix::copy(exMatrix, projMatrix); - bool aligned_with_map = (bucketProperties.rotation_alignment == RotationAlignmentType::Map); - const float angleOffset = aligned_with_map ? state.getAngle() : 0; + bool skewed = aligned_with_map; + mat4 exMatrix; + float s; + float gammaScale; - if (angleOffset) { - matrix::rotate_z(exMatrix, exMatrix, angleOffset); + if (skewed) { + matrix::identity(exMatrix); + s = 4096.0f / util::tileSize / id.overscaling / std::pow(2, state.getZoom() - id.z); + gammaScale = 1.0f / std::cos(state.getPitch()); + } else { + exMatrix = extrudeMatrix; + s = state.getAltitude(); + gammaScale = 1.0f; } + matrix::scale(exMatrix, exMatrix, s, s, 1); // If layerStyle.size > bucket.info.fontSize then labels may collide float fontSize = styleProperties.size; float fontScale = fontSize / sdfFontSize; matrix::scale(exMatrix, exMatrix, fontScale, fontScale, 1.0f); + // calculate how much longer the real world distance is at the top of the screen + // than at the middle of the screen. + float topedgelength = std::sqrt(std::pow(state.getHeight(), 2) / 4.0f * (1.0f + std::pow(state.getAltitude(), 2))); + float x = state.getHeight() / 2.0f * std::tan(state.getPitch()); + float extra = (topedgelength + x) / topedgelength - 1; + useProgram(sdfShader.program); sdfShader.u_matrix = vtxMatrix; sdfShader.u_exmatrix = exMatrix; sdfShader.u_texsize = texsize; + sdfShader.u_skewed = skewed; + sdfShader.u_extra = extra; // adjust min/max zooms for variable font sies float zoomAdjust = std::log(fontSize / bucketProperties.size) / std::log(2); @@ -70,7 +85,7 @@ void Painter::renderSDF(SymbolBucket &bucket, // We're drawing in the translucent pass which is bottom-to-top, so we need // to draw the halo first. if (styleProperties.halo_color[3] > 0.0f && styleProperties.halo_width > 0.0f) { - sdfShader.u_gamma = styleProperties.halo_blur * blurOffset / fontScale / sdfPx + gamma; + sdfShader.u_gamma = (styleProperties.halo_blur * blurOffset / fontScale / sdfPx + gamma) * gammaScale; if (styleProperties.opacity < 1.0f) { Color color = styleProperties.halo_color; @@ -91,7 +106,7 @@ void Painter::renderSDF(SymbolBucket &bucket, // Then, we draw the text/icon over the halo if (styleProperties.color[3] > 0.0f) { - sdfShader.u_gamma = gamma; + sdfShader.u_gamma = gamma * gammaScale; if (styleProperties.opacity < 1.0f) { Color color = styleProperties.color; @@ -120,7 +135,6 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c const auto &properties = layer_desc.getProperties(); const auto &layout = bucket.layout; - config.depthTest = true; config.depthMask = GL_FALSE; if (bucket.hasCollisionBoxData()) { @@ -150,6 +164,8 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c config.stencilTest = drawAcrossEdges ? false : true; if (bucket.hasIconData()) { + config.depthTest = layout.icon.rotation_alignment == RotationAlignmentType::Map; + bool sdf = bucket.sdfIcons; const float angleOffset = @@ -160,7 +176,8 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c const float fontSize = properties.icon.size; const float fontScale = fontSize / 1.0f; - spriteAtlas->bind(state.isChanging() || layout.placement == PlacementType::Line || angleOffset != 0 || fontScale != 1 || sdf); + spriteAtlas->bind(state.isChanging() || layout.placement == PlacementType::Line + || angleOffset != 0 || fontScale != 1 || sdf || state.getPitch() != 0); if (sdf) { renderSDF(bucket, @@ -175,19 +192,33 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c } else { mat4 vtxMatrix = translatedMatrix(matrix, properties.icon.translate, id, properties.icon.translate_anchor); + bool skewed = layout.icon.rotation_alignment == RotationAlignmentType::Map; mat4 exMatrix; - matrix::copy(exMatrix, projMatrix); + float s; - if (angleOffset) { - matrix::rotate_z(exMatrix, exMatrix, angleOffset); + if (skewed) { + matrix::identity(exMatrix); + s = 4096.0f / util::tileSize / id.overscaling / std::pow(2, state.getZoom() - id.z); + } else { + exMatrix = extrudeMatrix; + s = state.getAltitude(); } + matrix::scale(exMatrix, exMatrix, s, s, 1); matrix::scale(exMatrix, exMatrix, fontScale, fontScale, 1.0f); + // calculate how much longer the real world distance is at the top of the screen + // than at the middle of the screen. + float topedgelength = std::sqrt(std::pow(state.getHeight(), 2) / 4.0f * (1.0f + std::pow(state.getAltitude(), 2))); + float x = state.getHeight() / 2.0f * std::tan(state.getPitch()); + float extra = (topedgelength + x) / topedgelength - 1; + useProgram(iconShader->program); iconShader->u_matrix = vtxMatrix; iconShader->u_exmatrix = exMatrix; iconShader->u_texsize = {{ float(spriteAtlas->getWidth()) / 4.0f, float(spriteAtlas->getHeight()) / 4.0f }}; + iconShader->u_skewed = skewed; + iconShader->u_extra = extra; // adjust min/max zooms for variable font sies float zoomAdjust = std::log(fontSize / layout.icon.size) / std::log(2); @@ -205,6 +236,8 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c } if (bucket.hasTextData()) { + config.depthTest = layout.text.rotation_alignment == RotationAlignmentType::Map; + glyphAtlas->bind(); renderSDF(bucket, diff --git a/src/mbgl/shader/icon.vertex.glsl b/src/mbgl/shader/icon.vertex.glsl index 549570021..3850e01ab 100644 --- a/src/mbgl/shader/icon.vertex.glsl +++ b/src/mbgl/shader/icon.vertex.glsl @@ -14,6 +14,8 @@ uniform float u_minfadezoom; uniform float u_maxfadezoom; uniform float u_fadezoom; uniform float u_opacity; +uniform bool u_skewed; +uniform float u_extra; uniform vec2 u_texsize; @@ -51,7 +53,15 @@ void main() { // if label has been faded out, clip it z += step(v_alpha, 0.0); - gl_Position = u_matrix * vec4(a_pos, 0, 1) + u_exmatrix * vec4(a_offset / 64.0, z, 0); + if (u_skewed) { + vec4 extrude = u_exmatrix * vec4(a_offset / 64.0, 0, 0); + gl_Position = u_matrix * vec4(a_pos + extrude.xy, 0, 1); + gl_Position.z += z * gl_Position.w; + } else { + vec4 extrude = u_exmatrix * vec4(a_offset / 64.0, z, 0); + gl_Position = u_matrix * vec4(a_pos, 0, 1) + extrude; + } + v_tex = a_tex / u_texsize; v_alpha *= u_opacity; diff --git a/src/mbgl/shader/icon_shader.hpp b/src/mbgl/shader/icon_shader.hpp index b6156ae9a..18b0fce37 100644 --- a/src/mbgl/shader/icon_shader.hpp +++ b/src/mbgl/shader/icon_shader.hpp @@ -21,6 +21,8 @@ public: Uniform u_fadezoom = {"u_fadezoom", *this}; Uniform u_opacity = {"u_opacity", *this}; Uniform> u_texsize = {"u_texsize", *this}; + Uniform u_skewed = {"u_skewed", *this}; + Uniform u_extra = {"u_extra", *this}; private: int32_t a_pos = -1; diff --git a/src/mbgl/shader/sdf.fragment.glsl b/src/mbgl/shader/sdf.fragment.glsl index d72d61dab..a77e959e5 100644 --- a/src/mbgl/shader/sdf.fragment.glsl +++ b/src/mbgl/shader/sdf.fragment.glsl @@ -5,9 +5,11 @@ uniform float u_gamma; varying vec2 v_tex; varying float v_alpha; +varying float v_gamma_scale; void main() { float dist = texture2D(u_texture, v_tex).a; - float alpha = smoothstep(u_buffer - u_gamma, u_buffer + u_gamma, dist) * v_alpha; + float gamma = u_gamma * v_gamma_scale; + float alpha = smoothstep(u_buffer - gamma, u_buffer + gamma, dist) * v_alpha; gl_FragColor = u_color * alpha; } diff --git a/src/mbgl/shader/sdf.vertex.glsl b/src/mbgl/shader/sdf.vertex.glsl index 192459f9d..5d2e1ce24 100644 --- a/src/mbgl/shader/sdf.vertex.glsl +++ b/src/mbgl/shader/sdf.vertex.glsl @@ -13,11 +13,14 @@ uniform float u_fadedist; uniform float u_minfadezoom; uniform float u_maxfadezoom; uniform float u_fadezoom; +uniform bool u_skewed; +uniform float u_extra; uniform vec2 u_texsize; varying vec2 v_tex; varying float v_alpha; +varying float v_gamma_scale; void main() { vec2 a_tex = a_data1.xy; @@ -48,6 +51,19 @@ void main() { // if label has been faded out, clip it show *= (1.0 - step(v_alpha, 0.0)); - gl_Position = u_matrix * vec4(a_pos, 0, 1) + u_exmatrix * vec4(a_offset * show / 64.0, 0, 0); + if (u_skewed) { + vec4 extrude = u_exmatrix * vec4(a_offset * show / 64.0, 0, 0); + gl_Position = u_matrix * vec4(a_pos + extrude.xy, 0, 1); + } else { + vec4 extrude = u_exmatrix * vec4(a_offset * show / 64.0, 0, 0); + gl_Position = u_matrix * vec4(a_pos, 0, 1) + extrude; + } + + // position of y on the screen + float y = gl_Position.y / gl_Position.w; + // how much features are squished in all directions by the perspectiveness + float perspective_scale = 1.0 / (1.0 - y * u_extra); + v_gamma_scale = perspective_scale; + v_tex = a_tex / u_texsize; } diff --git a/src/mbgl/shader/sdf_shader.hpp b/src/mbgl/shader/sdf_shader.hpp index 36dfa30d3..181788ab1 100644 --- a/src/mbgl/shader/sdf_shader.hpp +++ b/src/mbgl/shader/sdf_shader.hpp @@ -23,6 +23,8 @@ public: Uniform u_minfadezoom = {"u_minfadezoom", *this}; Uniform u_maxfadezoom = {"u_maxfadezoom", *this}; Uniform u_fadezoom = {"u_fadezoom", *this}; + Uniform u_skewed = {"u_skewed", *this}; + Uniform u_extra = {"u_extra", *this}; protected: int32_t a_pos = -1; From bc92c2de3988a39d6def34617ade4afb5b82e214 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Fri, 14 Aug 2015 19:00:21 +0300 Subject: [PATCH 11/41] fix symbol collision detection in perspective view --- src/mbgl/map/live_tile_data.cpp | 2 +- src/mbgl/map/source.cpp | 8 ++++---- src/mbgl/map/tile_data.hpp | 2 +- src/mbgl/map/tile_worker.cpp | 4 ++-- src/mbgl/map/tile_worker.hpp | 2 +- src/mbgl/map/vector_tile_data.cpp | 15 ++++++++++----- src/mbgl/map/vector_tile_data.hpp | 5 ++++- src/mbgl/renderer/symbol_bucket.cpp | 2 +- src/mbgl/text/collision_tile.cpp | 2 +- src/mbgl/text/collision_tile.hpp | 6 +++--- src/mbgl/util/worker.cpp | 8 ++++---- src/mbgl/util/worker.hpp | 1 + 12 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/mbgl/map/live_tile_data.cpp b/src/mbgl/map/live_tile_data.cpp index 8be918d6d..9ac9c730f 100644 --- a/src/mbgl/map/live_tile_data.cpp +++ b/src/mbgl/map/live_tile_data.cpp @@ -27,7 +27,7 @@ LiveTileData::LiveTileData(const TileID& id_, state, std::make_unique(id_.z, 4096, source_.tile_size * id.overscaling, - 0, false)) { + 0, 0, false)) { state = State::loaded; if (!tile) { diff --git a/src/mbgl/map/source.cpp b/src/mbgl/map/source.cpp index 4b2ae2cfb..a3caab291 100644 --- a/src/mbgl/map/source.cpp +++ b/src/mbgl/map/source.cpp @@ -284,8 +284,8 @@ TileData::State Source::addTile(MapData& data, // If we don't find working tile data, we're just going to load it. if (info.type == SourceType::Vector) { - auto tileData = std::make_shared(normalized_id, style, info, - transformState.getAngle(), data.getCollisionDebug()); + auto tileData = std::make_shared(normalized_id, style, info, + transformState.getAngle(), transformState.getPitch(), data.getCollisionDebug()); tileData->request(data.pixelRatio, callback); new_tile.data = tileData; } else if (info.type == SourceType::Raster) { @@ -506,7 +506,7 @@ bool Source::update(MapData& data, updateTilePtrs(); for (auto& tilePtr : tilePtrs) { - tilePtr->data->redoPlacement(transformState.getAngle(), data.getCollisionDebug()); + tilePtr->data->redoPlacement(transformState.getAngle(), transformState.getPitch(), data.getCollisionDebug()); } updated = data.getAnimationTime(); @@ -568,7 +568,7 @@ void Source::tileLoadingCompleteCallback(const TileID& normalized_id, const Tran return; } - data->redoPlacement(transformState.getAngle(), collisionDebug); + data->redoPlacement(transformState.getAngle(), transformState.getPitch(), collisionDebug); emitTileLoaded(true); } diff --git a/src/mbgl/map/tile_data.hpp b/src/mbgl/map/tile_data.hpp index e78d88841..047ccd5cd 100644 --- a/src/mbgl/map/tile_data.hpp +++ b/src/mbgl/map/tile_data.hpp @@ -72,7 +72,7 @@ public: virtual Bucket* getBucket(const StyleLayer&) = 0; - virtual void redoPlacement(float, bool) {} + virtual void redoPlacement(float, float, bool) {} bool isReady() const { return isReadyState(state); diff --git a/src/mbgl/map/tile_worker.cpp b/src/mbgl/map/tile_worker.cpp index a555ca7ab..0b9175c53 100644 --- a/src/mbgl/map/tile_worker.cpp +++ b/src/mbgl/map/tile_worker.cpp @@ -55,8 +55,8 @@ TileParseResult TileWorker::parse(const GeometryTile& geometryTile) { return partialParse ? TileData::State::partial : TileData::State::parsed; } -void TileWorker::redoPlacement(float angle, bool collisionDebug) { - collision->reset(angle, 0); +void TileWorker::redoPlacement(float angle, float pitch, bool collisionDebug) { + collision->reset(angle, pitch); collision->setDebug(collisionDebug); for (auto i = layers.rbegin(); i != layers.rend(); i++) { auto bucket = getBucket(**i); diff --git a/src/mbgl/map/tile_worker.hpp b/src/mbgl/map/tile_worker.hpp index 15a5487dc..b8a93011e 100644 --- a/src/mbgl/map/tile_worker.hpp +++ b/src/mbgl/map/tile_worker.hpp @@ -44,7 +44,7 @@ public: Bucket* getBucket(const StyleLayer&) const; TileParseResult parse(const GeometryTile&); - void redoPlacement(float angle, bool collisionDebug); + void redoPlacement(float angle, float pitch, bool collisionDebug); std::vector> layers; diff --git a/src/mbgl/map/vector_tile_data.cpp b/src/mbgl/map/vector_tile_data.cpp index c9ee33910..60297396e 100644 --- a/src/mbgl/map/vector_tile_data.cpp +++ b/src/mbgl/map/vector_tile_data.cpp @@ -16,6 +16,7 @@ VectorTileData::VectorTileData(const TileID& id_, Style& style_, const SourceInfo& source_, float angle, + float pitch, bool collisionDebug) : TileData(id_), worker(style_.workers), @@ -27,7 +28,7 @@ VectorTileData::VectorTileData(const TileID& id_, state, std::make_unique(id_.z, 4096, source_.tile_size * id.overscaling, - angle, collisionDebug)), + angle, pitch, collisionDebug)), source(source_), lastAngle(angle), currentAngle(angle) { @@ -98,11 +99,14 @@ Bucket* VectorTileData::getBucket(const StyleLayer& layer) { return tileWorker.getBucket(layer); } -void VectorTileData::redoPlacement(float angle, bool collisionDebug) { - if (angle == currentAngle && collisionDebug == currentCollisionDebug) +void VectorTileData::redoPlacement(float angle, float pitch, bool collisionDebug) { + if (angle == currentAngle && + pitch == currentPitch && + collisionDebug == currentCollisionDebug) return; lastAngle = angle; + lastPitch = pitch; lastCollisionDebug = collisionDebug; if (state != State::parsed || redoingPlacement) @@ -110,9 +114,10 @@ void VectorTileData::redoPlacement(float angle, bool collisionDebug) { redoingPlacement = true; currentAngle = angle; + currentPitch = pitch; currentCollisionDebug = collisionDebug; - workRequest = worker.redoPlacement(tileWorker, angle, collisionDebug, [this] { + workRequest = worker.redoPlacement(tileWorker, angle, pitch, collisionDebug, [this] { for (const auto& layer : tileWorker.layers) { auto bucket = getBucket(*layer); if (bucket) { @@ -120,7 +125,7 @@ void VectorTileData::redoPlacement(float angle, bool collisionDebug) { } } redoingPlacement = false; - redoPlacement(lastAngle, lastCollisionDebug); + redoPlacement(lastAngle, lastPitch, lastCollisionDebug); }); } diff --git a/src/mbgl/map/vector_tile_data.hpp b/src/mbgl/map/vector_tile_data.hpp index e0e8be29b..4db0cbe00 100644 --- a/src/mbgl/map/vector_tile_data.hpp +++ b/src/mbgl/map/vector_tile_data.hpp @@ -19,6 +19,7 @@ public: Style&, const SourceInfo&, float angle_, + float pitch_, bool collisionDebug_); ~VectorTileData(); @@ -29,7 +30,7 @@ public: bool reparse(std::function callback); - void redoPlacement(float angle, bool collisionDebug) override; + void redoPlacement(float angle, float pitch, bool collisionDebug) override; void cancel() override; @@ -43,6 +44,8 @@ private: std::string data; float lastAngle = 0; float currentAngle; + float lastPitch = 0; + float currentPitch; bool lastCollisionDebug = 0; bool currentCollisionDebug = 0; bool redoingPlacement = false; diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp index e8ad132c5..16ba3cf1a 100644 --- a/src/mbgl/renderer/symbol_bucket.cpp +++ b/src/mbgl/renderer/symbol_bucket.cpp @@ -511,7 +511,7 @@ void SymbolBucket::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float void SymbolBucket::addToDebugBuffers() { - const float yStretch = 1.0f; + const float yStretch = collision.yStretch; const float angle = collision.angle; const float zoom = collision.zoom; float angle_sin = std::sin(-angle); diff --git a/src/mbgl/text/collision_tile.cpp b/src/mbgl/text/collision_tile.cpp index 1c7806a4e..b80d756c3 100644 --- a/src/mbgl/text/collision_tile.cpp +++ b/src/mbgl/text/collision_tile.cpp @@ -13,7 +13,7 @@ void CollisionTile::reset(const float _angle, const float pitch) { rotationMatrix = {{angle_cos, -angle_sin, angle_sin, angle_cos}}; // Stretch boxes in y direction to account for the map tilt. - const float _yStretch = 1.0f / std::cos(pitch / 180 * M_PI); + const float _yStretch = 1.0f / std::cos(pitch); // The amount the map is squished depends on the y position. // Sort of account for this by making all boxes a bit bigger. diff --git a/src/mbgl/text/collision_tile.hpp b/src/mbgl/text/collision_tile.hpp index aed9b59f3..632652256 100644 --- a/src/mbgl/text/collision_tile.hpp +++ b/src/mbgl/text/collision_tile.hpp @@ -35,8 +35,8 @@ namespace mbgl { class CollisionTile { public: - inline explicit CollisionTile(float _zoom, float tileExtent, float tileSize, float angle_, bool debug_) : - zoom(_zoom), tilePixelRatio(tileExtent / tileSize), debug(debug_) { reset(angle_, 0); } + inline explicit CollisionTile(float _zoom, float tileExtent, float tileSize, float angle_, float pitch_, bool debug_) : + zoom(_zoom), tilePixelRatio(tileExtent / tileSize), debug(debug_) { reset(angle_, pitch_); } void reset(const float angle, const float pitch); float placeFeature(const CollisionFeature &feature); @@ -51,6 +51,7 @@ class CollisionTile { const float minScale = 0.5f; const float maxScale = 2.0f; + float yStretch; private: @@ -58,7 +59,6 @@ class CollisionTile { Tree tree; std::array rotationMatrix; - float yStretch; bool debug; }; diff --git a/src/mbgl/util/worker.cpp b/src/mbgl/util/worker.cpp index 516d2f5db..b238071bc 100644 --- a/src/mbgl/util/worker.cpp +++ b/src/mbgl/util/worker.cpp @@ -46,8 +46,8 @@ public: } } - void redoPlacement(TileWorker* worker, float angle, bool collisionDebug, std::function callback) { - worker->redoPlacement(angle, collisionDebug); + void redoPlacement(TileWorker* worker, float angle, float pitch, bool collisionDebug, std::function callback) { + worker->redoPlacement(angle, pitch, collisionDebug); callback(); } }; @@ -76,9 +76,9 @@ std::unique_ptr Worker::parseLiveTile(TileWorker& worker, const Liv return threads[current]->invokeWithCallback(&Worker::Impl::parseLiveTile, callback, &worker, &tile); } -std::unique_ptr Worker::redoPlacement(TileWorker& worker, float angle, bool collisionDebug, std::function callback) { +std::unique_ptr Worker::redoPlacement(TileWorker& worker, float angle, float pitch, bool collisionDebug, std::function callback) { current = (current + 1) % threads.size(); - return threads[current]->invokeWithCallback(&Worker::Impl::redoPlacement, callback, &worker, angle, collisionDebug); + return threads[current]->invokeWithCallback(&Worker::Impl::redoPlacement, callback, &worker, angle, pitch, collisionDebug); } } // end namespace mbgl diff --git a/src/mbgl/util/worker.hpp b/src/mbgl/util/worker.hpp index 2d78338db..3ecc402ad 100644 --- a/src/mbgl/util/worker.hpp +++ b/src/mbgl/util/worker.hpp @@ -49,6 +49,7 @@ public: Request redoPlacement( TileWorker&, float angle, + float pitch, bool collisionDebug, std::function callback); From 554425b753c1eee6b6874f1ddde0c266a717c88e Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Fri, 14 Aug 2015 19:34:13 +0300 Subject: [PATCH 12/41] fix earthquakes in perspective view Use higher precision for matrix calculations so that the map does not jump around while zooming. --- include/mbgl/util/mat4.hpp | 14 +++++++------- src/mbgl/shader/uniform.hpp | 14 ++++++++++---- src/mbgl/util/mat2.cpp | 8 ++++---- src/mbgl/util/mat2.hpp | 6 +++--- src/mbgl/util/mat3.cpp | 10 +++++----- src/mbgl/util/mat3.hpp | 8 ++++---- src/mbgl/util/mat4.cpp | 26 +++++++++++++------------- 7 files changed, 46 insertions(+), 40 deletions(-) diff --git a/include/mbgl/util/mat4.hpp b/include/mbgl/util/mat4.hpp index e59712ed0..ea4854306 100644 --- a/include/mbgl/util/mat4.hpp +++ b/include/mbgl/util/mat4.hpp @@ -27,18 +27,18 @@ namespace mbgl { -typedef std::array mat4; +typedef std::array mat4; namespace matrix { void identity(mat4& out); -void ortho(mat4& out, float left, float right, float bottom, float top, float near, float far); -void perspective(mat4& out, float fovy, float aspect, float near, float far); +void ortho(mat4& out, double left, double right, double bottom, double top, double near, double far); +void perspective(mat4& out, double fovy, double aspect, double near, double far); void copy(mat4& out, const mat4& a); -void translate(mat4& out, const mat4& a, float x, float y, float z); -void rotate_x(mat4& out, const mat4& a, float rad); -void rotate_z(mat4& out, const mat4& a, float rad); -void scale(mat4& out, const mat4& a, float x, float y, float z); +void translate(mat4& out, const mat4& a, double x, double y, double z); +void rotate_x(mat4& out, const mat4& a, double rad); +void rotate_z(mat4& out, const mat4& a, double rad); +void scale(mat4& out, const mat4& a, double x, double y, double z); void multiply(mat4& out, const mat4& a, const mat4& b); } diff --git a/src/mbgl/shader/uniform.hpp b/src/mbgl/shader/uniform.hpp index d2a248c60..55646f7d8 100644 --- a/src/mbgl/shader/uniform.hpp +++ b/src/mbgl/shader/uniform.hpp @@ -36,10 +36,16 @@ public: location = MBGL_CHECK_ERROR(glGetUniformLocation(shader.program, name)); } - void operator=(const T& t) { - if (current != t) { - current = t; - bind(t); + void operator=(const std::array& t) { + bool dirty = false; + for (unsigned int i = 0; i < C*R; i++) { + if (current[i] != t[i]) { + current[i] = t[i]; + dirty = true; + } + } + if (dirty) { + bind(current); } } diff --git a/src/mbgl/util/mat2.cpp b/src/mbgl/util/mat2.cpp index 05900d166..691024454 100644 --- a/src/mbgl/util/mat2.cpp +++ b/src/mbgl/util/mat2.cpp @@ -33,8 +33,8 @@ void matrix::identity(mat2& out) { out[3] = 1.0f; } -void matrix::rotate(mat2& out, const mat2& a, float rad) { - float a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], +void matrix::rotate(mat2& out, const mat2& a, double rad) { + double a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], s = std::sin(rad), c = std::cos(rad); out[0] = a0 * c + a2 * s; @@ -43,8 +43,8 @@ void matrix::rotate(mat2& out, const mat2& a, float rad) { out[3] = a1 * -s + a3 * c; }; -void matrix::scale(mat2& out, const mat2& a, float v0, float v1) { - float a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3]; +void matrix::scale(mat2& out, const mat2& a, double v0, double v1) { + double a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3]; out[0] = a0 * v0; out[1] = a1 * v0; out[2] = a2 * v1; diff --git a/src/mbgl/util/mat2.hpp b/src/mbgl/util/mat2.hpp index 59110bf90..b5cec821f 100644 --- a/src/mbgl/util/mat2.hpp +++ b/src/mbgl/util/mat2.hpp @@ -27,13 +27,13 @@ namespace mbgl { -typedef std::array mat2; +typedef std::array mat2; namespace matrix { void identity(mat2& out); -void rotate(mat2& out, const mat2& a, float rad); -void scale(mat2& out, const mat2& a, float v0, float v1); +void rotate(mat2& out, const mat2& a, double rad); +void scale(mat2& out, const mat2& a, double v0, double v1); } } diff --git a/src/mbgl/util/mat3.cpp b/src/mbgl/util/mat3.cpp index 263768ee4..f4ae8841d 100644 --- a/src/mbgl/util/mat3.cpp +++ b/src/mbgl/util/mat3.cpp @@ -38,8 +38,8 @@ void matrix::identity(mat3& out) { out[8] = 1.0f; } -void matrix::translate(mat3& out, const mat3& a, float x, float y) { - float a00 = a[0], a01 = a[1], a02 = a[2], +void matrix::translate(mat3& out, const mat3& a, double x, double y) { + double a00 = a[0], a01 = a[1], a02 = a[2], a10 = a[3], a11 = a[4], a12 = a[5], a20 = a[6], a21 = a[7], a22 = a[8]; @@ -56,8 +56,8 @@ void matrix::translate(mat3& out, const mat3& a, float x, float y) { out[8] = x * a02 + y * a12 + a22; } -void matrix::rotate(mat3& out, const mat3& a, float rad) { - float s = std::sin(rad), +void matrix::rotate(mat3& out, const mat3& a, double rad) { + double s = std::sin(rad), c = std::cos(rad), a00 = a[0], a01 = a[1], @@ -82,7 +82,7 @@ void matrix::rotate(mat3& out, const mat3& a, float rad) { out[8] = a22; }; -void matrix::scale(mat3& out, const mat3& a, float x, float y) { +void matrix::scale(mat3& out, const mat3& a, double x, double y) { out[0] = x * a[0]; out[1] = x * a[1]; out[2] = x * a[2]; diff --git a/src/mbgl/util/mat3.hpp b/src/mbgl/util/mat3.hpp index fa4075176..3a6aba5a1 100644 --- a/src/mbgl/util/mat3.hpp +++ b/src/mbgl/util/mat3.hpp @@ -27,14 +27,14 @@ namespace mbgl { -typedef std::array mat3; +typedef std::array mat3; namespace matrix { void identity(mat3& out); -void translate(mat3& out, const mat3& a, float x, float y); -void rotate(mat3& out, const mat3& a, float rad); -void scale(mat3& out, const mat3& a, float x, float y); +void translate(mat3& out, const mat3& a, double x, double y); +void rotate(mat3& out, const mat3& a, double rad); +void scale(mat3& out, const mat3& a, double x, double y); } } diff --git a/src/mbgl/util/mat4.cpp b/src/mbgl/util/mat4.cpp index d48558dc2..59137ded3 100644 --- a/src/mbgl/util/mat4.cpp +++ b/src/mbgl/util/mat4.cpp @@ -45,8 +45,8 @@ void matrix::identity(mat4& out) { out[15] = 1.0f; } -void matrix::ortho(mat4& out, float left, float right, float bottom, float top, float near, float far) { - float lr = 1.0f / (left - right), +void matrix::ortho(mat4& out, double left, double right, double bottom, double top, double near, double far) { + double lr = 1.0f / (left - right), bt = 1.0f / (bottom - top), nf = 1.0f / (near - far); out[0] = -2.0f * lr; @@ -67,8 +67,8 @@ void matrix::ortho(mat4& out, float left, float right, float bottom, float top, out[15] = 1.0f; } -void matrix::perspective(mat4& out, float fovy, float aspect, float near, float far) { - float f = 1.0f / std::tan(fovy / 2.0f), +void matrix::perspective(mat4& out, double fovy, double aspect, double near, double far) { + double f = 1.0f / std::tan(fovy / 2.0f), nf = 1.0f / (near - far); out[0] = f / aspect; out[1] = 0.0f; @@ -107,14 +107,14 @@ void matrix::copy(mat4& out, const mat4& a) { out[15] = a[15]; } -void matrix::translate(mat4& out, const mat4& a, float x, float y, float z) { +void matrix::translate(mat4& out, const mat4& a, double x, double y, double z) { if (&a == &out) { out[12] = a[0] * x + a[4] * y + a[8] * z + a[12]; out[13] = a[1] * x + a[5] * y + a[9] * z + a[13]; out[14] = a[2] * x + a[6] * y + a[10] * z + a[14]; out[15] = a[3] * x + a[7] * y + a[11] * z + a[15]; } else { - float a00, a01, a02, a03, + double a00, a01, a02, a03, a10, a11, a12, a13, a20, a21, a22, a23; @@ -133,8 +133,8 @@ void matrix::translate(mat4& out, const mat4& a, float x, float y, float z) { } } -void matrix::rotate_x(mat4& out, const mat4& a, float rad) { - float s = std::sin(rad), +void matrix::rotate_x(mat4& out, const mat4& a, double rad) { + double s = std::sin(rad), c = std::cos(rad), a10 = a[4], a11 = a[5], @@ -167,8 +167,8 @@ void matrix::rotate_x(mat4& out, const mat4& a, float rad) { out[11] = a23 * c - a13 * s; } -void matrix::rotate_z(mat4& out, const mat4& a, float rad) { - float s = std::sin(rad), +void matrix::rotate_z(mat4& out, const mat4& a, double rad) { + double s = std::sin(rad), c = std::cos(rad), a00 = a[0], a01 = a[1], @@ -201,7 +201,7 @@ void matrix::rotate_z(mat4& out, const mat4& a, float rad) { out[7] = a13 * c - a03 * s; } -void matrix::scale(mat4& out, const mat4& a, float x, float y, float z) { +void matrix::scale(mat4& out, const mat4& a, double x, double y, double z) { out[0] = a[0] * x; out[1] = a[1] * x; out[2] = a[2] * x; @@ -221,13 +221,13 @@ void matrix::scale(mat4& out, const mat4& a, float x, float y, float z) { } void matrix::multiply(mat4& out, const mat4& a, const mat4& b) { - float a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], + double a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; // Cache only the current line of the second matrix - float b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; + double b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; From cef1b254445bdcfb20ada157ecc7f72c27aeacf9 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Mon, 17 Aug 2015 16:22:46 -0400 Subject: [PATCH 13/41] port invert and transformMat4 from gl-matrix --- src/mbgl/util/mat4.cpp | 47 ++++++++++++++++++++++++++++++++++++++++++ src/mbgl/util/vec4.cpp | 33 +++++++++++++++++++++++++++++ src/mbgl/util/vec4.hpp | 40 +++++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 src/mbgl/util/vec4.cpp create mode 100644 src/mbgl/util/vec4.hpp diff --git a/src/mbgl/util/mat4.cpp b/src/mbgl/util/mat4.cpp index 59137ded3..123c8464f 100644 --- a/src/mbgl/util/mat4.cpp +++ b/src/mbgl/util/mat4.cpp @@ -45,6 +45,53 @@ void matrix::identity(mat4& out) { out[15] = 1.0f; } +bool matrix::invert(mat4& out, mat4& a) { + float a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], + a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], + a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], + a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], + + b00 = a00 * a11 - a01 * a10, + b01 = a00 * a12 - a02 * a10, + b02 = a00 * a13 - a03 * a10, + b03 = a01 * a12 - a02 * a11, + b04 = a01 * a13 - a03 * a11, + b05 = a02 * a13 - a03 * a12, + b06 = a20 * a31 - a21 * a30, + b07 = a20 * a32 - a22 * a30, + b08 = a20 * a33 - a23 * a30, + b09 = a21 * a32 - a22 * a31, + b10 = a21 * a33 - a23 * a31, + b11 = a22 * a33 - a23 * a32, + + // Calculate the determinant + det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; + + if (!det) { + return true; + } + det = 1.0 / det; + + out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; + out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det; + out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det; + out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det; + out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det; + out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det; + out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det; + out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det; + out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det; + out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det; + out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det; + out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det; + out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det; + out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det; + out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det; + out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det; + + return false; +} + void matrix::ortho(mat4& out, double left, double right, double bottom, double top, double near, double far) { double lr = 1.0f / (left - right), bt = 1.0f / (bottom - top), diff --git a/src/mbgl/util/vec4.cpp b/src/mbgl/util/vec4.cpp new file mode 100644 index 000000000..415b15d80 --- /dev/null +++ b/src/mbgl/util/vec4.cpp @@ -0,0 +1,33 @@ +// This is an incomplete port of http://glmatrix.net/ +// +// Copyright (c) 2013 Brandon Jones, Colin MacKenzie IV +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the +// use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not claim +// that you wrote the original software. If you use this software in a +// product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. + +#include + +using namespace mbgl; + +void matrix::transformMat4(vec4& out, vec4& a, mat4& m) { + float x = a[0], y = a[1], z = a[2], w = a[3]; + out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w; + out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w; + out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w; + out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w; +} diff --git a/src/mbgl/util/vec4.hpp b/src/mbgl/util/vec4.hpp new file mode 100644 index 000000000..c5b4ab1d9 --- /dev/null +++ b/src/mbgl/util/vec4.hpp @@ -0,0 +1,40 @@ +// This is an incomplete port of http://glmatrix.net/ +// +// Copyright (c) 2013 Brandon Jones, Colin MacKenzie IV +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the +// use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not claim +// that you wrote the original software. If you use this software in a +// product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. + +#ifndef MBGL_UTIL_VEC4 +#define MBGL_UTIL_VEC4 + +#include +#include + +namespace mbgl { + +namespace matrix { + +typedef std::array vec4; + +void transformMat4(vec4& out, vec4& a, mat4& m); + +} +} + +#endif From 0d68c4fedf780ed11d697ccf81b4f6b5b92b3134 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Mon, 17 Aug 2015 16:45:20 -0400 Subject: [PATCH 14/41] load correct covering tiles in perspective view port pointCoordinate from -js to convert screen points to tile coordinates correctly in perspective view. --- include/mbgl/util/mat4.hpp | 1 + src/mbgl/map/source.cpp | 7 +- src/mbgl/map/transform_state.cpp | 117 ++++++++++++++++++++++-------- src/mbgl/map/transform_state.hpp | 11 ++- src/mbgl/renderer/painter.cpp | 21 +----- src/mbgl/util/box.hpp | 7 +- src/mbgl/util/tile_coordinate.hpp | 29 ++++++++ src/mbgl/util/tile_cover.cpp | 11 ++- 8 files changed, 145 insertions(+), 59 deletions(-) create mode 100644 src/mbgl/util/tile_coordinate.hpp diff --git a/include/mbgl/util/mat4.hpp b/include/mbgl/util/mat4.hpp index ea4854306..9c3433240 100644 --- a/include/mbgl/util/mat4.hpp +++ b/include/mbgl/util/mat4.hpp @@ -32,6 +32,7 @@ typedef std::array mat4; namespace matrix { void identity(mat4& out); +bool invert(mat4& out, mat4& a); void ortho(mat4& out, double left, double right, double bottom, double top, double near, double far); void perspective(mat4& out, double fovy, double aspect, double near, double far); void copy(mat4& out, const mat4& a); diff --git a/src/mbgl/map/source.cpp b/src/mbgl/map/source.cpp index a3caab291..f60ddce57 100644 --- a/src/mbgl/map/source.cpp +++ b/src/mbgl/map/source.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -332,14 +333,14 @@ std::forward_list Source::coveringTiles(const TransformState& state) con // Map four viewport corners to pixel coordinates box points = state.cornersToBox(z); - const vec2& center = points.center; + const TileCoordinate center = state.pointCoordinate({ state.getWidth() / 2.0f, state.getHeight()/ 2.0f }).zoomTo(z); std::forward_list covering_tiles = tileCover(z, points, reparseOverscaled ? actualZ : z); covering_tiles.sort([¢er](const TileID& a, const TileID& b) { // Sorts by distance from the box center - return std::fabs(a.x - center.x) + std::fabs(a.y - center.y) < - std::fabs(b.x - center.x) + std::fabs(b.y - center.y); + return std::fabs(a.x - center.column) + std::fabs(a.y - center.row) < + std::fabs(b.x - center.column) + std::fabs(b.y - center.row); }); return covering_tiles; diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp index 1cb1d9f82..c06d944d9 100644 --- a/src/mbgl/map/transform_state.cpp +++ b/src/mbgl/map/transform_state.cpp @@ -3,6 +3,8 @@ #include #include #include +#include +#include using namespace mbgl; @@ -17,37 +19,37 @@ void TransformState::matrixFor(mat4& matrix, const TileID& id, const int8_t z) c matrix::scale(matrix, matrix, s / 4096.0f, s / 4096.0f, 1); } +void TransformState::getProjMatrix(mat4& projMatrix) const { + double halfFov = std::atan(0.5 / getAltitude()); + double topHalfSurfaceDistance = std::sin(halfFov) * getAltitude() / + std::sin(M_PI / 2.0f - getPitch() - halfFov); + // Calculate z value of the farthest fragment that should be rendered. + double farZ = std::cos(M_PI / 2.0f - getPitch()) * topHalfSurfaceDistance + getAltitude(); + + matrix::perspective(projMatrix, 2.0f * std::atan((getHeight() / 2.0f) / getAltitude()), + double(getWidth()) / getHeight(), 0.1, farZ); + + matrix::translate(projMatrix, projMatrix, 0, 0, -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 / getHeight()); + + matrix::rotate_x(projMatrix, projMatrix, getPitch()); + matrix::rotate_z(projMatrix, projMatrix, getAngle()); + + matrix::translate(projMatrix, projMatrix, pixel_x() - getWidth() / 2.0f, + pixel_y() - getWidth() / 2.0f, 0); +} + box TransformState::cornersToBox(uint32_t z) const { - const double ref_scale = std::pow(2, z); - - const double angle_sin = std::sin(-angle); - const double angle_cos = std::cos(-angle); - - const double w_2 = static_cast(width) / 2.0; - const double h_2 = static_cast(height) / 2.0; - const double ss_0 = scale * util::tileSize; - const double ss_1 = ref_scale / ss_0; - const double ss_2 = ss_0 / 2.0; - - // Calculate the corners of the map view. The resulting coordinates will be - // in fractional tile coordinates. - box b; - - b.tl.x = ((-w_2) * angle_cos - (-h_2) * angle_sin + ss_2 - x) * ss_1; - b.tl.y = ((-w_2) * angle_sin + (-h_2) * angle_cos + ss_2 - y) * ss_1; - - b.tr.x = ((+w_2) * angle_cos - (-h_2) * angle_sin + ss_2 - x) * ss_1; - b.tr.y = ((+w_2) * angle_sin + (-h_2) * angle_cos + ss_2 - y) * ss_1; - - b.bl.x = ((-w_2) * angle_cos - (+h_2) * angle_sin + ss_2 - x) * ss_1; - b.bl.y = ((-w_2) * angle_sin + (+h_2) * angle_cos + ss_2 - y) * ss_1; - - b.br.x = ((+w_2) * angle_cos - (+h_2) * angle_sin + ss_2 - x) * ss_1; - b.br.y = ((+w_2) * angle_sin + (+h_2) * angle_cos + ss_2 - y) * ss_1; - - b.center.x = (ss_2 - x) * ss_1; - b.center.y = (ss_2 - y) * ss_1; - + double w = width; + double h = height; + box b( + pointCoordinate({ 0, 0 }).zoomTo(z), + pointCoordinate({ w, 0 }).zoomTo(z), + pointCoordinate({ w, h }).zoomTo(z), + pointCoordinate({ 0, h }).zoomTo(z)); return b; } @@ -240,6 +242,61 @@ const LatLng TransformState::latLngForPixel(const vec2 pixel) const { return Projection::latLngForProjectedMeters(givenMeters); } +TileCoordinate TransformState::pointCoordinate(const vec2 point) const { + + float targetZ = 0; + float tileZoom = std::floor(getZoom()); + + mat4 mat = coordinatePointMatrix(tileZoom); + + mat4 inverted; + bool err = matrix::invert(inverted, mat); + + if (err) throw std::runtime_error("failed to invert coordinatePointMatrix"); + + // since we don't know the correct projected z value for the point, + // unproject two points to get a line and then find the point on that + // line with z=0 + + matrix::vec4 coord0; + matrix::vec4 coord1; + matrix::vec4 point0 = {{ point.x, point.y, 0, 1 }}; + matrix::vec4 point1 = {{ point.x, point.y, 1, 1 }}; + matrix::transformMat4(coord0, point0, inverted); + matrix::transformMat4(coord1, point1, inverted); + + float w0 = coord0[3]; + float w1 = coord1[3]; + float x0 = coord0[0] / w0; + float x1 = coord1[0] / w1; + float y0 = coord0[1] / w0; + float y1 = coord1[1] / w1; + float z0 = coord0[2] / w0; + float z1 = coord1[2] / w1; + + + float t = z0 == z1 ? 0 : (targetZ - z0) / (z1 - z0); + + return { util::interpolate(x0, x1, t), util::interpolate(y0, y1, t), tileZoom }; +} + +mat4 TransformState::coordinatePointMatrix(float z) const { + mat4 proj; + getProjMatrix(proj); + float s = util::tileSize * scale / std::pow(2, z); + matrix::scale(proj, proj, s , s, 1); + matrix::multiply(proj, getPixelMatrix(), proj); + return proj; +} + +mat4 TransformState::getPixelMatrix() const { + mat4 m; + matrix::identity(m); + matrix::scale(m, m, width / 2.0f, -height / 2.0f, 1); + matrix::translate(m, m, 1, -1, 0); + return m; +} + #pragma mark - Changing diff --git a/src/mbgl/map/transform_state.hpp b/src/mbgl/map/transform_state.hpp index 92e2fb809..5b648ad07 100644 --- a/src/mbgl/map/transform_state.hpp +++ b/src/mbgl/map/transform_state.hpp @@ -1,10 +1,11 @@ #ifndef MBGL_MAP_TRANSFORM_STATE #define MBGL_MAP_TRANSFORM_STATE -#include #include #include #include +#include +#include #include #include @@ -14,6 +15,7 @@ namespace mbgl { class TileID; struct box; +struct TileCoordinate; class TransformState { friend class Transform; @@ -21,6 +23,7 @@ class TransformState { public: // Matrix void matrixFor(mat4& matrix, const TileID& id, const int8_t z) const; + void getProjMatrix(mat4& matrix) const; box cornersToBox(uint32_t z) const; // Dimensions @@ -62,6 +65,9 @@ public: double pixel_x() const; double pixel_y() const; + // Conversions + TileCoordinate pointCoordinate(const vec2 point) const; + private: void constrain(double& scale, double& y) const; @@ -72,6 +78,9 @@ private: // logical dimensions uint16_t width = 0, height = 0; + mat4 coordinatePointMatrix(float z) const; + mat4 getPixelMatrix() const; + private: // animation state bool rotating = false; diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index 7f06b2345..74268a401 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -133,26 +133,7 @@ void Painter::lineWidth(float line_width) { void Painter::changeMatrix() { - 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); + state.getProjMatrix(projMatrix); // The extrusion matrix. matrix::ortho(extrudeMatrix, 0, state.getWidth(), state.getHeight(), 0, 0, -1); diff --git a/src/mbgl/util/box.hpp b/src/mbgl/util/box.hpp index 55a5d46fb..f03adc2e5 100644 --- a/src/mbgl/util/box.hpp +++ b/src/mbgl/util/box.hpp @@ -1,13 +1,14 @@ #ifndef MBGL_UTIL_BOX #define MBGL_UTIL_BOX -#include +#include namespace mbgl { struct box { - vec2 tl, tr, bl, br; - vec2 center; + box(TileCoordinate tl_, TileCoordinate tr_, TileCoordinate br_, TileCoordinate bl_) : + tl(tl_), tr(tr_), br(br_), bl(bl_) {} + TileCoordinate tl, tr, br, bl; }; } diff --git a/src/mbgl/util/tile_coordinate.hpp b/src/mbgl/util/tile_coordinate.hpp new file mode 100644 index 000000000..0f5f0dcb8 --- /dev/null +++ b/src/mbgl/util/tile_coordinate.hpp @@ -0,0 +1,29 @@ +#ifndef MBGL_UTIL_TILE_COORDINATE +#define MBGL_UTIL_TILE_COORDINATE + +#include + +namespace mbgl { + +struct TileCoordinate { + float column; + float row; + float zoom; + + TileCoordinate(float column_, float row_, float zoom_) : + column(column_), row(row_), zoom(zoom_) {} + + TileCoordinate zoomTo(float targetZoom) { + float scale = std::pow(2, targetZoom - zoom); + return { column * scale, row * scale, targetZoom }; + } + + TileCoordinate operator-(TileCoordinate c) { + c = c.zoomTo(zoom); + return { column - c.column, row - c.row, zoom }; + }; +}; + +} + +#endif diff --git a/src/mbgl/util/tile_cover.cpp b/src/mbgl/util/tile_cover.cpp index 9e444fec1..b7937bf84 100644 --- a/src/mbgl/util/tile_cover.cpp +++ b/src/mbgl/util/tile_cover.cpp @@ -1,6 +1,7 @@ #include #include #include +#include namespace mbgl { @@ -78,13 +79,19 @@ std::forward_list tileCover(int8_t z, const mbgl::box &bounds, int8_t ac } }; + mbgl::vec2 tl = { bounds.tl.column, bounds.tl.row }; + mbgl::vec2 tr = { bounds.tr.column, bounds.tr.row }; + mbgl::vec2 br = { bounds.br.column, bounds.br.row }; + mbgl::vec2 bl = { bounds.bl.column, bounds.bl.row }; + // Divide the screen up in two triangles and scan each of them: // \---+ // | \ | // +---\. - scanTriangle(bounds.tl, bounds.tr, bounds.br, 0, tiles, scanLine); - scanTriangle(bounds.br, bounds.bl, bounds.tl, 0, tiles, scanLine); + scanTriangle(tl, tr, br, 0, tiles, scanLine); + scanTriangle(br, bl, tl, 0, tiles, scanLine); + t.sort(); t.unique(); return t; From 9e68e49c896ff857c0c0bcf5281a74ab3b12cd13 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Mon, 17 Aug 2015 19:02:30 -0400 Subject: [PATCH 15/41] fix depth clipping in perspective view The depth range is now set slightly differently. Both ends of the range are shifted for each layer to solve some precision issues. Some layers draw multiple things at different depths. For example, fill layers draw fills and antialiasing separately. To handle this case, I added setDepthSublayer(n) which a --- src/mbgl/map/transform_state.cpp | 2 +- src/mbgl/map/transform_state.hpp | 2 +- src/mbgl/renderer/gl_config.hpp | 1 - src/mbgl/renderer/painter.cpp | 25 +++++++++++++------------ src/mbgl/renderer/painter.hpp | 15 ++++++++------- src/mbgl/renderer/painter_fill.cpp | 8 ++++---- src/mbgl/renderer/painter_line.cpp | 3 +-- src/mbgl/renderer/painter_raster.cpp | 2 +- src/mbgl/renderer/painter_symbol.cpp | 8 ++++---- src/mbgl/shader/plain.vertex.glsl | 1 - 10 files changed, 33 insertions(+), 34 deletions(-) diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp index c06d944d9..2f6231828 100644 --- a/src/mbgl/map/transform_state.cpp +++ b/src/mbgl/map/transform_state.cpp @@ -39,7 +39,7 @@ void TransformState::getProjMatrix(mat4& projMatrix) const { matrix::rotate_z(projMatrix, projMatrix, getAngle()); matrix::translate(projMatrix, projMatrix, pixel_x() - getWidth() / 2.0f, - pixel_y() - getWidth() / 2.0f, 0); + pixel_y() - getHeight() / 2.0f, 0); } box TransformState::cornersToBox(uint32_t z) const { diff --git a/src/mbgl/map/transform_state.hpp b/src/mbgl/map/transform_state.hpp index 5b648ad07..521131b33 100644 --- a/src/mbgl/map/transform_state.hpp +++ b/src/mbgl/map/transform_state.hpp @@ -93,7 +93,7 @@ private: double angle = 0; double scale = 1; double altitude = 1.5; - double pitch = 0.001; + double pitch = 0.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 b2a2dcb2a..59507f721 100644 --- a/src/mbgl/renderer/gl_config.hpp +++ b/src/mbgl/renderer/gl_config.hpp @@ -117,7 +117,6 @@ 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 74268a401..6b78ca40d 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -154,10 +154,6 @@ void Painter::clear() { MBGL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); } -void Painter::setStrata(float value) { - strata = value; -} - void Painter::prepareTile(const Tile& tile) { const GLint ref = (GLint)tile.clip.reference.to_ulong(); const GLuint mask = (GLuint)tile.clip.mask.to_ulong(); @@ -223,19 +219,19 @@ void Painter::render(const Style& style, TransformState state_, const FrameData& if (debug::renderTree) { Log::Info(Event::Render, "{"); indent++; } // TODO: Correctly compute the number of layers recursively beforehand. - const float strataThickness = 1.0f / (order.size() + 1); + depthRangeSize = 1 - (order.size() + 2) * numSublayers * depthEpsilon; // - OPAQUE PASS ------------------------------------------------------------------------------- // Render everything top-to-bottom by using reverse iterators. Render opaque objects first. renderPass(RenderPass::Opaque, order.rbegin(), order.rend(), - 0, 1, strataThickness); + 0, 1); // - TRANSLUCENT PASS -------------------------------------------------------------------------- // Make a second pass, rendering translucent objects. This time, we render bottom-to-top. renderPass(RenderPass::Translucent, order.begin(), order.end(), - order.size() - 1, -1, strataThickness); + order.size() - 1, -1); if (debug::renderTree) { Log::Info(Event::Render, "}"); indent--; } @@ -266,8 +262,7 @@ void Painter::render(const Style& style, TransformState state_, const FrameData& template void Painter::renderPass(RenderPass pass_, Iterator it, Iterator end, - std::size_t i, int8_t increment, - const float strataThickness) { + std::size_t i, int8_t increment) { pass = pass_; const double zoom = state.getZoom(); @@ -282,6 +277,7 @@ void Painter::renderPass(RenderPass pass_, config.blend = pass == RenderPass::Translucent; for (; it != end; ++it, i += increment) { + currentLayer = i; const auto& item = *it; if (item.bucket && item.tile) { // Skip this layer if it's outside the range of min/maxzoom. @@ -293,13 +289,11 @@ void Painter::renderPass(RenderPass pass_, } if (item.layer.hasRenderPass(pass)) { MBGL_DEBUG_GROUP(item.layer.id + " - " + std::string(item.tile->id)); - setStrata(i * strataThickness); prepareTile(*item.tile); item.bucket->render(*this, item.layer, item.tile->id, item.tile->matrix); } } else { MBGL_DEBUG_GROUP("background"); - setStrata(i * strataThickness); renderBackground(item.layer); } } @@ -426,7 +420,8 @@ void Painter::renderBackground(const StyleLayer &layer_desc) { config.stencilTest = false; config.depthTest = true; - config.depthRange = { strata + strata_epsilon, 1.0f }; + config.depthRange = { 1.0f, 1.0f }; + MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); } @@ -455,3 +450,9 @@ mat4 Painter::translatedMatrix(const mat4& matrix, const std::array &t return vtxMatrix; } } + +void Painter::setDepthSublayer(int n) { + float nearDepth = ((1 + currentLayer) * numSublayers + n) * depthEpsilon; + float farDepth = nearDepth + depthRangeSize; + config.depthRange = { nearDepth, farDepth }; +} diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp index 78cf308b7..da67ffdd7 100644 --- a/src/mbgl/renderer/painter.hpp +++ b/src/mbgl/renderer/painter.hpp @@ -123,9 +123,6 @@ public: // Changes whether debug information is drawn onto the map void setDebug(bool enabled); - // Configures the painter strata that is used for early z-culling of fragments. - void setStrata(float strata); - void drawClippingMasks(const std::set&); void drawClippingMask(const mat4& matrix, const ClipID& clip); @@ -146,8 +143,7 @@ private: template void renderPass(RenderPass, Iterator it, Iterator end, - std::size_t i, int8_t iIncrement, - const float strataThickness); + std::size_t i, int8_t increment); void prepareTile(const Tile& tile); @@ -162,6 +158,8 @@ private: SDFShader& sdfShader, void (SymbolBucket::*drawSDF)(SDFShader&)); + void setDepthSublayer(int n); + public: void useProgram(uint32_t program); void lineWidth(float lineWidth); @@ -199,13 +197,16 @@ private: uint32_t gl_program = 0; float gl_lineWidth = 0; std::array gl_viewport = {{ 0, 0 }}; - float strata = 0; RenderPass pass = RenderPass::Opaque; - const float strata_epsilon = 1.0f / (1 << 16); Color background = {{ 0, 0, 0, 0 }}; std::vector order; + int numSublayers = 3; + int currentLayer; + float depthRangeSize; + const float depthEpsilon = 1.0f / (1 << 16); + public: FrameHistory frameHistory; diff --git a/src/mbgl/renderer/painter_fill.cpp b/src/mbgl/renderer/painter_fill.cpp index 414ec2bbc..d27feb469 100644 --- a/src/mbgl/renderer/painter_fill.cpp +++ b/src/mbgl/renderer/painter_fill.cpp @@ -55,7 +55,7 @@ void Painter::renderFill(FillBucket& bucket, const StyleLayer &layer_desc, const static_cast(frame.framebufferSize[0]), static_cast(frame.framebufferSize[1]) }}; - config.depthRange = { strata, 1.0f }; + setDepthSublayer(0); bucket.drawVertices(*outlineShader); } @@ -95,7 +95,7 @@ void Painter::renderFill(FillBucket& bucket, const StyleLayer &layer_desc, const // Draw the actual triangles into the color & stencil buffer. config.depthMask = GL_TRUE; - config.depthRange = { strata, 1.0f }; + setDepthSublayer(0); bucket.drawElements(*patternShader); } } @@ -112,7 +112,7 @@ void Painter::renderFill(FillBucket& bucket, const StyleLayer &layer_desc, const // Draw the actual triangles into the color & stencil buffer. config.depthMask = GL_TRUE; - config.depthRange = { strata + strata_epsilon, 1.0f }; + setDepthSublayer(1); bucket.drawElements(*plainShader); } } @@ -132,7 +132,7 @@ void Painter::renderFill(FillBucket& bucket, const StyleLayer &layer_desc, const static_cast(frame.framebufferSize[1]) }}; - config.depthRange = { strata + strata_epsilon + strata_epsilon, 1.0f }; + setDepthSublayer(2); bucket.drawVertices(*outlineShader); } } diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp index cf586c05e..0b7e8a96f 100644 --- a/src/mbgl/renderer/painter_line.cpp +++ b/src/mbgl/renderer/painter_line.cpp @@ -67,7 +67,7 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const mat4 vtxMatrix = translatedMatrix(matrix, properties.translate, id, properties.translateAnchor); - config.depthRange = { strata, 1.0f }; + setDepthSublayer(0); if (!properties.dash_array.from.empty()) { @@ -125,7 +125,6 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const MBGL_CHECK_ERROR(glActiveTexture(GL_TEXTURE0)); spriteAtlas->bind(true); - config.depthRange = { strata + strata_epsilon, 1.0f }; // may or may not matter bucket.drawLinePatterns(*linepatternShader); diff --git a/src/mbgl/renderer/painter_raster.cpp b/src/mbgl/renderer/painter_raster.cpp index 2a8f8e707..70cbcb4ca 100644 --- a/src/mbgl/renderer/painter_raster.cpp +++ b/src/mbgl/renderer/painter_raster.cpp @@ -24,7 +24,7 @@ void Painter::renderRaster(RasterBucket& bucket, const StyleLayer &layer_desc, c config.stencilTest = true; config.depthTest = true; - config.depthRange = { strata + strata_epsilon, 1.0f }; + setDepthSublayer(0); bucket.drawRaster(*rasterShader, tileStencilBuffer, coveringRasterArray); } } diff --git a/src/mbgl/renderer/painter_symbol.cpp b/src/mbgl/renderer/painter_symbol.cpp index c64f32620..c6ea37239 100644 --- a/src/mbgl/renderer/painter_symbol.cpp +++ b/src/mbgl/renderer/painter_symbol.cpp @@ -100,7 +100,7 @@ void Painter::renderSDF(SymbolBucket &bucket, sdfShader.u_buffer = (haloOffset - styleProperties.halo_width / fontScale) / sdfPx; - config.depthRange = { strata, 1.0f }; + setDepthSublayer(0); (bucket.*drawSDF)(sdfShader); } @@ -121,7 +121,7 @@ void Painter::renderSDF(SymbolBucket &bucket, sdfShader.u_buffer = (256.0f - 64.0f) / 256.0f; - config.depthRange = { strata + strata_epsilon, 1.0f }; + setDepthSublayer(1); (bucket.*drawSDF)(sdfShader); } } @@ -147,7 +147,7 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c collisionBoxShader->u_maxzoom = (id.z + 1) * 10; lineWidth(1.0f); - config.depthRange = { strata, 1.0f }; + setDepthSublayer(0); bucket.drawCollisionBoxes(*collisionBoxShader); } @@ -230,7 +230,7 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c iconShader->u_fadezoom = state.getNormalizedZoom() * 10; iconShader->u_opacity = properties.icon.opacity; - config.depthRange = { strata, 1.0f }; + setDepthSublayer(0); bucket.drawIcons(*iconShader); } } diff --git a/src/mbgl/shader/plain.vertex.glsl b/src/mbgl/shader/plain.vertex.glsl index 7ccbed12b..866c3cd2f 100644 --- a/src/mbgl/shader/plain.vertex.glsl +++ b/src/mbgl/shader/plain.vertex.glsl @@ -4,5 +4,4 @@ uniform mat4 u_matrix; void main() { gl_Position = u_matrix * vec4(a_pos, 0, 1); - gl_Position.z = 1.0; } From 14dee43a713d7155073630687a5ba6975d70f62b Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Tue, 18 Aug 2015 08:47:08 -0400 Subject: [PATCH 16/41] add map.setPitch(pitch) and map.getPitch() --- include/mbgl/map/map.hpp | 4 ++++ src/mbgl/map/map.cpp | 12 ++++++++++++ src/mbgl/map/transform.cpp | 9 +++++++++ src/mbgl/map/transform.hpp | 4 ++++ 4 files changed, 29 insertions(+) diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index ebd79620d..bd8847d42 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -123,6 +123,10 @@ public: double getBearing() const; void resetNorth(); + // Pitch + void setPitch(double pitch); + double getPitch() const; + // Size uint16_t getWidth() const; uint16_t getHeight() const; diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 9bfb04841..e70972a13 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -269,6 +269,18 @@ void Map::resetNorth() { } +#pragma mark - Pitch + +void Map::setPitch(double pitch) { + transform->setPitch(std::min(pitch, 60.0) * M_PI / 180); + update(Update::Repaint); +} + +double Map::getPitch() const { + return transform->getPitch() / M_PI * 180; +} + + #pragma mark - Projection void Map::getWorldBoundsMeters(ProjectedMeters& sw, ProjectedMeters& ne) const { diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp index ea8775dbc..7ccc2ad4c 100644 --- a/src/mbgl/map/transform.cpp +++ b/src/mbgl/map/transform.cpp @@ -347,6 +347,15 @@ double Transform::getAngle() const { return state.angle; } +#pragma mark - Pitch + +void Transform::setPitch(double pitch) { + state.pitch = pitch; +} + +double Transform::getPitch() const { + return state.pitch; +} #pragma mark - Transition diff --git a/src/mbgl/map/transform.hpp b/src/mbgl/map/transform.hpp index 57dc8c453..5d5a72d6d 100644 --- a/src/mbgl/map/transform.hpp +++ b/src/mbgl/map/transform.hpp @@ -41,6 +41,10 @@ public: void setAngle(double angle, double cx, double cy); double getAngle() const; + // Pitch + void setPitch(double pitch); + double getPitch() const; + // Transitions Update updateTransitions(const TimePoint& now); void cancelTransitions(); From 19c256e34916d123b758c42befc2c13dc0f5c3fa Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Tue, 18 Aug 2015 09:31:40 -0400 Subject: [PATCH 17/41] make fill-image tests less sensitive --- src/mbgl/renderer/painter.hpp | 2 +- test/suite | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp index da67ffdd7..dfe13fa2d 100644 --- a/src/mbgl/renderer/painter.hpp +++ b/src/mbgl/renderer/painter.hpp @@ -203,7 +203,7 @@ private: std::vector order; int numSublayers = 3; - int currentLayer; + size_t currentLayer; float depthRangeSize; const float depthEpsilon = 1.0f / (1 << 16); diff --git a/test/suite b/test/suite index b6828212d..b3a0cddc8 160000 --- a/test/suite +++ b/test/suite @@ -1 +1 @@ -Subproject commit b6828212d3fe5a06e1e91df1dc9a212cb5656093 +Subproject commit b3a0cddc8ae488df6ed2fc966a51c86f0fe78cd7 From 99c5976498f09ca2dffd46dd6e26d2a26b9efc13 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Thu, 20 Aug 2015 13:18:48 -0400 Subject: [PATCH 18/41] port minor collision code cleanup, fix #1705 https://github.com/mapbox/mapbox-gl-js/pull/1261 --- src/mbgl/map/live_tile_data.cpp | 4 +- src/mbgl/map/tile_worker.cpp | 11 ++--- src/mbgl/map/tile_worker.hpp | 2 +- src/mbgl/map/vector_tile_data.cpp | 4 +- src/mbgl/renderer/bucket.hpp | 3 +- src/mbgl/renderer/symbol_bucket.cpp | 71 ++++++++++++++--------------- src/mbgl/renderer/symbol_bucket.hpp | 21 ++++++--- src/mbgl/text/collision_tile.cpp | 8 ++-- src/mbgl/text/collision_tile.hpp | 9 +--- src/mbgl/text/quads.cpp | 42 ++++++++--------- src/mbgl/text/quads.hpp | 6 +-- 11 files changed, 89 insertions(+), 92 deletions(-) diff --git a/src/mbgl/map/live_tile_data.cpp b/src/mbgl/map/live_tile_data.cpp index 9ac9c730f..0b73b52f3 100644 --- a/src/mbgl/map/live_tile_data.cpp +++ b/src/mbgl/map/live_tile_data.cpp @@ -25,9 +25,7 @@ LiveTileData::LiveTileData(const TileID& id_, style_, style_.layers, state, - std::make_unique(id_.z, 4096, - source_.tile_size * id.overscaling, - 0, 0, false)) { + std::make_unique(0, 0, false)) { state = State::loaded; if (!tile) { diff --git a/src/mbgl/map/tile_worker.cpp b/src/mbgl/map/tile_worker.cpp index 0b9175c53..06de585a3 100644 --- a/src/mbgl/map/tile_worker.cpp +++ b/src/mbgl/map/tile_worker.cpp @@ -25,7 +25,7 @@ TileWorker::TileWorker(TileID id_, maxZoom(maxZoom_), style(style_), state(state_), - collision(std::move(collision_)) { + collisionTile(std::move(collision_)) { assert(style.sprite); } @@ -56,12 +56,11 @@ TileParseResult TileWorker::parse(const GeometryTile& geometryTile) { } void TileWorker::redoPlacement(float angle, float pitch, bool collisionDebug) { - collision->reset(angle, pitch); - collision->setDebug(collisionDebug); + collisionTile = std::make_unique(angle, pitch, collisionDebug); for (auto i = layers.rbegin(); i != layers.rend(); i++) { auto bucket = getBucket(**i); if (bucket) { - bucket->placeFeatures(); + bucket->placeFeatures(*collisionTile); } } } @@ -224,7 +223,7 @@ std::unique_ptr TileWorker::createCircleBucket(const GeometryTileLayer& std::unique_ptr TileWorker::createSymbolBucket(const GeometryTileLayer& layer, const StyleBucket& bucket_desc) { - auto bucket = std::make_unique(*collision, id.overscaling); + auto bucket = std::make_unique(id.overscaling, id.z); const float z = id.z; auto& layout = bucket->layout; @@ -283,7 +282,7 @@ std::unique_ptr TileWorker::createSymbolBucket(const GeometryTileLayer& } bucket->addFeatures(reinterpret_cast(this), *style.spriteAtlas, *style.glyphAtlas, - *style.glyphStore); + *style.glyphStore, *collisionTile); return bucket->hasData() ? std::move(bucket) : nullptr; } diff --git a/src/mbgl/map/tile_worker.hpp b/src/mbgl/map/tile_worker.hpp index b8a93011e..62527b9fd 100644 --- a/src/mbgl/map/tile_worker.hpp +++ b/src/mbgl/map/tile_worker.hpp @@ -75,7 +75,7 @@ private: TriangleElementsBuffer triangleElementsBuffer; LineElementsBuffer lineElementsBuffer; - std::unique_ptr collision; + std::unique_ptr collisionTile; // Contains all the Bucket objects for the tile. Buckets are render // objects and they get added to this map as they get processed. diff --git a/src/mbgl/map/vector_tile_data.cpp b/src/mbgl/map/vector_tile_data.cpp index 60297396e..678a3867c 100644 --- a/src/mbgl/map/vector_tile_data.cpp +++ b/src/mbgl/map/vector_tile_data.cpp @@ -26,9 +26,7 @@ VectorTileData::VectorTileData(const TileID& id_, style_, style_.layers, state, - std::make_unique(id_.z, 4096, - source_.tile_size * id.overscaling, - angle, pitch, collisionDebug)), + std::make_unique(angle, pitch, collisionDebug)), source(source_), lastAngle(angle), currentAngle(angle) { diff --git a/src/mbgl/renderer/bucket.hpp b/src/mbgl/renderer/bucket.hpp index 4bdb766a7..c6a7b788d 100644 --- a/src/mbgl/renderer/bucket.hpp +++ b/src/mbgl/renderer/bucket.hpp @@ -12,6 +12,7 @@ namespace mbgl { class Painter; class StyleLayer; class TileID; +class CollisionTile; class Bucket : private util::noncopyable { public: @@ -29,7 +30,7 @@ public: return !uploaded; } - virtual void placeFeatures() {} + virtual void placeFeatures(CollisionTile&) {} virtual void swapRenderData() {} protected: diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp index 16ba3cf1a..7665fd9a6 100644 --- a/src/mbgl/renderer/symbol_bucket.cpp +++ b/src/mbgl/renderer/symbol_bucket.cpp @@ -53,8 +53,8 @@ SymbolInstance::SymbolInstance(Anchor &anchor, const std::vector &li iconCollisionFeature(line, anchor, shapedIcon, iconBoxScale, iconPadding, iconAlongLine) {}; -SymbolBucket::SymbolBucket(CollisionTile &collision_, float overscaling_) - : collision(collision_), overscaling(overscaling_) { +SymbolBucket::SymbolBucket(float overscaling_, float zoom_) + : overscaling(overscaling_), zoom(zoom_), tileSize(512 * overscaling_), tilePixelRatio(tileExtent / tileSize) { } SymbolBucket::~SymbolBucket() { @@ -174,7 +174,8 @@ bool SymbolBucket::needsDependencies(const GeometryTileLayer& layer, void SymbolBucket::addFeatures(uintptr_t tileUID, SpriteAtlas& spriteAtlas, GlyphAtlas& glyphAtlas, - GlyphStore& glyphStore) { + GlyphStore& glyphStore, + CollisionTile& collisionTile) { float horizontalAlign = 0.5; float verticalAlign = 0.5; @@ -264,7 +265,7 @@ void SymbolBucket::addFeatures(uintptr_t tileUID, features.clear(); - placeFeatures(true); + placeFeatures(collisionTile, true); } @@ -275,13 +276,13 @@ void SymbolBucket::addFeature(const std::vector> &lines, const float glyphSize = 24.0f; const float fontScale = layout.text.size / glyphSize; - const float textBoxScale = collision.tilePixelRatio * fontScale; - const float textMaxBoxScale = collision.tilePixelRatio * layout.text.max_size / glyphSize; - const float iconBoxScale = collision.tilePixelRatio * layout.icon.size; - const float symbolSpacing = collision.tilePixelRatio * layout.spacing; + const float textBoxScale = tilePixelRatio * fontScale; + const float textMaxBoxScale = tilePixelRatio * layout.text.max_size / glyphSize; + const float iconBoxScale = tilePixelRatio * layout.icon.size; + const float symbolSpacing = tilePixelRatio * layout.spacing; const bool avoidEdges = layout.avoid_edges && layout.placement != PlacementType::Line; - const float textPadding = layout.text.padding * collision.tilePixelRatio; - const float iconPadding = layout.icon.padding * collision.tilePixelRatio; + const float textPadding = layout.text.padding * tilePixelRatio; + const float iconPadding = layout.icon.padding * tilePixelRatio; const float textMaxAngle = layout.text.max_angle * M_PI / 180; const bool textAlongLine = layout.text.rotation_alignment == RotationAlignmentType::Map && @@ -354,11 +355,11 @@ bool SymbolBucket::anchorIsTooClose(const std::u32string &text, const float repe return false; } -void SymbolBucket::placeFeatures() { - placeFeatures(false); +void SymbolBucket::placeFeatures(CollisionTile& collisionTile) { + placeFeatures(collisionTile, false); } -void SymbolBucket::placeFeatures(bool swapImmediately) { +void SymbolBucket::placeFeatures(CollisionTile& collisionTile, bool swapImmediately) { renderDataInProgress = std::make_unique(); @@ -380,8 +381,8 @@ void SymbolBucket::placeFeatures(bool swapImmediately) { // Don't sort symbols that won't overlap because it isn't necessary and // because it causes more labels to pop in and out when rotating. if (mayOverlap) { - float sin = std::sin(collision.angle); - float cos = std::cos(collision.angle); + float sin = std::sin(collisionTile.angle); + float cos = std::cos(collisionTile.angle); std::sort(symbolInstances.begin(), symbolInstances.end(), [sin, cos](SymbolInstance &a, SymbolInstance &b) { const float aRotated = sin * a.x + cos * a.y; @@ -401,9 +402,9 @@ void SymbolBucket::placeFeatures(bool swapImmediately) { // Calculate the scales at which the text and icon can be placed without collision. float glyphScale = hasText && !layout.text.allow_overlap ? - collision.placeFeature(symbolInstance.textCollisionFeature) : collision.minScale; + collisionTile.placeFeature(symbolInstance.textCollisionFeature) : collisionTile.minScale; float iconScale = hasIcon && !layout.icon.allow_overlap ? - collision.placeFeature(symbolInstance.iconCollisionFeature) : collision.minScale; + collisionTile.placeFeature(symbolInstance.iconCollisionFeature) : collisionTile.minScale; // Combine the scales for icons and text. @@ -421,33 +422,32 @@ void SymbolBucket::placeFeatures(bool swapImmediately) { if (hasText) { if (!layout.text.ignore_placement) { - collision.insertFeature(symbolInstance.textCollisionFeature, glyphScale); + collisionTile.insertFeature(symbolInstance.textCollisionFeature, glyphScale); } - if (glyphScale < collision.maxScale) { + if (glyphScale < collisionTile.maxScale) { addSymbols(renderDataInProgress->text, - symbolInstance.glyphQuads, glyphScale, layout.text.keep_upright, textAlongLine); + symbolInstance.glyphQuads, glyphScale, layout.text.keep_upright, textAlongLine, collisionTile.angle); } } if (hasIcon) { if (!layout.icon.ignore_placement) { - collision.insertFeature(symbolInstance.iconCollisionFeature, iconScale); + collisionTile.insertFeature(symbolInstance.iconCollisionFeature, iconScale); } - if (iconScale < collision.maxScale) { + if (iconScale < collisionTile.maxScale) { addSymbols(renderDataInProgress->icon, - symbolInstance.iconQuads, iconScale, layout.icon.keep_upright, iconAlongLine); + symbolInstance.iconQuads, iconScale, layout.icon.keep_upright, iconAlongLine, collisionTile.angle); } } } - if (collision.getDebug()) addToDebugBuffers(); + if (collisionTile.getDebug()) addToDebugBuffers(collisionTile); if (swapImmediately) swapRenderData(); } template -void SymbolBucket::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float scale, const bool keepUpright, const bool alongLine) { - const float zoom = collision.zoom; +void SymbolBucket::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float scale, const bool keepUpright, const bool alongLine, const float placementAngle) { const float placementZoom = ::fmax(std::log(scale) / std::log(2) + zoom, 0); @@ -461,10 +461,10 @@ void SymbolBucket::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float float minZoom = util::max(static_cast(zoom + log(symbol.minScale) / log(2)), placementZoom); float maxZoom = util::min(static_cast(zoom + log(symbol.maxScale) / log(2)), 25.0f); - const auto &glyphAnchor = symbol.anchor; + const auto &anchorPoint = symbol.anchorPoint; // drop upside down versions of glyphs - const float a = std::fmod(symbol.angle + collision.angle + M_PI, M_PI * 2); + const float a = std::fmod(symbol.angle + placementAngle + M_PI, M_PI * 2); if (keepUpright && alongLine && (a <= M_PI / 2 || a > M_PI * 3 / 2)) continue; @@ -491,13 +491,13 @@ void SymbolBucket::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float uint32_t triangleIndex = triangleGroup.vertex_length; // coordinates (2 triangles) - buffer.vertices.add(glyphAnchor.x, glyphAnchor.y, tl.x, tl.y, tex.x, tex.y, minZoom, + buffer.vertices.add(anchorPoint.x, anchorPoint.y, tl.x, tl.y, tex.x, tex.y, minZoom, maxZoom, placementZoom); - buffer.vertices.add(glyphAnchor.x, glyphAnchor.y, tr.x, tr.y, tex.x + tex.w, tex.y, + buffer.vertices.add(anchorPoint.x, anchorPoint.y, tr.x, tr.y, tex.x + tex.w, tex.y, minZoom, maxZoom, placementZoom); - buffer.vertices.add(glyphAnchor.x, glyphAnchor.y, bl.x, bl.y, tex.x, tex.y + tex.h, + buffer.vertices.add(anchorPoint.x, anchorPoint.y, bl.x, bl.y, tex.x, tex.y + tex.h, minZoom, maxZoom, placementZoom); - buffer.vertices.add(glyphAnchor.x, glyphAnchor.y, br.x, br.y, tex.x + tex.w, tex.y + tex.h, + buffer.vertices.add(anchorPoint.x, anchorPoint.y, br.x, br.y, tex.x + tex.w, tex.y + tex.h, minZoom, maxZoom, placementZoom); // add the two triangles, referencing the four coordinates we just inserted. @@ -509,11 +509,10 @@ void SymbolBucket::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float } } -void SymbolBucket::addToDebugBuffers() { +void SymbolBucket::addToDebugBuffers(CollisionTile &collisionTile) { - const float yStretch = collision.yStretch; - const float angle = collision.angle; - const float zoom = collision.zoom; + const float yStretch = collisionTile.yStretch; + const float angle = collisionTile.angle; float angle_sin = std::sin(-angle); float angle_cos = std::cos(-angle); std::array matrix = {{angle_cos, -angle_sin, angle_sin, angle_cos}}; diff --git a/src/mbgl/renderer/symbol_bucket.hpp b/src/mbgl/renderer/symbol_bucket.hpp index 3a181be55..c8264bc43 100644 --- a/src/mbgl/renderer/symbol_bucket.hpp +++ b/src/mbgl/renderer/symbol_bucket.hpp @@ -64,7 +64,7 @@ class SymbolBucket : public Bucket { typedef ElementGroup<1> CollisionBoxElementGroup; public: - SymbolBucket(CollisionTile &collision, float overscaling); + SymbolBucket(float overscaling, float zoom); ~SymbolBucket() override; void upload() override; @@ -77,7 +77,8 @@ public: void addFeatures(uintptr_t tileUID, SpriteAtlas&, GlyphAtlas&, - GlyphStore&); + GlyphStore&, + CollisionTile&); void drawGlyphs(SDFShader& shader); void drawIcons(SDFShader& shader); @@ -88,7 +89,7 @@ public: const FilterExpression&, GlyphStore&, Sprite&); - void placeFeatures() override; + void placeFeatures(CollisionTile&) override; private: void addFeature(const std::vector> &lines, @@ -97,22 +98,28 @@ private: bool anchorIsTooClose(const std::u32string &text, const float repeatDistance, Anchor &anchor); std::map> compareText; - void addToDebugBuffers(); + void addToDebugBuffers(CollisionTile &collisionTile); - void placeFeatures(bool swapImmediately); + void placeFeatures(CollisionTile& collisionTile, bool swapImmediately); void swapRenderData() override; // Adds placed items to the buffer. template - void addSymbols(Buffer &buffer, const SymbolQuads &symbols, float scale, const bool keepUpright, const bool alongLine); + void addSymbols(Buffer &buffer, const SymbolQuads &symbols, float scale, + const bool keepUpright, const bool alongLine, const float placementAngle); public: StyleLayoutSymbol layout; bool sdfIcons = false; private: - CollisionTile &collision; + const float overscaling; + const float zoom; + const float tileSize; + const float tileExtent = 4096.0f; + const float tilePixelRatio; + std::vector symbolInstances; std::vector features; diff --git a/src/mbgl/text/collision_tile.cpp b/src/mbgl/text/collision_tile.cpp index b80d756c3..d18860ccf 100644 --- a/src/mbgl/text/collision_tile.cpp +++ b/src/mbgl/text/collision_tile.cpp @@ -3,13 +3,13 @@ namespace mbgl { -void CollisionTile::reset(const float _angle, const float pitch) { +CollisionTile::CollisionTile(const float angle_, const float pitch, bool debug_) : + angle(angle_), debug(debug_) { tree.clear(); - angle = _angle; // Compute the transformation matrix. - float angle_sin = std::sin(_angle); - float angle_cos = std::cos(_angle); + float angle_sin = std::sin(angle); + float angle_cos = std::cos(angle); rotationMatrix = {{angle_cos, -angle_sin, angle_sin, angle_cos}}; // Stretch boxes in y direction to account for the map tilt. diff --git a/src/mbgl/text/collision_tile.hpp b/src/mbgl/text/collision_tile.hpp index 632652256..3fd1b0a4c 100644 --- a/src/mbgl/text/collision_tile.hpp +++ b/src/mbgl/text/collision_tile.hpp @@ -35,19 +35,14 @@ namespace mbgl { class CollisionTile { public: - inline explicit CollisionTile(float _zoom, float tileExtent, float tileSize, float angle_, float pitch_, bool debug_) : - zoom(_zoom), tilePixelRatio(tileExtent / tileSize), debug(debug_) { reset(angle_, pitch_); } + explicit CollisionTile(float angle_, float pitch_, bool debug_); - void reset(const float angle, const float pitch); float placeFeature(const CollisionFeature &feature); void insertFeature(CollisionFeature &feature, const float minPlacementScale); - void setDebug(bool debug_) { debug = debug_; } bool getDebug() { return debug; } - const float zoom; - const float tilePixelRatio; - float angle = 0; + const float angle = 0; const float minScale = 0.5f; const float maxScale = 2.0f; diff --git a/src/mbgl/text/quads.cpp b/src/mbgl/text/quads.cpp index 943439615..19c48d731 100644 --- a/src/mbgl/text/quads.cpp +++ b/src/mbgl/text/quads.cpp @@ -50,12 +50,12 @@ SymbolQuads getIconQuads(Anchor &anchor, const PositionedIcon &shapedIcon, } struct GlyphInstance { - explicit GlyphInstance(const vec2 &anchor_) : anchor(anchor_) {} - explicit GlyphInstance(const vec2 &anchor_, float offset_, float minScale_, float maxScale_, + explicit GlyphInstance(const vec2 &anchorPoint_) : anchorPoint(anchorPoint_) {} + explicit GlyphInstance(const vec2 &anchorPoint_, float offset_, float minScale_, float maxScale_, float angle_) - : anchor(anchor_), offset(offset_), minScale(minScale_), maxScale(maxScale_), angle(angle_) {} + : anchorPoint(anchorPoint_), offset(offset_), minScale(minScale_), maxScale(maxScale_), angle(angle_) {} - const vec2 anchor; + const vec2 anchorPoint; const float offset = 0.0f; const float minScale = globalMinScale; const float maxScale = std::numeric_limits::infinity(); @@ -65,19 +65,19 @@ struct GlyphInstance { typedef std::vector GlyphInstances; void getSegmentGlyphs(std::back_insert_iterator glyphs, Anchor &anchor, - float offset, const std::vector &line, int segment, int8_t direction) { + float offset, const std::vector &line, int segment, bool forward) { - const bool upsideDown = direction < 0; + const bool upsideDown = !forward; if (offset < 0) - direction *= -1; + forward = !forward; - if (direction > 0) + if (forward) segment++; assert((int)line.size() > segment); vec2 end = line[segment]; - vec2 newAnchor = anchor; + vec2 newAnchorPoint = anchor; float prevscale = std::numeric_limits::infinity(); offset = std::fabs(offset); @@ -85,16 +85,16 @@ void getSegmentGlyphs(std::back_insert_iterator glyphs, Anchor & const float placementScale = anchor.scale; while (true) { - const float dist = util::dist(newAnchor, end); + const float dist = util::dist(newAnchorPoint, end); const float scale = offset / dist; - float angle = std::atan2(end.y - newAnchor.y, end.x - newAnchor.x); - if (direction < 0) + float angle = std::atan2(end.y - newAnchorPoint.y, end.x - newAnchorPoint.x); + if (!forward) angle += M_PI; if (upsideDown) angle += M_PI; glyphs = GlyphInstance{ - /* anchor */ newAnchor, + /* anchor */ newAnchorPoint, /* offset */ static_cast(upsideDown ? M_PI : 0.0), /* minScale */ scale, /* maxScale */ prevscale, @@ -103,11 +103,11 @@ void getSegmentGlyphs(std::back_insert_iterator glyphs, Anchor & if (scale <= placementScale) break; - newAnchor = end; + newAnchorPoint = end; // skip duplicate nodes - while (newAnchor == end) { - segment += direction; + while (newAnchorPoint == end) { + segment += forward ? 1 : -1; if ((int)line.size() <= segment || segment < 0) { anchor.scale = scale; return; @@ -115,8 +115,8 @@ void getSegmentGlyphs(std::back_insert_iterator glyphs, Anchor & end = line[segment]; } - vec2 normal = util::normal(newAnchor, end) * dist; - newAnchor = newAnchor - normal; + vec2 normal = util::normal(newAnchorPoint, end) * dist; + newAnchorPoint = newAnchorPoint - normal; prevscale = scale; } @@ -148,9 +148,9 @@ SymbolQuads getGlyphQuads(Anchor &anchor, const Shaping &shapedText, GlyphInstances glyphInstances; if (alongLine) { - getSegmentGlyphs(std::back_inserter(glyphInstances), anchor, centerX, line, anchor.segment, 1); + getSegmentGlyphs(std::back_inserter(glyphInstances), anchor, centerX, line, anchor.segment, true); if (keepUpright) - getSegmentGlyphs(std::back_inserter(glyphInstances), anchor, centerX, line, anchor.segment, -1); + getSegmentGlyphs(std::back_inserter(glyphInstances), anchor, centerX, line, anchor.segment, false); } else { glyphInstances.emplace_back(GlyphInstance{anchor}); @@ -194,7 +194,7 @@ SymbolQuads getGlyphQuads(Anchor &anchor, const Shaping &shapedText, const float glyphMinScale = std::max(instance.minScale, anchor.scale); const float glyphAngle = std::fmod((anchor.angle + textRotate + instance.offset + 2 * M_PI), (2 * M_PI)); - quads.emplace_back(tl, tr, bl, br, rect, glyphAngle, instance.anchor, glyphMinScale, instance.maxScale); + quads.emplace_back(tl, tr, bl, br, rect, glyphAngle, instance.anchorPoint, glyphMinScale, instance.maxScale); } diff --git a/src/mbgl/text/quads.hpp b/src/mbgl/text/quads.hpp index b47cc718b..97fdb6a1f 100644 --- a/src/mbgl/text/quads.hpp +++ b/src/mbgl/text/quads.hpp @@ -11,7 +11,7 @@ namespace mbgl { struct SymbolQuad { explicit SymbolQuad(const vec2 &tl_, const vec2 &tr_, const vec2 &bl_, const vec2 &br_, - const Rect &tex_, float angle_, const vec2 &anchor_, + const Rect &tex_, float angle_, const vec2 &anchorPoint_, float minScale_, float maxScale_) : tl(tl_), tr(tr_), @@ -19,14 +19,14 @@ namespace mbgl { br(br_), tex(tex_), angle(angle_), - anchor(anchor_), + anchorPoint(anchorPoint_), minScale(minScale_), maxScale(maxScale_) {} vec2 tl, tr, bl, br; Rect tex; float angle; - vec2 anchor; + vec2 anchorPoint; float minScale, maxScale; }; From 51c93867aeeb34fd423bd0fb85d2cc06f074b88b Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Thu, 20 Aug 2015 18:50:17 -0400 Subject: [PATCH 19/41] fix LatLng --> point for perspective views --- platform/ios/MGLMapView.mm | 8 -- src/mbgl/map/map.cpp | 4 +- src/mbgl/map/source.cpp | 2 +- src/mbgl/map/transform_state.cpp | 152 +++++++++++++------------------ src/mbgl/map/transform_state.hpp | 26 ++++-- src/mbgl/renderer/painter.cpp | 2 +- 6 files changed, 86 insertions(+), 108 deletions(-) diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index cdd3044dc..cdfa77935 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -1621,10 +1621,6 @@ mbgl::LatLngBounds MGLLatLngBoundsFromCoordinateBounds(MGLCoordinateBounds coord { CGPoint convertedPoint = [self convertPoint:point fromView:view]; - // flip y coordinate for iOS view origin top left - // - convertedPoint.y = self.bounds.size.height - convertedPoint.y; - return MGLLocationCoordinate2DFromLatLng(_mbglMap->latLngForPixel(mbgl::vec2(convertedPoint.x, convertedPoint.y))); } @@ -1632,10 +1628,6 @@ mbgl::LatLngBounds MGLLatLngBoundsFromCoordinateBounds(MGLCoordinateBounds coord { mbgl::vec2 pixel = _mbglMap->pixelForLatLng(MGLLatLngFromLocationCoordinate2D(coordinate)); - // flip y coordinate for iOS view origin in top left - // - pixel.y = self.bounds.size.height - pixel.y; - return [self convertPoint:CGPointMake(pixel.x, pixel.y) toView:view]; } diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index e70972a13..065c33ce5 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -304,11 +304,11 @@ const LatLng Map::latLngForProjectedMeters(const ProjectedMeters projectedMeters } const vec2 Map::pixelForLatLng(const LatLng latLng) const { - return transform->getState().pixelForLatLng(latLng); + return transform->getState().latLngToPoint(latLng); } const LatLng Map::latLngForPixel(const vec2 pixel) const { - return transform->getState().latLngForPixel(pixel); + return transform->getState().pointToLatLng(pixel); } #pragma mark - Annotations diff --git a/src/mbgl/map/source.cpp b/src/mbgl/map/source.cpp index f60ddce57..9aedf26a6 100644 --- a/src/mbgl/map/source.cpp +++ b/src/mbgl/map/source.cpp @@ -333,7 +333,7 @@ std::forward_list Source::coveringTiles(const TransformState& state) con // Map four viewport corners to pixel coordinates box points = state.cornersToBox(z); - const TileCoordinate center = state.pointCoordinate({ state.getWidth() / 2.0f, state.getHeight()/ 2.0f }).zoomTo(z); + const TileCoordinate center = state.pointToCoordinate({ state.getWidth() / 2.0f, state.getHeight()/ 2.0f }).zoomTo(z); std::forward_list covering_tiles = tileCover(z, points, reparseOverscaled ? actualZ : z); diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp index 2f6231828..9e4ea457e 100644 --- a/src/mbgl/map/transform_state.cpp +++ b/src/mbgl/map/transform_state.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -46,10 +45,10 @@ box TransformState::cornersToBox(uint32_t z) const { double w = width; double h = height; box b( - pointCoordinate({ 0, 0 }).zoomTo(z), - pointCoordinate({ w, 0 }).zoomTo(z), - pointCoordinate({ w, h }).zoomTo(z), - pointCoordinate({ 0, h }).zoomTo(z)); + pointToCoordinate({ 0, 0 }).zoomTo(z), + pointToCoordinate({ w, 0 }).zoomTo(z), + pointToCoordinate({ w, h }).zoomTo(z), + pointToCoordinate({ 0, h }).zoomTo(z)); return b; } @@ -158,94 +157,73 @@ float TransformState::getPitch() const { #pragma mark - Projection -const vec2 TransformState::pixelForLatLng(const LatLng latLng) const { - LatLng ll = getLatLng(); - double zoom = getZoom(); - - const double centerX = static_cast(width) / 2.0; - const double centerY = static_cast(height) / 2.0; - - const double m = Projection::getMetersPerPixelAtLatitude(0, zoom); - - const double angle_sin = std::sin(-angle); - const double angle_cos = std::cos(-angle); - - const ProjectedMeters givenMeters = Projection::projectedMetersForLatLng(latLng); - - const double givenAbsoluteX = givenMeters.easting / m; - const double givenAbsoluteY = givenMeters.northing / m; - - const ProjectedMeters centerMeters = Projection::projectedMetersForLatLng(ll); - - const double centerAbsoluteX = centerMeters.easting / m; - const double centerAbsoluteY = centerMeters.northing / m; - - const double deltaX = givenAbsoluteX - centerAbsoluteX; - const double deltaY = givenAbsoluteY - centerAbsoluteY; - - const double translatedX = deltaX + centerX; - const double translatedY = deltaY + centerY; - - const double rotatedX = translatedX * angle_cos - translatedY * angle_sin; - const double rotatedY = translatedX * angle_sin + translatedY * angle_cos; - - const double rotatedCenterX = centerX * angle_cos - centerY * angle_sin; - const double rotatedCenterY = centerX * angle_sin + centerY * angle_cos; - - double x_ = rotatedX + (centerX - rotatedCenterX); - double y_ = rotatedY + (centerY - rotatedCenterY); - - return vec2(x_, y_); +float TransformState::lngX(float lng) const { + return (180.0f + lng) * worldSize() / 360.0f; } -const LatLng TransformState::latLngForPixel(const vec2 pixel) const { - LatLng ll = getLatLng(); - double zoom = getZoom(); - - const double centerX = static_cast(width) / 2.0; - const double centerY = static_cast(height) / 2.0; - - const double m = Projection::getMetersPerPixelAtLatitude(0, zoom); - - const double angle_sin = std::sin(angle); - const double angle_cos = std::cos(angle); - - const double unrotatedCenterX = centerX * angle_cos - centerY * angle_sin; - const double unrotatedCenterY = centerX * angle_sin + centerY * angle_cos; - - const double unrotatedX = pixel.x * angle_cos - pixel.y * angle_sin; - const double unrotatedY = pixel.x * angle_sin + pixel.y * angle_cos; - - const double givenX = unrotatedX + (centerX - unrotatedCenterX); - const double givenY = unrotatedY + (centerY - unrotatedCenterY); - - const ProjectedMeters centerMeters = Projection::projectedMetersForLatLng(ll); - - const double centerAbsoluteX = centerMeters.easting / m; - const double centerAbsoluteY = centerMeters.northing / m; - - const double givenAbsoluteX = givenX + centerAbsoluteX - centerX; - const double givenAbsoluteY = givenY + centerAbsoluteY - centerY; - - ProjectedMeters givenMeters = ProjectedMeters(givenAbsoluteY * m, givenAbsoluteX * m); - - // adjust for date line - ProjectedMeters sw, ne; - Projection::getWorldBoundsMeters(sw, ne); - double d = ne.easting - sw.easting; - if (ll.longitude > 0 && givenMeters.easting > centerMeters.easting) givenMeters.easting -= d; - - // adjust for world wrap - while (givenMeters.easting < sw.easting) givenMeters.easting += d; - while (givenMeters.easting > ne.easting) givenMeters.easting -= d; - - return Projection::latLngForProjectedMeters(givenMeters); +float TransformState::latY(float lat) const { + float y_ = 180.0f / M_PI * std::log(std::tan(M_PI / 4 + lat * M_PI / 360.0f)); + return (180.0f - y_) * worldSize() / 360.0f; } -TileCoordinate TransformState::pointCoordinate(const vec2 point) const { +float TransformState::xLng(float x_, float worldSize_) const { + return x_ * 360.0f / worldSize_ - 180.0f; +} + +float TransformState::yLat(float y_, float worldSize_) const { + float y2 = 180.0f - y_ * 360.0f / worldSize_; + return 360.0f / M_PI * std::atan(std::exp(y2 * M_PI / 180.0f)) - 90.0f; +} + +float TransformState::zoomScale(float zoom) const { + return std::pow(2.0f, zoom); +} + +float TransformState::worldSize() const { + return util::tileSize * scale; +} + +vec2 TransformState::latLngToPoint(const LatLng& latLng) const { + return coordinateToPoint(latLngToCoordinate(latLng)); +} + +LatLng TransformState::pointToLatLng(const vec2 point) const { + return coordinateToLatLng(pointToCoordinate(point)); +} + +TileCoordinate TransformState::latLngToCoordinate(const LatLng& latLng) const { + const float tileZoom = getIntegerZoom(); + const float k = zoomScale(tileZoom) / worldSize(); + return { + lngX(latLng.longitude) * k, + latY(latLng.latitude) * k, + tileZoom + }; +} + +LatLng TransformState::coordinateToLatLng(const TileCoordinate& coord) const { + const float worldSize_ = zoomScale(coord.zoom); + LatLng latLng = { + yLat(coord.row, worldSize_), + xLng(coord.column, worldSize_) + }; + while (latLng.longitude < 180.0f) latLng.longitude += 360.0f; + while (latLng.longitude > 180.0f) latLng.longitude -= 360.0f; + return latLng; +} + +vec2 TransformState::coordinateToPoint(const TileCoordinate& coord) const { + mat4 mat = coordinatePointMatrix(coord.zoom); + matrix::vec4 p; + matrix::vec4 c = {{ coord.column, coord.row, 0, 1 }}; + matrix::transformMat4(p, c, mat); + return { p[0] / p[3], p[1] / p[3] }; +} + +TileCoordinate TransformState::pointToCoordinate(const vec2 point) const { float targetZ = 0; - float tileZoom = std::floor(getZoom()); + const float tileZoom = getIntegerZoom(); mat4 mat = coordinatePointMatrix(tileZoom); diff --git a/src/mbgl/map/transform_state.hpp b/src/mbgl/map/transform_state.hpp index 521131b33..d4b46f04b 100644 --- a/src/mbgl/map/transform_state.hpp +++ b/src/mbgl/map/transform_state.hpp @@ -31,9 +31,6 @@ public: uint16_t getWidth() const; uint16_t getHeight() const; - float worldSize() const; - float lngX(float lon) const; - float latY(float lat) const; std::array locationCoordinate(float lon, float lat) const; void getLonLat(double &lon, double &lat) const; @@ -55,18 +52,22 @@ public: float getAltitude() const; float getPitch() const; - // Projection - const vec2 pixelForLatLng(const LatLng latLng) const; - const LatLng latLngForPixel(const vec2 pixel) const; - // Changing bool isChanging() const; double pixel_x() const; double pixel_y() const; - // Conversions - TileCoordinate pointCoordinate(const vec2 point) const; + // Conversion and projection + + vec2 latLngToPoint(const LatLng& latLng) const; + LatLng pointToLatLng(const vec2 point) const; + + TileCoordinate latLngToCoordinate(const LatLng& latLng) const; + LatLng coordinateToLatLng(const TileCoordinate& coord) const; + + vec2 coordinateToPoint(const TileCoordinate& coord) const; + TileCoordinate pointToCoordinate(const vec2 point) const; private: void constrain(double& scale, double& y) const; @@ -78,6 +79,13 @@ private: // logical dimensions uint16_t width = 0, height = 0; + float xLng(float x, float worldSize) const; + float yLat(float y, float worldSize) const; + float lngX(float lon) const; + float latY(float lat) const; + float zoomScale(float zoom) const; + float worldSize() const; + mat4 coordinatePointMatrix(float z) const; mat4 getPixelMatrix() const; diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index 6b78ca40d..9ea75efb8 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -379,7 +379,7 @@ void Painter::renderBackground(const StyleLayer &layer_desc) { patternShader->u_opacity = properties.opacity; LatLng latLng = state.getLatLng(); - vec2 center = state.pixelForLatLng(latLng); + vec2 center = state.latLngToPoint(latLng); float scale = 1 / std::pow(2, zoomFraction); std::array sizeA = imagePosA.size; From 10f0d8d23ab0d40254751220df76e28bac4786b8 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Mon, 24 Aug 2015 20:33:19 -0400 Subject: [PATCH 20/41] fix circle rendering --- src/mbgl/renderer/painter_circle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mbgl/renderer/painter_circle.cpp b/src/mbgl/renderer/painter_circle.cpp index 0c0ac1506..538ba9e6a 100644 --- a/src/mbgl/renderer/painter_circle.cpp +++ b/src/mbgl/renderer/painter_circle.cpp @@ -40,7 +40,7 @@ void Painter::renderCircle(CircleBucket& bucket, useProgram(circleShader->program); circleShader->u_matrix = vtxMatrix; - circleShader->u_exmatrix = projMatrix; + circleShader->u_exmatrix = extrudeMatrix; circleShader->u_color = color; circleShader->u_blur = std::max(properties.blur, antialiasing); circleShader->u_size = properties.radius; From 36d71c95dc36a182e2b27cf874ab4cbd168a8cd0 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Tue, 25 Aug 2015 11:59:02 -0400 Subject: [PATCH 21/41] move the point origin back to bottom-left --- platform/ios/MGLMapView.mm | 8 ++++++++ src/mbgl/map/transform_state.cpp | 8 +++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index cdfa77935..cdd3044dc 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -1621,6 +1621,10 @@ mbgl::LatLngBounds MGLLatLngBoundsFromCoordinateBounds(MGLCoordinateBounds coord { CGPoint convertedPoint = [self convertPoint:point fromView:view]; + // flip y coordinate for iOS view origin top left + // + convertedPoint.y = self.bounds.size.height - convertedPoint.y; + return MGLLocationCoordinate2DFromLatLng(_mbglMap->latLngForPixel(mbgl::vec2(convertedPoint.x, convertedPoint.y))); } @@ -1628,6 +1632,10 @@ mbgl::LatLngBounds MGLLatLngBoundsFromCoordinateBounds(MGLCoordinateBounds coord { mbgl::vec2 pixel = _mbglMap->pixelForLatLng(MGLLatLngFromLocationCoordinate2D(coordinate)); + // flip y coordinate for iOS view origin in top left + // + pixel.y = self.bounds.size.height - pixel.y; + return [self convertPoint:CGPointMake(pixel.x, pixel.y) toView:view]; } diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp index 9e4ea457e..c672ca5de 100644 --- a/src/mbgl/map/transform_state.cpp +++ b/src/mbgl/map/transform_state.cpp @@ -217,7 +217,7 @@ vec2 TransformState::coordinateToPoint(const TileCoordinate& coord) cons matrix::vec4 p; matrix::vec4 c = {{ coord.column, coord.row, 0, 1 }}; matrix::transformMat4(p, c, mat); - return { p[0] / p[3], p[1] / p[3] }; + return { p[0] / p[3], height - p[1] / p[3] }; } TileCoordinate TransformState::pointToCoordinate(const vec2 point) const { @@ -232,14 +232,16 @@ TileCoordinate TransformState::pointToCoordinate(const vec2 point) const if (err) throw std::runtime_error("failed to invert coordinatePointMatrix"); + double flippedY = height - point.y; + // since we don't know the correct projected z value for the point, // unproject two points to get a line and then find the point on that // line with z=0 matrix::vec4 coord0; matrix::vec4 coord1; - matrix::vec4 point0 = {{ point.x, point.y, 0, 1 }}; - matrix::vec4 point1 = {{ point.x, point.y, 1, 1 }}; + matrix::vec4 point0 = {{ point.x, flippedY, 0, 1 }}; + matrix::vec4 point1 = {{ point.x, flippedY, 1, 1 }}; matrix::transformMat4(coord0, point0, inverted); matrix::transformMat4(coord1, point1, inverted); From c7dfbec96ec54fc6b99c03a6e4752bf7962e1f07 Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Tue, 25 Aug 2015 11:18:27 -0700 Subject: [PATCH 22/41] Make Bucket::uploaded an atomic bool This class is called from multiple threads, so we better make this synchronization flag atomic. --- src/mbgl/renderer/bucket.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/mbgl/renderer/bucket.hpp b/src/mbgl/renderer/bucket.hpp index 4bdb766a7..6185a5c9b 100644 --- a/src/mbgl/renderer/bucket.hpp +++ b/src/mbgl/renderer/bucket.hpp @@ -5,6 +5,8 @@ #include #include +#include + #define BUFFER_OFFSET(i) ((char*)nullptr + (i)) namespace mbgl { @@ -15,6 +17,8 @@ class TileID; class Bucket : private util::noncopyable { public: + Bucket() : uploaded(false) {} + // As long as this bucket has a Prepare render pass, this function is getting called. Typically, // this only happens once when the bucket is being rendered for the first time. virtual void upload() = 0; @@ -33,7 +37,7 @@ public: virtual void swapRenderData() {} protected: - bool uploaded = false; + std::atomic uploaded; }; From 765c4695d85ca9114c419e2e49f121b41f80a85d Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Tue, 25 Aug 2015 11:18:31 -0700 Subject: [PATCH 23/41] Revert "only update the render order array when there are changes to tiles" This reverts commit fd98607c5fcb14aaa29c046a0b7115f47aaf2ddc. Fixes #2163. --- src/mbgl/map/map_context.cpp | 5 ----- src/mbgl/map/source.cpp | 9 ++------- src/mbgl/renderer/painter.cpp | 28 +++++++++++++++++----------- src/mbgl/renderer/painter.hpp | 6 ++---- 4 files changed, 21 insertions(+), 27 deletions(-) diff --git a/src/mbgl/map/map_context.cpp b/src/mbgl/map/map_context.cpp index 19e8d02ec..a8dd86284 100644 --- a/src/mbgl/map/map_context.cpp +++ b/src/mbgl/map/map_context.cpp @@ -334,7 +334,6 @@ bool MapContext::renderSync(const TransformState& state, const FrameData& frame) if (!painter) { painter = std::make_unique(data); painter->setup(); - painter->updateRenderOrder(*style); } painter->setDebug(data.getDebug()); @@ -401,10 +400,6 @@ void MapContext::setSprite(const std::string& name, std::shared_ptrupdateRenderOrder(*style); - } - updateFlags |= Update::Repaint; asyncUpdate->send(); } diff --git a/src/mbgl/map/source.cpp b/src/mbgl/map/source.cpp index 4b2ae2cfb..518468af6 100644 --- a/src/mbgl/map/source.cpp +++ b/src/mbgl/map/source.cpp @@ -529,14 +529,9 @@ void Source::invalidateTiles(const std::unordered_set& ids } void Source::updateTilePtrs() { - std::vector newPtrs; + tilePtrs.clear(); for (const auto& pair : tiles) { - newPtrs.push_back(pair.second.get()); - } - - if (tilePtrs != newPtrs) { - tilePtrs = newPtrs; - emitTileLoaded(true); + tilePtrs.push_back(pair.second.get()); } } diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index b55b71dcb..9e5feaec7 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -184,6 +184,9 @@ void Painter::render(const Style& style, TransformState state_, const FrameData& resize(); changeMatrix(); + // Figure out what buckets we have to draw and what order we have to draw them in. + const auto order = determineRenderOrder(style); + // - UPLOAD PASS ------------------------------------------------------------------------------- // Uploads all required buffers and images before we do any actual rendering. { @@ -202,6 +205,7 @@ void Painter::render(const Style& style, TransformState state_, const FrameData& } } + // - CLIPPING MASKS ---------------------------------------------------------------------------- // Draws the clipping masks to the stencil buffer. { @@ -272,8 +276,6 @@ void Painter::renderPass(RenderPass pass_, const float strataThickness) { pass = pass_; - const double zoom = state.getZoom(); - MBGL_DEBUG_GROUP(pass == RenderPass::Opaque ? "opaque" : "translucent"); if (debug::renderTree) { @@ -286,13 +288,6 @@ void Painter::renderPass(RenderPass pass_, for (; it != end; ++it, i += increment) { const auto& item = *it; if (item.bucket && item.tile) { - // Skip this layer if it's outside the range of min/maxzoom. - // This may occur when there /is/ a bucket created for this layer, but the min/max-zoom - // is set to a fractional value, or value that is larger than the source maxzoom. - if (item.layer.bucket->min_zoom > zoom || - item.layer.bucket->max_zoom <= zoom) { - continue; - } if (item.layer.hasRenderPass(pass)) { MBGL_DEBUG_GROUP(item.layer.id + " - " + std::string(item.tile->id)); setStrata(i * strataThickness); @@ -311,8 +306,8 @@ void Painter::renderPass(RenderPass pass_, } } -void Painter::updateRenderOrder(const Style& style) { - order.clear(); +std::vector Painter::determineRenderOrder(const Style& style) { + std::vector order; for (const auto& layerPtr : style.layers) { const auto& layer = *layerPtr; @@ -349,6 +344,15 @@ void Painter::updateRenderOrder(const Style& style) { continue; } + // Skip this layer if it's outside the range of min/maxzoom. + // This may occur when there /is/ a bucket created for this layer, but the min/max-zoom + // is set to a fractional value, or value that is larger than the source maxzoom. + const double zoom = state.getZoom(); + if (layer.bucket->min_zoom > zoom || + layer.bucket->max_zoom <= zoom) { + continue; + } + const auto& tiles = source->getTiles(); for (auto tile : tiles) { assert(tile); @@ -362,6 +366,8 @@ void Painter::updateRenderOrder(const Style& style) { } } } + + return order; } void Painter::renderBackground(const StyleLayer &layer_desc) { diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp index 78cf308b7..e4e1f8cff 100644 --- a/src/mbgl/renderer/painter.hpp +++ b/src/mbgl/renderer/painter.hpp @@ -137,12 +137,12 @@ public: bool needsAnimation() const; - void updateRenderOrder(const Style& style); - private: void setupShaders(); mat4 translatedMatrix(const mat4& matrix, const std::array &translation, const TileID &id, TranslateAnchorType anchor); + std::vector determineRenderOrder(const Style& style); + template void renderPass(RenderPass, Iterator it, Iterator end, @@ -204,8 +204,6 @@ private: const float strata_epsilon = 1.0f / (1 << 16); Color background = {{ 0, 0, 0, 0 }}; - std::vector order; - public: FrameHistory frameHistory; From 92d9308eb8a996ad2d85268e36fc04caeec8f5d6 Mon Sep 17 00:00:00 2001 From: Jason Wray Date: Tue, 21 Jul 2015 18:09:48 -0400 Subject: [PATCH 24/41] Ask for 'always' location permissions, too --- platform/ios/MGLMapView.mm | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index cdd3044dc..5ed9d9200 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -2214,7 +2214,15 @@ CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng) [NSException raise:@"Missing Location Services usage description" format: @"In iOS 8 and above, this app must have a value for NSLocationWhenInUseUsageDescription or NSLocationAlwaysUsageDescription in its Info.plist."]; } - [self.locationManager requestWhenInUseAuthorization]; + // request location permissions, if both keys exist ask for less permissive + if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) + { + [self.locationManager requestWhenInUseAuthorization]; + } + else if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]) + { + [self.locationManager requestAlwaysAuthorization]; + } } #endif From 4977858f4d5cc181ab8204c472b3ee84c37245a4 Mon Sep 17 00:00:00 2001 From: Jason Wray Date: Wed, 22 Jul 2015 11:41:58 -0400 Subject: [PATCH 25/41] Fix testUserTrackingModeFollow test to accept location permissions ask I thought that the tests were bypassing the permissions dialog, but it turns out that was only half correct: we were not actually asking for `always` location permission in MBGL. --- test/ios/MapViewTests.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/ios/MapViewTests.m b/test/ios/MapViewTests.m index fadbbae60..f4ae501d7 100644 --- a/test/ios/MapViewTests.m +++ b/test/ios/MapViewTests.m @@ -544,7 +544,7 @@ - (void)testUserTrackingModeFollow { tester.mapView.userTrackingMode = MGLUserTrackingModeFollow; - [tester waitForTimeInterval:1]; + [tester acknowledgeSystemAlert]; XCTAssertEqual(tester.mapView.userLocationVisible, YES, @@ -570,7 +570,7 @@ - (void)testUserTrackingModeFollowWithHeading { tester.mapView.userTrackingMode = MGLUserTrackingModeFollowWithHeading; - [tester waitForTimeInterval:1]; + [tester acknowledgeSystemAlert]; XCTAssertEqual(tester.mapView.userLocationVisible, YES, From 3643053cb413c3f8289be9e5d183218fb314b310 Mon Sep 17 00:00:00 2001 From: Jason Wray Date: Tue, 25 Aug 2015 16:00:44 -0700 Subject: [PATCH 26/41] Bump metrics tests timeouts EVERYWHERE --- test/ios/MetricsTests.m | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/ios/MetricsTests.m b/test/ios/MetricsTests.m index cd02c2d52..d3b99dc63 100644 --- a/test/ios/MetricsTests.m +++ b/test/ios/MetricsTests.m @@ -119,7 +119,7 @@ const NSTimeInterval MGLFlushInterval = 60; [[MGLMapboxEvents sharedManager] flush]; - [self waitForExpectationsWithTimeout:1.0 handler:nil]; + [self waitForExpectationsWithTimeout:2.0 handler:nil]; XCTAssertNil([[MGLMapboxEvents sharedManager] timer]); } @@ -143,7 +143,7 @@ const NSTimeInterval MGLFlushInterval = 60; id eventsMock = [OCMockObject partialMockForObject:[MGLMapboxEvents sharedManager]]; [[[eventsMock expect] andForwardToRealObject] startTimer]; [self pushFakeEvent]; - [eventsMock verifyWithDelay:0.5]; + [eventsMock verifyWithDelay:2.0]; XCTAssertEqual([[[MGLMapboxEvents sharedManager] eventQueue] count], 1); XCTAssertNotNil([[MGLMapboxEvents sharedManager] timer]); @@ -164,7 +164,7 @@ const NSTimeInterval MGLFlushInterval = 60; [[MGLMapboxEvents sharedManager] flush]; - [self waitForExpectationsWithTimeout:1.0 handler:nil]; + [self waitForExpectationsWithTimeout:2.0 handler:nil]; [self pushFakeEvent]; id eventsMock = [OCMockObject partialMockForObject:[MGLMapboxEvents sharedManager]]; @@ -178,7 +178,7 @@ const NSTimeInterval MGLFlushInterval = 60; id eventsMock = [OCMockObject partialMockForObject:[MGLMapboxEvents sharedManager]]; [[eventsMock expect] postEvents:events]; [[MGLMapboxEvents sharedManager] flush]; - [eventsMock verifyWithDelay:1.0]; + [eventsMock verifyWithDelay:2.0]; XCTAssertTrue([[[MGLMapboxEvents sharedManager] eventQueue] count] == 0); } @@ -209,7 +209,7 @@ const NSTimeInterval MGLFlushInterval = 60; [self pushFakeEvent]; [MGLMapboxEvents flush]; - [self waitForExpectationsWithTimeout:1.0 handler:nil]; + [self waitForExpectationsWithTimeout:2.0 handler:nil]; } - (void)testPushEventAddsToEventQueue { From 2f30dfe97d851f2a2bb4141dc234013b01f8afd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Tue, 25 Aug 2015 15:27:23 -0700 Subject: [PATCH 27/41] Disable heading updates for .FollowWithCourse Fixes #2180. --- platform/ios/MGLMapView.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 5ed9d9200..f12836b05 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -2310,6 +2310,7 @@ CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng) break; } case MGLUserTrackingModeFollow: + case MGLUserTrackingModeFollowWithCourse: { self.showsUserLocation = YES; @@ -2323,7 +2324,6 @@ CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng) break; } case MGLUserTrackingModeFollowWithHeading: - case MGLUserTrackingModeFollowWithCourse: { self.showsUserLocation = YES; From 42dc5336db5179c50b8d1edeca0bef7a27c8cefd Mon Sep 17 00:00:00 2001 From: Jason Wray Date: Tue, 18 Aug 2015 16:25:40 -0400 Subject: [PATCH 28/41] iOS perspective gesture support Drag two fingers upward to tilt the map. Implements #2116 --- include/mbgl/ios/MGLMapView.h | 21 ++++ .../darwin/settings_nsuserdefaults.hpp | 1 + ios/app/MBXViewController.mm | 2 + platform/darwin/settings_nsuserdefaults.mm | 3 + platform/ios/MGLMapView.mm | 111 +++++++++++++++++- platform/ios/MGLMapboxEvents.h | 1 + platform/ios/MGLMapboxEvents.m | 1 + 7 files changed, 136 insertions(+), 4 deletions(-) diff --git a/include/mbgl/ios/MGLMapView.h b/include/mbgl/ios/MGLMapView.h index 2b9a3d291..fc70f3d90 100644 --- a/include/mbgl/ios/MGLMapView.h +++ b/include/mbgl/ios/MGLMapView.h @@ -74,6 +74,13 @@ IB_DESIGNABLE * The default value of this property is `YES`. */ @property(nonatomic, getter=isRotateEnabled) BOOL rotateEnabled; +/** A Boolean value that determines whether the user may change the pitch (tilt) of the map. + * + * This property controls only user interactions with the map. If you set the value of this property to `NO`, you may still change the pitch of the map programmatically. + * + * The default value of this property is `YES`. */ +@property(nonatomic, getter=isPitchEnabled) BOOL pitchEnabled; + /** The compass image view shown in the upper-right when the map is rotated. */ @property (nonatomic, readonly) UIImageView *compassView; @@ -173,6 +180,20 @@ IB_DESIGNABLE /** Resets the map rotation to a northern heading. */ - (IBAction)resetNorth; +/** The pitch of the map (measured in degrees). + * + * The default value `0` shows a completely flat map. Maximum value is `60`. */ +@property (nonatomic) double pitch; + +/** Changes the pitch of the map. + * @param pitch The pitch of the map (measured in degrees) relative to top-down. + * + * Changing the pitch tilts the map without changing the current center coordinate or zoom level. */ +- (void)setPitch:(double)pitch; + +/** Resets the map pitch to head-on. */ +- (IBAction)resetPitch; + #pragma mark - Converting Map Coordinates /** @name Converting Map Coordinates */ diff --git a/include/mbgl/platform/darwin/settings_nsuserdefaults.hpp b/include/mbgl/platform/darwin/settings_nsuserdefaults.hpp index 6c91fd302..615320ee5 100644 --- a/include/mbgl/platform/darwin/settings_nsuserdefaults.hpp +++ b/include/mbgl/platform/darwin/settings_nsuserdefaults.hpp @@ -17,6 +17,7 @@ public: double latitude = 0; double zoom = 0; double bearing = 0; + double pitch = 0; MGLUserTrackingMode userTrackingMode = MGLUserTrackingModeNone; bool showsUserLocation = false; diff --git a/ios/app/MBXViewController.mm b/ios/app/MBXViewController.mm index f7cbf0c04..99c207d24 100644 --- a/ios/app/MBXViewController.mm +++ b/ios/app/MBXViewController.mm @@ -86,6 +86,7 @@ mbgl::Settings_NSUserDefaults *settings = nullptr; settings->latitude = self.mapView.centerCoordinate.latitude; settings->zoom = self.mapView.zoomLevel; settings->bearing = self.mapView.direction; + settings->pitch = self.mapView.pitch; settings->debug = self.mapView.isDebugActive; settings->userTrackingMode = self.mapView.userTrackingMode; settings->showsUserLocation = self.mapView.showsUserLocation; @@ -99,6 +100,7 @@ mbgl::Settings_NSUserDefaults *settings = nullptr; settings->load(); [self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(settings->latitude, settings->longitude) zoomLevel:settings->zoom animated:NO]; self.mapView.direction = settings->bearing; + self.mapView.pitch = settings->pitch; self.mapView.userTrackingMode = settings->userTrackingMode; self.mapView.showsUserLocation = settings->showsUserLocation; [self.mapView setDebugActive:settings->debug]; diff --git a/platform/darwin/settings_nsuserdefaults.mm b/platform/darwin/settings_nsuserdefaults.mm index f6f9bbeed..5c943baff 100644 --- a/platform/darwin/settings_nsuserdefaults.mm +++ b/platform/darwin/settings_nsuserdefaults.mm @@ -11,6 +11,7 @@ Settings_NSUserDefaults::Settings_NSUserDefaults() @"latitude" : @(latitude), @"zoom" : @(zoom), @"bearing" : @(bearing), + @"pitch" : @(pitch), @"userTrackingMode" : @(userTrackingMode), @"showsUserLocation" : @(showsUserLocation), @"debug" : @(debug), @@ -26,6 +27,7 @@ void Settings_NSUserDefaults::load() latitude = [settings[@"latitude"] doubleValue]; zoom = [settings[@"zoom"] doubleValue]; bearing = [settings[@"bearing"] doubleValue]; + pitch = [settings[@"pitch"] doubleValue]; debug = [settings[@"debug"] boolValue]; unsigned uncheckedTrackingMode = [settings[@"trackingMode"] unsignedIntValue]; @@ -44,6 +46,7 @@ void Settings_NSUserDefaults::save() @"latitude" : @(latitude), @"zoom" : @(zoom), @"bearing" : @(bearing), + @"pitch" : @(pitch), @"userTrackingMode" : @(userTrackingMode), @"showsUserLocation" : @(showsUserLocation), @"debug" : @(debug), diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index f12836b05..4f3e90307 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -85,6 +85,7 @@ CLLocationDegrees MGLDegreesFromRadians(CGFloat radians) @property (nonatomic) UIPinchGestureRecognizer *pinch; @property (nonatomic) UIRotationGestureRecognizer *rotate; @property (nonatomic) UILongPressGestureRecognizer *quickZoom; +@property (nonatomic) UIPanGestureRecognizer *twoFingerDrag; @property (nonatomic) NSMapTable *annotationIDsByAnnotation; @property (nonatomic) NS_MUTABLE_DICTIONARY_OF(NSString *, MGLAnnotationImage *) *annotationImages; @property (nonatomic) std::vector annotationsNearbyLastTap; @@ -338,6 +339,15 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration) [twoFingerTap requireGestureRecognizerToFail:_pinch]; [twoFingerTap requireGestureRecognizerToFail:_rotate]; [self addGestureRecognizer:twoFingerTap]; + + _twoFingerDrag = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleTwoFingerDragGesture:)]; + _twoFingerDrag.minimumNumberOfTouches = 2; + _twoFingerDrag.maximumNumberOfTouches = 2; + _twoFingerDrag.delegate = self; + [_twoFingerDrag requireGestureRecognizerToFail:twoFingerTap]; + [_twoFingerDrag requireGestureRecognizerToFail:_pan]; + [self addGestureRecognizer:_twoFingerDrag]; + _pitchEnabled = YES; if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { @@ -1326,6 +1336,59 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration) } } +- (void)handleTwoFingerDragGesture:(UIPanGestureRecognizer *)twoFingerDrag +{ + if ( ! self.isPitchEnabled) return; + + _mbglMap->cancelTransitions(); + + if (twoFingerDrag.state == UIGestureRecognizerStateBegan) + { + [self trackGestureEvent:MGLEventGesturePitchStart forRecognizer:twoFingerDrag]; + } + else if (twoFingerDrag.state == UIGestureRecognizerStateBegan || twoFingerDrag.state == UIGestureRecognizerStateChanged) + { + CGFloat gestureDistance = CGPoint([twoFingerDrag translationInView:twoFingerDrag.view]).y; + double currentPitch = _mbglMap->getPitch(); + double minPitch = 0; + double maxPitch = 60.0; + double slowdown = 20.0; + + double pitchNew = fmax(fmin(currentPitch - (gestureDistance / slowdown), maxPitch), minPitch); + + _mbglMap->setPitch(pitchNew); + } + else if (twoFingerDrag.state == UIGestureRecognizerStateEnded || twoFingerDrag.state == UIGestureRecognizerStateCancelled) + { + [self unrotateIfNeededAnimated:YES]; + + //[self notifyMapChange:(mbgl::MapChangeRegionDidChange)]; + } + +} + +- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer +{ + if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) + { + UIPanGestureRecognizer *panGesture = (UIPanGestureRecognizer *)gestureRecognizer; + + if (panGesture.minimumNumberOfTouches == 2) + { + CGPoint velocity = [panGesture velocityInView:panGesture.view]; + double gestureAngle = MGLDegreesFromRadians(atan(velocity.y / velocity.x)); + double horizontalToleranceDegrees = 20.0; + + // cancel if gesture angle is not 90º±20º (more or less vertical) + if ( ! (fabs((fabs(gestureAngle) - 90.0)) < horizontalToleranceDegrees)) + { + return NO; + } + } + } + return YES; +} + - (void)handleCalloutAccessoryTapGesture:(UITapGestureRecognizer *)tap { if ([self.delegate respondsToSelector:@selector(mapView:annotation:calloutAccessoryControlTapped:)]) @@ -1419,6 +1482,11 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration) return [NSSet setWithObject:@"allowsRotating"]; } ++ (NS_SET_OF(NSString *) *)keyPathsForValuesAffectingPitchEnabled +{ + return [NSSet setWithObject:@"allowsPitching"]; +} + - (void)setDebugActive:(BOOL)debugActive { _mbglMap->setDebug(debugActive); @@ -1617,6 +1685,25 @@ mbgl::LatLngBounds MGLLatLngBoundsFromCoordinateBounds(MGLCoordinateBounds coord [self setDirection:direction animated:NO]; } +- (double)pitch +{ + return _mbglMap->getPitch(); +} + +- (void)setPitch:(double)pitch +{ + // constrain pitch to between 0º and 60º + // + _mbglMap->setPitch(fmax(fmin(pitch, 60), 0)); + + //[self notifyMapChange:(mbgl::MapChangeRegionDidChange)]; +} + +- (void)resetPitch +{ + [self setPitch:0]; +} + - (CLLocationCoordinate2D)convertPoint:(CGPoint)point toCoordinateFromView:(nullable UIView *)view { CGPoint convertedPoint = [self convertPoint:point fromView:view]; @@ -2630,10 +2717,11 @@ CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng) { [self updateCompass]; - if (self.pan.state == UIGestureRecognizerStateChanged || - self.pinch.state == UIGestureRecognizerStateChanged || - self.rotate.state == UIGestureRecognizerStateChanged || - self.quickZoom.state == UIGestureRecognizerStateChanged) return; + if (self.pan.state == UIGestureRecognizerStateChanged || + self.pinch.state == UIGestureRecognizerStateChanged || + self.rotate.state == UIGestureRecognizerStateChanged || + self.quickZoom.state == UIGestureRecognizerStateChanged || + self.twoFingerDrag.state == UIGestureRecognizerStateChanged) return; if (self.isAnimatingGesture) return; @@ -3062,6 +3150,21 @@ class MBGLView : public mbgl::View self.rotateEnabled = allowsRotating; } ++ (NS_SET_OF(NSString *) *)keyPathsForValuesAffectingAllowsPitching +{ + return [NSSet setWithObject:@"pitchEnabled"]; +} + +- (BOOL)allowsPitching +{ + return self.pitchEnabled; +} + +- (void)setAllowsPitching:(BOOL)allowsPitching +{ + self.pitchEnabled = allowsPitching; +} + - (void)didReceiveMemoryWarning { _mbglMap->onLowMemory(); diff --git a/platform/ios/MGLMapboxEvents.h b/platform/ios/MGLMapboxEvents.h index 9efb53c5e..45f809495 100644 --- a/platform/ios/MGLMapboxEvents.h +++ b/platform/ios/MGLMapboxEvents.h @@ -30,6 +30,7 @@ extern NSString *const MGLEventGestureQuickZoom; extern NSString *const MGLEventGesturePanStart; extern NSString *const MGLEventGesturePinchStart; extern NSString *const MGLEventGestureRotateStart; +extern NSString *const MGLEventGesturePitchStart; typedef NS_DICTIONARY_OF(NSString *, id) MGLMapboxEventAttributes; typedef NS_MUTABLE_DICTIONARY_OF(NSString *, id) MGLMutableMapboxEventAttributes; diff --git a/platform/ios/MGLMapboxEvents.m b/platform/ios/MGLMapboxEvents.m index 314d50dd0..77e68ddde 100644 --- a/platform/ios/MGLMapboxEvents.m +++ b/platform/ios/MGLMapboxEvents.m @@ -45,6 +45,7 @@ NSString *const MGLEventGestureQuickZoom = @"QuickZoom"; NSString *const MGLEventGesturePanStart = @"Pan"; NSString *const MGLEventGesturePinchStart = @"Pinch"; NSString *const MGLEventGestureRotateStart = @"Rotation"; +NSString *const MGLEventGesturePitchStart = @"Pitch"; const NSUInteger MGLMaximumEventsPerFlush = 20; const NSTimeInterval MGLFlushInterval = 60; From 1424ce72a5d9fcb9f3861a0006989092a3b984ee Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Wed, 26 Aug 2015 17:25:30 -0700 Subject: [PATCH 29/41] #2182 - Replacing existing iOS style compass with more Android style compass artwork --- .../java/com/mapbox/mapboxgl/views/MapView.java | 2 +- .../res/drawable-xxhdpi/compass_custom_flat.png | Bin 0 -> 2519 bytes .../src/main/res/drawable/compass.png | Bin 2376 -> 0 bytes 3 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 android/java/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/compass_custom_flat.png delete mode 100644 android/java/MapboxGLAndroidSDK/src/main/res/drawable/compass.png diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java index f6723d786..219069fda 100644 --- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java @@ -287,7 +287,7 @@ public class MapView extends FrameLayout implements LocationListener { mCompassListener = new CompassListener(); mCompassView = new ImageView(mContext); - mCompassView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.compass)); + mCompassView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.compass_custom_flat)); mCompassView.setContentDescription(getResources().getString(R.string.compassContentDescription)); LayoutParams lp = new FrameLayout.LayoutParams((int)(48 * mScreenDensity), (int)(48 * mScreenDensity)); lp.gravity = Gravity.TOP | Gravity.END; diff --git a/android/java/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/compass_custom_flat.png b/android/java/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/compass_custom_flat.png new file mode 100644 index 0000000000000000000000000000000000000000..d545b03f3ca054eb6923eac871d9570467e4ee97 GIT binary patch literal 2519 zcmV;|2`Ki7P)Px;kx4{BRCodHnd^^L)fK?6Ac{h%f`V2>WEgx+QAeZlQqb5M6dSO*$JEA3;1{Ix|^#39Fc&HM1T&# znXxbf?C)wg9_GS0(AguwdOEKd#IIln7`V^i1=s?QfWi3>d=x%CK|;O zcb*I2KG+3SMt;DIId5!ZU~A7H=W|~%i<17eMVl@JZLBPHGRThS!&0~j+_Edl5m<3I z8~r&P23UidQC`Kq^rh}r6KylA_3u-77b=~bs?JlV)%kE8To1uhiZ=V?Xxuo1lg|Xw zMw!L^WS)Io$)!OZ{5>2zTDV|)R(c8cK#&;WP_d1pV{ptI4XG>#WBwgSG#c0ZfK|1% z_e^2fcCd21NEX#xKpe=E0ZonfVLJrnWoyi6R$e^pEreU3R&eZcCNA`oF=Jc7@tOBN zvn+yWqqbfI+8!jK0dh*71^2@Epq@HZZl)rESlmIA&(5SQ$*K;`Lmt_~Z^3g?(6SN| zApPkBw{j*$eVIyzxV7)@kn}!VO4-yPcXDmgW^LDp(o0L(0677UhTFgw%P8VP+)I!S zO--*vvCn2uW}ObjNwv_cLDC1OS}C<<17yT|;ar#qwZ-lHPRyN75VFKF>x?PoN|u%( z&$V42PJvRnSvEkPD}Dj}5Jfl)HhR&Tx5ijDgF3UR8!tvpAM{0^3Z+bd%$`eNexbIK z6`VfvI5`=lBC(Ej&A5o->HkvDw_GU`Ah*d=TI4D#Tj=hzgngyVInX-RwN1nr^`O=z zqwttg6d-My2EI;o*lTziC=Qv^<|Nja!r`N?b*53*HlyQ3NMH168sx?xw~)pzWSnsu zY`FCYQ2%^uci}y(!M2dqBnKLMRzvq$s~F$({a+D zb!{_;wt0(sQorO?pRR=5nNeh?bJS0nQG}V&_$eA^mfAmtc4-^isw1N48!KG4AwX+r zS3gEg-<%~c+AVxX@&aW4n6vM{o!@C(_Q5zjbAkN^jpwBfUS*quuEtA0+`gHJ@WtcL=r%v?>pE(L< z!!fDh&>{o$;Lhx~`4yB|CvCkt7NaYrs<8i@3dY=3F;iV$fNbO&y#F1jELyOLed6@C zoy+W4h335Zt8p(-$GT}b4PENYGd^8E=iV=kM?t2l%mNy@fbE9N=u%cFo_@c=!S>l; z;9R&#kWA5l@f|EQUVHd6N+tEg@$o+(b`>m+`ENjb>hcjf=0m$nm-EaI>RI|NyA0Bz z4t1$Bt6j)*eQe8bp0uRH_#{QmL3iNUGir;=>Q_R{hOKbC=kNJQrppIK&|v`pm3 zQfMvR>7w9!eY3yz1mCA9Z~8b=Tj6tHS*#`Q6n)^L@1P_GZQ%Y%Fx77br?levYdKi9 z5fZVji>kWRSy%LJ3$$nUKD~JXa$ar&mcuA=E?RDb-?eG`2fyEezrlInh^~h9uo2Q? z*)PF*F~os43G_8s9IdnAP0+Bqm^CZmbf_w}RfoFj+GBftI}0*1h_YNUogac2#w0p! zL|+wyY-8I*PmHU+>0_ptC3#}G>FgWN(I zYs}-|S`Q^J#B7;SYjsJ4WR+Li#E26 zC1#Jl>0_o81;}~sImGQYmbjMmf;*A-MPeQ6&Mc}JSgud{rjMCY6d)UVV0#T-@kbpA$&S$vBzu*JNU7QoWWdr2sZ3Yikejf0544I6QxzOot+GkF| zDG+1r(PnM`3%modd_dJuSJ07A- z=sFQ%fIE{riPNqRehyPwBs<b|hs6MKLH&UwI5(hbJKEi`%%8Wmw!^2H&+# zMX85D17?QJ2LHF^jxzy#_eyp`-|)TP3BGddf>q$zXeI1`H^6`mtBh2D5+~d>9c?qh z-O9jB1s7G%R4(*RMNhmszYR8nfpV(a-mJ9F_ePSVhJ$60lIdpvk}~hR(v3hj0^JC7 hBhZaNHv&Ns_#dqPnoFPLWIzA_002ovPDHLkV1hZC*E|3K literal 0 HcmV?d00001 diff --git a/android/java/MapboxGLAndroidSDK/src/main/res/drawable/compass.png b/android/java/MapboxGLAndroidSDK/src/main/res/drawable/compass.png deleted file mode 100644 index 58e7e08d2455e10b98d529d45ae3a9646956027c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2376 zcmV-O3Agr%P)F;&-Y`@6;yRCQSV~1a)066EUBX5c6tjiQ!3N0~mlMr1N@~m8VJc4LQ|J z;UFL}MJq|&zxmv5K*xduxEJ?}@>Q+@o4F5hkHO&qV4%ld^By~oW zAlQOU*yioXQeY;Mx;}xQ&`tBL42=JKy_pOuZmB8P z2{{1ys8V73`}<5ctw^Wrp#sC>cdYdtHed@jTk}J=6oVDfg$G5Z^GBO4CUe;Jd=_$ zV;9-qvCGbLuP~CBBvB`X=FGt5vX1B685%w$hpXs8F`0_u5(J->*l{C)+4kO-(F*~BwtAo;ads ztX(2Vyf1QZAKKM})oFcW!&y3UD#sx)$vLPM>_burCqtAj6i=oySpze$!v|~w;8WPj z>)n=w3(2{f5%d^hFbG-TB#nb-obymCDf~B-0fmT&;rTyG7nvo%#BIq^UY zT*s<~vqSp;m3u3M8`2nVkB3i5$>AiStk|J;#f!?7r>{%HElyp!cO!y=dm@t7gvfZ> z`L)JYqM$R4-|sECgL6;Xw>^Ph~UtA~?^I%(q&*#j2=g6PnOyYjAs zD9{l7eeRO7dN@J9s7_WY0v7>-h@7=72)bey*dOoA#hq78uTtGCFoKH!LEe8-WCftF z+W{8=f@lTX&Zu|#njD7%;vz_pVeK3f#OGjZCxjsW(M|DB1pJ<=HBGuf>}4m|g<_~r zPoF&xsG1Y>4*&rF|8_b0YybcRdPzhZCE_T)_k z4^l<9-#`ViFBaS4(Ss-y>=p|4U{89eXQ5cwp7c{zo}XtQmzN{I+Q49_Ua-w+&({XeNBn`0FJ4YX zeBxaE)Ucf0A{~79{sTKcK4v>Rza!$fj)lcVw+>QXR!r*b`e1m*Fzuhkblw@M91tMM z0F(xZSa2?WYFhU9vH%?(9hSuF$5#>O{y8vWSXIyHd6f^+fH ze$!qk1JIMnNyZ^PefB&AsjLwM7CsoBF-@mY79dP7OtXW7gV0nf3lLavE`DlR)<{`^ z&@YGaX>H9PMZ64Yk=nq*2NTFtXeIlVCd9NIHad1SvtYi8VT$oSvE*Y_yL0!RTb3uF zI%$S>-j_5b2E?Qi;Bu0sSZGDoaA`AH0#Cq#rC4XyiP!|OM0vd`=5?C9u-wOTFqxY1xvZ6Kk8a6~TJY&11J!9m$a9+7Lq zs9sYurZ$yiwvqs$4Ie$d7(p^k@I3+~uE4PEFH$2UK9758fY1lxqQU@?&v7hb%ld8m zb{-JUk`4GA3qw*^p;7cz$HBN2L8pD5b+xsSuf!of_K^VUGflHjqT4FMA52WROQ*K5 zoTh6~BQ#(cho)e8LcR@OWgHUAY18&5!LTcU!_g3=D!l7@I-1~PB7~Hi6c^c>GDtc? zWHx$LuBdI3{7;U1QUGD9T_Gp-L`QCokLwQQu1AE}x9T;A1g$Y`_TXEZ|4R31`~OJn zz^>Jpq~ka-nfGqN{&n_&&cHDrGkv2MD1GZo@*oSH!K9JLTOS%T7bKO9~4jM-# zX-@F>aB1~mtF^tIYEQJ|!8xblZ&y_-I@1l)3UNvD8BAyUq6!GMU{hzxdef?BBPT-A zdvHfqH}SuQqY|9Gh~;tDs({cIHeox?j!;IcRn8CO2n|Vr7XnD*BnZWsi)w_e0|+*w z=Q)v$^k!~LxrBjAan*~sm9{0qe>XG&bO0sUp?hsFLe3Ths(7zjhyGJ_-3_kjBtDqH zPb}BEri~}GsOm1dUd25sDd0RQ0*(6gjx36M5NDy=Ihn-qZTO5k;#j5~J#14SswaV2 z9O_})YUgbUy;4$m@0JSCwc#|qw-2Z18Iu#h3OP1H%Wi`nqWBhI)%~i({q!dIeG=uV u%=_YG6?M@DZAr)3m_j)L`)}r~6Zi+-n6!b6vRQlp0000 Date: Thu, 27 Aug 2015 14:00:43 -0400 Subject: [PATCH 30/41] add Point <--> LatLng conversion tests --- test/miscellaneous/transform.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/test/miscellaneous/transform.cpp b/test/miscellaneous/transform.cpp index 5d00bfd20..426e9e534 100644 --- a/test/miscellaneous/transform.cpp +++ b/test/miscellaneous/transform.cpp @@ -105,3 +105,35 @@ TEST(Transform, InvalidBearing) { ASSERT_DOUBLE_EQ(2, transform.getScale()); ASSERT_DOUBLE_EQ(2, transform.getAngle()); } + +TEST(Transform, PerspectiveProjection) { + MockView view; + Transform transform(view); + + transform.resize({{ 1000, 1000 }}); + transform.setScale(1024); + transform.setPitch(0.9); + transform.setLatLng(LatLng(38, -77)); + + // expected values are from mapbox-gl-js + + LatLng loc = transform.getState().pointToLatLng({ 500, 500 }); + ASSERT_NEAR(-77, loc.longitude, 0.0001); + ASSERT_NEAR(38, loc.latitude, 0.0001); + + loc = transform.getState().pointToLatLng({ 0, 1000 }); + ASSERT_NEAR(-77.59198961199148, loc.longitude, 0.0002); + ASSERT_NEAR(38.74661326302018, loc.latitude, 0.0001); + + loc = transform.getState().pointToLatLng({ 1000, 0 }); + ASSERT_NEAR(-76.75823239205641, loc.longitude, 0.0001); + ASSERT_NEAR(37.692872969426375, loc.latitude, 0.0001); + + vec2 point = transform.getState().latLngToPoint({38.74661326302018, -77.59198961199148}); + ASSERT_NEAR(point.x, 0, 0.01); + ASSERT_NEAR(point.y, 1000, 0.01); + + point = transform.getState().latLngToPoint({37.692872969426375, -76.75823239205641}); + ASSERT_NEAR(point.x, 1000, 0.02); + ASSERT_NEAR(point.y, 0, 0.02); +} From 76e94fdb2db7d917b055e2c46dfa5c2a4050efd3 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Thu, 27 Aug 2015 13:31:07 -0700 Subject: [PATCH 31/41] #2194 - Removing elevation due to drop shadow issue --- .../src/main/res/layout/activity_main.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_main.xml b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_main.xml index 292f77c3a..2d22dcce7 100644 --- a/android/java/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_main.xml +++ b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_main.xml @@ -54,6 +54,7 @@ android:layout_margin="@dimen/fab_margin" app:backgroundTint="@color/white" app:borderWidth="0dp" + app:elevation="0dp" /> From 294b307cb3f470b1cf5fb94633c9082dc0bfd719 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Thu, 27 Aug 2015 16:49:35 -0400 Subject: [PATCH 32/41] fix line antialiasing adjustment bug fix #2189 This puts an upper limit on how much lines can be blurred because of their y position. It's a hacky fix but the entire way lines are antialiased in perspective view is hacky. --- src/mbgl/shader/line.vertex.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mbgl/shader/line.vertex.glsl b/src/mbgl/shader/line.vertex.glsl index f818565cc..3b3caaab1 100644 --- a/src/mbgl/shader/line.vertex.glsl +++ b/src/mbgl/shader/line.vertex.glsl @@ -49,7 +49,7 @@ void main() { float squish_scale = length(a_extrude) / length(u_antialiasingmatrix * a_extrude); // how much features are squished in all directions by the perspectiveness - float perspective_scale = 1.0 / (1.0 - y * u_extra); + float perspective_scale = 1.0 / (1.0 - min(y * u_extra, 0.90)); v_gamma_scale = perspective_scale * squish_scale; } From d50ade7aa47a4460b0d6bc4e89f83288070b8d9f Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Thu, 27 Aug 2015 17:33:56 -0400 Subject: [PATCH 33/41] improve dashed and patterned line antialiasing in perspective view. This is exactly the same approach used for regular lines. I just forgot to implement it for these types of lines. --- src/mbgl/renderer/painter_line.cpp | 4 ++++ src/mbgl/shader/line.vertex.glsl | 4 ++-- src/mbgl/shader/linepattern.fragment.glsl | 9 ++++---- src/mbgl/shader/linepattern.vertex.glsl | 28 ++++++++++++----------- src/mbgl/shader/linepattern_shader.hpp | 2 ++ src/mbgl/shader/linesdf.fragment.glsl | 4 +++- src/mbgl/shader/linesdf.vertex.glsl | 19 +++++++++++++-- src/mbgl/shader/linesdf_shader.hpp | 2 ++ 8 files changed, 49 insertions(+), 23 deletions(-) diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp index 0b7e8a96f..258bab6ae 100644 --- a/src/mbgl/renderer/painter_line.cpp +++ b/src/mbgl/renderer/painter_line.cpp @@ -97,6 +97,8 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const linesdfShader->u_image = 0; linesdfShader->u_sdfgamma = lineAtlas->width / (properties.dash_line_width * std::min(posA.width, posB.width) * 256.0 * data.pixelRatio) / 2; linesdfShader->u_mix = properties.dash_array.t; + linesdfShader->u_extra = extra; + linesdfShader->u_antialiasingmatrix = antialiasingMatrix; bucket.drawLineSDF(*linesdfShader); @@ -122,6 +124,8 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const linepatternShader->u_pattern_br_b = imagePosB.br; linepatternShader->u_fade = properties.image.t; linepatternShader->u_opacity = properties.opacity; + linepatternShader->u_extra = extra; + linepatternShader->u_antialiasingmatrix = antialiasingMatrix; MBGL_CHECK_ERROR(glActiveTexture(GL_TEXTURE0)); spriteAtlas->bind(true); diff --git a/src/mbgl/shader/line.vertex.glsl b/src/mbgl/shader/line.vertex.glsl index 3b3caaab1..980212384 100644 --- a/src/mbgl/shader/line.vertex.glsl +++ b/src/mbgl/shader/line.vertex.glsl @@ -34,13 +34,13 @@ void main() { // Scale the extrusion vector down to a normal and then up by the line width // of this vertex. - vec4 dist = vec4(u_linewidth.s * a_extrude * scale, 0.0, 0.0); + vec2 dist = u_linewidth.s * a_extrude * scale; // Remove the texture normal bit of the position before scaling it with the // model/view matrix. Add the extrusion vector *after* the model/view matrix // because we're extruding the line in pixel space, regardless of the current // tile's zoom level. - gl_Position = u_matrix * vec4(floor(a_pos * 0.5) + dist.xy / u_ratio, 0.0, 1.0); + gl_Position = u_matrix * vec4(floor(a_pos * 0.5) + dist / u_ratio, 0.0, 1.0); // position of y on the screen float y = gl_Position.y / gl_Position.w; diff --git a/src/mbgl/shader/linepattern.fragment.glsl b/src/mbgl/shader/linepattern.fragment.glsl index 08feff439..4110a99ea 100644 --- a/src/mbgl/shader/linepattern.fragment.glsl +++ b/src/mbgl/shader/linepattern.fragment.glsl @@ -1,5 +1,4 @@ uniform vec2 u_linewidth; -uniform float u_point; uniform float u_blur; uniform vec2 u_pattern_size_a; @@ -15,17 +14,17 @@ uniform sampler2D u_image; varying vec2 v_normal; varying float v_linesofar; +varying float v_gamma_scale; void main() { // Calculate the distance of the pixel from the line in pixels. - float dist = length(v_normal) * (1.0 - u_point) + u_point * length(gl_PointCoord * 2.0 - 1.0); - - dist *= u_linewidth.s; + float dist = length(v_normal) * u_linewidth.s; // Calculate the antialiasing fade factor. This is either when fading in // the line in case of an offset line (v_linewidth.t) or when fading out // (v_linewidth.s) - float alpha = clamp(min(dist - (u_linewidth.t - u_blur), u_linewidth.s - dist) / u_blur, 0.0, 1.0); + float blur = u_blur * v_gamma_scale; + float alpha = clamp(min(dist - (u_linewidth.t - blur), u_linewidth.s - dist) / blur, 0.0, 1.0); float x_a = mod(v_linesofar / u_pattern_size_a.x, 1.0); float y_a = 0.5 + (v_normal.y * u_linewidth.s / u_pattern_size_a.y); diff --git a/src/mbgl/shader/linepattern.vertex.glsl b/src/mbgl/shader/linepattern.vertex.glsl index 47d551e2e..541c9fc3a 100644 --- a/src/mbgl/shader/linepattern.vertex.glsl +++ b/src/mbgl/shader/linepattern.vertex.glsl @@ -18,10 +18,13 @@ uniform mat4 u_exmatrix; uniform float u_ratio; uniform vec2 u_linewidth; uniform vec4 u_color; -uniform float u_point; + +uniform float u_extra; +uniform mat2 u_antialiasingmatrix; varying vec2 v_normal; varying float v_linesofar; +varying float v_gamma_scale; void main() { vec2 a_extrude = a_data.xy; @@ -37,24 +40,23 @@ void main() { // Scale the extrusion vector down to a normal and then up by the line width // of this vertex. - vec2 extrude = a_extrude * scale; - vec2 dist = u_linewidth.s * extrude * (1.0 - u_point); - - // If the x coordinate is the maximum integer, we move the z coordinates out - // of the view plane so that the triangle gets clipped. This makes it easier - // for us to create degenerate triangle strips. - float z = step(32767.0, a_pos.x); - - // When drawing points, skip every other vertex - z += u_point * step(1.0, v_normal.y); + vec2 dist = u_linewidth.s * a_extrude * scale; // Remove the texture normal bit of the position before scaling it with the // model/view matrix. Add the extrusion vector *after* the model/view matrix // because we're extruding the line in pixel space, regardless of the current // tile's zoom level. gl_Position = u_matrix * vec4(floor(a_pos / 2.0) + dist.xy / u_ratio, 0.0, 1.0); - v_linesofar = a_linesofar;// * u_ratio; + v_linesofar = a_linesofar; + // position of y on the screen + float y = gl_Position.y / gl_Position.w; - gl_PointSize = 2.0 * u_linewidth.s - 1.0; + // how much features are squished in the y direction by the tilt + float squish_scale = length(a_extrude) / length(u_antialiasingmatrix * a_extrude); + + // how much features are squished in all directions by the perspectiveness + float perspective_scale = 1.0 / (1.0 - y * u_extra); + + v_gamma_scale = perspective_scale * squish_scale; } diff --git a/src/mbgl/shader/linepattern_shader.hpp b/src/mbgl/shader/linepattern_shader.hpp index 16d9ff8be..dce065a0d 100644 --- a/src/mbgl/shader/linepattern_shader.hpp +++ b/src/mbgl/shader/linepattern_shader.hpp @@ -26,6 +26,8 @@ public: Uniform u_blur = {"u_blur", *this}; Uniform u_fade = {"u_fade", *this}; Uniform u_opacity = {"u_opacity", *this}; + Uniform u_extra = {"u_extra", *this}; + UniformMatrix<2> u_antialiasingmatrix = {"u_antialiasingmatrix", *this}; private: int32_t a_pos = -1; diff --git a/src/mbgl/shader/linesdf.fragment.glsl b/src/mbgl/shader/linesdf.fragment.glsl index 5d53dbe88..f8962fa57 100644 --- a/src/mbgl/shader/linesdf.fragment.glsl +++ b/src/mbgl/shader/linesdf.fragment.glsl @@ -8,6 +8,7 @@ uniform float u_mix; varying vec2 v_normal; varying vec2 v_tex_a; varying vec2 v_tex_b; +varying float v_gamma_scale; void main() { // Calculate the distance of the pixel from the line in pixels. @@ -16,7 +17,8 @@ void main() { // Calculate the antialiasing fade factor. This is either when fading in // the line in case of an offset line (v_linewidth.t) or when fading out // (v_linewidth.s) - float alpha = clamp(min(dist - (u_linewidth.t - u_blur), u_linewidth.s - dist) / u_blur, 0.0, 1.0); + float blur = u_blur * v_gamma_scale; + float alpha = clamp(min(dist - (u_linewidth.t - blur), u_linewidth.s - dist) / blur, 0.0, 1.0); float sdfdist_a = texture2D(u_image, v_tex_a).a; float sdfdist_b = texture2D(u_image, v_tex_b).a; diff --git a/src/mbgl/shader/linesdf.vertex.glsl b/src/mbgl/shader/linesdf.vertex.glsl index 6529fb45c..03851ed53 100644 --- a/src/mbgl/shader/linesdf.vertex.glsl +++ b/src/mbgl/shader/linesdf.vertex.glsl @@ -22,9 +22,13 @@ uniform float u_tex_y_a; uniform vec2 u_patternscale_b; uniform float u_tex_y_b; +uniform float u_extra; +uniform mat2 u_antialiasingmatrix; + varying vec2 v_normal; varying vec2 v_tex_a; varying vec2 v_tex_b; +varying float v_gamma_scale; void main() { vec2 a_extrude = a_data.xy; @@ -40,14 +44,25 @@ void main() { // Scale the extrusion vector down to a normal and then up by the line width // of this vertex. - vec4 dist = vec4(u_linewidth.s * a_extrude * scale, 0.0, 0.0); + vec2 dist = u_linewidth.s * a_extrude * scale; // Remove the texture normal bit of the position before scaling it with the // model/view matrix. Add the extrusion vector *after* the model/view matrix // because we're extruding the line in pixel space, regardless of the current // tile's zoom level. - gl_Position = u_matrix * vec4(floor(a_pos * 0.5) + dist.xy / u_ratio, 0.0, 1.0); + gl_Position = u_matrix * vec4(floor(a_pos * 0.5) + dist / u_ratio, 0.0, 1.0); v_tex_a = vec2(a_linesofar * u_patternscale_a.x, normal.y * u_patternscale_a.y + u_tex_y_a); v_tex_b = vec2(a_linesofar * u_patternscale_b.x, normal.y * u_patternscale_b.y + u_tex_y_b); + + // position of y on the screen + float y = gl_Position.y / gl_Position.w; + + // how much features are squished in the y direction by the tilt + float squish_scale = length(a_extrude) / length(u_antialiasingmatrix * a_extrude); + + // how much features are squished in all directions by the perspectiveness + float perspective_scale = 1.0 / (1.0 - min(y * u_extra, 0.9)); + + v_gamma_scale = perspective_scale * squish_scale; } diff --git a/src/mbgl/shader/linesdf_shader.hpp b/src/mbgl/shader/linesdf_shader.hpp index 16b7f3cb1..9928d5b30 100644 --- a/src/mbgl/shader/linesdf_shader.hpp +++ b/src/mbgl/shader/linesdf_shader.hpp @@ -25,6 +25,8 @@ public: Uniform u_image = {"u_image", *this}; Uniform u_sdfgamma = {"u_sdfgamma", *this}; Uniform u_mix = {"u_mix", *this}; + Uniform u_extra = {"u_extra", *this}; + UniformMatrix<2> u_antialiasingmatrix = {"u_antialiasingmatrix", *this}; private: int32_t a_pos = -1; From f3cd47ededd6c2994749df12d543de744773b671 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Fri, 28 Aug 2015 10:26:59 -0400 Subject: [PATCH 34/41] update test suite to disable failing test --- test/suite | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/suite b/test/suite index b3a0cddc8..80e8ff67d 160000 --- a/test/suite +++ b/test/suite @@ -1 +1 @@ -Subproject commit b3a0cddc8ae488df6ed2fc966a51c86f0fe78cd7 +Subproject commit 80e8ff67dcf9ae5627d5fcd22a831fe318df7cdf From bcfce808ca178c01eb417a6575035903d57265c1 Mon Sep 17 00:00:00 2001 From: "Justin R. Miller" Date: Fri, 28 Aug 2015 15:29:04 -0700 Subject: [PATCH 35/41] implement annotation marker tap recognition in Android --- android/cpp/jni.cpp | 104 ++++++++++++++++++ .../com/mapbox/mapboxgl/views/MapView.java | 36 ++++++ .../mapbox/mapboxgl/views/NativeMapView.java | 9 ++ include/mbgl/android/jni.hpp | 7 ++ 4 files changed, 156 insertions(+) diff --git a/android/cpp/jni.cpp b/android/cpp/jni.cpp index d1040d68e..e077e318a 100644 --- a/android/cpp/jni.cpp +++ b/android/cpp/jni.cpp @@ -50,6 +50,13 @@ jfieldID latLngZoomLatitudeId = nullptr; jfieldID latLngZoomLongitudeId = nullptr; jfieldID latLngZoomZoomId = nullptr; +jclass bboxClass = nullptr; +jmethodID bboxConstructorId = nullptr; +jfieldID bboxLatNorthId = nullptr; +jfieldID bboxLatSouthId = nullptr; +jfieldID bboxLonEastId = nullptr; +jfieldID bboxLonWestId = nullptr; + jclass markerClass = nullptr; jmethodID markerConstructorId = nullptr; jfieldID markerPositionId = nullptr; @@ -970,6 +977,50 @@ void JNICALL nativeRemoveAnnotations(JNIEnv *env, jobject obj, jlong nativeMapVi nativeMapView->getMap().removeAnnotations(ids); } +jlongArray JNICALL nativeGetAnnotationsInBounds(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject bbox) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetAnnotationsInBounds"); + assert(nativeMapViewPtr != 0); + NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); + + if (env->ExceptionCheck() || (bbox == nullptr)) { + env->ExceptionDescribe(); + return nullptr; + } + + jdouble swLat = env->GetDoubleField(bbox, bboxLatSouthId); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return nullptr; + } + + jdouble swLon = env->GetDoubleField(bbox, bboxLonWestId); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return nullptr; + } + + jdouble neLat = env->GetDoubleField(bbox, bboxLatNorthId); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return nullptr; + } + + jdouble neLon = env->GetDoubleField(bbox, bboxLonEastId); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return nullptr; + } + + mbgl::LatLngBounds bounds; + bounds.sw = { swLat, swLon }; + bounds.ne = { neLat, neLon }; + + // assume only points for now + std::vector annotations = nativeMapView->getMap().getAnnotationsInBounds(bounds, mbgl::AnnotationType::Point); + + return std_vector_uint_to_jobject(env, annotations); +} + void JNICALL nativeSetSprite(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jstring symbol, jint width, jint height, jfloat scale, jbyteArray jpixels) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetSprite"); @@ -1246,6 +1297,42 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { return JNI_ERR; } + bboxClass = env->FindClass("com/mapbox/mapboxgl/geometry/BoundingBox"); + if (bboxClass == nullptr) { + env->ExceptionDescribe(); + return JNI_ERR; + } + + bboxConstructorId = env->GetMethodID(bboxClass, "", "(DDDD)V"); + if (bboxConstructorId == nullptr) { + env->ExceptionDescribe(); + return JNI_ERR; + } + + bboxLatNorthId = env->GetFieldID(bboxClass, "mLatNorth", "D"); + if (bboxLatNorthId == nullptr) { + env->ExceptionDescribe(); + return JNI_ERR; + } + + bboxLatSouthId = env->GetFieldID(bboxClass, "mLatSouth", "D"); + if (bboxLatSouthId == nullptr) { + env->ExceptionDescribe(); + return JNI_ERR; + } + + bboxLonEastId = env->GetFieldID(bboxClass, "mLonEast", "D"); + if (bboxLonEastId == nullptr) { + env->ExceptionDescribe(); + return JNI_ERR; + } + + bboxLonWestId = env->GetFieldID(bboxClass, "mLonWest", "D"); + if (bboxLonWestId == nullptr) { + env->ExceptionDescribe(); + return JNI_ERR; + } + markerClass = env->FindClass("com/mapbox/mapboxgl/annotations/Marker"); if (markerClass == nullptr) { env->ExceptionDescribe(); @@ -1596,6 +1683,8 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { reinterpret_cast(&nativeAddPolygons)}, {"nativeRemoveAnnotation", "(JJ)V", reinterpret_cast(&nativeRemoveAnnotation)}, {"nativeRemoveAnnotations", "(J[J)V", reinterpret_cast(&nativeRemoveAnnotations)}, + {"nativeGetAnnotationsInBounds", "(JLcom/mapbox/mapboxgl/geometry/BoundingBox;)[J", + reinterpret_cast(&nativeGetAnnotationsInBounds)}, {"nativeSetSprite", "(JLjava/lang/String;IIF[B)V", reinterpret_cast(&nativeSetSprite)}, {"nativeOnLowMemory", "(J)V", reinterpret_cast(&nativeOnLowMemory)}, {"nativeSetDebug", "(JZ)V", reinterpret_cast(&nativeSetDebug)}, @@ -1639,6 +1728,13 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { return JNI_ERR; } + bboxClass = reinterpret_cast(env->NewGlobalRef(bboxClass)); + if (bboxClass == nullptr) { + env->ExceptionDescribe(); + env->DeleteGlobalRef(bboxClass); + return JNI_ERR; + } + markerClass = reinterpret_cast(env->NewGlobalRef(markerClass)); if (markerClass == nullptr) { env->ExceptionDescribe(); @@ -1795,6 +1891,14 @@ extern "C" JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) { latLngZoomLatitudeId = nullptr; latLngZoomZoomId = nullptr; + env->DeleteGlobalRef(bboxClass); + bboxClass = nullptr; + bboxConstructorId = nullptr; + bboxLatNorthId = nullptr; + bboxLatSouthId = nullptr; + bboxLonEastId = nullptr; + bboxLonWestId = nullptr; + env->DeleteGlobalRef(markerClass); markerClass = nullptr; markerConstructorId = nullptr; diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java index 219069fda..8dde403c7 100644 --- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java @@ -50,6 +50,7 @@ import com.mapbox.mapboxgl.annotations.Polygon; import com.mapbox.mapboxgl.annotations.PolygonOptions; import com.mapbox.mapboxgl.annotations.Polyline; import com.mapbox.mapboxgl.annotations.PolylineOptions; +import com.mapbox.mapboxgl.geometry.BoundingBox; import com.mapbox.mapboxgl.geometry.LatLng; import com.mapbox.mapboxgl.geometry.LatLngZoom; import com.mapzen.android.lost.api.LocationListener; @@ -428,6 +429,25 @@ public class MapView extends FrameLayout implements LocationListener { return Collections.unmodifiableList(mAnnotations); } + public List getAnnotationsInBounds(BoundingBox bbox) { + List annotations = new ArrayList<>(); + long[] ids = mNativeMapView.getAnnotationsInBounds(bbox); + List idsList = new ArrayList<>(); + for(int i = 0; i < ids.length; i++) { + idsList.add(new Long(ids[i])); + } + for(int i = 0; i < mAnnotations.size(); i++) { + Annotation annotation = mAnnotations.get(i); + if (annotation instanceof Marker && idsList.contains(annotation.getId())) { + annotations.add(annotation); + } + } + for(int i = 0; i < annotations.size(); i++) { + Log.d(TAG, "tapped: " + Long.toString(annotations.get(i).getId())); + } + return annotations; + } + // // Property methods // @@ -919,6 +939,22 @@ public class MapView extends FrameLayout implements LocationListener { // Cancel any animation mNativeMapView.cancelTransitions(); + // Select or deselect point annotations + PointF tapPoint = new PointF(e.getX(), e.getY()); + + float toleranceWidth = 60 * mScreenDensity; + float toleranceHeight = 80 * mScreenDensity; + + PointF tr = new PointF(tapPoint.x + toleranceWidth / 2, tapPoint.y + 2 * toleranceHeight / 3); + PointF bl = new PointF(tapPoint.x - toleranceWidth / 2, tapPoint.y - 1 * toleranceHeight / 3); + + LatLng sw = fromScreenLocation(bl); + LatLng ne = fromScreenLocation(tr); + + BoundingBox bbox = new BoundingBox(ne, sw); + + List annotations = getAnnotationsInBounds(bbox); + return true; } diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/NativeMapView.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/NativeMapView.java index 6257a2362..56589f479 100644 --- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/NativeMapView.java +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/NativeMapView.java @@ -3,13 +3,16 @@ package com.mapbox.mapboxgl.views; import android.graphics.PointF; import android.view.Surface; +import com.mapbox.mapboxgl.annotations.Annotation; import com.mapbox.mapboxgl.annotations.Marker; import com.mapbox.mapboxgl.annotations.Polygon; import com.mapbox.mapboxgl.annotations.Polyline; +import com.mapbox.mapboxgl.geometry.BoundingBox; import com.mapbox.mapboxgl.geometry.LatLng; import com.mapbox.mapboxgl.geometry.LatLngZoom; import com.mapbox.mapboxgl.geometry.ProjectedMeters; +import java.util.ArrayList; import java.util.List; // Class that wraps the native methods for convenience @@ -353,6 +356,10 @@ class NativeMapView { nativeRemoveAnnotations(mNativeMapViewPtr, ids); } + public long[] getAnnotationsInBounds(BoundingBox bbox) { + return nativeGetAnnotationsInBounds(mNativeMapViewPtr, bbox); + } + public void setSprite(String symbol, int width, int height, float scale, byte[] pixels) { nativeSetSprite(mNativeMapViewPtr, symbol, width, height, scale, pixels); } @@ -563,6 +570,8 @@ class NativeMapView { private native void nativeRemoveAnnotations(long nativeMapViewPtr, long[] id); + private native long[] nativeGetAnnotationsInBounds(long mNativeMapViewPtr, BoundingBox bbox); + private native void nativeSetSprite(long nativeMapViewPtr, String symbol, int width, int height, float scale, byte[] pixels); diff --git a/include/mbgl/android/jni.hpp b/include/mbgl/android/jni.hpp index 62cb399d3..07c44fc7a 100644 --- a/include/mbgl/android/jni.hpp +++ b/include/mbgl/android/jni.hpp @@ -43,6 +43,13 @@ extern jfieldID latLngZoomLatitudeId; extern jfieldID latLngZoomLongitudeId; extern jfieldID latLngZoomZoomId; +extern jclass bboxClass; +extern jmethodID bboxConstructorId; +extern jfieldID bboxLatNorthId; +extern jfieldID bboxLatSouthId; +extern jfieldID bboxLonEastId; +extern jfieldID bboxLonWestId; + extern jclass markerClass; extern jmethodID markerConstructorId; extern jfieldID markerPositionId; From c6e3ed8c6629d0a42d984a4ced57eff558eac0ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Fri, 28 Aug 2015 13:03:05 -0700 Subject: [PATCH 36/41] Updated title of attribution action sheet --- platform/ios/MGLMapView.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 4f3e90307..a037ff05c 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -280,7 +280,7 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration) [self addSubview:_attributionButton]; _attributionButtonConstraints = [NSMutableArray array]; - _attributionSheet = [[UIActionSheet alloc] initWithTitle:@"Mapbox for iOS" + _attributionSheet = [[UIActionSheet alloc] initWithTitle:@"Mapbox iOS SDK" delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil From dabfec6ddc2701e0e225ad8d90febbad299e6c1e Mon Sep 17 00:00:00 2001 From: tobrunvannuland Date: Sun, 30 Aug 2015 20:46:13 +0200 Subject: [PATCH 37/41] Added proguard config for SDK Updated build.gradle from the SDK to correct use proguard file from a AAR library Adjusted build.gradle sample app to use the thumb proguard file Added proguard config for SDK, added thumb config for sample project Updated build.gradle from the SDK to correct use proguard file from a AAR library Adjusted build.gradle sample app to use the thumb proguard file Added proguard config for SDK, added thumb config for sample project Updated build.gradle from the SDK to correct use proguard file from a AAR library Adjusted build.gradle sample app to use the thumb proguard file --- android/java/MapboxGLAndroidSDK/build.gradle | 3 +-- .../MapboxGLAndroidSDK/proguard-rules.pro | 24 +++++++++++++++++++ .../MapboxGLAndroidSDKTestApp/build.gradle | 2 +- .../proguard-rules.pro | 1 + 4 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 android/java/MapboxGLAndroidSDK/proguard-rules.pro create mode 100644 android/java/MapboxGLAndroidSDKTestApp/proguard-rules.pro diff --git a/android/java/MapboxGLAndroidSDK/build.gradle b/android/java/MapboxGLAndroidSDK/build.gradle index b749765eb..ea0be4fa1 100644 --- a/android/java/MapboxGLAndroidSDK/build.gradle +++ b/android/java/MapboxGLAndroidSDK/build.gradle @@ -65,9 +65,8 @@ android { } release { - minifyEnabled false jniDebuggable false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' + consumerProguardFiles 'proguard-rules.pro' } } } diff --git a/android/java/MapboxGLAndroidSDK/proguard-rules.pro b/android/java/MapboxGLAndroidSDK/proguard-rules.pro new file mode 100644 index 000000000..6d3ca44d4 --- /dev/null +++ b/android/java/MapboxGLAndroidSDK/proguard-rules.pro @@ -0,0 +1,24 @@ +# By default, the flags in this file are appended to flags specified +# in ../sdk/tools/proguard/proguard-android.txt, +# contents of this file will be appended into proguard-android.txt + +# Square okio, ignoring warnings, +# see https://github.com/square/okio/issues/60 +-dontwarn okio.** + +# Package: annotations +-keep class com.mapbox.mapboxgl.annotations.** { *; } + +# Package: geometry +-keep class com.mapbox.mapboxgl.geometry.** { *; } + +# Package: http +-keep class com.mapbox.mapboxgl.http.** { *; } + +# Package views +-keep class com.mapbox.mapboxgl.views.MapView** +-keep class com.mapbox.mapboxgl.views.NativeMapView** +-keepclassmembers class com.mapbox.mapboxgl.views.NativeMapView** { + *; +} + diff --git a/android/java/MapboxGLAndroidSDKTestApp/build.gradle b/android/java/MapboxGLAndroidSDKTestApp/build.gradle index b3e4164f2..b0c0f1a3e 100644 --- a/android/java/MapboxGLAndroidSDKTestApp/build.gradle +++ b/android/java/MapboxGLAndroidSDKTestApp/build.gradle @@ -73,7 +73,7 @@ android { buildTypes { release { minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } diff --git a/android/java/MapboxGLAndroidSDKTestApp/proguard-rules.pro b/android/java/MapboxGLAndroidSDKTestApp/proguard-rules.pro new file mode 100644 index 000000000..578d94692 --- /dev/null +++ b/android/java/MapboxGLAndroidSDKTestApp/proguard-rules.pro @@ -0,0 +1 @@ +# Proguard configuration is handeld in the SDK \ No newline at end of file From 1189dea852cc207253452b511a2f62564535f4b2 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Mon, 31 Aug 2015 16:55:25 -0500 Subject: [PATCH 38/41] #2063 - Fixing test/suite stomping from merge --- test/suite | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/suite b/test/suite index b6828212d..80e8ff67d 160000 --- a/test/suite +++ b/test/suite @@ -1 +1 @@ -Subproject commit b6828212d3fe5a06e1e91df1dc9a212cb5656093 +Subproject commit 80e8ff67dcf9ae5627d5fcd22a831fe318df7cdf From fc55a34831021efe3475346cf2f4c45f9bb1d151 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 31 Aug 2015 15:17:45 -0700 Subject: [PATCH 39/41] Update test-suite --- test/suite | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/suite b/test/suite index 80e8ff67d..083dbe5f3 160000 --- a/test/suite +++ b/test/suite @@ -1 +1 @@ -Subproject commit 80e8ff67dcf9ae5627d5fcd22a831fe318df7cdf +Subproject commit 083dbe5f3da13d006f3d2eb6669780b1d003a7e3 From cb905bac28f845477816bd04128bb2d04f7667ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Fri, 28 Aug 2015 12:35:50 -0700 Subject: [PATCH 40/41] Fixed persistence of user tracking mode in iOS This typo prevented the tracking mode from being restored when relaunching iosapp. --- platform/darwin/settings_nsuserdefaults.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/darwin/settings_nsuserdefaults.mm b/platform/darwin/settings_nsuserdefaults.mm index 5c943baff..548ee9b22 100644 --- a/platform/darwin/settings_nsuserdefaults.mm +++ b/platform/darwin/settings_nsuserdefaults.mm @@ -30,7 +30,7 @@ void Settings_NSUserDefaults::load() pitch = [settings[@"pitch"] doubleValue]; debug = [settings[@"debug"] boolValue]; - unsigned uncheckedTrackingMode = [settings[@"trackingMode"] unsignedIntValue]; + unsigned uncheckedTrackingMode = [settings[@"userTrackingMode"] unsignedIntValue]; if (uncheckedTrackingMode > MGLUserTrackingModeNone && uncheckedTrackingMode <= MGLUserTrackingModeFollowWithCourse) { @@ -57,4 +57,4 @@ void Settings_NSUserDefaults::save() void Settings_NSUserDefaults::clear() { [NSUserDefaults resetStandardUserDefaults]; -} \ No newline at end of file +} From 831df11ec47cb44f6664490a361ff42ef288ce9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Mon, 31 Aug 2015 15:27:26 -0700 Subject: [PATCH 41/41] Disabled iOS metrics tests ref #1887 --- .../xcschemes/Mapbox GL Tests.xcscheme | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/test/ios/ios-tests.xcodeproj/xcshareddata/xcschemes/Mapbox GL Tests.xcscheme b/test/ios/ios-tests.xcodeproj/xcshareddata/xcschemes/Mapbox GL Tests.xcscheme index f7173ee64..2737f5185 100644 --- a/test/ios/ios-tests.xcodeproj/xcshareddata/xcschemes/Mapbox GL Tests.xcscheme +++ b/test/ios/ios-tests.xcodeproj/xcshareddata/xcschemes/Mapbox GL Tests.xcscheme @@ -37,10 +37,10 @@ + shouldUseLaunchSchemeArgsEnv = "YES"> @@ -58,6 +58,9 @@ + + @@ -79,15 +82,18 @@ ReferencedContainer = "container:ios-tests.xcodeproj"> + + @@ -103,10 +109,10 @@