Bläddra i källkod

Merge pull request #87 from NASA-AMMOS/small-fixes

Small fixes
Garrett Johnson 5 år sedan
förälder
incheckning
e482e71cec

+ 10 - 0
CHANGELOG.md

@@ -9,6 +9,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
 
 - Basic support for CMPT, PNTS, and I3DM file formats.
 - `autoDisableRendererCulling` field to `TilesRenderer`.
+- A count of the amount of failed tile content loads to `TilesRenderer.stats`.
+
+### Fixed
+
+- Failed tileset downloads being indefinitely retried.
+- Tile content stats not being correctly updated if a tile failed to load.
+- Not propagating image load errors.
+- DebugTilesRenderer using a different color for every submesh in a tile. Now a single color is used for every submesh in a tile.
+- Tiles not rendering if an empty tile is encountered.
+- Child tiles not rendering if a parent tile content failed to load.
 
 ## [0.1.2] - 2020-06-08
 ### Changed

+ 24 - 0
TESTCASES.md

@@ -200,3 +200,27 @@ Verify the boxes change with the level of detail of the terrain.
 #### expected
 
 Verify the display does not change and the tiles to not disappear while parent tiles load.
+
+## Verify the renderer does not repeatedly try to download a failed tileset.json
+
+#### steps
+
+1. Open the kitchen sink example.
+1. Set the location hash to `#./non/existing/tileset.json` to load a different tileset.
+
+#### expected
+
+Verify that an error is logged stating that the tileset could not be found just once.
+
+## Verify that failing to load a parent tile does not prevent child tiles from loading
+
+#### steps
+
+1. Temporarily rename the root b3dm file the provided example tileset.
+1. Open the kitchen sink example.
+1. Set the error threshold as high as it goes.
+1. Click rebuild.
+
+#### expected
+
+Verify an error is logged stating that the root tile content could not be loaded, that the stats state that is 1 tile that failed, that "downloads" and "parsing" eventually settle to 0, and that child tiles continue to render.

+ 30 - 7
src/base/TilesRendererBase.js

@@ -55,6 +55,7 @@ export class TilesRendererBase {
 		this.stats = {
 			parsing: 0,
 			downloading: 0,
+			failed: 0,
 			inFrustum: 0,
 			used: 0,
 			active: 0,
@@ -235,7 +236,7 @@ export class TilesRendererBase {
 
 						} else {
 
-							throw new Error( `Status ${ res.status } (${ res.statusText })` );
+							throw new Error( `TilesRenderer: Failed to load tileset "${ url }" with status ${ res.status } : ${ res.statusText }` );
 
 						}
 
@@ -253,19 +254,26 @@ export class TilesRendererBase {
 
 					} );
 
-			pr.catch( e => {
+			pr.catch( err => {
 
-				console.error( `TilesLoader: Failed to load tile set json "${ url }"` );
-				console.error( e );
-				delete tileSets[ url ];
+				console.error( err );
+				tileSets[ url ] = err;
 
 			} );
 
 			tileSets[ url ] = pr;
 
-		}
+			return pr;
+
+		} else if ( tileSets[ url ] instanceof Error ) {
+
+			return Promise.reject( tileSets[ url ] );
+
+		} else {
+
+			return Promise.resolve( tileSets[ url ] );
 
-		return Promise.resolve( tileSets[ url ] );
+		}
 
 	}
 
