Skip to content

Commit

Permalink
Add support for plugin system (#603)
Browse files Browse the repository at this point in the history
* Add initial plugin support

* update function names

* Update

* Updates

* Updates

* Update use of plugin

* Remove unused file

* Remove unused function

* Add disposal support

* Update demos
  • Loading branch information
gkjohnson committed Jul 6, 2024
1 parent 3c46314 commit a15470d
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 333 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@
</head>
<body>
<div id="info">
Set of tiles from M2020 Drive 1004 generated using NASA JPL's <a href="">Landform</a>.
Set of tiles from M20 Drive 1004 generated using NASA JPL's <a href="">Landform</a> with generated slope magnitude overlay.
<br/>
See more tile set information <a href="https://github.com/NASA-AMMOS/3DTilesSampleData/tree/master/m20-drive-1004">here</a>.
See information on this tile sets generation <a href="https://github.com/NASA-AMMOS/3DTilesSampleData/tree/master/m20-drive-1004">here</a>.
</div>
<script src="./landformSite.js" type="module"></script>
<script src="./landformSiteOverlay.js" type="module"></script>
</body>
</html>
48 changes: 23 additions & 25 deletions example/landformSite.js → example/landformSiteOverlay.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
TilesRenderer,
EnvironmentControls,
} from '..';
} from '../src/index.js';
import {
Scene,
WebGLRenderer,
Expand All @@ -12,8 +12,8 @@ import {
} from 'three';
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js';
import { JPLLandformSiteSceneLoader } from './src/jpl/JPLLandformSceneLoader.js';
import { TextureOverlayTilesRendererMixin } from './src/plugins/overlays/TextureOverlayTilesRenderer.js';
import { TextureOverlayMaterialMixin } from './src/plugins/overlays/TextureOverlayMaterial.js';
import { TextureOverlayPlugin } from './src/plugins/overlays/TextureOverlayPlugin.js';

const URLS = [

Expand All @@ -29,16 +29,11 @@ const URLS = [
'NLF_0477_0709298393M010RAS_N0261004NCAM13477_0A0195J02/NLF_0477_0709298393M010RAS_N0261004NCAM13477_0A0195J02_scene.json',

// 'NLFS0498_0711156087M000RAS_N0261004NCAM00607_0A0095J01/NLFS0498_0711156087M000RAS_N0261004NCAM00607_0A0095J01_scene.json',

// 'NLF_0482_0709734873M194RAS_N0261004NCAM00347_0A0195J02/NLF_0482_0709734873M194RAS_N0261004NCAM00347_0A0195J02_scene.json',
// 'NLF_0482_0709735996M816RAS_N0261004NCAM00709_0A0095J02/NLF_0482_0709735996M816RAS_N0261004NCAM00709_0A0095J02_scene.json',

// 'NLF_0490_0710456117M926RAS_N0261004NCAM00709_0A0095J03/NLF_0490_0710456117M926RAS_N0261004NCAM00709_0A0095J03_scene.json',

// 'NLF_0491_0710536867M784RAS_N0261004NCAM00709_0A0095J02/NLF_0491_0710536867M784RAS_N0261004NCAM00709_0A0095J02_scene.json',

// 'NLF_0495_0710900102M755RAS_N0261004NCAM00709_0A0095J02/NLF_0495_0710900102M755RAS_N0261004NCAM00709_0A0095J02_scene.json',

// 'NLF_0499_0711256332M612RAS_N0261004NCAM00347_0A1195J03/NLF_0499_0711256332M612RAS_N0261004NCAM00347_0A1195J03_scene.json',

].map( n => {
Expand Down Expand Up @@ -74,7 +69,7 @@ function init() {
renderer.domElement.tabIndex = 1;

camera = new PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.025, 4000 );
camera.position.set( 20, 10, 20 );
camera.position.set( - 20, 10, 20 );
camera.lookAt( 0, 0, 0 );

// controls
Expand Down Expand Up @@ -113,41 +108,38 @@ function init() {
const tokens = url.split( /[\\/]/g );
tokens.pop();

const TextureOverlayTilesRenderer = TextureOverlayTilesRendererMixin( TilesRenderer );
const TextureOverlayMaterial = TextureOverlayMaterialMixin( MeshBasicMaterial );
scene.tilesets.forEach( info => {

const url = [ ...tokens, `${ info.id }_tileset.json` ].join( '/' );
const tiles = new TextureOverlayTilesRenderer( url );

// ensure all materials support overlay textures
tiles.addEventListener( 'load-model', ( { tile, scene } )=> {
const tiles = new TilesRenderer( url );
const plugin = new TextureOverlayPlugin( ( scene, tile, plugin ) => {

scene.traverse( c => {

if ( c.material ) {

const newMaterial = new TextureOverlayMaterial();
newMaterial.copy( c.material );
newMaterial.textures = Object.values( tiles.getTexturesForTile( tile ) );
newMaterial.displayAsOverlay = params.slopeDisplay === 'OVERLAY';
c.material = newMaterial;
c.material.textures = Object.values( plugin.getTexturesForTile( tile ) );
c.material.displayAsOverlay = params.slopeDisplay === 'OVERLAY';
c.material.needsUpdate = true;

}

} );

} );
tiles.registerPlugin( plugin );

// assign the texture layers
tiles.addEventListener( 'layer-textures-change', ( { tile, scene } ) => {
// ensure all materials support overlay textures
tiles.addEventListener( 'load-model', ( { tile, scene } )=> {

scene.traverse( c => {

if ( c.material ) {

c.material.textures = Object.values( tiles.getTexturesForTile( tile ) );
c.material.needsUpdate = true;
const newMaterial = new TextureOverlayMaterial();
newMaterial.copy( c.material );
c.material = newMaterial;

}

Expand Down Expand Up @@ -186,9 +178,10 @@ function init() {

tileSets.forEach( t => {

if ( ! t.hasLayer( 'slopeLayer' ) ) {
const plugin = t.getPluginByName( 'TEXTURE_OVERLAY_PLUGIN' );
if ( ! plugin.hasLayer( 'slopeLayer' ) ) {

t.registerLayer( 'slopeLayer', layerFunction );
plugin.registerLayer( 'slopeLayer', layerFunction );

}

Expand All @@ -211,7 +204,12 @@ function init() {

} else {

tileSets.forEach( t => t.unregisterLayer( 'slopeLayer' ) );
tileSets.forEach( t => {

const plugin = t.getPluginByName( 'TEXTURE_OVERLAY_PLUGIN' );
plugin.unregisterLayer( 'slopeLayer' );

} );

}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { TextureLoader, ImageBitmapLoader } from 'three';
import { PriorityQueue } from '../../../../src';

// TODO: Enable TilesRenderer to delay load model events until all textures have loaded
// TODO: Load textures while the tile geometry is loading - can we start this sooner than parse tile?
// TODO: What happens if a tile starts loading and then a layer is added, meaning it's not in the "loaded tiles" callback
// or active function and we haven't caught it in the parseTile function. Additional callback? Store the loading models?
import { PriorityQueue } from '../../../..';

function canUseImageBitmap() {

Expand Down Expand Up @@ -185,20 +180,31 @@ class TextureCache {

}

export const TextureOverlayTilesRendererMixin = base => class extends base {
export class TextureOverlayPlugin {

constructor( assignCallback ) {

this.name = 'TEXTURE_OVERLAY_PLUGIN';
this.caches = null;
this.queue = null;
this.tiles = null;
this.assignCallback = assignCallback;

constructor( ...args ) {
}

// plugin functions
init( tiles ) {

super( ...args );
this.tiles = tiles;
this.caches = {};
this.queue = new PriorityQueue();
this.queue.priorityCallback = ( a, b ) => {

return this.downloadQueue.priorityCallback( a, b );
return tiles.downloadQueue.priorityCallback( a, b );

};

this.addEventListener( 'dispose-model', ( { tile } ) => {
this._disposeModelCallback = ( { tile } ) => {

const caches = this.caches;
for ( const key in caches ) {
Expand All @@ -208,11 +214,21 @@ export const TextureOverlayTilesRendererMixin = base => class extends base {

}

} );
};

this._assignTexturesCallback = ( { tile, scene } ) => {

this.assignCallback( scene, tile, this );

};

tiles.addEventListener( 'dispose-model', this._disposeModelCallback );
tiles.addEventListener( 'load-model', this._assignTexturesCallback );
tiles.addEventListener( 'layer-textures-change', this._assignTexturesCallback );

}

_pluginProcessTileModel( scene, tile ) {
processTileModel( scene, tile ) {

const caches = this.caches;
const promises = [];
Expand All @@ -231,9 +247,24 @@ export const TextureOverlayTilesRendererMixin = base => class extends base {

}

dispose() {

const { caches, tiles } = this;
Object.keys( caches ).forEach( key => {

this.unregisterLayer( key );

} );

tiles.removeEventListener( 'dispose-model', this._disposeModelCallback );
tiles.removeEventListener( 'load-model', this._assignTexturesCallback );
tiles.removeEventListener( 'layer-textures-change', this._assignTexturesCallback );

}

// public functions
getTileKey( tile ) {

// TODO
return tile.content.uri;

}
Expand Down Expand Up @@ -268,35 +299,20 @@ export const TextureOverlayTilesRendererMixin = base => class extends base {

if ( name in this.caches ) {

throw new Error();
throw new Error( `TextureOverlayPlugin: Texture overlay named ${ name } already exists.` );

}

const tiles = this.tiles;
const cache = new TextureCache( customTextureCallback, this.queue );
cache.fetchOptions = this.fetchOptions;
cache.fetchOptions = tiles.fetchOptions;
this.caches[ name ] = cache;

this.forEachLoadedModel( ( scene, tile ) => {
tiles.forEachLoadedModel( ( scene, tile ) => {

cache
.loadTexture( this.getTileKey( tile ) )
.then( texture => {

this.dispatchEvent( {
type: 'load-layer-texture',
layer: name,
tile,
scene,
texture,
} );

this.dispatchEvent( {
type: 'layer-textures-change',
tile,
scene,
} );

} )
.then( () => this.assignCallback( scene, tile, this ) )
.catch( () => {} );

} );
Expand All @@ -305,30 +321,19 @@ export const TextureOverlayTilesRendererMixin = base => class extends base {

unregisterLayer( name ) {

const tiles = this.tiles;
const caches = this.caches;
if ( name in caches ) {

const cache = caches[ name ];
delete caches[ name ];

this.forEachLoadedModel( ( scene, tile ) => {
tiles.forEachLoadedModel( ( scene, tile ) => {

const texture = cache.getTexture( this.getTileKey( tile ) );
if ( texture ) {

this.dispatchEvent( {
type: 'delete-layer-texture',
layer: name,
tile,
scene,
texture,
} );

this.dispatchEvent( {
type: 'layer-textures-change',
tile,
scene,
} );
this.assignCallback( scene, tile, this );

}

Expand All @@ -340,5 +345,4 @@ export const TextureOverlayTilesRendererMixin = base => class extends base {

}

};

}
19 changes: 0 additions & 19 deletions example/textureOverlay.html

This file was deleted.

Loading

0 comments on commit a15470d

Please sign in to comment.