redo placement when map rotates
This commit is contained in:
@@ -497,6 +497,8 @@ bool Source::update(MapData& data,
|
||||
|
||||
updateTilePtrs();
|
||||
|
||||
redoPlacement(transformState);
|
||||
|
||||
updated = data.getAnimationTime();
|
||||
|
||||
return allTilesUpdated;
|
||||
@@ -518,6 +520,12 @@ void Source::updateTilePtrs() {
|
||||
}
|
||||
}
|
||||
|
||||
void Source::redoPlacement(const TransformState& transformState) {
|
||||
for (auto& tilePtr : tilePtrs) {
|
||||
tilePtr->data->redoPlacement(transformState.getAngle());
|
||||
}
|
||||
}
|
||||
|
||||
void Source::setCacheSize(size_t size) {
|
||||
cache.setSize(size);
|
||||
}
|
||||
|
||||
@@ -101,6 +101,7 @@ public:
|
||||
bool enabled;
|
||||
|
||||
private:
|
||||
void redoPlacement(const TransformState& transformState);
|
||||
void emitSourceLoaded();
|
||||
void emitTileLoaded(bool isNewTile);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <mbgl/map/tile_data.hpp>
|
||||
#include <mbgl/map/environment.hpp>
|
||||
#include <mbgl/map/source.hpp>
|
||||
#include <mbgl/map/transform_state.hpp>
|
||||
|
||||
#include <mbgl/storage/file_source.hpp>
|
||||
#include <mbgl/util/worker.hpp>
|
||||
|
||||
@@ -21,6 +21,7 @@ class StyleLayer;
|
||||
class Request;
|
||||
class Worker;
|
||||
class WorkRequest;
|
||||
class TransformState;
|
||||
|
||||
class TileData : private util::noncopyable {
|
||||
public:
|
||||
@@ -79,6 +80,8 @@ public:
|
||||
virtual void parse() = 0;
|
||||
virtual Bucket* getBucket(StyleLayer const &layer_desc) = 0;
|
||||
|
||||
virtual void redoPlacement(float) {}
|
||||
|
||||
const TileID id;
|
||||
const std::string name;
|
||||
std::atomic_flag parsing = ATOMIC_FLAG_INIT;
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
#include <mbgl/platform/log.hpp>
|
||||
#include <mbgl/text/collision_tile.hpp>
|
||||
#include <mbgl/util/pbf.hpp>
|
||||
#include <mbgl/util/worker.hpp>
|
||||
#include <mbgl/util/work_request.hpp>
|
||||
#include <mbgl/style/style.hpp>
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
@@ -104,6 +107,48 @@ void VectorTileData::setState(const State& state_) {
|
||||
TileData::setState(state_);
|
||||
|
||||
if (isImmutable()) {
|
||||
collision.reset();
|
||||
collision->reset(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void VectorTileData::redoPlacement(float angle) {
|
||||
if (angle != currentAngle) {
|
||||
lastAngle = angle;
|
||||
|
||||
if (getState() != State::parsed || redoingPlacement) {
|
||||
redoWhenDone = true;
|
||||
return;
|
||||
}
|
||||
|
||||
redoingPlacement = true;
|
||||
currentAngle = angle;
|
||||
|
||||
auto callback = std::bind(&VectorTileData::endRedoPlacement, this);
|
||||
workRequest = style.workers.send([this, angle] { workerRedoPlacement(angle); }, callback);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void VectorTileData::workerRedoPlacement(float angle) {
|
||||
collision->reset(angle, 0);
|
||||
for (const auto& layer_desc : style.layers) {
|
||||
auto bucket = getBucket(*layer_desc);
|
||||
if (bucket) {
|
||||
bucket->placeFeatures();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VectorTileData::endRedoPlacement() {
|
||||
for (const auto& layer_desc : style.layers) {
|
||||
auto bucket = getBucket(*layer_desc);
|
||||
if (bucket) {
|
||||
bucket->swapRenderData();
|
||||
}
|
||||
}
|
||||
redoingPlacement = false;
|
||||
if (redoWhenDone) {
|
||||
redoPlacement(lastAngle);
|
||||
redoWhenDone = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ public:
|
||||
~VectorTileData();
|
||||
|
||||
void parse() override;
|
||||
void redoPlacement(float angle) override;
|
||||
virtual Bucket* getBucket(StyleLayer const &layer_desc) override;
|
||||
|
||||
size_t countBuckets() const;
|
||||
@@ -81,6 +82,13 @@ private:
|
||||
mutable std::mutex bucketsMutex;
|
||||
|
||||
std::unique_ptr<CollisionTile> collision;
|
||||
|
||||
float lastAngle = 0;
|
||||
float currentAngle = 0;
|
||||
bool redoingPlacement = false;
|
||||
bool redoWhenDone = false;
|
||||
void endRedoPlacement();
|
||||
void workerRedoPlacement(float angle);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -27,6 +27,9 @@ public:
|
||||
return !uploaded;
|
||||
}
|
||||
|
||||
virtual void placeFeatures() {}
|
||||
virtual void swapRenderData() {}
|
||||
|
||||
protected:
|
||||
bool uploaded = false;
|
||||
|
||||
|
||||
@@ -63,12 +63,12 @@ SymbolBucket::~SymbolBucket() {
|
||||
|
||||
void SymbolBucket::upload() {
|
||||
if (hasTextData()) {
|
||||
text.vertices.upload();
|
||||
text.triangles.upload();
|
||||
renderData->text.vertices.upload();
|
||||
renderData->text.triangles.upload();
|
||||
}
|
||||
if (hasIconData()) {
|
||||
icon.vertices.upload();
|
||||
icon.triangles.upload();
|
||||
renderData->icon.vertices.upload();
|
||||
renderData->icon.triangles.upload();
|
||||
}
|
||||
|
||||
uploaded = true;
|
||||
@@ -83,11 +83,11 @@ void SymbolBucket::render(Painter& painter,
|
||||
|
||||
bool SymbolBucket::hasData() const { return hasTextData() || hasIconData(); }
|
||||
|
||||
bool SymbolBucket::hasTextData() const { return !text.groups.empty(); }
|
||||
bool SymbolBucket::hasTextData() const { return renderData && !renderData->text.groups.empty(); }
|
||||
|
||||
bool SymbolBucket::hasIconData() const { return !icon.groups.empty(); }
|
||||
bool SymbolBucket::hasIconData() const { return renderData && !renderData->icon.groups.empty(); }
|
||||
|
||||
bool SymbolBucket::hasCollisionBoxData() const { return !collisionBox.groups.empty(); }
|
||||
bool SymbolBucket::hasCollisionBoxData() const { return renderData && !renderData->collisionBox.groups.empty(); }
|
||||
|
||||
bool SymbolBucket::needsDependencies(const GeometryTileLayer& layer,
|
||||
const FilterExpression& filter,
|
||||
@@ -263,7 +263,7 @@ void SymbolBucket::addFeatures(uintptr_t tileUID,
|
||||
|
||||
features.clear();
|
||||
|
||||
placeFeatures();
|
||||
placeFeatures(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -317,6 +317,12 @@ void SymbolBucket::addFeature(const std::vector<std::vector<Coordinate>> &lines,
|
||||
}
|
||||
|
||||
void SymbolBucket::placeFeatures() {
|
||||
placeFeatures(false);
|
||||
}
|
||||
|
||||
void SymbolBucket::placeFeatures(bool swapImmediately) {
|
||||
|
||||
renderDataInProgress = util::make_unique<SymbolRenderData>();
|
||||
|
||||
// Calculate which labels can be shown and when they can be shown and
|
||||
// create the bufers used for rendering.
|
||||
@@ -363,7 +369,8 @@ void SymbolBucket::placeFeatures() {
|
||||
collision.insertFeature(symbolInstance.textCollisionFeature, glyphScale);
|
||||
}
|
||||
if (glyphScale < collision.maxScale) {
|
||||
addSymbols<TextBuffer, TextElementGroup>(text, symbolInstance.glyphQuads, glyphScale, layout.text.keep_upright, textAlongLine);
|
||||
addSymbols<SymbolRenderData::TextBuffer, TextElementGroup>(renderDataInProgress->text,
|
||||
symbolInstance.glyphQuads, glyphScale, layout.text.keep_upright, textAlongLine);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,12 +379,15 @@ void SymbolBucket::placeFeatures() {
|
||||
collision.insertFeature(symbolInstance.iconCollisionFeature, iconScale);
|
||||
}
|
||||
if (iconScale < collision.maxScale) {
|
||||
addSymbols<IconBuffer, IconElementGroup>(icon, symbolInstance.iconQuads, iconScale, layout.icon.keep_upright, iconAlongLine);
|
||||
addSymbols<SymbolRenderData::IconBuffer, IconElementGroup>(renderDataInProgress->icon,
|
||||
symbolInstance.iconQuads, iconScale, layout.icon.keep_upright, iconAlongLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addToDebugBuffers();
|
||||
|
||||
if (swapImmediately) swapRenderData();
|
||||
}
|
||||
|
||||
template <typename Buffer, typename GroupType>
|
||||
@@ -448,7 +458,7 @@ void SymbolBucket::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float
|
||||
void SymbolBucket::addToDebugBuffers() {
|
||||
|
||||
const float yStretch = 1.0f;
|
||||
const float angle = 0.0f;
|
||||
const float angle = collision.angle;
|
||||
const float zoom = collision.zoom;
|
||||
float angle_sin = std::sin(-angle);
|
||||
float angle_cos = std::cos(-angle);
|
||||
@@ -475,6 +485,7 @@ void SymbolBucket::addToDebugBuffers() {
|
||||
const float maxZoom = util::max(0.0f, util::min(25.0f, static_cast<float>(zoom + log(box.maxScale) / log(2))));
|
||||
const float placementZoom= util::max(0.0f, util::min(25.0f, static_cast<float>(zoom + log(box.placementScale) / log(2))));
|
||||
|
||||
auto& collisionBox = renderDataInProgress->collisionBox;
|
||||
if (!collisionBox.groups.size()) {
|
||||
// Move to a new group because the old one can't hold the geometry.
|
||||
collisionBox.groups.emplace_back(util::make_unique<CollisionBoxElementGroup>());
|
||||
@@ -496,9 +507,14 @@ void SymbolBucket::addToDebugBuffers() {
|
||||
}
|
||||
}
|
||||
|
||||
void SymbolBucket::swapRenderData() {
|
||||
renderData = std::move(renderDataInProgress);
|
||||
}
|
||||
|
||||
void SymbolBucket::drawGlyphs(SDFShader &shader) {
|
||||
char *vertex_index = BUFFER_OFFSET(0);
|
||||
char *elements_index = BUFFER_OFFSET(0);
|
||||
auto& text = renderData->text;
|
||||
for (auto &group : text.groups) {
|
||||
assert(group);
|
||||
group->array[0].bind(shader, text.vertices, text.triangles, vertex_index);
|
||||
@@ -511,6 +527,7 @@ void SymbolBucket::drawGlyphs(SDFShader &shader) {
|
||||
void SymbolBucket::drawIcons(SDFShader &shader) {
|
||||
char *vertex_index = BUFFER_OFFSET(0);
|
||||
char *elements_index = BUFFER_OFFSET(0);
|
||||
auto& icon = renderData->icon;
|
||||
for (auto &group : icon.groups) {
|
||||
assert(group);
|
||||
group->array[0].bind(shader, icon.vertices, icon.triangles, vertex_index);
|
||||
@@ -523,6 +540,7 @@ void SymbolBucket::drawIcons(SDFShader &shader) {
|
||||
void SymbolBucket::drawIcons(IconShader &shader) {
|
||||
char *vertex_index = BUFFER_OFFSET(0);
|
||||
char *elements_index = BUFFER_OFFSET(0);
|
||||
auto& icon = renderData->icon;
|
||||
for (auto &group : icon.groups) {
|
||||
assert(group);
|
||||
group->array[1].bind(shader, icon.vertices, icon.triangles, vertex_index);
|
||||
@@ -534,6 +552,7 @@ void SymbolBucket::drawIcons(IconShader &shader) {
|
||||
|
||||
void SymbolBucket::drawCollisionBoxes(CollisionBoxShader &shader) {
|
||||
char *vertex_index = BUFFER_OFFSET(0);
|
||||
auto& collisionBox = renderData->collisionBox;
|
||||
for (auto &group : collisionBox.groups) {
|
||||
group->array[0].bind(shader, collisionBox.vertices, vertex_index);
|
||||
MBGL_CHECK_ERROR(glDrawArrays(GL_LINES, 0, group->vertex_length));
|
||||
|
||||
@@ -87,15 +87,18 @@ public:
|
||||
const FilterExpression&,
|
||||
GlyphStore&,
|
||||
Sprite&);
|
||||
void placeFeatures();
|
||||
|
||||
private:
|
||||
void addFeature(const std::vector<std::vector<Coordinate>> &lines,
|
||||
const Shaping &shapedText, const PositionedIcon &shapedIcon,
|
||||
const GlyphPositions &face);
|
||||
|
||||
void placeFeatures();
|
||||
void addToDebugBuffers();
|
||||
|
||||
void placeFeatures(bool swapImmediately);
|
||||
void swapRenderData();
|
||||
|
||||
// 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);
|
||||
@@ -109,23 +112,27 @@ private:
|
||||
std::vector<SymbolInstance> symbolInstances;
|
||||
std::vector<SymbolFeature> features;
|
||||
|
||||
struct TextBuffer {
|
||||
TextVertexBuffer vertices;
|
||||
TriangleElementsBuffer triangles;
|
||||
std::vector<std::unique_ptr<TextElementGroup>> groups;
|
||||
} text;
|
||||
struct SymbolRenderData {
|
||||
struct TextBuffer {
|
||||
TextVertexBuffer vertices;
|
||||
TriangleElementsBuffer triangles;
|
||||
std::vector<std::unique_ptr<TextElementGroup>> groups;
|
||||
} text;
|
||||
|
||||
struct IconBuffer {
|
||||
IconVertexBuffer vertices;
|
||||
TriangleElementsBuffer triangles;
|
||||
std::vector<std::unique_ptr<IconElementGroup>> groups;
|
||||
} icon;
|
||||
struct IconBuffer {
|
||||
IconVertexBuffer vertices;
|
||||
TriangleElementsBuffer triangles;
|
||||
std::vector<std::unique_ptr<IconElementGroup>> groups;
|
||||
} icon;
|
||||
|
||||
struct CollisionBoxBuffer {
|
||||
CollisionBoxVertexBuffer vertices;
|
||||
std::vector<std::unique_ptr<CollisionBoxElementGroup>> groups;
|
||||
} collisionBox;
|
||||
struct CollisionBoxBuffer {
|
||||
CollisionBoxVertexBuffer vertices;
|
||||
std::vector<std::unique_ptr<CollisionBoxElementGroup>> groups;
|
||||
} collisionBox;
|
||||
};
|
||||
|
||||
std::unique_ptr<SymbolRenderData> renderData;
|
||||
std::unique_ptr<SymbolRenderData> renderDataInProgress;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user