summaryrefslogtreecommitdiff
path: root/src/mbgl/text
diff options
context:
space:
mode:
authorChris Loer <chris.loer@gmail.com>2017-05-15 14:17:06 -0700
committerAnsis Brammanis <brammanis@gmail.com>2017-07-10 13:09:32 -0400
commite9b67e9b6f40f5bdebb9d2b590d0ae91e04a116c (patch)
treeaf5666bdedcb2ea04e66e58d198371631f90eb51 /src/mbgl/text
parent7d59e3f8b3a0b83833cd87eb8bfefa7d0856f0a9 (diff)
downloadqtlocation-mapboxgl-e9b67e9b6f40f5bdebb9d2b590d0ae91e04a116c.tar.gz
[core] Improved label pitch-scaling: approximate collision box shapes based on tile distance from camera.
Diffstat (limited to 'src/mbgl/text')
-rw-r--r--src/mbgl/text/collision_tile.cpp50
-rw-r--r--src/mbgl/text/collision_tile.hpp6
-rw-r--r--src/mbgl/text/placement_config.hpp8
3 files changed, 44 insertions, 20 deletions
diff --git a/src/mbgl/text/collision_tile.cpp b/src/mbgl/text/collision_tile.cpp
index 368750c89f..520f66ead8 100644
--- a/src/mbgl/text/collision_tile.cpp
+++ b/src/mbgl/text/collision_tile.cpp
@@ -20,12 +20,17 @@ CollisionTile::CollisionTile(PlacementConfig config_) : config(std::move(config_
rotationMatrix = { { angle_cos, -angle_sin, angle_sin, angle_cos } };
reverseRotationMatrix = { { 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(config.pitch);
-
- // The amount the map is squished depends on the y position.
- // Sort of account for this by making all boxes a bit bigger.
- yStretch = std::pow(_yStretch, 1.3f);
+ perspectiveRatio = 1.0f + 0.5f * ((config.cameraToTileDistance / config.cameraToCenterDistance) - 1.0f);
+ minScale /= perspectiveRatio;
+ maxScale /= perspectiveRatio;
+
+ // We can only approximate here based on the y position of the tile
+ // The shaders calculate a more accurate "incidence_stretch"
+ // at render time to calculate an effective scale for collision
+ // purposes, but we still want to use the yStretch approximation
+ // here because we can't adjust the aspect ratio of the collision
+ // boxes at render time.
+ yStretch = util::max(1.0f, config.cameraToTileDistance / (config.cameraToCenterDistance * std::cos(config.pitch)));
}
@@ -157,13 +162,21 @@ void CollisionTile::insertFeature(CollisionFeature& feature, float minPlacementS
Box CollisionTile::getTreeBox(const Point<float>& anchor, const CollisionBox& box, const float scale) {
assert(box.x1 <= box.x2 && box.y1 <= box.y2);
return Box{
+ // When the 'perspectiveRatio' is high, we're effectively underzooming
+ // the tile because it's in the distance.
+ // In order to detect collisions that only happen while underzoomed,
+ // we have to query a larger portion of the grid.
+ // This extra work is offset by having a lower 'maxScale' bound
+ // Note that this adjustment ONLY affects the bounding boxes
+ // in the grid. It doesn't affect the boxes used for the
+ // minPlacementScale calculations.
CollisionPoint{
- anchor.x + box.x1 / scale,
- anchor.y + box.y1 / scale * yStretch
+ anchor.x + box.x1 / scale * perspectiveRatio,
+ anchor.y + box.y1 / scale * yStretch * perspectiveRatio,
},
CollisionPoint{
- anchor.x + box.x2 / scale,
- anchor.y + box.y2 / scale * yStretch
+ anchor.x + box.x2 / scale * perspectiveRatio,
+ anchor.y + box.y2 / scale * yStretch * perspectiveRatio
}
};
}
@@ -190,8 +203,14 @@ std::vector<IndexedSubfeature> CollisionTile::queryRenderedSymbols(const Geometr
return seenFeatures.find(feature.index) == seenFeatures.end();
};
+ // "perspectiveRatio" is a tile-based approximation of how much larger symbols will
+ // be in the distance. It won't line up exactly with the actually rendered symbols
+ // Being exact would require running the collision detection logic in symbol_sdf.vertex
+ // in the CPU
+ const float perspectiveScale = scale / perspectiveRatio;
+
// Account for the rounding done when updating symbol shader variables.
- const float roundedScale = std::pow(2.0f, std::ceil(util::log2(scale) * 10.0f) / 10.0f);
+ const float roundedScale = std::pow(2.0f, std::ceil(util::log2(perspectiveScale) * 10.0f) / 10.0f);
// Check if feature is rendered (collision free) at current scale.
auto visibleAtScale = [&] (const CollisionTreeBox& treeBox) -> bool {
@@ -203,10 +222,11 @@ std::vector<IndexedSubfeature> CollisionTile::queryRenderedSymbols(const Geometr
auto intersectsAtScale = [&] (const CollisionTreeBox& treeBox) -> bool {
const CollisionBox& collisionBox = std::get<1>(treeBox);
const auto anchor = util::matrixMultiply(rotationMatrix, collisionBox.anchor);
- const int16_t x1 = anchor.x + collisionBox.x1 / scale;
- const int16_t y1 = anchor.y + collisionBox.y1 / scale * yStretch;
- const int16_t x2 = anchor.x + collisionBox.x2 / scale;
- const int16_t y2 = anchor.y + collisionBox.y2 / scale * yStretch;
+
+ const int16_t x1 = anchor.x + (collisionBox.x1 / perspectiveScale);
+ const int16_t y1 = anchor.y + (collisionBox.y1 / perspectiveScale) * yStretch;
+ const int16_t x2 = anchor.x + (collisionBox.x2 / perspectiveScale);
+ const int16_t y2 = anchor.y + (collisionBox.y2 / perspectiveScale) * yStretch;
auto bbox = GeometryCoordinates {
{ x1, y1 }, { x2, y1 }, { x2, y2 }, { x1, y2 }
};
diff --git a/src/mbgl/text/collision_tile.hpp b/src/mbgl/text/collision_tile.hpp
index bdacbb7437..161bc3a688 100644
--- a/src/mbgl/text/collision_tile.hpp
+++ b/src/mbgl/text/collision_tile.hpp
@@ -47,8 +47,8 @@ public:
const PlacementConfig config;
- const float minScale = 0.5f;
- const float maxScale = 2.0f;
+ float minScale = 0.5f;
+ float maxScale = 2.0f;
float yStretch;
std::array<float, 4> rotationMatrix;
@@ -62,6 +62,8 @@ private:
Tree tree;
Tree ignoredTree;
+
+ float perspectiveRatio;
};
} // namespace mbgl
diff --git a/src/mbgl/text/placement_config.hpp b/src/mbgl/text/placement_config.hpp
index 7e61cabc24..c5c013055a 100644
--- a/src/mbgl/text/placement_config.hpp
+++ b/src/mbgl/text/placement_config.hpp
@@ -4,12 +4,12 @@ namespace mbgl {
class PlacementConfig {
public:
- PlacementConfig(float angle_ = 0, float pitch_ = 0, bool debug_ = false)
- : angle(angle_), pitch(pitch_), debug(debug_) {
+ PlacementConfig(float angle_ = 0, float pitch_ = 0, float cameraToCenterDistance_ = 0, float cameraToTileDistance_ = 0, bool debug_ = false)
+ : angle(angle_), pitch(pitch_), cameraToCenterDistance(cameraToCenterDistance_), cameraToTileDistance(cameraToTileDistance_), debug(debug_) {
}
bool operator==(const PlacementConfig& rhs) const {
- return angle == rhs.angle && pitch == rhs.pitch && debug == rhs.debug;
+ return angle == rhs.angle && pitch == rhs.pitch && cameraToCenterDistance == rhs.cameraToCenterDistance && cameraToTileDistance == rhs.cameraToTileDistance && debug == rhs.debug;
}
bool operator!=(const PlacementConfig& rhs) const {
@@ -19,6 +19,8 @@ public:
public:
float angle;
float pitch;
+ float cameraToCenterDistance;
+ float cameraToTileDistance;
bool debug;
};