Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for plugin system #603

Merged
merged 11 commits into from
Jul 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading