@openglobus/og 0.13.5 → 0.13.8

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 (78) hide show
  1. package/css/og.css +66 -25
  2. package/dist/@openglobus/og.css +1 -1
  3. package/dist/@openglobus/og.esm.js +2 -2
  4. package/dist/@openglobus/og.esm.js.map +1 -1
  5. package/dist/@openglobus/og.umd.js +2 -2
  6. package/dist/@openglobus/og.umd.js.map +1 -1
  7. package/package.json +1 -1
  8. package/src/og/Events.js +188 -188
  9. package/src/og/Extent.js +1 -9
  10. package/src/og/Globe.js +1 -0
  11. package/src/og/Object3d.js +384 -0
  12. package/src/og/arial.js +1705 -1703
  13. package/src/og/camera/Camera.js +640 -640
  14. package/src/og/control/DebugInfo.js +15 -4
  15. package/src/og/control/EarthCoordinates.js +151 -160
  16. package/src/og/control/KeyboardNavigation.js +48 -2
  17. package/src/og/control/LayerAnimation.js +115 -0
  18. package/src/og/control/MouseNavigation.js +460 -460
  19. package/src/og/control/Sun.js +170 -170
  20. package/src/og/control/TouchNavigation.js +13 -13
  21. package/src/og/control/ZoomControl.js +1 -3
  22. package/src/og/control/index.js +3 -1
  23. package/src/og/control/ruler/Ruler.js +43 -0
  24. package/src/og/control/ruler/RulerScene.js +370 -0
  25. package/src/og/control/visibleExtent/Segment.js +1 -4
  26. package/src/og/ellipsoid/Ellipsoid.js +20 -1
  27. package/src/og/entity/Entity.js +1 -1
  28. package/src/og/entity/GeoObject.js +1 -1
  29. package/src/og/entity/LabelHandler.js +3 -2
  30. package/src/og/input/input.js +7 -1
  31. package/src/og/layer/CanvasTiles.js +8 -8
  32. package/src/og/layer/KML.js +181 -12
  33. package/src/og/layer/Layer.js +27 -42
  34. package/src/og/layer/Vector.js +80 -14
  35. package/src/og/layer/XYZ.js +8 -2
  36. package/src/og/math/Vec3.js +1 -1
  37. package/src/og/math.js +4 -4
  38. package/src/og/quadTree/Node.js +2 -1
  39. package/src/og/renderer/Renderer.js +1 -2
  40. package/src/og/renderer/RendererEvents.js +17 -3
  41. package/src/og/res/images.js +0 -2
  42. package/src/og/scene/Planet.js +92 -32
  43. package/src/og/segment/Segment.js +1 -8
  44. package/src/og/shaders/label.js +30 -42
  45. package/src/og/terrain/EmptyTerrain.js +164 -146
  46. package/src/og/terrain/Geoid.js +246 -241
  47. package/src/og/terrain/GlobusTerrain.js +23 -24
  48. package/src/og/terrain/MapboxTerrain.js +292 -294
  49. package/src/og/utils/FontAtlas.js +1 -2
  50. package/src/og/utils/Loader.js +160 -112
  51. package/src/og/utils/PlainSegmentWorker.js +38 -26
  52. package/src/og/utils/VectorTileCreator.js +1 -1
  53. package/src/og/utils/units.js +78 -0
  54. package/src/og/webgl/ProgramController.js +143 -143
  55. package/types/Object3d.d.ts +21 -0
  56. package/types/arial.d.ts +1 -0
  57. package/types/control/EarthCoordinates.d.ts +27 -30
  58. package/types/control/KeyboardNavigation.d.ts +3 -0
  59. package/types/control/Sun.d.ts +1 -1
  60. package/types/control/index.d.ts +2 -1
  61. package/types/control/ruler/Ruler.d.ts +13 -0
  62. package/types/control/ruler/RulerScene.d.ts +48 -0
  63. package/types/ellipsoid/Ellipsoid.d.ts +8 -0
  64. package/types/input/input.d.ts +6 -0
  65. package/types/layer/KML.d.ts +26 -1
  66. package/types/layer/Layer.d.ts +23 -31
  67. package/types/layer/Vector.d.ts +2 -0
  68. package/types/layer/XYZ.d.ts +1 -0
  69. package/types/math.d.ts +1 -1
  70. package/types/renderer/RendererEvents.d.ts +2 -0
  71. package/types/res/images.d.ts +0 -1
  72. package/types/scene/Planet.d.ts +12 -3
  73. package/types/terrain/EmptyTerrain.d.ts +4 -1
  74. package/types/terrain/Geoid.d.ts +1 -10
  75. package/types/terrain/GlobusTerrain.d.ts +0 -2
  76. package/types/terrain/MapboxTerrain.d.ts +1 -1
  77. package/types/utils/Loader.d.ts +4 -0
  78. package/types/utils/units.d.ts +20 -0
