@openglobus/og 0.18.5 → 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 (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 +173 -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 +198 -84
  31. package/lib/js/segment/Segment.d.ts +7 -1
  32. package/lib/js/segment/Segment.js +40 -12
  33. package/lib/js/shaders/drawnode.js +21 -2
  34. package/lib/js/shaders/geoObject.js +26 -18
  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]);
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
+ }
726
818
  }
727
819
  }
728
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,65 @@ 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;
1061
+ let i = renderedNodes.length;
1062
+ let _renderingFadingNodes = this._renderingFadingNodes;
1063
+ if (cam.slope > 0.78 || cam.getAltitude() > 10000) {
1064
+ _renderingFadingNodes = this._renderingFadingNodesNoDepth;
1065
+ }
979
1066
  while (i--) {
980
- let s = rn[i].segment;
981
- isEq && s.equalize();
982
- s.readyToEngage && s.engage();
983
- 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);
984
1084
  }
1085
+ }
1086
+ _renderingScreenNodesWithHeight(sh, cam, renderedNodes) {
1087
+ let gl = this.renderer.handler.gl;
1088
+ let firstPass = cam.isFirstPass;
1089
+ let sl = this._visibleTileLayerSlices;
985
1090
  gl.enable(gl.POLYGON_OFFSET_FILL);
1091
+ gl.disable(gl.CULL_FACE);
1092
+ let nodes = new Map;
1093
+ let transparentSegments = [];
986
1094
  for (let j = 1, len = sl.length; j < len; j++) {
987
1095
  let slj = sl[j];
988
- for (i = slj.length - 1; i >= 0; --i) {
1096
+ for (let i = slj.length - 1; i >= 0; --i) {
989
1097
  let li = slj[i];
990
1098
  if (li._fading && firstPass && li._refreshFadingOpacity()) {
991
1099
  slj.splice(i, 1);
992
1100
  }
993
1101
  }
994
1102
  gl.polygonOffset(0, -j);
995
- i = rn.length;
1103
+ let i = renderedNodes.length;
996
1104
  while (i--) {
997
- 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
+ }
998
1113
  }
999
1114
  }
1000
1115
  gl.disable(gl.POLYGON_OFFSET_FILL);
1116
+ gl.enable(gl.CULL_FACE);
1001
1117
  }
