[core] Switch from background to foreground placement
- Background placement code now just generates static symbol buffers - Don't render GeometryTiles until their symbols are loaded. This is necessary for the CrossTileSymbolIndex to successfully prevent flicker. - SymbolInstances are transferred to SymbolBucket for use on foreground during collision detection - Symbols are sorted on foreground by sorting their index buffer but leaving vertex buffers intact (only works within one segment) - Vertical glyphs are generated at same time as horizontal glyphs. `reprojectLineLabels` chooses which one to use at render time and hides the other. - Icons are now always represented with a single collision box, even if they're placed along a line (this means their rotation alignment may be wrong, but the approach of representing them with multiple collision boxes wasn't very accurate either). - Generate vertices for new debug collision boxes and collision circles - Only add symbols within tile boundaries (reduces work, avoids double-draw) - Update symbol_projection.cpp to support line label projection calls from CollisionIndex.
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
#include <mbgl/style/source_impl.hpp>
|
||||
#include <mbgl/style/transition_options.hpp>
|
||||
#include <mbgl/text/glyph_manager.hpp>
|
||||
#include <mbgl/text/cross_tile_symbol_index.hpp>
|
||||
#include <mbgl/tile/tile.hpp>
|
||||
#include <mbgl/util/math.hpp>
|
||||
#include <mbgl/util/string.hpp>
|
||||
@@ -56,7 +57,9 @@ Renderer::Impl::Impl(RendererBackend& backend_,
|
||||
, imageImpls(makeMutable<std::vector<Immutable<style::Image::Impl>>>())
|
||||
, sourceImpls(makeMutable<std::vector<Immutable<style::Source::Impl>>>())
|
||||
, layerImpls(makeMutable<std::vector<Immutable<style::Layer::Impl>>>())
|
||||
, renderLight(makeMutable<Light::Impl>()) {
|
||||
, renderLight(makeMutable<Light::Impl>())
|
||||
, crossTileSymbolIndex(std::make_unique<CrossTileSymbolIndex>())
|
||||
, placement(std::make_unique<Placement>(TransformState{}, MapMode::Still)) {
|
||||
glyphManager->setObserver(this);
|
||||
}
|
||||
|
||||
@@ -348,26 +351,6 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We're not clipping symbol layers, so when we have both parents and children of symbol
|
||||
// layers, we drop all children in favor of their parent to avoid duplicate labels.
|
||||
// See https://github.com/mapbox/mapbox-gl-native/issues/2482
|
||||
if (symbolLayer) {
|
||||
bool skip = false;
|
||||
// Look back through the buckets we decided to render to find out whether there is
|
||||
// already a bucket from this layer that is a parent of this tile. Tiles are ordered
|
||||
// by zoom level when we obtain them from getTiles().
|
||||
for (auto it = sortedTilesForInsertion.rbegin();
|
||||
it != sortedTilesForInsertion.rend(); ++it) {
|
||||
if (tile.tile.id.isChildOf(it->get().tile.id)) {
|
||||
skip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (skip) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
auto bucket = tile.tile.getBucket(*layer->baseImpl);
|
||||
if (bucket) {
|
||||
sortedTilesForInsertion.emplace_back(tile);
|
||||
@@ -388,6 +371,45 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
|
||||
frameHistory.record(parameters.timePoint,
|
||||
parameters.state.getZoom(),
|
||||
parameters.mapMode == MapMode::Continuous ? util::DEFAULT_TRANSITION_DURATION : Milliseconds(0));
|
||||
bool symbolBucketsChanged = false;
|
||||
if (parameters.mapMode == MapMode::Still) {
|
||||
// TODO: Think about right way for symbol index to handle still rendering
|
||||
crossTileSymbolIndex->reset();
|
||||
}
|
||||
for (auto it = order.rbegin(); it != order.rend(); ++it) {
|
||||
if (it->layer.is<RenderSymbolLayer>()) {
|
||||
if (crossTileSymbolIndex->addLayer(*it->layer.as<RenderSymbolLayer>())) symbolBucketsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool placementChanged = false;
|
||||
if (!placement->stillRecent(parameters.timePoint)) {
|
||||
auto newPlacement = std::make_unique<Placement>(parameters.state, parameters.mapMode);
|
||||
for (auto it = order.rbegin(); it != order.rend(); ++it) {
|
||||
if (it->layer.is<RenderSymbolLayer>()) {
|
||||
newPlacement->placeLayer(*it->layer.as<RenderSymbolLayer>(), parameters.projMatrix, parameters.debugOptions & MapDebugOptions::Collision);
|
||||
}
|
||||
}
|
||||
|
||||
placementChanged = newPlacement->commit(*placement, parameters.timePoint);
|
||||
if (placementChanged || symbolBucketsChanged) {
|
||||
placement = std::move(newPlacement);
|
||||
}
|
||||
|
||||
placement->setRecent(parameters.timePoint);
|
||||
} else {
|
||||
placement->setStale();
|
||||
}
|
||||
|
||||
parameters.symbolFadeChange = placement->symbolFadeChange(parameters.timePoint);
|
||||
|
||||
if (placementChanged || symbolBucketsChanged) {
|
||||
for (auto it = order.rbegin(); it != order.rend(); ++it) {
|
||||
if (it->layer.is<RenderSymbolLayer>()) {
|
||||
placement->updateLayerOpacities(*it->layer.as<RenderSymbolLayer>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// - UPLOAD PASS -------------------------------------------------------------------------------
|
||||
// Uploads all required buffers and images before we do any actual rendering.
|
||||
@@ -607,7 +629,7 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
|
||||
|
||||
observer->onDidFinishRenderingFrame(
|
||||
loaded ? RendererObserver::RenderMode::Full : RendererObserver::RenderMode::Partial,
|
||||
updateParameters.mode == MapMode::Continuous && (hasTransitions() || frameHistory.needsAnimation(util::DEFAULT_TRANSITION_DURATION))
|
||||
updateParameters.mode == MapMode::Continuous && (hasTransitions(parameters.timePoint))
|
||||
);
|
||||
|
||||
if (!loaded) {
|
||||
@@ -647,7 +669,7 @@ std::vector<Feature> Renderer::Impl::queryRenderedFeatures(const ScreenLineStrin
|
||||
std::unordered_map<std::string, std::vector<Feature>> resultsByLayer;
|
||||
for (const auto& sourceID : sourceIDs) {
|
||||
if (RenderSource* renderSource = getRenderSource(sourceID)) {
|
||||
auto sourceResults = renderSource->queryRenderedFeatures(geometry, transformState, layers, options);
|
||||
auto sourceResults = renderSource->queryRenderedFeatures(geometry, transformState, layers, options, placement->getCollisionIndex());
|
||||
std::move(sourceResults.begin(), sourceResults.end(), std::inserter(resultsByLayer, resultsByLayer.begin()));
|
||||
}
|
||||
}
|
||||
@@ -727,7 +749,7 @@ RenderSource* Renderer::Impl::getRenderSource(const std::string& id) const {
|
||||
return it != renderSources.end() ? it->second.get() : nullptr;
|
||||
}
|
||||
|
||||
bool Renderer::Impl::hasTransitions() const {
|
||||
bool Renderer::Impl::hasTransitions(TimePoint timePoint) const {
|
||||
if (renderLight.hasTransition()) {
|
||||
return true;
|
||||
}
|
||||
@@ -738,6 +760,10 @@ bool Renderer::Impl::hasTransitions() const {
|
||||
}
|
||||
}
|
||||
|
||||
if (placement->hasTransitions(timePoint)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user