diff options
Diffstat (limited to 'src/mbgl/renderer/line_bucket.cpp')
-rw-r--r-- | src/mbgl/renderer/line_bucket.cpp | 70 |
1 files changed, 55 insertions, 15 deletions
diff --git a/src/mbgl/renderer/line_bucket.cpp b/src/mbgl/renderer/line_bucket.cpp index 83c5b43776..ba50e6b1f0 100644 --- a/src/mbgl/renderer/line_bucket.cpp +++ b/src/mbgl/renderer/line_bucket.cpp @@ -6,13 +6,14 @@ #include <mbgl/shader/linesdf_shader.hpp> #include <mbgl/shader/linepattern_shader.hpp> #include <mbgl/util/math.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/util/constants.hpp> +#include <mbgl/gl/gl.hpp> #include <cassert> using namespace mbgl; -LineBucket::LineBucket() { +LineBucket::LineBucket(float overscaling_) : overscaling(overscaling_) { } LineBucket::~LineBucket() { @@ -25,6 +26,21 @@ void LineBucket::addGeometry(const GeometryCollection& geometryCollection) { } } + +/* + * Sharp corners cause dashed lines to tilt because the distance along the line + * is the same at both the inner and outer corners. To improve the appearance of + * dashed lines we add extra points near sharp corners so that a smaller part + * of the line is tilted. + * + * COS_HALF_SHARP_CORNER controls how sharp a corner has to be for us to add an + * extra vertex. The default is 75 degrees. + * + * The newly created vertices are placed SHARP_CORNER_OFFSET pixels from the corner. + */ +const float COS_HALF_SHARP_CORNER = std::cos(75.0 / 2.0 * (M_PI / 180.0)); +const float SHARP_CORNER_OFFSET = 15.0f; + void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) { const GLsizei len = [&vertices] { GLsizei l = static_cast<GLsizei>(vertices.size()); @@ -42,6 +58,8 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) { const float miterLimit = layout.join == JoinType::Bevel ? 1.05f : float(layout.miterLimit); + const double sharpCornerOffset = SHARP_CORNER_OFFSET * (util::EXTENT / (512.0 * overscaling)); + const Coordinate firstVertex = vertices.front(); const Coordinate lastVertex = vertices[len - 1]; const bool closed = firstVertex == lastVertex; @@ -98,10 +116,6 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) { currentVertex = vertices[i]; - // Calculate how far along the line the currentVertex is - if (prevVertex) - distance += util::dist<double>(currentVertex, prevVertex); - // Calculate the normal towards the next vertex in this line. In case // there is no next vertex, pretend that the line is continuing straight, // meaning that we are just using the previous normal. @@ -134,6 +148,18 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) { const float cosHalfAngle = joinNormal.x * nextNormal.x + joinNormal.y * nextNormal.y; const float miterLength = cosHalfAngle != 0 ? 1 / cosHalfAngle: 1; + const bool isSharpCorner = cosHalfAngle < COS_HALF_SHARP_CORNER && prevVertex && nextVertex; + + if (isSharpCorner && i > 0) { + const double prevSegmentLength = util::dist<double>(currentVertex, prevVertex); + if (prevSegmentLength > 2.0 * sharpCornerOffset) { + Coordinate newPrevVertex = currentVertex - (util::round(vec2<double>(currentVertex - prevVertex) * (sharpCornerOffset / prevSegmentLength))); + distance += util::dist<double>(newPrevVertex, prevVertex); + addCurrentVertex(newPrevVertex, flip, distance, prevNormal, 0, 0, false, startVertex, triangleStore); + prevVertex = newPrevVertex; + } + } + // The join if a middle vertex, otherwise the cap const bool middleVertex = prevVertex && nextVertex; JoinType currentJoin = layout.join; @@ -167,6 +193,10 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) { } } + // Calculate how far along the line the currentVertex is + if (prevVertex) + distance += util::dist<double>(currentVertex, prevVertex); + if (middleVertex && currentJoin == JoinType::Miter) { joinNormal = joinNormal * miterLength; addCurrentVertex(currentVertex, flip, distance, joinNormal, 0, 0, false, startVertex, @@ -295,6 +325,16 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) { } } + if (isSharpCorner && i < len - 1) { + const double nextSegmentLength = util::dist<double>(currentVertex, nextVertex); + if (nextSegmentLength > 2 * sharpCornerOffset) { + Coordinate newCurrentVertex = currentVertex + util::round(vec2<double>(nextVertex - currentVertex) * (sharpCornerOffset / nextSegmentLength)); + distance += util::dist<double>(newCurrentVertex, currentVertex); + addCurrentVertex(newCurrentVertex, flip, distance, nextNormal, 0, 0, false, startVertex, triangleStore); + currentVertex = newCurrentVertex; + } + } + startOfLine = false; } @@ -378,9 +418,9 @@ void LineBucket::addPieSliceVertex(const Coordinate& currentVertex, } } -void LineBucket::upload() { - vertexBuffer.upload(); - triangleElementsBuffer.upload(); +void LineBucket::upload(gl::GLObjectStore& glObjectStore) { + vertexBuffer.upload(glObjectStore); + triangleElementsBuffer.upload(glObjectStore); // From now on, we're only going to render during the translucent pass. uploaded = true; @@ -397,7 +437,7 @@ bool LineBucket::hasData() const { return !triangleGroups.empty(); } -void LineBucket::drawLines(LineShader& shader) { +void LineBucket::drawLines(LineShader& shader, gl::GLObjectStore& glObjectStore) { GLbyte* vertex_index = BUFFER_OFFSET(0); GLbyte* elements_index = BUFFER_OFFSET(0); for (auto& group : triangleGroups) { @@ -405,7 +445,7 @@ void LineBucket::drawLines(LineShader& shader) { if (!group->elements_length) { continue; } - group->array[0].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index); + group->array[0].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, glObjectStore); MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT, elements_index)); vertex_index += group->vertex_length * vertexBuffer.itemSize; @@ -413,7 +453,7 @@ void LineBucket::drawLines(LineShader& shader) { } } -void LineBucket::drawLineSDF(LineSDFShader& shader) { +void LineBucket::drawLineSDF(LineSDFShader& shader, gl::GLObjectStore& glObjectStore) { GLbyte* vertex_index = BUFFER_OFFSET(0); GLbyte* elements_index = BUFFER_OFFSET(0); for (auto& group : triangleGroups) { @@ -421,7 +461,7 @@ void LineBucket::drawLineSDF(LineSDFShader& shader) { if (!group->elements_length) { continue; } - group->array[2].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index); + group->array[2].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, glObjectStore); MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT, elements_index)); vertex_index += group->vertex_length * vertexBuffer.itemSize; @@ -429,7 +469,7 @@ void LineBucket::drawLineSDF(LineSDFShader& shader) { } } -void LineBucket::drawLinePatterns(LinepatternShader& shader) { +void LineBucket::drawLinePatterns(LinepatternShader& shader, gl::GLObjectStore& glObjectStore) { GLbyte* vertex_index = BUFFER_OFFSET(0); GLbyte* elements_index = BUFFER_OFFSET(0); for (auto& group : triangleGroups) { @@ -437,7 +477,7 @@ void LineBucket::drawLinePatterns(LinepatternShader& shader) { if (!group->elements_length) { continue; } - group->array[1].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index); + group->array[1].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, glObjectStore); MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT, elements_index)); vertex_index += group->vertex_length * vertexBuffer.itemSize; |