Skip to content

Commit

Permalink
Fix issue #4860: apply map rotation to unpitched point labels.
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisLoer committed Jun 22, 2017
1 parent 37d660f commit 581dd0f
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 6 deletions.
11 changes: 9 additions & 2 deletions src/render/draw_symbol.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ function drawLayerSymbols(painter, sourceCache, layer, coords, isText, translate
const rotateWithMap = rotationAlignment === 'map';
const pitchWithMap = pitchAlignment === 'map';
const alongLine = rotateWithMap && layer.layout['symbol-placement'] === 'line';
// Line label rotation happens in `updateLineLabels`
// Pitched point labels are automatically rotated by the labelPlaneMatrix projection
// Unpitched point labels need to have their rotation applied after projection
const rotateInShader = rotateWithMap && !pitchWithMap && !alongLine;

const depthOn = pitchWithMap;

Expand Down Expand Up @@ -96,7 +100,7 @@ function drawLayerSymbols(painter, sourceCache, layer, coords, isText, translate
program = painter.useProgram(isSDF ? 'symbolSDF' : 'symbolIcon', programConfiguration);
programConfiguration.setUniforms(gl, program, layer, {zoom: painter.transform.zoom});

setSymbolDrawState(program, painter, layer, coord.z, isText, isSDF, rotateWithMap, pitchWithMap, bucket.fontstack, bucket.iconsNeedLinear, sizeData);
setSymbolDrawState(program, painter, layer, coord.z, isText, isSDF, rotateInShader, pitchWithMap, bucket.fontstack, bucket.iconsNeedLinear, sizeData);
}

painter.enableTileClippingMask(coord);
Expand Down Expand Up @@ -125,7 +129,7 @@ function drawLayerSymbols(painter, sourceCache, layer, coords, isText, translate
if (!depthOn) gl.enable(gl.DEPTH_TEST);
}

function setSymbolDrawState(program, painter, layer, tileZoom, isText, isSDF, rotateWithMap, pitchWithMap, fontstack, iconsNeedLinear, sizeData) {
function setSymbolDrawState(program, painter, layer, tileZoom, isText, isSDF, rotateInShader, pitchWithMap, fontstack, iconsNeedLinear, sizeData) {

const gl = painter.gl;
const tr = painter.transform;
Expand Down Expand Up @@ -170,6 +174,9 @@ function setSymbolDrawState(program, painter, layer, tileZoom, isText, isSDF, ro
const size = symbolSize.evaluateSizeForZoom(sizeData, tr, layer, isText);
if (size.uSizeT !== undefined) gl.uniform1f(program.u_size_t, size.uSizeT);
if (size.uSize !== undefined) gl.uniform1f(program.u_size, size.uSize);

gl.uniform1f(program.u_aspect_ratio, tr.width / tr.height);
gl.uniform1i(program.u_rotate_symbol, rotateInShader);
}

function drawTileSymbols(program, programConfiguration, painter, layer, tile, buffers, isText, isSDF, pitchWithMap) {
Expand Down
17 changes: 15 additions & 2 deletions src/shaders/symbol_icon.vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ uniform highp float u_size_t; // used to interpolate between zoom stops when siz
uniform highp float u_size; // used when size is both zoom and feature constant
uniform highp float u_camera_to_center_distance;
uniform highp float u_pitch;
uniform bool u_rotate_symbol;
uniform highp float u_aspect_ratio;
uniform highp float u_collision_y_stretch;

#pragma mapbox: define lowp float opacity
Expand Down Expand Up @@ -62,8 +64,19 @@ void main() {

float fontScale = u_is_text ? size / 24.0 : size;

highp float angle_sin = sin(segment_angle);
highp float angle_cos = cos(segment_angle);
highp float symbol_rotation = 0.0;
if (u_rotate_symbol) {
// See comments in symbol_sdf.vertex
vec4 offsetProjectedPoint = u_matrix * vec4(a_pos + vec2(1, 0), 0, 1);

vec2 a = projectedPoint.xy / projectedPoint.w;
vec2 b = offsetProjectedPoint.xy / offsetProjectedPoint.w;

symbol_rotation = atan((b.y - a.y) / u_aspect_ratio, b.x - a.x);
}

highp float angle_sin = sin(segment_angle + symbol_rotation);
highp float angle_cos = cos(segment_angle + symbol_rotation);
mat2 rotation_matrix = mat2(angle_cos, -1.0 * angle_sin, angle_sin, angle_cos);

vec4 projected_pos = u_label_plane_matrix * vec4(a_projected_pos.xy, 0.0, 1.0);
Expand Down
19 changes: 17 additions & 2 deletions src/shaders/symbol_sdf.vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ uniform mat4 u_gl_coord_matrix;
uniform bool u_is_text;
uniform bool u_pitch_with_map;
uniform highp float u_pitch;
uniform bool u_rotate_symbol;
uniform highp float u_aspect_ratio;
uniform highp float u_camera_to_center_distance;
uniform highp float u_collision_y_stretch;

Expand Down Expand Up @@ -82,8 +84,21 @@ void main() {

float fontScale = u_is_text ? size / 24.0 : size;

highp float angle_sin = sin(segment_angle);
highp float angle_cos = cos(segment_angle);
highp float symbol_rotation = 0.0;
if (u_rotate_symbol) {
// Point labels with 'rotation-alignment: map' are horizontal with respect to tile units
// To figure out that angle in projected space, we draw a short horizontal line in tile
// space, project it, and measure its angle in projected space.
vec4 offsetProjectedPoint = u_matrix * vec4(a_pos + vec2(1, 0), 0, 1);

vec2 a = projectedPoint.xy / projectedPoint.w;
vec2 b = offsetProjectedPoint.xy / offsetProjectedPoint.w;

symbol_rotation = atan((b.y - a.y) / u_aspect_ratio, b.x - a.x);
}

highp float angle_sin = sin(segment_angle + symbol_rotation);
highp float angle_cos = cos(segment_angle + symbol_rotation);
mat2 rotation_matrix = mat2(angle_cos, -1.0 * angle_sin, angle_sin, angle_cos);

vec4 projected_pos = u_label_plane_matrix * vec4(a_projected_pos.xy, 0.0, 1.0);
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"version": 8,
"metadata": {
"test": {
"width": 256,
"height": 256
}
},
"bearing": 45,
"pitch": 45,
"sources": {
"geojson": {
"type": "geojson",
"data": {
"type": "Point",
"coordinates": [
0,
0
]
}
}
},
"glyphs": "local://glyphs/{fontstack}/{range}.pbf",
"layers": [
{
"id": "text",
"type": "symbol",
"source": "geojson",
"layout": {
"symbol-placement": "point",
"text-rotation-alignment": "map",
"text-pitch-alignment": "viewport",
"text-field": "Test Text",
"text-font": [
"Open Sans Semibold",
"Arial Unicode MS Bold"
]
}
}
]
}

0 comments on commit 581dd0f

Please sign in to comment.