From 6aaff1b8d3740a5a23db99efb66484e18a72c1f0 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Fri, 21 Apr 2017 13:20:25 -0400 Subject: [PATCH 1/7] Expire temp --- Source/Scene/Cesium3DTile.js | 82 +++++++++++++++++++++++- Source/Scene/Cesium3DTileContentState.js | 5 +- Source/Scene/Cesium3DTileset.js | 57 ++++++++++++---- 3 files changed, 127 insertions(+), 17 deletions(-) diff --git a/Source/Scene/Cesium3DTile.js b/Source/Scene/Cesium3DTile.js index cbe21565819a..6b7c8db4784b 100644 --- a/Source/Scene/Cesium3DTile.js +++ b/Source/Scene/Cesium3DTile.js @@ -17,6 +17,7 @@ define([ '../Core/getStringFromTypedArray', '../Core/Intersect', '../Core/joinUrls', + '../Core/JulianDate', '../Core/loadArrayBuffer', '../Core/Matrix3', '../Core/Matrix4', @@ -60,6 +61,7 @@ define([ getStringFromTypedArray, Intersect, joinUrls, + JulianDate, loadArrayBuffer, Matrix3, Matrix4, @@ -268,6 +270,30 @@ define([ */ this.replacementNode = undefined; + var expire = header.expire; + var expireDuration; + var expireDate; + if (defined(expire)) { + expireDuration = expire.duration; + if (defined(expire.date)) { + expireDate = JulianDate.fromIso8601(expire.date); + } + } + + /** + * The time in seconds after the tile's content is ready when the content expires and new content is requested. + * + * @type {Number} + */ + this.expireDuration = expireDuration; + + /** + * The date when the content expires and new content is requested. + * + * @type {JulianDate} + */ + this.expireDate = expireDate; + // Members that are updated every frame for tree traversal and rendering optimizations: /** @@ -449,6 +475,21 @@ define([ } }, + /** + * Determines if the tile's content is expired. true if tile's + * content is expired; otherwise, false. + * + * @memberof Cesium3DTile.prototype + * + * @type {Boolean} + * @readonly + */ + contentExpired : { + get : function() { + return this._contentState === Cesium3DTileContentState.EXPIRED; + } + }, + /** * Gets the promise that will be resolved when the tile's content is ready to process. * This happens after the content is downloaded but before the content is ready @@ -490,6 +531,32 @@ define([ } }); + var scratchJulianDate = new JulianDate(); + + function updateExpiration(tile) { + if (defined(tile.expireDate) && tile.contentReady && !tile.hasEmptyContent) { + var now = JulianDate.now(scratchJulianDate); + if (JulianDate.lessThan(tile.expireDate, now)) { + tile._contentState = Cesium3DTileContentState.EXPIRED; + } + } + } + + function updateExpireDate(tile) { + if (defined(tile.expireDuration)) { + var expireDurationDate = JulianDate.now(scratchJulianDate); + JulianDate.addSeconds(expireDurationDate, tile.expireDuration, expireDurationDate); + + if (defined(tile.expireDate)) { + if (JulianDate.lessThan(tile.expireDate, expireDurationDate)) { + JulianDate.clone(expireDurationDate, tile.expireDate); + } + } else { + tile.expireDate = JulianDate.clone(expireDurationDate); + } + } + } + /** * Requests the tile's content. *

@@ -509,9 +576,16 @@ define([ return false; } + var url = this._contentUrl; + if (defined(this.expireDate)) { + // Append a query parameter of the tile expiration date to prevent caching + var timestampQuery = '?expired=' + this.expireDate.toString(); + url = joinUrls(url, timestampQuery, false); + } + var distance = this.distanceToCamera; var promise = RequestScheduler.schedule(new Request({ - url : this._contentUrl, + url : url, server : this._requestServer, requestFunction : loadArrayBuffer, type : RequestType.TILES3D, @@ -530,6 +604,10 @@ define([ if (that.isDestroyed()) { return when.reject('tileset is destroyed'); } + + // Destroy expired content to make way for the new content + that._content = that._content && that._content.destroy(); + var uint8Array = new Uint8Array(arrayBuffer); var magic = getMagic(uint8Array); var contentFactory = Cesium3DTileContentFactory[magic]; @@ -549,6 +627,7 @@ define([ that._contentReadyToProcessPromise.resolve(content); content.readyPromise.then(function(content) { + updateExpireDate(that); that._contentState = Cesium3DTileContentState.READY; that._contentReadyPromise.resolve(content); }).otherwise(function(error) { @@ -861,6 +940,7 @@ define([ */ Cesium3DTile.prototype.update = function(tileset, frameState) { applyDebugSettings(this, tileset, frameState); + updateExpiration(this); this._content.update(tileset, frameState); this._transformDirty = false; }; diff --git a/Source/Scene/Cesium3DTileContentState.js b/Source/Scene/Cesium3DTileContentState.js index 986e821b3e33..98fdad9a96bf 100644 --- a/Source/Scene/Cesium3DTileContentState.js +++ b/Source/Scene/Cesium3DTileContentState.js @@ -13,8 +13,9 @@ define([ LOADING : 1, // Is waiting on a pending request PROCESSING : 2, // Request received. Contents are being processed for rendering. Depending on the content, it might make its own requests for external data. READY : 3, // Ready to render. - FAILED : 4 // Request failed. + EXPIRED : 4, // Is expired and will be unloaded once new content is loaded. + FAILED : 5 // Request failed. }; return freezeObject(Cesium3DTileContentState); -}); \ No newline at end of file +}); diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 27ed62414e58..2e541aea0be6 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -450,7 +450,7 @@ define([ this.allTilesLoaded = new Event(); /** - * The event fired to indicate that a tile's content was unloaded from the cache. + * The event fired to indicate that a tile's content was unloaded. *

* The unloaded {@link Cesium3DTile} is passed to the event listener. *

@@ -1222,6 +1222,25 @@ define([ /////////////////////////////////////////////////////////////////////////// + function unloadSubtree(tileset, tile) { + var stats = tileset._statistics; + var stack = []; + stack.push(tile); + while (stack.length > 0) { + tile = stack.pop(); + unloadTile(tileset, tile); + var children = tile.children; + var length = children.length; + for (var i = 0; i < length; ++i) { + var child = children[i]; + --stats.numberTotal; + stack.push(child); + } + } + + tile.children = []; + } + function isVisible(visibilityPlaneMask) { return visibilityPlaneMask !== CullingVolume.MASK_OUTSIDE; } @@ -1236,7 +1255,7 @@ define([ } var stats = tileset._statistics; - + var expired = tile.contentExpired; var requested = tile.requestContent(); if (!requested) { @@ -1244,6 +1263,10 @@ define([ return; } + if (expired && tile.hasTilesetContent) { + unloadSubtree(tileset, tile); + } + ++stats.numberOfPendingRequests; var removeFunction = removeFromProcessingQueue(tileset, tile); @@ -1551,7 +1574,7 @@ define([ } function loadTile(tile) { - if (tile.contentUnloaded) { + if (tile.contentUnloaded || tile.contentExpired) { tile._requestHeap.insert(tile); } } @@ -1958,14 +1981,28 @@ define([ } } + function unloadTile(tileset, tile) { + if (!tile.hasRenderableContent) { + return; + } + + var stats = tileset._statistics; + var replacementList = tileset._replacementList; + var tileUnload = tileset.tileUnload; + + tileUnload.raiseEvent(tile); + replacementList.remove(tile.replacementNode); + decrementPointAndFeatureLoadCounts(tileset, tile.content); + --stats.numberContentReady; + tile.unloadContent(); + } + function unloadTiles(tileset, frameState) { var trimTiles = tileset._trimTiles; tileset._trimTiles = false; - var stats = tileset._statistics; var maximumNumberOfLoadedTiles = tileset._maximumNumberOfLoadedTiles + 1; // + 1 to account for sentinel var replacementList = tileset._replacementList; - var tileUnload = tileset.tileUnload; // Traverse the list only to the sentinel since tiles/nodes to the // right of the sentinel were used this frame. @@ -1975,16 +2012,8 @@ define([ var node = replacementList.head; while ((node !== sentinel) && ((replacementList.length > maximumNumberOfLoadedTiles) || trimTiles)) { var tile = node.item; - - decrementPointAndFeatureLoadCounts(tileset, tile.content); - tileUnload.raiseEvent(tile); - tile.unloadContent(); - - var currentNode = node; node = node.next; - replacementList.remove(currentNode); - - --stats.numberContentReady; + unloadTile(tileset, tile); } } From 5fb5f9176d2e8b0893a3dcdeeb14d8b73d3c6228 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Mon, 24 Apr 2017 10:09:38 -0400 Subject: [PATCH 2/7] Keep expired content while new content loads --- Source/Scene/Cesium3DTile.js | 38 +++++++++++++++++++++++++++++---- Source/Scene/Cesium3DTileset.js | 10 ++++----- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/Source/Scene/Cesium3DTile.js b/Source/Scene/Cesium3DTile.js index 6b7c8db4784b..d70e04d41b5b 100644 --- a/Source/Scene/Cesium3DTile.js +++ b/Source/Scene/Cesium3DTile.js @@ -212,6 +212,7 @@ define([ this._contentState = contentState; this._contentReadyToProcessPromise = undefined; this._contentReadyPromise = undefined; + this._expiredContent = undefined; this._requestServer = requestServer; @@ -445,6 +446,22 @@ define([ } }, + /** + * Determines if the tile has available content to render. true if the tile's + * content is ready or if it has expired content that renders while new content loads; otherwise, + * false. + * + * @memberof Cesium3DTile.prototype + * + * @type {Boolean} + * @readonly + */ + contentAvailable : { + get : function() { + return this.contentReady || defined(this._expiredContent); + } + }, + /** * Determines if the tile is ready to render. true if the tile * is ready to render; otherwise, false. @@ -538,6 +555,7 @@ define([ var now = JulianDate.now(scratchJulianDate); if (JulianDate.lessThan(tile.expireDate, now)) { tile._contentState = Cesium3DTileContentState.EXPIRED; + tile._expiredContent = tile._content; } } } @@ -605,9 +623,6 @@ define([ return when.reject('tileset is destroyed'); } - // Destroy expired content to make way for the new content - that._content = that._content && that._content.destroy(); - var uint8Array = new Uint8Array(arrayBuffer); var magic = getMagic(uint8Array); var contentFactory = Cesium3DTileContentFactory[magic]; @@ -933,6 +948,20 @@ define([ } } + function updateContent(tile, tileset, frameState) { + var content = tile._content; + var expiredContent = tile._expiredContent; + + if (defined(expiredContent) && !tile.contentReady) { + // Render the expired content while the content loads + expiredContent.update(tileset, frameState); + return; + } + + tile._expiredContent = tile._expiredContent && tile._expiredContent.destroy(); + content.update(tileset, frameState); + } + /** * Get the draw commands needed to render this tile. * @@ -941,7 +970,7 @@ define([ Cesium3DTile.prototype.update = function(tileset, frameState) { applyDebugSettings(this, tileset, frameState); updateExpiration(this); - this._content.update(tileset, frameState); + updateContent(this, tileset, frameState); this._transformDirty = false; }; @@ -977,6 +1006,7 @@ define([ */ Cesium3DTile.prototype.destroy = function() { this._content = this._content && this._content.destroy(); + this._expiredContent = this._expiredContent && this._expiredContent.destroy(); this._debugBoundingVolume = this._debugBoundingVolume && this._debugBoundingVolume.destroy(); this._debugContentBoundingVolume = this._debugContentBoundingVolume && this._debugContentBoundingVolume.destroy(); this._debugViewerRequestVolume = this._debugViewerRequestVolume && this._debugViewerRequestVolume.destroy(); diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 2e541aea0be6..8b32b7b42450 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -1277,7 +1277,7 @@ define([ function selectTile(tileset, tile, frameState) { // There may also be a tight box around just the tile's contents, e.g., for a city, we may be // zoomed into a neighborhood and can cull the skyscrapers in the root node. - if (tile.contentReady && ( + if (tile.contentAvailable && ( (tile.visibilityPlaneMask === CullingVolume.MASK_INSIDE) || (tile.contentVisibility(frameState) !== Intersect.OUTSIDE) )) { @@ -1357,8 +1357,8 @@ define([ var tile = original; // traverse up the tree to find a ready ancestor if (!tile.hasEmptyContent) { - while (defined(tile) && !(tile.hasRenderableContent && tile.contentReady)) { - if (!tile.contentReady) { + while (defined(tile) && !(tile.hasRenderableContent && tile.contentAvailable)) { + if (!tile.contentAvailable) { tileset._hasMixedContent = true; } tile = tile.parent; @@ -1381,7 +1381,7 @@ define([ var childrenLength = children.length; for (var j = 0; j < childrenLength; ++j) { var child = children[j]; - if (child.contentReady) { + if (child.contentAvailable) { if (!child.selected) { child._finalResolution = true; child.selected = true; @@ -1391,7 +1391,7 @@ define([ } } if (child._depth - original._depth < 2) { // prevent traversing too far - if (!child.contentReady || child.refine === Cesium3DTileRefine.ADD) { + if (!child.contentAvailable || child.refine === Cesium3DTileRefine.ADD) { descendantStack.push(child); } } From 63b899d73a07f895f120fd1575b79391aee6904b Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Mon, 24 Apr 2017 13:22:36 -0400 Subject: [PATCH 3/7] Handle expiring subtrees --- Source/Scene/Cesium3DTile.js | 52 ++++++++++------------ Source/Scene/Cesium3DTileset.js | 57 ++++++++++++++++--------- Source/Scene/PointCloud3DTileContent.js | 4 +- 3 files changed, 63 insertions(+), 50 deletions(-) diff --git a/Source/Scene/Cesium3DTile.js b/Source/Scene/Cesium3DTile.js index d70e04d41b5b..f19ded63180c 100644 --- a/Source/Scene/Cesium3DTile.js +++ b/Source/Scene/Cesium3DTile.js @@ -120,8 +120,6 @@ define([ */ this.computedTransform = computedTransform; - this._transformDirty = true; - this._boundingVolume = this.createBoundingVolume(header.boundingVolume, computedTransform); this._boundingVolume2D = undefined; @@ -422,20 +420,6 @@ define([ } }, - /** - * Whether the computedTransform has changed this frame. - * - * @memberof Cesium3DTile.prototype - * - * @type {Boolean} - * @readonly - */ - transformDirty : { - get : function() { - return this._transformDirty; - } - }, - /** * @readonly * @private @@ -550,15 +534,20 @@ define([ var scratchJulianDate = new JulianDate(); - function updateExpiration(tile) { - if (defined(tile.expireDate) && tile.contentReady && !tile.hasEmptyContent) { + /** + * Update whether the tile has expired. + * + * @private + */ + Cesium3DTile.prototype.updateExpiration = function() { + if (defined(this.expireDate) && this.contentReady && !this.hasEmptyContent) { var now = JulianDate.now(scratchJulianDate); - if (JulianDate.lessThan(tile.expireDate, now)) { - tile._contentState = Cesium3DTileContentState.EXPIRED; - tile._expiredContent = tile._content; + if (JulianDate.lessThan(this.expireDate, now)) { + this._contentState = Cesium3DTileContentState.EXPIRED; + this._expiredContent = this._content; } } - } + }; function updateExpireDate(tile) { if (defined(tile.expireDuration)) { @@ -620,9 +609,9 @@ define([ promise.then(function(arrayBuffer) { if (that.isDestroyed()) { - return when.reject('tileset is destroyed'); + // Tile is unloaded before the content finishes loading + return when.reject('tile is destroyed'); } - var uint8Array = new Uint8Array(arrayBuffer); var magic = getMagic(uint8Array); var contentFactory = Cesium3DTileContentFactory[magic]; @@ -642,6 +631,11 @@ define([ that._contentReadyToProcessPromise.resolve(content); content.readyPromise.then(function(content) { + if (that.isDestroyed()) { + // Tile is unloaded before the content finishes processing + that._content.destroy(); + return when.reject('tile is destroyed'); + } updateExpireDate(that); that._contentState = Cesium3DTileContentState.READY; that._contentReadyPromise.resolve(content); @@ -883,9 +877,8 @@ define([ Cesium3DTile.prototype.updateTransform = function(parentTransform) { parentTransform = defaultValue(parentTransform, Matrix4.IDENTITY); var computedTransform = Matrix4.multiply(parentTransform, this.transform, scratchTransform); - var transformDirty = !Matrix4.equals(computedTransform, this.computedTransform); - if (transformDirty) { - this._transformDirty = true; + var transformChanged = !Matrix4.equals(computedTransform, this.computedTransform); + if (transformChanged) { Matrix4.clone(computedTransform, this.computedTransform); // Update the bounding volumes @@ -969,9 +962,7 @@ define([ */ Cesium3DTile.prototype.update = function(tileset, frameState) { applyDebugSettings(this, tileset, frameState); - updateExpiration(this); updateContent(this, tileset, frameState); - this._transformDirty = false; }; var scratchCommandList = []; @@ -1005,8 +996,9 @@ define([ * @private */ Cesium3DTile.prototype.destroy = function() { + // For the interval between new content being requested and downloaded, expiredContent === content, so don't destroy twice this._content = this._content && this._content.destroy(); - this._expiredContent = this._expiredContent && this._expiredContent.destroy(); + this._expiredContent = this._expiredContent && !this._expiredContent.isDestroyed() && this._expiredContent.destroy(); this._debugBoundingVolume = this._debugBoundingVolume && this._debugBoundingVolume.destroy(); this._debugContentBoundingVolume = this._debugContentBoundingVolume && this._debugContentBoundingVolume.destroy(); this._debugViewerRequestVolume = this._debugViewerRequestVolume && this._debugViewerRequestVolume.destroy(); diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 8b32b7b42450..8863fb716f80 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -1222,23 +1222,25 @@ define([ /////////////////////////////////////////////////////////////////////////// - function unloadSubtree(tileset, tile) { + function destroySubtree(tileset, tile) { + var root = tile; var stats = tileset._statistics; - var stack = []; + var stack = scratchStack; stack.push(tile); while (stack.length > 0) { tile = stack.pop(); - unloadTile(tileset, tile); var children = tile.children; var length = children.length; for (var i = 0; i < length; ++i) { - var child = children[i]; + stack.push(children[i]); + } + if (tile !== root) { + unloadTileFromCache(tileset, tile); + tile.destroy(); --stats.numberTotal; - stack.push(child); } } - - tile.children = []; + root.children = []; } function isVisible(visibilityPlaneMask) { @@ -1263,8 +1265,13 @@ define([ return; } - if (expired && tile.hasTilesetContent) { - unloadSubtree(tileset, tile); + if (expired) { + if (tile.hasRenderableContent) { + decrementPointAndFeatureLoadCounts(tileset, tile.content); + --tileset._statistics.numberContentReady; + } else if (tile.hasTilesetContent) { + destroySubtree(tileset, tile); + } } ++stats.numberOfPendingRequests; @@ -1591,6 +1598,7 @@ define([ tile._sse = getScreenSpaceError(tileset, tile.geometricError, tile, frameState); tile.selected = false; tile._finalResolution = false; + tile.updateExpiration(); touch(tileset, tile, outOfCore); } @@ -1623,7 +1631,12 @@ define([ var loadSiblings = tileset.loadSiblings; if (tile.hasTilesetContent) { - updateAndPushChildren(tileset, tile, frameState, stack, loadSiblings, outOfCore); + if (tile.contentExpired) { + // Request new content and destroy subtree + loadTile(tile); + } else { + updateAndPushChildren(tileset, tile, frameState, stack, loadSiblings, outOfCore); + } } else { if (tile.refine === Cesium3DTileRefine.ADD) { loadAndAddToQueue(tileset, tile, finalQueue); @@ -1751,12 +1764,17 @@ define([ // Remove from processing queue tileset._processingQueue.splice(index, 1); --tileset._statistics.numberProcessing; + if (tile.hasRenderableContent) { // RESEARCH_IDEA: ability to unload tiles (without content) for an // external tileset when all the tiles are unloaded. - ++tileset._statistics.numberContentReady; incrementPointAndFeatureLoadCounts(tileset, tile.content); - tile.replacementNode = tileset._replacementList.add(tile); + ++tileset._statistics.numberContentReady; + + // Add to the tile cache. Previously expired tiles are already in the cache. + if (!defined(tile.replacementNode)) { + tile.replacementNode = tileset._replacementList.add(tile); + } } } else { // Not in processing queue @@ -1981,8 +1999,9 @@ define([ } } - function unloadTile(tileset, tile) { - if (!tile.hasRenderableContent) { + function unloadTileFromCache(tileset, tile) { + var node = tile.replacementNode; + if (!defined(node)) { return; } @@ -1991,13 +2010,12 @@ define([ var tileUnload = tileset.tileUnload; tileUnload.raiseEvent(tile); - replacementList.remove(tile.replacementNode); + replacementList.remove(node); decrementPointAndFeatureLoadCounts(tileset, tile.content); --stats.numberContentReady; - tile.unloadContent(); } - function unloadTiles(tileset, frameState) { + function unloadTiles(tileset) { var trimTiles = tileset._trimTiles; tileset._trimTiles = false; @@ -2013,7 +2031,8 @@ define([ while ((node !== sentinel) && ((replacementList.length > maximumNumberOfLoadedTiles) || trimTiles)) { var tile = node.item; node = node.next; - unloadTile(tileset, tile); + unloadTileFromCache(tileset, tile); + tile.unloadContent(); } } @@ -2100,7 +2119,7 @@ define([ updateTiles(this, frameState); if (outOfCore) { - unloadTiles(this, frameState); + unloadTiles(this); } // Events are raised (added to the afterRender queue) here since promises diff --git a/Source/Scene/PointCloud3DTileContent.js b/Source/Scene/PointCloud3DTileContent.js index c640c3978f8f..361eaa3c48b8 100644 --- a/Source/Scene/PointCloud3DTileContent.js +++ b/Source/Scene/PointCloud3DTileContent.js @@ -115,6 +115,7 @@ define([ this._quantizedVolumeScale = undefined; this._quantizedVolumeOffset = undefined; + this._modelMatrix = Matrix4.clone(Matrix4.IDENTITY); this._mode = undefined; /** @@ -1138,7 +1139,8 @@ define([ * Part of the {@link Cesium3DTileContent} interface. */ PointCloud3DTileContent.prototype.update = function(tileset, frameState) { - var updateModelMatrix = this._tile.transformDirty || this._mode !== frameState.mode; + var modelMatrixChanged = !Matrix4.equals(this._modelMatrix, this._tile.computedTransform); + var updateModelMatrix = modelMatrixChanged || this._mode !== frameState.mode; this._mode = frameState.mode; if (!defined(this._drawCommand)) { From 18e641b6d6674fe5b7ab8493094aa28d38a85274 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 26 Apr 2017 13:39:44 -0400 Subject: [PATCH 4/7] Clean up model matrix code --- Source/Scene/PointCloud3DTileContent.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Source/Scene/PointCloud3DTileContent.js b/Source/Scene/PointCloud3DTileContent.js index 361eaa3c48b8..77cc4f8af213 100644 --- a/Source/Scene/PointCloud3DTileContent.js +++ b/Source/Scene/PointCloud3DTileContent.js @@ -1139,8 +1139,10 @@ define([ * Part of the {@link Cesium3DTileContent} interface. */ PointCloud3DTileContent.prototype.update = function(tileset, frameState) { - var modelMatrixChanged = !Matrix4.equals(this._modelMatrix, this._tile.computedTransform); + var modelMatrix = this._tile.computedTransform; + var modelMatrixChanged = !Matrix4.equals(this._modelMatrix, modelMatrix); var updateModelMatrix = modelMatrixChanged || this._mode !== frameState.mode; + this._mode = frameState.mode; if (!defined(this._drawCommand)) { @@ -1153,17 +1155,18 @@ define([ } if (updateModelMatrix) { + Matrix4.clone(modelMatrix, this._modelMatrix); if (defined(this._rtcCenter)) { - Matrix4.multiplyByTranslation(this._tile.computedTransform, this._rtcCenter, this._drawCommand.modelMatrix); + Matrix4.multiplyByTranslation(modelMatrix, this._rtcCenter, this._drawCommand.modelMatrix); } else if (defined(this._quantizedVolumeOffset)) { - Matrix4.multiplyByTranslation(this._tile.computedTransform, this._quantizedVolumeOffset, this._drawCommand.modelMatrix); + Matrix4.multiplyByTranslation(modelMatrix, this._quantizedVolumeOffset, this._drawCommand.modelMatrix); } else { - Matrix4.clone(this._tile.computedTransform, this._drawCommand.modelMatrix); + Matrix4.clone(modelMatrix, this._drawCommand.modelMatrix); } if (frameState.mode !== SceneMode.SCENE3D) { var projection = frameState.mapProjection; - var modelMatrix = this._drawCommand.modelMatrix; + modelMatrix = this._drawCommand.modelMatrix; var translation = Matrix4.getColumn(modelMatrix, 3, scratchComputedTranslation); if (!Cartesian4.equals(translation, Cartesian4.UNIT_W)) { Transforms.basisTo2D(projection, modelMatrix, modelMatrix); From a46ca4c5afe94f6464c4441d5cb1403c3e1add6d Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 26 Apr 2017 17:45:13 -0400 Subject: [PATCH 5/7] Added tests + styling fix --- Source/Scene/Cesium3DTile.js | 12 +- Source/Scene/Cesium3DTileset.js | 1 - .../BatchedExpiration/batchedExpiration.b3dm | Bin 0 -> 14813 bytes .../Batched/BatchedExpiration/tileset.json | 44 +++++ .../Tilesets/TilesetSubtreeExpiration/ll.b3dm | Bin 0 -> 14829 bytes .../Tilesets/TilesetSubtreeExpiration/lr.b3dm | Bin 0 -> 14829 bytes .../TilesetSubtreeExpiration/parent.b3dm | Bin 0 -> 14805 bytes .../TilesetSubtreeExpiration/subtree.json | 86 +++++++++ .../TilesetSubtreeExpiration/tileset.json | 72 +++++++ .../Tilesets/TilesetSubtreeExpiration/ul.b3dm | Bin 0 -> 14809 bytes .../Tilesets/TilesetSubtreeExpiration/ur.b3dm | Bin 0 -> 14817 bytes Specs/Scene/Cesium3DTilesetSpec.js | 179 +++++++++++++++++- 12 files changed, 383 insertions(+), 11 deletions(-) create mode 100644 Specs/Data/Cesium3DTiles/Batched/BatchedExpiration/batchedExpiration.b3dm create mode 100644 Specs/Data/Cesium3DTiles/Batched/BatchedExpiration/tileset.json create mode 100644 Specs/Data/Cesium3DTiles/Tilesets/TilesetSubtreeExpiration/ll.b3dm create mode 100644 Specs/Data/Cesium3DTiles/Tilesets/TilesetSubtreeExpiration/lr.b3dm create mode 100644 Specs/Data/Cesium3DTiles/Tilesets/TilesetSubtreeExpiration/parent.b3dm create mode 100644 Specs/Data/Cesium3DTiles/Tilesets/TilesetSubtreeExpiration/subtree.json create mode 100644 Specs/Data/Cesium3DTiles/Tilesets/TilesetSubtreeExpiration/tileset.json create mode 100644 Specs/Data/Cesium3DTiles/Tilesets/TilesetSubtreeExpiration/ul.b3dm create mode 100644 Specs/Data/Cesium3DTiles/Tilesets/TilesetSubtreeExpiration/ur.b3dm diff --git a/Source/Scene/Cesium3DTile.js b/Source/Scene/Cesium3DTile.js index f19ded63180c..ee2c28cbf434 100644 --- a/Source/Scene/Cesium3DTile.js +++ b/Source/Scene/Cesium3DTile.js @@ -442,7 +442,7 @@ define([ */ contentAvailable : { get : function() { - return this.contentReady || defined(this._expiredContent); + return this.contentReady || (defined(this._expiredContent) && this._contentState !== Cesium3DTileContentState.FAILED); } }, @@ -633,10 +633,14 @@ define([ content.readyPromise.then(function(content) { if (that.isDestroyed()) { // Tile is unloaded before the content finishes processing - that._content.destroy(); return when.reject('tile is destroyed'); } updateExpireDate(that); + + // Refresh style for expired content + that.lastSelectedFrameNumber = 0; + that.lastStyleTime = 0; + that._contentState = Cesium3DTileContentState.READY; that._contentReadyPromise.resolve(content); }).otherwise(function(error) { @@ -686,10 +690,6 @@ define([ this.replacementNode = undefined; - // Restore properties set per frame to their defaults - this.distanceToCamera = 0; - this.visibilityPlaneMask = 0; - this.selected = false; this.lastSelectedFrameNumber = 0; this.lastStyleTime = 0; diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 8863fb716f80..9bc688fb07b4 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -1920,7 +1920,6 @@ define([ var selectedTiles = tileset._selectedTiles; var length = selectedTiles.length; var tileVisible = tileset.tileVisible; - var tile, i; var bivariateVisibilityTest = tileset._hasMixedContent && frameState.context.stencilBuffer && length > 0; diff --git a/Specs/Data/Cesium3DTiles/Batched/BatchedExpiration/batchedExpiration.b3dm b/Specs/Data/Cesium3DTiles/Batched/BatchedExpiration/batchedExpiration.b3dm new file mode 100644 index 0000000000000000000000000000000000000000..b3a7e3cb36ced2cafd6da8073e256ec1b6f84598 GIT binary patch literal 14813 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 literal 0 HcmV?d00001 diff --git a/Specs/Data/Cesium3DTiles/Tilesets/TilesetSubtreeExpiration/lr.b3dm b/Specs/Data/Cesium3DTiles/Tilesets/TilesetSubtreeExpiration/lr.b3dm new file mode 100644 index 0000000000000000000000000000000000000000..641627aafc6252769b543e1beddca97c46183670 GIT binary patch literal 14829 zcmeHOdw5jUwO^uwA}aNIeLuz#HQ;1C?=uq~nVBR=BqW#w#70Ob$w@Lgk2sGA#89kK z5fyI{tqQI9Kz!edEmdkm=2WeUulj!0M}1YR_O|!-)B6?gU3<^$Gi&l73AXnSzMFx) z*I9e5-~R2j*IwrgoV2KIv3&sGb3ef0*t4IN<8pnEI}~iJnA2QSReNUR9Cw*4^}2f8 zkv4Z(ljM;-ibwTm9^GSjOpnjwU+i($B;p;Bbf(Qhi&ELE%6>!l>x!hwlI+(EPhMxL zexJ`LnUbNYLT6~QENiN&Ns2CXy6IOXUGbZK!|~O9x~%zi2}fjMXZn05+TceKDnnLG zRnZimra5q??DOfSAsc>O6Ly*@%YL7!o2Kd5X-F4oV9VDOPKzZ;UIU5iJ_ScSxeE=Q z**g5Pq~=w+ia&mzZXm0?%J9pYfiq~T=@X7P>XUG}4wUZ4l^Tj)(KN?TLTE)sa9tNr zri8InCBJScVnPK2Et|6L^9fpp-&9Q`s-h?E%N#4x(V50gk!3GVfqR04R7q2G!y~I+ zzhA*v$!M+nC0+KIUd=B_J`5CYhU`;JW~BKvRaSJL8lO+!)*7C?{RtE%XSe>7b&a1w^3%c`U(s*V{U;i8$!MA5J4*qM@F_Q;Y~Mh8Vw zG1{0Urn$J+mHX+4HqK`GI@1K0bEwGEaBHiTN+pshcUg~HTr_tjQjv5d5ogMlOnbYP zTo|z~a+i^dX36bww=7Frb?xmb3qvI3E*sLx2uowUY)!oANN`|WA9_v2LM8ouy>OQY*YPw|lFphr1hdHflUPV$Q zzlIqu`6Nlh&5DJWB7jfD5SW_kHze7o;?eM!vR9TQ6Ejd%6pW_gK|oW|@W;R`$K#|d z?)4N_A5SD>;pkY_uHd2k2Q6RnvIXMl#clNC(PrzHaGPb_kafwY>4uK!%5^B2rlMg^ zV>ETuiNFvLLm;4PAOHS`mVYwkQwuvczB758& zR@_R4(}^S=UA3(=9f?}0(t^_C?zWOCe$L&pmmTP?WTG97*jmC}5%fC8YB{q82Z{}G zj;^E?%S6+Wu4u$+3r4#-!|t+lGGpOTu43?t(h`Y>lgpY}?O~Yt10PN%!^?73`R%H) z;vMNucB8~I?Qv(4Z0@#jI$Y*)vlSJJP!86qNi-W+eIoPaf-R6uLmW|3u+rgV2diBw zmJy|Bnr6AMpS#CZ@`*2Ca}!ZywHR3>gOe}2#n%SX#(M}$(t*r#3opcpoRZz+>%QWw zWDgjO@Ib)P2E=E|#ejaild(OtmZq&Z%eK^ll*Jx}+!a*~)eGh|*Ed#R8qA$j-%Ph} zvBw>Wg*z;^;piO;r>$fp9Oe5jE^@n{wpu&mkqa}Jwr)pe+1wqDX1KpQ9BYZ-jR+@| zyzK6u`zzxdZISl&ObT6_u-dQ>>a18Kl{*&rxW+zAnd-7yGtn>}C93R<#3OOMgYp|* zIvI|qy242--ntBPxtFavW~DlF9GJwCsw)|Z;oY^HX`AqzrSXp0l1b-`=GQe;H&)lx z;!+0RjXmz#y83y+8akN2S$W)zRf{U>>gp?5ObWhO#y#$4{xn)$Ne4t0B1J5#5qt`u zqoUFl;*O&v>Znh!yS&!R3r-v__{Jm?iF7R=>0#!{2)iT8JchYQmgX*~iUn6hsfkN& z)WpLvwx13l*67Yiv<+j6h3#CSh+4%@NBk{=CFPJ9^Xu!*s;b~sW1wel8AEzG z(^c0ltg3IQYOD{|HemUwDw7C*!Zs5qvV7#2#Su}u~QdnQJTG?1#Q`JyeJ$v>7 z#73_|buDtkkwS?bG*YOuVu*d6K%e58J7Cb+TTDhm$|2E@w!dZ5f5hb;QSh#a?GwcoAS}hCl?!c62(awrggH!$rq+AWI-Vzn7)t$ zg>>NhLI$`~j?6}iGoUyjc#SALc(D3bIC1O>?-F=W*-c83by?QE5`KSH@w+pAcQ4gU z6~BqfUi?=IO~J2}rbojs_qr;3b^Nym{Pw8(7UK*q*Eiiq1j{PF>3?hdvHkZQep&EG zpZ|u-U)Od8AK83!-&0>)ADHgn6*%D51Nxb~3As15AE) zWliuu*NqQuN*etiZu~`{{J9qbOdigL;?sF4KEPzt{H_CzH zpV0kj|9RWr&fYcs)$BthXY_BbeTmDrM4I~F>+8!V`X0$v&xPy_)1Kh+a}y?I51jiz zw&{so*|$np^*6k;h0ABxZs@Es$Xs3@^Cg3pUzA1DGud8Ia3?T zf#OqNich&w4ix`9Yjfb>|2QP{UbHT>YI|#N$*iNe{PAlw!SmL5L*M<~`Jq5%B5=^m zQ@Ffj!>NIb|7?UdJ?shHe}7r&utVn8)SeY$!gR zm*P_#%7JpGHk1R!r@j=Qa-$q5{*=wzgMAaG*?$R5x1Zkh*I@5MZZ6+a`dRR!PkS2x4xUb^V&*#{zIFB zbH;ti<>727KAo51Qyj{Ha;7$v1I4Gl6rXaV94P*E<#*bb#j@FxT3(wK-E^ZpGrE<_ z2mNrPeSUCNc16!;0qvA~><2>Yx%_3>J@zMGuFLLv_S*i(H*B;weQ_z5+b+4;zUlJP z?5}GM4_xiK-!54*m&?Q1P<%Qs#iuxw1LaI@CID5 z=f_utmfk%+`yKsw`_jp`g#NaEdq0!Mb^j#v<%S!|Pip(G?A&=*g#O;TbqAA&v!VEO zUW!j~CrgBM)RW$V;+p^fU=Q17h_btjKf-huXgXnz~pk0>9z?c~1eFF&#ToxfLJqcxTjDd%{>aIn5oDe} zXyfG1?&Q5CKL4LTL*MH~P4>Lt=E$$Lxw%wP4Q6Q2=e9v`%E; zZ;8+HmFt}Nj3D#)pp6rs-O2y#_^`T=`&n6D=!cSp9qZY+_$%~7`3$t7wqi{9i80m> zH74xDn6MLm!;K5QuoHe1N9aT^dB4?LQic44z&?>LMM8mAC14T-BWzwCvfPTR2FuWqwokI;!;=ttu(Z1)sj_z4_3CzXXAHCr})B8;Ltg#EbJ&p;UjdS z7y8lo3)?-#-v`*M|Kng^7!UiyelP+1{onvN5GGxPrzR5%5uz-ib|foU)m zO5k+tOTYuA;KkMpXMhAUDA+2Xf&n^cU}CR<5ByMuZ5d35Suhi3Ksoj^AOt}OKn3;z zsDvt*jqPkW6XrlQoQ3UKFc)fJ9@Ib`_BAjc&W3ty>!AS_!UAZ7bFgoO@4~sT2%4~8 z1n0qGSc2^mXol}W7+SDxfmUb-3)-Lq`!?u=2%L}Y`EUWmAqG)MU>}7fTnJr|!oCaA zkb!P&yWt{O3d>+Qw#%UhRzNRY4ByB8Vps{6zz?wf0bB|{gjH}ET#o%^um-Mx)o>;D ztKllR8rEXF7OsJRgCD^*2@PuZJ7pMz{&vn_vU{6n+95;b!bN!mV%% zY=Yac-vqbAX1D{}J75dk33tKW*xn8I!2NI^+zbDX{k`xrcmTFyyA>XUZSV{DIs6j) zpTl-|7#@OOVgC?30>6enZ2Mpb^g|YGY;E`rJPwb+qwrhoAB892Nq7p|r(h>M3(vsQ z@ErC}!wc{`cphHF{&{!_UWQk&eFa{H*Wh({1KT&?P53>$4R66a*uMqu!h7&Ow(r9q z;3N1DK7fz0{{TLPKf)*Q8TOyRpWt)&0^2X(OL_=KCGP`c`;5brGM3N2c&^6s*$>a& zSU&sXnH|e#Jf7~cd?sK$7|Z7XtQlkZ9Ef#hEFb56MOS+?5l*|DR}rUAEDUv9tqP75 z-gBBh5nuXljj%UkU7h%QFg1u6I~2ebKz{RnS)p5 zn#PAq3Uoa93jNgS%#9F1R|N1bUACN!bVQry=YO?^V-Ac2f}(W}BS(yz(RiSVc%^ju z#NLs1gs;GPF{=>hygvVG)*!ujIcv~>csr{wkV_zZZ%e$BHF$`=pfxD|xL*FNMr_Xp zZ087Dqq>|B<%Gy`tE4-hJh_cv`p{!6Gt|=*Gj7@xMe;(xoHI;X0^v9nyHw6_-j@rZHaVA4$c#u%H}J~)S8GU z*dm7sW^Ne4^OLavv+-5xiUJ9(B!}h9;SJ+_ R#jg!|#QZ~y;mUd^{x5sFpq2mt literal 0 HcmV?d00001 diff --git a/Specs/Data/Cesium3DTiles/Tilesets/TilesetSubtreeExpiration/parent.b3dm b/Specs/Data/Cesium3DTiles/Tilesets/TilesetSubtreeExpiration/parent.b3dm new file mode 100644 index 0000000000000000000000000000000000000000..8f1a47aee7e3d28d14baff9d0fcc0fe12afbe738 GIT binary patch literal 14805 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 KjN#0dj{9H0yqqoo literal 0 HcmV?d00001 diff --git a/Specs/Data/Cesium3DTiles/Tilesets/TilesetSubtreeExpiration/subtree.json b/Specs/Data/Cesium3DTiles/Tilesets/TilesetSubtreeExpiration/subtree.json new file mode 100644 index 000000000000..1451c6355150 --- /dev/null +++ b/Specs/Data/Cesium3DTiles/Tilesets/TilesetSubtreeExpiration/subtree.json @@ -0,0 +1,86 @@ +{ + "asset": { + "version": "0.0" + }, + "geometricError": 70, + "root": { + "boundingVolume": { + "region": [ + -1.3197209591796106, + 0.6988424218, + -1.3196390408203893, + 0.6989055782, + 0, + 20 + ] + }, + "geometricError": 70, + "refine": "add", + "children": [ + { + "boundingVolume": { + "region": [ + -1.3197209591796106, + 0.6988424218, + -1.31968, + 0.698874, + 0, + 20 + ] + }, + "geometricError": 0, + "content": { + "url": "ll.b3dm" + } + }, + { + "boundingVolume": { + "region": [ + -1.31968, + 0.6988424218, + -1.3196390408203893, + 0.698874, + 0, + 20 + ] + }, + "geometricError": 0, + "content": { + "url": "lr.b3dm" + } + }, + { + "boundingVolume": { + "region": [ + -1.31968, + 0.698874, + -1.3196390408203893, + 0.6989055782, + 0, + 20 + ] + }, + "geometricError": 0, + "content": { + "url": "ur.b3dm" + } + }, + { + "boundingVolume": { + "region": [ + -1.3197209591796106, + 0.698874, + -1.31968, + 0.6989055782, + 0, + 20 + ] + }, + "geometricError": 0, + "content": { + "url": "ul.b3dm" + } + } + ] + } +} diff --git a/Specs/Data/Cesium3DTiles/Tilesets/TilesetSubtreeExpiration/tileset.json b/Specs/Data/Cesium3DTiles/Tilesets/TilesetSubtreeExpiration/tileset.json new file mode 100644 index 000000000000..e9099172b26b --- /dev/null +++ b/Specs/Data/Cesium3DTiles/Tilesets/TilesetSubtreeExpiration/tileset.json @@ -0,0 +1,72 @@ +{ + "asset": { + "version": "0.0" + }, + "properties": { + "id": { + "minimum": 0, + "maximum": 9 + }, + "Longitude": { + "minimum": -1.3197192952275933, + "maximum": -1.319644104024109 + }, + "Latitude": { + "minimum": 0.698848878034009, + "maximum": 0.6989046192460953 + }, + "Height": { + "minimum": 6.161747192963958, + "maximum": 84.83180232718587 + } + }, + "geometricError": 240, + "root": { + "boundingVolume": { + "region": [ + -1.3197209591796106, + 0.6988424218, + -1.3196390408203893, + 0.6989055782, + 0, + 88 + ] + }, + "geometricError": 70, + "refine": "add", + "content": { + "boundingVolume": { + "region": [ + -1.3197004795898053, + 0.6988582109, + -1.3196595204101946, + 0.6988897891, + 0, + 88 + ] + }, + "url": "parent.b3dm" + }, + "children": [ + { + "expire": { + "duration": 5 + }, + "boundingVolume": { + "region": [ + -1.3197209591796106, + 0.6988424218, + -1.3196390408203893, + 0.6989055782, + 0, + 20 + ] + }, + "geometricError": 70, + "content": { + "url": "subtree.json" + } + } + ] + } +} diff --git a/Specs/Data/Cesium3DTiles/Tilesets/TilesetSubtreeExpiration/ul.b3dm b/Specs/Data/Cesium3DTiles/Tilesets/TilesetSubtreeExpiration/ul.b3dm new file mode 100644 index 0000000000000000000000000000000000000000..30c904d18b817893ab83ca7dce72aa1050410b2a GIT binary patch literal 14809 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 Date: Mon, 1 May 2017 16:02:00 -0400 Subject: [PATCH 6/7] Fix test --- Specs/Scene/Cesium3DTilesetSpec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Specs/Scene/Cesium3DTilesetSpec.js b/Specs/Scene/Cesium3DTilesetSpec.js index 3c9037ba3f68..eed5ba937130 100644 --- a/Specs/Scene/Cesium3DTilesetSpec.js +++ b/Specs/Scene/Cesium3DTilesetSpec.js @@ -2569,7 +2569,7 @@ defineSuite([ // Wait for the new tileset content to come in with one less leaf return pollToPromise(function() { scene.renderForSpecs(); - return subtreeRoot.contentReady; + return subtreeRoot.contentReady && tileset.tilesLoaded; }).then(function() { scene.renderForSpecs(); expect(stats.numberOfCommands).toBe(4); From b5c719d60eb124940a61c1cd91ca2281ef254a0d Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Mon, 8 May 2017 14:12:13 -0400 Subject: [PATCH 7/7] Fix tests --- Source/Scene/Cesium3DTileset.js | 1 + Source/Scene/Cesium3DTilesetTraversal.js | 15 +++++++------- Specs/Scene/Cesium3DTilesetSpec.js | 25 ++++++++++-------------- 3 files changed, 18 insertions(+), 23 deletions(-) diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index d852e97bf41e..44946b40d22c 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -1617,6 +1617,7 @@ define([ node = node.next; unloadTileFromCache(tileset, tile); tile.unloadContent(); + totalMemoryUsageInBytes = tileset.totalMemoryUsageInBytes; } } diff --git a/Source/Scene/Cesium3DTilesetTraversal.js b/Source/Scene/Cesium3DTilesetTraversal.js index b8d98b3e6231..da541691cf31 100644 --- a/Source/Scene/Cesium3DTilesetTraversal.js +++ b/Source/Scene/Cesium3DTilesetTraversal.js @@ -64,10 +64,7 @@ define([ return; } - if (root.contentUnloaded) { - loadTile(root, frameState); - return; - } + loadTile(root, frameState); if (!tileset.skipLODs) { // just execute base traversal and add tiles to _desiredTiles @@ -336,6 +333,11 @@ define([ tileset._desiredTiles.push(tile); } + // Stop traversal on the subtree since it will be destroyed + if (tile.hasTilesetContent && tile.contentExpired) { + return false; + } + // stop traversal when we've attained the desired level of error if (tile._screenSpaceError <= baseScreenSpaceError && !tile.hasTilesetContent) { // update children so the leaf handler can check if any are visible for the children union bound optimization @@ -343,10 +345,6 @@ define([ return false; } - if (tile.hasTilesetContent && tile.contentExpired) { - return false; - } - var childrenVisibility = updateChildren(tileset, tile, frameState); var showAdditive = tile.refine === Cesium3DTileRefine.ADD; var showReplacement = tile.refine === Cesium3DTileRefine.REPLACE && (childrenVisibility & Cesium3DTileChildrenVisibility.VISIBLE_IN_REQUEST_VOLUME) !== 0; @@ -493,6 +491,7 @@ define([ var tileset = this.tileset; var maximumScreenSpaceError = tileset._maximumScreenSpaceError; + // Stop traversal on the subtree since it will be destroyed if (tile.hasTilesetContent && tile.contentExpired) { return emptyArray; } diff --git a/Specs/Scene/Cesium3DTilesetSpec.js b/Specs/Scene/Cesium3DTilesetSpec.js index b588eceda28e..595a86d1abb6 100644 --- a/Specs/Scene/Cesium3DTilesetSpec.js +++ b/Specs/Scene/Cesium3DTilesetSpec.js @@ -416,15 +416,7 @@ defineSuite([ expect(stats.numberProcessing).toEqual(0); return Cesium3DTilesTester.waitForReady(scene, tileset).then(function() { - // Check that root tile is requested - expect(stats.visited).toEqual(0); - expect(stats.numberOfCommands).toEqual(0); - expect(stats.numberOfPendingRequests).toEqual(1); - expect(stats.numberProcessing).toEqual(0); - - // Update and check that child tiles are now requested - scene.renderForSpecs(); - + // Check that root and children are requested expect(stats.visited).toEqual(5); expect(stats.numberOfCommands).toEqual(0); expect(stats.numberOfPendingRequests).toEqual(5); @@ -1613,6 +1605,7 @@ defineSuite([ }); it('destroys before tile finishes loading', function() { + viewRootOnly(); var tileset = scene.primitives.add(new Cesium3DTileset({ url : tilesetUrl })); @@ -2547,7 +2540,7 @@ defineSuite([ RequestScheduler.maximumRequests = originalMaxmimumRequests; expiredContent = tile._expiredContent; expect(tile.contentExpired).toBe(true); - expect(tile.contentAvailable).toBe(true); // Expire content now exists + expect(tile.contentAvailable).toBe(true); // Expired content now exists expect(expiredContent).toBeDefined(); // Expired content renders while new content loads in @@ -2607,10 +2600,9 @@ defineSuite([ return Cesium3DTilesTester.loadTileset(scene, tilesetSubtreeExpirationUrl).then(function(tileset) { // Intercept the request and load a subtree with one less child. Still want to make an actual request to simulate // real use cases instead of immediately returning a pre-created array buffer. - var originalLoad = loadWithXhr.load; spyOn(loadWithXhr, 'load').and.callFake(function(url, responseType, method, data, headers, deferred, overrideMimeType) { var newDeferred = when.defer(); - originalLoad(tilesetSubtreeUrl, responseType, method, data, headers, newDeferred, overrideMimeType); + loadWithXhr.defaultLoad(tilesetSubtreeUrl, responseType, method, data, headers, newDeferred, overrideMimeType); newDeferred.promise.then(function(arrayBuffer) { deferred.resolve(modifySubtreeBuffer(arrayBuffer)); }); @@ -2634,7 +2626,8 @@ defineSuite([ tileset.tileUnload.addEventListener(spyUpdate); // Tiles in the subtree are removed from the cache and destroyed. - scene.renderForSpecs(); + scene.renderForSpecs(); // Becomes expired + scene.renderForSpecs(); // Makes request expect(subtreeRoot.children).toEqual([]); for (var i = 0; i < childrenLength; ++i) { expect(subtreeChildren[0].isDestroyed()).toBe(true); @@ -2642,7 +2635,7 @@ defineSuite([ expect(spyUpdate.calls.count()).toEqual(4); // Remove the spy so new tiles load in normally - loadWithXhr.load = originalLoad; + loadWithXhr.load = loadWithXhr.defaultLoad; // Wait for the new tileset content to come in with one less leaf return pollToPromise(function() { @@ -2668,12 +2661,14 @@ defineSuite([ // Trigger expiration to happen next frame tile.expireDate = JulianDate.addSeconds(JulianDate.now(), -1.0, new JulianDate()); + // After update the tile is expired + scene.renderForSpecs(); + // Make request (it will fail) scene.renderForSpecs(); // Render scene scene.renderForSpecs(); - expect(tile._contentState).toBe(Cesium3DTileContentState.FAILED); expect(stats.numberOfCommands).toBe(0); expect(stats.numberTotal).toBe(1);