diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2015-11-16 16:32:09 +0100 |
---|---|---|
committer | Konstantin Käfer <mail@kkaefer.com> | 2015-12-15 11:41:58 -0800 |
commit | 4fc8226838a23154ca8acc5e5fcb6144de0794cb (patch) | |
tree | ac2354fda5e9bca147d7eb3f5bdddbaa291dc319 | |
parent | 62412af6ab746dd8fb5b8984c75b3ff6e6b223e5 (diff) | |
download | qtlocation-mapboxgl-4fc8226838a23154ca8acc5e5fcb6144de0794cb.tar.gz |
[core] allow changing the orientation
You can now change the orientation of north to be to the right, bottom, left in addition to the default of top
-rw-r--r-- | include/mbgl/map/map.hpp | 4 | ||||
-rw-r--r-- | include/mbgl/platform/default/glfw_view.hpp | 2 | ||||
-rw-r--r-- | include/mbgl/util/geo.hpp | 8 | ||||
-rw-r--r-- | include/mbgl/util/mat4.hpp | 1 | ||||
-rw-r--r-- | platform/default/glfw_view.cpp | 14 | ||||
-rw-r--r-- | src/mbgl/map/map.cpp | 12 | ||||
-rw-r--r-- | src/mbgl/map/transform.cpp | 11 | ||||
-rw-r--r-- | src/mbgl/map/transform.hpp | 4 | ||||
-rw-r--r-- | src/mbgl/map/transform_state.cpp | 44 | ||||
-rw-r--r-- | src/mbgl/map/transform_state.hpp | 7 | ||||
-rw-r--r-- | src/mbgl/renderer/painter_symbol.cpp | 2 | ||||
-rw-r--r-- | src/mbgl/util/mat4.cpp | 34 |
12 files changed, 136 insertions, 7 deletions
diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index df7597ced4..f8c3f4a172 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -133,6 +133,10 @@ public: void setPitch(double pitch, const Duration& = Duration::zero()); double getPitch() const; + // North Orientation + void setNorthOrientation(NorthOrientation); + NorthOrientation getNorthOrientation() const; + // Size uint16_t getWidth() const; uint16_t getHeight() const; diff --git a/include/mbgl/platform/default/glfw_view.hpp b/include/mbgl/platform/default/glfw_view.hpp index a434b71bb1..0e46f7d87e 100644 --- a/include/mbgl/platform/default/glfw_view.hpp +++ b/include/mbgl/platform/default/glfw_view.hpp @@ -50,6 +50,8 @@ private: static std::shared_ptr<const mbgl::SpriteImage> makeSpriteImage(int width, int height, float pixelRatio); + void nextOrientation(); + void addRandomPointAnnotations(int count); void addRandomShapeAnnotations(int count); void addRandomCustomPointAnnotations(int count); diff --git a/include/mbgl/util/geo.hpp b/include/mbgl/util/geo.hpp index 2f0e4f6fdc..e815456f22 100644 --- a/include/mbgl/util/geo.hpp +++ b/include/mbgl/util/geo.hpp @@ -100,6 +100,14 @@ struct MetersBounds { } }; +// Determines the orientation of the map. +enum class NorthOrientation : uint8_t { + Upwards, // Default + Rightwards, + Downwards, + Leftwards, +}; + } // namespace mbgl #endif diff --git a/include/mbgl/util/mat4.hpp b/include/mbgl/util/mat4.hpp index e5b508e547..59f6e3ee00 100644 --- a/include/mbgl/util/mat4.hpp +++ b/include/mbgl/util/mat4.hpp @@ -38,6 +38,7 @@ 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, double x, double y, double z); void rotate_x(mat4& out, const mat4& a, double rad); +void rotate_y(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/platform/default/glfw_view.cpp b/platform/default/glfw_view.cpp index 418f427c74..c83e6c324b 100644 --- a/platform/default/glfw_view.cpp +++ b/platform/default/glfw_view.cpp @@ -92,6 +92,7 @@ GLFWView::GLFWView(bool fullscreen_, bool benchmark_) printf("- Press `X` to reset the transform\n"); printf("- Press `N` to reset north\n"); printf("- Press `R` to toggle any available `night` style class\n"); + printf("- Press `Z` to cycle through north orientations\n"); printf("\n"); printf("- Press `1` through `6` to add increasing numbers of point annotations for testing\n"); printf("- Press `7` through `0` to add increasing numbers of shape annotations for testing\n"); @@ -153,6 +154,9 @@ void GLFWView::onKey(GLFWwindow *window, int key, int /*scancode*/, int action, if (!mods) view->map->resetNorth(); break; + case GLFW_KEY_Z: + view->nextOrientation(); + break; case GLFW_KEY_Q: view->clearAnnotations(); break; @@ -218,6 +222,16 @@ GLFWView::makeSpriteImage(int width, int height, float pixelRatio) { return std::make_shared<mbgl::SpriteImage>(width, height, pixelRatio, std::move(pixels)); } +void GLFWView::nextOrientation() { + using NO = mbgl::NorthOrientation; + switch (map->getNorthOrientation()) { + case NO::Upwards: map->setNorthOrientation(NO::Rightwards); break; + case NO::Rightwards: map->setNorthOrientation(NO::Downwards); break; + case NO::Downwards: map->setNorthOrientation(NO::Leftwards); break; + default: map->setNorthOrientation(NO::Upwards); break; + } +} + void GLFWView::addRandomCustomPointAnnotations(int count) { std::vector<mbgl::PointAnnotation> points; diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 4336c2556d..3c585a8ae2 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -343,6 +343,18 @@ double Map::getPitch() const { } +#pragma mark - North Orientation + +void Map::setNorthOrientation(NorthOrientation orientation) { + transform->setNorthOrientation(orientation); + update(Update::Repaint); +} + +NorthOrientation Map::getNorthOrientation() const { + return transform->getNorthOrientation(); +} + + #pragma mark - Projection MetersBounds Map::getWorldBoundsMeters() const { diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp index 5ba3b7493d..4604fbb287 100644 --- a/src/mbgl/map/transform.cpp +++ b/src/mbgl/map/transform.cpp @@ -498,6 +498,17 @@ double Transform::getPitch() const { return state.pitch; } +#pragma mark - North Orientation + +void Transform::setNorthOrientation(NorthOrientation orientation) { + state.orientation = orientation; + state.constrain(state.scale, state.x, state.y); +} + +NorthOrientation Transform::getNorthOrientation() const { + return state.getNorthOrientation(); +} + #pragma mark - Transition void Transform::startTransition(std::function<double(double)> easing, diff --git a/src/mbgl/map/transform.hpp b/src/mbgl/map/transform.hpp index 391b8c8d65..0bb6bb851e 100644 --- a/src/mbgl/map/transform.hpp +++ b/src/mbgl/map/transform.hpp @@ -52,6 +52,10 @@ public: void setPitch(double pitch, const Duration& = Duration::zero()); double getPitch() const; + // North Orientation + void setNorthOrientation(NorthOrientation); + NorthOrientation getNorthOrientation() const; + // Transitions bool inTransition() const; Update updateTransitions(const TimePoint& now); diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp index 44a4c29402..7153c2524b 100644 --- a/src/mbgl/map/transform_state.cpp +++ b/src/mbgl/map/transform_state.cpp @@ -37,10 +37,17 @@ void TransformState::getProjMatrix(mat4& projMatrix) const { // 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::scale(projMatrix, projMatrix, 1, -1, 1.0f / (rotatedNorth() ? getWidth() : getHeight())); + + using NO = NorthOrientation; + switch (getNorthOrientation()) { + case NO::Rightwards: matrix::rotate_y(projMatrix, projMatrix, getPitch()); break; + case NO::Downwards: matrix::rotate_x(projMatrix, projMatrix, -getPitch()); break; + case NO::Leftwards: matrix::rotate_y(projMatrix, projMatrix, -getPitch()); break; + default: matrix::rotate_x(projMatrix, projMatrix, getPitch()); break; + } - matrix::rotate_x(projMatrix, projMatrix, getPitch()); - matrix::rotate_z(projMatrix, projMatrix, getAngle()); + matrix::rotate_z(projMatrix, projMatrix, getAngle() + getNorthOrientationAngle()); matrix::translate(projMatrix, projMatrix, pixel_x() - getWidth() / 2.0f, pixel_y() - getHeight() / 2.0f, 0); @@ -72,6 +79,24 @@ uint16_t TransformState::getHeight() const { return height; } +#pragma mark - North Orientation + +NorthOrientation TransformState::getNorthOrientation() const { + return orientation; +} + +double TransformState::getNorthOrientationAngle() const { + double angleOrientation = 0; + if (orientation == NorthOrientation::Rightwards) { + angleOrientation += M_PI / 2.0f; + } else if (orientation == NorthOrientation::Downwards) { + angleOrientation += M_PI; + } else if (orientation == NorthOrientation::Leftwards) { + angleOrientation -= M_PI / 2.0f; + } + return angleOrientation; +} + #pragma mark - Position LatLng TransformState::getLatLng() const { @@ -318,21 +343,26 @@ mat4 TransformState::getPixelMatrix() const { #pragma mark - (private helper functions) +bool TransformState::rotatedNorth() const { + using NO = NorthOrientation; + return (orientation == NO::Leftwards || orientation == NO::Rightwards); +} + void TransformState::constrain(double& scale_, double& x_, double& y_) const { // Constrain minimum scale to avoid zooming out far enough to show off-world areas. if (constrainMode == ConstrainMode::WidthAndHeight) { - scale_ = std::max(scale_, static_cast<double>(width / util::tileSize)); + scale_ = std::max(scale_, static_cast<double>((rotatedNorth() ? height : width) / util::tileSize)); } - scale_ = std::max(scale_, static_cast<double>(height / util::tileSize)); + scale_ = std::max(scale_, static_cast<double>((rotatedNorth() ? width : height) / util::tileSize)); // Constrain min/max pan to avoid showing off-world areas. if (constrainMode == ConstrainMode::WidthAndHeight) { - double max_x = (scale_ * util::tileSize - width) / 2; + double max_x = (scale_ * util::tileSize - (rotatedNorth() ? height : width)) / 2; x_ = std::max(-max_x, std::min(x_, max_x)); } - double max_y = (scale_ * util::tileSize - height) / 2; + double max_y = (scale_ * util::tileSize - (rotatedNorth() ? width : height)) / 2; y_ = std::max(-max_y, std::min(y_, max_y)); } diff --git a/src/mbgl/map/transform_state.hpp b/src/mbgl/map/transform_state.hpp index 37ea7fa0f4..fd9a556eb9 100644 --- a/src/mbgl/map/transform_state.hpp +++ b/src/mbgl/map/transform_state.hpp @@ -34,6 +34,10 @@ public: uint16_t getWidth() const; uint16_t getHeight() const; + // North Orientation + NorthOrientation getNorthOrientation() const; + double getNorthOrientationAngle() const; + std::array<float, 2> locationCoordinate(float lon, float lat) const; void getLonLat(double &lon, double &lat) const; @@ -74,12 +78,15 @@ public: TileCoordinate pointToCoordinate(const PrecisionPoint&) const; private: + bool rotatedNorth() const; void constrain(double& scale, double& x, double& y) const; // Limit the amount of zooming possible on the map. double min_scale = std::pow(2, 0); double max_scale = std::pow(2, 18); + NorthOrientation orientation = NorthOrientation::Upwards; + // logical dimensions uint16_t width = 0, height = 0; diff --git a/src/mbgl/renderer/painter_symbol.cpp b/src/mbgl/renderer/painter_symbol.cpp index 4a00d941db..0cb73b9f27 100644 --- a/src/mbgl/renderer/painter_symbol.cpp +++ b/src/mbgl/renderer/painter_symbol.cpp @@ -40,6 +40,7 @@ void Painter::renderSDF(SymbolBucket &bucket, exMatrix = extrudeMatrix; s = state.getAltitude(); gammaScale = 1.0f; + matrix::rotate_z(exMatrix, exMatrix, state.getNorthOrientationAngle()); } matrix::scale(exMatrix, exMatrix, s, s, 1); @@ -218,6 +219,7 @@ void Painter::renderSymbol(SymbolBucket& bucket, const SymbolLayer& layer, const s = 4096.0f / util::tileSize / id.overscaling / std::pow(2, state.getZoom() - id.z); } else { exMatrix = extrudeMatrix; + matrix::rotate_z(exMatrix, exMatrix, state.getNorthOrientationAngle()); s = state.getAltitude(); } matrix::scale(exMatrix, exMatrix, s, s, 1); diff --git a/src/mbgl/util/mat4.cpp b/src/mbgl/util/mat4.cpp index 0934cd081e..5f6f9d1b4c 100644 --- a/src/mbgl/util/mat4.cpp +++ b/src/mbgl/util/mat4.cpp @@ -214,6 +214,40 @@ void matrix::rotate_x(mat4& out, const mat4& a, double rad) { out[11] = a23 * c - a13 * s; } +void matrix::rotate_y(mat4& out, const mat4& a, double rad) { + double s = std::sin(rad), + c = std::cos(rad), + a00 = a[0], + a01 = a[1], + a02 = a[2], + a03 = a[3], + 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[4] = a[4]; + out[5] = a[5]; + out[6] = a[6]; + out[7] = a[7]; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + } + + // Perform axis-specific matrix multiplication + out[0] = a00 * c - a20 * s; + out[1] = a01 * c - a21 * s; + out[2] = a02 * c - a22 * s; + out[3] = a03 * c - a23 * s; + out[8] = a00 * s + a20 * c; + out[9] = a01 * s + a21 * c; + out[10] = a02 * s + a22 * c; + out[11] = a03 * s + a23 * c; +} + void matrix::rotate_z(mat4& out, const mat4& a, double rad) { double s = std::sin(rad), c = std::cos(rad), |