@openglobus/og 0.18.4 → 0.19.0

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.
Files changed (64) hide show
  1. package/README.md +19 -68
  2. package/css/og.css +308 -45
  3. package/lib/@openglobus/og.css +1 -1
  4. package/lib/@openglobus/og.esm.js +1 -1
  5. package/lib/@openglobus/og.esm.js.map +1 -1
  6. package/lib/@openglobus/og.umd.js +1 -1
  7. package/lib/@openglobus/og.umd.js.map +1 -1
  8. package/lib/js/Globe.d.ts +2 -0
  9. package/lib/js/Globe.js +3 -1
  10. package/lib/js/camera/PlanetCamera.d.ts +2 -2
  11. package/lib/js/camera/PlanetCamera.js +3 -2
  12. package/lib/js/control/DebugInfo.js +5 -0
  13. package/lib/js/control/EarthCoordinates.js +2 -2
  14. package/lib/js/control/LayerSwitcher.d.ts +18 -3
  15. package/lib/js/control/LayerSwitcher.js +111 -11
  16. package/lib/js/control/MouseNavigation.d.ts +2 -0
  17. package/lib/js/control/MouseNavigation.js +15 -15
  18. package/lib/js/control/elevationProfile/ElevationProfile.d.ts +41 -25
  19. package/lib/js/control/elevationProfile/ElevationProfile.js +106 -75
  20. package/lib/js/control/elevationProfile/ElevationProfileButtonsView.d.ts +14 -0
  21. package/lib/js/control/elevationProfile/ElevationProfileButtonsView.js +61 -0
  22. package/lib/js/control/elevationProfile/ElevationProfileControl.d.ts +33 -0
  23. package/lib/js/control/elevationProfile/ElevationProfileControl.js +153 -0
  24. package/lib/js/control/elevationProfile/ElevationProfileLegend.d.ts +20 -0
  25. package/lib/js/control/elevationProfile/ElevationProfileLegend.js +82 -0
  26. package/lib/js/control/elevationProfile/ElevationProfileScene.d.ts +80 -0
  27. package/lib/js/control/elevationProfile/ElevationProfileScene.js +539 -0
  28. package/lib/js/control/elevationProfile/ElevationProfileView.d.ts +63 -0
  29. package/lib/js/control/elevationProfile/ElevationProfileView.js +504 -0
  30. package/lib/js/control/elevationProfile/PointListDialog.d.ts +12 -0
  31. package/lib/js/control/elevationProfile/PointListDialog.js +57 -0
  32. package/lib/js/control/heightRuler/HeightRulerScene.js +1 -1
  33. package/lib/js/control/index.d.ts +2 -1
  34. package/lib/js/control/index.js +2 -1
  35. package/lib/js/control/ruler/RulerScene.js +3 -3
  36. package/lib/js/control/selection/SelectionScene.js +2 -2
  37. package/lib/js/entity/Entity.js +5 -1
  38. package/lib/js/entity/Polyline.js +1 -1
  39. package/lib/js/layer/GeoImage.js +3 -0
  40. package/lib/js/layer/Layer.d.ts +18 -4
  41. package/lib/js/layer/Layer.js +25 -4
  42. package/lib/js/layer/XYZ.d.ts +0 -1
  43. package/lib/js/quadTree/Node.d.ts +21 -3
  44. package/lib/js/quadTree/Node.js +173 -62
  45. package/lib/js/renderer/Renderer.d.ts +0 -1
  46. package/lib/js/renderer/Renderer.js +22 -44
  47. package/lib/js/renderer/RendererEvents.d.ts +1 -0
  48. package/lib/js/renderer/RendererEvents.js +5 -7
  49. package/lib/js/scene/Planet.d.ts +33 -4
  50. package/lib/js/scene/Planet.js +206 -84
  51. package/lib/js/segment/Segment.d.ts +7 -1
  52. package/lib/js/segment/Segment.js +40 -12
  53. package/lib/js/shaders/drawnode.js +21 -2
  54. package/lib/js/shaders/geoObject.js +26 -18
  55. package/lib/js/terrain/GlobusTerrain.d.ts +3 -0
  56. package/lib/js/terrain/GlobusTerrain.js +15 -3
  57. package/lib/js/terrain/MapboxTerrain.js +29 -29
  58. package/lib/js/ui/Dialog.js +1 -1
  59. package/lib/js/utils/TerrainWorker.js +1 -1
  60. package/lib/js/utils/shared.d.ts +3 -1
  61. package/lib/js/utils/shared.js +22 -3
  62. package/package.json +2 -2
  63. package/lib/js/shaders/pickingMask.d.ts +0 -2
  64. package/lib/js/shaders/pickingMask.js +0 -22
