diff options
author | Ansis Brammanis <brammanis@gmail.com> | 2016-03-28 16:35:49 -0700 |
---|---|---|
committer | Ansis Brammanis <brammanis@gmail.com> | 2016-03-28 17:44:41 -0700 |
commit | 930c3c46c559960f689994e720e3a4efd1ddf608 (patch) | |
tree | c4214d763429c4056c66d437ab0c9654a13108f9 /src | |
parent | b352bb81d8259f1e52fe933a20f782d1c4327f1a (diff) | |
download | qtlocation-mapboxgl-930c3c46c559960f689994e720e3a4efd1ddf608.tar.gz |
[core] reset line distance when it is near max
port https://github.com/mapbox/mapbox-gl-js/commit/77ce4b45b24e8a0ed1bb739da436d19415c7e5e4
fix #4492
Diffstat (limited to 'src')
-rw-r--r-- | src/mbgl/geometry/line_buffer.cpp | 2 | ||||
-rw-r--r-- | src/mbgl/renderer/line_bucket.cpp | 28 | ||||
-rw-r--r-- | src/mbgl/renderer/line_bucket.hpp | 2 | ||||
-rw-r--r-- | src/mbgl/shader/linepattern.vertex.glsl | 6 | ||||
-rw-r--r-- | src/mbgl/shader/linesdf.vertex.glsl | 6 |
5 files changed, 36 insertions, 8 deletions
diff --git a/src/mbgl/geometry/line_buffer.cpp b/src/mbgl/geometry/line_buffer.cpp index b35d3e8f47..75b9af7e20 100644 --- a/src/mbgl/geometry/line_buffer.cpp +++ b/src/mbgl/geometry/line_buffer.cpp @@ -22,7 +22,7 @@ GLsizei LineVertexBuffer::add(vertex_type x, vertex_type y, float ex, float ey, // The z component's first bit, as well as the sign bit is reserved for the direction, // so we need to shift the linesofar. extrude[6] = ((dir < 0) ? -1 : 1) * ((dir ? 1 : 0) | static_cast<int8_t>((linesofar << 1) & 0x7F)); - extrude[7] = (linesofar >> 6) & 0x7F; + extrude[7] = ((linesofar >> 6) & 0xFF) - 128; return idx; } diff --git a/src/mbgl/renderer/line_bucket.cpp b/src/mbgl/renderer/line_bucket.cpp index 06daf3bbc3..1e8ba0ecb5 100644 --- a/src/mbgl/renderer/line_bucket.cpp +++ b/src/mbgl/renderer/line_bucket.cpp @@ -41,6 +41,17 @@ void LineBucket::addGeometry(const GeometryCollection& geometryCollection) { const float COS_HALF_SHARP_CORNER = std::cos(75.0 / 2.0 * (M_PI / 180.0)); const float SHARP_CORNER_OFFSET = 15.0f; +// The number of bits that is used to store the line distance in the buffer. +const int LINE_DISTANCE_BUFFER_BITS = 14; + +// We don't have enough bits for the line distance as we'd like to have, so +// use this value to scale the line distance (in tile units) down to a smaller +// value. This lets us store longer distances while sacrificing precision. +const float LINE_DISTANCE_SCALE = 1.0 / 2.0; + +// The maximum line distance, in tile units, that fits in the buffer. +const float MAX_LINE_DISTANCE = std::pow(2, LINE_DISTANCE_BUFFER_BITS) / LINE_DISTANCE_SCALE; + void LineBucket::addGeometry(const GeometryCoordinates& vertices) { const GLsizei len = [&vertices] { GLsizei l = static_cast<GLsizei>(vertices.size()); @@ -363,7 +374,7 @@ void LineBucket::addGeometry(const GeometryCoordinates& vertices) { void LineBucket::addCurrentVertex(const GeometryCoordinate& currentVertex, float flip, - double distance, + double &distance, const vec2<double>& normal, float endLeft, float endRight, @@ -375,7 +386,7 @@ void LineBucket::addCurrentVertex(const GeometryCoordinate& currentVertex, vec2<double> extrude = normal * flip; if (endLeft) extrude = extrude - (util::perp(normal) * endLeft); - e3 = vertexBuffer.add(currentVertex.x, currentVertex.y, extrude.x, extrude.y, tx, 0, endLeft, distance) + e3 = vertexBuffer.add(currentVertex.x, currentVertex.y, extrude.x, extrude.y, tx, 0, endLeft, distance * LINE_DISTANCE_SCALE) - startVertex; if (e1 >= 0 && e2 >= 0) { triangleStore.emplace_back(e1, e2, e3); @@ -386,13 +397,22 @@ void LineBucket::addCurrentVertex(const GeometryCoordinate& currentVertex, extrude = normal * (-flip); if (endRight) extrude = extrude - (util::perp(normal) * endRight); - e3 = vertexBuffer.add(currentVertex.x, currentVertex.y, extrude.x, extrude.y, tx, 1, -endRight, distance) + e3 = vertexBuffer.add(currentVertex.x, currentVertex.y, extrude.x, extrude.y, tx, 1, -endRight, distance * LINE_DISTANCE_SCALE) - startVertex; if (e1 >= 0 && e2 >= 0) { triangleStore.emplace_back(e1, e2, e3); } e1 = e2; e2 = e3; + + // There is a maximum "distance along the line" that we can store in the buffers. + // When we get close to the distance, reset it to zero and add the vertex again with + // a distance of zero. The max distance is determined by the number of bits we allocate + // to `linesofar`. + if (distance > MAX_LINE_DISTANCE / 2.0f) { + distance = 0; + addCurrentVertex(currentVertex, flip, distance, normal, endLeft, endRight, round, startVertex, triangleStore); + } } void LineBucket::addPieSliceVertex(const GeometryCoordinate& currentVertex, @@ -405,7 +425,7 @@ void LineBucket::addPieSliceVertex(const GeometryCoordinate& currentVertex, int8_t ty = lineTurnsLeft; auto flippedExtrude = extrude * (flip * (lineTurnsLeft ? -1 : 1)); - e3 = vertexBuffer.add(currentVertex.x, currentVertex.y, flippedExtrude.x, flippedExtrude.y, 0, ty, 0, distance) + e3 = vertexBuffer.add(currentVertex.x, currentVertex.y, flippedExtrude.x, flippedExtrude.y, 0, ty, 0, distance * LINE_DISTANCE_SCALE) - startVertex; if (e1 >= 0 && e2 >= 0) { triangleStore.emplace_back(e1, e2, e3); diff --git a/src/mbgl/renderer/line_bucket.hpp b/src/mbgl/renderer/line_bucket.hpp index 5b6509a5ee..1586bef0a7 100644 --- a/src/mbgl/renderer/line_bucket.hpp +++ b/src/mbgl/renderer/line_bucket.hpp @@ -43,7 +43,7 @@ private: TriangleElement(uint16_t a_, uint16_t b_, uint16_t c_) : a(a_), b(b_), c(c_) {} uint16_t a, b, c; }; - void addCurrentVertex(const GeometryCoordinate& currentVertex, float flip, double distance, + void addCurrentVertex(const GeometryCoordinate& currentVertex, float flip, double& distance, const vec2<double>& normal, float endLeft, float endRight, bool round, GLint startVertex, std::vector<LineBucket::TriangleElement>& triangleStore); void addPieSliceVertex(const GeometryCoordinate& currentVertex, float flip, double distance, diff --git a/src/mbgl/shader/linepattern.vertex.glsl b/src/mbgl/shader/linepattern.vertex.glsl index 5b3c468be0..6fa499106c 100644 --- a/src/mbgl/shader/linepattern.vertex.glsl +++ b/src/mbgl/shader/linepattern.vertex.glsl @@ -6,6 +6,10 @@ // #define scale 63.0 #define scale 0.015873016 +// We scale the distance before adding it to the buffers so that we can store +// long distances for long segments. Use this value to unscale the distance. +#define LINE_DISTANCE_SCALE 2.0 + attribute vec2 a_pos; attribute vec4 a_data; @@ -30,7 +34,7 @@ varying float v_gamma_scale; void main() { vec2 a_extrude = a_data.xy; float a_direction = sign(a_data.z) * mod(a_data.z, 2.0); - float a_linesofar = abs(floor(a_data.z / 2.0)) + a_data.w * 64.0; + float a_linesofar = (abs(floor(a_data.z / 2.0)) + (a_data.w + 128.0) * 64.0) * LINE_DISTANCE_SCALE; // We store the texture normals in the most insignificant bit // transform y so that 0 => -1 and 1 => 1 diff --git a/src/mbgl/shader/linesdf.vertex.glsl b/src/mbgl/shader/linesdf.vertex.glsl index 80516f97c0..f24d8399b8 100644 --- a/src/mbgl/shader/linesdf.vertex.glsl +++ b/src/mbgl/shader/linesdf.vertex.glsl @@ -6,6 +6,10 @@ // #define scale 63.0 #define scale 0.015873016 +// We scale the distance before adding it to the buffers so that we can store +// long distances for long segments. Use this value to unscale the distance. +#define LINE_DISTANCE_SCALE 2.0 + attribute vec2 a_pos; attribute vec4 a_data; @@ -34,7 +38,7 @@ varying float v_gamma_scale; void main() { vec2 a_extrude = a_data.xy; float a_direction = sign(a_data.z) * mod(a_data.z, 2.0); - float a_linesofar = abs(floor(a_data.z / 2.0)) + a_data.w * 64.0; + float a_linesofar = (abs(floor(a_data.z / 2.0)) + (a_data.w + 128.0) * 64.0) * LINE_DISTANCE_SCALE; // We store the texture normals in the most insignificant bit // transform y so that 0 => -1 and 1 => 1 |