@openglobus/og 0.18.5 → 0.19.1

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 (38) hide show
  1. package/README.md +17 -69
  2. package/css/og.css +59 -44
  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/control/DebugInfo.js +5 -0
  11. package/lib/js/control/LayerSwitcher.d.ts +18 -3
  12. package/lib/js/control/LayerSwitcher.js +111 -11
  13. package/lib/js/control/MouseNavigation.d.ts +2 -0
  14. package/lib/js/control/MouseNavigation.js +15 -15
  15. package/lib/js/control/elevationProfile/ElevationProfile.js +3 -1
  16. package/lib/js/control/elevationProfile/ElevationProfileScene.js +7 -7
  17. package/lib/js/control/heightRuler/HeightRulerScene.js +1 -1
  18. package/lib/js/control/ruler/RulerScene.js +3 -3
  19. package/lib/js/control/selection/SelectionScene.js +2 -2
  20. package/lib/js/entity/Entity.js +5 -1
  21. package/lib/js/layer/Layer.d.ts +18 -4
  22. package/lib/js/layer/Layer.js +25 -4
  23. package/lib/js/layer/XYZ.d.ts +0 -1
  24. package/lib/js/quadTree/Node.d.ts +21 -3
  25. package/lib/js/quadTree/Node.js +161 -62
  26. package/lib/js/renderer/Renderer.js +19 -16
  27. package/lib/js/renderer/RendererEvents.d.ts +1 -0
  28. package/lib/js/renderer/RendererEvents.js +5 -0
  29. package/lib/js/scene/Planet.d.ts +29 -4
  30. package/lib/js/scene/Planet.js +207 -85
  31. package/lib/js/segment/Segment.d.ts +7 -1
  32. package/lib/js/segment/Segment.js +57 -12
  33. package/lib/js/shaders/drawnode.js +21 -2
  34. package/lib/js/shaders/geoObject.js +30 -24
  35. package/lib/js/terrain/GlobusTerrain.js +1 -1
  36. package/lib/js/utils/shared.d.ts +1 -0
  37. package/lib/js/utils/shared.js +1 -0
  38. package/package.json +2 -2
@@ -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,14 @@ 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;
151
202
  }
