redo placement when map rotates

This commit is contained in:
Ansis Brammanis
2015-05-20 17:52:00 -04:00
parent 7abd7950c9
commit d41bfa2679
9 changed files with 122 additions and 27 deletions

View File

@@ -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);
}

View File

@@ -101,6 +101,7 @@ public:
bool enabled;
private:
void redoPlacement(const TransformState& transformState);
void emitSourceLoaded();
void emitTileLoaded(bool isNewTile);

View File

@@ -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>

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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);
};
}

View File

@@ -27,6 +27,9 @@ public:
return !uploaded;
}
virtual void placeFeatures() {}
virtual void swapRenderData() {}
protected:
bool uploaded = false;

View File

@@ -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));

View File

@@ -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;
};
}