[core] reset line distance when it is near max

port 77ce4b45b2

fix #4492
This commit is contained in:
Ansis Brammanis
2016-03-28 16:35:49 -07:00
parent b352bb81d8
commit 930c3c46c5
6 changed files with 37 additions and 9 deletions

View File

@@ -26,7 +26,7 @@
],
"devDependencies": {
"aws-sdk": "^2.2.21",
"mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#872753bf80fc026caf99e540b9f2089be8c06030",
"mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#10924ef1cea1bea0cb1fa0aac4233a037a4daecc",
"node-gyp": "^3.2.1",
"request": "^2.67.0",
"tape": "^4.2.2"

View File

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

View File

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

View File

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

View File

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

View File

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