Skip to content

Commit f7dfb5a

Browse files
authored
Dynamic overlay fixes (#1402)
* Remove lingering data * Fix incorrect level reference * Fix priority queue * Add more specific tile deletion * Handle errors more gracefully
1 parent 3579456 commit f7dfb5a

4 files changed

Lines changed: 80 additions & 21 deletions

File tree

src/core/renderer/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ export * from './loaders/CMPTLoaderBase.js';
88
export * from './constants.js';
99

1010
export { LRUCache } from './utilities/LRUCache.js';
11-
export { PriorityQueue } from './utilities/PriorityQueue.js';
11+
export * from './utilities/PriorityQueue.js';
1212
export * as TraversalUtils from './utilities/TraversalUtils.js';
1313
export * as LoaderUtils from './utilities/LoaderUtils.js';

src/core/renderer/utilities/PriorityQueue.js

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,15 @@
1-
class PriorityQueue {
1+
export class PriorityQueueItemRemovedError extends Error {
2+
3+
constructor() {
4+
5+
super( 'PriorityQueue: Item removed' );
6+
this.name = 'PriorityQueueItemRemovedError';
7+
8+
}
9+
10+
}
11+
12+
export class PriorityQueue {
213

314
// returns whether tasks are queued or actively running
415
get running() {
@@ -98,8 +109,16 @@ class PriorityQueue {
98109
// catch here to handle the case where the promise was never used anywhere
99110
// else.
100111
const info = callbacks.get( item );
101-
info.promise.catch( () => {} );
102-
info.reject( new Error( 'PriorityQueue: Item removed.' ) );
112+
info.promise.catch( err => {
113+
114+
if ( ! ( err instanceof PriorityQueueItemRemovedError ) ) {
115+
116+
throw err;
117+
118+
}
119+
120+
} );
121+
info.reject( new PriorityQueueItemRemovedError() );
103122

104123
items.splice( index, 1 );
105124
callbacks.delete( item );
@@ -117,6 +136,7 @@ class PriorityQueue {
117136
if ( filter( item ) ) {
118137

119138
this.remove( item );
139+
i --;
120140

121141
}
122142

@@ -196,5 +216,3 @@ class PriorityQueue {
196216
}
197217

198218
}
199-
200-
export { PriorityQueue };

src/three/plugins/images/ImageOverlayPlugin.js

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { WebGLRenderTarget, Color, SRGBColorSpace, BufferAttribute, Matrix4, Vector3, Box3, Triangle, CanvasTexture } from 'three';
2-
import { PriorityQueue } from '3d-tiles-renderer/core';
2+
import { PriorityQueue, PriorityQueueItemRemovedError } from '3d-tiles-renderer/core';
33
import { CesiumIonAuth, GoogleCloudAuth } from '3d-tiles-renderer/core/plugins';
44
import { TiledTextureComposer } from './overlays/TiledTextureComposer.js';
55
import { XYZImageSource } from './sources/XYZImageSource.js';
@@ -168,6 +168,12 @@ export class ImageOverlayPlugin {
168168
// plugin functions
169169
init( tiles ) {
170170

171+
if ( ! this.renderer ) {
172+
173+
throw new Error( 'ImageOverlayPlugin: "renderer" instance must be provided.' );
174+
175+
}
176+
171177
const tileComposer = new TiledTextureComposer( this.renderer );
172178
const processQueue = new PriorityQueue();
173179
processQueue.maxJobs = 10;
@@ -219,7 +225,7 @@ export class ImageOverlayPlugin {
219225
) {
220226

221227
const order = info.order;
222-
this.deleteOverlay( overlay, false );
228+
this.deleteOverlay( overlay );
223229
this.addOverlay( overlay, order );
224230

225231
overlayChanged = true;
@@ -879,21 +885,37 @@ export class ImageOverlayPlugin {
879885

880886
}
881887

882-
deleteOverlay( overlay, forceDispose = true ) {
888+
deleteOverlay( overlay ) {
883889

884890
const { overlays, overlayInfo, processQueue } = this;
885891
const index = overlays.indexOf( overlay );
886892
if ( index !== - 1 ) {
887893

894+
// delete tile info explicitly instead of blindly dispose of the full overlay
888895
const { tileInfo, controller } = overlayInfo.get( overlay );
889-
tileInfo.forEach( ( { meshInfo, target } ) => {
896+
tileInfo.forEach( ( { meshInfo, range, meshRange, level, target, meshRangeMarked, rangeMarked }, tile ) => {
897+
898+
// release the ranges
899+
if ( meshRange !== null && meshRangeMarked ) {
900+
901+
markOverlayImages( meshRange, level, overlay, true );
902+
903+
}
904+
905+
if ( range !== null && rangeMarked ) {
906+
907+
markOverlayImages( range, level, overlay, true );
908+
909+
}
890910

891911
if ( target !== null ) {
892912

913+
// release the render targets
893914
target.dispose();
894915

895916
}
896917

918+
tileInfo.delete( tile );
897919
meshInfo.clear();
898920

899921
} );
@@ -910,11 +932,6 @@ export class ImageOverlayPlugin {
910932
} );
911933

912934
overlays.splice( index, 1 );
913-
if ( forceDispose ) {
914-
915-
overlay.dispose();
916-
917-
}
918935

919936
this._markNeedsUpdate();
920937

@@ -1051,7 +1068,6 @@ export class ImageOverlayPlugin {
10511068

10521069
}
10531070

1054-
const level = tile.__depthFromRenderedParent - 1;
10551071
const info = {
10561072
range: null,
10571073
meshRange: null,
@@ -1086,12 +1102,16 @@ export class ImageOverlayPlugin {
10861102
.add( { tile, overlay }, () => {
10871103

10881104
info.rangeMarked = true;
1089-
return markOverlayImages( range, level, overlay, false );
1105+
return markOverlayImages( range, info.level, overlay, false );
10901106

10911107
} )
1092-
.catch( () => {
1108+
.catch( err => {
1109+
1110+
if ( ! ( err instanceof PriorityQueueItemRemovedError ) ) {
10931111

1094-
// the queue throws an error if a task is removed early
1112+
throw err;
1113+
1114+
}
10951115

10961116
} );
10971117

@@ -1284,9 +1304,13 @@ export class ImageOverlayPlugin {
12841304
} );
12851305

12861306
} )
1287-
.catch( () => {
1307+
.catch( err => {
12881308

1289-
// the queue throws an error if a task is removed early
1309+
if ( ! ( err instanceof PriorityQueueItemRemovedError ) ) {
1310+
1311+
throw err;
1312+
1313+
}
12901314

12911315
} );
12921316

test/core/PriorityQueue.test.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,4 +259,21 @@ describe( 'PriorityQueue', () => {
259259

260260
} );
261261

262+
it( 'should be able to successfully remove all items by filter.', async () => {
263+
264+
const queue = new PriorityQueue();
265+
queue.priorityCallback = () => 0;
266+
queue.autoUpdate = false;
267+
queue.maxJobs = 1;
268+
269+
queue.add( 1, () => {} );
270+
queue.add( 2, () => {} );
271+
queue.add( 3, () => {} );
272+
273+
expect( queue.items ).toHaveLength( 3 );
274+
queue.removeByFilter( i => true );
275+
expect( queue.items ).toHaveLength( 0 );
276+
277+
} );
278+
262279
} );

0 commit comments

Comments
 (0)