Skip to content

Commit 9733e3b

Browse files
committed
Added expire property to tiles
1 parent 5d3f792 commit 9733e3b

7 files changed

+187
-22
lines changed

Source/Scene/Batched3DModel3DTileContent.js

+10-4
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,9 @@ define([
154154
* Part of the {@link Cesium3DTileContent} interface.
155155
*/
156156
Batched3DModel3DTileContent.prototype.initialize = function(arrayBuffer, byteOffset) {
157+
// Destroy expired resources if they exist.
158+
destroyResources(this);
159+
157160
var byteStart = defaultValue(byteOffset, 0);
158161
byteOffset = byteStart;
159162

@@ -255,7 +258,12 @@ define([
255258
this._model.update(frameState);
256259

257260
frameState.addCommand = oldAddCommand;
258-
};
261+
};
262+
263+
function destroyResources(content) {
264+
content._model = content._model && content._model.destroy();
265+
content.batchTableResources = content.batchTableResources && content.batchTableResources.destroy();
266+
}
259267

260268
/**
261269
* Part of the {@link Cesium3DTileContent} interface.
@@ -268,9 +276,7 @@ define([
268276
* Part of the {@link Cesium3DTileContent} interface.
269277
*/
270278
Batched3DModel3DTileContent.prototype.destroy = function() {
271-
this._model = this._model && this._model.destroy();
272-
this.batchTableResources = this.batchTableResources && this.batchTableResources.destroy();
273-
279+
destroyResources(this);
274280
return destroyObject(this);
275281
};
276282

Source/Scene/Cesium3DTile.js

+35
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ define([
1313
'../Core/getExtensionFromUri',
1414
'../Core/Intersect',
1515
'../Core/joinUrls',
16+
'../Core/JulianDate',
1617
'../Core/Matrix3',
1718
'../Core/Matrix4',
1819
'../Core/OrientedBoundingBox',
@@ -46,6 +47,7 @@ define([
4647
getExtensionFromUri,
4748
Intersect,
4849
joinUrls,
50+
JulianDate,
4951
Matrix3,
5052
Matrix4,
5153
OrientedBoundingBox,
@@ -241,6 +243,30 @@ define([
241243
*/
242244
this.replacementNode = undefined;
243245

246+
var expire = header.expire;
247+
var expireDuration;
248+
var expireDate;
249+
if (defined(expire)) {
250+
expireDuration = expire.duration;
251+
if (defined(expire.date)) {
252+
expireDate = JulianDate.fromIso8601(expire.date);
253+
}
254+
}
255+
256+
/**
257+
* The time in seconds after the tile's content is downloaded when the content expires and new content is requested.
258+
*
259+
* @type {Number}
260+
*/
261+
this.expireDuration = expireDuration;
262+
263+
/**
264+
* The date when the content expires and new content is requested.
265+
*
266+
* @type {JulianDate}
267+
*/
268+
this.expireDate = expireDate;
269+
244270
// Members that are updated every frame for tree traversal and rendering optimizations:
245271

246272
/**
@@ -457,6 +483,15 @@ define([
457483
this._debugContentBoundingVolume = this._debugContentBoundingVolume && this._debugContentBoundingVolume.destroy();
458484
};
459485

486+
Cesium3DTile.prototype.unloadContentAndMakeEmpty = function() {
487+
this.hasContent = false;
488+
this.hasTilesetContent = false;
489+
this._createContent = function() {
490+
return new Empty3DTileContent();
491+
};
492+
this.unloadContent();
493+
};
494+
460495
/**
461496
* Determines whether the tile's bounding volume intersects the culling volume.
462497
*

Source/Scene/Cesium3DTileContentState.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ define([
1313
LOADING : 1, // Is waiting on a pending request
1414
PROCESSING : 2, // Request received. Contents are being processed for rendering. Depending on the content, it might make its own requests for external data.
1515
READY : 3, // Ready to render.
16-
FAILED : 4 // Request failed.
16+
EXPIRED : 4, // Is expired and will be unloaded once new content is loaded
17+
FAILED : 5 // Request failed.
1718
};
1819

1920
return freezeObject(Cesium3DTileContentState);

Source/Scene/Cesium3DTileset.js

+111-8
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ define([
1212
'../Core/Intersect',
1313
'../Core/isDataUri',
1414
'../Core/joinUrls',
15+
'../Core/JulianDate',
1516
'../Core/loadJson',
1617
'../Core/Math',
1718
'../Core/Request',
@@ -20,6 +21,7 @@ define([
2021
'../ThirdParty/Uri',
2122
'../ThirdParty/when',
2223
'./Cesium3DTile',
24+
'./Cesium3DTileContentState',
2325
'./Cesium3DTileRefine',
2426
'./Cesium3DTileStyleEngine',
2527
'./CullingVolume',
@@ -37,6 +39,7 @@ define([
3739
Intersect,
3840
isDataUri,
3941
joinUrls,
42+
JulianDate,
4043
loadJson,
4144
CesiumMath,
4245
Request,
@@ -45,6 +48,7 @@ define([
4548
Uri,
4649
when,
4750
Cesium3DTile,
51+
Cesium3DTileContentState,
4852
Cesium3DTileRefine,
4953
Cesium3DTileStyleEngine,
5054
CullingVolume,
@@ -669,6 +673,11 @@ define([
669673
// If there is a parentTile, add the root of the currently loading tileset
670674
// to parentTile's children, and increment its numberOfChildrenWithoutContent
671675
if (defined(parentTile)) {
676+
if (parentTile.children.length > 0) {
677+
// Unload the old subtree if it exists
678+
unloadExpiredSubtree(parentTile);
679+
}
680+
672681
parentTile.children.push(rootTile);
673682
++parentTile.numberOfChildrenWithoutContent;
674683

@@ -754,6 +763,13 @@ define([
754763
}
755764
}
756765

766+
function recheckRefinement(tile) {
767+
var ancestor = getAncestorWithContent(tile);
768+
if (defined(ancestor) && (ancestor.refine === Cesium3DTileRefine.REPLACE)) {
769+
prepareRefiningTiles([ancestor]);
770+
}
771+
}
772+
757773
function getScreenSpaceError(geometricError, tile, frameState) {
758774
// TODO: screenSpaceError2D like QuadtreePrimitive.js
759775
if (geometricError === 0.0) {
@@ -786,6 +802,68 @@ define([
786802

787803
///////////////////////////////////////////////////////////////////////////
788804

805+
var scratchJulianDate = new JulianDate();
806+
807+
function updateExpireDate(tile) {
808+
if (defined(tile.expireDuration)) {
809+
var expireDurationDate = JulianDate.now(scratchJulianDate);
810+
JulianDate.addSeconds(expireDurationDate, tile.expireDuration, expireDurationDate);
811+
812+
if (defined(tile.expireDate)) {
813+
if (JulianDate.lessThan(expireDurationDate, tile.expireDate)) {
814+
JulianDate.clone(expireDurationDate, tile.expireDate);
815+
}
816+
}
817+
}
818+
}
819+
820+
function unloadExpiredSubtree(tile) {
821+
var stack = [];
822+
stack.push(tile);
823+
while (stack.length > 0) {
824+
tile = stack.pop();
825+
var children = tile.children;
826+
var length = children.length;
827+
for (var i = 0; i < length; ++i) {
828+
var child = children[i];
829+
child.destroy();
830+
stack.push(child);
831+
}
832+
}
833+
tile.children = [];
834+
tile.unloadContent();
835+
}
836+
837+
function unloadExpiredLeafTile(tile) {
838+
tile.destroy();
839+
var parent = tile.parent;
840+
if (defined(parent)) {
841+
var index = parent.children.indexOf(tile);
842+
parent.children.splice(index, 1);
843+
recheckRefinement(parent);
844+
}
845+
}
846+
847+
function unloadExpiredTile(tile) {
848+
if (tile.children.length === 0) {
849+
unloadExpiredLeafTile(tile);
850+
return;
851+
}
852+
853+
if (tile.hasContent) {
854+
// When the tile is expired and the request fails, then there is no longer any content to show.
855+
// Unload the tile's old content and replace it with Empty3DTileContent.
856+
tile.unloadContentAndMakeEmpty();
857+
// Now that the tile is empty recheck its parent's refinement
858+
recheckRefinement(tile.parent);
859+
} else if (tile.hasTilesetContent) {
860+
// When the tile is the root of an external tileset, unload the entire subtree
861+
unloadExpiredSubtree(tile);
862+
// Also destroy this tile
863+
unloadExpiredLeafTile(tile);
864+
}
865+
}
866+
789867
function requestContent(tileset, tile, outOfCore) {
790868
if (!outOfCore) {
791869
return;
@@ -794,15 +872,30 @@ define([
794872
return;
795873
}
796874

875+
var expired = (tile.content.state === Cesium3DTileContentState.EXPIRED);
876+
797877
tile.requestContent();
798878

799-
if (!tile.contentUnloaded) {
879+
// If the RequestScheduler is full, the content will remain in the UNLOADED or EXPIRED state.
880+
// Otherwise, it will be in the LOADING state.
881+
if (tile.content.state === Cesium3DTileContentState.LOADING) {
800882
var stats = tileset._statistics;
801883
++stats.numberOfPendingRequests;
802884

803885
var removeFunction = removeFromProcessingQueue(tileset, tile);
804-
when(tile.content.contentReadyToProcessPromise).then(addToProcessingQueue(tileset, tile)).otherwise(removeFunction);
805-
when(tile.content.readyPromise).then(removeFunction).otherwise(removeFunction);
886+
when(tile.content.contentReadyToProcessPromise).then(function() {
887+
// Content is loaded and ready to process
888+
addToProcessingQueue(tileset, tile);
889+
updateExpireDate(tile);
890+
}).otherwise(removeFunction);
891+
892+
when(tile.content.readyPromise).then(removeFunction).otherwise(function() {
893+
// The request failed
894+
removeFunction();
895+
if (expired) {
896+
unloadExpiredTile(tile);
897+
}
898+
});
806899
}
807900
}
808901

@@ -895,6 +988,18 @@ define([
895988
var sse = getScreenSpaceError(t.geometricError, t, frameState);
896989
// PERFORMANCE_IDEA: refine also based on (1) occlusion/VMSSE and/or (2) center of viewport
897990

991+
// If the tile is expired, request new content
992+
if (defined(t.expireDate)) {
993+
var now = JulianDate.now(scratchJulianDate);
994+
if (JulianDate.lessThan(now, t.expireDate)) {
995+
// Request new content
996+
if (t.contentReady && (t.hasContent || t.hasTilesetContent)) {
997+
t.content.state = Cesium3DTileContentState.EXPIRED;
998+
requestContent(tileset, t, outOfCore);
999+
}
1000+
}
1001+
}
1002+
8981003
var children = t.children;
8991004
var childrenLength = children.length;
9001005
var child;
@@ -1063,12 +1168,10 @@ define([
10631168
///////////////////////////////////////////////////////////////////////////
10641169

10651170
function addToProcessingQueue(tileset, tile) {
1066-
return function() {
1067-
tileset._processingQueue.push(tile);
1171+
tileset._processingQueue.push(tile);
10681172

1069-
--tileset._statistics.numberOfPendingRequests;
1070-
++tileset._statistics.numberProcessing;
1071-
};
1173+
--tileset._statistics.numberOfPendingRequests;
1174+
++tileset._statistics.numberProcessing;
10721175
}
10731176

10741177
function removeFromProcessingQueue(tileset, tile) {

Source/Scene/Composite3DTileContent.js

+12-5
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ define([
149149
* Part of the {@link Cesium3DTileContent} interface.
150150
*/
151151
Composite3DTileContent.prototype.initialize = function(arrayBuffer, byteOffset) {
152+
// Destroy expired resources if they exist.
153+
destroyResources(this);
154+
152155
byteOffset = defaultValue(byteOffset, 0);
153156

154157
var uint8Array = new Uint8Array(arrayBuffer);
@@ -233,6 +236,14 @@ define([
233236
}
234237
};
235238

239+
function destroyResources(content) {
240+
var contents = content._contents;
241+
var length = contents.length;
242+
for (var i = 0; i < length; ++i) {
243+
contents[i].destroy();
244+
}
245+
}
246+
236247
/**
237248
* Part of the {@link Cesium3DTileContent} interface.
238249
*/
@@ -244,11 +255,7 @@ define([
244255
* Part of the {@link Cesium3DTileContent} interface.
245256
*/
246257
Composite3DTileContent.prototype.destroy = function() {
247-
var contents = this._contents;
248-
var length = contents.length;
249-
for (var i = 0; i < length; ++i) {
250-
contents[i].destroy();
251-
}
258+
destroyResources(this);
252259
return destroyObject(this);
253260
};
254261

Source/Scene/Instanced3DModel3DTileContent.js

+9-3
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,9 @@ define([
167167
* Part of the {@link Cesium3DTileContent} interface.
168168
*/
169169
Instanced3DModel3DTileContent.prototype.initialize = function(arrayBuffer, byteOffset) {
170+
// Destroy expired resources if they exist.
171+
destroyResources(this);
172+
170173
byteOffset = defaultValue(byteOffset, 0);
171174

172175
var uint8Array = new Uint8Array(arrayBuffer);
@@ -320,6 +323,11 @@ define([
320323
frameState.addCommand = oldAddCommand;
321324
};
322325

326+
function destroyResources(content) {
327+
content._modelInstanceCollection = content._modelInstanceCollection && content._modelInstanceCollection.destroy();
328+
content.batchTableResources = content.batchTableResources && content.batchTableResources.destroy();
329+
}
330+
323331
/**
324332
* Part of the {@link Cesium3DTileContent} interface.
325333
*/
@@ -331,9 +339,7 @@ define([
331339
* Part of the {@link Cesium3DTileContent} interface.
332340
*/
333341
Instanced3DModel3DTileContent.prototype.destroy = function() {
334-
this._modelInstanceCollection = this._modelInstanceCollection && this._modelInstanceCollection.destroy();
335-
this.batchTableResources = this.batchTableResources && this.batchTableResources.destroy();
336-
342+
destroyResources(this);
337343
return destroyObject(this);
338344
};
339345
return Instanced3DModel3DTileContent;

0 commit comments

Comments
 (0)