From f4d6b113704d3826dec68b133563ebfd13236435 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guimmara?= Date: Mon, 23 Dec 2024 14:20:08 +0100 Subject: [PATCH 1/5] fix(DebugTilesPlugin): remove tile-visibility-change event listener in dispose() --- src/plugins/three/DebugTilesPlugin.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/three/DebugTilesPlugin.js b/src/plugins/three/DebugTilesPlugin.js index f721338b8..2a0ce7c6c 100644 --- a/src/plugins/three/DebugTilesPlugin.js +++ b/src/plugins/three/DebugTilesPlugin.js @@ -698,6 +698,7 @@ export class DebugTilesPlugin { tiles.removeEventListener( 'load-model', this._onLoadModelCB ); tiles.removeEventListener( 'dispose-model', this._onDisposeModelCB ); tiles.removeEventListener( 'update-after', this._onUpdateAfterCB ); + tiles.removeEventListener( 'tile-visibility-change', this._onTileVisibilityChangeCB ); // reset all materials this.colorMode = NONE; From 85f27f68062424ed909f131df36de85a9a34380a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guimmara?= Date: Mon, 23 Dec 2024 14:15:31 +0100 Subject: [PATCH 2/5] perf(EllipsoidRegionHelper): don't compute vertex normals for the line-based version of the helper --- src/plugins/three/objects/EllipsoidRegionHelper.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/plugins/three/objects/EllipsoidRegionHelper.js b/src/plugins/three/objects/EllipsoidRegionHelper.js index 2b9a09159..8d866c747 100644 --- a/src/plugins/three/objects/EllipsoidRegionHelper.js +++ b/src/plugins/three/objects/EllipsoidRegionHelper.js @@ -45,7 +45,7 @@ function toGroupGeometry( geometry ) { } -function getRegionGeometry( ellipsoidRegion ) { +function getRegionGeometry( ellipsoidRegion, { computeNormals = false } = {} ) { // retrieve the relevant fields const { @@ -81,8 +81,12 @@ function getRegionGeometry( ellipsoidRegion ) { } - // compute the vertex normals so we can get the edge normals - geometry.computeVertexNormals(); + if ( computeNormals ) { + + // compute the vertex normals so we can get the edge normals + geometry.computeVertexNormals(); + + } // compute the top and bottom cap normals for ( let i = 0, l = refPosition.count; i < l; i ++ ) { @@ -159,7 +163,7 @@ export class EllipsoidRegionHelper extends Mesh { this.geometry.dispose(); // retrieve the relevant fields - const geometry = getRegionGeometry( this.ellipsoidRegion ); + const geometry = getRegionGeometry( this.ellipsoidRegion, { computeNormals: true } ); const { lonStart, lonEnd } = this; // exclude the side tris if the region wraps around From 888d0c14b5e7d9d93634ea24d1c99231e8565191 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guimmara?= Date: Mon, 23 Dec 2024 13:20:20 +0100 Subject: [PATCH 3/5] refactor(traverseFunctions.js): add traverseAncestors() --- src/base/traverseFunctions.js | 25 +++++++++++++++++++++++++ test/traverseFunctions.test.js | 29 ++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/base/traverseFunctions.js b/src/base/traverseFunctions.js index 8aafb130e..29c3ee53a 100644 --- a/src/base/traverseFunctions.js +++ b/src/base/traverseFunctions.js @@ -488,3 +488,28 @@ export function toggleTiles( tile, renderer ) { } } + +/** + * Traverses the ancestry of the tile up to the root tile. + */ +export function traverseAncestors( tile, callback = null ) { + + let current = tile; + + while ( current ) { + + const depth = current.__depth; + const parent = current.parent; + + if ( callback ) { + + callback( current, parent, depth ); + + } + + current = parent; + + } + + +} diff --git a/test/traverseFunctions.test.js b/test/traverseFunctions.test.js index bc0d82d80..5f309d6e3 100644 --- a/test/traverseFunctions.test.js +++ b/test/traverseFunctions.test.js @@ -1,4 +1,4 @@ -import { traverseSet } from '../src/base/traverseFunctions.js'; +import { traverseAncestors, traverseSet } from '../src/base/traverseFunctions.js'; describe( 'traverseSet', () => { @@ -99,3 +99,30 @@ describe( 'traverseSet', () => { } ); } ); + +describe( 'traverseAncestors', () => { + + function makeTile( name, parent = undefined ) { + + return { name, parent }; + + } + + it( 'visit all ancestry chain', () => { + + const root = makeTile( 'root' ); + + const lod1 = makeTile( '1', root ); + const lod2 = makeTile( '2', lod1 ); + const lod3 = makeTile( '3', lod2 ); + const lod4 = makeTile( '4', lod3 ); + + const visited = []; + + traverseAncestors( lod4, tile => visited.push( tile.name ) ); + + expect( visited ).toEqual( [ '4', '3', '2', '1', 'root' ] ); + + } ); + +} ); From 1dc510fac3283f07c964cbb09212a3b390e521fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guimmara?= Date: Mon, 23 Dec 2024 13:22:23 +0100 Subject: [PATCH 4/5] DebugTilesPlugin: add the displayParentBounds option (#730) --- src/plugins/three/DebugTilesPlugin.js | 206 +++++++++++++++++++++----- 1 file changed, 166 insertions(+), 40 deletions(-) diff --git a/src/plugins/three/DebugTilesPlugin.js b/src/plugins/three/DebugTilesPlugin.js index 2a0ce7c6c..1ae061531 100644 --- a/src/plugins/three/DebugTilesPlugin.js +++ b/src/plugins/three/DebugTilesPlugin.js @@ -1,12 +1,13 @@ import { Box3Helper, Group, MeshStandardMaterial, PointsMaterial, Sphere, Color } from 'three'; import { SphereHelper } from './objects/SphereHelper.js'; import { EllipsoidRegionLineHelper } from './objects/EllipsoidRegionHelper.js'; -import { traverseSet } from '../../base/traverseFunctions.js'; +import { traverseAncestors, traverseSet } from '../../base/traverseFunctions.js'; const ORIGINAL_MATERIAL = Symbol( 'ORIGINAL_MATERIAL' ); const HAS_RANDOM_COLOR = Symbol( 'HAS_RANDOM_COLOR' ); const HAS_RANDOM_NODE_COLOR = Symbol( 'HAS_RANDOM_NODE_COLOR' ); const LOAD_TIME = Symbol( 'LOAD_TIME' ); +const PARENT_BOUND_REF_COUNT = Symbol( 'PARENT_BOUND_REF_COUNT' ); const _sphere = /* @__PURE__ */ new Sphere(); const emptyRaycast = () => {}; @@ -46,6 +47,7 @@ export class DebugTilesPlugin { constructor( options ) { options = { + displayParentBounds: false, displayBoxBounds: false, displaySphereBounds: false, displayRegionBounds: false, @@ -69,6 +71,7 @@ export class DebugTilesPlugin { this.regionGroup = null; // options + this._displayParentBounds = options.displayParentBounds; this.displayBoxBounds = options.displayBoxBounds; this.displaySphereBounds = options.displaySphereBounds; this.displayRegionBounds = options.displayRegionBounds; @@ -116,6 +119,47 @@ export class DebugTilesPlugin { } + get displayParentBounds() { + + return this._displayParentBounds; + + } + + set displayParentBounds( v ) { + + if ( this._displayParentBounds !== v ) { + + this._displayParentBounds = v; + + if ( ! v ) { + + // Reset all ref counts + traverseSet( this.tiles.root, null, tile => { + + tile[ PARENT_BOUND_REF_COUNT ] = null; + this._onTileVisibilityChange( tile, tile.__visible ); + + } ); + + } else { + + // Initialize ref count for existing tiles + this.tiles.traverse( tile => { + + if ( tile.__visible ) { + + this._onTileVisibilityChange( tile, true ); + + } + + } ); + + } + + } + + } + // initialize the groups for displaying helpers, register events, and initialize existing tiles init( tiles ) { @@ -520,64 +564,41 @@ export class DebugTilesPlugin { _onTileVisibilityChange( tile, visible ) { - const cached = tile.cached; - const sphereGroup = this.sphereGroup; - const boxGroup = this.boxGroup; - const regionGroup = this.regionGroup; - const boxHelperGroup = cached.boxHelperGroup; - const sphereHelper = cached.sphereHelper; - const regionHelper = cached.regionHelper; - - if ( ! visible ) { - - if ( boxHelperGroup ) { - - boxGroup.remove( boxHelperGroup ); - - } - - if ( sphereHelper ) { - - sphereGroup.remove( sphereHelper ); + if ( this.displayParentBounds ) { - } + traverseAncestors( tile, current => { - if ( regionHelper ) { + if ( current[ PARENT_BOUND_REF_COUNT ] == null ) { - regionGroup.remove( regionHelper ); + current[ PARENT_BOUND_REF_COUNT ] = 0; - } + } - } else { + if ( visible ) { - if ( boxHelperGroup ) { + current[ PARENT_BOUND_REF_COUNT ] ++; - boxGroup.add( boxHelperGroup ); - boxHelperGroup.updateMatrixWorld( true ); + } else if ( current[ PARENT_BOUND_REF_COUNT ] > 0 ) { - } + current[ PARENT_BOUND_REF_COUNT ] --; - if ( sphereHelper ) { + } - sphereGroup.add( sphereHelper ); - sphereHelper.updateMatrixWorld( true ); + const tileVisible = ( current === tile && visible ) || ( this.displayParentBounds && current[ PARENT_BOUND_REF_COUNT ] > 0 ); - } + this._updateBoundHelper( current, tileVisible ); - if ( regionHelper ) { + } ); - regionGroup.add( regionHelper ); - regionHelper.updateMatrixWorld( true ); + } else { - } + this._updateBoundHelper( tile, visible ); } } - _onLoadModel( scene, tile ) { - - tile[ LOAD_TIME ] = performance.now(); + _createBoundHelper( tile ) { const tiles = this.tiles; const cached = tile.cached; @@ -648,6 +669,111 @@ export class DebugTilesPlugin { } + } + + _updateHelperMaterial( tile, material ) { + + if ( tile.__visible || ! this.displayParentBounds ) { + + material.opacity = 1; + + } else { + + material.opacity = 0.2; + + } + + const transparent = material.transparent; + material.transparent = material.opacity < 1; + if ( material.transparent !== transparent ) { + + material.needsUpdate = true; + + } + + } + + _updateBoundHelper( tile, visible ) { + + const cached = tile.cached; + + if ( ! cached ) { + + return; + + } + + const sphereGroup = this.sphereGroup; + const boxGroup = this.boxGroup; + const regionGroup = this.regionGroup; + + if ( visible && ( cached.boxHelperGroup == null && cached.sphereHelper == null && cached.regionHelper == null ) ) { + + this._createBoundHelper( tile ); + + } + + const boxHelperGroup = cached.boxHelperGroup; + const sphereHelper = cached.sphereHelper; + const regionHelper = cached.regionHelper; + + if ( ! visible ) { + + if ( boxHelperGroup ) { + + boxGroup.remove( boxHelperGroup ); + + } + + if ( sphereHelper ) { + + sphereGroup.remove( sphereHelper ); + + } + + if ( regionHelper ) { + + regionGroup.remove( regionHelper ); + + } + + } else { + + if ( boxHelperGroup ) { + + boxGroup.add( boxHelperGroup ); + boxHelperGroup.updateMatrixWorld( true ); + + this._updateHelperMaterial( tile, boxHelperGroup.children[ 0 ].material ); + + } + + if ( sphereHelper ) { + + sphereGroup.add( sphereHelper ); + sphereHelper.updateMatrixWorld( true ); + + this._updateHelperMaterial( tile, sphereHelper.material ); + + } + + if ( regionHelper ) { + + regionGroup.add( regionHelper ); + regionHelper.updateMatrixWorld( true ); + + this._updateHelperMaterial( tile, regionHelper.material ); + + } + + } + + } + + _onLoadModel( scene, tile ) { + + tile[ LOAD_TIME ] = performance.now(); + // Cache the original materials scene.traverse( c => { From b4bceeba9f1c3cce5555ebd8dd97b2ccbc0bd992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guimmara?= Date: Mon, 23 Dec 2024 13:23:01 +0100 Subject: [PATCH 5/5] refactor(index.js): add displayParentBounds toggle --- example/index.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/example/index.js b/example/index.js index 470942c0d..c5d866898 100644 --- a/example/index.js +++ b/example/index.js @@ -72,6 +72,7 @@ const params = { up: hashUrl ? '+Z' : '+Y', enableDebug: true, + displayParentBounds: false, displayBoxBounds: false, displaySphereBounds: false, displayRegionBounds: false, @@ -273,6 +274,7 @@ function init() { const debug = gui.addFolder( 'Debug Options' ); debug.add( params, 'enableDebug' ); + debug.add( params, 'displayParentBounds' ); debug.add( params, 'displayBoxBounds' ); debug.add( params, 'displaySphereBounds' ); debug.add( params, 'displayRegionBounds' ); @@ -489,6 +491,7 @@ function animate() { const plugin = tiles.getPluginByName( 'DEBUG_TILES_PLUGIN' ); plugin.enabled = params.enableDebug; plugin.displayBoxBounds = params.displayBoxBounds; + plugin.displayParentBounds = params.displayParentBounds; plugin.displaySphereBounds = params.displaySphereBounds; plugin.displayRegionBounds = params.displayRegionBounds; plugin.colorMode = parseFloat( params.colorMode );