@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
@@ -58,6 +58,53 @@ const HORIZON_TANGENT = 0.81;
58
58
  export class Planet extends RenderNode {
59
59
  constructor(options = {}) {
60
60
  super(options.name);
61
+ this._renderingFadingNodes = (nodes, sh, currentNode, sl, sliceIndex, outTransparentSegments) => {
62
+ let isFirstPass = sliceIndex === 0;
63
+ let isEq = this.terrain.equalizeVertices;
64
+ for (let j = 0, len = currentNode._fadingNodes.length; j < len; j++) {
65
+ let f = currentNode._fadingNodes[j].segment;
66
+ if (this._fadingNodes.has(currentNode._fadingNodes[0].nodeId) && !nodes.has(f.node.nodeId)) {
67
+ nodes.set(f.node.nodeId, true);
68
+ if (f._transitionOpacity < 1.0) {
69
+ outTransparentSegments.push(f);
70
+ }
71
+ else {
72
+ if (isFirstPass) {
73
+ isEq && f.equalize();
74
+ f.readyToEngage && f.engage();
75
+ f.screenRendering(sh, sl, sliceIndex);
76
+ }
77
+ else {
78
+ f.screenRendering(sh, sl, sliceIndex, this.transparentTexture, true);
79
+ }
80
+ }
81
+ }
82
+ }
83
+ };
84
+ this._renderingFadingNodesNoDepth = (nodes, sh, currentNode, sl, sliceIndex) => {
85
+ let isFirstPass = sliceIndex === 0;
86
+ let isEq = this.terrain.equalizeVertices;
87
+ let gl = sh.gl;
88
+ gl.disable(gl.DEPTH_TEST);
89
+ for (let j = 0, len = currentNode._fadingNodes.length; j < len; j++) {
90
+ let f = currentNode._fadingNodes[j].segment;
91
+ if (this._fadingNodes.has(currentNode._fadingNodes[0].nodeId) && !nodes.has(f.node.nodeId)) {
92
+ nodes.set(f.node.nodeId, true);
93
+ if (isFirstPass) {
94
+ isEq && f.equalize();
95
+ f.readyToEngage && f.engage();
96
+ f.screenRendering(sh, sl, sliceIndex);
97
+ }
98
+ else {
99
+ f.screenRendering(sh, sl, sliceIndex, this.transparentTexture, true);
100
+ }
101
+ }
102
+ }
103
+ gl.enable(gl.DEPTH_TEST);
104
+ };
105
+ this._prevNodes = new Map();
106
+ this._currNodes = new Map();
107
+ this.transitionTime = 580;
61
108
  this.ellipsoid = options.ellipsoid || wgs84;
62
109
  this.lightEnabled = true;
63
110
  this._planetRadius2 = this.ellipsoid.getPolarSize() * this.ellipsoid.getPolarSize();
@@ -92,6 +139,8 @@ export class Planet extends RenderNode {
92
139
  this._createdNodesCount = 0;
93
140
  this._renderedNodes = [];
94
141
  this._renderedNodesInFrustum = [];
142
+ this._fadingNodes = new Map;
143
+ this._fadingNodesInFrustum = [];
95
144
  this._visibleNodes = {};
96
145
  this._visibleNodesNorth = {};
97
146
  this._visibleNodesSouth = {};
@@ -142,12 +191,20 @@ export class Planet extends RenderNode {
142
191
  this._collectRenderNodesIsActive = true;
143
192
  this.nightTextureCoefficient = 2.0;
144
193
  this._renderScreenNodesPASS = this._renderScreenNodesPASSNoAtmos;
194
+ this._renderScreenNodesWithHeightPASS = this._renderScreenNodesWithHeightPASSNoAtmos;
145
195
  this._atmosphereEnabled = options.atmosphereEnabled || false;
146
196
  this._atmosphereMaxMinOpacity = new Float32Array([1.0, 0.41]);
147
197
  this.solidTextureOne = null;
148
198
  this.solidTextureTwo = null;
149
199
  this._nightTextureSrc = options.nightTextureSrc || null;
150
200
  this._specularTextureSrc = options.specularTextureSrc || null;
201
+ this._transitionOpacityEnabled = options.transitionOpacityEnabled != undefined ? options.transitionOpacityEnabled : true;
202
+ }
203
+ /**
204
+ * Returns true if current terrain data set is loaded
205
+ */
206
+ get terrainReady() {
207
+ return this._terrainCompleted && this._terrainCompletedActivated;
151
208
  }
152
209
  get maxGridSize() {
153
210
  return this._maxGridSize;
@@ -372,6 +429,7 @@ export class Planet extends RenderNode {
372
429
  h.removeProgram("drawnode_screen_wl");
373
430
  if (this._atmosphereEnabled) {
374
431
  this._renderScreenNodesPASS = this._renderScreenNodesPASSAtmos;
432
+ this._renderScreenNodesWithHeightPASS = this._renderScreenNodesWithHeightPASSAtmos;
375
433
  if (h.isWebGl2()) {
376
434
  h.addProgram(shaders.drawnode_screen_wl_webgl2Atmos(), true);
377
435
  }
@@ -390,6 +448,7 @@ export class Planet extends RenderNode {
390
448
  }
391
449
  else {
392
450
  this._renderScreenNodesPASS = this._renderScreenNodesPASSNoAtmos;
451
+ this._renderScreenNodesWithHeightPASS = this._renderScreenNodesWithHeightPASSNoAtmos;
393
452
  if (this.renderer.controls.Atmosphere) {
394
453
  this.renderer.controls.Atmosphere.deactivate();
395
454
  }
@@ -456,6 +515,9 @@ export class Planet extends RenderNode {
456
515
  this._renderCompletedActivated = false;
457
516
  this._terrainCompletedActivated = false;
458
517
  });
518
+ this.renderer.events.on("drawtransparent", () => {
519
+ this._renderScreenNodesWithHeightPASS();
520
+ });
459
521
  // Initialize texture coordinates buffer pool
460
522
  this._textureCoordsBufferCache = [];
461
523
  let texCoordCache = segmentHelper.getInstance().initTextureCoordsTable(TABLESIZE + 1);
@@ -483,6 +545,7 @@ export class Planet extends RenderNode {
483
545
  // loading Earth night glowing texture
484
546
  if (this._nightTextureSrc) {
485
547
  let img = new Image();
548
+ img.crossOrigin = "Anonymous";
486
549
  img.onload = () => {
487
550
  this._nightTexture = this.renderer.handler.createTextureDefault(img);
488
551
  this._nightTexture.default = true;
@@ -495,6 +558,7 @@ export class Planet extends RenderNode {
495
558
  // load water specular mask
496
559
  if (this._specularTextureSrc) {
497
560
  let img = new Image();
561
+ img.crossOrigin = "Anonymous";
498
562
  img.onload = () => {
499
563
  this._specularTexture = this.renderer.handler.createTextureDefault(img);
500
564
  this._specularTexture.default = true;
@@ -671,25 +735,7 @@ export class Planet extends RenderNode {
671
735
  this._renderedNodesInFrustum[i] = [];
672
736
  }
673
737
  }
674
- /**
675
- * Collects visible quad nodes.
676
- * @protected
677
- */
678
- _collectRenderNodes() {
679
- let cam = this.camera;
680
- this._lodSize = math.lerp(cam.slope < 0.0 ? 0.0 : cam.slope, this._curLodSize, this._minLodSize);
681
- cam._insideSegment = null;
682
- // clear first
683
- this._clearRenderedNodeList();
684
- this._clearRenderNodesInFrustum();
685
- this._viewExtent.southWest.set(180, 180);
686
- this._viewExtent.northEast.set(-180, -180);
687
- this._visibleNodes = {};
688
- this._visibleNodesNorth = {};
689
- this._visibleNodesSouth = {};
690
- this.minCurrZoom = math.MAX;
691
- this.maxCurrZoom = math.MIN;
692
- this.quadTreeStrategy.collectRenderNodes();
738
+ _collectRenderedNodesMaxZoom(cam) {
693
739
  if (cam.slope > this.minEqualZoomCameraSlope && cam._lonLat.height < this.maxEqualZoomAltitude && cam._lonLat.height > this.minEqualZoomAltitude) {
694
740
  this.minCurrZoom = this.maxCurrZoom;
695
741
  let temp = this._renderedNodes, rf = this._renderedNodesInFrustum, temp2 = [];
@@ -714,10 +760,92 @@ export class Planet extends RenderNode {
714
760
  }
715
761
  }
716
762
  for (let i = 0, len = temp2.length; i < len; i++) {
717
- temp2[i].renderTree(cam, this.maxCurrZoom, null);
763
+ temp2[i].renderTree(cam, this.maxCurrZoom, null, false, temp2[i]);
764
+ }
765
+ }
766
+ }
767
+ set transitionOpacityEnabled(isEnabled) {
768
+ this._transitionOpacityEnabled = isEnabled;
769
+ //@todo: set render nodes transition opacity to one
770
+ }
771
+ get transitionOpacityEnabled() {
772
+ return this._transitionOpacityEnabled;
773
+ }
774
+ /**
775
+ * Collects visible quad nodes.
776
+ * @protected
777
+ */
778
+ _collectRenderNodes(cam) {
779
+ this._lodSize = math.lerp(cam.slope < 0.0 ? 0.0 : cam.slope, this._curLodSize, this._minLodSize);
780
+ cam._insideSegment = null;
781
+ // clear first
782
+ this._clearRenderedNodeList();
783
+ this._clearRenderNodesInFrustum();
784
+ this._viewExtent.southWest.set(180, 180);
785
+ this._viewExtent.northEast.set(-180, -180);
786
+ // todo: replace to camera
787
+ this._visibleNodes = {};
788
+ this._visibleNodesNorth = {};
789
+ this._visibleNodesSouth = {};
790
+ // todo: replace to camera
791
+ this.minCurrZoom = math.MAX;
792
+ this.maxCurrZoom = math.MIN;
793
+ this.quadTreeStrategy.collectRenderNodes();
794
+ this._collectRenderedNodesMaxZoom(cam);
795
+ // main camera effect
796
+ this._fadingNodes.clear();
797
+ if (this._transitionOpacityEnabled) {
798
+ let opaqueNodes = [];
799
+ for (let i = 0; i < this._renderedNodes.length; i++) {
800
+ let ri = this._renderedNodes[i];
801
+ // it's not impossible to move the code into Node.addToRender, because
802
+ // we can't know actual state before _collectRenderedNodesMaxZoom pass
803
+ ri._collectFadingNodes();
804
+ ri._refreshTransitionOpacity();
805
+ if (ri.segment._transitionOpacity >= 1.0) {
806
+ ri.getRenderedNodesNeighbors(opaqueNodes);
807
+ opaqueNodes.push(ri);
808
+ }
809
+ else {
810
+ for (let j = 0; j < ri._fadingNodes.length; j++) {
811
+ let rij = ri._fadingNodes[j];
812
+ if (rij.segment && rij.segment._transitionOpacity >= 1.0) {
813
+ rij.getRenderedNodesNeighbors(opaqueNodes);
814
+ opaqueNodes.push(rij);
815
+ }
816
+ }
817
+ }
718
818
  }
719
819
  }
720
820
  }
821
+ _renderScreenNodesPASSNoAtmos() {
822
+ let cam = this.renderer.activeCamera;
823
+ let sh = this._setUniformsNoAtmos(cam);
824
+ //
825
+ // PASS 0: rendering base slice of layers, which is often zero height
826
+ this._renderingScreenNodes(sh, cam, this._renderedNodesInFrustum[cam.currentFrustumIndex]);
827
+ }
828
+ _renderScreenNodesPASSAtmos() {
829
+ let cam = this.renderer.activeCamera;
830
+ let sh = this._setUniformsAtmos(cam);
831
+ //
832
+ // PASS 0: rendering base slice of layers, which is often zero height
833
+ this._renderingScreenNodes(sh, cam, this._renderedNodesInFrustum[cam.currentFrustumIndex]);
834
+ }
835
+ _renderScreenNodesWithHeightPASSNoAtmos() {
836
+ let cam = this.renderer.activeCamera;
837
+ let sh = this._setUniformsNoAtmos(cam);
838
+ //
839
+ // PASS 1: rendering slices, and layers with heights, without transition opacity effect
840
+ this._renderingScreenNodesWithHeight(sh, cam, this._renderedNodesInFrustum[cam.currentFrustumIndex]);
841
+ }
842
+ _renderScreenNodesWithHeightPASSAtmos() {
843
+ let cam = this.renderer.activeCamera;
844
+ let sh = this._setUniformsAtmos(cam);
845
+ //
846
+ // PASS 1: rendering slices, and layers with heights, without transition opacity effect
847
+ this._renderingScreenNodesWithHeight(sh, cam, this._renderedNodesInFrustum[cam.currentFrustumIndex]);
848
+ }
721
849
  _globalPreDraw() {
722
850
  let cam = this.camera;
723
851
  // Might be it's better to replace it in setTerrain,
@@ -747,7 +875,7 @@ export class Planet extends RenderNode {
747
875
  if (this.camera.isFirstPass) {
748
876
  this.camera.update();
749
877
  if (this._skipPreRender && this._collectRenderNodesIsActive) {
750
- this._collectRenderNodes();
878
+ this._collectRenderNodes(this.camera);
751
879
  }
752
880
  this._skipPreRender = true;
753
881
  this.transformLights();
@@ -769,6 +897,7 @@ export class Planet extends RenderNode {
769
897
  }
770
898
  /**
771
899
  * Render node callback.
900
+ * Frame function is called for each renderer activrCamera frustum.
772
901
  * @public
773
902
  * @override
774
903
  */
@@ -805,14 +934,11 @@ export class Planet extends RenderNode {
805
934
  this._collectRenderNodesIsActive = true;
806
935
  this.camera.setTerrainCollisionActivity(true);
807
936
  }
808
- _renderScreenNodesPASSNoAtmos() {
937
+ _setUniformsNoAtmos(cam) {
809
938
  let sh, shu;
810
939
  let renderer = this.renderer;
811
940
  let h = renderer.handler;
812
941
  let gl = h.gl;
813
- let cam = renderer.activeCamera;
814
- let firstPass = cam.isFirstPass;
815
- let frustumIndex = cam.currentFrustumIndex;
816
942
  gl.enable(gl.CULL_FACE);
817
943
  renderer.enableBlendOneSrcAlpha();
818
944
  if (this.lightEnabled) {
@@ -854,54 +980,13 @@ export class Planet extends RenderNode {
854
980
  }
855
981
  gl.uniform3fv(shu.eyePositionHigh, cam.eyeHigh);
856
982
  gl.uniform3fv(shu.eyePositionLow, cam.eyeLow);
857
- //
858
- // drawing planet nodes
859
- //
860
- let rn = this._renderedNodesInFrustum[frustumIndex], sl = this._visibleTileLayerSlices;
861
- if (sl.length) {
862
- let sli = sl[0];
863
- for (let i = sli.length - 1; i >= 0; --i) {
864
- let li = sli[i];
865
- if (li._fading && firstPass && li._refreshFadingOpacity()) {
866
- sli.splice(i, 1);
867
- }
868
- }
869
- }
870
- let isEq = this.terrain.equalizeVertices;
871
- let i = rn.length;
872
- while (i--) {
873
- let s = rn[i].segment;
874
- isEq && s.equalize();
875
- s.readyToEngage && s.engage();
876
- s.screenRendering(sh, sl[0], 0);
877
- }
878
- gl.enable(gl.POLYGON_OFFSET_FILL);
879
- //gl.disable(gl.CULL_FACE);
880
- for (let j = 1, len = sl.length; j < len; j++) {
881
- let slj = sl[j];
882
- for (i = slj.length - 1; i >= 0; --i) {
883
- let li = slj[i];
884
- if (li._fading && firstPass && li._refreshFadingOpacity()) {
885
- slj.splice(i, 1);
886
- }
887
- }
888
- gl.polygonOffset(0, -j);
889
- i = rn.length;
890
- while (i--) {
891
- rn[i].segment.screenRendering(sh, sl[j], j, this.transparentTexture, true);
892
- }
893
- }
894
- //gl.enable(gl.CULL_FACE);
895
- gl.disable(gl.POLYGON_OFFSET_FILL);
983
+ return sh;
896
984
  }
897
- _renderScreenNodesPASSAtmos() {
985
+ _setUniformsAtmos(cam) {
898
986
  let sh, shu;
899
987
  let renderer = this.renderer;
900
988
  let h = renderer.handler;
901
989
  let gl = h.gl;
902
- let cam = renderer.activeCamera;
903
- let firstPass = cam.isFirstPass;
904
- let frustumIndex = cam.currentFrustumIndex;
905
990
  gl.enable(gl.CULL_FACE);
906
991
  renderer.enableBlendOneSrcAlpha();
907
992
  if (this.lightEnabled) {
@@ -953,10 +1038,14 @@ export class Planet extends RenderNode {
953
1038
  }
954
1039
  gl.uniform3fv(shu.eyePositionHigh, cam.eyeHigh);
955
1040
  gl.uniform3fv(shu.eyePositionLow, cam.eyeLow);
956
- //
957
- // drawing planet nodes
958
- //
959
- let rn = this._renderedNodesInFrustum[frustumIndex], sl = this._visibleTileLayerSlices;
1041
+ return sh;
1042
+ }
1043
+ /**
1044
+ * Drawing nodes
1045
+ */
1046
+ _renderingScreenNodes(sh, cam, renderedNodes) {
1047
+ let firstPass = cam.isFirstPass;
1048
+ let sl = this._visibleTileLayerSlices;
960
1049
  if (sl.length) {
961
1050
  let sli = sl[0];
962
1051
  for (let i = sli.length - 1; i >= 0; --i) {
@@ -966,30 +1055,65 @@ export class Planet extends RenderNode {
966
1055
  }
967
1056
  }
968
1057
  }
1058
+ let nodes = new Map;
1059
+ let transparentSegments = [];
969
1060
  let isEq = this.terrain.equalizeVertices;
970
- let i = rn.length;
1061
+ let i = renderedNodes.length;
1062
+ let _renderingFadingNodes = this._renderingFadingNodes;
1063
+ if (cam.slope > 0.78 || cam.getAltitude() > 10000) {
1064
+ _renderingFadingNodes = this._renderingFadingNodesNoDepth;
1065
+ }
971
1066
  while (i--) {
972
- let s = rn[i].segment;
973
- isEq && s.equalize();
974
- s.readyToEngage && s.engage();
975
- s.screenRendering(sh, sl[0], 0);
1067
+ let ri = renderedNodes[i];
1068
+ let s = ri.segment;
1069
+ _renderingFadingNodes(nodes, sh, ri, sl[0], 0, transparentSegments);
1070
+ if (s._transitionOpacity < 1) {
1071
+ transparentSegments.push(s);
1072
+ }
1073
+ else {
1074
+ isEq && s.equalize();
1075
+ s.readyToEngage && s.engage();
1076
+ s.screenRendering(sh, sl[0], 0);
1077
+ }
1078
+ }
1079
+ for (let j = 0; j < transparentSegments.length; j++) {
1080
+ let tj = transparentSegments[j];
1081
+ isEq && tj.equalize();
1082
+ tj.readyToEngage && tj.engage();
1083
+ tj.screenRendering(sh, sl[0], 0);
976
1084
  }
1085
+ }
1086
+ _renderingScreenNodesWithHeight(sh, cam, renderedNodes) {
1087
+ let gl = this.renderer.handler.gl;
1088
+ let firstPass = cam.isFirstPass;
1089
+ let sl = this._visibleTileLayerSlices;
977
1090
  gl.enable(gl.POLYGON_OFFSET_FILL);
1091
+ gl.disable(gl.CULL_FACE);
1092
+ let nodes = new Map;
1093
+ let transparentSegments = [];
978
1094
  for (let j = 1, len = sl.length; j < len; j++) {
979
1095
  let slj = sl[j];
980
- for (i = slj.length - 1; i >= 0; --i) {
1096
+ for (let i = slj.length - 1; i >= 0; --i) {
981
1097
  let li = slj[i];
982
1098
  if (li._fading && firstPass && li._refreshFadingOpacity()) {
983
1099
  slj.splice(i, 1);
984
1100
  }
985
1101
  }
986
1102
  gl.polygonOffset(0, -j);
987
- i = rn.length;
1103
+ let i = renderedNodes.length;
988
1104
  while (i--) {
989
- rn[i].segment.screenRendering(sh, sl[j], j, this.transparentTexture, true);
1105
+ let ri = renderedNodes[i];
1106
+ this._renderingFadingNodes(nodes, sh, ri, sl[j], j, transparentSegments);
1107
+ if (ri.segment._transitionOpacity < 1) {
1108
+ ri.segment.initSlice(j);
1109
+ }
1110
+ else {
1111
+ ri.segment.screenRendering(sh, sl[j], j, this.transparentTexture, true);
1112
+ }
990
1113
  }
991
1114
  }
992
1115
  gl.disable(gl.POLYGON_OFFSET_FILL);
1116
+ gl.enable(gl.CULL_FACE);
993
1117
  }
994
1118
  _renderDistanceFramebufferPASS() {
995
1119
  if (!this.terrain.isEmpty) {
@@ -1023,10 +1147,6 @@ export class Planet extends RenderNode {
1023
1147
  sh = h.programs.drawnode_colorPicking._program;
1024
1148
  let shu = sh.uniforms;
1025
1149
  let cam = renderer.activeCamera;
1026
- // Special blend
1027
- // gl.enable(gl.BLEND);
1028
- // gl.blendEquation(gl.FUNC_ADD);
1029
- // gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
1030
1150
  gl.enable(gl.CULL_FACE);
1031
1151
  gl.uniformMatrix4fv(shu.viewMatrix, false, cam.getViewMatrix());
1032
1152
  gl.uniformMatrix4fv(shu.projectionMatrix, false, cam.getProjectionMatrix());
@@ -1039,6 +1159,8 @@ export class Planet extends RenderNode {
1039
1159
  while (i--) {
1040
1160
  rn[i].segment.colorPickingRendering(sh, sl[0], 0);
1041
1161
  }
1162
+ // Here is set blending for transparent overlays
1163
+ renderer.enableBlendDefault();
1042
1164
  gl.enable(gl.POLYGON_OFFSET_FILL);
1043
1165
  for (let j = 1, len = sl.length; j < len; j++) {
1044
1166
  i = rn.length;
@@ -169,6 +169,8 @@ declare class Segment {
169
169
  readyToEngage: boolean;
170
170
  plainProcessing: boolean;
171
171
  normalMapTexturePtr: WebGLTextureExt | null;
172
+ _transitionOpacity: number;
173
+ _transitionTimestamp: number;
172
174
  constructor(node: Node, planet: Planet, tileZoom: number, extent: Extent);
173
175
  checkZoom(): boolean;
174
176
  /**
@@ -220,6 +222,7 @@ declare class Segment {
220
222
  deleteMaterials(): void;
221
223
  deleteElevations(): void;
222
224
  clearSegment(): void;
225
+ childrenInitialized(): boolean;
223
226
  destroySegment(): void;
224
227
  /**
225
228
  * @todo: looks like it could be simplified in Segment contructor
@@ -255,8 +258,11 @@ declare class Segment {
255
258
  *
256
259
  */
257
260
  protected _getLayerExtentOffset(layer: Layer): [number, number, number, number];
258
- screenRendering(sh: Program, layerSlice: Layer[], sliceIndex: number, defaultTexture?: WebGLTextureExt | null, isOverlay?: boolean): void;
261
+ initSlice(sliceIndex: number): Slice;
262
+ screenRendering(sh: Program, layerSlice: Layer[], sliceIndex: number, defaultTexture?: WebGLTextureExt | null, isOverlay?: boolean, forcedOpacity?: number): void;
259
263
  heightPickingRendering(sh: Program, layerSlice: Layer[]): void;
264
+ increaseTransitionOpacity(): void;
265
+ fadingTransitionOpacity(): void;
260
266
  colorPickingRendering(sh: Program, layerSlice: Layer[], sliceIndex: number, defaultTexture?: WebGLTextureExt | null, isOverlay?: boolean): void;
261
267
  depthRendering(sh: Program, layerSlice: Layer[]): void;
262
268
  protected _getIndexBuffer(): WebGLBufferExt;
@@ -106,6 +106,8 @@ class Segment {
106
106
  this.readyToEngage = false;
107
107
  this.plainProcessing = false;
108
108
  this.normalMapTexturePtr = null;
109
+ this._transitionOpacity = 1.0;
110
+ this._transitionTimestamp = 0;
109
111
  }
110
112
  checkZoom() {
111
113
  return this.tileZoom < this.planet.terrain._maxNodeZoom;
@@ -277,7 +279,7 @@ class Segment {
277
279
  }
278
280
  }
279
281
  _checkEqualization(neighborSide, neigborNode) {
280
- return neigborNode && this.tileZoom >= neigborNode.segment.tileZoom &&
282
+ return neigborNode && neigborNode.segment && this.tileZoom >= neigborNode.segment.tileZoom &&
281
283
  this.node.equalizedSideWithNodeId[neighborSide] !== neigborNode.equalizedSideWithNodeId[OPSIDE[neighborSide]];
282
284
  }
283
285
  equalize() {
@@ -430,10 +432,11 @@ class Segment {
430
432
  }
431
433
  _normalMapEdgeEqualize(side) {
432
434
  let nn = this.node.neighbors;
433
- let n = nn[side][0];
435
+ let nns = nn[side];
436
+ let n = nns && nns[0];
434
437
  let maxZ = this.planet.terrain.maxZoom;
435
438
  if (this.tileZoom === maxZ) {
436
- if (!(nn[0].length || nn[1].length || nn[2].length || nn[3].length)) {
439
+ if (nns && !(nn[0].length || nn[1].length || nn[2].length || nn[3].length)) {
437
440
  n = this.node.getEqualNeighbor(side);
438
441
  }
439
442
  }
@@ -556,6 +559,10 @@ class Segment {
556
559
  this.deleteMaterials();
557
560
  this.deleteElevations();
558
561
  }
562
+ childrenInitialized() {
563
+ let n = this.node.nodes;
564
+ return n.length === 4 && n[0].segment.initialized && n[1].segment.initialized && n[2].segment.initialized && n[3].segment.initialized;
565
+ }
559
566
  destroySegment() {
560
567
  this.clearSegment();
561
568
  let i = this._slices.length;
@@ -913,7 +920,18 @@ class Segment {
913
920
  const dSize_y = (v0t.northEast.lat - v0t.southWest.lat) / sSize_y;
914
921
  return [dV0s_x, dV0s_y, dSize_x, dSize_y];
915
922
  }
916
- screenRendering(sh, layerSlice, sliceIndex, defaultTexture, isOverlay = false) {
923
+ initSlice(sliceIndex) {
924
+ let slice = this._slices[sliceIndex];
925
+ if (!slice) {
926
+ slice = this._slices[sliceIndex] = new Slice(this);
927
+ }
928
+ else {
929
+ //TODO: optimization!!!
930
+ slice.layers = [];
931
+ }
932
+ return slice;
933
+ }
934
+ screenRendering(sh, layerSlice, sliceIndex, defaultTexture, isOverlay = false, forcedOpacity) {
917
935
  const gl = this.handler.gl;
918
936
  const sha = sh.attributes;
919
937
  const shu = sh.uniforms;
@@ -933,14 +951,7 @@ class Segment {
933
951
  gl.uniform1i(shu.defaultTexture, p.SLICE_SIZE + 2);
934
952
  let n = 0, i = 0;
935
953
  let notEmpty = false;
936
- let slice = this._slices[sliceIndex];
937
- if (!slice) {
938
- slice = this._slices[sliceIndex] = new Slice(this);
939
- }
940
- else {
941
- //TODO: optimization!!!
942
- slice.layers = [];
943
- }
954
+ let slice = this.initSlice(sliceIndex);
944
955
  this._indexBuffer = this._getIndexBuffer();
945
956
  while (li) {
946
957
  if (this.layerOverlap(li) &&
@@ -965,6 +976,7 @@ class Segment {
965
976
  li = layerSlice[i];
966
977
  }
967
978
  if (notEmpty || !isOverlay) {
979
+ gl.uniform1f(shu.transitionOpacity, forcedOpacity || this._transitionOpacity > 1.0 ? 1.0 : this._transitionOpacity);
968
980
  gl.uniform1i(shu.samplerCount, n);
969
981
  gl.uniform1f(shu.height, currHeight);
970
982
  gl.uniform1iv(shu.samplerArr, p._samplerArr);
@@ -1012,6 +1024,22 @@ class Segment {
1012
1024
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBuffer);
1013
1025
  gl.drawElements(gl.TRIANGLE_STRIP, this._indexBuffer.numItems, gl.UNSIGNED_INT, 0);
1014
1026
  }
1027
+ increaseTransitionOpacity() {
1028
+ //this._transitionOpacity += 0.01;
1029
+ this._transitionOpacity += (window.performance.now() - this._transitionTimestamp) / this.planet.transitionTime;
1030
+ this._transitionTimestamp = window.performance.now();
1031
+ if (this._transitionOpacity > 1.0) {
1032
+ this._transitionOpacity = 1.0;
1033
+ }
1034
+ }
1035
+ fadingTransitionOpacity() {
1036
+ //this._transitionOpacity -= 0.01;
1037
+ this._transitionOpacity -= (window.performance.now() - this._transitionTimestamp) / this.planet.transitionTime;
1038
+ this._transitionTimestamp = window.performance.now();
1039
+ if (this._transitionOpacity < 0.0) {
1040
+ this._transitionOpacity = 0;
1041
+ }
1042
+ }
1015
1043
  colorPickingRendering(sh, layerSlice, sliceIndex, defaultTexture, isOverlay = false) {
1016
1044
  const gl = this.handler.gl;
1017
1045
  const sha = sh.attributes;