diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp index 5b6b27c1854..f9956dbc2a5 100644 --- a/src/mbgl/renderer/render_orchestrator.cpp +++ b/src/mbgl/renderer/render_orchestrator.cpp @@ -361,7 +361,7 @@ std::unique_ptr 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 usedSymbolLayers; if (placementChanged) { placement = std::make_unique( @@ -381,7 +381,7 @@ std::unique_ptr 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 27c4913c63e..22c4a2c2dd5 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(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(now - commitTime) / transitionOptions.duration.value_or(util::DEFAULT_TRANSITION_DURATION); + return std::chrono::duration(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, (placementZoom - zoom) / 1.5); +} + bool Placement::hasTransitions(TimePoint now) const { if (mapMode == MapMode::Continuous && transitionOptions.enablePlacementTransitions) { return stale || std::chrono::duration(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 722a4a0926a..2349fd37853 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 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 @@ class Placement { void updateBucketOpacities(SymbolBucket&, const TransformState&, std::set&); 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 @@ class Placement { TimePoint fadeStartTime; TimePoint commitTime; + float placementZoom; + float prevZoomAdjustment = 0; std::unordered_map placements; std::unordered_map opacities;