Skip to content

Commit

Permalink
Make pitched collision detection more conservative:
Browse files Browse the repository at this point in the history
 When doing collision detection, assume all labels are scaled the same
 as the least scaled label in the tile.
  • Loading branch information
ChrisLoer committed Apr 26, 2017
1 parent cacbad9 commit 35127d3
Show file tree
Hide file tree
Showing 6 changed files with 22 additions and 10 deletions.
4 changes: 2 additions & 2 deletions src/data/bucket/symbol_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@ class SymbolBucket {
// Insert final placement into collision tree and add glyphs/icons to buffers

if (hasText) {
collisionTile.insertCollisionFeature(textCollisionFeature, glyphScale, layout['text-ignore-placement']);
collisionTile.insertCollisionFeature(textCollisionFeature, glyphScale, layout['text-ignore-placement'], layer.getLayoutValue('text-pitch-scale'));
if (glyphScale <= maxScale) {
const textSizeData = getSizeVertexData(layer,
this.zoom,
Expand All @@ -619,7 +619,7 @@ class SymbolBucket {
}

if (hasIcon) {
collisionTile.insertCollisionFeature(iconCollisionFeature, iconScale, layout['icon-ignore-placement']);
collisionTile.insertCollisionFeature(iconCollisionFeature, iconScale, layout['icon-ignore-placement'], layer.getLayoutValue('icon-pitch-scale'));
if (iconScale <= maxScale) {
const iconSizeData = getSizeVertexData(
layer,
Expand Down
3 changes: 1 addition & 2 deletions src/render/draw_collision_debug.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ function drawCollisionDebug(painter, sourceCache, layer, coords) {
gl.uniform1f(program.u_collision_y_stretch, tile.collisionTile.yStretch);
gl.uniform1f(program.u_pitch, painter.transform.pitch / 360 * 2 * Math.PI);
gl.uniform1f(program.u_camera_to_center_distance, painter.transform.cameraToCenterDistance);
// TODO: Hook up to `text-pitch-scale` and `icon-pitch-scale` properties
gl.uniform1f(program.u_pitch_scale, 0.0);
gl.uniform1f(program.u_pitch_scale, tile.collisionTile.minimumPitchScaling);

for (const segment of buffers.segments) {
segment.vaos[layer.id].bind(gl, program, buffers.layoutVertexBuffer, buffers.elementBuffer, null, segment.vertexOffset);
Expand Down
5 changes: 3 additions & 2 deletions src/render/draw_symbol.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,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, rotateWithMap, pitchWithMap, bucket.fontstack, bucket.iconsNeedLinear, sizeData, tile.collisionTile.minimumPitchScaling);
}

painter.enableTileClippingMask(coord);
Expand All @@ -112,7 +112,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, rotateWithMap, pitchWithMap, fontstack, iconsNeedLinear, sizeData, minimumPitchScaling) {

const gl = painter.gl;
const tr = painter.transform;
Expand Down Expand Up @@ -196,6 +196,7 @@ function setSymbolDrawState(program, painter, layer, tileZoom, isText, isSDF, ro
}
gl.uniform1f(program.u_camera_to_center_distance, tr.cameraToCenterDistance);
gl.uniform1f(program.u_pitch_scale, layer.getLayoutValue(isText ? 'text-pitch-scale' : 'icon-pitch-scale'));
gl.uniform1f(program.u_collision_pitch_scale, minimumPitchScaling);
}

function drawTileSymbols(program, programConfiguration, painter, layer, tile, buffers, isText, isSDF, pitchWithMap) {
Expand Down
4 changes: 3 additions & 1 deletion src/shaders/symbol_icon.vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ uniform mediump float u_layout_size; // used when size is feature constant
uniform mediump float u_camera_to_center_distance;
uniform mediump float u_pitch;
uniform mediump float u_pitch_scale;
uniform mediump float u_collision_pitch_scale;
uniform mediump float u_collision_y_stretch;

#pragma mapbox: define lowp float opacity
Expand Down Expand Up @@ -91,7 +92,8 @@ void main() {
// See comments in symbol_sdf.vertex
highp float incidence_stretch = camera_to_anchor_distance / (u_camera_to_center_distance * cos(u_pitch));
highp float collision_adjustment = max(1.0, incidence_stretch / u_collision_y_stretch);
highp float collision_perspective_ratio = 1.0 + (1.0 - u_collision_pitch_scale)*((camera_to_anchor_distance / u_camera_to_center_distance) - 1.0);

highp float perspective_zoom_adjust = log2(perspective_ratio * collision_adjustment)*10.0 / 255.0;
highp float perspective_zoom_adjust = log2(collision_perspective_ratio * collision_adjustment)*10.0 / 255.0;
v_fade_tex = vec2((a_labelminzoom / 255.0) + perspective_zoom_adjust, 0.0);
}
11 changes: 9 additions & 2 deletions src/shaders/symbol_sdf.vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ uniform mediump float u_bearing;
uniform mediump float u_aspect_ratio;
uniform mediump float u_camera_to_center_distance;
uniform mediump float u_pitch_scale;
uniform mediump float u_collision_pitch_scale;
uniform mediump float u_collision_y_stretch;
uniform vec2 u_extrude_scale;

Expand Down Expand Up @@ -170,7 +171,13 @@ void main() {
// Never make the adjustment less than 1.0: instead of allowing collisions on the x-axis, be conservative on
// the y-axis.
highp float collision_adjustment = max(1.0, incidence_stretch / u_collision_y_stretch);

highp float perspective_zoom_adjust = log2(perspective_ratio * collision_adjustment)*10.0 / 255.0;
// "collision_perspective_ratio" is based on the smallest pitch scaling of any label on the tile, instead of
// just the pitch scaling for this label. This is a conservative approximation that makes sure we don't collide
// with an unscaled (large) label even though this particular label is highly scaled (and thus small).
// Note that this same conservatism doesn't apply to the minzoom/maxzoom for line-following glyphs: those
// zoom bounds are independent of other labels on the tile.
highp float collision_perspective_ratio = 1.0 + (1.0 - u_collision_pitch_scale)*((camera_to_anchor_distance / u_camera_to_center_distance) - 1.0);

highp float perspective_zoom_adjust = log2(collision_perspective_ratio * collision_adjustment)*10.0 / 255.0;
v_fade_tex = vec2((a_labelminzoom / 255.0) + perspective_zoom_adjust, 0.0);
}
5 changes: 4 additions & 1 deletion src/symbol/collision_tile.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ class CollisionTile {
this.angle = angle;
this.pitch = pitch;

this.minimumPitchScaling = 1;

const sin = Math.sin(angle),
cos = Math.cos(angle);
this.rotationMatrix = [cos, -sin, sin, cos];
Expand Down Expand Up @@ -314,7 +316,8 @@ class CollisionTile {
* @param {number} minPlacementScale
* @private
*/
insertCollisionFeature(collisionFeature, minPlacementScale, ignorePlacement) {
insertCollisionFeature(collisionFeature, minPlacementScale, ignorePlacement, pitchScaling) {
this.minimumPitchScaling = Math.min(pitchScaling, this.minimumPitchScaling);

const grid = ignorePlacement ? this.ignoredGrid : this.grid;
const collisionBoxArray = this.collisionBoxArray;
Expand Down

0 comments on commit 35127d3

Please sign in to comment.