maplibre-gl 2.1.8 → 2.2.0-pre.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/generate-style-spec.ts +2 -0
- package/dist/maplibre-gl-csp-worker.js +1 -1
- package/dist/maplibre-gl-csp-worker.js.map +1 -1
- package/dist/maplibre-gl-csp.js +1 -1
- package/dist/maplibre-gl-csp.js.map +1 -1
- package/dist/maplibre-gl-dev.js +1517 -290
- package/dist/maplibre-gl.css +1 -1
- package/dist/maplibre-gl.d.ts +3476 -3112
- package/dist/maplibre-gl.js +4 -4
- package/dist/maplibre-gl.js.map +1 -1
- package/dist/package.json +1 -1
- package/package.json +15 -15
- package/src/css/maplibre-gl.css +20 -0
- package/src/css/svg/maplibregl-ctrl-terrain.svg +7 -0
- package/src/data/bucket/fill_extrusion_attributes.ts +4 -0
- package/src/data/bucket/fill_extrusion_bucket.ts +28 -4
- package/src/data/dem_data.test.ts +14 -1
- package/src/data/dem_data.ts +13 -0
- package/src/geo/transform.test.ts +56 -1
- package/src/geo/transform.ts +199 -47
- package/src/index.ts +2 -0
- package/src/render/draw_background.ts +6 -6
- package/src/render/draw_circle.ts +6 -2
- package/src/render/draw_collision_debug.ts +5 -1
- package/src/render/draw_debug.ts +5 -5
- package/src/render/draw_fill.ts +5 -2
- package/src/render/draw_fill_extrusion.ts +3 -2
- package/src/render/draw_heatmap.ts +2 -3
- package/src/render/draw_hillshade.ts +8 -7
- package/src/render/draw_line.ts +7 -5
- package/src/render/draw_raster.ts +8 -6
- package/src/render/draw_symbol.test.ts +34 -10
- package/src/render/draw_symbol.ts +23 -12
- package/src/render/draw_terrain.ts +123 -0
- package/src/render/painter.ts +52 -14
- package/src/render/program/hillshade_program.ts +7 -2
- package/src/render/program/line_program.ts +24 -10
- package/src/render/program/program_uniforms.ts +5 -1
- package/src/render/program/terrain_program.ts +83 -0
- package/src/render/program.ts +29 -5
- package/src/render/render_to_texture.test.ts +41 -0
- package/src/render/render_to_texture.ts +154 -0
- package/src/render/terrain.test.ts +53 -0
- package/src/render/terrain.ts +369 -0
- package/src/render/vertex_array_object.ts +21 -4
- package/src/shaders/_prelude.vertex.glsl +76 -0
- package/src/shaders/_prelude.vertex.glsl.g.ts +1 -1
- package/src/shaders/circle.fragment.glsl +2 -1
- package/src/shaders/circle.fragment.glsl.g.ts +1 -1
- package/src/shaders/circle.vertex.glsl +6 -2
- package/src/shaders/circle.vertex.glsl.g.ts +1 -1
- package/src/shaders/collision_box.vertex.glsl +1 -1
- package/src/shaders/collision_box.vertex.glsl.g.ts +1 -1
- package/src/shaders/debug.vertex.glsl +1 -1
- package/src/shaders/debug.vertex.glsl.g.ts +1 -1
- package/src/shaders/fill_extrusion.vertex.glsl +16 -2
- package/src/shaders/fill_extrusion.vertex.glsl.g.ts +1 -1
- package/src/shaders/fill_extrusion_pattern.vertex.glsl +15 -2
- package/src/shaders/fill_extrusion_pattern.vertex.glsl.g.ts +1 -1
- package/src/shaders/line.vertex.glsl +7 -3
- package/src/shaders/line.vertex.glsl.g.ts +1 -1
- package/src/shaders/line_gradient.vertex.glsl +7 -3
- package/src/shaders/line_gradient.vertex.glsl.g.ts +1 -1
- package/src/shaders/line_pattern.vertex.glsl +7 -3
- package/src/shaders/line_pattern.vertex.glsl.g.ts +1 -1
- package/src/shaders/line_sdf.vertex.glsl +7 -4
- package/src/shaders/line_sdf.vertex.glsl.g.ts +1 -1
- package/src/shaders/shaders.ts +11 -1
- package/src/shaders/symbol_icon.vertex.glsl +8 -8
- package/src/shaders/symbol_icon.vertex.glsl.g.ts +1 -1
- package/src/shaders/symbol_sdf.vertex.glsl +8 -5
- package/src/shaders/symbol_sdf.vertex.glsl.g.ts +1 -1
- package/src/shaders/symbol_text_and_icon.vertex.glsl +8 -5
- package/src/shaders/symbol_text_and_icon.vertex.glsl.g.ts +1 -1
- package/src/shaders/terrain.fragment.glsl +7 -0
- package/src/shaders/terrain.fragment.glsl.g.ts +2 -0
- package/src/shaders/terrain.vertex.glsl +12 -0
- package/src/shaders/terrain.vertex.glsl.g.ts +2 -0
- package/src/shaders/terrain_coords.fragment.glsl +11 -0
- package/src/shaders/terrain_coords.fragment.glsl.g.ts +2 -0
- package/src/shaders/terrain_depth.fragment.glsl +15 -0
- package/src/shaders/terrain_depth.fragment.glsl.g.ts +2 -0
- package/src/source/canvas_source.test.ts +1 -1
- package/src/source/geojson_source.test.ts +25 -0
- package/src/source/geojson_source.ts +1 -8
- package/src/source/geojson_worker_source.test.ts +19 -23
- package/src/source/geojson_worker_source.ts +19 -70
- package/src/source/raster_dem_tile_source.ts +4 -3
- package/src/source/raster_dem_tile_worker_source.ts +0 -1
- package/src/source/source_cache.test.ts +83 -0
- package/src/source/source_cache.ts +72 -11
- package/src/source/terrain_source_cache.test.ts +89 -0
- package/src/source/terrain_source_cache.ts +201 -0
- package/src/source/tile.ts +15 -0
- package/src/source/tile_id.ts +9 -0
- package/src/style/pauseable_placement.ts +3 -1
- package/src/style/style.test.ts +16 -0
- package/src/style/style.ts +57 -3
- package/src/style/validate_style.ts +2 -0
- package/src/style-spec/CHANGELOG.md +6 -0
- package/src/style-spec/error/validation_error.ts +1 -1
- package/src/style-spec/package.json +2 -2
- package/src/style-spec/reference/v8.json +42 -0
- package/src/style-spec/types.g.ts +7 -0
- package/src/style-spec/validate/validate.ts +2 -0
- package/src/style-spec/validate/validate_terrain.test.ts +46 -0
- package/src/style-spec/validate/validate_terrain.ts +41 -0
- package/src/style-spec/validate_style.min.ts +2 -0
- package/src/style-spec/validate_style.ts +1 -0
- package/src/symbol/collision_index.ts +28 -12
- package/src/symbol/placement.ts +24 -9
- package/src/symbol/projection.ts +42 -27
- package/src/ui/camera.ts +2 -0
- package/src/ui/control/terrain_control.ts +77 -0
- package/src/ui/default_locale.ts +3 -2
- package/src/ui/events.ts +18 -3
- package/src/ui/handler_manager.ts +33 -3
- package/src/ui/map.ts +36 -6
- package/src/ui/marker.test.ts +21 -0
- package/src/ui/marker.ts +14 -0
- package/src/util/primitives.ts +14 -11
package/src/geo/transform.ts
CHANGED
|
@@ -5,12 +5,13 @@ import Point from '@mapbox/point-geometry';
|
|
|
5
5
|
import {wrap, clamp} from '../util/util';
|
|
6
6
|
import {number as interpolate} from '../style-spec/util/interpolate';
|
|
7
7
|
import EXTENT from '../data/extent';
|
|
8
|
-
import {vec4, mat4, mat2, vec2} from 'gl-matrix';
|
|
8
|
+
import {vec3, vec4, mat4, mat2, vec2} from 'gl-matrix';
|
|
9
9
|
import {Aabb, Frustum} from '../util/primitives';
|
|
10
10
|
import EdgeInsets from './edge_insets';
|
|
11
11
|
|
|
12
12
|
import {UnwrappedTileID, OverscaledTileID, CanonicalTileID} from '../source/tile_id';
|
|
13
13
|
import type {PaddingOptions} from './edge_insets';
|
|
14
|
+
import Terrain from '../render/terrain';
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* A single transform, generally used for a single tile to be
|
|
@@ -31,14 +32,17 @@ class Transform {
|
|
|
31
32
|
zoomFraction: number;
|
|
32
33
|
pixelsToGLUnits: [number, number];
|
|
33
34
|
cameraToCenterDistance: number;
|
|
35
|
+
cameraToSeaLevelDistance: number;
|
|
34
36
|
mercatorMatrix: mat4;
|
|
35
37
|
projMatrix: mat4;
|
|
36
38
|
invProjMatrix: mat4;
|
|
37
39
|
alignedProjMatrix: mat4;
|
|
38
40
|
pixelMatrix: mat4;
|
|
41
|
+
pixelMatrix3D: mat4;
|
|
39
42
|
pixelMatrixInverse: mat4;
|
|
40
43
|
glCoordMatrix: mat4;
|
|
41
44
|
labelPlaneMatrix: mat4;
|
|
45
|
+
freezeElevation: boolean;
|
|
42
46
|
_fov: number;
|
|
43
47
|
_pitch: number;
|
|
44
48
|
_zoom: number;
|
|
@@ -49,6 +53,8 @@ class Transform {
|
|
|
49
53
|
_minPitch: number;
|
|
50
54
|
_maxPitch: number;
|
|
51
55
|
_center: LngLat;
|
|
56
|
+
_elevation: number;
|
|
57
|
+
_pixelPerMeter: number;
|
|
52
58
|
_edgeInsets: EdgeInsets;
|
|
53
59
|
_constraining: boolean;
|
|
54
60
|
_posMatrixCache: {[_: string]: mat4};
|
|
@@ -57,6 +63,7 @@ class Transform {
|
|
|
57
63
|
constructor(minZoom?: number, maxZoom?: number, minPitch?: number, maxPitch?: number, renderWorldCopies?: boolean) {
|
|
58
64
|
this.tileSize = 512; // constant
|
|
59
65
|
this.maxValidLatitude = 85.051129; // constant
|
|
66
|
+
this.freezeElevation = false;
|
|
60
67
|
|
|
61
68
|
this._renderWorldCopies = renderWorldCopies === undefined ? true : !!renderWorldCopies;
|
|
62
69
|
this._minZoom = minZoom || 0;
|
|
@@ -70,6 +77,7 @@ class Transform {
|
|
|
70
77
|
this.width = 0;
|
|
71
78
|
this.height = 0;
|
|
72
79
|
this._center = new LngLat(0, 0);
|
|
80
|
+
this._elevation = 0;
|
|
73
81
|
this.zoom = 0;
|
|
74
82
|
this.angle = 0;
|
|
75
83
|
this._fov = 0.6435011087932844;
|
|
@@ -87,6 +95,7 @@ class Transform {
|
|
|
87
95
|
clone.width = this.width;
|
|
88
96
|
clone.height = this.height;
|
|
89
97
|
clone._center = this._center;
|
|
98
|
+
clone._elevation = this._elevation;
|
|
90
99
|
clone.zoom = this.zoom;
|
|
91
100
|
clone.angle = this.angle;
|
|
92
101
|
clone._fov = this._fov;
|
|
@@ -207,6 +216,14 @@ class Transform {
|
|
|
207
216
|
this._calcMatrices();
|
|
208
217
|
}
|
|
209
218
|
|
|
219
|
+
get elevation(): number { return this._elevation; }
|
|
220
|
+
set elevation(elevation: number) {
|
|
221
|
+
if (elevation === this._elevation) return;
|
|
222
|
+
this._elevation = elevation;
|
|
223
|
+
this._constrain();
|
|
224
|
+
this._calcMatrices();
|
|
225
|
+
}
|
|
226
|
+
|
|
210
227
|
get padding(): PaddingOptions { return this._edgeInsets.toJSON(); }
|
|
211
228
|
set padding(padding: PaddingOptions) {
|
|
212
229
|
if (this._edgeInsets.equals(padding)) return;
|
|
@@ -322,6 +339,7 @@ class Transform {
|
|
|
322
339
|
roundZoom?: boolean;
|
|
323
340
|
reparseOverscaled?: boolean;
|
|
324
341
|
renderWorldCopies?: boolean;
|
|
342
|
+
terrain?: Terrain;
|
|
325
343
|
}
|
|
326
344
|
): Array<OverscaledTileID> {
|
|
327
345
|
let z = this.coveringZoomLevel(options);
|
|
@@ -330,23 +348,24 @@ class Transform {
|
|
|
330
348
|
if (options.minzoom !== undefined && z < options.minzoom) return [];
|
|
331
349
|
if (options.maxzoom !== undefined && z > options.maxzoom) z = options.maxzoom;
|
|
332
350
|
|
|
351
|
+
const cameraCoord = this.pointCoordinate(this.getCameraPoint());
|
|
333
352
|
const centerCoord = MercatorCoordinate.fromLngLat(this.center);
|
|
334
353
|
const numTiles = Math.pow(2, z);
|
|
354
|
+
const cameraPoint = [numTiles * cameraCoord.x, numTiles * cameraCoord.y, 0];
|
|
335
355
|
const centerPoint = [numTiles * centerCoord.x, numTiles * centerCoord.y, 0];
|
|
336
356
|
const cameraFrustum = Frustum.fromInvProjectionMatrix(this.invProjMatrix, this.worldSize, z);
|
|
337
357
|
|
|
338
358
|
// No change of LOD behavior for pitch lower than 60 and when there is no top padding: return only tile ids from the requested zoom level
|
|
339
359
|
let minZoom = options.minzoom || 0;
|
|
340
360
|
// Use 0.1 as an epsilon to avoid for explicit == 0.0 floating point checks
|
|
341
|
-
if (this.pitch <= 60.0 && this._edgeInsets.top < 0.1)
|
|
361
|
+
if (!options.terrain && this.pitch <= 60.0 && this._edgeInsets.top < 0.1)
|
|
342
362
|
minZoom = z;
|
|
343
363
|
|
|
344
|
-
// There should always be a certain number of maximum zoom level tiles surrounding the center location
|
|
345
|
-
const radiusOfMaxLvlLodInTiles = 3;
|
|
364
|
+
// There should always be a certain number of maximum zoom level tiles surrounding the center location in 2D or in front of the camera in 3D
|
|
365
|
+
const radiusOfMaxLvlLodInTiles = options.terrain ? 2 / Math.min(this.tileSize, options.tileSize) * this.tileSize : 3;
|
|
346
366
|
|
|
347
367
|
const newRootTile = (wrap: number): any => {
|
|
348
368
|
return {
|
|
349
|
-
// All tiles are on zero elevation plane => z difference is zero
|
|
350
369
|
aabb: new Aabb([wrap * numTiles, 0, 0], [(wrap + 1) * numTiles, numTiles, 0]),
|
|
351
370
|
zoom: 0,
|
|
352
371
|
x: 0,
|
|
@@ -388,8 +407,9 @@ class Transform {
|
|
|
388
407
|
fullyVisible = intersectResult === 2;
|
|
389
408
|
}
|
|
390
409
|
|
|
391
|
-
const
|
|
392
|
-
const
|
|
410
|
+
const refPoint = options.terrain ? cameraPoint : centerPoint;
|
|
411
|
+
const distanceX = it.aabb.distanceX(refPoint);
|
|
412
|
+
const distanceY = it.aabb.distanceY(refPoint);
|
|
393
413
|
const longestDim = Math.max(Math.abs(distanceX), Math.abs(distanceY));
|
|
394
414
|
|
|
395
415
|
// We're using distance based heuristics to determine if a tile should be split into quadrants or not.
|
|
@@ -401,9 +421,12 @@ class Transform {
|
|
|
401
421
|
|
|
402
422
|
// Have we reached the target depth or is the tile too far away to be any split further?
|
|
403
423
|
if (it.zoom === maxZoom || (longestDim > distToSplit && it.zoom >= minZoom)) {
|
|
424
|
+
const dz = maxZoom - it.zoom, dx = cameraPoint[0] - 0.5 - (x << dz), dy = cameraPoint[1] - 0.5 - (y << dz);
|
|
404
425
|
result.push({
|
|
405
426
|
tileID: new OverscaledTileID(it.zoom === maxZoom ? overscaledZ : it.zoom, it.wrap, it.zoom, x, y),
|
|
406
|
-
distanceSq: vec2.sqrLen([centerPoint[0] - 0.5 - x, centerPoint[1] - 0.5 - y])
|
|
427
|
+
distanceSq: vec2.sqrLen([centerPoint[0] - 0.5 - x, centerPoint[1] - 0.5 - y]),
|
|
428
|
+
// this variable is currently not used, but may be important to reduce the amount of loaded tiles
|
|
429
|
+
tileDistanceToCamera: Math.sqrt(dx * dx + dy * dy)
|
|
407
430
|
});
|
|
408
431
|
continue;
|
|
409
432
|
}
|
|
@@ -411,8 +434,22 @@ class Transform {
|
|
|
411
434
|
for (let i = 0; i < 4; i++) {
|
|
412
435
|
const childX = (x << 1) + (i % 2);
|
|
413
436
|
const childY = (y << 1) + (i >> 1);
|
|
414
|
-
|
|
415
|
-
|
|
437
|
+
const childZ = it.zoom + 1;
|
|
438
|
+
let quadrant = it.aabb.quadrant(i);
|
|
439
|
+
if (options.terrain) {
|
|
440
|
+
const tileID = new OverscaledTileID(childZ, it.wrap, childZ, childX, childY);
|
|
441
|
+
const tile = options.terrain.getTerrainData(tileID).tile;
|
|
442
|
+
let minElevation = this.elevation, maxElevation = this.elevation;
|
|
443
|
+
if (tile && tile.dem) {
|
|
444
|
+
minElevation = tile.dem.min * options.terrain.exaggeration;
|
|
445
|
+
maxElevation = tile.dem.max * options.terrain.exaggeration;
|
|
446
|
+
}
|
|
447
|
+
quadrant = new Aabb(
|
|
448
|
+
[quadrant.min[0], quadrant.min[1], minElevation] as vec3,
|
|
449
|
+
[quadrant.max[0], quadrant.max[1], maxElevation] as vec3
|
|
450
|
+
);
|
|
451
|
+
}
|
|
452
|
+
stack.push({aabb: quadrant, zoom: childZ, x: childX, y: childY, wrap: it.wrap, fullyVisible});
|
|
416
453
|
}
|
|
417
454
|
}
|
|
418
455
|
|
|
@@ -446,6 +483,72 @@ class Transform {
|
|
|
446
483
|
|
|
447
484
|
get point(): Point { return this.project(this.center); }
|
|
448
485
|
|
|
486
|
+
/**
|
|
487
|
+
* Updates the center-elevation value unless freezeElevation is activated.
|
|
488
|
+
* @param terrain the terrain
|
|
489
|
+
*/
|
|
490
|
+
updateElevation(terrain?: Terrain) {
|
|
491
|
+
if (this.freezeElevation) return;
|
|
492
|
+
this.elevation = terrain ? this.getElevation(this._center, terrain) : 0;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* get the elevation from terrain for the current zoomlevel.
|
|
497
|
+
* @param lnglat the location
|
|
498
|
+
* @param terrain the terrain
|
|
499
|
+
* @returns {Number} elevation in meters
|
|
500
|
+
*/
|
|
501
|
+
getElevation(lnglat: LngLat, terrain: Terrain) {
|
|
502
|
+
const merc = MercatorCoordinate.fromLngLat(lnglat);
|
|
503
|
+
const worldSize = (1 << this.tileZoom) * EXTENT;
|
|
504
|
+
const mercX = merc.x * worldSize, mercY = merc.y * worldSize;
|
|
505
|
+
const tileX = Math.floor(mercX / EXTENT), tileY = Math.floor(mercY / EXTENT);
|
|
506
|
+
const tileID = new OverscaledTileID(this.tileZoom, 0, this.tileZoom, tileX, tileY);
|
|
507
|
+
return terrain.getElevation(tileID, mercX % EXTENT, mercY % EXTENT, EXTENT);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* get the camera position in LngLat and altitudes in meter
|
|
512
|
+
* @returns {Object} An object with lngLat & altitude.
|
|
513
|
+
*/
|
|
514
|
+
getCameraPosition(): {
|
|
515
|
+
lngLat: LngLat;
|
|
516
|
+
altitude: number;
|
|
517
|
+
} {
|
|
518
|
+
const lngLat = this.pointLocation(this.getCameraPoint());
|
|
519
|
+
const altitude = Math.cos(this._pitch) * this.cameraToCenterDistance / this._pixelPerMeter;
|
|
520
|
+
return {lngLat, altitude: altitude + this.elevation};
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* This method works in combination with freezeElevation activated.
|
|
525
|
+
* freezeElevtion is enabled during map-panning because during this the camera should sit in constant height.
|
|
526
|
+
* After panning finished, call this method to recalculate the zoomlevel for the current camera-height in current terrain.
|
|
527
|
+
* @param {Terrain} terrain the terrain
|
|
528
|
+
*/
|
|
529
|
+
recalculateZoom(terrain: Terrain) {
|
|
530
|
+
// find position the camera is looking on
|
|
531
|
+
const center = this.pointLocation(this.centerPoint, terrain);
|
|
532
|
+
const elevation = this.getElevation(center, terrain);
|
|
533
|
+
const deltaElevation = this.elevation - elevation;
|
|
534
|
+
if (!deltaElevation) return;
|
|
535
|
+
|
|
536
|
+
// calculate mercator distance between camera & target
|
|
537
|
+
const cameraPosition = this.getCameraPosition();
|
|
538
|
+
const camera = MercatorCoordinate.fromLngLat(cameraPosition.lngLat, cameraPosition.altitude);
|
|
539
|
+
const target = MercatorCoordinate.fromLngLat(center, elevation);
|
|
540
|
+
const dx = camera.x - target.x, dy = camera.y - target.y, dz = camera.z - target.z;
|
|
541
|
+
const distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
542
|
+
|
|
543
|
+
// from this distance we calculate the new zoomlevel
|
|
544
|
+
const zoom = this.scaleZoom(this.cameraToCenterDistance / distance / this.tileSize);
|
|
545
|
+
|
|
546
|
+
// update matrices
|
|
547
|
+
this._elevation = elevation;
|
|
548
|
+
this._center = center;
|
|
549
|
+
this.zoom = zoom;
|
|
550
|
+
}
|
|
551
|
+
|
|
449
552
|
setLocationAtPoint(lnglat: LngLat, point: Point) {
|
|
450
553
|
const a = this.pointCoordinate(point);
|
|
451
554
|
const b = this.pointCoordinate(this.centerPoint);
|
|
@@ -462,31 +565,35 @@ class Transform {
|
|
|
462
565
|
/**
|
|
463
566
|
* Given a location, return the screen point that corresponds to it
|
|
464
567
|
* @param {LngLat} lnglat location
|
|
568
|
+
* @param {Terrain} terrain optional terrain
|
|
465
569
|
* @returns {Point} screen point
|
|
466
570
|
* @private
|
|
467
571
|
*/
|
|
468
|
-
locationPoint(lnglat: LngLat) {
|
|
469
|
-
return
|
|
572
|
+
locationPoint(lnglat: LngLat, terrain?: Terrain): Point {
|
|
573
|
+
return terrain ?
|
|
574
|
+
this.coordinatePoint(this.locationCoordinate(lnglat), this.getElevation(lnglat, terrain), this.pixelMatrix3D) :
|
|
575
|
+
this.coordinatePoint(this.locationCoordinate(lnglat));
|
|
470
576
|
}
|
|
471
577
|
|
|
472
578
|
/**
|
|
473
579
|
* Given a point on screen, return its lnglat
|
|
474
580
|
* @param {Point} p screen point
|
|
581
|
+
* @param {Terrain} terrain optional terrain
|
|
475
582
|
* @returns {LngLat} lnglat location
|
|
476
583
|
* @private
|
|
477
584
|
*/
|
|
478
|
-
pointLocation(p: Point) {
|
|
479
|
-
return this.coordinateLocation(this.pointCoordinate(p));
|
|
585
|
+
pointLocation(p: Point, terrain?: Terrain): LngLat {
|
|
586
|
+
return this.coordinateLocation(this.pointCoordinate(p, terrain));
|
|
480
587
|
}
|
|
481
588
|
|
|
482
589
|
/**
|
|
483
590
|
* Given a geographical lnglat, return an unrounded
|
|
484
591
|
* coordinate that represents it at this transform's zoom level.
|
|
485
592
|
* @param {LngLat} lnglat
|
|
486
|
-
* @returns {
|
|
593
|
+
* @returns {MercatorCoordinate}
|
|
487
594
|
* @private
|
|
488
595
|
*/
|
|
489
|
-
locationCoordinate(lnglat: LngLat) {
|
|
596
|
+
locationCoordinate(lnglat: LngLat): MercatorCoordinate {
|
|
490
597
|
return MercatorCoordinate.fromLngLat(lnglat);
|
|
491
598
|
}
|
|
492
599
|
|
|
@@ -496,11 +603,27 @@ class Transform {
|
|
|
496
603
|
* @returns {LngLat} lnglat
|
|
497
604
|
* @private
|
|
498
605
|
*/
|
|
499
|
-
coordinateLocation(coord: MercatorCoordinate) {
|
|
500
|
-
return coord.toLngLat();
|
|
606
|
+
coordinateLocation(coord: MercatorCoordinate): LngLat {
|
|
607
|
+
return coord && coord.toLngLat();
|
|
501
608
|
}
|
|
502
609
|
|
|
503
|
-
|
|
610
|
+
/**
|
|
611
|
+
* Given a Point, return its mercator coordinate.
|
|
612
|
+
* @param {Point} p the point
|
|
613
|
+
* @param {Terrain} terrain optional terrain
|
|
614
|
+
* @returns {LngLat} lnglat
|
|
615
|
+
* @private
|
|
616
|
+
*/
|
|
617
|
+
pointCoordinate(p: Point, terrain?: Terrain): MercatorCoordinate {
|
|
618
|
+
// get point-coordinate from terrain coordinates framebuffer
|
|
619
|
+
if (terrain) {
|
|
620
|
+
const coordinate = terrain.pointCoordinate(p);
|
|
621
|
+
if (coordinate != null) {
|
|
622
|
+
return coordinate;
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
// calcuate point-coordinate on flat earth
|
|
504
627
|
const targetZ = 0;
|
|
505
628
|
// since we don't know the correct projected z value for the point,
|
|
506
629
|
// unproject two points to get a line and then find the point on that
|
|
@@ -531,12 +654,14 @@ class Transform {
|
|
|
531
654
|
/**
|
|
532
655
|
* Given a coordinate, return the screen point that corresponds to it
|
|
533
656
|
* @param {Coordinate} coord
|
|
657
|
+
* @params {number} elevation default = 0
|
|
658
|
+
* @params {mat4} pixelMatrix, default = this.pixelMatrix
|
|
534
659
|
* @returns {Point} screen point
|
|
535
660
|
* @private
|
|
536
661
|
*/
|
|
537
|
-
coordinatePoint(coord: MercatorCoordinate) {
|
|
538
|
-
const p = [coord.x * this.worldSize, coord.y * this.worldSize,
|
|
539
|
-
vec4.transformMat4(p, p,
|
|
662
|
+
coordinatePoint(coord: MercatorCoordinate, elevation: number = 0, pixelMatrix = this.pixelMatrix): Point {
|
|
663
|
+
const p = [coord.x * this.worldSize, coord.y * this.worldSize, elevation, 1] as any;
|
|
664
|
+
vec4.transformMat4(p, p, pixelMatrix);
|
|
540
665
|
return new Point(p[0] / p[3], p[1] / p[3]);
|
|
541
666
|
}
|
|
542
667
|
|
|
@@ -546,9 +671,10 @@ class Transform {
|
|
|
546
671
|
* @returns {LngLatBounds} Returns a {@link LngLatBounds} object describing the map's geographical bounds.
|
|
547
672
|
*/
|
|
548
673
|
getBounds(): LngLatBounds {
|
|
674
|
+
const top = Math.max(0, this.height / 2 - this.getHorizon());
|
|
549
675
|
return new LngLatBounds()
|
|
550
|
-
.extend(this.pointLocation(new Point(0,
|
|
551
|
-
.extend(this.pointLocation(new Point(this.width,
|
|
676
|
+
.extend(this.pointLocation(new Point(0, top)))
|
|
677
|
+
.extend(this.pointLocation(new Point(this.width, top)))
|
|
552
678
|
.extend(this.pointLocation(new Point(this.width, this.height)))
|
|
553
679
|
.extend(this.pointLocation(new Point(0, this.height)));
|
|
554
680
|
}
|
|
@@ -564,6 +690,16 @@ class Transform {
|
|
|
564
690
|
return new LngLatBounds([this.lngRange[0], this.latRange[0]], [this.lngRange[1], this.latRange[1]]);
|
|
565
691
|
}
|
|
566
692
|
|
|
693
|
+
/**
|
|
694
|
+
* Calculate pixel height of the visible horizon in relation to map-center (e.g. height/2),
|
|
695
|
+
* multiplied by a static factor to simulate the earth-radius.
|
|
696
|
+
* The calculated value is the horizontal line from the camera-height to sea-level.
|
|
697
|
+
* @returns {number} Horizon above center in pixels.
|
|
698
|
+
*/
|
|
699
|
+
getHorizon(): number {
|
|
700
|
+
return Math.tan(Math.PI / 2 - this._pitch) * this.cameraToCenterDistance * 0.85;
|
|
701
|
+
}
|
|
702
|
+
|
|
567
703
|
/**
|
|
568
704
|
* Sets or clears the map's geographical constraints.
|
|
569
705
|
* @param {LngLatBounds} bounds A {@link LngLatBounds} object describing the new geographic boundaries of the map.
|
|
@@ -682,7 +818,23 @@ class Transform {
|
|
|
682
818
|
|
|
683
819
|
const halfFov = this._fov / 2;
|
|
684
820
|
const offset = this.centerOffset;
|
|
821
|
+
const x = this.point.x, y = this.point.y;
|
|
685
822
|
this.cameraToCenterDistance = 0.5 / Math.tan(halfFov) * this.height;
|
|
823
|
+
this._pixelPerMeter = mercatorZfromAltitude(1, this.center.lat) * this.worldSize;
|
|
824
|
+
|
|
825
|
+
let m = mat4.identity(new Float64Array(16) as any);
|
|
826
|
+
mat4.scale(m, m, [this.width / 2, -this.height / 2, 1]);
|
|
827
|
+
mat4.translate(m, m, [1, -1, 0]);
|
|
828
|
+
this.labelPlaneMatrix = m;
|
|
829
|
+
|
|
830
|
+
m = mat4.identity(new Float64Array(16) as any);
|
|
831
|
+
mat4.scale(m, m, [1, -1, 1]);
|
|
832
|
+
mat4.translate(m, m, [-1, -1, 0]);
|
|
833
|
+
mat4.scale(m, m, [2 / this.width, 2 / this.height, 1]);
|
|
834
|
+
this.glCoordMatrix = m;
|
|
835
|
+
|
|
836
|
+
// calculate the camera to sea-level distance in pixel in respect of terrain
|
|
837
|
+
this.cameraToSeaLevelDistance = this.cameraToCenterDistance + this._elevation * this._pixelPerMeter / Math.cos(this._pitch);
|
|
686
838
|
|
|
687
839
|
// Find the distance from the center point [width/2 + offset.x, height/2 + offset.y] to the
|
|
688
840
|
// center top point [width/2 + offset.x, 0] in Z units, using the law of sines.
|
|
@@ -690,14 +842,20 @@ class Transform {
|
|
|
690
842
|
// (the distance between[width/2, height/2] and [width/2 + 1, height/2])
|
|
691
843
|
const groundAngle = Math.PI / 2 + this._pitch;
|
|
692
844
|
const fovAboveCenter = this._fov * (0.5 + offset.y / this.height);
|
|
693
|
-
const topHalfSurfaceDistance = Math.sin(fovAboveCenter) * this.
|
|
694
|
-
|
|
695
|
-
|
|
845
|
+
const topHalfSurfaceDistance = Math.sin(fovAboveCenter) * this.cameraToSeaLevelDistance / Math.sin(clamp(Math.PI - groundAngle - fovAboveCenter, 0.01, Math.PI - 0.01));
|
|
846
|
+
|
|
847
|
+
// Find the distance from the center point to the horizon
|
|
848
|
+
const horizon = this.getHorizon();
|
|
849
|
+
const horizonAngle = Math.atan(horizon / this.cameraToCenterDistance);
|
|
850
|
+
const fovCenterToHorizon = 2 * horizonAngle * (0.5 + offset.y / (horizon * 2));
|
|
851
|
+
const topHalfSurfaceDistanceHorizon = Math.sin(fovCenterToHorizon) * this.cameraToSeaLevelDistance / Math.sin(clamp(Math.PI - groundAngle - fovCenterToHorizon, 0.01, Math.PI - 0.01));
|
|
696
852
|
|
|
697
853
|
// Calculate z distance of the farthest fragment that should be rendered.
|
|
698
|
-
const furthestDistance = Math.cos(Math.PI / 2 - this._pitch) * topHalfSurfaceDistance + this.
|
|
854
|
+
const furthestDistance = Math.cos(Math.PI / 2 - this._pitch) * topHalfSurfaceDistance + this.cameraToSeaLevelDistance;
|
|
855
|
+
const furthestDistanceHorizon = Math.cos(Math.PI / 2 - this._pitch) * topHalfSurfaceDistanceHorizon + this.cameraToSeaLevelDistance;
|
|
856
|
+
|
|
699
857
|
// Add a bit extra to avoid precision problems when a fragment's distance is exactly `furthestDistance`
|
|
700
|
-
const farZ = furthestDistance * 1.01;
|
|
858
|
+
const farZ = Math.min(furthestDistance, furthestDistanceHorizon) * 1.01;
|
|
701
859
|
|
|
702
860
|
// The larger the value of nearZ is
|
|
703
861
|
// - the more depth precision is available for features (good)
|
|
@@ -709,10 +867,10 @@ class Transform {
|
|
|
709
867
|
const nearZ = this.height / 50;
|
|
710
868
|
|
|
711
869
|
// matrix for conversion from location to GL coordinates (-1 .. 1)
|
|
712
|
-
|
|
870
|
+
m = new Float64Array(16) as any;
|
|
713
871
|
mat4.perspective(m, this._fov, this.width / this.height, nearZ, farZ);
|
|
714
872
|
|
|
715
|
-
//Apply center of perspective offset
|
|
873
|
+
// Apply center of perspective offset
|
|
716
874
|
m[8] = -offset.x * 2 / this.width;
|
|
717
875
|
m[9] = offset.y * 2 / this.height;
|
|
718
876
|
|
|
@@ -727,10 +885,18 @@ class Transform {
|
|
|
727
885
|
this.mercatorMatrix = mat4.scale([] as any, m, [this.worldSize, this.worldSize, this.worldSize]);
|
|
728
886
|
|
|
729
887
|
// scale vertically to meters per pixel (inverse of ground resolution):
|
|
730
|
-
mat4.scale(m, m, [1, 1,
|
|
888
|
+
mat4.scale(m, m, [1, 1, this._pixelPerMeter]);
|
|
889
|
+
|
|
890
|
+
// matrix for conversion from location to screen coordinates in 2D
|
|
891
|
+
this.pixelMatrix = mat4.multiply(new Float64Array(16) as any, this.labelPlaneMatrix, m);
|
|
731
892
|
|
|
893
|
+
// matrix for conversion from location to GL coordinates (-1 .. 1)
|
|
894
|
+
mat4.translate(m, m, [0, 0, -this.elevation]); // elevate camera over terrain
|
|
732
895
|
this.projMatrix = m;
|
|
733
|
-
this.invProjMatrix = mat4.invert([] as any,
|
|
896
|
+
this.invProjMatrix = mat4.invert([] as any, m);
|
|
897
|
+
|
|
898
|
+
// matrix for conversion from location to screen coordinates in 2D
|
|
899
|
+
this.pixelMatrix3D = mat4.multiply(new Float64Array(16) as any, this.labelPlaneMatrix, m);
|
|
734
900
|
|
|
735
901
|
// Make a second projection matrix that is aligned to a pixel grid for rendering raster tiles.
|
|
736
902
|
// We're rounding the (floating point) x/y values to achieve to avoid rendering raster images to fractional
|
|
@@ -746,20 +912,6 @@ class Transform {
|
|
|
746
912
|
mat4.translate(alignedM, alignedM, [ dx > 0.5 ? dx - 1 : dx, dy > 0.5 ? dy - 1 : dy, 0 ]);
|
|
747
913
|
this.alignedProjMatrix = alignedM;
|
|
748
914
|
|
|
749
|
-
m = mat4.create();
|
|
750
|
-
mat4.scale(m, m, [this.width / 2, -this.height / 2, 1]);
|
|
751
|
-
mat4.translate(m, m, [1, -1, 0]);
|
|
752
|
-
this.labelPlaneMatrix = m;
|
|
753
|
-
|
|
754
|
-
m = mat4.create();
|
|
755
|
-
mat4.scale(m, m, [1, -1, 1]);
|
|
756
|
-
mat4.translate(m, m, [-1, -1, 0]);
|
|
757
|
-
mat4.scale(m, m, [2 / this.width, 2 / this.height, 1]);
|
|
758
|
-
this.glCoordMatrix = m;
|
|
759
|
-
|
|
760
|
-
// matrix for conversion from location to screen coordinates
|
|
761
|
-
this.pixelMatrix = mat4.multiply(new Float64Array(16) as any, this.labelPlaneMatrix, this.projMatrix);
|
|
762
|
-
|
|
763
915
|
// inverse matrix for conversion from screen coordinaes to location
|
|
764
916
|
m = mat4.invert(new Float64Array(16) as any, this.pixelMatrix);
|
|
765
917
|
if (!m) throw new Error('failed to invert matrix');
|
package/src/index.ts
CHANGED
|
@@ -8,6 +8,7 @@ import AttributionControl from './ui/control/attribution_control';
|
|
|
8
8
|
import LogoControl from './ui/control/logo_control';
|
|
9
9
|
import ScaleControl from './ui/control/scale_control';
|
|
10
10
|
import FullscreenControl from './ui/control/fullscreen_control';
|
|
11
|
+
import TerrainControl from './ui/control/terrain_control';
|
|
11
12
|
import Popup from './ui/popup';
|
|
12
13
|
import Marker from './ui/marker';
|
|
13
14
|
import Style from './style/style';
|
|
@@ -46,6 +47,7 @@ const exported = {
|
|
|
46
47
|
LogoControl,
|
|
47
48
|
ScaleControl,
|
|
48
49
|
FullscreenControl,
|
|
50
|
+
TerrainControl,
|
|
49
51
|
Popup,
|
|
50
52
|
Marker,
|
|
51
53
|
Style,
|
|
@@ -9,10 +9,11 @@ import {
|
|
|
9
9
|
import type Painter from './painter';
|
|
10
10
|
import type SourceCache from '../source/source_cache';
|
|
11
11
|
import type BackgroundStyleLayer from '../style/style_layer/background_style_layer';
|
|
12
|
+
import {OverscaledTileID} from '../source/tile_id';
|
|
12
13
|
|
|
13
14
|
export default drawBackground;
|
|
14
15
|
|
|
15
|
-
function drawBackground(painter: Painter, sourceCache: SourceCache, layer: BackgroundStyleLayer) {
|
|
16
|
+
function drawBackground(painter: Painter, sourceCache: SourceCache, layer: BackgroundStyleLayer, coords?: Array<OverscaledTileID>) {
|
|
16
17
|
const color = layer.paint.get('background-color');
|
|
17
18
|
const opacity = layer.paint.get('background-opacity');
|
|
18
19
|
|
|
@@ -31,10 +32,8 @@ function drawBackground(painter: Painter, sourceCache: SourceCache, layer: Backg
|
|
|
31
32
|
const stencilMode = StencilMode.disabled;
|
|
32
33
|
const depthMode = painter.depthModeForSublayer(0, pass === 'opaque' ? DepthMode.ReadWrite : DepthMode.ReadOnly);
|
|
33
34
|
const colorMode = painter.colorModeForRenderPass();
|
|
34
|
-
|
|
35
35
|
const program = painter.useProgram(image ? 'backgroundPattern' : 'background');
|
|
36
|
-
|
|
37
|
-
const tileIDs = transform.coveringTiles({tileSize});
|
|
36
|
+
const tileIDs = coords ? coords : transform.coveringTiles({tileSize, terrain: painter.style.terrain});
|
|
38
37
|
|
|
39
38
|
if (image) {
|
|
40
39
|
context.activeTexture.set(gl.TEXTURE0);
|
|
@@ -43,13 +42,14 @@ function drawBackground(painter: Painter, sourceCache: SourceCache, layer: Backg
|
|
|
43
42
|
|
|
44
43
|
const crossfade = layer.getCrossfadeParameters();
|
|
45
44
|
for (const tileID of tileIDs) {
|
|
46
|
-
const matrix = painter.transform.calculatePosMatrix(tileID.toUnwrapped());
|
|
45
|
+
const matrix = coords ? tileID.posMatrix : painter.transform.calculatePosMatrix(tileID.toUnwrapped());
|
|
47
46
|
const uniformValues = image ?
|
|
48
47
|
backgroundPatternUniformValues(matrix, opacity, painter, image, {tileID, tileSize}, crossfade) :
|
|
49
48
|
backgroundUniformValues(matrix, opacity, color);
|
|
49
|
+
const terrainData = painter.style.terrain && painter.style.terrain.getTerrainData(tileID);
|
|
50
50
|
|
|
51
51
|
program.draw(context, gl.TRIANGLES, depthMode, stencilMode, colorMode, CullFaceMode.disabled,
|
|
52
|
-
uniformValues, layer.id, painter.tileExtentBuffer,
|
|
52
|
+
uniformValues, terrainData, layer.id, painter.tileExtentBuffer,
|
|
53
53
|
painter.quadTriangleIndexBuffer, painter.tileExtentSegments);
|
|
54
54
|
}
|
|
55
55
|
}
|
|
@@ -15,6 +15,7 @@ import type VertexBuffer from '../gl/vertex_buffer';
|
|
|
15
15
|
import type IndexBuffer from '../gl/index_buffer';
|
|
16
16
|
import type {UniformValues} from './uniform_binding';
|
|
17
17
|
import type {CircleUniformsType} from './program/circle_program';
|
|
18
|
+
import type {TerrainData} from '../render/terrain';
|
|
18
19
|
|
|
19
20
|
export default drawCircles;
|
|
20
21
|
|
|
@@ -24,6 +25,7 @@ type TileRenderState = {
|
|
|
24
25
|
layoutVertexBuffer: VertexBuffer;
|
|
25
26
|
indexBuffer: IndexBuffer;
|
|
26
27
|
uniformValues: UniformValues<CircleUniformsType>;
|
|
28
|
+
terrainData: TerrainData;
|
|
27
29
|
};
|
|
28
30
|
|
|
29
31
|
type SegmentsTileRenderState = {
|
|
@@ -66,6 +68,7 @@ function drawCircles(painter: Painter, sourceCache: SourceCache, layer: CircleSt
|
|
|
66
68
|
const program = painter.useProgram('circle', programConfiguration);
|
|
67
69
|
const layoutVertexBuffer = bucket.layoutVertexBuffer;
|
|
68
70
|
const indexBuffer = bucket.indexBuffer;
|
|
71
|
+
const terrainData = painter.style.terrain && painter.style.terrain.getTerrainData(coord);
|
|
69
72
|
const uniformValues = circleUniformValues(painter, coord, tile, layer);
|
|
70
73
|
|
|
71
74
|
const state: TileRenderState = {
|
|
@@ -74,6 +77,7 @@ function drawCircles(painter: Painter, sourceCache: SourceCache, layer: CircleSt
|
|
|
74
77
|
layoutVertexBuffer,
|
|
75
78
|
indexBuffer,
|
|
76
79
|
uniformValues,
|
|
80
|
+
terrainData
|
|
77
81
|
};
|
|
78
82
|
|
|
79
83
|
if (sortFeaturesByKey) {
|
|
@@ -100,11 +104,11 @@ function drawCircles(painter: Painter, sourceCache: SourceCache, layer: CircleSt
|
|
|
100
104
|
}
|
|
101
105
|
|
|
102
106
|
for (const segmentsState of segmentsRenderStates) {
|
|
103
|
-
const {programConfiguration, program, layoutVertexBuffer, indexBuffer, uniformValues} = segmentsState.state;
|
|
107
|
+
const {programConfiguration, program, layoutVertexBuffer, indexBuffer, uniformValues, terrainData} = segmentsState.state;
|
|
104
108
|
const segments = segmentsState.segments;
|
|
105
109
|
|
|
106
110
|
program.draw(context, gl.TRIANGLES, depthMode, stencilMode, colorMode, CullFaceMode.disabled,
|
|
107
|
-
uniformValues, layer.id,
|
|
111
|
+
uniformValues, terrainData, layer.id,
|
|
108
112
|
layoutVertexBuffer, indexBuffer, segments,
|
|
109
113
|
layer.paint, painter.transform.zoom, programConfiguration);
|
|
110
114
|
}
|
|
@@ -22,6 +22,7 @@ type TileBatch = {
|
|
|
22
22
|
circleOffset: number;
|
|
23
23
|
transform: mat4;
|
|
24
24
|
invTransform: mat4;
|
|
25
|
+
coord: OverscaledTileID;
|
|
25
26
|
};
|
|
26
27
|
|
|
27
28
|
let quadTriangles: QuadTriangleArray;
|
|
@@ -60,7 +61,8 @@ function drawCollisionDebug(painter: Painter, sourceCache: SourceCache, layer: S
|
|
|
60
61
|
circleArray,
|
|
61
62
|
circleOffset,
|
|
62
63
|
transform,
|
|
63
|
-
invTransform
|
|
64
|
+
invTransform,
|
|
65
|
+
coord
|
|
64
66
|
});
|
|
65
67
|
|
|
66
68
|
circleCount += circleArray.length / 4; // 4 values per circle
|
|
@@ -75,6 +77,7 @@ function drawCollisionDebug(painter: Painter, sourceCache: SourceCache, layer: S
|
|
|
75
77
|
posMatrix,
|
|
76
78
|
painter.transform,
|
|
77
79
|
tile),
|
|
80
|
+
painter.style.terrain && painter.style.terrain.getTerrainData(coord),
|
|
78
81
|
layer.id, buffers.layoutVertexBuffer, buffers.indexBuffer,
|
|
79
82
|
buffers.segments, null, painter.transform.zoom, null, null,
|
|
80
83
|
buffers.collisionVertexBuffer);
|
|
@@ -132,6 +135,7 @@ function drawCollisionDebug(painter: Painter, sourceCache: SourceCache, layer: S
|
|
|
132
135
|
painter.colorModeForRenderPass(),
|
|
133
136
|
CullFaceMode.disabled,
|
|
134
137
|
uniforms,
|
|
138
|
+
painter.style.terrain && painter.style.terrain.getTerrainData(batch.coord),
|
|
135
139
|
layer.id,
|
|
136
140
|
vertexBuffer,
|
|
137
141
|
indexBuffer,
|
package/src/render/draw_debug.ts
CHANGED
|
@@ -77,15 +77,12 @@ function drawDebugTile(painter, sourceCache, coord: OverscaledTileID) {
|
|
|
77
77
|
const stencilMode = StencilMode.disabled;
|
|
78
78
|
const colorMode = painter.colorModeForRenderPass();
|
|
79
79
|
const id = '$debug';
|
|
80
|
+
const terrainData = painter.style.terrain && painter.style.terrain.getTerrainData(coord);
|
|
80
81
|
|
|
81
82
|
context.activeTexture.set(gl.TEXTURE0);
|
|
82
83
|
// Bind the empty texture for drawing outlines
|
|
83
84
|
painter.emptyTexture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);
|
|
84
85
|
|
|
85
|
-
program.draw(context, gl.LINE_STRIP, depthMode, stencilMode, colorMode, CullFaceMode.disabled,
|
|
86
|
-
debugUniformValues(posMatrix, Color.red), id,
|
|
87
|
-
painter.debugBuffer, painter.tileBorderIndexBuffer, painter.debugSegments);
|
|
88
|
-
|
|
89
86
|
const tileRawData = sourceCache.getTileByID(coord.key).latestRawTileData;
|
|
90
87
|
const tileByteLength = (tileRawData && tileRawData.byteLength) || 0;
|
|
91
88
|
const tileSizeKb = Math.floor(tileByteLength / 1024);
|
|
@@ -99,8 +96,11 @@ function drawDebugTile(painter, sourceCache, coord: OverscaledTileID) {
|
|
|
99
96
|
drawTextToOverlay(painter, tileLabel);
|
|
100
97
|
|
|
101
98
|
program.draw(context, gl.TRIANGLES, depthMode, stencilMode, ColorMode.alphaBlended, CullFaceMode.disabled,
|
|
102
|
-
debugUniformValues(posMatrix, Color.transparent, scaleRatio), id,
|
|
99
|
+
debugUniformValues(posMatrix, Color.transparent, scaleRatio), null, id,
|
|
103
100
|
painter.debugBuffer, painter.quadTriangleIndexBuffer, painter.debugSegments);
|
|
101
|
+
program.draw(context, gl.LINE_STRIP, depthMode, stencilMode, colorMode, CullFaceMode.disabled,
|
|
102
|
+
debugUniformValues(posMatrix, Color.red), terrainData, id,
|
|
103
|
+
painter.debugBuffer, painter.tileBorderIndexBuffer, painter.debugSegments);
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
function drawTextToOverlay(painter: Painter, text: string) {
|
package/src/render/draw_fill.ts
CHANGED
|
@@ -81,6 +81,7 @@ function drawFillTiles(painter, sourceCache, layer, coords, depthMode, colorMode
|
|
|
81
81
|
|
|
82
82
|
const programConfiguration = bucket.programConfigurations.get(layer.id);
|
|
83
83
|
const program = painter.useProgram(programName, programConfiguration);
|
|
84
|
+
const terrainData = painter.style.terrain && painter.style.terrain.getTerrainData(coord);
|
|
84
85
|
|
|
85
86
|
if (image) {
|
|
86
87
|
painter.context.activeTexture.set(gl.TEXTURE0);
|
|
@@ -96,7 +97,9 @@ function drawFillTiles(painter, sourceCache, layer, coords, depthMode, colorMode
|
|
|
96
97
|
if (posTo && posFrom) programConfiguration.setConstantPatternPositions(posTo, posFrom);
|
|
97
98
|
}
|
|
98
99
|
|
|
99
|
-
const
|
|
100
|
+
const terrainCoord = terrainData ? coord : null;
|
|
101
|
+
const posMatrix = terrainCoord ? terrainCoord.posMatrix : coord.posMatrix;
|
|
102
|
+
const tileMatrix = painter.translatePosMatrix(posMatrix, tile,
|
|
100
103
|
layer.paint.get('fill-translate'), layer.paint.get('fill-translate-anchor'));
|
|
101
104
|
|
|
102
105
|
if (!isOutline) {
|
|
@@ -115,7 +118,7 @@ function drawFillTiles(painter, sourceCache, layer, coords, depthMode, colorMode
|
|
|
115
118
|
}
|
|
116
119
|
|
|
117
120
|
program.draw(painter.context, drawMode, depthMode,
|
|
118
|
-
painter.stencilModeForClipping(coord), colorMode, CullFaceMode.disabled, uniformValues,
|
|
121
|
+
painter.stencilModeForClipping(coord), colorMode, CullFaceMode.disabled, uniformValues, terrainData,
|
|
119
122
|
layer.id, bucket.layoutVertexBuffer, indexBuffer, segments,
|
|
120
123
|
layer.paint, painter.transform.zoom, programConfiguration);
|
|
121
124
|
}
|