@@ -0,0 +1,370 @@
1
+ 'use strict';
2
+
3
+ import * as math from '../../math.js';
4
+ import { RenderNode } from '../../scene/RenderNode.js';
5
+ import { Events } from '../../Events.js';
6
+ import { LonLat } from '../../LonLat.js';
7
+ import { Vec3 } from '../../math/Vec3.js';
8
+ import { Vec2 } from '../../math/Vec2.js';
9
+ import { Vector } from '../../layer/Vector.js';
10
+ import { Entity } from '../../entity/Entity.js';
11
+ import { Ellipsoid } from '../../ellipsoid/Ellipsoid.js';
12
+ import { Object3d } from '../../Object3d.js';
13
+
14
+ const OUTLINE_COUNT = 120;
15
+
16
+ const MAX_SCALE = 0.005;
17
+ const MIN_SCALE = 0.001;
18
+ const MAX_SCALE_HEIGHT = 3000.0;
19
+ const MIN_SCALE_HEIGHT = 19000000.0;
20
+
21
+ function distanceFormat(v) {
22
+ if (v > 1000) {
23
+ return `${(v / 1000).toFixed(1)} km`;
24
+ } else if (v > 9) {
25
+ return `${Math.round(v)} m`;
26
+ } else {
27
+ return `${v.toFixed(1)} m`;
28
+ }
29
+ }
30
+
31
+ class RulerScene extends RenderNode {
32
+ constructor(options = {}) {
33
+ super(options.name);
34
+
35
+ this.events = new Events(EVENT_NAMES);
36
+
37
+ this._ignoreTerrain = options.ignoreTerrain != undefined ? options.ignoreTerrain : true;
38
+
39
+ this._planet = options.planet || null;
40
+
41
+ this._startLonLat = null;
42
+ this._preventClick = false;
43
+ this._stopDrawing = false;
44
+
45
+ this._pickedCorner = null;
46
+ this._startPos = null;
47
+ this._startClick = new Vec2();
48
+
49
+ this._heading = 0;
50
+
51
+ this._propsLabel = new Entity({
52
+ 'name': 'propsLabel',
53
+ 'label': {
54
+ text: "",
55
+ size: 11,
56
+ color: "rgba(455,455,455,1.0)",
57
+ outlineColor: "rgba(0,0,0,0.34)",
58
+ outline: 0.23,
59
+ align: "center",
60
+ offset: [0, 18]
61
+ }
62
+ });
63
+
64
+ this._propsLabel.label.setVisibility(false);
65
+
66
+ this._trackEntity = new Entity({
67
+ polyline: {
68
+ path3v: [],
69
+ thickness: 3.8,
70
+ color: "rgb(455,455,455)",
71
+ isClosed: false
72
+ }
73
+ });
74
+
75
+ this._trackEntity.polyline.altitude = 0.01;
76
+
77
+ let obj3d = Object3d.createCylinder(1.1, 0, 2.7, 20, 1, true, false, 0, 0, 0)
78
+
79
+ this._cornerEntity = [
80
+ new Entity({
81
+ geoObject: {
82
+ scale: 1,
83
+ instanced: true,
84
+ tag: "ruler",
85
+ color: "rgb(0,305,0)",
86
+ vertices: obj3d.vertices,
87
+ indices: obj3d.indexes,
88
+ normals: obj3d.normals
89
+ },
90
+ properties: {
91
+ name: "start"
92
+ }
93
+ }),
94
+ new Entity({
95
+ geoObject: {
96
+ scale: 1,
97
+ instanced: true,
98
+ tag: "ruler",
99
+ color: "rgb(455,0,0)",
100
+ vertices: obj3d.vertices,
101
+ indices: obj3d.indexes,
102
+ normals: obj3d.normals
103
+ },
104
+ properties: {
105
+ name: "end"
106
+ }
107
+
108
+ })
109
+ ];
110
+
111
+ this._trackLayer = new Vector("track", {
112
+ entities: [this._trackEntity, this._propsLabel],
113
+ pickingEnabled: false,
114
+ polygonOffsetUnits: -1.0,
115
+ relativeToGround: true
116
+ });
117
+
118
+ this._cornersLayer = new Vector("corners", {
119
+ entities: [this._cornerEntity[0], this._cornerEntity[1]],
120
+ pickingEnabled: true
121
+ });
122
+ }
123
+
124
+ set ignoreTerrain(v) {
125
+ this._ignoreTerrain = v;
126
+ if (v) {
127
+ //...redraw line
128
+ }
129
+ }
130
+
131
+ bindPlanet(planet) {
132
+ this._planet = planet;
133
+ }
134
+
135
+ init() {
136
+ this._activate();
137
+ }
138
+
139
+ onremove() {
140
+ this._deactivate();
141
+ }
142
+
143
+ _activate() {
144
+ this._propsLabel.label.setVisibility(false);
145
+ this._onLclick_ = this._onLclick.bind(this);
146
+ this.renderer.events.on("lclick", this._onLclick_, this);
147
+ this._onMouseMove_ = this._onMouseMove.bind(this);
148
+ this.renderer.events.on("mousemove", this._onMouseMove_, this);
149
+ this._onLdblclick_ = this._onLdblclick.bind(this);
150
+ this.renderer.events.on("ldblclick", this._onLdblclick_, this);
151
+
152
+ this._onCornerEnter_ = this._onCornerEnter.bind(this);
153
+ this._cornersLayer.events.on("mouseenter", this._onCornerEnter_, this);
154
+
155
+ this._onCornerLeave_ = this._onCornerLeave.bind(this);
156
+ this._cornersLayer.events.on("mouseleave", this._onCornerLeave_, this);
157
+
158
+ this._onCornerLdown_ = this._onCornerLdown.bind(this);
159
+ this._cornersLayer.events.on("ldown", this._onCornerLdown_, this);
160
+
161
+ this._onCornerLup_ = this._onCornerLup.bind(this);
162
+ this._cornersLayer.events.on("lup", this._onCornerLup, this);
163
+
164
+ this._planet.addLayer(this._trackLayer);
165
+ this._planet.addLayer(this._cornersLayer);
166
+ }
167
+
168
+ _deactivate() {
169
+ this._startLonLat = null;
170
+ this._preventClick = false;
171
+ this._stopDrawing = false;
172
+ this._pickedCorner = null;
173
+ this._trackLayer.remove();
174
+ this._cornersLayer.remove();
175
+ this.renderer.events.off("lclick", this._onLclick_);
176
+ this.renderer.events.off("mousemove", this._onMouseMove_);
177
+ this._cornersLayer.events.off("mouseenter", this._onCornerEnter_);
178
+ this._cornersLayer.events.off("mouseleave", this._onCornerLeave_);
179
+ this._cornersLayer.events.off("ldown", this._onCornerLdown_);
180
+ this._cornersLayer.events.off("lup", this._onCornerLup_);
181
+
182
+ this.clear();
183
+
184
+ this._onLclick_ = null;
185
+ this._onMouseMove_ = null;
186
+ this._onCornerLeave_ = null;
187
+ this._onCornerEnter_ = null;
188
+ this._onCornerLdown_ = null;
189
+ this._onCornerLup_ = null;
190
+ }
191
+
192
+ _onCornerLdown(e) {
193
+ if (!this._startLonLat) {
194
+ this.renderer.controls.mouseNavigation.deactivate();
195
+ this._startClick.set(e.x, e.y);
196
+ let coords = e.pickingObject.getCartesian();
197
+ this._startPos = this._planet.getPixelFromCartesian(coords);
198
+ this._pickedCorner = e.pickingObject;
199
+ if (e.pickingObject.properties.name == "start") {
200
+ this._anchorLonLat = this._cornerEntity[1].getLonLat().clone();
201
+ } else {
202
+ this._anchorLonLat = this._cornerEntity[0].getLonLat().clone();
203
+ }
204
+ }
205
+ }
206
+
207
+ _onCornerLup(e) {
208
+ if (this._pickedCorner) {
209
+ this.renderer.controls.mouseNavigation.activate();
210
+ this._pickedCorner = null;
211
+ this._anchorLonLat = null;
212
+ }
213
+ }
214
+
215
+ _onCornerEnter(e) {
216
+ e.renderer.handler.canvas.style.cursor = "pointer";
217
+ }
218
+
219
+ _onCornerLeave(e) {
220
+ e.renderer.handler.canvas.style.cursor = "default";
221
+ }
222
+
223
+ _onLdblclick() {
224
+ this._preventClick = true;
225
+ }
226
+
227
+ _onLclick(e) {
228
+ let startLonLat = this._planet.getLonLatFromPixelTerrain(e);
229
+ this._timeout = setTimeout(() => {
230
+ if (!this._preventClick) {
231
+ if (!this._startLonLat) {
232
+ this._stopDrawing = false;
233
+ this._propsLabel.label.setVisibility(false);
234
+ this._trackEntity.polyline.setPath3v([]);
235
+ this._cornerEntity[0].geoObject.setVisibility(true);
236
+ this._cornerEntity[1].geoObject.setVisibility(true);
237
+ this._startLonLat = startLonLat;
238
+ } else {
239
+ this._startLonLat = null;
240
+ }
241
+ }
242
+ this._preventClick = false;
243
+ this._stopDrawing = false;
244
+ clearTimeout(this._timeout);
245
+ }, 200);
246
+
247
+ if (this._startLonLat) {
248
+ this._stopDrawing = true;
249
+ }
250
+ }
251
+
252
+ _drawLine(startLonLat, endLonLat, startPos) {
253
+
254
+ if (!startPos) {
255
+ startPos = this._planet.ellipsoid.lonLatToCartesian(startLonLat);
256
+ }
257
+
258
+ let endPos = this._planet.ellipsoid.lonLatToCartesian(endLonLat);
259
+
260
+ let length = this._planet.ellipsoid.getGreatCircleDistance(startLonLat, endLonLat);
261
+ this._heading = Ellipsoid.getRhumbBearing(startLonLat, endLonLat);
262
+
263
+ let path = [];
264
+ let dir = endPos.sub(startPos);
265
+ let dist = dir.length();
266
+ dir.normalize();
267
+
268
+ for (let i = 0; i < OUTLINE_COUNT; i++) {
269
+ let f = dir.scaleTo(i * dist / OUTLINE_COUNT).addA(startPos);
270
+ path.push(f);
271
+ }
272
+ path.push(endPos);
273
+
274
+ this._trackEntity.polyline.setPath3v([path]);
275
+
276
+ if (this._ignoreTerrain) {
277
+ this._propsLabel.setCartesian3v(path[Math.floor(path.length / 2)]);
278
+ this._propsLabel.label.setText(`${distanceFormat(length)}, ${Math.round(this._heading)} deg`);
279
+ }
280
+ }
281
+
282
+ _onMouseMove(e) {
283
+ if (this._startLonLat && !this._stopDrawing) {
284
+ this._propsLabel.label.setVisibility(true);
285
+ let endLonLat = this._planet.getLonLatFromPixelTerrain(e);
286
+ if (!endLonLat) return;
287
+ this._drawLine(this._startLonLat, endLonLat);
288
+ } else if (this._pickedCorner) {
289
+ let newLonLat = this._planet.getLonLatFromPixelTerrain(e);
290
+ if (newLonLat) {
291
+ if (this._pickedCorner.properties.name === "start") {
292
+ this._drawLine(newLonLat, this._anchorLonLat);
293
+ } else {
294
+ this._drawLine(this._anchorLonLat, newLonLat);
295
+ }
296
+ }
297
+ }
298
+ }
299
+
300
+ clear() {
301
+ // удаляем трек
302
+ this._trackEntity.polyline.clear();
303
+ this._cornerEntity[0].geoObject.setVisibility(false);
304
+ this._cornerEntity[1].geoObject.setVisibility(false);
305
+ }
306
+
307
+ getScale(cart) {
308
+ let r = this.renderer;
309
+ let t = 1.0 - (r.activeCamera._lonLat.height - MAX_SCALE_HEIGHT) / (MIN_SCALE_HEIGHT - MAX_SCALE_HEIGHT);
310
+ let _distanceToCamera = cart.distance(r.activeCamera.eye);
311
+ return math.lerp(t < 0 ? 0 : t, MAX_SCALE, MIN_SCALE) * _distanceToCamera;
312
+ }
313
+
314
+ frame() {
315
+ let t = this._trackEntity.polyline.getPath3v()[0];
316
+ if (t) {
317
+ this._cornerEntity[0].setCartesian3v(t[0].clone());
318
+ this._cornerEntity[1].setCartesian3v(t[t.length - 1].clone());
319
+
320
+ this._cornerEntity[0].geoObject.setScale(this.getScale(this._cornerEntity[0].getCartesian()));
321
+ this._cornerEntity[1].geoObject.setScale(this.getScale(this._cornerEntity[1].getCartesian()));
322
+
323
+ if (!this._ignoreTerrain) {
324
+ let res = 0;
325
+ for (let i = 0, len = t.length - 1; i < len; i++) {
326
+ res += t[i + 1].distance(t[i]);
327
+ }
328
+
329
+ this._propsLabel.setCartesian3v(t[Math.floor(t.length / 2)]);
330
+ this._propsLabel.label.setText(`${distanceFormat(res)}, ${Math.round(this._heading)} deg`);
331
+ }
332
+ }
333
+ }
334
+
335
+ get ellipsoid() {
336
+ return this._planet ? this._planet.ellipsoid : null;
337
+ }
338
+ }
339
+
340
+ const EVENT_NAMES = [
341
+ "add",
342
+ "remove",
343
+ "mousemove",
344
+ "mouseenter",
345
+ "mouseleave",
346
+ "lclick",
347
+ "rclick",
348
+ "mclick",
349
+ "ldblclick",
350
+ "rdblclick",
351
+ "mdblclick",
352
+ "lup",
353
+ "rup",
354
+ "mup",
355
+ "ldown",
356
+ "rdown",
357
+ "mdown",
358
+ "lhold",
359
+ "rhold",
360
+ "mhold",
361
+ "mousewheel",
362
+ "touchmove",
363
+ "touchstart",
364
+ "touchend",
365
+ "doubletouch",
366
+ "touchleave",
367
+ "touchenter"
368
+ ];
369
+
370
+ export { RulerScene };
@@ -257,10 +257,7 @@ class Segment {
257
257
  * @returns {boolean} -
258
258
  */
259
259
  acceptForRendering(camera) {
260
- return (
261
- camera.projectedSize(this.bsphere.center, this._plainRadius) <
262
- 256 / this.planet._lodRatio
263
- );
260
+ return camera.projectedSize(this.bsphere.center, this._plainRadius) < (256 / this.planet._lodRatio);
264
261
  }
265
262
 
266
263
  /**
@@ -57,6 +57,25 @@ class Ellipsoid {
57
57
  return -Math.acos(d);
58
58
  }
59
59
 
60
+ /**
61
+ * Returns the distance travelling from ‘this’ point to destination point along a rhumb line.
62
+ *
63
+ * @param {LonLat} start coordinates.
64
+ * @param {LonLat} end coordinates
65
+ * @returns {number} Distance in m between this point and destination point (same units as radius).
66
+ */
67
+ rhumbDistanceTo(startLonLat, endLonLat) {
68
+ const f1 = startLonLat.lat * math.RADIANS;
69
+ const f2 = endLonLat.lat * math.RADIANS;
70
+ const df = f2 - f1;
71
+ let d = Math.abs(endLonLat.lon - startLonLat.lon) * math.RADIANS;
72
+ if (Math.abs(d) > Math.PI) d = d > 0 ? -(2 * Math.PI - d) : (2 * Math.PI + d);
73
+ const dd = Math.log(Math.tan(f2 / 2 + Math.PI / 4) / Math.tan(f1 / 2 + Math.PI / 4));
74
+ const q = Math.abs(dd) > 10e-12 ? df / dd : Math.cos(f1);
75
+ const t = Math.sqrt(df * df + q * q * d * d); // angular distance in radians
76
+ return t * this._a;
77
+ }
78
+
60
79
  /**
61
80
  * Returns the midpoint between two points on the great circle.
62
81
  * @param {LonLat} lonLat1 - Longitude/latitude of first point.
@@ -536,7 +555,7 @@ class Ellipsoid {
536
555
 
537
556
  let eps = Math.abs(qw2 - product);
538
557
 
539
- if (eps > math.EPSILON10 && qw2 < product) {
558
+ if (eps > math.EPSILON15 && qw2 < product) {
540
559
  // Imaginary roots (0 intersections).
541
560
  return null;
542
561
  } else if (qw2 > product) {
@@ -65,7 +65,7 @@ class Entity {
65
65
  * @public
66
66
  * @type {string}
67
67
  */
68
- this.properties.name = this.properties.name || options.name || "";
68
+ this.properties.name = this.properties.name != undefined ? this.properties.name : "";
69
69
 
70
70
  /**
71
71
  * Children entities.
@@ -20,7 +20,7 @@ class GeoObject {
20
20
  constructor(options) {
21
21
  options = options || {};
22
22
 
23
- this.scale = options.scale || 0.02;
23
+ this.scale = options.scale || 1.0;
24
24
  this.scaleByDistance = new Float32Array(options.scaleByDistance || [MAX32, MAX32, MAX32]);
25
25
 
26
26
  /**
@@ -205,6 +205,7 @@ class LabelHandler extends BillboardHandler {
205
205
  ec = this._entityCollection;
206
206
 
207
207
  gl.disable(gl.CULL_FACE);
208
+ //gl.disable(gl.DEPTH_TEST);
208
209
 
209
210
  gl.uniform1iv(shu.fontTextureArr, r.fontAtlas.samplerArr);
210
211
  gl.uniform4fv(shu.sdfParamsArr, r.fontAtlas.sdfParamsArr);
@@ -385,14 +386,14 @@ class LabelHandler extends BillboardHandler {
385
386
  if (isRTL) {
386
387
  _rtl_ = RTL;
387
388
  }
388
- let n = fa.get(text[c].charCodeAt());
389
+
389
390
  let offset = 0.0;
390
391
  let kern = fa.kernings;
391
392
 
392
393
  for (c = 0; c < len; c++) {
393
394
  let j = i + c * 24;
394
395
  let char = text[c];
395
- n = fa.get(char.charCodeAt()) || fa.get(" ".charCodeAt());
396
+ let n = fa.get(char.charCodeAt()) || fa.get(" ".charCodeAt());
396
397
  let tc = n.texCoords;
397
398
 
398
399
  let m = n.metrics;
@@ -9,11 +9,14 @@ export const input = {
9
9
  KEY_ALT: 18,
10
10
  KEY_SHIFT: 16,
11
11
  KEY_SPACE: 32,
12
+ KEY_PGUP: 33,
13
+ KEY_PGDN: 34,
12
14
  KEY_LEFT: 37,
13
15
  KEY_UP: 38,
14
16
  KEY_RIGHT: 39,
15
17
  KEY_DOWN: 40,
16
18
  KEY_PRINTSCREEN: 44,
19
+ KEY_EQUALS: 61,
17
20
  KEY_A: 65,
18
21
  KEY_C: 67,
19
22
  KEY_D: 68,
@@ -23,6 +26,7 @@ export const input = {
23
26
  KEY_I: 73,
24
27
  KEY_K: 75,
25
28
  KEY_L: 76,
29
+ KEY_N: 78,
26
30
  KEY_O: 79,
27
31
  KEY_P: 80,
28
32
  KEY_Q: 81,
@@ -32,9 +36,11 @@ export const input = {
32
36
  KEY_W: 87,
33
37
  KEY_X: 88,
34
38
  KEY_Z: 90,
39
+ KEY_PLUS: 107,
35
40
  KEY_F1: 112,
41
+ KEY_MINUS: 173,
36
42
  KEY_APOSTROPHE: 192,
37
43
  MB_LEFT: 0,
38
44
  MB_RIGHT: 2,
39
45
  MB_MIDDLE: 1
40
- };
46
+ };
@@ -98,14 +98,14 @@ class CanvasTiles extends Layer {
98
98
  * @public
99
99
  * @param {boolean} visibility - Layer visibility.
100
100
  */
101
- setVisibility(visibility) {
101
+ setVisibility(visibility) {
102
102
  if (visibility !== this._visibility) {
103
103
  super.setVisibility(visibility);
104
104
 
105
105
  if (!visibility) {
106
106
  this.abortLoading();
107
107
  }
108
- }
108
+ }
109
109
  }
110
110
 
111
111
  /**
@@ -203,7 +203,7 @@ class CanvasTiles extends Layer {
203
203
  this._exec(pmat);
204
204
  }
205
205
  }
206
- } else if (this._counter === 0) {
206
+ } else if (this._counter === 0 && this._planet._terrainCompletedActivated) {
207
207
  this.events.dispatch(this.events.loadend);
208
208
  }
209
209
  }
@@ -227,21 +227,21 @@ class CanvasTiles extends Layer {
227
227
  applyMaterial(material) {
228
228
  if (material.isReady) {
229
229
  return [0, 0, 1, 1];
230
- } else {
231
-
230
+ } else {
231
+
232
232
  var segment = material.segment;
233
233
  var pn = segment.node,
234
234
  notEmpty = false;
235
-
235
+
236
236
  if (segment.passReady && !material.isLoading) {
237
- this.loadMaterial(material);
237
+ this.loadMaterial(material);
238
238
  }
239
239
 
240
240
  var mId = this._id;
241
241
  var psegm = material;
242
242
  while (pn.parentNode) {
243
243
  pn = pn.parentNode;
244
- psegm = pn.segment.materials[mId];
244
+ psegm = pn.segment.materials[mId];
245
245
  if (psegm && psegm.isReady) {
246
246
  notEmpty = true;
247
247
  break;