@@ -426,6 +434,21 @@ export class TilesRendererBase {
 
 				if ( e.name !== 'AbortError' ) {
 
+					parseQueue.remove( tile );
+					downloadQueue.remove( tile );
+
+					if ( tile.__loadingState === PARSING ) {
+
+						stats.parsing --;
+
+					} else if ( tile.__loadingState === LOADING ) {
+
+						stats.downloading --;
+
+					}
+
+					stats.failed ++;
+
 					console.error( 'TilesRenderer : Failed to load tile.' );
 					console.error( e );
 					tile.__loadingState = FAILED;

+ 12 - 4
src/base/traverseFunctions.js

@@ -1,4 +1,10 @@
-import { LOADED } from './constants.js';
+import { LOADED, FAILED } from './constants.js';
+
+function isDownloadFinished( value ) {
+
+	return value === LOADED || value === FAILED;
+
+}
 
 // Checks whether this tile was last used on the given frame.
 function isUsedThisFrame( tile, frameCount ) {
@@ -195,7 +201,7 @@ export function markUsedSetLeaves( tile, renderer ) {
 
 			if ( isUsedThisFrame( c, frameCount ) ) {
 
-				const childLoaded = ( ! c.__contentEmpty && c.__loadingState === LOADED ) || c.__allChildrenLoaded;
+				const childLoaded = ( ! c.__contentEmpty && isDownloadFinished( c.__loadingState ) ) || c.__allChildrenLoaded;
 				allChildrenLoaded = allChildrenLoaded && childLoaded;
 
 			}
@@ -253,7 +259,7 @@ export function skipTraversal( tile, renderer ) {
 	const errorRequirement = ( renderer.errorTarget + 1 ) * renderer.errorThreshold;
 	const meetsSSE = tile.__error <= errorRequirement;
 	const hasContent = ! tile.__contentEmpty;
-	const loadedContent = tile.__loadingState === LOADED && ! tile.__contentEmpty;
+	const loadedContent = isDownloadFinished( tile.__loadingState ) && ! tile.__contentEmpty;
 	const childrenWereVisible = tile.__childrenWereVisible;
 	const children = tile.children;
 	let allChildrenHaveContent = tile.__allChildrenLoaded;
@@ -277,7 +283,9 @@ export function skipTraversal( tile, renderer ) {
 	// all children have loaded yet, and if no children were visible last frame. We want to keep children visible
 	// that _were_ visible to avoid a pop in level of detail as the camera moves around and parent / sibling tiles
 	// load in.
-	if ( meetsSSE && ! allChildrenHaveContent && ! childrenWereVisible ) {
+
+	// Skip the tile entirely if there's no content to load
+	if ( meetsSSE && ! allChildrenHaveContent && ! childrenWereVisible && hasContent ) {
 
 		if ( loadedContent ) {
 

+ 18 - 4
src/three/DebugTilesRenderer.js

@@ -68,7 +68,13 @@ export class DebugTilesRenderer extends TilesRenderer {
 	loadTileSet( ...args ) {
 
 		const pr = super.loadTileSet( ...args );
-		pr.then( () => this.initExtremes() );
+		pr
+			.then( () => this.initExtremes() )
+			.catch( () => {
+
+				// error is logged internally
+
+			} );
 
 		return pr;
 
@@ -179,6 +185,17 @@ export class DebugTilesRenderer extends TilesRenderer {
 		visibleTiles.forEach( tile => {
 
 			const scene = tile.cached.scene;
+
+			// create a random color per-tile
+			let h, s, l;
+			if ( colorMode === RANDOM_COLOR ) {
+
+				h = Math.random();
+				s = 0.5 + Math.random() * 0.5;
+				l = 0.375 + Math.random() * 0.25;
+
+			}
+
 			scene.traverse( c => {
 
 				const currMaterial = c.material;
@@ -280,9 +297,6 @@ export class DebugTilesRenderer extends TilesRenderer {
 
 							if ( ! c.material[ HAS_RANDOM_COLOR ] ) {
 
-								const h = Math.random();
-								const s = 0.5 + Math.random() * 0.5;
-								const l = 0.375 + Math.random() * 0.25;
 								c.material.color.setHSL( h, s, l );
 								c.material[ HAS_RANDOM_COLOR ] = true;
 

+ 2 - 2
src/three/TilesRenderer.js

@@ -456,14 +456,14 @@ export class TilesRenderer extends TilesRendererBase {
 			// behavior. Fall back to regular texture loading
 			manager.addHandler( /(^blob:)|(\.png$)|(\.jpg$)|(\.jpeg$)/g, {
 
-				load( url, onComplete ) {
+				load( url, onComplete, onProgress, onError ) {
 
 					const loader = new ImageBitmapLoader();
 					loader.load( url, res => {
 
 						onComplete( new CanvasTexture( res ) );
 
-					} );
+					}, onProgress, onError);
 
 				}