Skip to content

Commit

Permalink
Merge pull request #6390 from AnalyticalGraphicsInc/traversal-cleanup
Browse files Browse the repository at this point in the history
3D Tiles Traversal cleanup
  • Loading branch information
ggetz authored Aug 16, 2018
2 parents 8ff642f + b527503 commit 939e4c3
Show file tree
Hide file tree
Showing 18 changed files with 793 additions and 923 deletions.
6 changes: 6 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ Change Log
* Added optional `width` and `height` to `Scene.drillPick` for specifying a search area.

##### Fixes :wrench:
* Several performance improvements and fixes to the 3D Tiles traversal code. [#6390](https://github.com/AnalyticalGraphicsInc/cesium/pull/6390)
* Improved load performance when `skipLevelOfDetail` is false.
* Fixed a bug that caused some skipped tiles to load when `skipLevelOfDetail` is true.
* Fixed pick statistics in the 3D Tiles Inspector.
* Fixed drawing of debug labels for external tilesets.
* Fixed drawing of debug outlines for empty tiles.
* The Geocoder widget now takes terrain altitude into account when calculating its final destination.
* The Viewer widget now takes terrain altitude into account when zooming or flying to imagery layers.
* Fixed `getPickRay` in 2D. [#2480](https://github.com/AnalyticalGraphicsInc/cesium/issues/2480)
Expand Down
17 changes: 14 additions & 3 deletions Source/Core/ManagedArray.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,21 +74,32 @@ define([
* Sets the element at an index. Resizes the array if index is greater than the length of the array.
*
* @param {Number} index The index to set.
* @param {*} value The value to set at index.
* @param {*} element The element to set at index.
*/
ManagedArray.prototype.set = function(index, value) {
ManagedArray.prototype.set = function(index, element) {
//>>includeStart('debug', pragmas.debug);
Check.typeOf.number('index', index);
//>>includeEnd('debug');

if (index >= this.length) {
this.length = index + 1;
}
this._array[index] = value;
this._array[index] = element;
};

/**
* Returns the last element in the array without modifying the array.
*
* @returns {*} The last element in the array.
*/
ManagedArray.prototype.peek = function() {
return this._array[this._length - 1];
};

/**
* Push an element into the array.
*
* @param {*} element The element to push.
*/
ManagedArray.prototype.push = function(element) {
var index = this.length++;
Expand Down
3 changes: 1 addition & 2 deletions Source/Scene/Batched3DModel3DTileContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -482,8 +482,7 @@ define([
// If any commands were pushed, add derived commands
var commandEnd = frameState.commandList.length;
if ((commandStart < commandEnd) && (frameState.passes.render || frameState.passes.pick) && !defined(tileset.classificationType)) {
var finalResolution = this._tile._finalResolution;
this._batchTable.addDerivedCommands(frameState, commandStart, finalResolution);
this._batchTable.addDerivedCommands(frameState, commandStart);
}
};

Expand Down
103 changes: 56 additions & 47 deletions Source/Scene/Cesium3DTile.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ define([
'../Core/BoundingSphere',
'../Core/Cartesian3',
'../Core/Color',
'../Core/ColorGeometryInstanceAttribute',
'../Core/CullingVolume',
'../Core/defaultValue',
'../Core/defined',
Expand All @@ -24,7 +25,6 @@ define([
'../Core/Resource',
'../Core/RuntimeError',
'../ThirdParty/when',
'./Cesium3DTileChildrenVisibility',
'./Cesium3DTileContentFactory',
'./Cesium3DTileContentState',
'./Cesium3DTileOptimizationHint',
Expand All @@ -38,6 +38,7 @@ define([
BoundingSphere,
Cartesian3,
Color,
ColorGeometryInstanceAttribute,
CullingVolume,
defaultValue,
defined,
Expand All @@ -60,7 +61,6 @@ define([
Resource,
RuntimeError,
when,
Cesium3DTileChildrenVisibility,
Cesium3DTileContentFactory,
Cesium3DTileContentState,
Cesium3DTileOptimizationHint,
Expand Down Expand Up @@ -235,19 +235,6 @@ define([
*/
this.hasEmptyContent = hasEmptyContent;

/**
* When <code>true</code>, the tile's content is renderable.
* <p>
* This is <code>false</code> until the tile's content is loaded.
* </p>
*
* @type {Boolean}
* @readonly
*
* @private
*/
this.hasRenderableContent = false;

/**
* When <code>true</code>, the tile's content points to an external tileset.
* <p>
Expand All @@ -262,14 +249,16 @@ define([
this.hasTilesetContent = false;

/**
* The corresponding node in the cache replacement list.
* The node in the tileset's LRU cache, used to determine when to unload a tile's content.
*
* See {@link Cesium3DTilesetCache}
*
* @type {DoublyLinkedListNode}
* @readonly
*
* @private
*/
this.replacementNode = undefined;
this.cacheNode = undefined;

var expire = header.expire;
var expireDuration;
Expand All @@ -295,15 +284,6 @@ define([
*/
this.expireDate = expireDate;

/**
* Marks if the tile is selected this frame.
*
* @type {Boolean}
*
* @private
*/
this.selected = false;

/**
* The time when a style was last applied to this tile.
*
Expand Down Expand Up @@ -334,22 +314,27 @@ define([

// Members that are updated every frame for tree traversal and rendering optimizations:
this._distanceToCamera = 0;
this._visibilityPlaneMask = 0;
this._childrenVisibility = Cesium3DTileChildrenVisibility.VISIBLE;
this._lastSelectedFrameNumber = -1;
this._centerZDepth = 0;
this._screenSpaceError = 0;
this._screenSpaceErrorComputedFrame = -1;
this._visibilityPlaneMask = 0;
this._visible = false;
this._inRequestVolume = false;

this._finalResolution = true;
this._depth = 0;
this._centerZDepth = 0;
this._stackLength = 0;
this._selectedFrame = -1;
this._selectionDepth = 0;
this._lastSelectionDepth = undefined;
this._requestedFrame = undefined;
this._lastVisitedFrame = undefined;

this._updatedVisibilityFrame = 0;
this._touchedFrame = 0;
this._visitedFrame = 0;
this._selectedFrame = 0;
this._requestedFrame = 0;
this._ancestorWithContent = undefined;
this._ancestorWithLoadedContent = undefined;
this._ancestorWithContentAvailable = undefined;
this._refines = false;
this._shouldSelect = false;
this._priority = 0.0;
this._isClipped = true;
this._clippingPlanesState = 0; // encapsulates (_isClipped, clippingPlanes.enabled) and number/function

Expand Down Expand Up @@ -467,13 +452,13 @@ define([
*/
contentAvailable : {
get : function() {
return this.contentReady || (defined(this._expiredContent) && this._contentState !== Cesium3DTileContentState.FAILED);
return (this.contentReady && !this.hasEmptyContent && !this.hasTilesetContent) || (defined(this._expiredContent) && !this.contentFailed);
}
},

/**
* Determines if the tile is ready to render. <code>true</code> if the tile
* is ready to render; otherwise, <code>false</code>.
* Determines if the tile's content is ready. This is automatically <code>true</code> for
* tile's with empty content.
*
* @memberof Cesium3DTile.prototype
*
Expand Down Expand Up @@ -522,6 +507,23 @@ define([
}
},

/**
* Determines if the tile's content failed to load. <code>true</code> if the tile's
* content failed to load; otherwise, <code>false</code>.
*
* @memberof Cesium3DTile.prototype
*
* @type {Boolean}
* @readonly
*
* @private
*/
contentFailed : {
get : function() {
return this._contentState === Cesium3DTileContentState.FAILED;
}
},

/**
* 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
Expand Down Expand Up @@ -618,7 +620,7 @@ define([

function createPriorityFunction(tile) {
return function() {
return tile._distanceToCamera;
return tile._priority;
};
}

Expand Down Expand Up @@ -690,7 +692,6 @@ define([

if (defined(contentFactory)) {
content = contentFactory(tileset, that, that._contentResource, arrayBuffer, 0);
that.hasRenderableContent = true;
} else {
// The content may be json instead
content = Cesium3DTileContentFactory.json(tileset, that, that._contentResource, arrayBuffer, 0);
Expand All @@ -710,7 +711,7 @@ define([
updateExpireDate(that);

// Refresh style for expired content
that.lastStyleTime = 0;
that._selectedFrame = 0;

that._contentState = Cesium3DTileContentState.READY;
that._contentReadyPromise.resolve(content);
Expand All @@ -735,7 +736,7 @@ define([
* @private
*/
Cesium3DTile.prototype.unloadContent = function() {
if (!this.hasRenderableContent) {
if (this.hasEmptyContent || this.hasTilesetContent) {
return;
}

Expand All @@ -744,8 +745,6 @@ define([
this._contentReadyToProcessPromise = undefined;
this._contentReadyPromise = undefined;

this.replacementNode = undefined;

this.lastStyleTime = 0;
this.clippingPlanesDirty = (this._clippingPlanesState === 0);
this._clippingPlanesState = 0;
Expand Down Expand Up @@ -859,7 +858,7 @@ define([
* Computes the distance from the center of the tile's bounding volume to the camera.
*
* @param {FrameState} frameState The frame state.
* @returns {Number} The distance, in meters, or zero if the camera is inside the bounding volume.
* @returns {Number} The distance, in meters.
*
* @private
*/
Expand Down Expand Up @@ -1032,14 +1031,24 @@ define([

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

var showVolume = tileset.debugShowBoundingVolume || (tileset.debugShowContentBoundingVolume && !hasContentBoundingVolume);
if (showVolume) {
var color;
if (!tile._finalResolution) {
color = Color.YELLOW;
} else if (empty) {
color = Color.DARKGRAY;
} else {
color = Color.WHITE;
}
if (!defined(tile._debugBoundingVolume)) {
var color = tile._finalResolution ? (hasContentBoundingVolume ? Color.WHITE : Color.RED) : Color.YELLOW;
tile._debugBoundingVolume = tile._boundingVolume.createDebugVolume(color);
}
tile._debugBoundingVolume.update(frameState);
var attributes = tile._debugBoundingVolume.getGeometryInstanceAttributes('outline');
attributes.color = ColorGeometryInstanceAttribute.toValue(color, attributes.color);
} else if (!showVolume && defined(tile._debugBoundingVolume)) {
tile._debugBoundingVolume = tile._debugBoundingVolume.destroy();
}
Expand Down
10 changes: 7 additions & 3 deletions Source/Scene/Cesium3DTileBatchTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -1241,10 +1241,11 @@ define([
OPAQUE_AND_TRANSLUCENT : 2
};

Cesium3DTileBatchTable.prototype.addDerivedCommands = function(frameState, commandStart, finalResolution) {
Cesium3DTileBatchTable.prototype.addDerivedCommands = function(frameState, commandStart) {
var commandList = frameState.commandList;
var commandEnd = commandList.length;
var tile = this._content._tile;
var finalResolution = tile._finalResolution;
var tileset = tile._tileset;
var bivariateVisibilityTest = tileset._skipLevelOfDetail && tileset._hasMixedContent && frameState.context.stencilBuffer;
var styleCommandsNeeded = getStyleCommandsNeeded(this);
Expand Down Expand Up @@ -1276,9 +1277,8 @@ define([
}
tileset._backfaceCommands.push(derivedCommands.zback);
}
if (!defined(derivedCommands.stencil) || tile._selectionDepth !== tile._lastSelectionDepth) {
if (!defined(derivedCommands.stencil) || tile._selectionDepth !== getLastSelectionDepth(derivedCommands.stencil)) {
derivedCommands.stencil = deriveStencilCommand(derivedCommands.originalCommand, tile._selectionDepth);
tile._lastSelectionDepth = tile._selectionDepth;
}
updateDerivedCommand(derivedCommands.stencil, command);
}
Expand Down Expand Up @@ -1423,6 +1423,10 @@ define([
return derivedCommand;
}

function getLastSelectionDepth(stencilCommand) {
return stencilCommand.renderState.stencilTest.reference >>> 4;
}

function getTranslucentRenderState(renderState) {
var rs = clone(renderState, true);
rs.cull.enabled = false;
Expand Down
19 changes: 0 additions & 19 deletions Source/Scene/Cesium3DTileChildrenVisibility.js

This file was deleted.

2 changes: 1 addition & 1 deletion Source/Scene/Cesium3DTileStyleEngine.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ define([
var length = tiles.length;
for (var i = 0; i < length; ++i) {
var tile = tiles[i];
if (tile.selected && (tile.lastStyleTime !== lastStyleTime)) {
if (tile.lastStyleTime !== lastStyleTime) {
// Apply the style to this tile if it wasn't already applied because:
// 1) the user assigned a new style to the tileset
// 2) this tile is now visible, but it wasn't visible when the style was first assigned
Expand Down
Loading

0 comments on commit 939e4c3

Please sign in to comment.