From ba260b785f95405190707ce380446d8f108581df Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Sat, 17 Jan 2026 11:43:26 +0900 Subject: [PATCH 1/7] Add initial "coverage" calculation --- src/core/renderer/tiles/TilesRendererBase.js | 5 ++ .../tiles/optimizedTraverseFunctions.js | 46 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/src/core/renderer/tiles/TilesRendererBase.js b/src/core/renderer/tiles/TilesRendererBase.js index 37698d293..bc1d8b7a5 100644 --- a/src/core/renderer/tiles/TilesRendererBase.js +++ b/src/core/renderer/tiles/TilesRendererBase.js @@ -73,6 +73,11 @@ const optimizedPriorityCallback = ( a, b ) => { // load internal tile sets first return a.__hasUnrenderableContent ? 1 : - 1; + } else if ( a.__coverage !== b.__coverage ) { + + // load tiles with less coverage first + return a.__coverage < b.__coverage ? 1 : - 1; + } else if ( a.__distanceFromCamera !== b.__distanceFromCamera ) { // load closer tiles first diff --git a/src/core/renderer/tiles/optimizedTraverseFunctions.js b/src/core/renderer/tiles/optimizedTraverseFunctions.js index 8149efa6b..8da2e8f68 100644 --- a/src/core/renderer/tiles/optimizedTraverseFunctions.js +++ b/src/core/renderer/tiles/optimizedTraverseFunctions.js @@ -51,6 +51,8 @@ function resetFrameState( tile, renderer ) { tile.__allChildrenReady = false; tile.__kicked = false; tile.__allUsedChildrenProcessed = false; + tile.__coverage = 0.0; + tile.__visibleCoverage = 0.0; // update tile frustum and error state renderer.calculateTileViewError( tile, viewErrorTarget ); @@ -489,13 +491,57 @@ function toggleTiles( tile, renderer ) { tile.__usedLastFrame = isUsed; const children = tile.children; + let coverage = 0; + let coverageChildren = 0; + let visibleCoverageChildren = 0; + let visibleCoverage = 0; for ( let i = 0, l = children.length; i < l; i ++ ) { const c = children[ i ]; toggleTiles( c, renderer ); + coverage += c.__coverage || 0; + coverageChildren += c.__coverageChildren || 1; + + if ( c.__inFrustum ) { + + visibleCoverageChildren += c.__visibleCoverageChildren || 1; + visibleCoverage += c.__visibleCoverage || 0; + + } } + // TODO: it may be more simple to keep non-content tiles marked as "active" and fire "setVisible" and "setActive" + // so plugins etc can react to empty tile visibility if desired + if ( tile.__active && ! canUnconditionallyRefine( tile ) || tile.__refine === 'ADD' || tile.__isLeaf ) { + + if ( tile.__isLeaf && tile.__hasContent && ! isDownloadFinished( tile.__loadingState ) ) { + + tile.__coverage = 0; + tile.__visibleCoverage = 0; + + } else { + + tile.__coverage = 1.0; + tile.__visibleCoverage = tile.__inFrustum ? 1.0 : 0.0; + + } + + tile.__coverageChildren = 1; + tile.__visibleCoverageChildren = 1; + + } else { + + tile.__coverageChildren = coverageChildren; + tile.__visibleCoverageChildren = visibleCoverageChildren; + tile.__coverage = coverage; + tile.__visibleCoverage = visibleCoverage; + + } + + tile.__finalCoverage = tile.__coverage / tile.__coverageChildren || 0; + tile.__finalVisibleCoverage = tile.__visibleCoverage / tile.__visibleCoverageChildren || 0; + } } From 9db110087755370d3c1b98b5857087b38e3d5150 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Sun, 18 Jan 2026 16:57:45 +0900 Subject: [PATCH 2/7] Use per-tile coverage --- src/core/renderer/tiles/optimizedTraverseFunctions.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/core/renderer/tiles/optimizedTraverseFunctions.js b/src/core/renderer/tiles/optimizedTraverseFunctions.js index 8da2e8f68..37d140804 100644 --- a/src/core/renderer/tiles/optimizedTraverseFunctions.js +++ b/src/core/renderer/tiles/optimizedTraverseFunctions.js @@ -527,15 +527,10 @@ function toggleTiles( tile, renderer ) { } - tile.__coverageChildren = 1; - tile.__visibleCoverageChildren = 1; - } else { - tile.__coverageChildren = coverageChildren; - tile.__visibleCoverageChildren = visibleCoverageChildren; - tile.__coverage = coverage; - tile.__visibleCoverage = visibleCoverage; + tile.__coverage = coverage / coverageChildren; + tile.__visibleCoverage = visibleCoverage / visibleCoverageChildren; } From ef8a6f15a3547ff70f37b1cc5df280e0d7bf3caa Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Sun, 18 Jan 2026 17:43:46 +0900 Subject: [PATCH 3/7] Improve "unconditionally refine" logic --- src/core/renderer/tiles/optimizedTraverseFunctions.js | 2 +- src/core/renderer/tiles/traverseFunctions.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/renderer/tiles/optimizedTraverseFunctions.js b/src/core/renderer/tiles/optimizedTraverseFunctions.js index 37d140804..81c14905f 100644 --- a/src/core/renderer/tiles/optimizedTraverseFunctions.js +++ b/src/core/renderer/tiles/optimizedTraverseFunctions.js @@ -29,7 +29,7 @@ function areChildrenProcessed( tile ) { // Checks whether we can stop at this tile for rendering or not function canUnconditionallyRefine( tile ) { - return tile.__hasUnrenderableContent || ( tile.parent && tile.parent.geometricError < tile.geometricError ); + return tile.__hasUnrenderableContent || tile.geometricError > 1e90 || ( tile.parent && tile.parent.geometricError < tile.geometricError ); } diff --git a/src/core/renderer/tiles/traverseFunctions.js b/src/core/renderer/tiles/traverseFunctions.js index 0625a9414..cc1ef8e6b 100644 --- a/src/core/renderer/tiles/traverseFunctions.js +++ b/src/core/renderer/tiles/traverseFunctions.js @@ -33,7 +33,7 @@ function areChildrenProcessed( tile ) { function canUnconditionallyRefine( tile ) { - return tile.__hasUnrenderableContent || ( tile.parent && tile.parent.geometricError < tile.geometricError ); + return tile.__hasUnrenderableContent || tile.geometricError > 1e90 || ( tile.parent && tile.parent.geometricError < tile.geometricError ); } From 683beed3132c1c207af8bfff210da00154d9cbf7 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Sun, 18 Jan 2026 17:51:11 +0900 Subject: [PATCH 4/7] Improve coverage calculation logic --- .../tiles/optimizedTraverseFunctions.js | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/core/renderer/tiles/optimizedTraverseFunctions.js b/src/core/renderer/tiles/optimizedTraverseFunctions.js index 81c14905f..ba0fbd56e 100644 --- a/src/core/renderer/tiles/optimizedTraverseFunctions.js +++ b/src/core/renderer/tiles/optimizedTraverseFunctions.js @@ -513,12 +513,21 @@ function toggleTiles( tile, renderer ) { // TODO: it may be more simple to keep non-content tiles marked as "active" and fire "setVisible" and "setActive" // so plugins etc can react to empty tile visibility if desired - if ( tile.__active && ! canUnconditionallyRefine( tile ) || tile.__refine === 'ADD' || tile.__isLeaf ) { + if ( tile.__hasContent && ! canUnconditionallyRefine( tile ) || tile.__isLeaf ) { - if ( tile.__isLeaf && tile.__hasContent && ! isDownloadFinished( tile.__loadingState ) ) { + if ( tile.__hasContent && ! isDownloadFinished( tile.__loadingState ) ) { - tile.__coverage = 0; - tile.__visibleCoverage = 0; + if ( tile.__active ) { + + tile.__coverage = 0; + tile.__visibleCoverage = 0; + + } else { + + tile.__coverage = coverage / coverageChildren; + tile.__visibleCoverage = visibleCoverage / visibleCoverageChildren; + + } } else { @@ -527,6 +536,12 @@ function toggleTiles( tile, renderer ) { } + + } else if ( tile.__refine === 'ADD' ) { + + tile.__coverage = 1.0; + tile.__visibleCoverage = tile.__inFrustum ? 1.0 : 0.0; + } else { tile.__coverage = coverage / coverageChildren; @@ -534,9 +549,6 @@ function toggleTiles( tile, renderer ) { } - tile.__finalCoverage = tile.__coverage / tile.__coverageChildren || 0; - tile.__finalVisibleCoverage = tile.__visibleCoverage / tile.__visibleCoverageChildren || 0; - } } From 24b7a0cd914438e8143e244c5b7cadcbc9c95ab6 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Sun, 18 Jan 2026 18:10:15 +0900 Subject: [PATCH 5/7] Further priority improvements --- src/core/renderer/tiles/TilesRendererBase.js | 4 ++++ src/core/renderer/tiles/optimizedTraverseFunctions.js | 1 + 2 files changed, 5 insertions(+) diff --git a/src/core/renderer/tiles/TilesRendererBase.js b/src/core/renderer/tiles/TilesRendererBase.js index bc1d8b7a5..b0a8f87eb 100644 --- a/src/core/renderer/tiles/TilesRendererBase.js +++ b/src/core/renderer/tiles/TilesRendererBase.js @@ -63,6 +63,10 @@ const optimizedPriorityCallback = ( a, b ) => { // load tiles that have been used return a.__used ? 1 : - 1; + } else if ( a.__kicked !== b.__kicked ) { + + return a.__kicked ? 1 : - 1; + } else if ( a.__inFrustum !== b.__inFrustum ) { // load tiles that have are in the frustum diff --git a/src/core/renderer/tiles/optimizedTraverseFunctions.js b/src/core/renderer/tiles/optimizedTraverseFunctions.js index ba0fbd56e..fc29dadc7 100644 --- a/src/core/renderer/tiles/optimizedTraverseFunctions.js +++ b/src/core/renderer/tiles/optimizedTraverseFunctions.js @@ -419,6 +419,7 @@ function toggleTiles( tile, renderer ) { if ( tile.__loadingState !== LOADED ) { tile.__active = false; + tile.__kicked = true; } From f0e80e5be0784bf26faa4202456411acb7909071 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Mon, 19 Jan 2026 14:40:26 +0900 Subject: [PATCH 6/7] Adjust load priority --- src/core/renderer/tiles/TilesRendererBase.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/core/renderer/tiles/TilesRendererBase.js b/src/core/renderer/tiles/TilesRendererBase.js index 8f32f2a54..3195c0364 100644 --- a/src/core/renderer/tiles/TilesRendererBase.js +++ b/src/core/renderer/tiles/TilesRendererBase.js @@ -71,10 +71,6 @@ const optimizedPriorityCallback = ( a, b ) => { // load tiles that have been used return a.traversal.used ? 1 : - 1; - } else if ( a.traversal.kicked !== b.traversal.kicked ) { - - return a.traversal.kicked ? 1 : - 1; - } else if ( a.traversal.inFrustum !== b.traversal.inFrustum ) { // load tiles that have are in the frustum @@ -85,6 +81,11 @@ const optimizedPriorityCallback = ( a, b ) => { // load internal tile sets first return a.internal.hasUnrenderableContent ? 1 : - 1; + } else if ( a.traversal.kicked !== b.traversal.kicked ) { + + // kicked means that a tile should be visible but isn't ready yet + return a.traversal.kicked ? 1 : - 1; + } else if ( a.traversal.coverage !== b.traversal.coverage ) { // load tiles with less coverage first From 35dbae7bdcde3332fb229e078cea8512ca8ae238 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Mon, 19 Jan 2026 15:12:26 +0900 Subject: [PATCH 7/7] Improve the coverage calculation --- .../renderer/tiles/optimizedTraverseFunctions.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/core/renderer/tiles/optimizedTraverseFunctions.js b/src/core/renderer/tiles/optimizedTraverseFunctions.js index a0b0a3495..ebad4ff8b 100644 --- a/src/core/renderer/tiles/optimizedTraverseFunctions.js +++ b/src/core/renderer/tiles/optimizedTraverseFunctions.js @@ -506,13 +506,13 @@ function toggleTiles( tile, renderer ) { const c = children[ i ]; toggleTiles( c, renderer ); - coverage += c.traversal.coverage || 0; - coverageChildren += c.traversal.coverageChildren || 1; + coverage += c.traversal?.coverage || 0; + coverageChildren ++; - if ( c.traversal.inFrustum ) { + if ( c.traversal?.inFrustum ) { - visibleCoverageChildren += c.traversal.visibleCoverageChildren || 1; - visibleCoverage += c.traversal.visibleCoverage || 0; + visibleCoverageChildren ++; + visibleCoverage += c.traversal?.visibleCoverage || 0; } @@ -551,8 +551,8 @@ function toggleTiles( tile, renderer ) { } else { - tile.traversal.coverage = coverage / coverageChildren; - tile.traversal.visibleCoverage = visibleCoverage / visibleCoverageChildren; + tile.traversal.coverage = coverage / coverageChildren || 0; + tile.traversal.visibleCoverage = visibleCoverage / visibleCoverageChildren || 0; }