152
203
  /**
153
204
  * Returns true if current terrain data set is loaded
@@ -378,6 +429,7 @@ export class Planet extends RenderNode {
378
429
  h.removeProgram("drawnode_screen_wl");
379
430
  if (this._atmosphereEnabled) {
380
431
  this._renderScreenNodesPASS = this._renderScreenNodesPASSAtmos;
432
+ this._renderScreenNodesWithHeightPASS = this._renderScreenNodesWithHeightPASSAtmos;
381
433
  if (h.isWebGl2()) {
382
434
  h.addProgram(shaders.drawnode_screen_wl_webgl2Atmos(), true);
383
435
  }
@@ -396,6 +448,7 @@ export class Planet extends RenderNode {
396
448
  }
397
449
  else {
398
450
  this._renderScreenNodesPASS = this._renderScreenNodesPASSNoAtmos;
451
+ this._renderScreenNodesWithHeightPASS = this._renderScreenNodesWithHeightPASSNoAtmos;
399
452
  if (this.renderer.controls.Atmosphere) {
400
453
  this.renderer.controls.Atmosphere.deactivate();
401
454
  }
@@ -462,6 +515,9 @@ export class Planet extends RenderNode {
462
515
  this._renderCompletedActivated = false;
463
516
  this._terrainCompletedActivated = false;
464
517
  });
518
+ this.renderer.events.on("drawtransparent", () => {
519
+ this._renderScreenNodesWithHeightPASS();
520
+ });
465
521
  // Initialize texture coordinates buffer pool
466
522
  this._textureCoordsBufferCache = [];
467
523
  let texCoordCache = segmentHelper.getInstance().initTextureCoordsTable(TABLESIZE + 1);
@@ -679,25 +735,7 @@ export class Planet extends RenderNode {
679
735
  this._renderedNodesInFrustum[i] = [];
680
736
  }
681
737
  }
682
- /**
683
- * Collects visible quad nodes.
684
- * @protected
685
- */
686
- _collectRenderNodes() {
687
- let cam = this.camera;
688
- this._lodSize = math.lerp(cam.slope < 0.0 ? 0.0 : cam.slope, this._curLodSize, this._minLodSize);
689
- cam._insideSegment = null;
690
- // clear first
691
- this._clearRenderedNodeList();
692
- this._clearRenderNodesInFrustum();
693
- this._viewExtent.southWest.set(180, 180);
694
- this._viewExtent.northEast.set(-180, -180);
695
- this._visibleNodes = {};
696
- this._visibleNodesNorth = {};
697
- this._visibleNodesSouth = {};
698
- this.minCurrZoom = math.MAX;
699
- this.maxCurrZoom = math.MIN;
700
- this.quadTreeStrategy.collectRenderNodes();
738
+ _collectRenderedNodesMaxZoom(cam) {
701
739
  if (cam.slope > this.minEqualZoomCameraSlope && cam._lonLat.height < this.maxEqualZoomAltitude && cam._lonLat.height > this.minEqualZoomAltitude) {
702
740
  this.minCurrZoom = this.maxCurrZoom;
703
741
  let temp = this._renderedNodes, rf = this._renderedNodesInFrustum, temp2 = [];
@@ -722,10 +760,92 @@ export class Planet extends RenderNode {
722
760
  }
723
761
  }
724
762
  for (let i = 0, len = temp2.length; i < len; i++) {
725
- temp2[i].renderTree(cam, this.maxCurrZoom, null);
763
+ temp2[i].renderTree(cam, this.maxCurrZoom, null, false, temp2[i]);
726
764
  }
727
765
  }
728
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
+ }
818
+ }
819
+ }
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
+ }
729
849
  _globalPreDraw() {
730
850
  let cam = this.camera;
731
851
  // Might be it's better to replace it in setTerrain,
@@ -755,7 +875,7 @@ export class Planet extends RenderNode {
755
875
  if (this.camera.isFirstPass) {
756
876
  this.camera.update();
757
877
  if (this._skipPreRender && this._collectRenderNodesIsActive) {
758
- this._collectRenderNodes();
878
+ this._collectRenderNodes(this.camera);
759
879
  }
760
880
  this._skipPreRender = true;
761
881
  this.transformLights();
@@ -777,6 +897,7 @@ export class Planet extends RenderNode {
777
897
  }
778
898
  /**
779
899
  * Render node callback.
900
+ * Frame function is called for each renderer activrCamera frustum.
780
901
  * @public
781
902
  * @override
782
903
  */
@@ -813,14 +934,11 @@ export class Planet extends RenderNode {
813
934
  this._collectRenderNodesIsActive = true;
814
935
  this.camera.setTerrainCollisionActivity(true);
815
936
  }
816
- _renderScreenNodesPASSNoAtmos() {
937
+ _setUniformsNoAtmos(cam) {
817
938
  let sh, shu;
818
939
  let renderer = this.renderer;
819
940
  let h = renderer.handler;
820
941
  let gl = h.gl;
821
- let cam = renderer.activeCamera;
822
- let firstPass = cam.isFirstPass;
823
- let frustumIndex = cam.currentFrustumIndex;
824
942
  gl.enable(gl.CULL_FACE);
825
943
  renderer.enableBlendOneSrcAlpha();
826
944
  if (this.lightEnabled) {
@@ -862,54 +980,13 @@ export class Planet extends RenderNode {
862
980
  }
863
981
  gl.uniform3fv(shu.eyePositionHigh, cam.eyeHigh);
864
982
  gl.uniform3fv(shu.eyePositionLow, cam.eyeLow);
865
- //
866
- // drawing planet nodes
867
- //
868
- let rn = this._renderedNodesInFrustum[frustumIndex], sl = this._visibleTileLayerSlices;
869
- if (sl.length) {
870
- let sli = sl[0];
871
- for (let i = sli.length - 1; i >= 0; --i) {
872
- let li = sli[i];
873
- if (li._fading && firstPass && li._refreshFadingOpacity()) {
874
- sli.splice(i, 1);
875
- }
876
- }
877
- }
878
- let isEq = this.terrain.equalizeVertices;
879
- let i = rn.length;
880
- while (i--) {
881
- let s = rn[i].segment;
882
- isEq && s.equalize();
883
- s.readyToEngage && s.engage();
884
- s.screenRendering(sh, sl[0], 0);
885
- }
886
- gl.enable(gl.POLYGON_OFFSET_FILL);
887
- //gl.disable(gl.CULL_FACE);
888
- for (let j = 1, len = sl.length; j < len; j++) {
889
- let slj = sl[j];
890
- for (i = slj.length - 1; i >= 0; --i) {
891
- let li = slj[i];
892
- if (li._fading && firstPass && li._refreshFadingOpacity()) {
893
- slj.splice(i, 1);
894
- }
895
- }
896
- gl.polygonOffset(0, -j);
897
- i = rn.length;
898
- while (i--) {
899
- rn[i].segment.screenRendering(sh, sl[j], j, this.transparentTexture, true);
900
- }
901
- }
902
- //gl.enable(gl.CULL_FACE);
903
- gl.disable(gl.POLYGON_OFFSET_FILL);
983
+ return sh;
904
984
  }
905
- _renderScreenNodesPASSAtmos() {
985
+ _setUniformsAtmos(cam) {
906
986
  let sh, shu;
907
987
  let renderer = this.renderer;
908
988
  let h = renderer.handler;
909
989
  let gl = h.gl;
910
- let cam = renderer.activeCamera;
911
- let firstPass = cam.isFirstPass;
912
- let frustumIndex = cam.currentFrustumIndex;
913
990
  gl.enable(gl.CULL_FACE);
914
991
  renderer.enableBlendOneSrcAlpha();
915
992
  if (this.lightEnabled) {
@@ -961,10 +1038,14 @@ export class Planet extends RenderNode {
961
1038
  }
962
1039
  gl.uniform3fv(shu.eyePositionHigh, cam.eyeHigh);
963
1040
  gl.uniform3fv(shu.eyePositionLow, cam.eyeLow);
964
- //
965
- // drawing planet nodes
966
- //
967
- 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;
968
1049
  if (sl.length) {
969
1050
  let sli = sl[0];
970
1051
  for (let i = sli.length - 1; i >= 0; --i) {
@@ -974,30 +1055,73 @@ export class Planet extends RenderNode {
974
1055
  }
975
1056
  }
976
1057
  }
1058
+ let nodes = new Map;
1059
+ let transparentSegments = [];
977
1060
  let isEq = this.terrain.equalizeVertices;
978
- let i = rn.length;
979
- while (i--) {
980
- let s = rn[i].segment;
981
- isEq && s.equalize();
982
- s.readyToEngage && s.engage();
983
- s.screenRendering(sh, sl[0], 0);
1061
+ let i = renderedNodes.length;
1062
+ if (cam.slope > 0.8 /*|| cam.getAltitude() > 10000*/) {
1063
+ while (i--) {
1064
+ let ri = renderedNodes[i];
1065
+ let s = ri.segment;
1066
+ this._renderingFadingNodesNoDepth(nodes, sh, ri, sl[0], 0);
1067
+ isEq && s.equalize();
1068
+ s.readyToEngage && s.engage();
1069
+ s.screenRendering(sh, sl[0], 0);
1070
+ }
984
1071
  }
1072
+ else {
1073
+ while (i--) {
1074
+ let ri = renderedNodes[i];
1075
+ let s = ri.segment;
1076
+ this._renderingFadingNodes(nodes, sh, ri, sl[0], 0, transparentSegments);
1077
+ if (s._transitionOpacity < 1) {
1078
+ transparentSegments.push(s);
1079
+ }
1080
+ else {
1081
+ isEq && s.equalize();
1082
+ s.readyToEngage && s.engage();
1083
+ s.screenRendering(sh, sl[0], 0);
1084
+ }
1085
+ }
1086
+ for (let j = 0; j < transparentSegments.length; j++) {
1087
+ let tj = transparentSegments[j];
1088
+ isEq && tj.equalize();
1089
+ tj.readyToEngage && tj.engage();
1090
+ tj.screenRendering(sh, sl[0], 0);
1091
+ }
1092
+ }
1093
+ }
1094
+ _renderingScreenNodesWithHeight(sh, cam, renderedNodes) {
1095
+ let gl = this.renderer.handler.gl;
1096
+ let firstPass = cam.isFirstPass;
1097
+ let sl = this._visibleTileLayerSlices;
985
1098
  gl.enable(gl.POLYGON_OFFSET_FILL);
1099
+ gl.disable(gl.CULL_FACE);
1100
+ let nodes = new Map;
1101
+ let transparentSegments = [];
986
1102
  for (let j = 1, len = sl.length; j < len; j++) {
987
1103
  let slj = sl[j];
988
- for (i = slj.length - 1; i >= 0; --i) {
1104
+ for (let i = slj.length - 1; i >= 0; --i) {
989
1105
  let li = slj[i];
990
1106
  if (li._fading && firstPass && li._refreshFadingOpacity()) {
991
1107
  slj.splice(i, 1);
992
1108
  }
993
1109
  }
994
1110
  gl.polygonOffset(0, -j);
995
- i = rn.length;
1111
+ let i = renderedNodes.length;
996
1112
  while (i--) {
997
- rn[i].segment.screenRendering(sh, sl[j], j, this.transparentTexture, true);
1113
+ let ri = renderedNodes[i];
1114
+ this._renderingFadingNodes(nodes, sh, ri, sl[j], j, transparentSegments);
1115
+ if (ri.segment._transitionOpacity < 1) {
1116
+ ri.segment.initSlice(j);
1117
+ }
1118
+ else {
1119
+ ri.segment.screenRendering(sh, sl[j], j, this.transparentTexture, true);
1120
+ }
998
1121
  }
999
1122
  }
1000
1123
  gl.disable(gl.POLYGON_OFFSET_FILL);
1124
+ gl.enable(gl.CULL_FACE);
1001
1125
  }
1002
1126
  _renderDistanceFramebufferPASS() {
1003
1127
  if (!this.terrain.isEmpty) {
@@ -1031,10 +1155,6 @@ export class Planet extends RenderNode {
1031
1155
  sh = h.programs.drawnode_colorPicking._program;
1032
1156
  let shu = sh.uniforms;
1033
1157
  let cam = renderer.activeCamera;
1034
- // Special blend
1035
- // gl.enable(gl.BLEND);
1036
- // gl.blendEquation(gl.FUNC_ADD);
1037
- // gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
1038
1158
  gl.enable(gl.CULL_FACE);
1039
1159
  gl.uniformMatrix4fv(shu.viewMatrix, false, cam.getViewMatrix());
1040
1160
  gl.uniformMatrix4fv(shu.projectionMatrix, false, cam.getProjectionMatrix());
@@ -1047,6 +1167,8 @@ export class Planet extends RenderNode {
1047
1167
  while (i--) {
1048
1168
  rn[i].segment.colorPickingRendering(sh, sl[0], 0);
1049
1169
  }
1170
+ // Here is set blending for transparent overlays
1171
+ renderer.enableBlendDefault();
1050
1172
  gl.enable(gl.POLYGON_OFFSET_FILL);
1051
1173
  for (let j = 1, len = sl.length; j < len; j++) {
1052
1174
  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,39 @@ 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 > 2.0) {
1032
+ this._transitionOpacity = 2.0;
1033
+ }
1034
+ let i = this.node._fadingNodes.length;
1035
+ while (i--) {
1036
+ let n = this.node._fadingNodes[i];
1037
+ if (n.segment) {
1038
+ if (n.segment._transitionOpacity > 0 && !this.planet._fadingNodes.has(n.nodeId)) {
1039
+ this.planet._fadingNodes.set(n.nodeId, n);
1040
+ n.segment._transitionOpacity = 2.0 - this._transitionOpacity;
1041
+ if (n.segment._transitionOpacity === 0) {
1042
+ this.node._fadingNodes.splice(i, 1);
1043
+ }
1044
+ }
1045
+ }
1046
+ else {
1047
+ this._transitionOpacity = 1.0;
1048
+ break;
1049
+ }
1050
+ }
1051
+ }
1052
+ fadingTransitionOpacity() {
1053
+ this._transitionOpacity -= 0.01;
1054
+ // this._transitionOpacity -= (window.performance.now() - this._transitionTimestamp) / this.planet.transitionTime;
1055
+ this._transitionTimestamp = window.performance.now();
1056
+ if (this._transitionOpacity < 0.0) {
1057
+ this._transitionOpacity = 0;
1058
+ }
1059
+ }
1015
1060
  colorPickingRendering(sh, layerSlice, sliceIndex, defaultTexture, isOverlay = false) {
1016
1061
  const gl = this.handler.gl;
1017
1062
  const sha = sh.attributes;