[core] reset line distance when it is near max
port 77ce4b45b2
fix #4492
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user