@deck.gl/core 9.2.11 → 9.3.0-alpha.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/debug.min.js +1 -1
- package/dist/controllers/controller.d.ts +10 -0
- package/dist/controllers/controller.d.ts.map +1 -1
- package/dist/controllers/controller.js +15 -0
- package/dist/controllers/controller.js.map +1 -1
- package/dist/controllers/first-person-controller.d.ts +3 -2
- package/dist/controllers/first-person-controller.d.ts.map +1 -1
- package/dist/controllers/first-person-controller.js +13 -5
- package/dist/controllers/first-person-controller.js.map +1 -1
- package/dist/controllers/globe-controller.d.ts +1 -0
- package/dist/controllers/globe-controller.d.ts.map +1 -1
- package/dist/controllers/globe-controller.js +66 -5
- package/dist/controllers/globe-controller.js.map +1 -1
- package/dist/controllers/map-controller.d.ts +21 -3
- package/dist/controllers/map-controller.d.ts.map +1 -1
- package/dist/controllers/map-controller.js +139 -25
- package/dist/controllers/map-controller.js.map +1 -1
- package/dist/controllers/orbit-controller.d.ts +12 -4
- package/dist/controllers/orbit-controller.d.ts.map +1 -1
- package/dist/controllers/orbit-controller.js +118 -10
- package/dist/controllers/orbit-controller.js.map +1 -1
- package/dist/controllers/orthographic-controller.d.ts +117 -9
- package/dist/controllers/orthographic-controller.d.ts.map +1 -1
- package/dist/controllers/orthographic-controller.js +302 -37
- package/dist/controllers/orthographic-controller.js.map +1 -1
- package/dist/controllers/view-state.d.ts +4 -1
- package/dist/controllers/view-state.d.ts.map +1 -1
- package/dist/controllers/view-state.js +2 -1
- package/dist/controllers/view-state.js.map +1 -1
- package/dist/debug/loggers.d.ts.map +1 -1
- package/dist/debug/loggers.js +1 -4
- package/dist/debug/loggers.js.map +1 -1
- package/dist/dist.dev.js +7585 -10714
- package/dist/effects/lighting/lighting-effect.d.ts +1 -0
- package/dist/effects/lighting/lighting-effect.d.ts.map +1 -1
- package/dist/effects/lighting/lighting-effect.js +14 -5
- package/dist/effects/lighting/lighting-effect.js.map +1 -1
- package/dist/index.cjs +812 -120
- package/dist/index.cjs.map +4 -4
- package/dist/lib/attribute/attribute-manager.d.ts.map +1 -1
- package/dist/lib/attribute/attribute-manager.js +2 -0
- package/dist/lib/attribute/attribute-manager.js.map +1 -1
- package/dist/lib/attribute/data-column.js +2 -2
- package/dist/lib/attribute/data-column.js.map +1 -1
- package/dist/lib/attribute/gl-utils.d.ts +1 -1
- package/dist/lib/attribute/gl-utils.d.ts.map +1 -1
- package/dist/lib/attribute/gl-utils.js +4 -0
- package/dist/lib/attribute/gl-utils.js.map +1 -1
- package/dist/lib/deck-picker.d.ts +14 -1
- package/dist/lib/deck-picker.d.ts.map +1 -1
- package/dist/lib/deck-picker.js +43 -11
- package/dist/lib/deck-picker.js.map +1 -1
- package/dist/lib/deck-renderer.d.ts +6 -1
- package/dist/lib/deck-renderer.d.ts.map +1 -1
- package/dist/lib/deck-renderer.js +14 -2
- package/dist/lib/deck-renderer.js.map +1 -1
- package/dist/lib/deck.d.ts +10 -0
- package/dist/lib/deck.d.ts.map +1 -1
- package/dist/lib/deck.js +29 -11
- package/dist/lib/deck.js.map +1 -1
- package/dist/lib/init.js +2 -2
- package/dist/lib/init.js.map +1 -1
- package/dist/lib/layer.d.ts.map +1 -1
- package/dist/lib/layer.js +7 -3
- package/dist/lib/layer.js.map +1 -1
- package/dist/lib/view-manager.d.ts +4 -0
- package/dist/lib/view-manager.d.ts.map +1 -1
- package/dist/lib/view-manager.js +6 -1
- package/dist/lib/view-manager.js.map +1 -1
- package/dist/lib/widget.d.ts +4 -0
- package/dist/lib/widget.d.ts.map +1 -1
- package/dist/lib/widget.js +11 -0
- package/dist/lib/widget.js.map +1 -1
- package/dist/passes/draw-layers-pass.d.ts +2 -0
- package/dist/passes/draw-layers-pass.d.ts.map +1 -1
- package/dist/passes/draw-layers-pass.js +3 -0
- package/dist/passes/draw-layers-pass.js.map +1 -1
- package/dist/passes/layers-pass.d.ts +2 -1
- package/dist/passes/layers-pass.d.ts.map +1 -1
- package/dist/passes/layers-pass.js +7 -3
- package/dist/passes/layers-pass.js.map +1 -1
- package/dist/passes/pick-layers-pass.d.ts +6 -3
- package/dist/passes/pick-layers-pass.d.ts.map +1 -1
- package/dist/passes/pick-layers-pass.js +12 -4
- package/dist/passes/pick-layers-pass.js.map +1 -1
- package/dist/shaderlib/project/project.glsl.d.ts.map +1 -1
- package/dist/shaderlib/project/project.glsl.js +3 -0
- package/dist/shaderlib/project/project.glsl.js.map +1 -1
- package/dist/utils/deep-merge.d.ts +5 -0
- package/dist/utils/deep-merge.d.ts.map +1 -0
- package/dist/utils/deep-merge.js +31 -0
- package/dist/utils/deep-merge.js.map +1 -0
- package/dist/utils/math-utils.d.ts +4 -0
- package/dist/utils/math-utils.d.ts.map +1 -1
- package/dist/utils/math-utils.js +8 -0
- package/dist/utils/math-utils.js.map +1 -1
- package/dist/utils/texture.d.ts.map +1 -1
- package/dist/utils/texture.js +3 -1
- package/dist/utils/texture.js.map +1 -1
- package/dist/viewports/globe-viewport.d.ts +1 -0
- package/dist/viewports/globe-viewport.d.ts.map +1 -1
- package/dist/viewports/globe-viewport.js +1 -1
- package/dist/viewports/globe-viewport.js.map +1 -1
- package/dist/viewports/orbit-viewport.d.ts.map +1 -1
- package/dist/viewports/orbit-viewport.js +7 -2
- package/dist/viewports/orbit-viewport.js.map +1 -1
- package/dist/viewports/orthographic-viewport.d.ts +8 -2
- package/dist/viewports/orthographic-viewport.d.ts.map +1 -1
- package/dist/viewports/orthographic-viewport.js.map +1 -1
- package/dist/viewports/web-mercator-viewport.d.ts +5 -0
- package/dist/viewports/web-mercator-viewport.d.ts.map +1 -1
- package/dist/viewports/web-mercator-viewport.js +9 -0
- package/dist/viewports/web-mercator-viewport.js.map +1 -1
- package/dist/views/orthographic-view.d.ts +38 -4
- package/dist/views/orthographic-view.d.ts.map +1 -1
- package/dist/views/orthographic-view.js.map +1 -1
- package/dist/views/view.d.ts.map +1 -1
- package/dist/views/view.js +2 -8
- package/dist/views/view.js.map +1 -1
- package/dist.min.js +226 -154
- package/package.json +9 -9
- package/src/controllers/controller.ts +25 -2
- package/src/controllers/first-person-controller.ts +18 -8
- package/src/controllers/globe-controller.ts +89 -5
- package/src/controllers/map-controller.ts +174 -32
- package/src/controllers/orbit-controller.ts +147 -13
- package/src/controllers/orthographic-controller.ts +417 -41
- package/src/controllers/view-state.ts +10 -3
- package/src/debug/loggers.ts +1 -5
- package/src/effects/lighting/lighting-effect.ts +20 -8
- package/src/lib/attribute/attribute-manager.ts +1 -0
- package/src/lib/attribute/data-column.ts +3 -3
- package/src/lib/attribute/gl-utils.ts +5 -1
- package/src/lib/deck-picker.ts +47 -12
- package/src/lib/deck-renderer.ts +17 -3
- package/src/lib/deck.ts +39 -11
- package/src/lib/layer.ts +7 -3
- package/src/lib/view-manager.ts +9 -1
- package/src/lib/widget.ts +14 -0
- package/src/passes/draw-layers-pass.ts +5 -0
- package/src/passes/layers-pass.ts +9 -4
- package/src/passes/pick-layers-pass.ts +18 -6
- package/src/shaderlib/project/project.glsl.ts +3 -0
- package/src/utils/deep-merge.ts +33 -0
- package/src/utils/math-utils.ts +12 -0
- package/src/utils/texture.ts +3 -1
- package/src/viewports/globe-viewport.ts +1 -1
- package/src/viewports/orbit-viewport.ts +8 -2
- package/src/viewports/orthographic-viewport.ts +8 -2
- package/src/viewports/web-mercator-viewport.ts +10 -0
- package/src/views/orthographic-view.ts +38 -4
- package/src/views/view.ts +2 -8
package/src/lib/deck-picker.ts
CHANGED
|
@@ -11,7 +11,8 @@ import {
|
|
|
11
11
|
getEmptyPickingInfo,
|
|
12
12
|
PickingInfo
|
|
13
13
|
} from './picking/pick-info';
|
|
14
|
-
|
|
14
|
+
import type {RenderStats} from '../passes/layers-pass';
|
|
15
|
+
import type {Stats} from '@probe.gl/stats';
|
|
15
16
|
import type {Framebuffer} from '@luma.gl/core';
|
|
16
17
|
import type {FilterContext, Rect} from '../passes/layers-pass';
|
|
17
18
|
import type Layer from './layer';
|
|
@@ -52,6 +53,7 @@ export default class DeckPicker {
|
|
|
52
53
|
depthFBO?: Framebuffer;
|
|
53
54
|
pickLayersPass: PickLayersPass;
|
|
54
55
|
layerFilter?: (context: FilterContext) => boolean;
|
|
56
|
+
stats?: Stats;
|
|
55
57
|
|
|
56
58
|
/** Identifiers of the previously picked object, for callback tracking and auto highlight */
|
|
57
59
|
lastPickedInfo: {
|
|
@@ -62,8 +64,9 @@ export default class DeckPicker {
|
|
|
62
64
|
|
|
63
65
|
_pickable: boolean = true;
|
|
64
66
|
|
|
65
|
-
constructor(device: Device) {
|
|
67
|
+
constructor(device: Device, opts: {stats?: Stats} = {}) {
|
|
66
68
|
this.device = device;
|
|
69
|
+
this.stats = opts.stats;
|
|
67
70
|
this.pickLayersPass = new PickLayersPass(device);
|
|
68
71
|
this.lastPickedInfo = {
|
|
69
72
|
index: -1,
|
|
@@ -281,16 +284,17 @@ export default class DeckPicker {
|
|
|
281
284
|
}
|
|
282
285
|
|
|
283
286
|
let z;
|
|
284
|
-
|
|
287
|
+
const depthLayers = this._getDepthLayers(pickInfo, pickableLayers, unproject3D);
|
|
288
|
+
if (depthLayers.length > 0) {
|
|
285
289
|
const {pickedColors: pickedColors2} = this._drawAndSample(
|
|
286
290
|
{
|
|
287
|
-
layers:
|
|
291
|
+
layers: depthLayers,
|
|
288
292
|
views,
|
|
289
293
|
viewports,
|
|
290
294
|
onViewportActive,
|
|
291
295
|
deviceRect: {
|
|
292
|
-
x: pickInfo.pickedX
|
|
293
|
-
y: pickInfo.pickedY
|
|
296
|
+
x: pickInfo.pickedX ?? devicePixel[0],
|
|
297
|
+
y: pickInfo.pickedY ?? devicePixel[1],
|
|
294
298
|
width: 1,
|
|
295
299
|
height: 1
|
|
296
300
|
},
|
|
@@ -444,16 +448,17 @@ export default class DeckPicker {
|
|
|
444
448
|
}
|
|
445
449
|
|
|
446
450
|
let z;
|
|
447
|
-
|
|
451
|
+
const depthLayers = this._getDepthLayers(pickInfo, pickableLayers, unproject3D);
|
|
452
|
+
if (depthLayers.length > 0) {
|
|
448
453
|
const {pickedColors: pickedColors2} = this._drawAndSample(
|
|
449
454
|
{
|
|
450
|
-
layers:
|
|
455
|
+
layers: depthLayers,
|
|
451
456
|
views,
|
|
452
457
|
viewports,
|
|
453
458
|
onViewportActive,
|
|
454
459
|
deviceRect: {
|
|
455
|
-
x: pickInfo.pickedX
|
|
456
|
-
y: pickInfo.pickedY
|
|
460
|
+
x: pickInfo.pickedX ?? devicePixel[0],
|
|
461
|
+
y: pickInfo.pickedY ?? devicePixel[1],
|
|
457
462
|
width: 1,
|
|
458
463
|
height: 1
|
|
459
464
|
},
|
|
@@ -806,7 +811,8 @@ export default class DeckPicker {
|
|
|
806
811
|
}
|
|
807
812
|
}
|
|
808
813
|
|
|
809
|
-
const {decodePickingColor} = this.pickLayersPass.render(opts);
|
|
814
|
+
const {decodePickingColor, stats} = this.pickLayersPass.render(opts);
|
|
815
|
+
this._updateStats(stats);
|
|
810
816
|
|
|
811
817
|
// Read from an already rendered picking buffer
|
|
812
818
|
// Returns an Uint8ClampedArray of picked pixels
|
|
@@ -911,7 +917,8 @@ export default class DeckPicker {
|
|
|
911
917
|
}
|
|
912
918
|
}
|
|
913
919
|
|
|
914
|
-
const {decodePickingColor} = this.pickLayersPass.render(opts);
|
|
920
|
+
const {decodePickingColor, stats} = this.pickLayersPass.render(opts);
|
|
921
|
+
this._updateStats(stats);
|
|
915
922
|
|
|
916
923
|
// Read from an already rendered picking buffer
|
|
917
924
|
// Returns an Uint8ClampedArray of picked pixels
|
|
@@ -928,6 +935,34 @@ export default class DeckPicker {
|
|
|
928
935
|
return {pickedColors, decodePickingColor};
|
|
929
936
|
}
|
|
930
937
|
|
|
938
|
+
private _updateStats(source: RenderStats[]) {
|
|
939
|
+
if (!this.stats) return;
|
|
940
|
+
let layersCount = 0;
|
|
941
|
+
for (const {visibleCount} of source) {
|
|
942
|
+
layersCount += visibleCount;
|
|
943
|
+
}
|
|
944
|
+
this.stats.get('Layers picked').addCount(layersCount);
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
/**
|
|
948
|
+
* Determine which layers to use for the depth (pickZ) pass.
|
|
949
|
+
* - If a non-draped layer was picked, use just that layer.
|
|
950
|
+
* - If a draped layer was picked (geometry is at z=0) or no layer was picked
|
|
951
|
+
* (e.g. no-FBO tiles at extreme zoom), fall back to terrain layers.
|
|
952
|
+
*/
|
|
953
|
+
_getDepthLayers(pickInfo: PickedPixel, pickableLayers: Layer[], unproject3D?: boolean): Layer[] {
|
|
954
|
+
if (!unproject3D || !this.depthFBO) {
|
|
955
|
+
return [];
|
|
956
|
+
}
|
|
957
|
+
const {pickedLayer} = pickInfo;
|
|
958
|
+
const isDraped = pickedLayer?.state?.terrainDrawMode === 'drape';
|
|
959
|
+
if (pickedLayer && !isDraped) {
|
|
960
|
+
return [pickedLayer];
|
|
961
|
+
}
|
|
962
|
+
// For draped layers or when no layer was picked, use terrain layers for depth
|
|
963
|
+
return pickableLayers.filter(l => l.props.operation.includes('terrain'));
|
|
964
|
+
}
|
|
965
|
+
|
|
931
966
|
/**
|
|
932
967
|
* Calculate a picking rect centered on deviceX and deviceY and clipped to device
|
|
933
968
|
* @returns null if pixel is outside of device
|
package/src/lib/deck-renderer.ts
CHANGED
|
@@ -7,7 +7,8 @@ import {Framebuffer} from '@luma.gl/core';
|
|
|
7
7
|
import debug from '../debug/index';
|
|
8
8
|
import DrawLayersPass from '../passes/draw-layers-pass';
|
|
9
9
|
import PickLayersPass from '../passes/pick-layers-pass';
|
|
10
|
-
|
|
10
|
+
import type {RenderStats} from '../passes/layers-pass';
|
|
11
|
+
import type {Stats} from '@probe.gl/stats';
|
|
11
12
|
import type Layer from './layer';
|
|
12
13
|
import type Viewport from '../viewports/viewport';
|
|
13
14
|
import type View from '../views/view';
|
|
@@ -24,14 +25,16 @@ export default class DeckRenderer {
|
|
|
24
25
|
drawPickingColors: boolean;
|
|
25
26
|
drawLayersPass: DrawLayersPass;
|
|
26
27
|
pickLayersPass: PickLayersPass;
|
|
28
|
+
stats?: Stats;
|
|
27
29
|
|
|
28
30
|
private renderCount: number;
|
|
29
31
|
private _needsRedraw: string | false;
|
|
30
32
|
private renderBuffers: Framebuffer[];
|
|
31
33
|
private lastPostProcessEffect: string | null;
|
|
32
34
|
|
|
33
|
-
constructor(device: Device) {
|
|
35
|
+
constructor(device: Device, opts: {stats?: Stats} = {}) {
|
|
34
36
|
this.device = device;
|
|
37
|
+
this.stats = opts.stats;
|
|
35
38
|
this.layerFilter = null;
|
|
36
39
|
this.drawPickingColors = false;
|
|
37
40
|
this.drawLayersPass = new DrawLayersPass(device);
|
|
@@ -88,7 +91,8 @@ export default class DeckRenderer {
|
|
|
88
91
|
renderOpts.clearColor = [0, 0, 0, 0];
|
|
89
92
|
renderOpts.clearCanvas = true;
|
|
90
93
|
}
|
|
91
|
-
const
|
|
94
|
+
const renderResult = layerPass.render({...renderOpts, target: outputBuffer});
|
|
95
|
+
const renderStats = 'stats' in renderResult ? renderResult.stats : renderResult;
|
|
92
96
|
|
|
93
97
|
if (renderOpts.effects) {
|
|
94
98
|
if (this.lastPostProcessEffect) {
|
|
@@ -102,6 +106,7 @@ export default class DeckRenderer {
|
|
|
102
106
|
this.renderCount++;
|
|
103
107
|
|
|
104
108
|
debug(TRACE_RENDER_LAYERS, this, renderStats, opts);
|
|
109
|
+
this._updateStats(renderStats);
|
|
105
110
|
}
|
|
106
111
|
|
|
107
112
|
needsRedraw(opts: {clearRedrawFlags: boolean} = {clearRedrawFlags: false}): string | false {
|
|
@@ -120,6 +125,15 @@ export default class DeckRenderer {
|
|
|
120
125
|
renderBuffers.length = 0;
|
|
121
126
|
}
|
|
122
127
|
|
|
128
|
+
private _updateStats(source: RenderStats[]) {
|
|
129
|
+
if (!this.stats) return;
|
|
130
|
+
let layersCount = 0;
|
|
131
|
+
for (const {visibleCount} of source) {
|
|
132
|
+
layersCount += visibleCount;
|
|
133
|
+
}
|
|
134
|
+
this.stats.get('Layers rendered').addCount(layersCount);
|
|
135
|
+
}
|
|
136
|
+
|
|
123
137
|
private _preRender(effects: Effect[], opts: LayersPassRenderOptions) {
|
|
124
138
|
this.lastPostProcessEffect = null;
|
|
125
139
|
opts.preRenderStats = opts.preRenderStats || {};
|
package/src/lib/deck.ts
CHANGED
|
@@ -55,10 +55,15 @@ const getCursor = ({isDragging}) => (isDragging ? 'grabbing' : 'grab');
|
|
|
55
55
|
export type DeckMetrics = {
|
|
56
56
|
fps: number;
|
|
57
57
|
setPropsTime: number;
|
|
58
|
+
layersCount: number;
|
|
59
|
+
drawLayersCount: number;
|
|
60
|
+
updateLayersCount: number;
|
|
58
61
|
updateAttributesTime: number;
|
|
62
|
+
updateAttributesCount: number;
|
|
59
63
|
framesRedrawn: number;
|
|
60
64
|
pickTime: number;
|
|
61
65
|
pickCount: number;
|
|
66
|
+
pickLayersCount: number;
|
|
62
67
|
gpuTime: number;
|
|
63
68
|
gpuTimePerFrame: number;
|
|
64
69
|
cpuTime: number;
|
|
@@ -309,10 +314,15 @@ export default class Deck<ViewsT extends ViewOrViews = null> {
|
|
|
309
314
|
protected metrics: DeckMetrics = {
|
|
310
315
|
fps: 0,
|
|
311
316
|
setPropsTime: 0,
|
|
317
|
+
layersCount: 0,
|
|
318
|
+
drawLayersCount: 0,
|
|
319
|
+
updateLayersCount: 0,
|
|
320
|
+
updateAttributesCount: 0,
|
|
312
321
|
updateAttributesTime: 0,
|
|
313
322
|
framesRedrawn: 0,
|
|
314
323
|
pickTime: 0,
|
|
315
324
|
pickCount: 0,
|
|
325
|
+
pickLayersCount: 0,
|
|
316
326
|
gpuTime: 0,
|
|
317
327
|
gpuTimePerFrame: 0,
|
|
318
328
|
cpuTime: 0,
|
|
@@ -381,13 +391,9 @@ export default class Deck<ViewsT extends ViewOrViews = null> {
|
|
|
381
391
|
_cachePipelines: true,
|
|
382
392
|
...this.props.deviceProps,
|
|
383
393
|
onResize: (canvasContext, info) => {
|
|
384
|
-
//
|
|
385
|
-
// TODO(v9.3): Use canvasContext.setDrawingBufferSize(width, height) when upgrading to luma 9.3+
|
|
394
|
+
// Sync drawing buffer dimensions with externally-managed canvas
|
|
386
395
|
const {width, height} = canvasContext.canvas;
|
|
387
|
-
|
|
388
|
-
canvasContext.drawingBufferWidth = width;
|
|
389
|
-
// @ts-ignore
|
|
390
|
-
canvasContext.drawingBufferHeight = height;
|
|
396
|
+
canvasContext.setDrawingBufferSize(width, height);
|
|
391
397
|
|
|
392
398
|
this._needsRedraw = 'Canvas resized';
|
|
393
399
|
userOnResize?.(canvasContext, info);
|
|
@@ -678,6 +684,15 @@ export default class Deck<ViewsT extends ViewOrViews = null> {
|
|
|
678
684
|
return this._pick('pickObjects', 'pickObjects Time', opts);
|
|
679
685
|
}
|
|
680
686
|
|
|
687
|
+
/**
|
|
688
|
+
* Internal method used by controllers to pick 3D position at a screen coordinate
|
|
689
|
+
* @private
|
|
690
|
+
*/
|
|
691
|
+
private _pickPositionForController(x: number, y: number): {coordinate?: number[]} | null {
|
|
692
|
+
const pickResult = this.pickObject({x, y, radius: 0, unproject3D: true});
|
|
693
|
+
return pickResult;
|
|
694
|
+
}
|
|
695
|
+
|
|
681
696
|
/** Experimental
|
|
682
697
|
* Add a global resource for sharing among layers
|
|
683
698
|
*/
|
|
@@ -1072,7 +1087,9 @@ export default class Deck<ViewsT extends ViewOrViews = null> {
|
|
|
1072
1087
|
timeline.play();
|
|
1073
1088
|
this.animationLoop.attachTimeline(timeline);
|
|
1074
1089
|
|
|
1075
|
-
|
|
1090
|
+
const eventRoot =
|
|
1091
|
+
this.props.parent?.querySelector<HTMLDivElement>('.deck-events-root') || this.canvas;
|
|
1092
|
+
this.eventManager = new EventManager(eventRoot, {
|
|
1076
1093
|
touchAction: this.props.touchAction,
|
|
1077
1094
|
recognizers: Object.keys(RECOGNIZERS).map((eventName: string) => {
|
|
1078
1095
|
// Resolve recognizer settings
|
|
@@ -1101,6 +1118,7 @@ export default class Deck<ViewsT extends ViewOrViews = null> {
|
|
|
1101
1118
|
eventManager: this.eventManager,
|
|
1102
1119
|
onViewStateChange: this._onViewStateChange.bind(this),
|
|
1103
1120
|
onInteractionStateChange: this._onInteractionStateChange.bind(this),
|
|
1121
|
+
pickPosition: this._pickPositionForController.bind(this),
|
|
1104
1122
|
views: this._getViews(),
|
|
1105
1123
|
viewState: this._getViewState(),
|
|
1106
1124
|
width: this.width,
|
|
@@ -1124,13 +1142,17 @@ export default class Deck<ViewsT extends ViewOrViews = null> {
|
|
|
1124
1142
|
device: this.device
|
|
1125
1143
|
});
|
|
1126
1144
|
|
|
1127
|
-
this.deckRenderer = new DeckRenderer(this.device);
|
|
1145
|
+
this.deckRenderer = new DeckRenderer(this.device, {stats: this.stats});
|
|
1146
|
+
|
|
1147
|
+
this.deckPicker = new DeckPicker(this.device, {stats: this.stats});
|
|
1128
1148
|
|
|
1129
|
-
|
|
1149
|
+
const widgetParent =
|
|
1150
|
+
this.props.parent?.querySelector<HTMLDivElement>('.deck-widgets-root') ||
|
|
1151
|
+
this.canvas?.parentElement;
|
|
1130
1152
|
|
|
1131
1153
|
this.widgetManager = new WidgetManager({
|
|
1132
1154
|
deck: this,
|
|
1133
|
-
parentElement:
|
|
1155
|
+
parentElement: widgetParent
|
|
1134
1156
|
});
|
|
1135
1157
|
this.widgetManager.addDefault(new TooltipWidget());
|
|
1136
1158
|
|
|
@@ -1337,13 +1359,19 @@ export default class Deck<ViewsT extends ViewOrViews = null> {
|
|
|
1337
1359
|
stats.get('pickObjects Time').time;
|
|
1338
1360
|
metrics.pickCount = stats.get('Pick Count').count;
|
|
1339
1361
|
|
|
1362
|
+
metrics.layersCount = this.layerManager?.layers.length ?? 0;
|
|
1363
|
+
metrics.drawLayersCount = stats.get('Layers rendered').lastSampleCount;
|
|
1364
|
+
metrics.pickLayersCount = stats.get('Layers picked').lastSampleCount;
|
|
1365
|
+
metrics.updateAttributesCount = stats.get('Layers updated').count;
|
|
1366
|
+
metrics.updateAttributesCount = stats.get('Attributes updated').count;
|
|
1367
|
+
|
|
1340
1368
|
// Luma stats
|
|
1341
1369
|
metrics.gpuTime = stats.get('GPU Time').time;
|
|
1342
1370
|
metrics.cpuTime = stats.get('CPU Time').time;
|
|
1343
1371
|
metrics.gpuTimePerFrame = stats.get('GPU Time').getAverageTime();
|
|
1344
1372
|
metrics.cpuTimePerFrame = stats.get('CPU Time').getAverageTime();
|
|
1345
1373
|
|
|
1346
|
-
const memoryStats = luma.stats.get('Memory
|
|
1374
|
+
const memoryStats = luma.stats.get('GPU Time and Memory');
|
|
1347
1375
|
metrics.bufferMemory = memoryStats.get('Buffer Memory').count;
|
|
1348
1376
|
metrics.textureMemory = memoryStats.get('Texture Memory').count;
|
|
1349
1377
|
metrics.renderbufferMemory = memoryStats.get('Renderbuffer Memory').count;
|
package/src/lib/layer.ts
CHANGED
|
@@ -96,9 +96,12 @@ const defaultProps: DefaultProps<LayerProps> = {
|
|
|
96
96
|
if (signal) {
|
|
97
97
|
loadOptions = {
|
|
98
98
|
...loadOptions,
|
|
99
|
-
|
|
100
|
-
...loadOptions?.
|
|
101
|
-
|
|
99
|
+
core: {
|
|
100
|
+
...loadOptions?.core,
|
|
101
|
+
fetch: {
|
|
102
|
+
...loadOptions?.core?.fetch,
|
|
103
|
+
signal
|
|
104
|
+
}
|
|
102
105
|
}
|
|
103
106
|
};
|
|
104
107
|
}
|
|
@@ -966,6 +969,7 @@ export default abstract class Layer<PropsT extends {} = {}> extends Component<
|
|
|
966
969
|
if (!stateNeedsUpdate) {
|
|
967
970
|
return;
|
|
968
971
|
}
|
|
972
|
+
this.context.stats.get('Layer updates').incrementCount();
|
|
969
973
|
|
|
970
974
|
const currentProps = this.props;
|
|
971
975
|
const context = this.context;
|
package/src/lib/view-manager.ts
CHANGED
|
@@ -43,6 +43,7 @@ type ViewManagerProps<ViewsT extends ViewOrViews> = {
|
|
|
43
43
|
viewState: ViewStateObject<ViewsT> | null;
|
|
44
44
|
onViewStateChange?: (params: ViewStateChangeParameters<AnyViewStateOf<ViewsT>>) => void;
|
|
45
45
|
onInteractionStateChange?: (state: InteractionState) => void;
|
|
46
|
+
pickPosition?: (x: number, y: number) => {coordinate?: number[]} | null;
|
|
46
47
|
width?: number;
|
|
47
48
|
height?: number;
|
|
48
49
|
};
|
|
@@ -65,6 +66,7 @@ export default class ViewManager<ViewsT extends View[]> {
|
|
|
65
66
|
onViewStateChange?: (params: ViewStateChangeParameters) => void;
|
|
66
67
|
onInteractionStateChange?: (state: InteractionState) => void;
|
|
67
68
|
};
|
|
69
|
+
private _pickPosition?: (x: number, y: number) => {coordinate?: number[]} | null;
|
|
68
70
|
|
|
69
71
|
constructor(
|
|
70
72
|
props: ViewManagerProps<ViewsT> & {
|
|
@@ -92,6 +94,7 @@ export default class ViewManager<ViewsT extends View[]> {
|
|
|
92
94
|
onViewStateChange: props.onViewStateChange,
|
|
93
95
|
onInteractionStateChange: props.onInteractionStateChange
|
|
94
96
|
};
|
|
97
|
+
this._pickPosition = props.pickPosition;
|
|
95
98
|
|
|
96
99
|
Object.seal(this);
|
|
97
100
|
|
|
@@ -224,6 +227,10 @@ export default class ViewManager<ViewsT extends View[]> {
|
|
|
224
227
|
this._setSize(props.width as number, props.height as number);
|
|
225
228
|
}
|
|
226
229
|
|
|
230
|
+
if ('pickPosition' in props) {
|
|
231
|
+
this._pickPosition = props.pickPosition;
|
|
232
|
+
}
|
|
233
|
+
|
|
227
234
|
// Important: avoid invoking _update() inside itself
|
|
228
235
|
// Nested updates result in unexpected side effects inside _rebuildViewports()
|
|
229
236
|
// when using auto control in pure-js
|
|
@@ -308,7 +315,8 @@ export default class ViewManager<ViewsT extends View[]> {
|
|
|
308
315
|
viewState,
|
|
309
316
|
width: this.width,
|
|
310
317
|
height: this.height
|
|
311
|
-
})
|
|
318
|
+
}),
|
|
319
|
+
pickPosition: this._pickPosition
|
|
312
320
|
});
|
|
313
321
|
|
|
314
322
|
return controller;
|
package/src/lib/widget.ts
CHANGED
|
@@ -98,6 +98,20 @@ export abstract class Widget<
|
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
// VIEW STATE HELPERS
|
|
102
|
+
|
|
103
|
+
/** Returns the current view state for the given view */
|
|
104
|
+
protected getViewState(viewId: string): Record<string, unknown> {
|
|
105
|
+
// @ts-ignore viewManager is private
|
|
106
|
+
return this.deck?.viewManager?.getViewState(viewId) || {};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Updates the view state for the given view */
|
|
110
|
+
protected setViewState(viewId: string, viewState: Record<string, unknown>): void {
|
|
111
|
+
// @ts-ignore Using private method temporary until there's a public one
|
|
112
|
+
this.deck?._onViewStateChange({viewId, viewState, interactionState: {}});
|
|
113
|
+
}
|
|
114
|
+
|
|
101
115
|
// @note empty method calls have an overhead in V8 but it is very low, ~1ns
|
|
102
116
|
|
|
103
117
|
/**
|
|
@@ -3,10 +3,15 @@
|
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
5
|
import LayersPass from './layers-pass';
|
|
6
|
+
import type {LayersPassRenderOptions, RenderStats} from './layers-pass';
|
|
6
7
|
|
|
7
8
|
export default class DrawLayersPass extends LayersPass {
|
|
8
9
|
shouldDrawLayer(layer) {
|
|
9
10
|
const {operation} = layer.props;
|
|
10
11
|
return operation.includes('draw') || operation.includes('terrain');
|
|
11
12
|
}
|
|
13
|
+
|
|
14
|
+
render(options: LayersPassRenderOptions): RenderStats[] {
|
|
15
|
+
return this._render(options);
|
|
16
|
+
}
|
|
12
17
|
}
|
|
@@ -65,9 +65,14 @@ export type RenderStats = {
|
|
|
65
65
|
export default class LayersPass extends Pass {
|
|
66
66
|
_lastRenderIndex: number = -1;
|
|
67
67
|
|
|
68
|
-
render(options: LayersPassRenderOptions):
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
render(options: LayersPassRenderOptions): void {
|
|
69
|
+
this._render(options);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
protected _render(options: LayersPassRenderOptions): RenderStats[] {
|
|
73
|
+
const canvasContext = this.device.canvasContext!;
|
|
74
|
+
const framebuffer = options.target ?? canvasContext.getCurrentFramebuffer();
|
|
75
|
+
const [width, height] = canvasContext.getDrawingBufferSize();
|
|
71
76
|
|
|
72
77
|
// Explicitly specify clearColor and clearDepth, overriding render pass defaults.
|
|
73
78
|
const clearCanvas = options.clearCanvas ?? true;
|
|
@@ -85,7 +90,7 @@ export default class LayersPass extends Pass {
|
|
|
85
90
|
}
|
|
86
91
|
|
|
87
92
|
const renderPass = this.device.beginRenderPass({
|
|
88
|
-
framebuffer
|
|
93
|
+
framebuffer,
|
|
89
94
|
parameters,
|
|
90
95
|
clearColor: clearColor as NumberArray4,
|
|
91
96
|
clearDepth,
|
|
@@ -46,13 +46,17 @@ export default class PickLayersPass extends LayersPass {
|
|
|
46
46
|
byAlpha: EncodedPickingColors[];
|
|
47
47
|
} | null = null;
|
|
48
48
|
|
|
49
|
-
render(props: LayersPassRenderOptions | PickLayersPassRenderOptions) {
|
|
49
|
+
render(props: LayersPassRenderOptions | PickLayersPassRenderOptions): {
|
|
50
|
+
decodePickingColor: PickingColorDecoder | null;
|
|
51
|
+
stats: RenderStats[];
|
|
52
|
+
} {
|
|
50
53
|
if ('pickingFBO' in props) {
|
|
51
54
|
// When drawing into an off-screen buffer, use the alpha channel to encode layer index
|
|
52
55
|
return this._drawPickingBuffer(props);
|
|
53
56
|
}
|
|
54
57
|
// When drawing to screen (debug mode), do not use the alpha channel so that result is always visible
|
|
55
|
-
|
|
58
|
+
const stats = super._render(props);
|
|
59
|
+
return {decodePickingColor: null, stats};
|
|
56
60
|
}
|
|
57
61
|
|
|
58
62
|
// Private
|
|
@@ -70,10 +74,11 @@ export default class PickLayersPass extends LayersPass {
|
|
|
70
74
|
effects,
|
|
71
75
|
pass = 'picking',
|
|
72
76
|
pickZ,
|
|
73
|
-
shaderModuleProps
|
|
77
|
+
shaderModuleProps,
|
|
78
|
+
clearColor
|
|
74
79
|
}: PickLayersPassRenderOptions): {
|
|
75
80
|
decodePickingColor: PickingColorDecoder | null;
|
|
76
|
-
stats: RenderStats;
|
|
81
|
+
stats: RenderStats[];
|
|
77
82
|
} {
|
|
78
83
|
this.pickZ = pickZ;
|
|
79
84
|
const colorEncoderState = this._resetColorEncoder(pickZ);
|
|
@@ -84,7 +89,7 @@ export default class PickLayersPass extends LayersPass {
|
|
|
84
89
|
// Note that the callback here is called synchronously.
|
|
85
90
|
// Set blend mode for picking
|
|
86
91
|
// always overwrite existing pixel with [r,g,b,layerIndex]
|
|
87
|
-
const renderStatus = super.
|
|
92
|
+
const renderStatus = super._render({
|
|
88
93
|
target: pickingFBO,
|
|
89
94
|
layers,
|
|
90
95
|
layerFilter,
|
|
@@ -96,7 +101,7 @@ export default class PickLayersPass extends LayersPass {
|
|
|
96
101
|
pass,
|
|
97
102
|
isPicking: true,
|
|
98
103
|
shaderModuleProps,
|
|
99
|
-
clearColor: [0, 0, 0, 0],
|
|
104
|
+
clearColor: clearColor ?? [0, 0, 0, 0],
|
|
100
105
|
colorMask: 0xf,
|
|
101
106
|
scissorRect
|
|
102
107
|
});
|
|
@@ -145,6 +150,13 @@ export default class PickLayersPass extends LayersPass {
|
|
|
145
150
|
pickParameters.blend = true;
|
|
146
151
|
// TODO: blendColor no longer part of luma.gl API
|
|
147
152
|
pickParameters.blendColor = encodeColor(this._colorEncoderState, layer, viewport);
|
|
153
|
+
if (operation.includes('terrain') && layer.state?._hasPickingCover) {
|
|
154
|
+
// For terrain+draw layers with a valid cover FBO, the terrain shader outputs the
|
|
155
|
+
// cover FBO pixel which already has correctly encoded alpha from the cover encoder.
|
|
156
|
+
// Use srcFactor 'one' to pass through the cover alpha without double-encoding.
|
|
157
|
+
// Without a cover FBO, keep 'constant' so the layer's own picking colors encode correctly.
|
|
158
|
+
pickParameters.blendAlphaSrcFactor = 'one';
|
|
159
|
+
}
|
|
148
160
|
} else if (operation.includes('terrain')) {
|
|
149
161
|
// Pure terrain layers (without 'draw') don't need picking colors
|
|
150
162
|
pickParameters.blend = false;
|
|
@@ -265,6 +265,9 @@ vec2 project_pixel_size_to_clipspace(vec2 pixels) {
|
|
|
265
265
|
float project_size_to_pixel(float meters) {
|
|
266
266
|
return project_size(meters) * project.scale;
|
|
267
267
|
}
|
|
268
|
+
vec2 project_size_to_pixel(vec2 meters) {
|
|
269
|
+
return project_size(meters) * project.scale;
|
|
270
|
+
}
|
|
268
271
|
float project_size_to_pixel(float size, int unit) {
|
|
269
272
|
if (unit == UNIT_METERS) return project_size_to_pixel(size);
|
|
270
273
|
if (unit == UNIT_COMMON) return size * project.scale;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// deck.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
/** Merge two viewstates, except `id`
|
|
6
|
+
* For position arrays such as `target`, only override the components that are defined.
|
|
7
|
+
*/
|
|
8
|
+
export function deepMergeViewState<ViewStateT extends Record<string, any>>(
|
|
9
|
+
a: ViewStateT,
|
|
10
|
+
b: ViewStateT
|
|
11
|
+
): ViewStateT {
|
|
12
|
+
const result = {...a};
|
|
13
|
+
for (const key in b) {
|
|
14
|
+
if (key === 'id') continue;
|
|
15
|
+
if (Array.isArray(result[key]) && Array.isArray(b[key])) {
|
|
16
|
+
result[key] = mergeNumericArray(result[key], b[key]) as any;
|
|
17
|
+
} else {
|
|
18
|
+
result[key] = b[key];
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function mergeNumericArray(target: number[], source: number[]): number[] {
|
|
25
|
+
target = target.slice();
|
|
26
|
+
for (let i = 0; i < source.length; i++) {
|
|
27
|
+
const v = source[i];
|
|
28
|
+
if (Number.isFinite(v)) {
|
|
29
|
+
target[i] = v;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return target;
|
|
33
|
+
}
|
package/src/utils/math-utils.ts
CHANGED
|
@@ -26,6 +26,18 @@ export function getCameraPosition(
|
|
|
26
26
|
return [viewMatrixInverse[12], viewMatrixInverse[13], viewMatrixInverse[14]];
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
export function getProjectionParameters(projectionMatrix: Matrix4 | NumericArray): {
|
|
30
|
+
near: number;
|
|
31
|
+
far: number;
|
|
32
|
+
} {
|
|
33
|
+
const m22 = projectionMatrix[10];
|
|
34
|
+
const m23 = projectionMatrix[14];
|
|
35
|
+
return {
|
|
36
|
+
near: m23 / (m22 - 1),
|
|
37
|
+
far: m23 / (m22 + 1)
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
29
41
|
export type FrustumPlane = {
|
|
30
42
|
distance: number;
|
|
31
43
|
normal: Vector3;
|
package/src/utils/texture.ts
CHANGED
|
@@ -57,7 +57,9 @@ export function createTexture(
|
|
|
57
57
|
},
|
|
58
58
|
mipLevels: device.getMipLevelCount(width, height)
|
|
59
59
|
});
|
|
60
|
-
|
|
60
|
+
if (device.type === 'webgl') {
|
|
61
|
+
texture.generateMipmapsWebGL();
|
|
62
|
+
}
|
|
61
63
|
|
|
62
64
|
// Track this texture
|
|
63
65
|
internalTextures[texture.id] = owner;
|
|
@@ -13,7 +13,7 @@ import {vec3, vec4} from '@math.gl/core';
|
|
|
13
13
|
const DEGREES_TO_RADIANS = Math.PI / 180;
|
|
14
14
|
const RADIANS_TO_DEGREES = 180 / Math.PI;
|
|
15
15
|
const EARTH_RADIUS = 6370972;
|
|
16
|
-
const GLOBE_RADIUS = 256;
|
|
16
|
+
export const GLOBE_RADIUS = 256;
|
|
17
17
|
|
|
18
18
|
function getDistanceScales() {
|
|
19
19
|
const unitsPerMeter = GLOBE_RADIUS / EARTH_RADIUS;
|
|
@@ -6,6 +6,7 @@ import Viewport from '../viewports/viewport';
|
|
|
6
6
|
|
|
7
7
|
import {Matrix4} from '@math.gl/core';
|
|
8
8
|
import {pixelsToWorld, fovyToAltitude} from '@math.gl/web-mercator';
|
|
9
|
+
import {getProjectionParameters} from '../utils/math-utils';
|
|
9
10
|
|
|
10
11
|
const DEGREES_TO_RADIANS = Math.PI / 180;
|
|
11
12
|
|
|
@@ -150,9 +151,14 @@ export default class OrbitViewport extends Viewport {
|
|
|
150
151
|
|
|
151
152
|
panByPosition(coords: number[], pixel: number[], startPixel?: number[]): OrbitViewportOptions {
|
|
152
153
|
const p0 = this.project(coords);
|
|
154
|
+
const {near, far} = getProjectionParameters(this.projectionMatrix);
|
|
155
|
+
const pz = (near * far) / (far - p0[2] * (far - near));
|
|
156
|
+
const centerZ = (near * far) / (far - this.projectedCenter[2] * (far - near));
|
|
157
|
+
const shiftScale = pz / centerZ;
|
|
158
|
+
|
|
153
159
|
const nextCenter = [
|
|
154
|
-
this.width / 2 + p0[0] - pixel[0],
|
|
155
|
-
this.height / 2 + p0[1] - pixel[1],
|
|
160
|
+
this.width / 2 + (p0[0] - pixel[0]) * shiftScale,
|
|
161
|
+
this.height / 2 + (p0[1] - pixel[1]) * shiftScale,
|
|
156
162
|
this.projectedCenter[2]
|
|
157
163
|
];
|
|
158
164
|
return {
|
|
@@ -48,6 +48,10 @@ function getProjectionMatrix({
|
|
|
48
48
|
});
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
/** independent zoom levels for X and Y axes
|
|
52
|
+
* @deprecated use `zoomX` and `zoomY` instead */
|
|
53
|
+
type Deprecated2DZoom = [number, number];
|
|
54
|
+
|
|
51
55
|
export type OrthographicViewportOptions = {
|
|
52
56
|
/** Name of the viewport */
|
|
53
57
|
id?: string;
|
|
@@ -62,8 +66,10 @@ export type OrthographicViewportOptions = {
|
|
|
62
66
|
/** The world position at the center of the viewport. Default `[0, 0, 0]`. */
|
|
63
67
|
target?: [number, number, number] | [number, number];
|
|
64
68
|
/** The zoom level of the viewport. `zoom: 0` maps one unit distance to one pixel on screen, and increasing `zoom` by `1` scales the same object to twice as large.
|
|
65
|
-
* To apply independent zoom levels to the X and Y axes,
|
|
66
|
-
|
|
69
|
+
* To apply independent zoom levels to the X and Y axes, use `zoomX` and `zoomY`.
|
|
70
|
+
* @default 0
|
|
71
|
+
*/
|
|
72
|
+
zoom?: number | Deprecated2DZoom;
|
|
67
73
|
/** Independent zoom along the X axis. Overrides `zoom`. */
|
|
68
74
|
zoomX?: number;
|
|
69
75
|
/** Independent zoom along the Y axis. Overrides `zoom`. */
|
|
@@ -285,6 +285,16 @@ export default class WebMercatorViewport extends Viewport {
|
|
|
285
285
|
return {longitude, latitude};
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
+
/**
|
|
289
|
+
* Returns a new longitude and latitude that keeps a 3D world coordinate at a given screen pixel
|
|
290
|
+
* This version handles the z-component (altitude) properly for cameras positioned above ground
|
|
291
|
+
*/
|
|
292
|
+
panByPosition3D(coords: number[], pixel: number[]): WebMercatorViewportOptions {
|
|
293
|
+
const targetZ = coords[2] || 0;
|
|
294
|
+
const deltaLngLat = vec2.sub([], coords, this.unproject(pixel, {targetZ}));
|
|
295
|
+
return {longitude: this.longitude + deltaLngLat[0], latitude: this.latitude + deltaLngLat[1]};
|
|
296
|
+
}
|
|
297
|
+
|
|
288
298
|
getBounds(options: {z?: number} = {}): [number, number, number, number] {
|
|
289
299
|
// @ts-ignore
|
|
290
300
|
const corners = getBounds(this, options.z || 0);
|