Repository: NASA-AMMOS/3DTilesRendererJS
Pull request #53 (2020-04-30 21:41:59)

Misc updates
Originally intended to address #51 but that turned out to be more complicated than expected. Instead this adds:

- Relative depth debug display
- Toggle for priority queue autoupdate
- Traverse to check recursively past empty children when checking if all children are loaded 


Patch:
diff --git a/README.md b/README.md
index 1926ce4..aeba79d 100644
--- a/README.md
+++ b/README.md
@@ -12,9 +12,9 @@ The renderer supports a limited subset of the spec for the moment. See [Issue #1
 See it in action [here](https://nasa-ammos.github.io/3DTilesRendererJS/example/bundle/)!
 
 **In Progress Features**
+- Multicamera support
+- Travis integration
 - Performance
-- Bug Triage
-- Tileset / Browser validation
 
 # Use
 
diff --git a/example/index.js b/example/index.js
index 1914848..ad80761 100644
--- a/example/index.js
+++ b/example/index.js
@@ -213,8 +213,9 @@ function init() {
 		GEOMETRIC_ERROR: 2,
 		DISTANCE: 3,
 		DEPTH: 4,
-		IS_LEAF: 5,
-		RANDOM_COLOR: 6,
+		RELATIVE_DEPTH: 5,
+		IS_LEAF: 6,
+		RANDOM_COLOR: 7,
 
 	} );
 	debug.open();
@@ -224,7 +225,19 @@ function init() {
 	exampleOptions.add( params, 'orthographic' );
 	exampleOptions.add( params, 'showThirdPerson' );
 	exampleOptions.add( params, 'showSecondView' ).onChange( onWindowResize );
-	exampleOptions.add( params, 'enableUpdate' );
+	exampleOptions.add( params, 'enableUpdate' ).onChange( v => {
+
+		tiles.parseQueue.autoUpdate = v;
+		tiles.downloadQueue.autoUpdate = v;
+
+		if ( v ) {
+
+			tiles.parseQueue.scheduleJobRun();
+			tiles.downloadQueue.scheduleJobRun();
+
+		}
+
+	} );
 	exampleOptions.add( params, 'enableRaycast' );
 	exampleOptions.add( params, 'enableCacheDisplay' );
 	exampleOptions.open();
diff --git a/src/base/TilesRendererBase.js b/src/base/TilesRendererBase.js
index bdda68b..0495e29 100644
--- a/src/base/TilesRendererBase.js
+++ b/src/base/TilesRendererBase.js
@@ -182,6 +182,7 @@ export class TilesRendererBase {
 		tile.__wasSetVisible = false;
 		tile.__visible = false;
 		tile.__childrenWereVisible = false;
+		tile.__allChildrenLoaded = false;
 
 		tile.__wasSetActive = false;
 		tile.__active = false;
diff --git a/src/base/traverseFunctions.js b/src/base/traverseFunctions.js
index f96d9a5..4887ea9 100644
--- a/src/base/traverseFunctions.js
+++ b/src/base/traverseFunctions.js
@@ -20,6 +20,7 @@ function resetFrameState( tile, frameCount ) {
 		tile.__active = false;
 		tile.__error = 0;
 		tile.__childrenWereVisible = false;
+		tile.__allChildrenLoaded = false;
 
 	}
 
@@ -188,14 +189,23 @@ export function markUsedSetLeaves( tile, renderer ) {
 	} else {
 
 		let childrenWereVisible = false;
+		let allChildrenLoaded = true;
 		for ( let i = 0, l = children.length; i < l; i ++ ) {
 
 			const c = children[ i ];
 			markUsedSetLeaves( c, renderer );
 			childrenWereVisible = childrenWereVisible || c.__wasSetVisible || c.__childrenWereVisible;
 
+			if ( isUsedThisFrame( c, frameCount ) ) {
+
+				const childLoaded = ( ! c.__contentEmpty && c.__loadingState === LOADED ) || c.__allChildrenLoaded;
+				allChildrenLoaded = allChildrenLoaded && childLoaded;
+
+			}
+
 		}
 		tile.__childrenWereVisible = childrenWereVisible;
+		tile.__allChildrenLoaded = allChildrenLoaded;
 
 	}
 
@@ -249,19 +259,7 @@ export function skipTraversal( tile, renderer ) {
 	const loadedContent = tile.__loadingState === LOADED && ! tile.__contentEmpty;
 	const childrenWereVisible = tile.__childrenWereVisible;
 	const children = tile.children;
-	let allChildrenHaveContent = true;
-	for ( let i = 0, l = children.length; i < l; i ++ ) {
-
-		const c = children[ i ];
-		if ( isUsedThisFrame( c, frameCount ) ) {
-
-			// TODO: This doesn't seem right -- we should check down to the next children with content?
-			const childContent = c.__loadingState === LOADED || tile.__contentEmpty;
-			allChildrenHaveContent = allChildrenHaveContent && childContent;
-
-		}
-
-	}
+	let allChildrenHaveContent = tile.__allChildrenLoaded;
 
 	// Increment the relative depth of the node to the nearest rendered parent if it has content
 	// and is being rendered.
diff --git a/src/three/DebugTilesRenderer.js b/src/three/DebugTilesRenderer.js
index d08d05b..3b2469b 100644
--- a/src/three/DebugTilesRenderer.js
+++ b/src/three/DebugTilesRenderer.js
@@ -9,8 +9,9 @@ const SCREEN_ERROR = 1;
 const GEOMETRIC_ERROR = 2;
 const DISTANCE = 3;
 const DEPTH = 4;
-const IS_LEAF = 5;
-const RANDOM_COLOR = 6;
+const RELATIVE_DEPTH = 5;
+const IS_LEAF = 6;
+const RANDOM_COLOR = 7;
 
 function emptyRaycast() {}
 
@@ -204,6 +205,13 @@ export class DebugTilesRenderer extends TilesRenderer {
 							c.material.color.setRGB( val, val, val );
 							break;
 
+						}
+						case RELATIVE_DEPTH: {
+
+							const val = tile.__depthFromRenderedParent / maxDepth;
+							c.material.color.setRGB( val, val, val );
+							break;
+
 						}
 						case SCREEN_ERROR: {
 
diff --git a/src/utilities/PriorityQueue.js b/src/utilities/PriorityQueue.js
index ebc25e9..bd93ba5 100644
--- a/src/utilities/PriorityQueue.js
+++ b/src/utilities/PriorityQueue.js
@@ -16,6 +16,7 @@ class PriorityQueue {
 		this.callbacks = new Map();
 		this.currJobs = 0;
 		this.scheduled = false;
+		this.autoUpdate = true;
 
 		this.priorityCallback = () => {
 
@@ -48,7 +49,11 @@ class PriorityQueue {
 			items.push( item );
 			callbacks.set( item, prCallback );
 
-			this.scheduleJobRun();
+			if ( this.autoUpdate ) {
+
+				this.scheduleJobRun();
+
+			}
 
 		} );
 
@@ -87,13 +92,23 @@ class PriorityQueue {
 				.then( () => {
 
 					this.currJobs --;
-					this.scheduleJobRun();
+
+					if ( this.autoUpdate ) {
+
+						this.scheduleJobRun();
+
+					}
 
 				} )
 				.catch( () => {
 
 					this.currJobs --;
-					this.scheduleJobRun();
+
+					if ( this.autoUpdate ) {
+
+						this.scheduleJobRun();
+
+					}
 
 				} );
 


Test patch:
diff --git a/test/PriorityQueue.test.js b/test/PriorityQueue.test.js
index 2d6b43d..b9fef78 100644
--- a/test/PriorityQueue.test.js
+++ b/test/PriorityQueue.test.js
@@ -154,4 +154,36 @@ describe( 'PriorityQueue', () => {
 
 	} );
 
+	it( 'should not automatically run if autoUpdate is false.', async () => {
+
+		const queue = new PriorityQueue();
+		queue.priorityCallback = () => 0;
+		queue.autoUpdate = false;
+		queue.maxJobs = 1;
+
+		queue.add( {}, async () => {} );
+		queue.add( {}, async () => {} );
+
+		expect( queue.items ).toHaveLength( 2 );
+
+		await nextTick();
+
+		expect( queue.items ).toHaveLength( 2 );
+
+		queue.scheduleJobRun();
+		await nextTick();
+
+		expect( queue.items ).toHaveLength( 1 );
+
+		await nextTick();
+
+		expect( queue.items ).toHaveLength( 1 );
+
+		queue.scheduleJobRun();
+		await nextTick();
+
+		expect( queue.items ).toHaveLength( 0 );
+
+	});
+
 } );