summaryrefslogtreecommitdiff
path: root/src/mbgl
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2015-08-31 16:45:21 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2015-08-31 16:45:21 -0700
commitabc1c84fb817a8e31dd1226a633dc895fdae602e (patch)
tree0eef59c9f60a19b722b413f9deef20982cb77b45 /src/mbgl
parent119a9fbf776fc488b19668f54cc68998ebdfb12a (diff)
parent831df11ec47cb44f6664490a361ff42ef288ce9b (diff)
downloadqtlocation-mapboxgl-abc1c84fb817a8e31dd1226a633dc895fdae602e.tar.gz
Merge branch 'master' into node
Diffstat (limited to 'src/mbgl')
-rw-r--r--src/mbgl/map/live_tile_data.cpp4
-rw-r--r--src/mbgl/map/map.cpp16
-rw-r--r--src/mbgl/map/map_context.cpp5
-rw-r--r--src/mbgl/map/source.cpp24
-rw-r--r--src/mbgl/map/tile_data.hpp2
-rw-r--r--src/mbgl/map/tile_worker.cpp13
-rw-r--r--src/mbgl/map/tile_worker.hpp4
-rw-r--r--src/mbgl/map/transform.cpp9
-rw-r--r--src/mbgl/map/transform.hpp4
-rw-r--r--src/mbgl/map/transform_state.cpp226
-rw-r--r--src/mbgl/map/transform_state.hpp42
-rw-r--r--src/mbgl/map/vector_tile_data.cpp17
-rw-r--r--src/mbgl/map/vector_tile_data.hpp5
-rw-r--r--src/mbgl/renderer/bucket.hpp9
-rw-r--r--src/mbgl/renderer/painter.cpp63
-rw-r--r--src/mbgl/renderer/painter.hpp19
-rw-r--r--src/mbgl/renderer/painter_circle.cpp2
-rw-r--r--src/mbgl/renderer/painter_fill.cpp8
-rw-r--r--src/mbgl/renderer/painter_line.cpp29
-rw-r--r--src/mbgl/renderer/painter_raster.cpp2
-rw-r--r--src/mbgl/renderer/painter_symbol.cpp71
-rw-r--r--src/mbgl/renderer/symbol_bucket.cpp71
-rw-r--r--src/mbgl/renderer/symbol_bucket.hpp21
-rw-r--r--src/mbgl/shader/icon.vertex.glsl12
-rw-r--r--src/mbgl/shader/icon_shader.hpp2
-rw-r--r--src/mbgl/shader/line.fragment.glsl4
-rw-r--r--src/mbgl/shader/line.vertex.glsl23
-rw-r--r--src/mbgl/shader/line_shader.hpp2
-rw-r--r--src/mbgl/shader/linepattern.fragment.glsl9
-rw-r--r--src/mbgl/shader/linepattern.vertex.glsl30
-rw-r--r--src/mbgl/shader/linepattern_shader.hpp2
-rw-r--r--src/mbgl/shader/linesdf.fragment.glsl4
-rw-r--r--src/mbgl/shader/linesdf.vertex.glsl19
-rw-r--r--src/mbgl/shader/linesdf_shader.hpp2
-rw-r--r--src/mbgl/shader/outline.vertex.glsl2
-rw-r--r--src/mbgl/shader/sdf.fragment.glsl4
-rw-r--r--src/mbgl/shader/sdf.vertex.glsl18
-rw-r--r--src/mbgl/shader/sdf_shader.hpp2
-rw-r--r--src/mbgl/shader/uniform.hpp14
-rw-r--r--src/mbgl/text/collision_tile.cpp10
-rw-r--r--src/mbgl/text/collision_tile.hpp11
-rw-r--r--src/mbgl/text/quads.cpp42
-rw-r--r--src/mbgl/text/quads.hpp6
-rw-r--r--src/mbgl/util/box.hpp7
-rw-r--r--src/mbgl/util/mat2.cpp52
-rw-r--r--src/mbgl/util/mat2.hpp41
-rw-r--r--src/mbgl/util/mat3.cpp10
-rw-r--r--src/mbgl/util/mat3.hpp8
-rw-r--r--src/mbgl/util/mat4.cpp120
-rw-r--r--src/mbgl/util/tile_coordinate.hpp29
-rw-r--r--src/mbgl/util/tile_cover.cpp11
-rw-r--r--src/mbgl/util/vec4.cpp33
-rw-r--r--src/mbgl/util/vec4.hpp40
-rw-r--r--src/mbgl/util/worker.cpp8
-rw-r--r--src/mbgl/util/worker.hpp1
55 files changed, 882 insertions, 362 deletions
diff --git a/src/mbgl/map/live_tile_data.cpp b/src/mbgl/map/live_tile_data.cpp
index 8be918d6d4..0b73b52f36 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<CollisionTile>(id_.z, 4096,
- source_.tile_size * id.overscaling,
- 0, false)) {
+ std::make_unique<CollisionTile>(0, 0, false)) {
state = State::loaded;
if (!tile) {
diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp
index b260b228fc..bab1a48225 100644
--- a/src/mbgl/map/map.cpp
+++ b/src/mbgl/map/map.cpp
@@ -271,6 +271,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 {
@@ -294,11 +306,11 @@ const LatLng Map::latLngForProjectedMeters(const ProjectedMeters projectedMeters
}
const vec2<double> Map::pixelForLatLng(const LatLng latLng) const {
- return transform->getState().pixelForLatLng(latLng);
+ return transform->getState().latLngToPoint(latLng);
}
const LatLng Map::latLngForPixel(const vec2<double> pixel) const {
- return transform->getState().latLngForPixel(pixel);
+ return transform->getState().pointToLatLng(pixel);
}
#pragma mark - Annotations
diff --git a/src/mbgl/map/map_context.cpp b/src/mbgl/map/map_context.cpp
index 175f987195..f6cc4ec2b7 100644
--- a/src/mbgl/map/map_context.cpp
+++ b/src/mbgl/map/map_context.cpp
@@ -336,7 +336,6 @@ bool MapContext::renderSync(const TransformState& state, const FrameData& frame)
if (!painter) {
painter = std::make_unique<Painter>(data);
painter->setup();
- painter->updateRenderOrder(*style);
}
painter->setDebug(data.getDebug());
@@ -403,10 +402,6 @@ void MapContext::setSprite(const std::string& name, std::shared_ptr<const Sprite
void MapContext::onTileDataChanged() {
assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
- if (painter) {
- painter->updateRenderOrder(*style);
- }
-
updateFlags |= Update::Repaint;
asyncUpdate->send();
}
diff --git a/src/mbgl/map/source.cpp b/src/mbgl/map/source.cpp
index 4b2ae2cfbd..5899fea1ec 100644
--- a/src/mbgl/map/source.cpp
+++ b/src/mbgl/map/source.cpp
@@ -9,6 +9,7 @@
#include <mbgl/storage/response.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/util/box.hpp>
+#include <mbgl/util/tile_coordinate.hpp>
#include <mbgl/util/mapbox.hpp>
#include <mbgl/storage/file_source.hpp>
#include <mbgl/style/style_layer.hpp>
@@ -284,8 +285,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<VectorTileData>(normalized_id, style, info,
- transformState.getAngle(), data.getCollisionDebug());
+ auto tileData = std::make_shared<VectorTileData>(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) {
@@ -332,14 +333,14 @@ std::forward_list<TileID> Source::coveringTiles(const TransformState& state) con
// Map four viewport corners to pixel coordinates
box points = state.cornersToBox(z);
- const vec2<double>& center = points.center;
+ const TileCoordinate center = state.pointToCoordinate({ state.getWidth() / 2.0f, state.getHeight()/ 2.0f }).zoomTo(z);
std::forward_list<TileID> covering_tiles = tileCover(z, points, reparseOverscaled ? actualZ : z);
covering_tiles.sort([&center](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;
@@ -506,7 +507,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();
@@ -529,14 +530,9 @@ void Source::invalidateTiles(const std::unordered_set<TileID, TileID::Hash>& ids
}
void Source::updateTilePtrs() {
- std::vector<Tile*> 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());
}
}
@@ -568,7 +564,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 e78d888415..047ccd5cd0 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 a555ca7ab0..06de585a3c 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);
}
@@ -55,13 +55,12 @@ 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);
- collision->setDebug(collisionDebug);
+void TileWorker::redoPlacement(float angle, float pitch, bool collisionDebug) {
+ collisionTile = std::make_unique<CollisionTile>(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<Bucket> TileWorker::createCircleBucket(const GeometryTileLayer&
std::unique_ptr<Bucket> TileWorker::createSymbolBucket(const GeometryTileLayer& layer,
const StyleBucket& bucket_desc) {
- auto bucket = std::make_unique<SymbolBucket>(*collision, id.overscaling);
+ auto bucket = std::make_unique<SymbolBucket>(id.overscaling, id.z);
const float z = id.z;
auto& layout = bucket->layout;
@@ -283,7 +282,7 @@ std::unique_ptr<Bucket> TileWorker::createSymbolBucket(const GeometryTileLayer&
}
bucket->addFeatures(reinterpret_cast<uintptr_t>(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 15a5487dc9..62527b9fd9 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<util::ptr<StyleLayer>> layers;
@@ -75,7 +75,7 @@ private:
TriangleElementsBuffer triangleElementsBuffer;
LineElementsBuffer lineElementsBuffer;
- std::unique_ptr<CollisionTile> collision;
+ std::unique_ptr<CollisionTile> 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/transform.cpp b/src/mbgl/map/transform.cpp
index ea8775dbcb..7ccc2ad4cc 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 57dc8c4534..5d5a72d6d3 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();
diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp
index 9a5e530920..c672ca5dea 100644
--- a/src/mbgl/map/transform_state.cpp
+++ b/src/mbgl/map/transform_state.cpp
@@ -1,8 +1,9 @@
#include <mbgl/map/transform_state.hpp>
#include <mbgl/map/tile_id.hpp>
-#include <mbgl/util/projection.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/box.hpp>
+#include <mbgl/util/tile_coordinate.hpp>
+#include <mbgl/util/interpolate.hpp>
using namespace mbgl;
@@ -10,52 +11,44 @@ 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 {
- 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<double>(width) / 2.0;
- const double h_2 = static_cast<double>(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;
+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();
- // Calculate the corners of the map view. The resulting coordinates will be
- // in fractional tile coordinates.
- box b;
+ matrix::perspective(projMatrix, 2.0f * std::atan((getHeight() / 2.0f) / getAltitude()),
+ double(getWidth()) / getHeight(), 0.1, farZ);
- 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;
+ matrix::translate(projMatrix, projMatrix, 0, 0, -getAltitude());
- 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;
+ // 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());
- 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;
+ matrix::rotate_x(projMatrix, projMatrix, getPitch());
+ matrix::rotate_z(projMatrix, projMatrix, getAngle());
- 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;
+ matrix::translate(projMatrix, projMatrix, pixel_x() - getWidth() / 2.0f,
+ pixel_y() - getHeight() / 2.0f, 0);
+}
+box TransformState::cornersToBox(uint32_t z) const {
+ double w = width;
+ double h = height;
+ box b(
+ pointToCoordinate({ 0, 0 }).zoomTo(z),
+ pointToCoordinate({ w, 0 }).zoomTo(z),
+ pointToCoordinate({ w, h }).zoomTo(z),
+ pointToCoordinate({ 0, h }).zoomTo(z));
return b;
}
@@ -154,91 +147,134 @@ float TransformState::getAngle() const {
return angle;
}
+float TransformState::getAltitude() const {
+ return altitude;
+}
-#pragma mark - Projection
-
-const vec2<double> TransformState::pixelForLatLng(const LatLng latLng) const {
- LatLng ll = getLatLng();
- double zoom = getZoom();
-
- const double centerX = static_cast<double>(width) / 2.0;
- const double centerY = static_cast<double>(height) / 2.0;
-
- const double m = Projection::getMetersPerPixelAtLatitude(0, zoom);
+float TransformState::getPitch() const {
+ return pitch;
+}
- const double angle_sin = std::sin(-angle);
- const double angle_cos = std::cos(-angle);
+#pragma mark - Projection
- const ProjectedMeters givenMeters = Projection::projectedMetersForLatLng(latLng);
+float TransformState::lngX(float lng) const {
+ return (180.0f + lng) * worldSize() / 360.0f;
+}
- const double givenAbsoluteX = givenMeters.easting / m;
- const double givenAbsoluteY = givenMeters.northing / m;
+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;
+}
- const ProjectedMeters centerMeters = Projection::projectedMetersForLatLng(ll);
+float TransformState::xLng(float x_, float worldSize_) const {
+ return x_ * 360.0f / worldSize_ - 180.0f;
+}
- const double centerAbsoluteX = centerMeters.easting / m;
- const double centerAbsoluteY = centerMeters.northing / m;
+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;
+}
- const double deltaX = givenAbsoluteX - centerAbsoluteX;
- const double deltaY = givenAbsoluteY - centerAbsoluteY;
+float TransformState::zoomScale(float zoom) const {
+ return std::pow(2.0f, zoom);
+}
- const double translatedX = deltaX + centerX;
- const double translatedY = deltaY + centerY;
+float TransformState::worldSize() const {
+ return util::tileSize * scale;
+}
- const double rotatedX = translatedX * angle_cos - translatedY * angle_sin;
- const double rotatedY = translatedX * angle_sin + translatedY * angle_cos;
+vec2<double> TransformState::latLngToPoint(const LatLng& latLng) const {
+ return coordinateToPoint(latLngToCoordinate(latLng));
+}
- const double rotatedCenterX = centerX * angle_cos - centerY * angle_sin;
- const double rotatedCenterY = centerX * angle_sin + centerY * angle_cos;
+LatLng TransformState::pointToLatLng(const vec2<double> point) const {
+ return coordinateToLatLng(pointToCoordinate(point));
+}
- double x_ = rotatedX + (centerX - rotatedCenterX);
- double y_ = rotatedY + (centerY - rotatedCenterY);
+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
+ };
+}
- return vec2<double>(x_, y_);
+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;
}
-const LatLng TransformState::latLngForPixel(const vec2<double> pixel) const {
- LatLng ll = getLatLng();
- double zoom = getZoom();
+vec2<double> 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], height - p[1] / p[3] };
+}
- const double centerX = static_cast<double>(width) / 2.0;
- const double centerY = static_cast<double>(height) / 2.0;
+TileCoordinate TransformState::pointToCoordinate(const vec2<double> point) const {
- const double m = Projection::getMetersPerPixelAtLatitude(0, zoom);
+ float targetZ = 0;
+ const float tileZoom = getIntegerZoom();
- const double angle_sin = std::sin(angle);
- const double angle_cos = std::cos(angle);
+ mat4 mat = coordinatePointMatrix(tileZoom);
- const double unrotatedCenterX = centerX * angle_cos - centerY * angle_sin;
- const double unrotatedCenterY = centerX * angle_sin + centerY * angle_cos;
+ mat4 inverted;
+ bool err = matrix::invert(inverted, mat);
- const double unrotatedX = pixel.x * angle_cos - pixel.y * angle_sin;
- const double unrotatedY = pixel.x * angle_sin + pixel.y * angle_cos;
+ if (err) throw std::runtime_error("failed to invert coordinatePointMatrix");
- const double givenX = unrotatedX + (centerX - unrotatedCenterX);
- const double givenY = unrotatedY + (centerY - unrotatedCenterY);
+ double flippedY = height - point.y;
- const ProjectedMeters centerMeters = Projection::projectedMetersForLatLng(ll);
+ // 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
- const double centerAbsoluteX = centerMeters.easting / m;
- const double centerAbsoluteY = centerMeters.northing / m;
+ matrix::vec4 coord0;
+ matrix::vec4 coord1;
+ 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);
- const double givenAbsoluteX = givenX + centerAbsoluteX - centerX;
- const double givenAbsoluteY = givenY + centerAbsoluteY - centerY;
+ 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;
- 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;
+ float t = z0 == z1 ? 0 : (targetZ - z0) / (z1 - z0);
+
+ return { util::interpolate(x0, x1, t), util::interpolate(y0, y1, t), tileZoom };
+}
- // adjust for world wrap
- while (givenMeters.easting < sw.easting) givenMeters.easting += d;
- while (givenMeters.easting > ne.easting) givenMeters.easting -= d;
+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;
+}
- return Projection::latLngForProjectedMeters(givenMeters);
+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;
}
diff --git a/src/mbgl/map/transform_state.hpp b/src/mbgl/map/transform_state.hpp
index 16f2de2f79..d4b46f04b1 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 <mbgl/util/mat4.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/vec.hpp>
+#include <mbgl/util/mat4.hpp>
+#include <mbgl/util/vec4.hpp>
#include <cstdint>
#include <array>
@@ -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
@@ -28,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<float, 2> locationCoordinate(float lon, float lat) const;
void getLonLat(double &lon, double &lat) const;
@@ -49,13 +49,26 @@ public:
// Rotation
float getAngle() const;
- // Projection
- const vec2<double> pixelForLatLng(const LatLng latLng) const;
- const LatLng latLngForPixel(const vec2<double> pixel) const;
+ float getAltitude() const;
+ float getPitch() const;
// Changing
bool isChanging() const;
+ double pixel_x() const;
+ double pixel_y() const;
+
+ // Conversion and projection
+
+ vec2<double> latLngToPoint(const LatLng& latLng) const;
+ LatLng pointToLatLng(const vec2<double> point) const;
+
+ TileCoordinate latLngToCoordinate(const LatLng& latLng) const;
+ LatLng coordinateToLatLng(const TileCoordinate& coord) const;
+
+ vec2<double> coordinateToPoint(const TileCoordinate& coord) const;
+ TileCoordinate pointToCoordinate(const vec2<double> point) const;
+
private:
void constrain(double& scale, double& y) const;
@@ -63,12 +76,19 @@ 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;
+ 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;
+
private:
// animation state
bool rotating = false;
@@ -80,6 +100,8 @@ private:
double x = 0, y = 0;
double angle = 0;
double scale = 1;
+ double altitude = 1.5;
+ double pitch = 0.0;
// cache values for spherical mercator math
double Bc = (scale * util::tileSize) / 360;
diff --git a/src/mbgl/map/vector_tile_data.cpp b/src/mbgl/map/vector_tile_data.cpp
index c9ee33910b..678a3867ca 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),
@@ -25,9 +26,7 @@ VectorTileData::VectorTileData(const TileID& id_,
style_,
style_.layers,
state,
- std::make_unique<CollisionTile>(id_.z, 4096,
- source_.tile_size * id.overscaling,
- angle, collisionDebug)),
+ std::make_unique<CollisionTile>(angle, pitch, collisionDebug)),
source(source_),
lastAngle(angle),
currentAngle(angle) {
@@ -98,11 +97,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 +112,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 +123,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 e0e8be29bf..4db0cbe004 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<void ()> 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/bucket.hpp b/src/mbgl/renderer/bucket.hpp
index 4bdb766a7c..eb02f32ebc 100644
--- a/src/mbgl/renderer/bucket.hpp
+++ b/src/mbgl/renderer/bucket.hpp
@@ -5,6 +5,8 @@
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/mat4.hpp>
+#include <atomic>
+
#define BUFFER_OFFSET(i) ((char*)nullptr + (i))
namespace mbgl {
@@ -12,9 +14,12 @@ namespace mbgl {
class Painter;
class StyleLayer;
class TileID;
+class CollisionTile;
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;
@@ -29,11 +34,11 @@ public:
return !uploaded;
}
- virtual void placeFeatures() {}
+ virtual void placeFeatures(CollisionTile&) {}
virtual void swapRenderData() {}
protected:
- bool uploaded = false;
+ std::atomic<bool> uploaded;
};
diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp
index b55b71dcb1..e757d682a6 100644
--- a/src/mbgl/renderer/painter.cpp
+++ b/src/mbgl/renderer/painter.cpp
@@ -132,13 +132,11 @@ void Painter::lineWidth(float line_width) {
}
void Painter::changeMatrix() {
- // Initialize projection matrix
- matrix::ortho(projMatrix, 0, state.getWidth(), state.getHeight(), 0, -1, 1);
+
+ state.getProjMatrix(projMatrix);
// 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.
@@ -156,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();
@@ -184,6 +178,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 +199,7 @@ void Painter::render(const Style& style, TransformState state_, const FrameData&
}
}
+
// - CLIPPING MASKS ----------------------------------------------------------------------------
// Draws the clipping masks to the stencil buffer.
{
@@ -225,19 +223,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--; }
@@ -268,12 +266,9 @@ void Painter::render(const Style& style, TransformState state_, const FrameData&
template <class Iterator>
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();
-
MBGL_DEBUG_GROUP(pass == RenderPass::Opaque ? "opaque" : "translucent");
if (debug::renderTree) {
@@ -284,24 +279,16 @@ 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.
- // 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);
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);
}
}
@@ -311,8 +298,8 @@ void Painter::renderPass(RenderPass pass_,
}
}
-void Painter::updateRenderOrder(const Style& style) {
- order.clear();
+std::vector<RenderItem> Painter::determineRenderOrder(const Style& style) {
+ std::vector<RenderItem> order;
for (const auto& layerPtr : style.layers) {
const auto& layer = *layerPtr;
@@ -349,6 +336,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 +358,8 @@ void Painter::updateRenderOrder(const Style& style) {
}
}
}
+
+ return order;
}
void Painter::renderBackground(const StyleLayer &layer_desc) {
@@ -387,7 +385,7 @@ void Painter::renderBackground(const StyleLayer &layer_desc) {
patternShader->u_opacity = properties.opacity;
LatLng latLng = state.getLatLng();
- vec2<double> center = state.pixelForLatLng(latLng);
+ vec2<double> center = state.latLngToPoint(latLng);
float scale = 1 / std::pow(2, zoomFraction);
std::array<float, 2> sizeA = imagePosA.size;
@@ -428,7 +426,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));
}
@@ -457,3 +456,9 @@ mat4 Painter::translatedMatrix(const mat4& matrix, const std::array<float, 2> &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 78cf308b7b..9c0f5db8ca 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<Source*>&);
void drawClippingMask(const mat4& matrix, const ClipID& clip);
@@ -137,17 +134,16 @@ public:
bool needsAnimation() const;
- void updateRenderOrder(const Style& style);
-
private:
void setupShaders();
mat4 translatedMatrix(const mat4& matrix, const std::array<float, 2> &translation, const TileID &id, TranslateAnchorType anchor);
+ std::vector<RenderItem> determineRenderOrder(const Style& style);
+
template <class Iterator>
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,12 +197,13 @@ private:
uint32_t gl_program = 0;
float gl_lineWidth = 0;
std::array<uint16_t, 2> 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<RenderItem> order;
+ int numSublayers = 3;
+ size_t currentLayer;
+ float depthRangeSize;
+ const float depthEpsilon = 1.0f / (1 << 16);
public:
FrameHistory frameHistory;
diff --git a/src/mbgl/renderer/painter_circle.cpp b/src/mbgl/renderer/painter_circle.cpp
index 0c0ac15069..538ba9e6ab 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;
diff --git a/src/mbgl/renderer/painter_fill.cpp b/src/mbgl/renderer/painter_fill.cpp
index 414ec2bbcb..d27feb4693 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<float>(frame.framebufferSize[0]),
static_cast<float>(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<float>(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 f406c0d8f1..258bab6aef 100644
--- a/src/mbgl/renderer/painter_line.cpp
+++ b/src/mbgl/renderer/painter_line.cpp
@@ -11,6 +11,7 @@
#include <mbgl/shader/linepattern_shader.hpp>
#include <mbgl/geometry/sprite_atlas.hpp>
#include <mbgl/geometry/line_atlas.hpp>
+#include <mbgl/util/mat2.hpp>
using namespace mbgl;
@@ -51,9 +52,22 @@ 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 };
+ setDepthSublayer(0);
if (!properties.dash_array.from.empty()) {
@@ -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;
@@ -83,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);
@@ -97,7 +113,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]}};
@@ -108,10 +124,11 @@ 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);
- config.depthRange = { strata + strata_epsilon, 1.0f }; // may or may not matter
bucket.drawLinePatterns(*linepatternShader);
@@ -121,8 +138,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/renderer/painter_raster.cpp b/src/mbgl/renderer/painter_raster.cpp
index 2a8f8e7078..70cbcb4ca5 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 5c2db77096..c6ea372398 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;
-
- if (angleOffset) {
- matrix::rotate_z(exMatrix, exMatrix, angleOffset);
+ bool skewed = aligned_with_map;
+ mat4 exMatrix;
+ float s;
+ float gammaScale;
+
+ 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;
@@ -85,13 +100,13 @@ void Painter::renderSDF(SymbolBucket &bucket,
sdfShader.u_buffer = (haloOffset - styleProperties.halo_width / fontScale) / sdfPx;
- config.depthRange = { strata, 1.0f };
+ setDepthSublayer(0);
(bucket.*drawSDF)(sdfShader);
}
// 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;
@@ -106,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);
}
}
@@ -120,7 +135,6 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c
const auto &properties = layer_desc.getProperties<SymbolProperties>();
const auto &layout = bucket.layout;
- config.depthTest = true;
config.depthMask = GL_FALSE;
if (bucket.hasCollisionBoxData()) {
@@ -133,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);
}
@@ -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);
-
- if (angleOffset) {
- matrix::rotate_z(exMatrix, exMatrix, angleOffset);
+ float s;
+
+ 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);
@@ -199,12 +230,14 @@ 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);
}
}
if (bucket.hasTextData()) {
+ config.depthTest = layout.text.rotation_alignment == RotationAlignmentType::Map;
+
glyphAtlas->bind();
renderSDF(bucket,
diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp
index e8ad132c51..7665fd9a6d 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<Coordinate> &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<std::vector<Coordinate>> &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<SymbolRenderData>();
@@ -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<SymbolRenderData::TextBuffer, TextElementGroup>(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<SymbolRenderData::IconBuffer, IconElementGroup>(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 <typename Buffer, typename GroupType>
-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<float>(zoom + log(symbol.minScale) / log(2)), placementZoom);
float maxZoom = util::min(static_cast<float>(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 = 1.0f;
- 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<float, 4> 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 3a181be55d..c8264bc438 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<std::vector<Coordinate>> &lines,
@@ -97,22 +98,28 @@ private:
bool anchorIsTooClose(const std::u32string &text, const float repeatDistance, Anchor &anchor);
std::map<std::u32string, std::vector<Anchor>> 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 <typename Buffer, typename GroupType>
- 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<SymbolInstance> symbolInstances;
std::vector<SymbolFeature> features;
diff --git a/src/mbgl/shader/icon.vertex.glsl b/src/mbgl/shader/icon.vertex.glsl
index 549570021d..3850e01ab7 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 b6156ae9a0..18b0fce37b 100644
--- a/src/mbgl/shader/icon_shader.hpp
+++ b/src/mbgl/shader/icon_shader.hpp
@@ -21,6 +21,8 @@ public:
Uniform<float> u_fadezoom = {"u_fadezoom", *this};
Uniform<float> u_opacity = {"u_opacity", *this};
Uniform<std::array<float, 2>> u_texsize = {"u_texsize", *this};
+ Uniform<int32_t> u_skewed = {"u_skewed", *this};
+ Uniform<float> u_extra = {"u_extra", *this};
private:
int32_t a_pos = -1;
diff --git a/src/mbgl/shader/line.fragment.glsl b/src/mbgl/shader/line.fragment.glsl
index 717c46e10d..e0ef649965 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 1f5432991c..980212384b 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;
@@ -34,11 +34,22 @@ 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), 0.0, 1.0) + u_exmatrix * dist;
+ 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;
+
+ // 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.90));
+
+ v_gamma_scale = perspective_scale * squish_scale;
}
diff --git a/src/mbgl/shader/line_shader.hpp b/src/mbgl/shader/line_shader.hpp
index 85152d6e0c..0572cac88d 100644
--- a/src/mbgl/shader/line_shader.hpp
+++ b/src/mbgl/shader/line_shader.hpp
@@ -18,6 +18,8 @@ public:
Uniform<std::array<float, 2>> u_linewidth = {"u_linewidth", *this};
Uniform<float> u_ratio = {"u_ratio", *this};
Uniform<float> u_blur = {"u_blur", *this};
+ Uniform<float> 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.fragment.glsl b/src/mbgl/shader/linepattern.fragment.glsl
index 08feff4396..4110a99ead 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 ada384a3d1..541c9fc3a7 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), 0.0, 1.0) + u_exmatrix * vec4(dist, z, 0.0);
- v_linesofar = a_linesofar;// * u_ratio;
+ gl_Position = u_matrix * vec4(floor(a_pos / 2.0) + dist.xy / u_ratio, 0.0, 1.0);
+ v_linesofar = a_linesofar;
+
+ // 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);
- gl_PointSize = 2.0 * u_linewidth.s - 1.0;
+ v_gamma_scale = perspective_scale * squish_scale;
}
diff --git a/src/mbgl/shader/linepattern_shader.hpp b/src/mbgl/shader/linepattern_shader.hpp
index 16d9ff8be7..dce065a0d5 100644
--- a/src/mbgl/shader/linepattern_shader.hpp
+++ b/src/mbgl/shader/linepattern_shader.hpp
@@ -26,6 +26,8 @@ public:
Uniform<float> u_blur = {"u_blur", *this};
Uniform<float> u_fade = {"u_fade", *this};
Uniform<float> u_opacity = {"u_opacity", *this};
+ Uniform<float> 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 5d53dbe883..f8962fa570 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 7f246ced67..03851ed533 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), 0.0, 1.0) + u_exmatrix * dist;
+ 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 16b7f3cb1b..9928d5b304 100644
--- a/src/mbgl/shader/linesdf_shader.hpp
+++ b/src/mbgl/shader/linesdf_shader.hpp
@@ -25,6 +25,8 @@ public:
Uniform<int32_t> u_image = {"u_image", *this};
Uniform<float> u_sdfgamma = {"u_sdfgamma", *this};
Uniform<float> u_mix = {"u_mix", *this};
+ Uniform<float> u_extra = {"u_extra", *this};
+ UniformMatrix<2> u_antialiasingmatrix = {"u_antialiasingmatrix", *this};
private:
int32_t a_pos = -1;
diff --git a/src/mbgl/shader/outline.vertex.glsl b/src/mbgl/shader/outline.vertex.glsl
index 29c16e3ded..f720b8d629 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;
}
diff --git a/src/mbgl/shader/sdf.fragment.glsl b/src/mbgl/shader/sdf.fragment.glsl
index d72d61dab1..a77e959e53 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 192459f9da..5d2e1ce249 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 36dfa30d3e..181788ab16 100644
--- a/src/mbgl/shader/sdf_shader.hpp
+++ b/src/mbgl/shader/sdf_shader.hpp
@@ -23,6 +23,8 @@ public:
Uniform<float> u_minfadezoom = {"u_minfadezoom", *this};
Uniform<float> u_maxfadezoom = {"u_maxfadezoom", *this};
Uniform<float> u_fadezoom = {"u_fadezoom", *this};
+ Uniform<int32_t> u_skewed = {"u_skewed", *this};
+ Uniform<float> u_extra = {"u_extra", *this};
protected:
int32_t a_pos = -1;
diff --git a/src/mbgl/shader/uniform.hpp b/src/mbgl/shader/uniform.hpp
index d2a248c609..55646f7d87 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<double, C*R>& 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/text/collision_tile.cpp b/src/mbgl/text/collision_tile.cpp
index 1c7806a4e0..d18860ccf5 100644
--- a/src/mbgl/text/collision_tile.cpp
+++ b/src/mbgl/text/collision_tile.cpp
@@ -3,17 +3,17 @@
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.
- 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 aed9b59f32..3fd1b0a4c8 100644
--- a/src/mbgl/text/collision_tile.hpp
+++ b/src/mbgl/text/collision_tile.hpp
@@ -35,22 +35,18 @@ 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); }
+ 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;
+ float yStretch;
private:
@@ -58,7 +54,6 @@ class CollisionTile {
Tree tree;
std::array<float, 4> rotationMatrix;
- float yStretch;
bool debug;
};
diff --git a/src/mbgl/text/quads.cpp b/src/mbgl/text/quads.cpp
index 9434396156..19c48d7315 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<float> &anchor_) : anchor(anchor_) {}
- explicit GlyphInstance(const vec2<float> &anchor_, float offset_, float minScale_, float maxScale_,
+ explicit GlyphInstance(const vec2<float> &anchorPoint_) : anchorPoint(anchorPoint_) {}
+ explicit GlyphInstance(const vec2<float> &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<float> anchor;
+ const vec2<float> anchorPoint;
const float offset = 0.0f;
const float minScale = globalMinScale;
const float maxScale = std::numeric_limits<float>::infinity();
@@ -65,19 +65,19 @@ struct GlyphInstance {
typedef std::vector<GlyphInstance> GlyphInstances;
void getSegmentGlyphs(std::back_insert_iterator<GlyphInstances> glyphs, Anchor &anchor,
- float offset, const std::vector<Coordinate> &line, int segment, int8_t direction) {
+ float offset, const std::vector<Coordinate> &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<float> end = line[segment];
- vec2<float> newAnchor = anchor;
+ vec2<float> newAnchorPoint = anchor;
float prevscale = std::numeric_limits<float>::infinity();
offset = std::fabs(offset);
@@ -85,16 +85,16 @@ void getSegmentGlyphs(std::back_insert_iterator<GlyphInstances> glyphs, Anchor &
const float placementScale = anchor.scale;
while (true) {
- const float dist = util::dist<float>(newAnchor, end);
+ const float dist = util::dist<float>(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<float>(upsideDown ? M_PI : 0.0),
/* minScale */ scale,
/* maxScale */ prevscale,
@@ -103,11 +103,11 @@ void getSegmentGlyphs(std::back_insert_iterator<GlyphInstances> 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<GlyphInstances> glyphs, Anchor &
end = line[segment];
}
- vec2<float> normal = util::normal<float>(newAnchor, end) * dist;
- newAnchor = newAnchor - normal;
+ vec2<float> normal = util::normal<float>(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 b47cc718b6..97fdb6a1fc 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<float> &tl_, const vec2<float> &tr_,
const vec2<float> &bl_, const vec2<float> &br_,
- const Rect<uint16_t> &tex_, float angle_, const vec2<float> &anchor_,
+ const Rect<uint16_t> &tex_, float angle_, const vec2<float> &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<float> tl, tr, bl, br;
Rect<uint16_t> tex;
float angle;
- vec2<float> anchor;
+ vec2<float> anchorPoint;
float minScale, maxScale;
};
diff --git a/src/mbgl/util/box.hpp b/src/mbgl/util/box.hpp
index 55a5d46fbc..f03adc2e50 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 <mbgl/util/vec.hpp>
+#include <mbgl/util/tile_coordinate.hpp>
namespace mbgl {
struct box {
- vec2<double> tl, tr, bl, br;
- vec2<double> 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/mat2.cpp b/src/mbgl/util/mat2.cpp
new file mode 100644
index 0000000000..6910244541
--- /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 <mbgl/util/mat2.hpp>
+
+#include <cmath>
+
+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, 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;
+ 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, 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;
+ out[3] = a3 * v1;
+}
diff --git a/src/mbgl/util/mat2.hpp b/src/mbgl/util/mat2.hpp
new file mode 100644
index 0000000000..b5cec821f9
--- /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 <array>
+
+namespace mbgl {
+
+typedef std::array<double, 4> mat2;
+
+namespace matrix {
+
+void identity(mat2& out);
+void rotate(mat2& out, const mat2& a, double rad);
+void scale(mat2& out, const mat2& a, double v0, double v1);
+
+}
+}
+
+#endif
diff --git a/src/mbgl/util/mat3.cpp b/src/mbgl/util/mat3.cpp
index 263768ee41..f4ae8841d5 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 fa40751764..3a6aba5a11 100644
--- a/src/mbgl/util/mat3.hpp
+++ b/src/mbgl/util/mat3.hpp
@@ -27,14 +27,14 @@
namespace mbgl {
-typedef std::array<float, 9> mat3;
+typedef std::array<double, 9> 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 cabd8e2842..123c8464fd 100644
--- a/src/mbgl/util/mat4.cpp
+++ b/src/mbgl/util/mat4.cpp
@@ -45,8 +45,55 @@ 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),
+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),
nf = 1.0f / (near - far);
out[0] = -2.0f * lr;
@@ -67,6 +114,27 @@ void matrix::ortho(mat4& out, float left, float right, float bottom, float top,
out[15] = 1.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;
+ 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];
@@ -86,14 +154,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;
@@ -112,8 +180,42 @@ void matrix::translate(mat4& out, const mat4& a, float x, float y, float z) {
}
}
-void matrix::rotate_z(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],
+ 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, double rad) {
+ double s = std::sin(rad),
c = std::cos(rad),
a00 = a[0],
a01 = a[1],
@@ -146,7 +248,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;
@@ -166,13 +268,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;
diff --git a/src/mbgl/util/tile_coordinate.hpp b/src/mbgl/util/tile_coordinate.hpp
new file mode 100644
index 0000000000..0f5f0dcb8b
--- /dev/null
+++ b/src/mbgl/util/tile_coordinate.hpp
@@ -0,0 +1,29 @@
+#ifndef MBGL_UTIL_TILE_COORDINATE
+#define MBGL_UTIL_TILE_COORDINATE
+
+#include <mbgl/util/vec.hpp>
+
+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 9e444fec12..b7937bf849 100644
--- a/src/mbgl/util/tile_cover.cpp
+++ b/src/mbgl/util/tile_cover.cpp
@@ -1,6 +1,7 @@
#include <mbgl/util/tile_cover.hpp>
#include <mbgl/util/vec.hpp>
#include <mbgl/util/box.hpp>
+#include <mbgl/util/tile_coordinate.hpp>
namespace mbgl {
@@ -78,13 +79,19 @@ std::forward_list<TileID> tileCover(int8_t z, const mbgl::box &bounds, int8_t ac
}
};
+ mbgl::vec2<double> tl = { bounds.tl.column, bounds.tl.row };
+ mbgl::vec2<double> tr = { bounds.tr.column, bounds.tr.row };
+ mbgl::vec2<double> br = { bounds.br.column, bounds.br.row };
+ mbgl::vec2<double> 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;
diff --git a/src/mbgl/util/vec4.cpp b/src/mbgl/util/vec4.cpp
new file mode 100644
index 0000000000..415b15d806
--- /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 <mbgl/util/vec4.hpp>
+
+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 0000000000..c5b4ab1d9e
--- /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 <array>
+#include <mbgl/util/mat4.hpp>
+
+namespace mbgl {
+
+namespace matrix {
+
+typedef std::array<double, 4> vec4;
+
+void transformMat4(vec4& out, vec4& a, mat4& m);
+
+}
+}
+
+#endif
diff --git a/src/mbgl/util/worker.cpp b/src/mbgl/util/worker.cpp
index 516d2f5dba..b238071bc5 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<void ()> callback) {
- worker->redoPlacement(angle, collisionDebug);
+ void redoPlacement(TileWorker* worker, float angle, float pitch, bool collisionDebug, std::function<void ()> callback) {
+ worker->redoPlacement(angle, pitch, collisionDebug);
callback();
}
};
@@ -76,9 +76,9 @@ std::unique_ptr<WorkRequest> Worker::parseLiveTile(TileWorker& worker, const Liv
return threads[current]->invokeWithCallback(&Worker::Impl::parseLiveTile, callback, &worker, &tile);
}
-std::unique_ptr<WorkRequest> Worker::redoPlacement(TileWorker& worker, float angle, bool collisionDebug, std::function<void ()> callback) {
+std::unique_ptr<WorkRequest> Worker::redoPlacement(TileWorker& worker, float angle, float pitch, bool collisionDebug, std::function<void ()> 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 2d78338db2..3ecc402ad2 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<void ()> callback);