From 0ee10943043c4d6f935f26ddf263f3d8b58b457f Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Thu, 6 Sep 2018 10:35:23 -0400 Subject: [PATCH 1/2] Select ancestor of empty tile that can't refine --- CHANGES.md | 6 ++++++ Source/Scene/Cesium3DTilesetTraversal.js | 26 ++++++++++++++++-------- Specs/Scene/Cesium3DTilesetSpec.js | 20 ++++++++++++++++++ 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index d1fb853b1431..f037ecf0f417 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,12 @@ Change Log ========== +### 1.50 - 2018-10-01 + +##### Fixes :wrench: + +* Fixed an issue in the 3D Tiles traversal where empty tiles would be selected instead of their nearest loaded ancestors. [#7011](https://github.com/AnalyticalGraphicsInc/cesium/pull/7011) + ### 1.49 - 2018-09-04 ##### Breaking Changes :mega: diff --git a/Source/Scene/Cesium3DTilesetTraversal.js b/Source/Scene/Cesium3DTilesetTraversal.js index ef5eaff01521..a8d3c7dab268 100644 --- a/Source/Scene/Cesium3DTilesetTraversal.js +++ b/Source/Scene/Cesium3DTilesetTraversal.js @@ -156,13 +156,15 @@ define([ var childrenLength = children.length; for (var i = 0; i < childrenLength; ++i) { var child = children[i]; - if (child.contentAvailable) { - updateTile(tileset, child, frameState); - touchTile(tileset, child, frameState); - selectTile(tileset, child, frameState); - } else if (child._depth - root._depth < descendantSelectionDepth) { - // Continue traversing, but not too far - stack.push(child); + if (isVisible(child)) { + if (child.contentAvailable) { + updateTile(tileset, child, frameState); + touchTile(tileset, child, frameState); + selectTile(tileset, child, frameState); + } else if (child._depth - root._depth < descendantSelectionDepth) { + // Continue traversing, but not too far + stack.push(child); + } } } } @@ -469,11 +471,17 @@ define([ refines = updateAndPushChildren(tileset, tile, stack, frameState) && parentRefines; } + var stoppedRefining = !refines && parentRefines; + if (hasEmptyContent(tile)) { // Add empty tile just to show its debug bounding volume // If the tile has tileset content load the external tileset + // If the tile cannot refine further select its nearest loaded ancestor addEmptyTile(tileset, tile, frameState); loadTile(tileset, tile, frameState); + if (stoppedRefining) { + selectDesiredTile(tileset, tile, frameState); + } } else if (add) { // Additive tiles are always loaded and selected selectDesiredTile(tileset, tile, frameState); @@ -483,13 +491,13 @@ define([ // Always load tiles in the base traversal // Select tiles that can't refine further loadTile(tileset, tile, frameState); - if (!refines && parentRefines) { + if (stoppedRefining) { selectDesiredTile(tileset, tile, frameState); } } else { // Load tiles that are not skipped or can't refine further. In practice roughly half the tiles stay unloaded. // Select tiles that can't refine further. If the tile doesn't have loaded content it will try to select an ancestor with loaded content instead. - if (!refines) { // eslint-disable-line + if (stoppedRefining) { // eslint-disable-line selectDesiredTile(tileset, tile, frameState); loadTile(tileset, tile, frameState); } else if (reachedSkippingThreshold(tileset, tile)) { diff --git a/Specs/Scene/Cesium3DTilesetSpec.js b/Specs/Scene/Cesium3DTilesetSpec.js index 4fde0ab601c6..204ae8911bc9 100644 --- a/Specs/Scene/Cesium3DTilesetSpec.js +++ b/Specs/Scene/Cesium3DTilesetSpec.js @@ -1070,6 +1070,26 @@ defineSuite([ }); }); + it('replacement refinement - selects upwards when traversal stops at empty tile', function() { + // No children have content, but all grandchildren have content + // + // C + // E E + // C C C C + // + return Cesium3DTilesTester.loadTileset(scene, tilesetReplacement1Url).then(function(tileset) { + tileset.root.geometricError = 90; + viewRootOnly(); + scene.camera.zoomIn(20); + scene.renderForSpecs(); + + var statistics = tileset._statistics; + expect(statistics.selected).toEqual(1); + expect(statistics.visited).toEqual(3); + expect(isSelected(tileset, tileset.root)).toBe(true); + }); + }); + it('replacement refinement - selects root when sse is not met and subtree is not refinable (1)', function() { // No children have content, but all grandchildren have content // From 24b40c6a8999bd76721a377f67dc95ab4217ad37 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Mon, 10 Sep 2018 11:18:55 -0400 Subject: [PATCH 2/2] Changed if else flow --- Source/Scene/Cesium3DTilesetTraversal.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/Source/Scene/Cesium3DTilesetTraversal.js b/Source/Scene/Cesium3DTilesetTraversal.js index a8d3c7dab268..d01be2a539de 100644 --- a/Source/Scene/Cesium3DTilesetTraversal.js +++ b/Source/Scene/Cesium3DTilesetTraversal.js @@ -494,15 +494,13 @@ define([ if (stoppedRefining) { selectDesiredTile(tileset, tile, frameState); } - } else { - // Load tiles that are not skipped or can't refine further. In practice roughly half the tiles stay unloaded. - // Select tiles that can't refine further. If the tile doesn't have loaded content it will try to select an ancestor with loaded content instead. - if (stoppedRefining) { // eslint-disable-line - selectDesiredTile(tileset, tile, frameState); - loadTile(tileset, tile, frameState); - } else if (reachedSkippingThreshold(tileset, tile)) { - loadTile(tileset, tile, frameState); - } + } else if (stoppedRefining) { + // In skip traversal, load and select tiles that can't refine further + selectDesiredTile(tileset, tile, frameState); + loadTile(tileset, tile, frameState); + } else if (reachedSkippingThreshold(tileset, tile)) { + // In skip traversal, load tiles that aren't skipped. In practice roughly half the tiles stay unloaded. + loadTile(tileset, tile, frameState); } }