From d13d52ff16f946b102c97c79d427e10bd2220bd0 Mon Sep 17 00:00:00 2001 From: ggetz Date: Wed, 7 Feb 2018 14:22:22 -0500 Subject: [PATCH 01/12] Fix order tiles inavlidated --- Source/Scene/QuadtreePrimitive.js | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/Source/Scene/QuadtreePrimitive.js b/Source/Scene/QuadtreePrimitive.js index d2c6b39e90b9..0df3e7c710ed 100644 --- a/Source/Scene/QuadtreePrimitive.js +++ b/Source/Scene/QuadtreePrimitive.js @@ -100,6 +100,7 @@ define([ this._tileReplacementQueue = new TileReplacementQueue(); this._levelZeroTiles = undefined; this._loadQueueTimeSlice = 5.0; + this._tilesInvalidated = false; this._addHeightCallbacks = []; this._removeHeightCallbacks = []; @@ -167,16 +168,20 @@ define([ * @memberof QuadtreePrimitive */ QuadtreePrimitive.prototype.invalidateAllTiles = function() { + this._tilesInvalidated = true; + }; + + function invalidateAllTiles(primitive) { // Clear the replacement queue - var replacementQueue = this._tileReplacementQueue; + var replacementQueue = primitive._tileReplacementQueue; replacementQueue.head = undefined; replacementQueue.tail = undefined; replacementQueue.count = 0; - clearTileLoadQueue(this); + clearTileLoadQueue(primitive); // Free and recreate the level zero tiles. - var levelZeroTiles = this._levelZeroTiles; + var levelZeroTiles = primitive._levelZeroTiles; if (defined(levelZeroTiles)) { for (var i = 0; i < levelZeroTiles.length; ++i) { var tile = levelZeroTiles[i]; @@ -186,16 +191,16 @@ define([ for (var j = 0; j < customDataLength; ++j) { var data = customData[j]; data.level = 0; - this._addHeightCallbacks.push(data); + primitive._addHeightCallbacks.push(data); } levelZeroTiles[i].freeResources(); } } - this._levelZeroTiles = undefined; + primitive._levelZeroTiles = undefined; - this._tileProvider.cancelReprojections(); + primitive._tileProvider.cancelReprojections(); }; /** @@ -267,6 +272,11 @@ define([ * @private */ QuadtreePrimitive.prototype.update = function(frameState) { + if (this._tilesInvalidated) { + invalidateAllTiles(this); + this._tilesInvalidated = false; + } + if (defined(this._tileProvider.update)) { this._tileProvider.update(frameState); } From b25edc41441ac78addbf2cf795a9df5b54e90fcb Mon Sep 17 00:00:00 2001 From: ggetz Date: Wed, 7 Feb 2018 14:23:54 -0500 Subject: [PATCH 02/12] Updated CHANGES.md --- CHANGES.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 0dcfd8ed5311..ef744a12b3a9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,7 +4,8 @@ Change Log ### 1.43 - 2018-03-01 ##### Fixes :wrench: -* Fixed bug where AxisAlignedBoundingBox did not copy over center value when cloning an undefined result. [#6183](https://github.com/AnalyticalGraphicsInc/cesium/pull/6183) +* Fixed a bug where AxisAlignedBoundingBox did not copy over center value when cloning an undefined result. [#6183](https://github.com/AnalyticalGraphicsInc/cesium/pull/6183) +* Fixed a bug where imagery stops loading when changing terrain in request render mode. [#6193](https://github.com/AnalyticalGraphicsInc/cesium/issues/6193) ### 1.42.1 - 2018-02-01 _This is an npm-only release to fix an issue with using Cesium in Node.js.__ From 82220f37b45227cde42f22df2f308d0d41ac3e95 Mon Sep 17 00:00:00 2001 From: ggetz Date: Wed, 7 Feb 2018 14:36:28 -0500 Subject: [PATCH 03/12] Fix eslint error, specs --- Source/Scene/QuadtreePrimitive.js | 2 +- Specs/Scene/GlobeSurfaceTileProviderSpec.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Scene/QuadtreePrimitive.js b/Source/Scene/QuadtreePrimitive.js index 0df3e7c710ed..860b0e279e25 100644 --- a/Source/Scene/QuadtreePrimitive.js +++ b/Source/Scene/QuadtreePrimitive.js @@ -201,7 +201,7 @@ define([ primitive._levelZeroTiles = undefined; primitive._tileProvider.cancelReprojections(); - }; + } /** * Invokes a specified function for each {@link QuadtreeTile} that is partially diff --git a/Specs/Scene/GlobeSurfaceTileProviderSpec.js b/Specs/Scene/GlobeSurfaceTileProviderSpec.js index d2d9202fa6b9..78dd4af772c1 100644 --- a/Specs/Scene/GlobeSurfaceTileProviderSpec.js +++ b/Specs/Scene/GlobeSurfaceTileProviderSpec.js @@ -674,6 +674,7 @@ defineSuite([ expect(replacementQueue.count).toBeGreaterThan(0); surface.tileProvider.terrainProvider = new EllipsoidTerrainProvider(); + surface.update(scene.frameState); expect(replacementQueue.count).toBe(0); }); }); From baf449ae682386419769634569364c9ea08ec512 Mon Sep 17 00:00:00 2001 From: ggetz Date: Tue, 20 Feb 2018 15:33:10 -0500 Subject: [PATCH 04/12] Invalidate tile on start of render frame --- Source/Scene/QuadtreePrimitive.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Source/Scene/QuadtreePrimitive.js b/Source/Scene/QuadtreePrimitive.js index 860b0e279e25..9be66c8071df 100644 --- a/Source/Scene/QuadtreePrimitive.js +++ b/Source/Scene/QuadtreePrimitive.js @@ -272,11 +272,6 @@ define([ * @private */ QuadtreePrimitive.prototype.update = function(frameState) { - if (this._tilesInvalidated) { - invalidateAllTiles(this); - this._tilesInvalidated = false; - } - if (defined(this._tileProvider.update)) { this._tileProvider.update(frameState); } @@ -345,7 +340,7 @@ define([ function updateTileLoadProgress(primitive, frameState) { var currentLoadQueueLength = primitive._tileLoadQueueHigh.length + primitive._tileLoadQueueMedium.length + primitive._tileLoadQueueLow.length; - if (currentLoadQueueLength !== primitive._lastTileLoadQueueLength) { + if (currentLoadQueueLength !== primitive._lastTileLoadQueueLength || primitive._tilesInvalidated) { frameState.afterRender.push(Event.prototype.raiseEvent.bind(primitive._tileLoadProgressEvent, currentLoadQueueLength)); primitive._lastTileLoadQueueLength = currentLoadQueueLength; } @@ -381,10 +376,16 @@ define([ return; } + if (this._tilesInvalidated) { + invalidateAllTiles(this); + } + // Load/create resources for terrain and imagery. Prepare texture re-projections for the next frame. processTileLoadQueue(this, frameState); updateHeights(this, frameState); updateTileLoadProgress(this, frameState); + + this._tilesInvalidated = false; }; /** From e2e1342608fe18d21296d3b99e194b2993007ba7 Mon Sep 17 00:00:00 2001 From: ggetz Date: Tue, 20 Feb 2018 16:31:53 -0500 Subject: [PATCH 05/12] Fixed specs --- Specs/Scene/GlobeSurfaceTileProviderSpec.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Specs/Scene/GlobeSurfaceTileProviderSpec.js b/Specs/Scene/GlobeSurfaceTileProviderSpec.js index 78dd4af772c1..e92a18364c63 100644 --- a/Specs/Scene/GlobeSurfaceTileProviderSpec.js +++ b/Specs/Scene/GlobeSurfaceTileProviderSpec.js @@ -674,7 +674,9 @@ defineSuite([ expect(replacementQueue.count).toBeGreaterThan(0); surface.tileProvider.terrainProvider = new EllipsoidTerrainProvider(); - surface.update(scene.frameState); + + scene.renderForSpecs(); + expect(replacementQueue.count).toBe(0); }); }); @@ -692,6 +694,7 @@ defineSuite([ surface.tileProvider.terrainProvider = new EllipsoidTerrainProvider(); + scene.renderForSpecs(); scene.renderForSpecs(); levelZeroTiles = surface._levelZeroTiles; From 3a42de51a7648cf2e8ae4e11aafdab262c449a35 Mon Sep 17 00:00:00 2001 From: ggetz Date: Tue, 20 Feb 2018 16:37:25 -0500 Subject: [PATCH 06/12] RequestRender subscribe to terrainProviderChanged --- Source/Scene/Scene.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js index d2e375709d51..cdc34030f0cd 100644 --- a/Source/Scene/Scene.js +++ b/Source/Scene/Scene.js @@ -784,6 +784,7 @@ define([ if (defined(globe)) { removeGlobeCallbacks.push(globe.tileLoadedEvent.addEventListener(requestRenderAfterFrame(scene))); removeGlobeCallbacks.push(globe.imageryLayersUpdatedEvent.addEventListener(requestRenderAfterFrame(scene))); + removeGlobeCallbacks.push(globe.terrainProviderChanged.addEventListener(requestRenderAfterFrame(scene))); } scene._removeGlobeCallbacks = removeGlobeCallbacks; } From 8281b286d3ca3d87523d62d8f19b73fb22aa4a71 Mon Sep 17 00:00:00 2001 From: ggetz Date: Tue, 20 Feb 2018 16:40:50 -0500 Subject: [PATCH 07/12] Add test for switching terrain providers --- Specs/Scene/SceneSpec.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/Specs/Scene/SceneSpec.js b/Specs/Scene/SceneSpec.js index 5f2c6409147c..7ee467949c11 100644 --- a/Specs/Scene/SceneSpec.js +++ b/Specs/Scene/SceneSpec.js @@ -1502,6 +1502,34 @@ defineSuite([ scene.destroyForSpecs(); }); + it('Globe changing terrain providers triggers a new frame to be rendered in requestRenderMode', function() { + var scene = createScene(); + + scene.renderForSpecs(); + + var lastRenderTime = JulianDate.clone(scene.lastRenderTime, scratchTime); + expect(lastRenderTime).toBeDefined(); + expect(scene._renderRequested).toBe(false); + + scene.requestRenderMode = true; + scene.maximumRenderTimeChange = undefined; + + var ellipsoid = Ellipsoid.UNIT_SPHERE; + var globe = new Globe(ellipsoid); + scene.globe = globe; + globe.terrainProviderChanged.raiseEvent(); + + scene.renderForSpecs(); + + expect(scene._renderRequested).toBe(true); + + scene.renderForSpecs(); + expect(scene.lastRenderTime).not.toEqual(lastRenderTime); + + scene.destroyForSpecs(); + }); + + it('scene morphing causes a new frame to be rendered in requestRenderMode', function() { var scene = createScene(); scene.renderForSpecs(); From ddc5358700f310fa003311e1b84f5faaf06f4f84 Mon Sep 17 00:00:00 2001 From: ggetz Date: Wed, 21 Feb 2018 11:38:21 -0500 Subject: [PATCH 08/12] Fix specs --- Specs/DataSources/EntityClusterSpec.js | 1 + Specs/DataSources/PointVisualizerSpec.js | 4 ++-- Specs/createGlobe.js | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Specs/DataSources/EntityClusterSpec.js b/Specs/DataSources/EntityClusterSpec.js index b2039abb08df..bba3165cbc83 100644 --- a/Specs/DataSources/EntityClusterSpec.js +++ b/Specs/DataSources/EntityClusterSpec.js @@ -49,6 +49,7 @@ defineSuite([ } }, tileLoadedEvent : new Event(), + terrainProviderChanged : new Event(), imageryLayersUpdatedEvent : new Event(), beginFrame : function() {}, update : function() {}, diff --git a/Specs/DataSources/PointVisualizerSpec.js b/Specs/DataSources/PointVisualizerSpec.js index 80165b071bf8..07853ca88d2a 100644 --- a/Specs/DataSources/PointVisualizerSpec.js +++ b/Specs/DataSources/PointVisualizerSpec.js @@ -52,7 +52,8 @@ defineSuite([ ellipsoid : Ellipsoid.WGS84, _surface : {}, tileLoadedEvent : new Event(), - imageryLayersUpdatedEvent : new Event() + imageryLayersUpdatedEvent : new Event(), + terrainProviderChanged : new Event() }; scene.globe.getHeight = function() { @@ -65,7 +66,6 @@ defineSuite([ scene.globe._surface.updateHeight = function() { }; - scene.globe.terrainProviderChanged = new Event(); defineProperties(scene.globe, { terrainProvider : { set : function(value) { diff --git a/Specs/createGlobe.js b/Specs/createGlobe.js index 3f9f0d3db044..98fbff04d656 100644 --- a/Specs/createGlobe.js +++ b/Specs/createGlobe.js @@ -27,6 +27,7 @@ define([ _surface : {}, tileLoadedEvent : new Event(), imageryLayersUpdatedEvent : new Event(), + terrainProviderChanged : new Event(), destroy : function() {} }; From 428c3cfb65af40de47d5261fa5bd35d99d6c0f24 Mon Sep 17 00:00:00 2001 From: ggetz Date: Mon, 26 Feb 2018 16:22:10 -0500 Subject: [PATCH 09/12] RequestRender renders when tile load queue is not empty --- CHANGES.md | 1 + Source/Scene/Globe.js | 15 +++++++++++++++ Source/Scene/Scene.js | 5 ++++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index c34cd441f164..397bc97968b0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -20,6 +20,7 @@ Change Log * Added `preserveQueryParameters` parameter to `getDerivedResource`, to allow us to append query parameters instead of always replacing them. * Added `setQueryParameters` and `appendQueryParameters` to allow for better handling of query strings. * Enable terrain in the `CesiumViewer` demo application [#6198](https://github.com/AnalyticalGraphicsInc/cesium/pull/6198) +* Added `Globe.tilesLoaded` getter property to determine if all terrain and imagery is loaded. [#6194](https://github.com/AnalyticalGraphicsInc/cesium/pull/6194) ##### Fixes :wrench: * Fixed bug where AxisAlignedBoundingBox did not copy over center value when cloning an undefined result. [#6183](https://github.com/AnalyticalGraphicsInc/cesium/pull/6183) diff --git a/Source/Scene/Globe.js b/Source/Scene/Globe.js index 2b98a8dd0fa0..da9ecf46cae3 100644 --- a/Source/Scene/Globe.js +++ b/Source/Scene/Globe.js @@ -237,6 +237,21 @@ define([ return this._surface.tileProvider.tileLoadedEvent; } }, + /** + * Returns true when the tile load queue is empty, false otherwise. When the load queue is empty, + * all terrain and imagery for the current view have been loaded. + * @memeberof Globe.prototype + * @type {Boolean} + * @readonly + */ + tilesLoaded: { + get: function() { + if (!defined(this._surface)) { + return true; + } + return (this._surface.tileProvider.ready && this._surface._tileLoadQueueHigh.length === 0 && this._surface._tileLoadQueueMedium.length === 0 && this._surface._tileLoadQueueLow.length === 0); + } + }, /** * Gets or sets the color of the globe when no imagery is available. * @memberof Globe.prototype diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js index cdc34030f0cd..4b435cddbf5a 100644 --- a/Source/Scene/Scene.js +++ b/Source/Scene/Scene.js @@ -782,7 +782,6 @@ define([ var removeGlobeCallbacks = []; if (defined(globe)) { - removeGlobeCallbacks.push(globe.tileLoadedEvent.addEventListener(requestRenderAfterFrame(scene))); removeGlobeCallbacks.push(globe.imageryLayersUpdatedEvent.addEventListener(requestRenderAfterFrame(scene))); removeGlobeCallbacks.push(globe.terrainProviderChanged.addEventListener(requestRenderAfterFrame(scene))); } @@ -3011,6 +3010,10 @@ define([ if (defined(scene.globe)) { scene.globe.endFrame(frameState); + + if (!scene.globe.tilesLoaded) { + scene._renderRequested = true; + } } frameState.creditDisplay.endFrame(); From 19926c65d6e5422342fbce97e3a1d536af1cb090 Mon Sep 17 00:00:00 2001 From: ggetz Date: Mon, 26 Feb 2018 17:04:27 -0500 Subject: [PATCH 10/12] Updated specs --- Specs/Scene/GlobeSpec.js | 50 ++++++++++++++++++++++++++++++---------- Specs/Scene/SceneSpec.js | 5 ++-- 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/Specs/Scene/GlobeSpec.js b/Specs/Scene/GlobeSpec.js index 5e2b30df044f..bc3db3e0b33c 100644 --- a/Specs/Scene/GlobeSpec.js +++ b/Specs/Scene/GlobeSpec.js @@ -61,7 +61,7 @@ defineSuite([ return pollToPromise(function() { globe._surface._debug.enableDebugOutput = true; scene.render(); - return globe._surface.tileProvider.ready && globe._surface._tileLoadQueueHigh.length === 0 && globe._surface._tileLoadQueueMedium.length === 0 && globe._surface._tileLoadQueueLow.length === 0 && globe._surface._debug.tilesWaitingForChildren === 0; + return globe.tilesLoaded; }); } @@ -148,6 +148,37 @@ defineSuite([ expect(spyListener).toHaveBeenCalledWith(terrainProvider); }); + it('tilesLoaded return true when tile load queue is empty', function() { + expect(globe.tilesLoaded).toBe(true); + + globe._surface._tileLoadQueueHigh.length = 2; + expect(globe.tilesLoaded).toBe(false); + + globe._surface._tileLoadQueueHigh.length = 0; + expect(globe.tilesLoaded).toBe(true); + + globe._surface._tileLoadQueueMedium.length = 2; + expect(globe.tilesLoaded).toBe(false); + + globe._surface._tileLoadQueueMedium.length = 0; + expect(globe.tilesLoaded).toBe(true); + + globe._surface._tileLoadQueueLow.length = 2; + expect(globe.tilesLoaded).toBe(false); + + globe._surface._tileLoadQueueLow.length = 0; + expect(globe.tilesLoaded).toBe(true); + + var terrainProvider = new CesiumTerrainProvider({ + url : 'made/up/url', + requestVertexNormals : true + }); + + globe.terrainProvider = terrainProvider; + scene.render(); + expect(globe.tilesLoaded).toBe(false); + }); + it('renders terrain with enableLighting', function() { globe.enableLighting = true; @@ -167,18 +198,13 @@ defineSuite([ }); globe.terrainProvider = terrainProvider; + scene.camera.setView({ destination : new Rectangle(0.0001, 0.0001, 0.0025, 0.0025) }); - return pollToPromise(function() { - return terrainProvider.ready; - }).then(function() { - scene.camera.setView({ destination : new Rectangle(0.0001, 0.0001, 0.0025, 0.0025) }); - - return updateUntilDone(globe).then(function() { - scene.globe.show = false; - expect(scene).toRender([0, 0, 0, 255]); - scene.globe.show = true; - expect(scene).notToRender([0, 0, 0, 255]); - }); + return updateUntilDone(globe).then(function() { + expect(scene).notToRender([0, 0, 0, 255]); + + scene.globe.show = false; + expect(scene).toRender([0, 0, 0, 255]); }); }); }, 'WebGL'); diff --git a/Specs/Scene/SceneSpec.js b/Specs/Scene/SceneSpec.js index 7ee467949c11..0b1846586fc7 100644 --- a/Specs/Scene/SceneSpec.js +++ b/Specs/Scene/SceneSpec.js @@ -1463,12 +1463,13 @@ defineSuite([ var ellipsoid = Ellipsoid.UNIT_SPHERE; var globe = new Globe(ellipsoid); scene.globe = globe; - globe.tileLoadedEvent.raiseEvent(); + scene.requestRender(); + Object.defineProperty(globe, 'tilesLoaded', { value: false }); scene.renderForSpecs(); + lastRenderTime = JulianDate.clone(scene.lastRenderTime, scratchTime); expect(scene._renderRequested).toBe(true); - scene.renderForSpecs(); expect(scene.lastRenderTime).not.toEqual(lastRenderTime); From 1fdc936317598eae98367ff6c221e9a0392a3fe7 Mon Sep 17 00:00:00 2001 From: ggetz Date: Tue, 27 Feb 2018 09:51:43 -0500 Subject: [PATCH 11/12] Fix doc typo --- Source/Scene/Globe.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Scene/Globe.js b/Source/Scene/Globe.js index da9ecf46cae3..97f0fab1a1cc 100644 --- a/Source/Scene/Globe.js +++ b/Source/Scene/Globe.js @@ -240,7 +240,8 @@ define([ /** * Returns true when the tile load queue is empty, false otherwise. When the load queue is empty, * all terrain and imagery for the current view have been loaded. - * @memeberof Globe.prototype + * + * @memberof Globe.prototype * @type {Boolean} * @readonly */ From a4d77547a43f8adc8dae085e90b429aeba4ed769 Mon Sep 17 00:00:00 2001 From: ggetz Date: Tue, 27 Feb 2018 10:08:19 -0500 Subject: [PATCH 12/12] fix eslint error --- Source/Scene/Globe.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Scene/Globe.js b/Source/Scene/Globe.js index 97f0fab1a1cc..343295c50c1d 100644 --- a/Source/Scene/Globe.js +++ b/Source/Scene/Globe.js @@ -240,7 +240,6 @@ define([ /** * Returns true when the tile load queue is empty, false otherwise. When the load queue is empty, * all terrain and imagery for the current view have been loaded. - * * @memberof Globe.prototype * @type {Boolean} * @readonly