summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnsis Brammanis <ansis@mapbox.com>2019-08-19 19:32:31 -0400
committerAnsis Brammanis <ansis@mapbox.com>2019-08-19 19:32:31 -0400
commitdc23490981682579b033ca26f7c1b29ca2e7a7eb (patch)
treec87df7f395655a1dc33a82d2f66b28bc2c1488f7
parent71a334152ad0332f93ed4cc0d7af89e2eb689496 (diff)
downloadqtlocation-mapboxgl-upstream/improve-symbol-fade-zoom-out.tar.gz
[core] make symbols fade out faster while zooming outupstream/improve-symbol-fade-zoom-out
Zooming outcan make symbols overlap quickly. The area previously covered by the viewport is covered by a lot of colliding labels while the surrounding area has no labels. This difference produces an unwanted effect. This reduces that effect by: - reducing the fade duration while zooming out - doing placement more frequently while zooming out
-rw-r--r--src/mbgl/renderer/render_orchestrator.cpp4
-rw-r--r--src/mbgl/text/placement.cpp26
-rw-r--r--src/mbgl/text/placement.hpp7
3 files changed, 24 insertions, 13 deletions
diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp
index 5b6b27c185..f9956dbc2a 100644
--- a/src/mbgl/renderer/render_orchestrator.cpp
+++ b/src/mbgl/renderer/render_orchestrator.cpp
@@ -361,7 +361,7 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar
}
bool symbolBucketsChanged = false;
- const bool placementChanged = !placement->stillRecent(updateParameters.timePoint);
+ const bool placementChanged = !placement->stillRecent(updateParameters.timePoint, updateParameters.transformState.getZoom());
std::set<std::string> usedSymbolLayers;
if (placementChanged) {
placement = std::make_unique<Placement>(
@@ -381,7 +381,7 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar
}
if (placementChanged) {
- placement->commit(updateParameters.timePoint);
+ placement->commit(updateParameters.timePoint, updateParameters.transformState.getZoom());
crossTileSymbolIndex.pruneUnusedLayers(usedSymbolLayers);
for (const auto& entry : renderSources) {
entry.second->updateFadingTiles();
diff --git a/src/mbgl/text/placement.cpp b/src/mbgl/text/placement.cpp
index 27c4913c63..ca2c254ff1 100644
--- a/src/mbgl/text/placement.cpp
+++ b/src/mbgl/text/placement.cpp
@@ -62,6 +62,7 @@ Placement::Placement(const TransformState& state_, MapMode mapMode_, style::Tran
: collisionIndex(state_)
, mapMode(mapMode_)
, transitionOptions(std::move(transitionOptions_))
+ , placementZoom(state_.getZoom())
, collisionGroups(crossSourceCollisions)
, prevPlacement(std::move(prevPlacement_))
{
@@ -438,17 +439,15 @@ void Placement::placeBucket(
std::forward_as_tuple(bucket.bucketInstanceId, params.featureIndex, overscaledID));
}
-void Placement::commit(TimePoint now) {
+void Placement::commit(TimePoint now, const double zoom) {
assert(prevPlacement);
commitTime = now;
bool placementChanged = false;
- float increment = mapMode == MapMode::Continuous &&
- transitionOptions.enablePlacementTransitions &&
- transitionOptions.duration.value_or(util::DEFAULT_TRANSITION_DURATION) > Milliseconds(0) ?
- std::chrono::duration<float>(commitTime - prevPlacement->commitTime) / transitionOptions.duration.value_or(util::DEFAULT_TRANSITION_DURATION) :
- 1.0;
+ prevZoomAdjustment = prevPlacement->zoomAdjustment(zoom);
+
+ float increment = prevPlacement->symbolFadeChange(commitTime);
// add the opacities from the current placement, and copy their current values from the previous placement
for (auto& jointPlacement : placements) {
@@ -855,12 +854,20 @@ void Placement::markUsedOrientation(SymbolBucket& bucket, style::TextWritingMode
float Placement::symbolFadeChange(TimePoint now) const {
if (mapMode == MapMode::Continuous && transitionOptions.enablePlacementTransitions &&
transitionOptions.duration.value_or(util::DEFAULT_TRANSITION_DURATION) > Milliseconds(0)) {
- return std::chrono::duration<float>(now - commitTime) / transitionOptions.duration.value_or(util::DEFAULT_TRANSITION_DURATION);
+ return std::chrono::duration<float>(now - commitTime) / transitionOptions.duration.value_or(util::DEFAULT_TRANSITION_DURATION) + prevZoomAdjustment;
} else {
return 1.0;
}
}
+float Placement::zoomAdjustment(const float zoom) const {
+ // When zooming out labels can overlap each other quickly. This
+ // adjustment is used to reduce the fade duration for symbols while zooming out quickly.
+ // It is also used to reduce the interval between placement calculations. Reducing the
+ // interval between placements means collisions are discovered and eliminated sooner.
+ return std::max(0.0, 1.0 - std::pow(2.0, zoom - placementZoom));
+}
+
bool Placement::hasTransitions(TimePoint now) const {
if (mapMode == MapMode::Continuous && transitionOptions.enablePlacementTransitions) {
return stale || std::chrono::duration<float>(now - fadeStartTime) < transitionOptions.duration.value_or(util::DEFAULT_TRANSITION_DURATION);
@@ -869,12 +876,13 @@ bool Placement::hasTransitions(TimePoint now) const {
}
}
-bool Placement::stillRecent(TimePoint now) const {
+bool Placement::stillRecent(TimePoint now, const float zoom) const {
// Even if transitionOptions.duration is set to a value < 300ms, we still wait for this default transition duration
// before attempting another placement operation.
+ const auto fadeDuration = std::max(util::DEFAULT_TRANSITION_DURATION, transitionOptions.duration.value_or(util::DEFAULT_TRANSITION_DURATION));
return mapMode == MapMode::Continuous &&
transitionOptions.enablePlacementTransitions &&
- commitTime + std::max(util::DEFAULT_TRANSITION_DURATION, transitionOptions.duration.value_or(util::DEFAULT_TRANSITION_DURATION)) > now;
+ commitTime + fadeDuration * (1.0 - zoomAdjustment(zoom)) > now;
}
void Placement::setStale() {
diff --git a/src/mbgl/text/placement.hpp b/src/mbgl/text/placement.hpp
index 722a4a0926..2349fd3785 100644
--- a/src/mbgl/text/placement.hpp
+++ b/src/mbgl/text/placement.hpp
@@ -102,14 +102,14 @@ class Placement {
public:
Placement(const TransformState&, MapMode, style::TransitionOptions, const bool crossSourceCollisions, std::unique_ptr<Placement> prevPlacementOrNull = nullptr);
void placeLayer(const RenderLayer&, const mat4&, bool showCollisionBoxes);
- void commit(TimePoint);
+ void commit(TimePoint, const double zoom);
void updateLayerBuckets(const RenderLayer&, const TransformState&, bool updateOpacities);
float symbolFadeChange(TimePoint now) const;
bool hasTransitions(TimePoint now) const;
const CollisionIndex& getCollisionIndex() const;
- bool stillRecent(TimePoint now) const;
+ bool stillRecent(TimePoint now, const float zoom) const;
void setRecent(TimePoint now);
void setStale();
@@ -125,6 +125,7 @@ private:
void updateBucketOpacities(SymbolBucket&, const TransformState&, std::set<uint32_t>&);
void markUsedJustification(SymbolBucket&, style::TextVariableAnchorType, const SymbolInstance&, style::TextWritingModeType orientation);
void markUsedOrientation(SymbolBucket&, style::TextWritingModeType, const SymbolInstance&);
+ float zoomAdjustment(const float zoom) const;
CollisionIndex collisionIndex;
@@ -133,6 +134,8 @@ private:
TimePoint fadeStartTime;
TimePoint commitTime;
+ float placementZoom;
+ float prevZoomAdjustment = 0;
std::unordered_map<uint32_t, JointPlacement> placements;
std::unordered_map<uint32_t, JointOpacityState> opacities;