@@ -32,6 +32,7 @@ class GeoImage extends BaseGeoImage {
32
32
  this._sourceReady = false;
33
33
  this._sourceCreated = false;
34
34
  this._image = new Image();
35
+ this._image.crossOrigin = "Anonymous";
35
36
  this._onLoad_ = this._onLoad.bind(this);
36
37
  this._image.addEventListener("load", this._onLoad_);
37
38
  this._image.src = src;
@@ -46,6 +47,7 @@ class GeoImage extends BaseGeoImage {
46
47
  this._sourceCreated = false;
47
48
  this._sourceReady = false;
48
49
  this._image = image;
50
+ this._image.crossOrigin = "Anonymous";
49
51
  this._src = image.src;
50
52
  if (isImageLoaded(this._image)) {
51
53
  this._applyImage(this._image);
@@ -105,6 +107,7 @@ class GeoImage extends BaseGeoImage {
105
107
  }
106
108
  else {
107
109
  this._image = new Image();
110
+ this._image.crossOrigin = "Anonymous";
108
111
  this._onLoad_ = this._onLoad.bind(this);
109
112
  this._image.addEventListener("load", this._onLoad_);
110
113
  this._image.src = this._src;
@@ -10,7 +10,7 @@ import { IDefaultTextureParams } from "../webgl/Handler";
10
10
  export interface ILayerParams {
11
11
  properties?: any;
12
12
  labelMaxLetters?: number;
13
- displayInLayerSwitcher?: boolean;
13
+ hideInLayerSwitcher?: boolean;
14
14
  opacity?: number;
15
15
  minZoom?: number;
16
16
  maxZoom?: number;
@@ -31,6 +31,7 @@ export interface ILayerParams {
31
31
  specular?: string | NumberArray3 | Vec3;
32
32
  shininess?: number;
33
33
  nightTextureCoefficient?: number;
34
+ iconSrc?: string | null;
34
35
  }
35
36
  /**
36
37
  * @class
@@ -45,11 +46,11 @@ export interface ILayerParams {
45
46
  * @param {string} [options.attribution] - Layer attribution that displayed in the attribution area on the screen.
46
47
  * @param {boolean} [options.isBaseLayer=false] - This is a base layer.
47
48
  * @param {boolean} [options.visibility=true] - Layer visibility.
48
- * @param {boolean} [options.displayInLayerSwitcher=true] - Presence of layer in dialog window of LayerSwitcher control.
49
+ * @param {boolean} [options.hideInLayerSwitcher=false] - Presence of layer in dialog window of LayerSwitcher control.
49
50
  * @param {boolean} [options.isSRGB=false] - Layer image webgl internal format.
50
51
  * @param {Extent} [options.extent=[[-180.0, -90.0], [180.0, 90.0]]] - Visible extent.
51
52
  * @param {string} [options.textureFilter="anisotropic"] - Image texture filter. Available values: "nearest", "linear", "mipmap" and "anisotropic".
52
- *
53
+ * @param {string} [options.icon] - Icon for LayerSwitcher
53
54
  * @fires EventsHandler<LayerEventsList>#visibilitychange
54
55
  * @fires EventsHandler<LayerEventsList>#add
55
56
  * @fires EventsHandler<LayerEventsList>#remove
@@ -98,7 +99,7 @@ declare class Layer {
98
99
  */
99
100
  name: string;
100
101
  properties: any;
101
- displayInLayerSwitcher: boolean;
102
+ hideInLayerSwitcher: boolean;
102
103
  /**
103
104
  * Minimal zoom level when layer is visible.
104
105
  * @public
@@ -188,7 +189,10 @@ declare class Layer {
188
189
  _diffuse: Float32Array | null;
189
190
  _specular: Float32Array | null;
190
191
  isVector: boolean;
192
+ protected _iconSrc: string | null;
191
193
  constructor(name?: string | null, options?: ILayerParams);
194
+ get iconSrc(): string | null;
195
+ set iconSrc(src: string | null);
192
196
  set diffuse(rgb: string | NumberArray3 | Vec3 | null | undefined);
193
197
  set ambient(rgb: string | NumberArray3 | Vec3 | null | undefined);
194
198
  set specular(rgb: string | NumberArray3 | Vec3 | null | undefined);
@@ -354,6 +358,16 @@ declare class Layer {
354
358
  * @return {Extent} - Layer extent.
355
359
  */
356
360
  getExtentMerc(): Extent;
361
+ /**
362
+ * Fly extent.
363
+ * @public
364
+ */
365
+ flyExtent(): void;
366
+ /**
367
+ * View extent.
368
+ * @public
369
+ */
370
+ viewExtent(): void;
357
371
  /**
358
372
  * Special correction of the whole globe extent.
359
373
  * @protected
@@ -20,11 +20,11 @@ const FADING_RATIO = 15.8;
20
20
  * @param {string} [options.attribution] - Layer attribution that displayed in the attribution area on the screen.
21
21
  * @param {boolean} [options.isBaseLayer=false] - This is a base layer.
22
22
  * @param {boolean} [options.visibility=true] - Layer visibility.
23
- * @param {boolean} [options.displayInLayerSwitcher=true] - Presence of layer in dialog window of LayerSwitcher control.
23
+ * @param {boolean} [options.hideInLayerSwitcher=false] - Presence of layer in dialog window of LayerSwitcher control.
24
24
  * @param {boolean} [options.isSRGB=false] - Layer image webgl internal format.
25
25
  * @param {Extent} [options.extent=[[-180.0, -90.0], [180.0, 90.0]]] - Visible extent.
26
26
  * @param {string} [options.textureFilter="anisotropic"] - Image texture filter. Available values: "nearest", "linear", "mipmap" and "anisotropic".
27
- *
27
+ * @param {string} [options.icon] - Icon for LayerSwitcher
28
28
  * @fires EventsHandler<LayerEventsList>#visibilitychange
29
29
  * @fires EventsHandler<LayerEventsList>#add
30
30
  * @fires EventsHandler<LayerEventsList>#remove
@@ -56,11 +56,11 @@ class Layer {
56
56
  constructor(name, options = {}) {
57
57
  this.isVector = false;
58
58
  this.__id = Layer.__counter__++;
59
+ this._iconSrc = options.iconSrc || null;
59
60
  this.events = createEvents(LAYER_EVENTS, this);
60
61
  this.name = name || "noname";
61
62
  this.properties = options.properties || {};
62
- this.displayInLayerSwitcher =
63
- options.displayInLayerSwitcher !== undefined ? options.displayInLayerSwitcher : true;
63
+ this.hideInLayerSwitcher = options.hideInLayerSwitcher || false;
64
64
  this._hasImageryTiles = true;
65
65
  this._opacity = options.opacity || 1.0;
66
66
  this.minZoom = options.minZoom || 0;
@@ -116,6 +116,13 @@ class Layer {
116
116
  }
117
117
  this.nightTextureCoefficient = options.nightTextureCoefficient || 1.0;
118
118
  }
119
+ get iconSrc() {
120
+ return this._iconSrc;
121
+ }
122
+ set iconSrc(src) {
123
+ // @todo: add event
124
+ this._iconSrc = src;
125
+ }
119
126
  set diffuse(rgb) {
120
127
  if (rgb) {
121
128
  let vec = createColorRGB(rgb);
@@ -508,6 +515,20 @@ class Layer {
508
515
  getExtentMerc() {
509
516
  return this._extentMerc;
510
517
  }
518
+ /**
519
+ * Fly extent.
520
+ * @public
521
+ */
522
+ flyExtent() {
523
+ this._planet?.flyExtent(this.getExtent());
524
+ }
525
+ /**
526
+ * View extent.
527
+ * @public
528
+ */
529
+ viewExtent() {
530
+ this._planet?.viewExtent(this.getExtent());
531
+ }
511
532
  /**
512
533
  * Special correction of the whole globe extent.
513
534
  * @protected
@@ -73,7 +73,6 @@ export declare class XYZ extends Layer {
73
73
  /**
74
74
  * Rewrites imagery tile url query.
75
75
  * @private
76
- * @callback og.layer.XYZ~_urlRewriteCallback
77
76
  * @param {Segment} segment - Segment to load.
78
77
  * @param {string} url - Created url.
79
78
  * @returns {string} - Url query string.
@@ -20,6 +20,7 @@ declare class Node {
20
20
  partId: number;
21
21
  nodeId: number;
22
22
  state: number | null;
23
+ prevState: number | null;
23
24
  appliedTerrainNodeId: number;
24
25
  sideSizeLog2: [number, number, number, number];
25
26
  ready: boolean;
@@ -29,6 +30,7 @@ declare class Node {
29
30
  segment: Segment;
30
31
  _cameraInside: boolean;
31
32
  inFrustum: number;
33
+ _fadingNodes: Node[];
32
34
  constructor(SegmentPrototype: typeof Segment, planet: Planet, partId: number, parent: Node | null, id: number, tileZoom: number, extent: Extent);
33
35
  createChildrenNodes(): void;
34
36
  createBounds(): void;
@@ -40,14 +42,30 @@ declare class Node {
40
42
  * @returns {Node} -
41
43
  */
42
44
  getEqualNeighbor(side: number): Node | undefined;
43
- renderTree(cam: PlanetCamera, maxZoom?: number | null, terrainReadySegment?: Segment | null, stopLoading?: boolean): void;
44
- traverseNodes(cam: PlanetCamera, maxZoom?: number | null, terrainReadySegment?: Segment | null, stopLoading?: boolean): void;
45
+ traverseNodes(cam: PlanetCamera, maxZoom?: number | null, terrainReadySegment?: Segment | null, stopLoading?: boolean, zoomPassNode?: Node): void;
46
+ renderTree(cam: PlanetCamera, maxZoom?: number | null, terrainReadySegment?: Segment | null, stopLoading?: boolean, zoomPassNode?: Node): void;
45
47
  renderNode(inFrustum: number, onlyTerrain?: boolean, terrainReadySegment?: Segment | null, stopLoading?: boolean): void;
48
+ childrenPrevStateEquals(state: number): boolean;
49
+ isFading(): boolean;
50
+ _collectFadingNodes(): void;
51
+ clearNeighbors(): void;
52
+ _refreshTransitionOpacity(): void;
46
53
  /**
47
- * Searching for neighbours and picking up current node to render processing.
54
+ * Picking up current node to render processing.
48
55
  * @public
49
56
  */
50
57
  addToRender(inFrustum: number): void;
58
+ applyNeighbor(node: Node, side: number): void;
59
+ /**
60
+ * Searching current node for its neighbours.
61
+ * @public
62
+ */
63
+ getRenderedNodesNeighbors(nodes: Node[]): void;
64
+ /**
65
+ * Checking if current node has a common side with input node and return side index N, E, S or W. Otherwise returns -1.
66
+ * @param {Node} node - Input node
67
+ * @returns {number} - Node side index
68
+ */
51
69
  getCommonSide(node: Node): number;
52
70
  whileNormalMapCreating(): void;
53
71
  whileTerrainLoading(terrainReadySegment?: Segment | null): void;
@@ -1,7 +1,7 @@
1
1
  import { Extent } from "../Extent";
2
2
  import { EPSG3857 } from "../proj/EPSG3857";
3
3
  import { EPSG4326 } from "../proj/EPSG4326";
4
- import { getMatrixSubArray32, getMatrixSubArray64, getMatrixSubArrayBoundsExt } from "../utils/shared";
4
+ import { binaryInsert, getMatrixSubArray32, getMatrixSubArray64, getMatrixSubArrayBoundsExt } from "../utils/shared";
5
5
  import { LonLat } from "../LonLat";
6
6
  import { MAX, MIN } from "../math";
7
7
  import { MAX_LAT } from "../mercator";
@@ -39,15 +39,18 @@ class Node {
39
39
  this.partId = partId;
40
40
  this.nodeId = partId + id;
41
41
  this.state = null;
42
+ this.prevState = null;
42
43
  this.appliedTerrainNodeId = -1;
43
44
  this.sideSizeLog2 = [0, 0, 0, 0];
44
45
  this.ready = false;
45
46
  this.neighbors = [[], [], [], []];
46
47
  this.equalizedSideWithNodeId = [this.nodeId, this.nodeId, this.nodeId, this.nodeId];
48
+ // @todo: this.nodes = null;
47
49
  this.nodes = [];
48
50
  this.segment = new SegmentPrototype(this, planet, tileZoom, extent);
49
51
  this._cameraInside = false;
50
52
  this.inFrustum = 0;
53
+ this._fadingNodes = [];
51
54
  this.createBounds();
52
55
  }
53
56
  createChildrenNodes() {
@@ -133,23 +136,28 @@ class Node {
133
136
  // public isBrother(node: Node): boolean {
134
137
  // return !(this.parentNode || node.parentNode) || (this.parentNode!.nodeId === node.parentNode!.nodeId);
135
138
  // }
136
- renderTree(cam, maxZoom, terrainReadySegment, stopLoading) {
139
+ traverseNodes(cam, maxZoom, terrainReadySegment, stopLoading, zoomPassNode) {
140
+ if (!this.ready) {
141
+ this.createChildrenNodes();
142
+ }
143
+ let n = this.nodes;
144
+ n[0].renderTree(cam, maxZoom, terrainReadySegment, stopLoading, zoomPassNode);
145
+ n[1].renderTree(cam, maxZoom, terrainReadySegment, stopLoading, zoomPassNode);
146
+ n[2].renderTree(cam, maxZoom, terrainReadySegment, stopLoading, zoomPassNode);
147
+ n[3].renderTree(cam, maxZoom, terrainReadySegment, stopLoading, zoomPassNode);
148
+ }
149
+ renderTree(cam, maxZoom, terrainReadySegment, stopLoading, zoomPassNode) {
137
150
  if (this.planet._renderedNodes.length >= MAX_RENDERED_NODES) {
138
151
  return;
139
152
  }
153
+ if (!maxZoom || zoomPassNode && this.segment.tileZoom > zoomPassNode.segment.tileZoom) {
154
+ this.prevState = this.state;
155
+ }
140
156
  this.state = WALKTHROUGH;
141
- // @ts-ignore
142
- this.neighbors[0] = null;
143
- // @ts-ignore
144
- this.neighbors[1] = null;
145
- // @ts-ignore
146
- this.neighbors[2] = null;
147
- // @ts-ignore
148
- this.neighbors[3] = null;
149
- this.neighbors[0] = [];
150
- this.neighbors[1] = [];
151
- this.neighbors[2] = [];
152
- this.neighbors[3] = [];
157
+ this.clearNeighbors();
158
+ for (let i = 0; i < this._fadingNodes.length; i++) {
159
+ this._fadingNodes[i].neighbors && this._fadingNodes[i].clearNeighbors();
160
+ }
153
161
  let seg = this.segment, planet = this.planet;
154
162
  this._cameraInside = false;
155
163
  // Search a node which the camera is flying over.
@@ -208,7 +216,7 @@ class Node {
208
216
  seg._collectVisibleNodes();
209
217
  }
210
218
  if (seg.tileZoom < 2) {
211
- this.traverseNodes(cam, maxZoom, terrainReadySegment, stopLoading);
219
+ this.traverseNodes(cam, maxZoom, terrainReadySegment, stopLoading, zoomPassNode);
212
220
  }
213
221
  else if (seg.terrainReady && (!maxZoom && cam.projectedSize(seg.bsphere.center, seg._plainRadius) < planet.lodSize || maxZoom && ((seg.tileZoom === maxZoom) || !altVis))) {
214
222
  if (altVis) {
@@ -220,7 +228,7 @@ class Node {
220
228
  }
221
229
  }
222
230
  else if (seg.terrainReady && seg.checkZoom() && (!maxZoom || cam.projectedSize(seg.bsphere.center, seg.bsphere.radius) > this.planet._maxLodSize)) {
223
- this.traverseNodes(cam, maxZoom, seg, stopLoading);
231
+ this.traverseNodes(cam, maxZoom, seg, stopLoading, zoomPassNode);
224
232
  }
225
233
  else if (altVis) {
226
234
  seg.passReady = maxZoom ? seg.terrainReady : false;
@@ -234,16 +242,6 @@ class Node {
234
242
  this.state = NOTRENDERING;
235
243
  }
236
244
  }
237
- traverseNodes(cam, maxZoom, terrainReadySegment, stopLoading) {
238
- if (!this.ready) {
239
- this.createChildrenNodes();
240
- }
241
- let n = this.nodes;
242
- n[0].renderTree(cam, maxZoom, terrainReadySegment, stopLoading);
243
- n[1].renderTree(cam, maxZoom, terrainReadySegment, stopLoading);
244
- n[2].renderTree(cam, maxZoom, terrainReadySegment, stopLoading);
245
- n[3].renderTree(cam, maxZoom, terrainReadySegment, stopLoading);
246
- }
247
245
  renderNode(inFrustum, onlyTerrain, terrainReadySegment, stopLoading) {
248
246
  let seg = this.segment;
249
247
  // Create and load terrain data
@@ -278,39 +276,119 @@ class Node {
278
276
  // Finally this node proceeds to rendering.
279
277
  this.addToRender(inFrustum);
280
278
  }
279
+ childrenPrevStateEquals(state) {
280
+ let n = this.nodes;
281
+ return n.length === 4 && n[0].prevState === state && n[1].prevState === state && n[2].prevState === state && n[3].prevState === state;
282
+ }
283
+ isFading() {
284
+ let n = this.nodes;
285
+ return this.state === WALKTHROUGH && this.segment._transitionOpacity > 0.0 && n.length === 4 && (n[0].state === RENDERING && n[1].state === RENDERING && n[2].state === RENDERING && n[3].state === RENDERING);
286
+ }
287
+ _collectFadingNodes() {
288
+ if (this.segment.tileZoom < 3) {
289
+ this.segment._transitionOpacity = 1.0;
290
+ return;
291
+ }
292
+ // Light up the node
293
+ if (this.prevState !== RENDERING) {
294
+ // means that the node is lighting up
295
+ this.segment._transitionOpacity = 0.0;
296
+ // store fading nodes, could be a parent or children nodes
297
+ this._fadingNodes = [];
298
+ let timestamp = window.performance.now();
299
+ this.segment._transitionTimestamp = timestamp;
300
+ if (this.parentNode) {
301
+ // Parent was visible the last frame, make the parent fading
302
+ if (this.parentNode.prevState === RENDERING) {
303
+ let pn = this.parentNode.parentNode;
304
+ while (pn) {
305
+ if (pn.isFading()) {
306
+ for (let i = 0; i < pn.nodes.length; i++) {
307
+ pn.nodes[i].segment._transitionOpacity = 1.0;
308
+ pn.nodes[i]._fadingNodes = [];
309
+ }
310
+ pn.segment._transitionOpacity = 0.0;
311
+ break;
312
+ }
313
+ pn = pn.parentNode;
314
+ }
315
+ // not sure it's necessary here
316
+ //this.parentNode.whileTerrainLoading();
317
+ this._fadingNodes.push(this.parentNode);
318
+ this.parentNode.segment._transitionOpacity = 2.0;
319
+ this.parentNode.segment._transitionTimestamp = timestamp;
320
+ }
321
+ else {
322
+ // Check if the children were visible last frame, and make them fading
323
+ if (this.segment.childrenInitialized() && this.childrenPrevStateEquals(RENDERING)) {
324
+ for (let i = 0; i < this.nodes.length; i++) {
325
+ let ni = this.nodes[i];
326
+ // not sure it's necessary here
327
+ //ni.whileTerrainLoading();
328
+ this._fadingNodes.push(ni);
329
+ ni.segment._transitionOpacity = 2.0;
330
+ ni.segment._transitionTimestamp = timestamp;
331
+ ni.prevState = ni.state;
332
+ ni.state = NOTRENDERING;
333
+ }
334
+ }
335
+ }
336
+ }
337
+ }
338
+ }
339
+ clearNeighbors() {
340
+ //this.sideSizeLog2[0] = this.sideSizeLog2[1] = this.sideSizeLog2[2] = this.sideSizeLog2[3] = Math.log2(this.segment.gridSize);
341
+ // @ts-ignore
342
+ this.neighbors[0] = this.neighbors[1] = this.neighbors[2] = this.neighbors[3] = null;
343
+ this.neighbors[0] = [];
344
+ this.neighbors[1] = [];
345
+ this.neighbors[2] = [];
346
+ this.neighbors[3] = [];
347
+ }
348
+ _refreshTransitionOpacity() {
349
+ if (this._fadingNodes.length === 0) {
350
+ this.segment._transitionOpacity = 1.0;
351
+ }
352
+ else {
353
+ if (this._fadingNodes.length === 4 && !this.childrenPrevStateEquals(RENDERING)) {
354
+ this.segment._transitionOpacity = 1.0;
355
+ }
356
+ else {
357
+ this.segment.increaseTransitionOpacity();
358
+ for (let i = 0; i < this._fadingNodes.length; i++) {
359
+ let n = this._fadingNodes[i];
360
+ if (n.segment) {
361
+ if (n.segment._transitionOpacity > 0 && !this.planet._fadingNodes.has(n.nodeId)) {
362
+ this.planet._fadingNodes.set(n.nodeId, n);
363
+ n.segment.fadingTransitionOpacity();
364
+ }
365
+ }
366
+ else {
367
+ this.segment._transitionOpacity = 1.0;
368
+ break;
369
+ }
370
+ }
371
+ }
372
+ }
373
+ }
281
374
  /**
282
- * Searching for neighbours and picking up current node to render processing.
375
+ * Picking up current node to render processing.
283
376
  * @public
284
377
  */
285
378
  addToRender(inFrustum) {
286
379
  this.state = RENDERING;
287
380
  let nodes = this.planet._renderedNodes;
288
- for (let i = nodes.length - 1; i >= 0; --i) {
289
- const ni = nodes[i];
290
- const cs = this.getCommonSide(ni);
291
- if (cs !== -1) {
292
- const opcs = OPSIDE[cs];
293
- if (this.neighbors[cs].length === 0 || ni.neighbors[opcs].length === 0) {
294
- const ap = this.segment;
295
- const bp = ni.segment;
296
- const ld = ap.gridSize / (bp.gridSize * Math.pow(2, bp.tileZoom - ap.tileZoom));
297
- let cs_size = ap.gridSize, opcs_size = bp.gridSize;
298
- if (ld > 1) {
299
- cs_size = Math.ceil(ap.gridSize / ld);
300
- opcs_size = bp.gridSize;
301
- }
302
- else if (ld < 1) {
303
- cs_size = ap.gridSize;
304
- opcs_size = Math.ceil(bp.gridSize * ld);
305
- }
306
- this.sideSizeLog2[cs] = Math.log2(cs_size);
307
- ni.sideSizeLog2[opcs] = Math.log2(opcs_size);
308
- }
309
- this.neighbors[cs].push(ni);
310
- ni.neighbors[opcs].push(this);
311
- }
381
+ //@ts-ignore
382
+ if (!this.planet._transitionOpacityEnabled) {
383
+ this.getRenderedNodesNeighbors(nodes);
384
+ nodes.push(this);
385
+ }
386
+ else {
387
+ //@todo: check if it's possible to get rid of the sorting when using breadth traverse tree
388
+ binaryInsert(nodes, this, (a, b) => {
389
+ return a.segment.tileZoom - b.segment.tileZoom;
390
+ });
312
391
  }
313
- nodes.push(this);
314
392
  if (!this.segment.terrainReady) {
315
393
  this.planet._renderCompleted = false;
316
394
  this.planet._terrainCompleted = false;
@@ -324,6 +402,46 @@ class Node {
324
402
  inFrustum >>= 1;
325
403
  }
326
404
  }
405
+ applyNeighbor(node, side) {
406
+ const opcs = OPSIDE[side];
407
+ if (this.neighbors[side].length === 0 || node.neighbors[opcs].length === 0) {
408
+ const ap = this.segment;
409
+ const bp = node.segment;
410
+ const ld = ap.gridSize / (bp.gridSize * Math.pow(2, bp.tileZoom - ap.tileZoom));
411
+ let cs_size = ap.gridSize, opcs_size = bp.gridSize;
412
+ if (ld > 1) {
413
+ cs_size = Math.ceil(ap.gridSize / ld);
414
+ opcs_size = bp.gridSize;
415
+ }
416
+ else if (ld < 1) {
417
+ cs_size = ap.gridSize;
418
+ opcs_size = Math.ceil(bp.gridSize * ld);
419
+ }
420
+ this.sideSizeLog2[side] = Math.log2(cs_size);
421
+ node.sideSizeLog2[opcs] = Math.log2(opcs_size);
422
+ }
423
+ //@todo: fix dupe neighbors
424
+ this.neighbors[side].push(node);
425
+ node.neighbors[opcs].push(this);
426
+ }
427
+ /**
428
+ * Searching current node for its neighbours.
429
+ * @public
430
+ */
431
+ getRenderedNodesNeighbors(nodes) {
432
+ for (let i = nodes.length - 1; i >= 0; --i) {
433
+ let ni = nodes[i];
434
+ let cs = this.getCommonSide(ni);
435
+ if (cs !== -1) {
436
+ this.applyNeighbor(ni, cs);
437
+ }
438
+ }
439
+ }
440
+ /**
441
+ * Checking if current node has a common side with input node and return side index N, E, S or W. Otherwise returns -1.
442
+ * @param {Node} node - Input node
443
+ * @returns {number} - Node side index
444
+ */
327
445
  getCommonSide(node) {
328
446
  const as = this.segment;
329
447
  const bs = node.segment;
@@ -574,23 +692,16 @@ class Node {
574
692
  }
575
693
  }
576
694
  destroy() {
577
- this.state = NOTRENDERING;
695
+ this.prevState = this.state = NOTRENDERING;
578
696
  this.segment.destroySegment();
579
697
  let n = this.neighbors;
580
- for (let i = 0; i < n.length; i++) {
698
+ for (let i = 0, len = n.length; i < len; i++) {
581
699
  let ni = n[i];
582
700
  if (ni) {
583
701
  for (let j = 0; j < ni.length; j++) {
584
702
  let nij = ni[j];
585
703
  if (nij && nij.neighbors) {
586
- // @ts-ignore
587
- nij.neighbors[N] = null;
588
- // @ts-ignore
589
- nij.neighbors[E] = null;
590
- // @ts-ignore
591
- nij.neighbors[S] = null;
592
- // @ts-ignore
593
- nij.neighbors[W] = null;
704
+ nij.clearNeighbors();
594
705
  }
595
706
  }
596
707
  }
@@ -151,7 +151,6 @@ declare class Renderer {
151
151
  screenFramePositionBuffer: WebGLBufferExt | null;
152
152
  screenTexture: Record<string, WebGLTexture>;
153
153
  outputTexture: WebGLTexture | null;
154
- protected _pickingMaskCoordinatesBuffer: WebGLBufferExt | null;
155
154
  protected _skipDistanceFrame: boolean;
156
155
  protected _distancePixelBuffer: WebGLBuffer | null;
157
156
  protected _skipPickingFrame: boolean;