1002
1118
  _renderDistanceFramebufferPASS() {
1003
1119
  if (!this.terrain.isEmpty) {
@@ -1031,10 +1147,6 @@ export class Planet extends RenderNode {
1031
1147
  sh = h.programs.drawnode_colorPicking._program;
1032
1148
  let shu = sh.uniforms;
1033
1149
  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
1150
  gl.enable(gl.CULL_FACE);
1039
1151
  gl.uniformMatrix4fv(shu.viewMatrix, false, cam.getViewMatrix());
1040
1152
  gl.uniformMatrix4fv(shu.projectionMatrix, false, cam.getProjectionMatrix());
@@ -1047,6 +1159,8 @@ export class Planet extends RenderNode {
1047
1159
  while (i--) {
1048
1160
  rn[i].segment.colorPickingRendering(sh, sl[0], 0);
1049
1161
  }
1162
+ // Here is set blending for transparent overlays
1163
+ renderer.enableBlendDefault();
1050
1164
  gl.enable(gl.POLYGON_OFFSET_FILL);
1051
1165
  for (let j = 1, len = sl.length; j < len; j++) {
1052
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;
@@ -299,7 +299,8 @@ export function drawnode_screen_wl_webgl2NoAtmos() {
299
299
  ambient: "vec3",
300
300
  specular: "vec4",
301
301
  camHeight: "float",
302
- nightTextureCoefficient: "float"
302
+ nightTextureCoefficient: "float",
303
+ transitionOpacity: "float"
303
304
  }, attributes: {
304
305
  aVertexPositionHigh: "vec3",
305
306
  aVertexPositionLow: "vec3",
@@ -373,6 +374,8 @@ export function drawnode_screen_wl_webgl2NoAtmos() {
373
374
 
374
375
  uniform int samplerCount;
375
376
  uniform float nightTextureCoefficient;
377
+
378
+ uniform float transitionOpacity;
376
379
 
377
380
  uniform float camHeight;
378
381
 
@@ -424,8 +427,10 @@ export function drawnode_screen_wl_webgl2NoAtmos() {
424
427
  vec4 lightWeighting = vec4(ambient + diffuse * diffuseLightWeighting + night, 1.0);
425
428
 
426
429
  diffuseColor = texture( defaultTexture, vTextureCoord.xy );
430
+
427
431
  if( samplerCount == 0 ) {
428
432
  diffuseColor = diffuseColor * lightWeighting + vec4(spec, 0.0);
433
+ diffuseColor *= transitionOpacity;
429
434
  return;
430
435
  }
431
436
 
@@ -434,29 +439,34 @@ export function drawnode_screen_wl_webgl2NoAtmos() {
434
439
  blend(diffuseColor, samplerArr[0], tileOffsetArr[0], layerOpacityArr[0]);
435
440
  if( samplerCount == 1 ) {
436
441
  diffuseColor = diffuseColor * lightWeighting + vec4(spec, 0.0);
442
+ diffuseColor *= transitionOpacity;
437
443
  return;
438
444
  }
439
445
 
440
446
  blend(diffuseColor, samplerArr[1], tileOffsetArr[1], layerOpacityArr[1]);
441
447
  if( samplerCount == 2 ) {
442
448
  diffuseColor = diffuseColor * lightWeighting + vec4(spec, 0.0);
449
+ diffuseColor *= transitionOpacity;
443
450
  return;
444
451
  }
445
452
 
446
453
  blend(diffuseColor, samplerArr[2], tileOffsetArr[2], layerOpacityArr[2]);
447
454
  if( samplerCount == 3 ) {
448
455
  diffuseColor = diffuseColor * lightWeighting + vec4(spec, 0.0);
456
+ diffuseColor *= transitionOpacity;
449
457
  return;
450
458
  }
451
459
 
452
460
  blend(diffuseColor, samplerArr[3], tileOffsetArr[3], layerOpacityArr[3]);
453
461
  if( samplerCount == 4 ) {
454
462
  diffuseColor = diffuseColor * lightWeighting + vec4(spec, 0.0);
463
+ diffuseColor *= transitionOpacity;
455
464
  return;
456
465
  }
457
466
 
458
467
  blend(diffuseColor, samplerArr[4], tileOffsetArr[4], layerOpacityArr[4]);
459
468
  diffuseColor = diffuseColor * lightWeighting + vec4(spec, 0.0);
469
+ diffuseColor *= transitionOpacity;
460
470
  }`
461
471
  });
462
472
  }
@@ -486,7 +496,8 @@ export function drawnode_screen_wl_webgl2Atmos() {
486
496
  scatteringTexture: "sampler2D",
487
497
  camHeight: "float",
488
498
  nightTextureCoefficient: "float",
489
- maxMinOpacity: "vec2"
499
+ maxMinOpacity: "vec2",
500
+ transitionOpacity: "float"
490
501
  }, attributes: {
491
502
  aVertexPositionHigh: "vec3",
492
503
  aVertexPositionLow: "vec3",
@@ -566,6 +577,8 @@ export function drawnode_screen_wl_webgl2Atmos() {
566
577
 
567
578
  uniform vec2 maxMinOpacity;
568
579
  uniform float camHeight;
580
+
581
+ uniform float transitionOpacity;
569
582
 
570
583
  in vec4 vTextureCoord;
571
584
  in vec3 v_vertex;
@@ -749,6 +762,7 @@ export function drawnode_screen_wl_webgl2Atmos() {
749
762
  diffuseColor = texture( defaultTexture, vTextureCoord.xy );
750
763
  if( samplerCount == 0 ) {
751
764
  diffuseColor = mix(diffuseColor * lightWeighting, atmosColor, fadingOpacity) + vec4(spec, 0.0);
765
+ diffuseColor *= transitionOpacity;
752
766
  return;
753
767
  }
754
768
 
@@ -757,29 +771,34 @@ export function drawnode_screen_wl_webgl2Atmos() {
757
771
  blend(diffuseColor, samplerArr[0], tileOffsetArr[0], layerOpacityArr[0]);
758
772
  if( samplerCount == 1 ) {
759
773
  diffuseColor = mix(diffuseColor * lightWeighting, atmosColor * diffuseColor.a, fadingOpacity) + vec4(spec, 0.0);
774
+ diffuseColor *= transitionOpacity;
760
775
  return;
761
776
  }
762
777
 
763
778
  blend(diffuseColor, samplerArr[1], tileOffsetArr[1], layerOpacityArr[1]);
764
779
  if( samplerCount == 2 ) {
765
780
  diffuseColor = mix(diffuseColor * lightWeighting, atmosColor * diffuseColor.a, fadingOpacity) + vec4(spec, 0.0);
781
+ diffuseColor *= transitionOpacity;
766
782
  return;
767
783
  }
768
784
 
769
785
  blend(diffuseColor, samplerArr[2], tileOffsetArr[2], layerOpacityArr[2]);
770
786
  if( samplerCount == 3 ) {
771
787
  diffuseColor = mix(diffuseColor * lightWeighting, atmosColor * diffuseColor.a, fadingOpacity) + vec4(spec, 0.0);
788
+ diffuseColor *= transitionOpacity;
772
789
  return;
773
790
  }
774
791
 
775
792
  blend(diffuseColor, samplerArr[3], tileOffsetArr[3], layerOpacityArr[3]);
776
793
  if( samplerCount == 4 ) {
777
794
  diffuseColor = mix(diffuseColor * lightWeighting, atmosColor * diffuseColor.a, fadingOpacity) + vec4(spec, 0.0);
795
+ diffuseColor *= transitionOpacity;
778
796
  return;
779
797
  }
780
798
 
781
799
  blend(diffuseColor, samplerArr[4], tileOffsetArr[4], layerOpacityArr[4]);
782
800
  diffuseColor = mix(diffuseColor * lightWeighting, atmosColor * diffuseColor.a, fadingOpacity) + vec4(spec, 0.0);
801
+ diffuseColor *= transitionOpacity;
783
802
  }`
784
803
  });
785
804
  }