aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnsis Brammanis <brammanis@gmail.com>2017-06-20 12:38:02 -0400
committerAnsis Brammanis <brammanis@gmail.com>2017-06-20 12:38:02 -0400
commita200c8be04e6ea13f14a7d74dce1a66d9eea1506 (patch)
tree08be8ee7084882fbb4e0b53a608f8a27e1837c87
parent6f299f514d4f8db9cb9e5d145d1776cc5b3023fd (diff)
progress
-rw-r--r--src/mbgl/layout/symbol_layout.cpp4
-rw-r--r--src/mbgl/layout/symbol_projection.cpp162
-rw-r--r--src/mbgl/layout/symbol_projection.hpp3
-rw-r--r--src/mbgl/renderer/buckets/symbol_bucket.hpp20
-rw-r--r--src/mbgl/renderer/layers/render_symbol_layer.cpp2
-rw-r--r--src/mbgl/renderer/layers/render_symbol_layer.hpp1
-rw-r--r--src/mbgl/renderer/painters/painter_symbol.cpp11
7 files changed, 195 insertions, 8 deletions
diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp
index b0430de92..c59f1040a 100644
--- a/src/mbgl/layout/symbol_layout.cpp
+++ b/src/mbgl/layout/symbol_layout.cpp
@@ -505,6 +505,8 @@ std::unique_ptr<SymbolBucket> SymbolLayout::place(CollisionTile& collisionTile)
bucket->text, *bucket->textSizeBinder, symbol, feature, placementZoom,
keepUpright, textPlacement, collisionTile.config.angle, symbolInstance.writingModes, symbolInstance.point);
}
+ PlacedSymbol placedSymbol(symbolInstance.point, 0, 0, 0, 0, 0, placementZoom, false);
+ bucket->text.placedSymbols.emplace_back(std::move(placedSymbol));
}
}
@@ -515,6 +517,8 @@ std::unique_ptr<SymbolBucket> SymbolLayout::place(CollisionTile& collisionTile)
addSymbol(
bucket->icon, *bucket->iconSizeBinder, *symbolInstance.iconQuad, feature, placementZoom,
keepUpright, iconPlacement, collisionTile.config.angle, symbolInstance.writingModes, symbolInstance.point);
+ PlacedSymbol placedSymbol(symbolInstance.point, 0, 0, 0, 0, 0, placementZoom, false);
+ bucket->icon.placedSymbols.emplace_back(std::move(placedSymbol));
}
}
diff --git a/src/mbgl/layout/symbol_projection.cpp b/src/mbgl/layout/symbol_projection.cpp
index 6efe218ba..b740688e3 100644
--- a/src/mbgl/layout/symbol_projection.cpp
+++ b/src/mbgl/layout/symbol_projection.cpp
@@ -1,9 +1,10 @@
#include <mbgl/layout/symbol_projection.hpp>
-
#include <mbgl/map/transform_state.hpp>
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/renderer/buckets/symbol_bucket.hpp>
#include <mbgl/renderer/layers/render_symbol_layer.hpp>
+#include <mbgl/util/optional.hpp>
+#include <mbgl/util/math.hpp>
namespace mbgl {
@@ -40,11 +41,164 @@ namespace mbgl {
return m;
}
- void reprojectLineLabels(SymbolBucket& bucket, const mat4& posMatrix, const bool isText, const style::SymbolPropertyValues& values, const RenderTile& tile) {
+
+ Point<float> project(const Point<float>& point, const mat4& matrix) {
+ vec4 pos = {{ point.x, point.y, 0, 1 }};
+ matrix::transformMat4(pos, pos, matrix);
+ return { static_cast<float>(pos[0] / pos[3]), static_cast<float>(pos[1] / pos[3]) };
+ }
+
+ bool isVisible(const vec4& anchorPos, const float, const std::array<double, 2>& clippingBuffer) {
+ const float x = anchorPos[0] / anchorPos[3];
+ const float y = anchorPos[1] / anchorPos[3];
+ const bool inPaddedViewport = (
+ x >= -clippingBuffer[0] &&
+ x <= clippingBuffer[0] &&
+ y >= -clippingBuffer[1] &&
+ y <= clippingBuffer[1]);
+ // TODO do framehistory check here as well
+ return inPaddedViewport;
+ }
+
+ void addDynamicAttributes(const Point<float>&, const float, const float) {
+ }
+
+ void hideGlyphs(size_t) {
+ }
+
+ struct PlacedGlyph {
+ PlacedGlyph(Point<float> point_, float angle_) : point(point_), angle(angle_) {}
+ Point<float> point;
+ float angle;
+ };
+
+ optional<PlacedGlyph> placeGlyphAlongLine(const float offsetX, const float lineOffsetX, const float lineOffsetY, const bool flip,
+ Point<float> anchorPoint, const uint16_t anchorSegment, const std::vector<Point<float>>& line, const mat4& labelPlaneMatrix) {
+
+ const float combinedOffsetX = flip ?
+ offsetX - lineOffsetX :
+ offsetX + lineOffsetX;
+
+ int16_t dir = combinedOffsetX > 0 ? 1 : -1;
+
+ float angle = 0.0;
+ if (flip) {
+ // The label needs to be flipped to keep text upright.
+ // Iterate in the reverse direction.
+ dir *= -1;
+ angle = M_PI;
+ }
+
+ if (dir < 0) angle += M_PI;
+
+ int32_t currentIndex = dir > 0 ? anchorSegment : anchorSegment + 1;
+
+ Point<float>& current = anchorPoint;
+ Point<float>& prev = anchorPoint;
+ float distanceToPrev = 0.0;
+ float currentSegmentDistance = 0.0;
+ const float absOffsetX = std::abs(combinedOffsetX);
+
+ while (distanceToPrev + currentSegmentDistance <= absOffsetX) {
+ currentIndex += dir;
+
+ // offset does not fit on the projected line
+ if (currentIndex < 0 || currentIndex >= static_cast<int32_t>(line.size())) return {};
+
+ prev = current;
+ current = project(line.at(currentIndex), labelPlaneMatrix);
+
+ distanceToPrev += currentSegmentDistance;
+ currentSegmentDistance = util::dist<float>(prev, current);
+ }
+
+ // The point is on the current segment. Interpolate to find it.
+ const float segmentInterpolationT = (absOffsetX - distanceToPrev) / currentSegmentDistance;
+ const Point<float> prevToCurrent = current - prev;
+ Point<float> p = (prevToCurrent * segmentInterpolationT) + prev;
+
+ // offset the point from the line to text-offset and icon-offset
+ p += util::perp(prevToCurrent) * static_cast<float>(lineOffsetY * dir / util::mag(prevToCurrent));
+
+ const float segmentAngle = angle + std::atan2(current.y - prev.y, current.x - prev.x);
+
+ return {{ p, segmentAngle }};
+ }
+
+ void placeGlyphsAlongLine(const PlacedSymbol& symbol, const float fontSize, const bool flip, const mat4& labelPlaneMatrix) {
+ const float fontScale = fontSize / 24.0;
+ const float lineOffsetX = symbol.lineOffsetX * fontSize;
+ const float lineOffsetY = symbol.lineOffsetY * fontSize;
+
+ const Point<float> anchorPoint = project(symbol.anchorPoint, labelPlaneMatrix);
+
+ std::vector<PlacedGlyph> placedGlyphs;
+ for (auto glyphOffsetX : symbol.glyphOffsets) {
+ auto placedGlyph = placeGlyphAlongLine(glyphOffsetX * fontScale, lineOffsetX, lineOffsetY, flip, anchorPoint, symbol.segment, symbol.line, labelPlaneMatrix);
+ if (placedGlyph) {
+ placedGlyphs.push_back(*placedGlyph);
+ } else {
+ hideGlyphs(symbol.glyphOffsets.size());
+ return;
+ }
+ }
+
+ for (auto& placedGlyph : placedGlyphs) {
+ addDynamicAttributes(placedGlyph.point, placedGlyph.angle, symbol.placementZoom);
+ }
+ }
+
+ void reprojectLineLabels(SymbolBucket& bucket, const mat4& posMatrix, const bool isText, const style::SymbolPropertyValues& values,
+ //const RenderTile& tile, const TransformState& state) {
+ const RenderTile&, const TransformState& state) {
// const sizeData = isText ? bucket.textSizeData : bucket.iconSizeData;
// const partiallyEvaluatedSize = symbolSize.evaluateSizeForZoom(sizeData, painter.transform, layer, isText);
- const std::array<float, 2> clippingBuffer(256.0 / state.getSize().width * 2.0 + 1.0, 256.0 / state.getHeight());
- const clippingBuffer = [256 / painter.width * 2 + 1, 256 / painter.height * 2 + 1];
+ const std::array<double, 2> clippingBuffer = {{ 256.0 / state.getSize().width * 2.0 + 1.0, 256.0 / state.getSize().height }};
+
+ //TODO
+ const float pixelsToTileUnits = 1.0;
+ const mat4 labelPlaneMatrix = getLabelPlaneMatrix(posMatrix, values.pitchAlignment == style::AlignmentType::Map,
+ values.rotationAlignment == style::AlignmentType::Map, state, pixelsToTileUnits);
+
+ //
+ // const dynamicLayoutVertexArray = isText ?
+ // bucket.buffers.glyph.dynamicLayoutVertexArray :
+ // bucket.buffers.icon.dynamicLayoutVertexArray;
+ // dynamicLayoutVertexArray.clear();
+
+ const std::vector<PlacedSymbol>& placedSymbols = isText ? bucket.text.placedSymbols : bucket.icon.placedSymbols;
+ for (auto& placedSymbol : placedSymbols) {
+ vec4 anchorPos = {{ placedSymbol.anchorPoint.x, placedSymbol.anchorPoint.y, 0, 1 }};
+ matrix::transformMat4(anchorPos, anchorPos, posMatrix);
+
+ // Don't bother calculating the correct point for invisible labels.
+ if (!isVisible(anchorPos, placedSymbol.placementZoom, clippingBuffer)) {
+ hideGlyphs(placedSymbol.glyphOffsets.size());
+ continue;
+ }
+
+ bool flip = false;
+ if (values.keepUpright) {
+ if (false) {
+ const Point<float> a = project(placedSymbol.line.at(placedSymbol.segment), posMatrix);
+ const Point<float> b = project(placedSymbol.line.at(placedSymbol.segment + 1), posMatrix);
+ flip = placedSymbol.vertical ? b.y > a.y : b.x < a.x;
+ }
+ }
+
+ const float cameraToAnchorDistance = anchorPos[3];
+ const float perspectiveRatio = 1 + 0.5 * ((cameraToAnchorDistance / state.getCameraToCenterDistance()) - 1.0);
+
+
+ //const fontSize = symbolSize.evaluateSizeForFeature(sizeData, partiallyEvaluatedSize, symbol);
+ const float fontSize = 16;
+ const float pitchScaledFontSize = values.pitchAlignment == style::AlignmentType::Map ?
+ fontSize * perspectiveRatio :
+ fontSize / perspectiveRatio;
+
+ //placeGlyphsAlongLine(symbol, pitchScaledFontSize, flip, labelPlaneMatrix, bucket.glyphOffsetArray, lineVertexArray, dynamicLayoutVertexArray);
+ placeGlyphsAlongLine(placedSymbol, pitchScaledFontSize, flip, labelPlaneMatrix);
+ }
}
} // end namespace mbgl
diff --git a/src/mbgl/layout/symbol_projection.hpp b/src/mbgl/layout/symbol_projection.hpp
index e26b1f4e2..21bd1c78a 100644
--- a/src/mbgl/layout/symbol_projection.hpp
+++ b/src/mbgl/layout/symbol_projection.hpp
@@ -14,6 +14,7 @@ namespace mbgl {
mat4 getLabelPlaneMatrix(const mat4& posMatrix, const bool pitchWithMap, const bool rotateWithMap, const TransformState& state, const float pixelsToTileUnits);
mat4 getGlCoordMatrix(const mat4& posMatrix, const bool pitchWithMap, const bool rotateWithMap, const TransformState& state, const float pixelsToTileUnits);
- void reprojectLineLabels(SymbolBucket& bucket, const mat4& posMatrix, const bool isText, const style::SymbolPropertyValues& values, const RenderTile& tile);
+ void reprojectLineLabels(SymbolBucket&, const mat4& posMatrix, const bool isText, const style::SymbolPropertyValues&,
+ const RenderTile&, const TransformState&);
} // end namespace mbgl
diff --git a/src/mbgl/renderer/buckets/symbol_bucket.hpp b/src/mbgl/renderer/buckets/symbol_bucket.hpp
index 6a9382c3f..1534dbcf8 100644
--- a/src/mbgl/renderer/buckets/symbol_bucket.hpp
+++ b/src/mbgl/renderer/buckets/symbol_bucket.hpp
@@ -15,6 +15,24 @@
namespace mbgl {
+class PlacedSymbol {
+public:
+ PlacedSymbol(Point<float> anchorPoint_, uint16_t segment_, float lowerSize_, float upperSize_,
+ float lineOffsetX_, float lineOffsetY_, float placementZoom_, bool vertical_) :
+ anchorPoint(anchorPoint_), segment(segment_), lowerSize(lowerSize_), upperSize(upperSize_),
+ lineOffsetX(lineOffsetX_), lineOffsetY(lineOffsetY_), placementZoom(placementZoom_), vertical(vertical_) {}
+ Point<float> anchorPoint;
+ uint16_t segment;
+ float lowerSize;
+ float upperSize;
+ float lineOffsetX;
+ float lineOffsetY;
+ float placementZoom;
+ bool vertical;
+ std::vector<float> glyphOffsets;
+ std::vector<Point<float>> line;
+};
+
class SymbolBucket : public Bucket {
public:
SymbolBucket(style::SymbolLayoutProperties::PossiblyEvaluated,
@@ -47,6 +65,7 @@ public:
gl::VertexVector<SymbolDynamicLayoutAttributes::Vertex> dynamicVertices;
gl::IndexVector<gl::Triangles> triangles;
gl::SegmentVector<SymbolTextAttributes> segments;
+ std::vector<PlacedSymbol> placedSymbols;
optional<gl::VertexBuffer<SymbolLayoutVertex>> vertexBuffer;
optional<gl::VertexBuffer<SymbolDynamicLayoutAttributes::Vertex>> dynamicVertexBuffer;
@@ -60,6 +79,7 @@ public:
gl::VertexVector<SymbolDynamicLayoutAttributes::Vertex> dynamicVertices;
gl::IndexVector<gl::Triangles> triangles;
gl::SegmentVector<SymbolIconAttributes> segments;
+ std::vector<PlacedSymbol> placedSymbols;
PremultipliedImage atlasImage;
optional<gl::VertexBuffer<SymbolLayoutVertex>> vertexBuffer;
diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp
index a2c253bf4..67649f443 100644
--- a/src/mbgl/renderer/layers/render_symbol_layer.cpp
+++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp
@@ -83,6 +83,7 @@ style::SymbolPropertyValues RenderSymbolLayer::iconPropertyValues(const style::S
return style::SymbolPropertyValues {
layout_.get<style::IconRotationAlignment>(), // icon-pitch-alignment is not yet implemented; inherit the rotation alignment
layout_.get<style::IconRotationAlignment>(),
+ layout_.get<style::IconKeepUpright>(),
evaluated.get<style::IconTranslate>(),
evaluated.get<style::IconTranslateAnchor>(),
evaluated.get<style::IconHaloColor>().constantOr(Color::black()).a > 0 &&
@@ -108,6 +109,7 @@ style::SymbolPropertyValues RenderSymbolLayer::textPropertyValues(const style::S
return style::SymbolPropertyValues {
layout_.get<style::TextPitchAlignment>(),
layout_.get<style::TextRotationAlignment>(),
+ layout_.get<style::TextKeepUpright>(),
evaluated.get<style::TextTranslate>(),
evaluated.get<style::TextTranslateAnchor>(),
evaluated.get<style::TextHaloColor>().constantOr(Color::black()).a > 0 &&
diff --git a/src/mbgl/renderer/layers/render_symbol_layer.hpp b/src/mbgl/renderer/layers/render_symbol_layer.hpp
index 6f9f058a9..efdf5ba44 100644
--- a/src/mbgl/renderer/layers/render_symbol_layer.hpp
+++ b/src/mbgl/renderer/layers/render_symbol_layer.hpp
@@ -40,6 +40,7 @@ public:
// Layout
AlignmentType pitchAlignment;
AlignmentType rotationAlignment;
+ bool keepUpright;
// Paint
std::array<float, 2> translate;
diff --git a/src/mbgl/renderer/painters/painter_symbol.cpp b/src/mbgl/renderer/painters/painter_symbol.cpp
index b52ce3a8d..04ca195ff 100644
--- a/src/mbgl/renderer/painters/painter_symbol.cpp
+++ b/src/mbgl/renderer/painters/painter_symbol.cpp
@@ -10,6 +10,7 @@
#include <mbgl/programs/collision_box_program.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/layout/symbol_projection.hpp>
#include <cmath>
@@ -65,15 +66,16 @@ void Painter::renderSymbol(PaintParameters& parameters,
assert(dynamic_cast<GeometryTile*>(&tile.tile));
GeometryTile& geometryTile = static_cast<GeometryTile&>(tile.tile);
- const alongLine = bucket.layout.get<SymbolPlacement>() == SymbolPlacementType::Line &&
- bucket.layout.get<RotationAlignment>() == AlignmentType::Map;
if (bucket.hasIconData()) {
auto values = layer.iconPropertyValues(layout);
auto paintPropertyValues = layer.iconPaintProperties();
+ const bool alongLine = bucket.layout.get<SymbolPlacement>() == SymbolPlacementType::Line &&
+ bucket.layout.get<IconRotationAlignment>() == AlignmentType::Map;
+
if (alongLine) {
- reprojectLineLabels(bucket, tile.matrix, false, values, tile);
+ reprojectLineLabels(bucket, tile.matrix, false, values, tile, state);
}
const bool iconScaled = layout.get<IconSize>().constantOr(1.0) != 1.0 || bucket.iconsNeedLinear;
@@ -122,6 +124,9 @@ void Painter::renderSymbol(PaintParameters& parameters,
auto values = layer.textPropertyValues(layout);
auto paintPropertyValues = layer.textPaintProperties();
+ const bool alongLine = bucket.layout.get<SymbolPlacement>() == SymbolPlacementType::Line &&
+ bucket.layout.get<TextRotationAlignment>() == AlignmentType::Map;
+
const Size texsize = geometryTile.glyphAtlasTexture->size;
if (values.hasHalo) {