Skip to content

Commit 939e4c3

Browse files
authored
Merge pull request #6390 from AnalyticalGraphicsInc/traversal-cleanup
3D Tiles Traversal cleanup
2 parents 8ff642f + b527503 commit 939e4c3

18 files changed

+793
-923
lines changed

CHANGES.md

+6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ Change Log
1515
* Added optional `width` and `height` to `Scene.drillPick` for specifying a search area.
1616

1717
##### Fixes :wrench:
18+
* Several performance improvements and fixes to the 3D Tiles traversal code. [#6390](https://github.com/AnalyticalGraphicsInc/cesium/pull/6390)
19+
* Improved load performance when `skipLevelOfDetail` is false.
20+
* Fixed a bug that caused some skipped tiles to load when `skipLevelOfDetail` is true.
21+
* Fixed pick statistics in the 3D Tiles Inspector.
22+
* Fixed drawing of debug labels for external tilesets.
23+
* Fixed drawing of debug outlines for empty tiles.
1824
* The Geocoder widget now takes terrain altitude into account when calculating its final destination.
1925
* The Viewer widget now takes terrain altitude into account when zooming or flying to imagery layers.
2026
* Fixed `getPickRay` in 2D. [#2480](https://github.com/AnalyticalGraphicsInc/cesium/issues/2480)

Source/Core/ManagedArray.js

+14-3
Original file line numberDiff line numberDiff line change
@@ -74,21 +74,32 @@ define([
7474
* Sets the element at an index. Resizes the array if index is greater than the length of the array.
7575
*
7676
* @param {Number} index The index to set.
77-
* @param {*} value The value to set at index.
77+
* @param {*} element The element to set at index.
7878
*/
79-
ManagedArray.prototype.set = function(index, value) {
79+
ManagedArray.prototype.set = function(index, element) {
8080
//>>includeStart('debug', pragmas.debug);
8181
Check.typeOf.number('index', index);
8282
//>>includeEnd('debug');
8383

8484
if (index >= this.length) {
8585
this.length = index + 1;
8686
}
87-
this._array[index] = value;
87+
this._array[index] = element;
88+
};
89+
90+
/**
91+
* Returns the last element in the array without modifying the array.
92+
*
93+
* @returns {*} The last element in the array.
94+
*/
95+
ManagedArray.prototype.peek = function() {
96+
return this._array[this._length - 1];
8897
};
8998

9099
/**
91100
* Push an element into the array.
101+
*
102+
* @param {*} element The element to push.
92103
*/
93104
ManagedArray.prototype.push = function(element) {
94105
var index = this.length++;

Source/Scene/Batched3DModel3DTileContent.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -482,8 +482,7 @@ define([
482482
// If any commands were pushed, add derived commands
483483
var commandEnd = frameState.commandList.length;
484484
if ((commandStart < commandEnd) && (frameState.passes.render || frameState.passes.pick) && !defined(tileset.classificationType)) {
485-
var finalResolution = this._tile._finalResolution;
486-
this._batchTable.addDerivedCommands(frameState, commandStart, finalResolution);
485+
this._batchTable.addDerivedCommands(frameState, commandStart);
487486
}
488487
};
489488

Source/Scene/Cesium3DTile.js

+56-47
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ define([
22
'../Core/BoundingSphere',
33
'../Core/Cartesian3',
44
'../Core/Color',
5+
'../Core/ColorGeometryInstanceAttribute',
56
'../Core/CullingVolume',
67
'../Core/defaultValue',
78
'../Core/defined',
@@ -24,7 +25,6 @@ define([
2425
'../Core/Resource',
2526
'../Core/RuntimeError',
2627
'../ThirdParty/when',
27-
'./Cesium3DTileChildrenVisibility',
2828
'./Cesium3DTileContentFactory',
2929
'./Cesium3DTileContentState',
3030
'./Cesium3DTileOptimizationHint',
@@ -38,6 +38,7 @@ define([
3838
BoundingSphere,
3939
Cartesian3,
4040
Color,
41+
ColorGeometryInstanceAttribute,
4142
CullingVolume,
4243
defaultValue,
4344
defined,
@@ -60,7 +61,6 @@ define([
6061
Resource,
6162
RuntimeError,
6263
when,
63-
Cesium3DTileChildrenVisibility,
6464
Cesium3DTileContentFactory,
6565
Cesium3DTileContentState,
6666
Cesium3DTileOptimizationHint,
@@ -235,19 +235,6 @@ define([
235235
*/
236236
this.hasEmptyContent = hasEmptyContent;
237237

238-
/**
239-
* When <code>true</code>, the tile's content is renderable.
240-
* <p>
241-
* This is <code>false</code> until the tile's content is loaded.
242-
* </p>
243-
*
244-
* @type {Boolean}
245-
* @readonly
246-
*
247-
* @private
248-
*/
249-
this.hasRenderableContent = false;
250-
251238
/**
252239
* When <code>true</code>, the tile's content points to an external tileset.
253240
* <p>
@@ -262,14 +249,16 @@ define([
262249
this.hasTilesetContent = false;
263250

264251
/**
265-
* The corresponding node in the cache replacement list.
252+
* The node in the tileset's LRU cache, used to determine when to unload a tile's content.
253+
*
254+
* See {@link Cesium3DTilesetCache}
266255
*
267256
* @type {DoublyLinkedListNode}
268257
* @readonly
269258
*
270259
* @private
271260
*/
272-
this.replacementNode = undefined;
261+
this.cacheNode = undefined;
273262

274263
var expire = header.expire;
275264
var expireDuration;
@@ -295,15 +284,6 @@ define([
295284
*/
296285
this.expireDate = expireDate;
297286

298-
/**
299-
* Marks if the tile is selected this frame.
300-
*
301-
* @type {Boolean}
302-
*
303-
* @private
304-
*/
305-
this.selected = false;
306-
307287
/**
308288
* The time when a style was last applied to this tile.
309289
*
@@ -334,22 +314,27 @@ define([
334314

335315
// Members that are updated every frame for tree traversal and rendering optimizations:
336316
this._distanceToCamera = 0;
337-
this._visibilityPlaneMask = 0;
338-
this._childrenVisibility = Cesium3DTileChildrenVisibility.VISIBLE;
339-
this._lastSelectedFrameNumber = -1;
317+
this._centerZDepth = 0;
340318
this._screenSpaceError = 0;
341-
this._screenSpaceErrorComputedFrame = -1;
319+
this._visibilityPlaneMask = 0;
320+
this._visible = false;
321+
this._inRequestVolume = false;
322+
342323
this._finalResolution = true;
343324
this._depth = 0;
344-
this._centerZDepth = 0;
345325
this._stackLength = 0;
346-
this._selectedFrame = -1;
347326
this._selectionDepth = 0;
348-
this._lastSelectionDepth = undefined;
349-
this._requestedFrame = undefined;
350-
this._lastVisitedFrame = undefined;
327+
328+
this._updatedVisibilityFrame = 0;
329+
this._touchedFrame = 0;
330+
this._visitedFrame = 0;
331+
this._selectedFrame = 0;
332+
this._requestedFrame = 0;
351333
this._ancestorWithContent = undefined;
352-
this._ancestorWithLoadedContent = undefined;
334+
this._ancestorWithContentAvailable = undefined;
335+
this._refines = false;
336+
this._shouldSelect = false;
337+
this._priority = 0.0;
353338
this._isClipped = true;
354339
this._clippingPlanesState = 0; // encapsulates (_isClipped, clippingPlanes.enabled) and number/function
355340

@@ -467,13 +452,13 @@ define([
467452
*/
468453
contentAvailable : {
469454
get : function() {
470-
return this.contentReady || (defined(this._expiredContent) && this._contentState !== Cesium3DTileContentState.FAILED);
455+
return (this.contentReady && !this.hasEmptyContent && !this.hasTilesetContent) || (defined(this._expiredContent) && !this.contentFailed);
471456
}
472457
},
473458

474459
/**
475-
* Determines if the tile is ready to render. <code>true</code> if the tile
476-
* is ready to render; otherwise, <code>false</code>.
460+
* Determines if the tile's content is ready. This is automatically <code>true</code> for
461+
* tile's with empty content.
477462
*
478463
* @memberof Cesium3DTile.prototype
479464
*
@@ -522,6 +507,23 @@ define([
522507
}
523508
},
524509

510+
/**
511+
* Determines if the tile's content failed to load. <code>true</code> if the tile's
512+
* content failed to load; otherwise, <code>false</code>.
513+
*
514+
* @memberof Cesium3DTile.prototype
515+
*
516+
* @type {Boolean}
517+
* @readonly
518+
*
519+
* @private
520+
*/
521+
contentFailed : {
522+
get : function() {
523+
return this._contentState === Cesium3DTileContentState.FAILED;
524+
}
525+
},
526+
525527
/**
526528
* Gets the promise that will be resolved when the tile's content is ready to process.
527529
* This happens after the content is downloaded but before the content is ready
@@ -618,7 +620,7 @@ define([
618620

619621
function createPriorityFunction(tile) {
620622
return function() {
621-
return tile._distanceToCamera;
623+
return tile._priority;
622624
};
623625
}
624626

@@ -690,7 +692,6 @@ define([
690692

691693
if (defined(contentFactory)) {
692694
content = contentFactory(tileset, that, that._contentResource, arrayBuffer, 0);
693-
that.hasRenderableContent = true;
694695
} else {
695696
// The content may be json instead
696697
content = Cesium3DTileContentFactory.json(tileset, that, that._contentResource, arrayBuffer, 0);
@@ -710,7 +711,7 @@ define([
710711
updateExpireDate(that);
711712

712713
// Refresh style for expired content
713-
that.lastStyleTime = 0;
714+
that._selectedFrame = 0;
714715

715716
that._contentState = Cesium3DTileContentState.READY;
716717
that._contentReadyPromise.resolve(content);
@@ -735,7 +736,7 @@ define([
735736
* @private
736737
*/
737738
Cesium3DTile.prototype.unloadContent = function() {
738-
if (!this.hasRenderableContent) {
739+
if (this.hasEmptyContent || this.hasTilesetContent) {
739740
return;
740741
}
741742

@@ -744,8 +745,6 @@ define([
744745
this._contentReadyToProcessPromise = undefined;
745746
this._contentReadyPromise = undefined;
746747

747-
this.replacementNode = undefined;
748-
749748
this.lastStyleTime = 0;
750749
this.clippingPlanesDirty = (this._clippingPlanesState === 0);
751750
this._clippingPlanesState = 0;
@@ -859,7 +858,7 @@ define([
859858
* Computes the distance from the center of the tile's bounding volume to the camera.
860859
*
861860
* @param {FrameState} frameState The frame state.
862-
* @returns {Number} The distance, in meters, or zero if the camera is inside the bounding volume.
861+
* @returns {Number} The distance, in meters.
863862
*
864863
* @private
865864
*/
@@ -1032,14 +1031,24 @@ define([
10321031

10331032
function applyDebugSettings(tile, tileset, frameState) {
10341033
var hasContentBoundingVolume = defined(tile._header.content) && defined(tile._header.content.boundingVolume);
1034+
var empty = tile.hasEmptyContent || tile.hasTilesetContent;
10351035

10361036
var showVolume = tileset.debugShowBoundingVolume || (tileset.debugShowContentBoundingVolume && !hasContentBoundingVolume);
10371037
if (showVolume) {
1038+
var color;
1039+
if (!tile._finalResolution) {
1040+
color = Color.YELLOW;
1041+
} else if (empty) {
1042+
color = Color.DARKGRAY;
1043+
} else {
1044+
color = Color.WHITE;
1045+
}
10381046
if (!defined(tile._debugBoundingVolume)) {
1039-
var color = tile._finalResolution ? (hasContentBoundingVolume ? Color.WHITE : Color.RED) : Color.YELLOW;
10401047
tile._debugBoundingVolume = tile._boundingVolume.createDebugVolume(color);
10411048
}
10421049
tile._debugBoundingVolume.update(frameState);
1050+
var attributes = tile._debugBoundingVolume.getGeometryInstanceAttributes('outline');
1051+
attributes.color = ColorGeometryInstanceAttribute.toValue(color, attributes.color);
10431052
} else if (!showVolume && defined(tile._debugBoundingVolume)) {
10441053
tile._debugBoundingVolume = tile._debugBoundingVolume.destroy();
10451054
}

Source/Scene/Cesium3DTileBatchTable.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -1241,10 +1241,11 @@ define([
12411241
OPAQUE_AND_TRANSLUCENT : 2
12421242
};
12431243

1244-
Cesium3DTileBatchTable.prototype.addDerivedCommands = function(frameState, commandStart, finalResolution) {
1244+
Cesium3DTileBatchTable.prototype.addDerivedCommands = function(frameState, commandStart) {
12451245
var commandList = frameState.commandList;
12461246
var commandEnd = commandList.length;
12471247
var tile = this._content._tile;
1248+
var finalResolution = tile._finalResolution;
12481249
var tileset = tile._tileset;
12491250
var bivariateVisibilityTest = tileset._skipLevelOfDetail && tileset._hasMixedContent && frameState.context.stencilBuffer;
12501251
var styleCommandsNeeded = getStyleCommandsNeeded(this);
@@ -1276,9 +1277,8 @@ define([
12761277
}
12771278
tileset._backfaceCommands.push(derivedCommands.zback);
12781279
}
1279-
if (!defined(derivedCommands.stencil) || tile._selectionDepth !== tile._lastSelectionDepth) {
1280+
if (!defined(derivedCommands.stencil) || tile._selectionDepth !== getLastSelectionDepth(derivedCommands.stencil)) {
12801281
derivedCommands.stencil = deriveStencilCommand(derivedCommands.originalCommand, tile._selectionDepth);
1281-
tile._lastSelectionDepth = tile._selectionDepth;
12821282
}
12831283
updateDerivedCommand(derivedCommands.stencil, command);
12841284
}
@@ -1423,6 +1423,10 @@ define([
14231423
return derivedCommand;
14241424
}
14251425

1426+
function getLastSelectionDepth(stencilCommand) {
1427+
return stencilCommand.renderState.stencilTest.reference >>> 4;
1428+
}
1429+
14261430
function getTranslucentRenderState(renderState) {
14271431
var rs = clone(renderState, true);
14281432
rs.cull.enabled = false;

Source/Scene/Cesium3DTileChildrenVisibility.js

-19
This file was deleted.

Source/Scene/Cesium3DTileStyleEngine.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ define([
6565
var length = tiles.length;
6666
for (var i = 0; i < length; ++i) {
6767
var tile = tiles[i];
68-
if (tile.selected && (tile.lastStyleTime !== lastStyleTime)) {
68+
if (tile.lastStyleTime !== lastStyleTime) {
6969
// Apply the style to this tile if it wasn't already applied because:
7070
// 1) the user assigned a new style to the tileset
7171
// 2) this tile is now visible, but it wasn't visible when the style was first assigned

0 commit comments

Comments
 (0)