@@ -2,7 +2,7 @@ import { getUrlExtension } from '../utilities/urlExtension.js';
22import { LRUCache } from '../utilities/LRUCache.js' ;
33import { PriorityQueue } from '../utilities/PriorityQueue.js' ;
44import { markUsedTiles , toggleTiles , markVisibleTiles , markUsedSetLeaves } from './traverseFunctions.js' ;
5- import { UNLOADED , LOADING , PARSING , LOADED , FAILED } from '../constants.js' ;
5+ import { UNLOADED , QUEUED , LOADING , PARSING , LOADED , FAILED } from '../constants.js' ;
66import { throttle } from '../utilities/throttle.js' ;
77import { traverseSet } from '../utilities/TraversalUtils.js' ;
88
@@ -108,7 +108,7 @@ export class TilesRendererBase {
108108 get loadProgress ( ) {
109109
110110 const { stats, isLoading } = this ;
111- const loading = stats . downloading + stats . parsing ;
111+ const loading = stats . queued + stats . downloading + stats . parsing ;
112112 const total = stats . inCacheSinceLoad + ( isLoading ? 1 : 0 ) ;
113113 return total === 0 ? 1.0 : 1.0 - loading / total ;
114114
@@ -157,16 +157,20 @@ export class TilesRendererBase {
157157 this . visibleTiles = new Set ( ) ;
158158 this . activeTiles = new Set ( ) ;
159159 this . usedSet = new Set ( ) ;
160+ this . loadingTiles = new Set ( ) ;
160161 this . lruCache = lruCache ;
161162 this . downloadQueue = downloadQueue ;
162163 this . parseQueue = parseQueue ;
163164 this . processNodeQueue = processNodeQueue ;
164165 this . stats = {
165166 inCacheSinceLoad : 0 ,
166167 inCache : 0 ,
167- parsing : 0 ,
168+
169+ queued : 0 ,
168170 downloading : 0 ,
171+ parsing : 0 ,
169172 failed : 0 ,
173+
170174 inFrustum : 0 ,
171175 used : 0 ,
172176 active : 0 ,
@@ -404,6 +408,9 @@ export class TilesRendererBase {
404408 markVisibleTiles ( root , this ) ;
405409 toggleTiles ( root , this ) ;
406410
411+ // remove any tiles that are loading but no longer used
412+ this . removeUnusedPendingTiles ( ) ;
413+
407414 // TODO: This will only sort for one tileset. We may want to store this queue on the
408415 // LRUCache so multiple tilesets can use it at once
409416 // start the downloads of the tiles as needed
@@ -492,6 +499,7 @@ export class TilesRendererBase {
492499 }
493500
494501 this . stats = {
502+ queued : 0 ,
495503 parsing : 0 ,
496504 downloading : 0 ,
497505 failed : 0 ,
@@ -501,6 +509,7 @@ export class TilesRendererBase {
501509 visible : 0 ,
502510 } ;
503511 this . frameCount = 0 ;
512+ this . loadingTiles . clear ( ) ;
504513
505514 }
506515
@@ -667,6 +676,32 @@ export class TilesRendererBase {
667676
668677 }
669678
679+ removeUnusedPendingTiles ( ) {
680+
681+ const { lruCache, loadingTiles } = this ;
682+
683+ // cannot delete items while iterating over a set
684+ const toRemove = [ ] ;
685+ for ( const tile of loadingTiles ) {
686+
687+ // we only remove tiles that are QUEUED to avoid cancelling tiles that may already be nearly downloaded
688+ // as the camera moves
689+ if ( ! lruCache . isUsed ( tile ) && tile . __loadingState === QUEUED ) {
690+
691+ toRemove . push ( tile ) ;
692+
693+ }
694+
695+ }
696+
697+ for ( let i = 0 ; i < toRemove . length ; i ++ ) {
698+
699+ lruCache . remove ( toRemove [ i ] ) ;
700+
701+ }
702+
703+ }
704+
670705 // Private Functions
671706 queueTileForDownload ( tile ) {
672707
@@ -882,6 +917,7 @@ export class TilesRendererBase {
882917 const lruCache = this . lruCache ;
883918 const downloadQueue = this . downloadQueue ;
884919 const parseQueue = this . parseQueue ;
920+ const loadingTiles = this . loadingTiles ;
885921 const extension = getUrlExtension ( uri ) ;
886922
887923 // track an abort controller and pass-through the below conditions if aborted
@@ -917,7 +953,11 @@ export class TilesRendererBase {
917953
918954 }
919955
920- if ( t . __loadingState === LOADING ) {
956+ if ( t . __loadingState === QUEUED ) {
957+
958+ stats . queued -- ;
959+
960+ } else if ( t . __loadingState === LOADING ) {
921961
922962 stats . downloading -- ;
923963
@@ -931,6 +971,7 @@ export class TilesRendererBase {
931971
932972 parseQueue . remove ( t ) ;
933973 downloadQueue . remove ( t ) ;
974+ loadingTiles . delete ( t ) ;
934975
935976 } ) ;
936977
@@ -953,8 +994,9 @@ export class TilesRendererBase {
953994 this . cachedSinceLoadComplete . add ( tile ) ;
954995 stats . inCacheSinceLoad ++ ;
955996 stats . inCache ++ ;
956- stats . downloading ++ ;
957- tile . __loadingState = LOADING ;
997+ stats . queued ++ ;
998+ tile . __loadingState = QUEUED ;
999+ loadingTiles . add ( tile ) ;
9581000
9591001 // queue the download and parse
9601002 return downloadQueue . add ( tile , downloadTile => {
@@ -965,6 +1007,10 @@ export class TilesRendererBase {
9651007
9661008 }
9671009
1010+ tile . __loadingState = LOADING ;
1011+ stats . downloading ++ ;
1012+ stats . queued -- ;
1013+
9681014 const res = this . invokeOnePlugin ( plugin => plugin . fetchData && plugin . fetchData ( uri , { ...this . fetchOptions , signal } ) ) ;
9691015 this . dispatchEvent ( { type : 'tile-download-start' , tile, uri } ) ;
9701016 return res ;
@@ -1043,6 +1089,7 @@ export class TilesRendererBase {
10431089
10441090 stats . parsing -- ;
10451091 tile . __loadingState = LOADED ;
1092+ loadingTiles . delete ( tile ) ;
10461093 lruCache . setLoaded ( tile , true ) ;
10471094
10481095 // If the memory of the item hasn't been registered yet then that means the memory usage hasn't
@@ -1100,7 +1147,11 @@ export class TilesRendererBase {
11001147 parseQueue . remove ( tile ) ;
11011148 downloadQueue . remove ( tile ) ;
11021149
1103- if ( tile . __loadingState === PARSING ) {
1150+ if ( tile . __loadingState === QUEUED ) {
1151+
1152+ stats . queued -- ;
1153+
1154+ } else if ( tile . __loadingState === PARSING ) {
11041155
11051156 stats . parsing -- ;
11061157
@@ -1115,6 +1166,7 @@ export class TilesRendererBase {
11151166 console . error ( `TilesRenderer : Failed to load tile at url "${ tile . content . uri } ".` ) ;
11161167 console . error ( error ) ;
11171168 tile . __loadingState = FAILED ;
1169+ loadingTiles . delete ( tile ) ;
11181170 lruCache . setLoaded ( tile , true ) ;
11191171
11201172 this . dispatchEvent ( {
0 commit comments