From 60e39f9c6aaa6bc6f4def8f2d94956126d41d570 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Fri, 1 Nov 2024 13:05:03 +0900 Subject: [PATCH 01/10] Move plugins --- src/base/plugins/ImplicitTilingPlugin.js | 80 +-- .../base}/ImplicitTilingPlugin.d.ts | 0 src/plugins/base/ImplicitTilingPlugin.js | 84 +++ .../plugins => plugins/base}/SUBTREELoader.js | 0 src/plugins/index.d.ts | 7 + src/plugins/index.js | 7 + src/plugins/three/CesiumIonAuthPlugin.d.ts | 9 + src/plugins/three/CesiumIonAuthPlugin.js | 172 +++++ src/plugins/three/DebugTilesPlugin.d.ts | 29 + src/plugins/three/DebugTilesPlugin.js | 677 ++++++++++++++++++ .../three/GoogleAttributionsManager.js | 62 ++ src/plugins/three/GoogleCloudAuthPlugin.d.ts | 5 + src/plugins/three/GoogleCloudAuthPlugin.js | 197 +++++ 13 files changed, 1253 insertions(+), 76 deletions(-) rename src/{base/plugins => plugins/base}/ImplicitTilingPlugin.d.ts (100%) create mode 100644 src/plugins/base/ImplicitTilingPlugin.js rename src/{base/plugins => plugins/base}/SUBTREELoader.js (100%) create mode 100644 src/plugins/index.d.ts create mode 100644 src/plugins/index.js create mode 100644 src/plugins/three/CesiumIonAuthPlugin.d.ts create mode 100644 src/plugins/three/CesiumIonAuthPlugin.js create mode 100644 src/plugins/three/DebugTilesPlugin.d.ts create mode 100644 src/plugins/three/DebugTilesPlugin.js create mode 100644 src/plugins/three/GoogleAttributionsManager.js create mode 100644 src/plugins/three/GoogleCloudAuthPlugin.d.ts create mode 100644 src/plugins/three/GoogleCloudAuthPlugin.js diff --git a/src/base/plugins/ImplicitTilingPlugin.js b/src/base/plugins/ImplicitTilingPlugin.js index 448d4a97b..7d2475dbc 100644 --- a/src/base/plugins/ImplicitTilingPlugin.js +++ b/src/base/plugins/ImplicitTilingPlugin.js @@ -1,83 +1,11 @@ -import { SUBTREELoader } from './SUBTREELoader.js'; +import { ImplicitTilingPlugin as ImplicitTilingPluginImpl } from '../../plugins/index.js'; -export class ImplicitTilingPlugin { +export class ImplicitTilingPlugin extends ImplicitTilingPluginImpl { constructor() { - this.name = 'IMPLICIT_TILING_PLUGIN'; - - } - - init( tiles ) { - - this.tiles = tiles; - - } - - preprocessNode( tile, tileSetDir, parentTile ) { - - if ( tile.implicitTiling ) { - - tile.__hasUnrenderableContent = true; - tile.__hasRenderableContent = false; - - // Declare some properties - tile.__subtreeIdx = 0; // Idx of the tile in its subtree - tile.__implicitRoot = tile; // Keep this tile as an Implicit Root Tile - - // Coords of the tile - tile.__x = 0; - tile.__y = 0; - tile.__z = 0; - tile.__level = 0; - - } else if ( /.subtree$/i.test( tile.content?.uri ) ) { - - // Handling content uri pointing to a subtree file - tile.__hasUnrenderableContent = true; - tile.__hasRenderableContent = false; - - } - - } - - parseTile( buffer, parseTile, extension ) { - - if ( /^subtree$/i.test( extension ) ) { - - const loader = new SUBTREELoader( parseTile ); - loader.parse( buffer ); - return Promise.resolve(); - - } - - } - - preprocessURL( url, tile ) { - - if ( tile && tile.implicitTiling ) { - - const implicitUri = tile.implicitTiling.subtrees.uri - .replace( '{level}', tile.__level ) - .replace( '{x}', tile.__x ) - .replace( '{y}', tile.__y ) - .replace( '{z}', tile.__z ); - - return new URL( implicitUri, tile.__basePath + '/' ).toString(); - - } - - return url; - - } - - disposeTile( tile ) { - - if ( /.subtree$/i.test( tile.content?.uri ) ) { - - tile.children.length = 0; - - } + super(); + console.warn( 'ImplicitTilingPlugin: Plugin should now be imported from "3d-tiles-renderer/plugins" path.' ); } diff --git a/src/base/plugins/ImplicitTilingPlugin.d.ts b/src/plugins/base/ImplicitTilingPlugin.d.ts similarity index 100% rename from src/base/plugins/ImplicitTilingPlugin.d.ts rename to src/plugins/base/ImplicitTilingPlugin.d.ts diff --git a/src/plugins/base/ImplicitTilingPlugin.js b/src/plugins/base/ImplicitTilingPlugin.js new file mode 100644 index 000000000..448d4a97b --- /dev/null +++ b/src/plugins/base/ImplicitTilingPlugin.js @@ -0,0 +1,84 @@ +import { SUBTREELoader } from './SUBTREELoader.js'; + +export class ImplicitTilingPlugin { + + constructor() { + + this.name = 'IMPLICIT_TILING_PLUGIN'; + + } + + init( tiles ) { + + this.tiles = tiles; + + } + + preprocessNode( tile, tileSetDir, parentTile ) { + + if ( tile.implicitTiling ) { + + tile.__hasUnrenderableContent = true; + tile.__hasRenderableContent = false; + + // Declare some properties + tile.__subtreeIdx = 0; // Idx of the tile in its subtree + tile.__implicitRoot = tile; // Keep this tile as an Implicit Root Tile + + // Coords of the tile + tile.__x = 0; + tile.__y = 0; + tile.__z = 0; + tile.__level = 0; + + } else if ( /.subtree$/i.test( tile.content?.uri ) ) { + + // Handling content uri pointing to a subtree file + tile.__hasUnrenderableContent = true; + tile.__hasRenderableContent = false; + + } + + } + + parseTile( buffer, parseTile, extension ) { + + if ( /^subtree$/i.test( extension ) ) { + + const loader = new SUBTREELoader( parseTile ); + loader.parse( buffer ); + return Promise.resolve(); + + } + + } + + preprocessURL( url, tile ) { + + if ( tile && tile.implicitTiling ) { + + const implicitUri = tile.implicitTiling.subtrees.uri + .replace( '{level}', tile.__level ) + .replace( '{x}', tile.__x ) + .replace( '{y}', tile.__y ) + .replace( '{z}', tile.__z ); + + return new URL( implicitUri, tile.__basePath + '/' ).toString(); + + } + + return url; + + } + + disposeTile( tile ) { + + if ( /.subtree$/i.test( tile.content?.uri ) ) { + + tile.children.length = 0; + + } + + } + +} diff --git a/src/base/plugins/SUBTREELoader.js b/src/plugins/base/SUBTREELoader.js similarity index 100% rename from src/base/plugins/SUBTREELoader.js rename to src/plugins/base/SUBTREELoader.js diff --git a/src/plugins/index.d.ts b/src/plugins/index.d.ts new file mode 100644 index 000000000..174d167ba --- /dev/null +++ b/src/plugins/index.d.ts @@ -0,0 +1,7 @@ +// three.js plugins +export { CesiumIonAuthPlugin } from './three/plugins/CesiumIonAuthPlugin'; +export { GoogleCloudAuthPlugin } from './three/plugins/GoogleCloudAuthPlugin'; +export * from './three/plugins/DebugTilesPlugin'; + +// common plugins +export { ImplicitTilingPlugin } from './base/plugins/ImplicitTilingPlugin'; diff --git a/src/plugins/index.js b/src/plugins/index.js new file mode 100644 index 000000000..eac6bf8ee --- /dev/null +++ b/src/plugins/index.js @@ -0,0 +1,7 @@ +// three.js plugins +export { CesiumIonAuthPlugin } from './three/plugins/CesiumIonAuthPlugin.js'; +export { GoogleCloudAuthPlugin } from './three/plugins/GoogleCloudAuthPlugin.js'; +export * from './three/plugins/DebugTilesPlugin.js'; + +// common plugins +export { ImplicitTilingPlugin } from './base/plugins/ImplicitTilingPlugin.js'; diff --git a/src/plugins/three/CesiumIonAuthPlugin.d.ts b/src/plugins/three/CesiumIonAuthPlugin.d.ts new file mode 100644 index 000000000..314dd639f --- /dev/null +++ b/src/plugins/three/CesiumIonAuthPlugin.d.ts @@ -0,0 +1,9 @@ +export class CesiumIonAuthPlugin { + + constructor( options : { + apiToken: String, + assetId?: String | null, + autoRefreshToken?: Boolean + } ); + +} diff --git a/src/plugins/three/CesiumIonAuthPlugin.js b/src/plugins/three/CesiumIonAuthPlugin.js new file mode 100644 index 000000000..c04fe9839 --- /dev/null +++ b/src/plugins/three/CesiumIonAuthPlugin.js @@ -0,0 +1,172 @@ +import { GoogleCloudAuthPlugin } from './GoogleCloudAuthPlugin.js'; + +export class CesiumIonAuthPlugin { + + constructor( { apiToken, assetId = null, autoRefreshToken = false } ) { + + this.name = 'CESIUM_ION_AUTH_PLUGIN'; + this.apiToken = apiToken; + this.assetId = assetId; + this.autoRefreshToken = autoRefreshToken; + this.tiles = null; + this.endpointURL = null; + + this._bearerToken = null; + this._tileSetVersion = - 1; + this._tokenRefreshPromise = null; + this._attributions = []; + + } + + init( tiles ) { + + if ( this.assetId !== null ) { + + tiles.rootURL = `https://api.cesium.com/v1/assets/${ this.assetId }/endpoint`; + + } + + this.tiles = tiles; + this.endpointURL = tiles.rootURL; + + } + + loadRootTileSet() { + + // ensure we have an up-to-date token and root url, then trigger the internal + // root tile set load function + return this._refreshToken() + .then( () => this.tiles.loadRootTileSet() ); + + } + + preprocessURL( uri ) { + + uri = new URL( uri ); + if ( /^http/.test( uri.protocol ) && this._tileSetVersion != - 1 ) { + + uri.searchParams.append( 'v', this._tileSetVersion ); + + } + return uri.toString(); + + } + + fetchData( uri, options ) { + + const tiles = this.tiles; + if ( tiles.getPluginByName( 'GOOGLE_CLOUD_AUTH_PLUGIN' ) !== null ) { + + return null; + + } else { + + return Promise.resolve().then( async () => { + + // wait for the token to refresh if loading + if ( this._tokenRefreshPromise !== null ) { + + await this._tokenRefreshPromise; + uri = this.preprocessURL( uri ); + + } + + const res = await fetch( uri, options ); + if ( res.status >= 400 && res.status <= 499 && this.autoRefreshToken ) { + + await this._refreshToken( options ); + return fetch( this.preprocessURL( uri ), options ); + + } else { + + return res; + + } + + } ); + + } + + } + + getAttributions( target ) { + + if ( this.tiles.visibleTiles.size > 0 ) { + + target.push( ...this._attributions ); + + } + + } + + _refreshToken( options ) { + + if ( this._tokenRefreshPromise === null ) { + + // construct the url to fetch the endpoint + const url = new URL( this.endpointURL ); + url.searchParams.append( 'access_token', this.apiToken ); + + this._tokenRefreshPromise = fetch( url, options ) + .then( res => { + + if ( ! res.ok ) { + + throw new Error( `CesiumIonAuthPlugin: Failed to load data with error code ${ res.status }` ); + + } + + return res.json(); + + } ) + .then( json => { + + const tiles = this.tiles; + if ( 'externalType' in json ) { + + const url = new URL( json.options.url ); + tiles.rootURL = json.options.url; + + // if the tile set is "external" then assume it's a google API tile set + tiles.registerPlugin( new GoogleCloudAuthPlugin( { apiToken: url.searchParams.get( 'key' ) } ) ); + + } else { + + tiles.rootURL = json.url; + tiles.fetchOptions.headers = tiles.fetchOptions.headers || {}; + tiles.fetchOptions.headers.Authorization = `Bearer ${ json.accessToken }`; + + // save the version key if present + if ( url.searchParams.has( 'v' ) && this._tileSetVersion === - 1 ) { + + const url = new URL( json.url ); + this._tileSetVersion = url.searchParams.get( 'v' ); + + } + + this._bearerToken = json.accessToken; + if ( json.attributions ) { + + this._attributions = json.attributions.map( att => ( { + value: att.html, + type: 'html', + collapsible: att.collapsible, + } ) ); + + } + + } + + this._tokenRefreshPromise = null; + + return json; + + } ); + + } + + return this._tokenRefreshPromise; + + } + +} diff --git a/src/plugins/three/DebugTilesPlugin.d.ts b/src/plugins/three/DebugTilesPlugin.d.ts new file mode 100644 index 000000000..06efbed0a --- /dev/null +++ b/src/plugins/three/DebugTilesPlugin.d.ts @@ -0,0 +1,29 @@ +import { Tile } from '../../base/Tile'; +import { Color } from 'three'; + +export enum ColorMode {} +export const NONE : ColorMode; +export const SCREEN_ERROR : ColorMode; +export const GEOMETRIC_ERROR : ColorMode; +export const DISTANCE : ColorMode; +export const DEPTH : ColorMode; +export const RELATIVE_DEPTH : ColorMode; +export const IS_LEAF : ColorMode; +export const RANDOM_COLOR : ColorMode; +export const RANDOM_NODE_COLOR: ColorMode; +export const CUSTOM_COLOR: ColorMode; +export class DebugTilesPlugin { + + displayBoxBounds : Boolean; + displaySphereBounds : Boolean; + displayRegionBounds : Boolean; + colorMode : ColorMode; + + maxDebugDepth : Number; + maxDebugDistance : Number; + maxDebugError : Number; + + getDebugColor : ( val: Number, target: Color ) => void; + customColorCallback : ( val: Tile, target: Color ) => void; + +} diff --git a/src/plugins/three/DebugTilesPlugin.js b/src/plugins/three/DebugTilesPlugin.js new file mode 100644 index 000000000..920d2f336 --- /dev/null +++ b/src/plugins/three/DebugTilesPlugin.js @@ -0,0 +1,677 @@ +import { Box3Helper, Group, MeshStandardMaterial, PointsMaterial, Sphere, Color } from 'three'; +import { SphereHelper } from '../objects/SphereHelper.js'; +import { EllipsoidRegionLineHelper } from '../objects/EllipsoidRegionHelper.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 _sphere = /* @__PURE__ */ new Sphere(); +const emptyRaycast = () => {}; +const colors = {}; + +// Return a consistant random color for an index +export function getIndexedRandomColor( index ) { + + if ( ! colors[ index ] ) { + + const h = Math.random(); + const s = 0.5 + Math.random() * 0.5; + const l = 0.375 + Math.random() * 0.25; + + colors[ index ] = new Color().setHSL( h, s, l ); + + } + return colors[ index ]; + +} + +// color modes +export const NONE = 0; +export const SCREEN_ERROR = 1; +export const GEOMETRIC_ERROR = 2; +export const DISTANCE = 3; +export const DEPTH = 4; +export const RELATIVE_DEPTH = 5; +export const IS_LEAF = 6; +export const RANDOM_COLOR = 7; +export const RANDOM_NODE_COLOR = 8; +export const CUSTOM_COLOR = 9; +export const LOAD_ORDER = 10; + +export class DebugTilesPlugin { + + constructor( options ) { + + options = { + displayBoxBounds: false, + displaySphereBounds: false, + displayRegionBounds: false, + colorMode: NONE, + maxDebugDepth: - 1, + maxDebugDistance: - 1, + maxDebugError: - 1, + customColorCallback: null, + ...options, + }; + + this.name = 'DEBUG_TILES_PLUGIN'; + this.tiles = null; + + this.extremeDebugDepth = - 1; + this.extremeDebugError = - 1; + this.boxGroup = null; + this.sphereGroup = null; + this.regionGroup = null; + + // options + this.displayBoxBounds = options.displayBoxBounds; + this.displaySphereBounds = options.displaySphereBounds; + this.displayRegionBounds = options.displayRegionBounds; + this.colorMode = options.colorMode; + this.maxDebugDepth = options.maxDebugDepth; + this.maxDebugDistance = options.maxDebugDistance; + this.maxDebugError = options.maxDebugError; + this.customColorCallback = options.customColorCallback; + + this.getDebugColor = ( value, target ) => { + + target.setRGB( value, value, value ); + + }; + + } + + // initialize the groups for displaying helpers, register events, and initialize existing tiles + init( tiles ) { + + this.tiles = tiles; + + // initialize groups + const tilesGroup = tiles.group; + this.boxGroup = new Group(); + this.boxGroup.name = 'DebugTilesRenderer.boxGroup'; + tilesGroup.add( this.boxGroup ); + this.boxGroup.updateMatrixWorld(); + + this.sphereGroup = new Group(); + this.sphereGroup.name = 'DebugTilesRenderer.sphereGroup'; + tilesGroup.add( this.sphereGroup ); + this.sphereGroup.updateMatrixWorld(); + + this.regionGroup = new Group(); + this.regionGroup.name = 'DebugTilesRenderer.regionGroup'; + tilesGroup.add( this.regionGroup ); + this.regionGroup.updateMatrixWorld(); + + // register events + this._onLoadTileSetCB = () => { + + this._initExtremes(); + + }; + + this._onLoadModelCB = ( { scene, tile } ) => { + + this._onLoadModel( scene, tile ); + + }; + + this._onDisposeModelCB = ( { tile } ) => { + + this._onDisposeModel( tile ); + + }; + + this._onUpdateAfterCB = () => { + + this._onUpdateAfter(); + + }; + + this._onTileVisibilityChangeCB = ( { scene, tile, visible } ) => { + + this._onTileVisibilityChange( tile, visible ); + + }; + + tiles.addEventListener( 'load-tile-set', this._onLoadTileSetCB ); + tiles.addEventListener( 'load-model', this._onLoadModelCB ); + tiles.addEventListener( 'dispose-model', this._onDisposeModelCB ); + tiles.addEventListener( 'update-after', this._onUpdateAfterCB ); + tiles.addEventListener( 'tile-visibility-change', this._onTileVisibilityChangeCB ); + + // initialize an already-loaded tiles + tiles.traverse( tile => { + + if ( tile.cached.scene ) { + + this._onLoadModel( tile.cached.scene, tile ); + + } + + } ); + + tiles.visibleTiles.forEach( tile => { + + this._onTileVisibilityChange( tile, true ); + + } ); + + } + + getTileInformationFromActiveObject( object ) { + + // Find which tile this scene is associated with. This is slow and + // intended for debug purposes only. + let targetTile = null; + const activeTiles = this.tiles.activeTiles; + activeTiles.forEach( tile => { + + if ( targetTile ) { + + return true; + + } + + const scene = tile.cached.scene; + if ( scene ) { + + scene.traverse( c => { + + if ( c === object ) { + + targetTile = tile; + + } + + } ); + + } + + } ); + + if ( targetTile ) { + + return { + + distanceToCamera: targetTile.__distanceFromCamera, + geometricError: targetTile.geometricError, + screenSpaceError: targetTile.__error, + depth: targetTile.__depth, + isLeaf: targetTile.__isLeaf + + }; + + } else { + + return null; + + } + + } + + _initExtremes() { + + // initialize the extreme values of the hierarchy + let maxDepth = - 1; + this.tiles.traverse( tile => { + + maxDepth = Math.max( maxDepth, tile.__depth ); + + } ); + + let maxError = - 1; + this.tiles.traverse( tile => { + + maxError = Math.max( maxError, tile.geometricError ); + + } ); + + this.extremeDebugDepth = maxDepth; + this.extremeDebugError = maxError; + + } + + _onUpdateAfter() { + + const tiles = this.tiles; + + if ( ! tiles.root ) { + + return; + + } + + // set box or sphere visibility + this.boxGroup.visible = this.displayBoxBounds; + this.sphereGroup.visible = this.displaySphereBounds; + this.regionGroup.visible = this.displayRegionBounds; + + // get max values to use for materials + let maxDepth = - 1; + if ( this.maxDebugDepth === - 1 ) { + + maxDepth = this.extremeDebugDepth; + + } else { + + maxDepth = this.maxDebugDepth; + + } + + let maxError = - 1; + if ( this.maxDebugError === - 1 ) { + + maxError = this.extremeDebugError; + + } else { + + maxError = this.maxDebugError; + + } + + let maxDistance = - 1; + if ( this.maxDebugDistance === - 1 ) { + + tiles.getBoundingSphere( _sphere ); + maxDistance = _sphere.radius; + + } else { + + maxDistance = this.maxDebugDistance; + + } + + const errorTarget = this.errorTarget; + const colorMode = this.colorMode; + const visibleTiles = tiles.visibleTiles; + let sortedTiles; + if ( colorMode === LOAD_ORDER ) { + + sortedTiles = Array.from( visibleTiles ).sort( ( a, b ) => { + + return a[ LOAD_TIME ] - b[ LOAD_TIME ]; + + } ); + + } + + // update plugins + 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 => { + + if ( colorMode === RANDOM_NODE_COLOR ) { + + h = Math.random(); + s = 0.5 + Math.random() * 0.5; + l = 0.375 + Math.random() * 0.25; + + } + + const currMaterial = c.material; + if ( currMaterial ) { + + // Reset the material if needed + const originalMaterial = c[ ORIGINAL_MATERIAL ]; + if ( colorMode === NONE && currMaterial !== originalMaterial ) { + + c.material.dispose(); + c.material = c[ ORIGINAL_MATERIAL ]; + + } else if ( colorMode !== NONE && currMaterial === originalMaterial ) { + + if ( c.isPoints ) { + + const pointsMaterial = new PointsMaterial(); + pointsMaterial.size = originalMaterial.size; + pointsMaterial.sizeAttenuation = originalMaterial.sizeAttenuation; + c.material = pointsMaterial; + + } else { + + c.material = new MeshStandardMaterial(); + c.material.flatShading = true; + + } + + } + + if ( colorMode !== RANDOM_COLOR ) { + + delete c.material[ HAS_RANDOM_COLOR ]; + + } + + if ( colorMode !== RANDOM_NODE_COLOR ) { + + delete c.material[ HAS_RANDOM_NODE_COLOR ]; + + } + + // Set the color on the basic material + switch ( colorMode ) { + + case DEPTH: { + + const val = tile.__depth / maxDepth; + this.getDebugColor( val, c.material.color ); + break; + + } + case RELATIVE_DEPTH: { + + const val = tile.__depthFromRenderedParent / maxDepth; + this.getDebugColor( val, c.material.color ); + break; + + } + case SCREEN_ERROR: { + + const val = tile.__error / errorTarget; + if ( val > 1.0 ) { + + c.material.color.setRGB( 1.0, 0.0, 0.0 ); + + } else { + + this.getDebugColor( val, c.material.color ); + + } + break; + + } + case GEOMETRIC_ERROR: { + + const val = Math.min( tile.geometricError / maxError, 1 ); + this.getDebugColor( val, c.material.color ); + break; + + } + case DISTANCE: { + + // We don't update the distance if the geometric error is 0.0 so + // it will always be black. + const val = Math.min( tile.__distanceFromCamera / maxDistance, 1 ); + this.getDebugColor( val, c.material.color ); + break; + + } + case IS_LEAF: { + + if ( ! tile.children || tile.children.length === 0 ) { + + this.getDebugColor( 1.0, c.material.color ); + + } else { + + this.getDebugColor( 0.0, c.material.color ); + + } + break; + + } + case RANDOM_NODE_COLOR: { + + if ( ! c.material[ HAS_RANDOM_NODE_COLOR ] ) { + + c.material.color.setHSL( h, s, l ); + c.material[ HAS_RANDOM_NODE_COLOR ] = true; + + } + break; + + } + case RANDOM_COLOR: { + + if ( ! c.material[ HAS_RANDOM_COLOR ] ) { + + c.material.color.setHSL( h, s, l ); + c.material[ HAS_RANDOM_COLOR ] = true; + + } + break; + + } + case CUSTOM_COLOR: { + + if ( this.customColorCallback ) { + + this.customColorCallback( tile, c ); + + } else { + + console.warn( 'DebugTilesRenderer: customColorCallback not defined' ); + + } + break; + + } + case LOAD_ORDER: { + + const value = sortedTiles.indexOf( tile ); + this.getDebugColor( value / ( sortedTiles.length - 1 ), c.material.color ); + break; + + } + + } + + } + + } ); + + } ); + + } + + _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 ( regionHelper ) { + + regionGroup.remove( regionHelper ); + + } + + } else { + + if ( boxHelperGroup ) { + + boxGroup.add( boxHelperGroup ); + boxHelperGroup.updateMatrixWorld( true ); + + } + + if ( sphereHelper ) { + + sphereGroup.add( sphereHelper ); + sphereHelper.updateMatrixWorld( true ); + + } + + if ( regionHelper ) { + + regionGroup.add( regionHelper ); + regionHelper.updateMatrixWorld( true ); + + } + + } + + } + + _onLoadModel( scene, tile ) { + + tile[ LOAD_TIME ] = performance.now(); + + const tiles = this.tiles; + const cached = tile.cached; + const { sphere, obb, region } = cached.boundingVolume; + if ( obb ) { + + // Create debug bounding box + // In some cases the bounding box may have a scale of 0 in one dimension resulting + // in the NaNs in an extracted rotation so we disable matrix updates instead. + const boxHelperGroup = new Group(); + boxHelperGroup.name = 'DebugTilesRenderer.boxHelperGroup'; + boxHelperGroup.matrix.copy( obb.transform ); + boxHelperGroup.matrixAutoUpdate = false; + + const boxHelper = new Box3Helper( obb.box, getIndexedRandomColor( tile.__depth ) ); + boxHelper.raycast = emptyRaycast; + boxHelperGroup.add( boxHelper ); + + cached.boxHelperGroup = boxHelperGroup; + + if ( tiles.visibleTiles.has( tile ) && this.displayBoxBounds ) { + + this.boxGroup.add( boxHelperGroup ); + boxHelperGroup.updateMatrixWorld( true ); + + } + + } + + if ( sphere ) { + + // Create debug bounding sphere + const sphereHelper = new SphereHelper( sphere, getIndexedRandomColor( tile.__depth ) ); + sphereHelper.raycast = emptyRaycast; + cached.sphereHelper = sphereHelper; + + if ( tiles.visibleTiles.has( tile ) && this.displaySphereBounds ) { + + this.sphereGroup.add( sphereHelper ); + sphereHelper.updateMatrixWorld( true ); + + } + + } + + if ( region ) { + + // Create debug bounding region + const regionHelper = new EllipsoidRegionLineHelper( region, getIndexedRandomColor( tile.__depth ) ); + regionHelper.raycast = emptyRaycast; + + // recenter the geometry to avoid rendering artifacts + const sphere = new Sphere(); + region.getBoundingSphere( sphere ); + regionHelper.position.copy( sphere.center ); + + sphere.center.multiplyScalar( - 1 ); + regionHelper.geometry.translate( ...sphere.center ); + + cached.regionHelper = regionHelper; + + if ( tiles.visibleTiles.has( tile ) && this.displayRegionBounds ) { + + this.regionGroup.add( regionHelper ); + regionHelper.updateMatrixWorld( true ); + + } + + } + + // Cache the original materials + scene.traverse( c => { + + const material = c.material; + if ( material ) { + + c[ ORIGINAL_MATERIAL ] = material; + + } + + } ); + + } + + _onDisposeModel( tile ) { + + const cached = tile.cached; + if ( cached.boxHelperGroup ) { + + cached.boxHelperGroup.children[ 0 ].geometry.dispose(); + delete cached.boxHelperGroup; + + } + + if ( cached.sphereHelper ) { + + cached.sphereHelper.geometry.dispose(); + delete cached.sphereHelper; + + } + + if ( cached.regionHelper ) { + + cached.regionHelper.geometry.dispose(); + delete cached.regionHelper; + + } + + } + + dispose() { + + const tiles = this.tiles; + tiles.removeEventListener( 'load-tile-set', this._onLoadTileSetCB ); + tiles.removeEventListener( 'load-model', this._onLoadModelCB ); + tiles.removeEventListener( 'dispose-model', this._onDisposeModelCB ); + tiles.removeEventListener( 'update-after', this._onUpdateAfterCB ); + + // reset all materials + this.colorMode = NONE; + this._onUpdateAfter(); + + // dispose of all helper objects + tiles.traverse( tile => { + + this._onDisposeModel( tile ); + + } ); + + this.boxGroup.removeFromParent(); + this.sphereGroup.removeFromParent(); + this.regionGroup.removeFromParent(); + + } + +} diff --git a/src/plugins/three/GoogleAttributionsManager.js b/src/plugins/three/GoogleAttributionsManager.js new file mode 100644 index 000000000..2f07e6c2b --- /dev/null +++ b/src/plugins/three/GoogleAttributionsManager.js @@ -0,0 +1,62 @@ +export class GoogleAttributionsManager { + + constructor() { + + this.creditsCount = {}; + + } + + _adjustAttributions( line, add ) { + + const creditsCount = this.creditsCount; + const tokens = line.split( /;/g ); + for ( let i = 0, l = tokens.length; i < l; i ++ ) { + + const t = tokens[ i ]; + if ( ! ( t in creditsCount ) ) { + + creditsCount[ t ] = 0; + + } + + creditsCount[ t ] += add ? 1 : - 1; + + if ( creditsCount[ t ] <= 0 ) { + + delete creditsCount[ t ]; + + } + + } + + } + + addAttributions( line ) { + + this._adjustAttributions( line, true ); + + } + + removeAttributions( line ) { + + this._adjustAttributions( line, false ); + + } + + toString() { + + // attribution guidelines: https://developers.google.com/maps/documentation/tile/create-renderer#display-attributions + + const sortedByCount = Object.entries( this.creditsCount ).sort( ( a, b ) => { + + const countA = a[ 1 ]; + const countB = b[ 1 ]; + return countB - countA; // Descending order + + } ); + + return sortedByCount.map( pair => pair[ 0 ] ).join( '; ' ); + + } + +} diff --git a/src/plugins/three/GoogleCloudAuthPlugin.d.ts b/src/plugins/three/GoogleCloudAuthPlugin.d.ts new file mode 100644 index 000000000..9e5e078bf --- /dev/null +++ b/src/plugins/three/GoogleCloudAuthPlugin.d.ts @@ -0,0 +1,5 @@ +export class GoogleCloudAuthPlugin { + + constructor( options : { apiToken: String, autoRefreshToken?: Boolean } ); + +} diff --git a/src/plugins/three/GoogleCloudAuthPlugin.js b/src/plugins/three/GoogleCloudAuthPlugin.js new file mode 100644 index 000000000..ce12c6a23 --- /dev/null +++ b/src/plugins/three/GoogleCloudAuthPlugin.js @@ -0,0 +1,197 @@ +import { traverseSet } from '../../base/traverseFunctions.js'; +import { GoogleAttributionsManager } from './GoogleAttributionsManager.js'; + +function getSessionToken( root ) { + + let sessionToken = null; + traverseSet( root, tile => { + + if ( tile.content && tile.content.uri ) { + + const [ , params ] = tile.content.uri.split( '?' ); + sessionToken = new URLSearchParams( params ).get( 'session' ); + return true; + + } + + return false; + + } ); + + return sessionToken; + +} + +export class GoogleCloudAuthPlugin { + + constructor( { apiToken, autoRefreshToken = false, logoUrl = null, useRecommendedSettings = true } ) { + + this.name = 'GOOGLE_CLOUD_AUTH_PLUGIN'; + this.apiToken = apiToken; + this.autoRefreshToken = autoRefreshToken; + this.useRecommendedSettings = useRecommendedSettings; + this.logoUrl = logoUrl; + this.sessionToken = null; + this.tiles = null; + + this._onLoadCallback = null; + this._visibilityChangeCallback = null; + this._tokenRefreshPromise = null; + this._attributionsManager = new GoogleAttributionsManager(); + this._logoAttribution = { + value: '', + type: 'image', + collapsible: false, + }; + this._attribution = { + value: '', + type: 'string', + collapsible: true, + }; + + } + + init( tiles ) { + + if ( tiles == null ) { + + return; + + } + + if ( tiles.rootURL == null ) { + + tiles.rootURL = 'https://tile.googleapis.com/v1/3dtiles/root.json'; + + } + + if ( this.useRecommendedSettings ) { + + // This plugin changes below values to be more efficient for the photorealistic tiles + tiles.parseQueue.maxJobs = 10; + tiles.downloadQueue.maxJobs = 30; + tiles.errorTarget = 40; + + } + + this.tiles = tiles; + this._onLoadCallback = ( { tileSet } ) => { + + // the first tile set loaded will be the root + this.sessionToken = getSessionToken( tileSet.root ); + + // clear the callback once the root is loaded + tiles.removeEventListener( 'load-tile-set', this._onLoadCallback ); + + }; + + this._visibilityChangeCallback = ( { tile, visible } ) => { + + const copyright = tile.cached.metadata.asset.copyright || ''; + if ( visible ) { + + this._attributionsManager.addAttributions( copyright ); + + } else { + + this._attributionsManager.removeAttributions( copyright ); + + } + + }; + + tiles.addEventListener( 'load-tile-set', this._onLoadCallback ); + tiles.addEventListener( 'tile-visibility-change', this._visibilityChangeCallback ); + + } + + getAttributions( target ) { + + if ( this.tiles.visibleTiles.size > 0 ) { + + if ( this.logoUrl ) { + + this._logoAttribution.value = this.logoUrl; + target.push( this._logoAttribution ); + + } + + this._attribution.value = this._attributionsManager.toString(); + target.push( this._attribution ); + + } + + } + + preprocessURL( uri ) { + + uri = new URL( uri ); + if ( /^http/.test( uri.protocol ) ) { + + uri.searchParams.append( 'key', this.apiToken ); + if ( this.sessionToken !== null ) { + + uri.searchParams.append( 'session', this.sessionToken ); + + } + + } + return uri.toString(); + + } + + dispose() { + + const { tiles } = this; + tiles.removeEventListener( 'load-tile-set', this._onLoadCallback ); + tiles.removeEventListener( 'tile-visibility-change', this._visibilityChangeCallback ); + + } + + async fetchData( uri, options ) { + + // wait for the token to refresh if loading + if ( this._tokenRefreshPromise !== null ) { + + await this._tokenRefreshPromise; + uri = this.preprocessURL( uri ); + + } + + const res = await fetch( uri, options ); + if ( res.status >= 400 && res.status <= 499 && this.autoRefreshToken ) { + + await this._refreshToken( options ); + return fetch( this.preprocessURL( uri ), options ); + + } else { + + return res; + + } + + } + + _refreshToken( options ) { + + if ( this._tokenRefreshPromise === null ) { + + // refetch the root if the token has expired + const rootURL = new URL( this.tiles.rootURL ); + rootURL.searchParams.append( 'key', this.apiToken ); + this._tokenRefreshPromise = fetch( rootURL, options ) + .then( res => res.json() ) + .then( res => { + + this.sessionToken = getSessionToken( res.root ); + this._tokenRefreshPromise = null; + + } ); + + } + + return this._tokenRefreshPromise; + + } + +} From 84df464f360d03f7e58c4a42af61c0741def4d58 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Fri, 1 Nov 2024 21:37:44 +0900 Subject: [PATCH 02/10] Add subclasses --- src/base/plugins/ImplicitTilingPlugin.js | 2 +- src/three/plugins/CesiumIonAuthPlugin.d.ts | 9 - src/three/plugins/CesiumIonAuthPlugin.js | 170 +---- src/three/plugins/DebugTilesPlugin.d.ts | 29 - src/three/plugins/DebugTilesPlugin.js | 675 +----------------- .../plugins/GoogleAttributionsManager.js | 62 -- src/three/plugins/GoogleCloudAuthPlugin.d.ts | 5 - src/three/plugins/GoogleCloudAuthPlugin.js | 195 +---- 8 files changed, 16 insertions(+), 1131 deletions(-) delete mode 100644 src/three/plugins/CesiumIonAuthPlugin.d.ts delete mode 100644 src/three/plugins/DebugTilesPlugin.d.ts delete mode 100644 src/three/plugins/GoogleAttributionsManager.js delete mode 100644 src/three/plugins/GoogleCloudAuthPlugin.d.ts diff --git a/src/base/plugins/ImplicitTilingPlugin.js b/src/base/plugins/ImplicitTilingPlugin.js index 7d2475dbc..d8d6054e6 100644 --- a/src/base/plugins/ImplicitTilingPlugin.js +++ b/src/base/plugins/ImplicitTilingPlugin.js @@ -5,7 +5,7 @@ export class ImplicitTilingPlugin extends ImplicitTilingPluginImpl { constructor() { super(); - console.warn( 'ImplicitTilingPlugin: Plugin should now be imported from "3d-tiles-renderer/plugins" path.' ); + console.warn( 'ImplicitTilingPlugin: Plugins should now be imported from "3d-tiles-renderer/plugins" path.' ); } diff --git a/src/three/plugins/CesiumIonAuthPlugin.d.ts b/src/three/plugins/CesiumIonAuthPlugin.d.ts deleted file mode 100644 index 314dd639f..000000000 --- a/src/three/plugins/CesiumIonAuthPlugin.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -export class CesiumIonAuthPlugin { - - constructor( options : { - apiToken: String, - assetId?: String | null, - autoRefreshToken?: Boolean - } ); - -} diff --git a/src/three/plugins/CesiumIonAuthPlugin.js b/src/three/plugins/CesiumIonAuthPlugin.js index c04fe9839..002a8fed4 100644 --- a/src/three/plugins/CesiumIonAuthPlugin.js +++ b/src/three/plugins/CesiumIonAuthPlugin.js @@ -1,171 +1,11 @@ -import { GoogleCloudAuthPlugin } from './GoogleCloudAuthPlugin.js'; +import { CesiumIonAuthPlugin as CesiumIonAuthPluginImpl } from '../../plugins/index.js'; -export class CesiumIonAuthPlugin { +export class CesiumIonAuthPlugin extends CesiumIonAuthPluginImpl { - constructor( { apiToken, assetId = null, autoRefreshToken = false } ) { + constructor( ...args ) { - this.name = 'CESIUM_ION_AUTH_PLUGIN'; - this.apiToken = apiToken; - this.assetId = assetId; - this.autoRefreshToken = autoRefreshToken; - this.tiles = null; - this.endpointURL = null; - - this._bearerToken = null; - this._tileSetVersion = - 1; - this._tokenRefreshPromise = null; - this._attributions = []; - - } - - init( tiles ) { - - if ( this.assetId !== null ) { - - tiles.rootURL = `https://api.cesium.com/v1/assets/${ this.assetId }/endpoint`; - - } - - this.tiles = tiles; - this.endpointURL = tiles.rootURL; - - } - - loadRootTileSet() { - - // ensure we have an up-to-date token and root url, then trigger the internal - // root tile set load function - return this._refreshToken() - .then( () => this.tiles.loadRootTileSet() ); - - } - - preprocessURL( uri ) { - - uri = new URL( uri ); - if ( /^http/.test( uri.protocol ) && this._tileSetVersion != - 1 ) { - - uri.searchParams.append( 'v', this._tileSetVersion ); - - } - return uri.toString(); - - } - - fetchData( uri, options ) { - - const tiles = this.tiles; - if ( tiles.getPluginByName( 'GOOGLE_CLOUD_AUTH_PLUGIN' ) !== null ) { - - return null; - - } else { - - return Promise.resolve().then( async () => { - - // wait for the token to refresh if loading - if ( this._tokenRefreshPromise !== null ) { - - await this._tokenRefreshPromise; - uri = this.preprocessURL( uri ); - - } - - const res = await fetch( uri, options ); - if ( res.status >= 400 && res.status <= 499 && this.autoRefreshToken ) { - - await this._refreshToken( options ); - return fetch( this.preprocessURL( uri ), options ); - - } else { - - return res; - - } - - } ); - - } - - } - - getAttributions( target ) { - - if ( this.tiles.visibleTiles.size > 0 ) { - - target.push( ...this._attributions ); - - } - - } - - _refreshToken( options ) { - - if ( this._tokenRefreshPromise === null ) { - - // construct the url to fetch the endpoint - const url = new URL( this.endpointURL ); - url.searchParams.append( 'access_token', this.apiToken ); - - this._tokenRefreshPromise = fetch( url, options ) - .then( res => { - - if ( ! res.ok ) { - - throw new Error( `CesiumIonAuthPlugin: Failed to load data with error code ${ res.status }` ); - - } - - return res.json(); - - } ) - .then( json => { - - const tiles = this.tiles; - if ( 'externalType' in json ) { - - const url = new URL( json.options.url ); - tiles.rootURL = json.options.url; - - // if the tile set is "external" then assume it's a google API tile set - tiles.registerPlugin( new GoogleCloudAuthPlugin( { apiToken: url.searchParams.get( 'key' ) } ) ); - - } else { - - tiles.rootURL = json.url; - tiles.fetchOptions.headers = tiles.fetchOptions.headers || {}; - tiles.fetchOptions.headers.Authorization = `Bearer ${ json.accessToken }`; - - // save the version key if present - if ( url.searchParams.has( 'v' ) && this._tileSetVersion === - 1 ) { - - const url = new URL( json.url ); - this._tileSetVersion = url.searchParams.get( 'v' ); - - } - - this._bearerToken = json.accessToken; - if ( json.attributions ) { - - this._attributions = json.attributions.map( att => ( { - value: att.html, - type: 'html', - collapsible: att.collapsible, - } ) ); - - } - - } - - this._tokenRefreshPromise = null; - - return json; - - } ); - - } - - return this._tokenRefreshPromise; + super( ...args ); + console.warn( 'CesiumIonAuthPlugin: Plugins should now be imported from "3d-tiles-renderer/plugins" path.' ); } diff --git a/src/three/plugins/DebugTilesPlugin.d.ts b/src/three/plugins/DebugTilesPlugin.d.ts deleted file mode 100644 index 06efbed0a..000000000 --- a/src/three/plugins/DebugTilesPlugin.d.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Tile } from '../../base/Tile'; -import { Color } from 'three'; - -export enum ColorMode {} -export const NONE : ColorMode; -export const SCREEN_ERROR : ColorMode; -export const GEOMETRIC_ERROR : ColorMode; -export const DISTANCE : ColorMode; -export const DEPTH : ColorMode; -export const RELATIVE_DEPTH : ColorMode; -export const IS_LEAF : ColorMode; -export const RANDOM_COLOR : ColorMode; -export const RANDOM_NODE_COLOR: ColorMode; -export const CUSTOM_COLOR: ColorMode; -export class DebugTilesPlugin { - - displayBoxBounds : Boolean; - displaySphereBounds : Boolean; - displayRegionBounds : Boolean; - colorMode : ColorMode; - - maxDebugDepth : Number; - maxDebugDistance : Number; - maxDebugError : Number; - - getDebugColor : ( val: Number, target: Color ) => void; - customColorCallback : ( val: Tile, target: Color ) => void; - -} diff --git a/src/three/plugins/DebugTilesPlugin.js b/src/three/plugins/DebugTilesPlugin.js index 920d2f336..71c272253 100644 --- a/src/three/plugins/DebugTilesPlugin.js +++ b/src/three/plugins/DebugTilesPlugin.js @@ -1,676 +1,11 @@ -import { Box3Helper, Group, MeshStandardMaterial, PointsMaterial, Sphere, Color } from 'three'; -import { SphereHelper } from '../objects/SphereHelper.js'; -import { EllipsoidRegionLineHelper } from '../objects/EllipsoidRegionHelper.js'; +import { DebugTilesPlugin as DebugTilesPluginImpl } from '../../plugins/three/DebugTilesPlugin.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' ); +export class DebugTilesPlugin extends DebugTilesPluginImpl { -const _sphere = /* @__PURE__ */ new Sphere(); -const emptyRaycast = () => {}; -const colors = {}; + constructor( ...args ) { -// Return a consistant random color for an index -export function getIndexedRandomColor( index ) { - - if ( ! colors[ index ] ) { - - const h = Math.random(); - const s = 0.5 + Math.random() * 0.5; - const l = 0.375 + Math.random() * 0.25; - - colors[ index ] = new Color().setHSL( h, s, l ); - - } - return colors[ index ]; - -} - -// color modes -export const NONE = 0; -export const SCREEN_ERROR = 1; -export const GEOMETRIC_ERROR = 2; -export const DISTANCE = 3; -export const DEPTH = 4; -export const RELATIVE_DEPTH = 5; -export const IS_LEAF = 6; -export const RANDOM_COLOR = 7; -export const RANDOM_NODE_COLOR = 8; -export const CUSTOM_COLOR = 9; -export const LOAD_ORDER = 10; - -export class DebugTilesPlugin { - - constructor( options ) { - - options = { - displayBoxBounds: false, - displaySphereBounds: false, - displayRegionBounds: false, - colorMode: NONE, - maxDebugDepth: - 1, - maxDebugDistance: - 1, - maxDebugError: - 1, - customColorCallback: null, - ...options, - }; - - this.name = 'DEBUG_TILES_PLUGIN'; - this.tiles = null; - - this.extremeDebugDepth = - 1; - this.extremeDebugError = - 1; - this.boxGroup = null; - this.sphereGroup = null; - this.regionGroup = null; - - // options - this.displayBoxBounds = options.displayBoxBounds; - this.displaySphereBounds = options.displaySphereBounds; - this.displayRegionBounds = options.displayRegionBounds; - this.colorMode = options.colorMode; - this.maxDebugDepth = options.maxDebugDepth; - this.maxDebugDistance = options.maxDebugDistance; - this.maxDebugError = options.maxDebugError; - this.customColorCallback = options.customColorCallback; - - this.getDebugColor = ( value, target ) => { - - target.setRGB( value, value, value ); - - }; - - } - - // initialize the groups for displaying helpers, register events, and initialize existing tiles - init( tiles ) { - - this.tiles = tiles; - - // initialize groups - const tilesGroup = tiles.group; - this.boxGroup = new Group(); - this.boxGroup.name = 'DebugTilesRenderer.boxGroup'; - tilesGroup.add( this.boxGroup ); - this.boxGroup.updateMatrixWorld(); - - this.sphereGroup = new Group(); - this.sphereGroup.name = 'DebugTilesRenderer.sphereGroup'; - tilesGroup.add( this.sphereGroup ); - this.sphereGroup.updateMatrixWorld(); - - this.regionGroup = new Group(); - this.regionGroup.name = 'DebugTilesRenderer.regionGroup'; - tilesGroup.add( this.regionGroup ); - this.regionGroup.updateMatrixWorld(); - - // register events - this._onLoadTileSetCB = () => { - - this._initExtremes(); - - }; - - this._onLoadModelCB = ( { scene, tile } ) => { - - this._onLoadModel( scene, tile ); - - }; - - this._onDisposeModelCB = ( { tile } ) => { - - this._onDisposeModel( tile ); - - }; - - this._onUpdateAfterCB = () => { - - this._onUpdateAfter(); - - }; - - this._onTileVisibilityChangeCB = ( { scene, tile, visible } ) => { - - this._onTileVisibilityChange( tile, visible ); - - }; - - tiles.addEventListener( 'load-tile-set', this._onLoadTileSetCB ); - tiles.addEventListener( 'load-model', this._onLoadModelCB ); - tiles.addEventListener( 'dispose-model', this._onDisposeModelCB ); - tiles.addEventListener( 'update-after', this._onUpdateAfterCB ); - tiles.addEventListener( 'tile-visibility-change', this._onTileVisibilityChangeCB ); - - // initialize an already-loaded tiles - tiles.traverse( tile => { - - if ( tile.cached.scene ) { - - this._onLoadModel( tile.cached.scene, tile ); - - } - - } ); - - tiles.visibleTiles.forEach( tile => { - - this._onTileVisibilityChange( tile, true ); - - } ); - - } - - getTileInformationFromActiveObject( object ) { - - // Find which tile this scene is associated with. This is slow and - // intended for debug purposes only. - let targetTile = null; - const activeTiles = this.tiles.activeTiles; - activeTiles.forEach( tile => { - - if ( targetTile ) { - - return true; - - } - - const scene = tile.cached.scene; - if ( scene ) { - - scene.traverse( c => { - - if ( c === object ) { - - targetTile = tile; - - } - - } ); - - } - - } ); - - if ( targetTile ) { - - return { - - distanceToCamera: targetTile.__distanceFromCamera, - geometricError: targetTile.geometricError, - screenSpaceError: targetTile.__error, - depth: targetTile.__depth, - isLeaf: targetTile.__isLeaf - - }; - - } else { - - return null; - - } - - } - - _initExtremes() { - - // initialize the extreme values of the hierarchy - let maxDepth = - 1; - this.tiles.traverse( tile => { - - maxDepth = Math.max( maxDepth, tile.__depth ); - - } ); - - let maxError = - 1; - this.tiles.traverse( tile => { - - maxError = Math.max( maxError, tile.geometricError ); - - } ); - - this.extremeDebugDepth = maxDepth; - this.extremeDebugError = maxError; - - } - - _onUpdateAfter() { - - const tiles = this.tiles; - - if ( ! tiles.root ) { - - return; - - } - - // set box or sphere visibility - this.boxGroup.visible = this.displayBoxBounds; - this.sphereGroup.visible = this.displaySphereBounds; - this.regionGroup.visible = this.displayRegionBounds; - - // get max values to use for materials - let maxDepth = - 1; - if ( this.maxDebugDepth === - 1 ) { - - maxDepth = this.extremeDebugDepth; - - } else { - - maxDepth = this.maxDebugDepth; - - } - - let maxError = - 1; - if ( this.maxDebugError === - 1 ) { - - maxError = this.extremeDebugError; - - } else { - - maxError = this.maxDebugError; - - } - - let maxDistance = - 1; - if ( this.maxDebugDistance === - 1 ) { - - tiles.getBoundingSphere( _sphere ); - maxDistance = _sphere.radius; - - } else { - - maxDistance = this.maxDebugDistance; - - } - - const errorTarget = this.errorTarget; - const colorMode = this.colorMode; - const visibleTiles = tiles.visibleTiles; - let sortedTiles; - if ( colorMode === LOAD_ORDER ) { - - sortedTiles = Array.from( visibleTiles ).sort( ( a, b ) => { - - return a[ LOAD_TIME ] - b[ LOAD_TIME ]; - - } ); - - } - - // update plugins - 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 => { - - if ( colorMode === RANDOM_NODE_COLOR ) { - - h = Math.random(); - s = 0.5 + Math.random() * 0.5; - l = 0.375 + Math.random() * 0.25; - - } - - const currMaterial = c.material; - if ( currMaterial ) { - - // Reset the material if needed - const originalMaterial = c[ ORIGINAL_MATERIAL ]; - if ( colorMode === NONE && currMaterial !== originalMaterial ) { - - c.material.dispose(); - c.material = c[ ORIGINAL_MATERIAL ]; - - } else if ( colorMode !== NONE && currMaterial === originalMaterial ) { - - if ( c.isPoints ) { - - const pointsMaterial = new PointsMaterial(); - pointsMaterial.size = originalMaterial.size; - pointsMaterial.sizeAttenuation = originalMaterial.sizeAttenuation; - c.material = pointsMaterial; - - } else { - - c.material = new MeshStandardMaterial(); - c.material.flatShading = true; - - } - - } - - if ( colorMode !== RANDOM_COLOR ) { - - delete c.material[ HAS_RANDOM_COLOR ]; - - } - - if ( colorMode !== RANDOM_NODE_COLOR ) { - - delete c.material[ HAS_RANDOM_NODE_COLOR ]; - - } - - // Set the color on the basic material - switch ( colorMode ) { - - case DEPTH: { - - const val = tile.__depth / maxDepth; - this.getDebugColor( val, c.material.color ); - break; - - } - case RELATIVE_DEPTH: { - - const val = tile.__depthFromRenderedParent / maxDepth; - this.getDebugColor( val, c.material.color ); - break; - - } - case SCREEN_ERROR: { - - const val = tile.__error / errorTarget; - if ( val > 1.0 ) { - - c.material.color.setRGB( 1.0, 0.0, 0.0 ); - - } else { - - this.getDebugColor( val, c.material.color ); - - } - break; - - } - case GEOMETRIC_ERROR: { - - const val = Math.min( tile.geometricError / maxError, 1 ); - this.getDebugColor( val, c.material.color ); - break; - - } - case DISTANCE: { - - // We don't update the distance if the geometric error is 0.0 so - // it will always be black. - const val = Math.min( tile.__distanceFromCamera / maxDistance, 1 ); - this.getDebugColor( val, c.material.color ); - break; - - } - case IS_LEAF: { - - if ( ! tile.children || tile.children.length === 0 ) { - - this.getDebugColor( 1.0, c.material.color ); - - } else { - - this.getDebugColor( 0.0, c.material.color ); - - } - break; - - } - case RANDOM_NODE_COLOR: { - - if ( ! c.material[ HAS_RANDOM_NODE_COLOR ] ) { - - c.material.color.setHSL( h, s, l ); - c.material[ HAS_RANDOM_NODE_COLOR ] = true; - - } - break; - - } - case RANDOM_COLOR: { - - if ( ! c.material[ HAS_RANDOM_COLOR ] ) { - - c.material.color.setHSL( h, s, l ); - c.material[ HAS_RANDOM_COLOR ] = true; - - } - break; - - } - case CUSTOM_COLOR: { - - if ( this.customColorCallback ) { - - this.customColorCallback( tile, c ); - - } else { - - console.warn( 'DebugTilesRenderer: customColorCallback not defined' ); - - } - break; - - } - case LOAD_ORDER: { - - const value = sortedTiles.indexOf( tile ); - this.getDebugColor( value / ( sortedTiles.length - 1 ), c.material.color ); - break; - - } - - } - - } - - } ); - - } ); - - } - - _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 ( regionHelper ) { - - regionGroup.remove( regionHelper ); - - } - - } else { - - if ( boxHelperGroup ) { - - boxGroup.add( boxHelperGroup ); - boxHelperGroup.updateMatrixWorld( true ); - - } - - if ( sphereHelper ) { - - sphereGroup.add( sphereHelper ); - sphereHelper.updateMatrixWorld( true ); - - } - - if ( regionHelper ) { - - regionGroup.add( regionHelper ); - regionHelper.updateMatrixWorld( true ); - - } - - } - - } - - _onLoadModel( scene, tile ) { - - tile[ LOAD_TIME ] = performance.now(); - - const tiles = this.tiles; - const cached = tile.cached; - const { sphere, obb, region } = cached.boundingVolume; - if ( obb ) { - - // Create debug bounding box - // In some cases the bounding box may have a scale of 0 in one dimension resulting - // in the NaNs in an extracted rotation so we disable matrix updates instead. - const boxHelperGroup = new Group(); - boxHelperGroup.name = 'DebugTilesRenderer.boxHelperGroup'; - boxHelperGroup.matrix.copy( obb.transform ); - boxHelperGroup.matrixAutoUpdate = false; - - const boxHelper = new Box3Helper( obb.box, getIndexedRandomColor( tile.__depth ) ); - boxHelper.raycast = emptyRaycast; - boxHelperGroup.add( boxHelper ); - - cached.boxHelperGroup = boxHelperGroup; - - if ( tiles.visibleTiles.has( tile ) && this.displayBoxBounds ) { - - this.boxGroup.add( boxHelperGroup ); - boxHelperGroup.updateMatrixWorld( true ); - - } - - } - - if ( sphere ) { - - // Create debug bounding sphere - const sphereHelper = new SphereHelper( sphere, getIndexedRandomColor( tile.__depth ) ); - sphereHelper.raycast = emptyRaycast; - cached.sphereHelper = sphereHelper; - - if ( tiles.visibleTiles.has( tile ) && this.displaySphereBounds ) { - - this.sphereGroup.add( sphereHelper ); - sphereHelper.updateMatrixWorld( true ); - - } - - } - - if ( region ) { - - // Create debug bounding region - const regionHelper = new EllipsoidRegionLineHelper( region, getIndexedRandomColor( tile.__depth ) ); - regionHelper.raycast = emptyRaycast; - - // recenter the geometry to avoid rendering artifacts - const sphere = new Sphere(); - region.getBoundingSphere( sphere ); - regionHelper.position.copy( sphere.center ); - - sphere.center.multiplyScalar( - 1 ); - regionHelper.geometry.translate( ...sphere.center ); - - cached.regionHelper = regionHelper; - - if ( tiles.visibleTiles.has( tile ) && this.displayRegionBounds ) { - - this.regionGroup.add( regionHelper ); - regionHelper.updateMatrixWorld( true ); - - } - - } - - // Cache the original materials - scene.traverse( c => { - - const material = c.material; - if ( material ) { - - c[ ORIGINAL_MATERIAL ] = material; - - } - - } ); - - } - - _onDisposeModel( tile ) { - - const cached = tile.cached; - if ( cached.boxHelperGroup ) { - - cached.boxHelperGroup.children[ 0 ].geometry.dispose(); - delete cached.boxHelperGroup; - - } - - if ( cached.sphereHelper ) { - - cached.sphereHelper.geometry.dispose(); - delete cached.sphereHelper; - - } - - if ( cached.regionHelper ) { - - cached.regionHelper.geometry.dispose(); - delete cached.regionHelper; - - } - - } - - dispose() { - - const tiles = this.tiles; - tiles.removeEventListener( 'load-tile-set', this._onLoadTileSetCB ); - tiles.removeEventListener( 'load-model', this._onLoadModelCB ); - tiles.removeEventListener( 'dispose-model', this._onDisposeModelCB ); - tiles.removeEventListener( 'update-after', this._onUpdateAfterCB ); - - // reset all materials - this.colorMode = NONE; - this._onUpdateAfter(); - - // dispose of all helper objects - tiles.traverse( tile => { - - this._onDisposeModel( tile ); - - } ); - - this.boxGroup.removeFromParent(); - this.sphereGroup.removeFromParent(); - this.regionGroup.removeFromParent(); + super( ...args ); + console.warn( 'DebugTilesPlugin: Plugins should now be imported from "3d-tiles-renderer/plugins" path.' ); } diff --git a/src/three/plugins/GoogleAttributionsManager.js b/src/three/plugins/GoogleAttributionsManager.js deleted file mode 100644 index 2f07e6c2b..000000000 --- a/src/three/plugins/GoogleAttributionsManager.js +++ /dev/null @@ -1,62 +0,0 @@ -export class GoogleAttributionsManager { - - constructor() { - - this.creditsCount = {}; - - } - - _adjustAttributions( line, add ) { - - const creditsCount = this.creditsCount; - const tokens = line.split( /;/g ); - for ( let i = 0, l = tokens.length; i < l; i ++ ) { - - const t = tokens[ i ]; - if ( ! ( t in creditsCount ) ) { - - creditsCount[ t ] = 0; - - } - - creditsCount[ t ] += add ? 1 : - 1; - - if ( creditsCount[ t ] <= 0 ) { - - delete creditsCount[ t ]; - - } - - } - - } - - addAttributions( line ) { - - this._adjustAttributions( line, true ); - - } - - removeAttributions( line ) { - - this._adjustAttributions( line, false ); - - } - - toString() { - - // attribution guidelines: https://developers.google.com/maps/documentation/tile/create-renderer#display-attributions - - const sortedByCount = Object.entries( this.creditsCount ).sort( ( a, b ) => { - - const countA = a[ 1 ]; - const countB = b[ 1 ]; - return countB - countA; // Descending order - - } ); - - return sortedByCount.map( pair => pair[ 0 ] ).join( '; ' ); - - } - -} diff --git a/src/three/plugins/GoogleCloudAuthPlugin.d.ts b/src/three/plugins/GoogleCloudAuthPlugin.d.ts deleted file mode 100644 index 9e5e078bf..000000000 --- a/src/three/plugins/GoogleCloudAuthPlugin.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -export class GoogleCloudAuthPlugin { - - constructor( options : { apiToken: String, autoRefreshToken?: Boolean } ); - -} diff --git a/src/three/plugins/GoogleCloudAuthPlugin.js b/src/three/plugins/GoogleCloudAuthPlugin.js index ce12c6a23..f94988d07 100644 --- a/src/three/plugins/GoogleCloudAuthPlugin.js +++ b/src/three/plugins/GoogleCloudAuthPlugin.js @@ -1,196 +1,11 @@ -import { traverseSet } from '../../base/traverseFunctions.js'; -import { GoogleAttributionsManager } from './GoogleAttributionsManager.js'; +import { GoogleCloudAuthPlugin as GoogleCloudAuthPluginImpl } from '../../plugins/index.js'; -function getSessionToken( root ) { +export class GoogleCloudAuthPlugin extends GoogleCloudAuthPluginImpl { - let sessionToken = null; - traverseSet( root, tile => { + constructor( ...args ) { - if ( tile.content && tile.content.uri ) { - - const [ , params ] = tile.content.uri.split( '?' ); - sessionToken = new URLSearchParams( params ).get( 'session' ); - return true; - - } - - return false; - - } ); - - return sessionToken; - -} - -export class GoogleCloudAuthPlugin { - - constructor( { apiToken, autoRefreshToken = false, logoUrl = null, useRecommendedSettings = true } ) { - - this.name = 'GOOGLE_CLOUD_AUTH_PLUGIN'; - this.apiToken = apiToken; - this.autoRefreshToken = autoRefreshToken; - this.useRecommendedSettings = useRecommendedSettings; - this.logoUrl = logoUrl; - this.sessionToken = null; - this.tiles = null; - - this._onLoadCallback = null; - this._visibilityChangeCallback = null; - this._tokenRefreshPromise = null; - this._attributionsManager = new GoogleAttributionsManager(); - this._logoAttribution = { - value: '', - type: 'image', - collapsible: false, - }; - this._attribution = { - value: '', - type: 'string', - collapsible: true, - }; - - } - - init( tiles ) { - - if ( tiles == null ) { - - return; - - } - - if ( tiles.rootURL == null ) { - - tiles.rootURL = 'https://tile.googleapis.com/v1/3dtiles/root.json'; - - } - - if ( this.useRecommendedSettings ) { - - // This plugin changes below values to be more efficient for the photorealistic tiles - tiles.parseQueue.maxJobs = 10; - tiles.downloadQueue.maxJobs = 30; - tiles.errorTarget = 40; - - } - - this.tiles = tiles; - this._onLoadCallback = ( { tileSet } ) => { - - // the first tile set loaded will be the root - this.sessionToken = getSessionToken( tileSet.root ); - - // clear the callback once the root is loaded - tiles.removeEventListener( 'load-tile-set', this._onLoadCallback ); - - }; - - this._visibilityChangeCallback = ( { tile, visible } ) => { - - const copyright = tile.cached.metadata.asset.copyright || ''; - if ( visible ) { - - this._attributionsManager.addAttributions( copyright ); - - } else { - - this._attributionsManager.removeAttributions( copyright ); - - } - - }; - - tiles.addEventListener( 'load-tile-set', this._onLoadCallback ); - tiles.addEventListener( 'tile-visibility-change', this._visibilityChangeCallback ); - - } - - getAttributions( target ) { - - if ( this.tiles.visibleTiles.size > 0 ) { - - if ( this.logoUrl ) { - - this._logoAttribution.value = this.logoUrl; - target.push( this._logoAttribution ); - - } - - this._attribution.value = this._attributionsManager.toString(); - target.push( this._attribution ); - - } - - } - - preprocessURL( uri ) { - - uri = new URL( uri ); - if ( /^http/.test( uri.protocol ) ) { - - uri.searchParams.append( 'key', this.apiToken ); - if ( this.sessionToken !== null ) { - - uri.searchParams.append( 'session', this.sessionToken ); - - } - - } - return uri.toString(); - - } - - dispose() { - - const { tiles } = this; - tiles.removeEventListener( 'load-tile-set', this._onLoadCallback ); - tiles.removeEventListener( 'tile-visibility-change', this._visibilityChangeCallback ); - - } - - async fetchData( uri, options ) { - - // wait for the token to refresh if loading - if ( this._tokenRefreshPromise !== null ) { - - await this._tokenRefreshPromise; - uri = this.preprocessURL( uri ); - - } - - const res = await fetch( uri, options ); - if ( res.status >= 400 && res.status <= 499 && this.autoRefreshToken ) { - - await this._refreshToken( options ); - return fetch( this.preprocessURL( uri ), options ); - - } else { - - return res; - - } - - } - - _refreshToken( options ) { - - if ( this._tokenRefreshPromise === null ) { - - // refetch the root if the token has expired - const rootURL = new URL( this.tiles.rootURL ); - rootURL.searchParams.append( 'key', this.apiToken ); - this._tokenRefreshPromise = fetch( rootURL, options ) - .then( res => res.json() ) - .then( res => { - - this.sessionToken = getSessionToken( res.root ); - this._tokenRefreshPromise = null; - - } ); - - } - - return this._tokenRefreshPromise; + super( ...args ); + console.warn( 'GoogleCloudAuthPlugin: Plugins should now be imported from "3d-tiles-renderer/plugins" path.' ); } From 176356476e209993ccd1eb83aacf54e7759ad538 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Fri, 1 Nov 2024 21:45:35 +0900 Subject: [PATCH 03/10] Move gltf plugins --- src/plugins/index.d.ts | 5 + src/plugins/index.js | 5 + .../three}/gltf/GLTFCesiumRTCExtension.d.ts | 0 .../three/gltf/GLTFCesiumRTCExtension.js | 27 ++++ .../gltf/GLTFMeshFeaturesExtension.d.ts | 0 .../three/gltf/GLTFMeshFeaturesExtension.js | 76 +++++++++ .../gltf/GLTFStructuralMetadataExtension.d.ts | 0 .../gltf/GLTFStructuralMetadataExtension.js | 147 ++++++++++++++++++ .../gltf/metadata/classes/ClassProperty.js | 0 .../gltf/metadata/classes/MeshFeatures.js | 0 .../classes/PropertyAttributeAccessor.js | 0 .../metadata/classes/PropertySetAccessor.js | 0 .../metadata/classes/PropertyTableAccessor.js | 0 .../classes/PropertyTextureAccessor.js | 0 .../metadata/classes/StructuralMetadata.js | 0 .../three}/gltf/metadata/math/Matrix2.js | 0 .../utilities/ClassPropertyHelpers.js | 0 .../metadata/utilities/TexCoordUtilities.js | 0 .../metadata/utilities/TextureReadUtility.js | 0 .../loaders/gltf/GLTFCesiumRTCExtension.js | 25 +-- .../loaders/gltf/GLTFMeshFeaturesExtension.js | 74 +-------- .../gltf/GLTFStructuralMetadataExtension.js | 145 +---------------- 22 files changed, 275 insertions(+), 229 deletions(-) rename src/{three/loaders => plugins/three}/gltf/GLTFCesiumRTCExtension.d.ts (100%) create mode 100644 src/plugins/three/gltf/GLTFCesiumRTCExtension.js rename src/{three/loaders => plugins/three}/gltf/GLTFMeshFeaturesExtension.d.ts (100%) create mode 100644 src/plugins/three/gltf/GLTFMeshFeaturesExtension.js rename src/{three/loaders => plugins/three}/gltf/GLTFStructuralMetadataExtension.d.ts (100%) create mode 100644 src/plugins/three/gltf/GLTFStructuralMetadataExtension.js rename src/{three/loaders => plugins/three}/gltf/metadata/classes/ClassProperty.js (100%) rename src/{three/loaders => plugins/three}/gltf/metadata/classes/MeshFeatures.js (100%) rename src/{three/loaders => plugins/three}/gltf/metadata/classes/PropertyAttributeAccessor.js (100%) rename src/{three/loaders => plugins/three}/gltf/metadata/classes/PropertySetAccessor.js (100%) rename src/{three/loaders => plugins/three}/gltf/metadata/classes/PropertyTableAccessor.js (100%) rename src/{three/loaders => plugins/three}/gltf/metadata/classes/PropertyTextureAccessor.js (100%) rename src/{three/loaders => plugins/three}/gltf/metadata/classes/StructuralMetadata.js (100%) rename src/{three/loaders => plugins/three}/gltf/metadata/math/Matrix2.js (100%) rename src/{three/loaders => plugins/three}/gltf/metadata/utilities/ClassPropertyHelpers.js (100%) rename src/{three/loaders => plugins/three}/gltf/metadata/utilities/TexCoordUtilities.js (100%) rename src/{three/loaders => plugins/three}/gltf/metadata/utilities/TextureReadUtility.js (100%) diff --git a/src/plugins/index.d.ts b/src/plugins/index.d.ts index 174d167ba..777c088d4 100644 --- a/src/plugins/index.d.ts +++ b/src/plugins/index.d.ts @@ -5,3 +5,8 @@ export * from './three/plugins/DebugTilesPlugin'; // common plugins export { ImplicitTilingPlugin } from './base/plugins/ImplicitTilingPlugin'; + +// gltf extensions +export { GLTFCesiumRTCExtension } from './three/gltf/GLTFCesiumRTCExtension'; +export { GLTFStructuralMetadataExtension } from './three/gltf/GLTFStructuralMetadataExtension'; +export { GLTFMeshFeaturesExtension } from './three/gltf/GLTFMeshFeaturesExtension'; diff --git a/src/plugins/index.js b/src/plugins/index.js index eac6bf8ee..ce7e58bc2 100644 --- a/src/plugins/index.js +++ b/src/plugins/index.js @@ -5,3 +5,8 @@ export * from './three/plugins/DebugTilesPlugin.js'; // common plugins export { ImplicitTilingPlugin } from './base/plugins/ImplicitTilingPlugin.js'; + +// gltf extensions +export { GLTFCesiumRTCExtension } from './three/loaders/gltf/GLTFCesiumRTCExtension.js'; +export { GLTFStructuralMetadataExtension } from './three/loaders/gltf/GLTFStructuralMetadataExtension.js'; +export { GLTFMeshFeaturesExtension } from './three/loaders/gltf/GLTFMeshFeaturesExtension.js'; diff --git a/src/three/loaders/gltf/GLTFCesiumRTCExtension.d.ts b/src/plugins/three/gltf/GLTFCesiumRTCExtension.d.ts similarity index 100% rename from src/three/loaders/gltf/GLTFCesiumRTCExtension.d.ts rename to src/plugins/three/gltf/GLTFCesiumRTCExtension.d.ts diff --git a/src/plugins/three/gltf/GLTFCesiumRTCExtension.js b/src/plugins/three/gltf/GLTFCesiumRTCExtension.js new file mode 100644 index 000000000..44ef1a5f9 --- /dev/null +++ b/src/plugins/three/gltf/GLTFCesiumRTCExtension.js @@ -0,0 +1,27 @@ +export class GLTFCesiumRTCExtension { + + constructor() { + + this.name = 'CESIUM_RTC'; + + } + + afterRoot( res ) { + + if ( res.parser.json.extensions && res.parser.json.extensions.CESIUM_RTC ) { + + const { center } = res.parser.json.extensions.CESIUM_RTC; + + if ( center ) { + + res.scene.position.x += center[ 0 ]; + res.scene.position.y += center[ 1 ]; + res.scene.position.z += center[ 2 ]; + + } + + } + + } + +} diff --git a/src/three/loaders/gltf/GLTFMeshFeaturesExtension.d.ts b/src/plugins/three/gltf/GLTFMeshFeaturesExtension.d.ts similarity index 100% rename from src/three/loaders/gltf/GLTFMeshFeaturesExtension.d.ts rename to src/plugins/three/gltf/GLTFMeshFeaturesExtension.d.ts diff --git a/src/plugins/three/gltf/GLTFMeshFeaturesExtension.js b/src/plugins/three/gltf/GLTFMeshFeaturesExtension.js new file mode 100644 index 000000000..419daec90 --- /dev/null +++ b/src/plugins/three/gltf/GLTFMeshFeaturesExtension.js @@ -0,0 +1,76 @@ +import { MeshFeatures } from './metadata/classes/MeshFeatures.js'; + +// https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_mesh_features + +const EXT_NAME = 'EXT_mesh_features'; + +function forEachPrimitiveExtension( scene, parser, callback ) { + + scene.traverse( c => { + + if ( parser.associations.has( c ) ) { + + // check if this object has extension references + const { meshes, primitives } = parser.associations.get( c ); + const primitive = parser.json.meshes[ meshes ].primitives[ primitives ]; + + if ( primitive && primitive.extensions && primitive.extensions[ EXT_NAME ] ) { + + callback( c, primitive.extensions[ EXT_NAME ] ); + + } + + } + + } ); + +} + +export class GLTFMeshFeaturesExtension { + + constructor( parser ) { + + this.parser = parser; + this.name = EXT_NAME; + + } + + async afterRoot( { scene, parser } ) { + + // skip if the extension is not present + const extensionsUsed = parser.json.extensionsUsed; + if ( ! extensionsUsed || ! extensionsUsed.includes( EXT_NAME ) ) { + + return; + + } + + // get fetch the relevant textures are loaded + const textureCount = parser.json.textures?.length || 0; + const promises = new Array( textureCount ).fill( null ); + forEachPrimitiveExtension( scene, parser, ( child, { featureIds } ) => { + + featureIds.forEach( info => { + + if ( info.texture && promises[ info.texture.index ] === null ) { + + const index = info.texture.index; + promises[ index ] = parser.loadTexture( index ); + + } + + } ); + + } ); + + // initialize mesh features on each primitive + const textures = await Promise.all( promises ); + forEachPrimitiveExtension( scene, parser, ( child, extension ) => { + + child.userData.meshFeatures = new MeshFeatures( child.geometry, textures, extension ); + + } ); + + } + +} diff --git a/src/three/loaders/gltf/GLTFStructuralMetadataExtension.d.ts b/src/plugins/three/gltf/GLTFStructuralMetadataExtension.d.ts similarity index 100% rename from src/three/loaders/gltf/GLTFStructuralMetadataExtension.d.ts rename to src/plugins/three/gltf/GLTFStructuralMetadataExtension.d.ts diff --git a/src/plugins/three/gltf/GLTFStructuralMetadataExtension.js b/src/plugins/three/gltf/GLTFStructuralMetadataExtension.js new file mode 100644 index 000000000..17758cf50 --- /dev/null +++ b/src/plugins/three/gltf/GLTFStructuralMetadataExtension.js @@ -0,0 +1,147 @@ +// https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_structural_metadata + +import { FileLoader } from 'three'; +import { StructuralMetadata } from './metadata/classes/StructuralMetadata.js'; + +const EXT_NAME = 'EXT_structural_metadata'; + +// returns the set of textures required by the property texture definitions +function getRelevantTextures( parser, propertyTextures = [] ) { + + const textureCount = parser.json.textures?.length || 0; + const result = new Array( textureCount ).fill( null ); + + propertyTextures.forEach( ( { properties } ) => { + + for ( const key in properties ) { + + const { index } = properties[ key ]; + if ( result[ index ] === null ) { + + result[ index ] = parser.loadTexture( index ); + + } + + } + + } ); + + return Promise.all( result ); + +} + +// returns the set of buffers required by the property table definitions +function getRelevantBuffers( parser, propertyTables = [] ) { + + const textureCount = parser.json.bufferViews?.length || 0; + const result = new Array( textureCount ).fill( null ); + + propertyTables.forEach( ( { properties } ) => { + + for ( const key in properties ) { + + const { values, arrayOffsets, stringOffsets } = properties[ key ]; + if ( result[ values ] === null ) { + + result[ values ] = parser.loadBufferView( values ); + + } + + if ( result[ arrayOffsets ] === null ) { + + result[ arrayOffsets ] = parser.loadBufferView( arrayOffsets ); + + } + + if ( result[ stringOffsets ] === null ) { + + result[ stringOffsets ] = parser.loadBufferView( stringOffsets ); + + } + + } + + } ); + + return Promise.all( result ); + +} + +export class GLTFStructuralMetadataExtension { + + constructor( parser ) { + + this.parser = parser; + this.name = EXT_NAME; + + } + + async afterRoot( { scene, parser } ) { + + // skip if the extension is not present + const extensionsUsed = parser.json.extensionsUsed; + if ( ! extensionsUsed || ! extensionsUsed.includes( EXT_NAME ) ) { + + return; + + } + + // load the remote schema definition if present + let schemaPromise = null; + let rootExtension = parser.json.extensions[ EXT_NAME ]; + if ( rootExtension.schemaUri ) { + + // TODO: cache the loaded schema so we can share it and dispose of it when the + // extension is no longer available + const { manager, path, requestHeader, crossOrigin } = parser.options; + const finalUri = new URL( rootExtension.schemaUri, path ).toString(); + const fileLoader = new FileLoader( manager ); + fileLoader.setCrossOrigin( crossOrigin ); + fileLoader.setResponseType( 'json' ); + fileLoader.setRequestHeader( requestHeader ); + + schemaPromise = fileLoader.loadAsync( finalUri ) + .then( schema => { + + rootExtension = { ...rootExtension, schema }; + + } ); + + } + + // prep the textures and buffers + const [ textures, buffers ] = await Promise.all( [ + getRelevantTextures( parser, rootExtension.propertyTextures ), + getRelevantBuffers( parser, rootExtension.propertyTables ), + schemaPromise, + ] ); + + // initialize the extension + const rootMetadata = new StructuralMetadata( rootExtension, textures, buffers ); + scene.userData.structuralMetadata = rootMetadata; + + scene.traverse( child => { + + if ( parser.associations.has( child ) ) { + + // check if this object has extension references and use a child-specific version of the extension + const { meshes, primitives } = parser.associations.get( child ); + const primitive = parser.json.meshes[ meshes ].primitives[ primitives ]; + if ( primitive && primitive.extensions && primitive.extensions[ EXT_NAME ] ) { + + const extension = primitive.extensions[ EXT_NAME ]; + child.userData.structuralMetadata = new StructuralMetadata( rootExtension, textures, buffers, extension, child ); + + } else { + + child.userData.structuralMetadata = rootMetadata; + + } + + } + + } ); + + } + +} diff --git a/src/three/loaders/gltf/metadata/classes/ClassProperty.js b/src/plugins/three/gltf/metadata/classes/ClassProperty.js similarity index 100% rename from src/three/loaders/gltf/metadata/classes/ClassProperty.js rename to src/plugins/three/gltf/metadata/classes/ClassProperty.js diff --git a/src/three/loaders/gltf/metadata/classes/MeshFeatures.js b/src/plugins/three/gltf/metadata/classes/MeshFeatures.js similarity index 100% rename from src/three/loaders/gltf/metadata/classes/MeshFeatures.js rename to src/plugins/three/gltf/metadata/classes/MeshFeatures.js diff --git a/src/three/loaders/gltf/metadata/classes/PropertyAttributeAccessor.js b/src/plugins/three/gltf/metadata/classes/PropertyAttributeAccessor.js similarity index 100% rename from src/three/loaders/gltf/metadata/classes/PropertyAttributeAccessor.js rename to src/plugins/three/gltf/metadata/classes/PropertyAttributeAccessor.js diff --git a/src/three/loaders/gltf/metadata/classes/PropertySetAccessor.js b/src/plugins/three/gltf/metadata/classes/PropertySetAccessor.js similarity index 100% rename from src/three/loaders/gltf/metadata/classes/PropertySetAccessor.js rename to src/plugins/three/gltf/metadata/classes/PropertySetAccessor.js diff --git a/src/three/loaders/gltf/metadata/classes/PropertyTableAccessor.js b/src/plugins/three/gltf/metadata/classes/PropertyTableAccessor.js similarity index 100% rename from src/three/loaders/gltf/metadata/classes/PropertyTableAccessor.js rename to src/plugins/three/gltf/metadata/classes/PropertyTableAccessor.js diff --git a/src/three/loaders/gltf/metadata/classes/PropertyTextureAccessor.js b/src/plugins/three/gltf/metadata/classes/PropertyTextureAccessor.js similarity index 100% rename from src/three/loaders/gltf/metadata/classes/PropertyTextureAccessor.js rename to src/plugins/three/gltf/metadata/classes/PropertyTextureAccessor.js diff --git a/src/three/loaders/gltf/metadata/classes/StructuralMetadata.js b/src/plugins/three/gltf/metadata/classes/StructuralMetadata.js similarity index 100% rename from src/three/loaders/gltf/metadata/classes/StructuralMetadata.js rename to src/plugins/three/gltf/metadata/classes/StructuralMetadata.js diff --git a/src/three/loaders/gltf/metadata/math/Matrix2.js b/src/plugins/three/gltf/metadata/math/Matrix2.js similarity index 100% rename from src/three/loaders/gltf/metadata/math/Matrix2.js rename to src/plugins/three/gltf/metadata/math/Matrix2.js diff --git a/src/three/loaders/gltf/metadata/utilities/ClassPropertyHelpers.js b/src/plugins/three/gltf/metadata/utilities/ClassPropertyHelpers.js similarity index 100% rename from src/three/loaders/gltf/metadata/utilities/ClassPropertyHelpers.js rename to src/plugins/three/gltf/metadata/utilities/ClassPropertyHelpers.js diff --git a/src/three/loaders/gltf/metadata/utilities/TexCoordUtilities.js b/src/plugins/three/gltf/metadata/utilities/TexCoordUtilities.js similarity index 100% rename from src/three/loaders/gltf/metadata/utilities/TexCoordUtilities.js rename to src/plugins/three/gltf/metadata/utilities/TexCoordUtilities.js diff --git a/src/three/loaders/gltf/metadata/utilities/TextureReadUtility.js b/src/plugins/three/gltf/metadata/utilities/TextureReadUtility.js similarity index 100% rename from src/three/loaders/gltf/metadata/utilities/TextureReadUtility.js rename to src/plugins/three/gltf/metadata/utilities/TextureReadUtility.js diff --git a/src/three/loaders/gltf/GLTFCesiumRTCExtension.js b/src/three/loaders/gltf/GLTFCesiumRTCExtension.js index 44ef1a5f9..51c011cca 100644 --- a/src/three/loaders/gltf/GLTFCesiumRTCExtension.js +++ b/src/three/loaders/gltf/GLTFCesiumRTCExtension.js @@ -1,26 +1,11 @@ -export class GLTFCesiumRTCExtension { +import { GLTFCesiumRTCExtension as GLTFCesiumRTCExtensionImpl } from '../../../plugins/index.js'; - constructor() { +export class GLTFCesiumRTCExtension extends GLTFCesiumRTCExtensionImpl { - this.name = 'CESIUM_RTC'; + constructor( ...args ) { - } - - afterRoot( res ) { - - if ( res.parser.json.extensions && res.parser.json.extensions.CESIUM_RTC ) { - - const { center } = res.parser.json.extensions.CESIUM_RTC; - - if ( center ) { - - res.scene.position.x += center[ 0 ]; - res.scene.position.y += center[ 1 ]; - res.scene.position.z += center[ 2 ]; - - } - - } + super( ...args ); + console.warn( 'GLTFCesiumRTCExtension: Plugins should now be imported from "3d-tiles-renderer/plugins" path.' ); } diff --git a/src/three/loaders/gltf/GLTFMeshFeaturesExtension.js b/src/three/loaders/gltf/GLTFMeshFeaturesExtension.js index 419daec90..b000c3aa8 100644 --- a/src/three/loaders/gltf/GLTFMeshFeaturesExtension.js +++ b/src/three/loaders/gltf/GLTFMeshFeaturesExtension.js @@ -1,75 +1,11 @@ -import { MeshFeatures } from './metadata/classes/MeshFeatures.js'; +import { GLTFMeshFeaturesExtension as GLTFMeshFeaturesExtensionImpl } from '../../../plugins/index.js'; -// https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_mesh_features +export class GLTFMeshFeaturesExtension extends GLTFMeshFeaturesExtensionImpl { -const EXT_NAME = 'EXT_mesh_features'; + constructor( ...args ) { -function forEachPrimitiveExtension( scene, parser, callback ) { - - scene.traverse( c => { - - if ( parser.associations.has( c ) ) { - - // check if this object has extension references - const { meshes, primitives } = parser.associations.get( c ); - const primitive = parser.json.meshes[ meshes ].primitives[ primitives ]; - - if ( primitive && primitive.extensions && primitive.extensions[ EXT_NAME ] ) { - - callback( c, primitive.extensions[ EXT_NAME ] ); - - } - - } - - } ); - -} - -export class GLTFMeshFeaturesExtension { - - constructor( parser ) { - - this.parser = parser; - this.name = EXT_NAME; - - } - - async afterRoot( { scene, parser } ) { - - // skip if the extension is not present - const extensionsUsed = parser.json.extensionsUsed; - if ( ! extensionsUsed || ! extensionsUsed.includes( EXT_NAME ) ) { - - return; - - } - - // get fetch the relevant textures are loaded - const textureCount = parser.json.textures?.length || 0; - const promises = new Array( textureCount ).fill( null ); - forEachPrimitiveExtension( scene, parser, ( child, { featureIds } ) => { - - featureIds.forEach( info => { - - if ( info.texture && promises[ info.texture.index ] === null ) { - - const index = info.texture.index; - promises[ index ] = parser.loadTexture( index ); - - } - - } ); - - } ); - - // initialize mesh features on each primitive - const textures = await Promise.all( promises ); - forEachPrimitiveExtension( scene, parser, ( child, extension ) => { - - child.userData.meshFeatures = new MeshFeatures( child.geometry, textures, extension ); - - } ); + super( ...args ); + console.warn( 'GLTFMeshFeaturesExtension: Plugins should now be imported from "3d-tiles-renderer/plugins" path.' ); } diff --git a/src/three/loaders/gltf/GLTFStructuralMetadataExtension.js b/src/three/loaders/gltf/GLTFStructuralMetadataExtension.js index 17758cf50..55833f3ff 100644 --- a/src/three/loaders/gltf/GLTFStructuralMetadataExtension.js +++ b/src/three/loaders/gltf/GLTFStructuralMetadataExtension.js @@ -1,146 +1,11 @@ -// https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_structural_metadata +import { GLTFStructuralMetadataExtension as GLTFStructuralMetadataExtensionImpl } from '../../../plugins/index.js'; -import { FileLoader } from 'three'; -import { StructuralMetadata } from './metadata/classes/StructuralMetadata.js'; +export class GLTFStructuralMetadataExtension extends GLTFStructuralMetadataExtensionImpl { -const EXT_NAME = 'EXT_structural_metadata'; + constructor( ...args ) { -// returns the set of textures required by the property texture definitions -function getRelevantTextures( parser, propertyTextures = [] ) { - - const textureCount = parser.json.textures?.length || 0; - const result = new Array( textureCount ).fill( null ); - - propertyTextures.forEach( ( { properties } ) => { - - for ( const key in properties ) { - - const { index } = properties[ key ]; - if ( result[ index ] === null ) { - - result[ index ] = parser.loadTexture( index ); - - } - - } - - } ); - - return Promise.all( result ); - -} - -// returns the set of buffers required by the property table definitions -function getRelevantBuffers( parser, propertyTables = [] ) { - - const textureCount = parser.json.bufferViews?.length || 0; - const result = new Array( textureCount ).fill( null ); - - propertyTables.forEach( ( { properties } ) => { - - for ( const key in properties ) { - - const { values, arrayOffsets, stringOffsets } = properties[ key ]; - if ( result[ values ] === null ) { - - result[ values ] = parser.loadBufferView( values ); - - } - - if ( result[ arrayOffsets ] === null ) { - - result[ arrayOffsets ] = parser.loadBufferView( arrayOffsets ); - - } - - if ( result[ stringOffsets ] === null ) { - - result[ stringOffsets ] = parser.loadBufferView( stringOffsets ); - - } - - } - - } ); - - return Promise.all( result ); - -} - -export class GLTFStructuralMetadataExtension { - - constructor( parser ) { - - this.parser = parser; - this.name = EXT_NAME; - - } - - async afterRoot( { scene, parser } ) { - - // skip if the extension is not present - const extensionsUsed = parser.json.extensionsUsed; - if ( ! extensionsUsed || ! extensionsUsed.includes( EXT_NAME ) ) { - - return; - - } - - // load the remote schema definition if present - let schemaPromise = null; - let rootExtension = parser.json.extensions[ EXT_NAME ]; - if ( rootExtension.schemaUri ) { - - // TODO: cache the loaded schema so we can share it and dispose of it when the - // extension is no longer available - const { manager, path, requestHeader, crossOrigin } = parser.options; - const finalUri = new URL( rootExtension.schemaUri, path ).toString(); - const fileLoader = new FileLoader( manager ); - fileLoader.setCrossOrigin( crossOrigin ); - fileLoader.setResponseType( 'json' ); - fileLoader.setRequestHeader( requestHeader ); - - schemaPromise = fileLoader.loadAsync( finalUri ) - .then( schema => { - - rootExtension = { ...rootExtension, schema }; - - } ); - - } - - // prep the textures and buffers - const [ textures, buffers ] = await Promise.all( [ - getRelevantTextures( parser, rootExtension.propertyTextures ), - getRelevantBuffers( parser, rootExtension.propertyTables ), - schemaPromise, - ] ); - - // initialize the extension - const rootMetadata = new StructuralMetadata( rootExtension, textures, buffers ); - scene.userData.structuralMetadata = rootMetadata; - - scene.traverse( child => { - - if ( parser.associations.has( child ) ) { - - // check if this object has extension references and use a child-specific version of the extension - const { meshes, primitives } = parser.associations.get( child ); - const primitive = parser.json.meshes[ meshes ].primitives[ primitives ]; - if ( primitive && primitive.extensions && primitive.extensions[ EXT_NAME ] ) { - - const extension = primitive.extensions[ EXT_NAME ]; - child.userData.structuralMetadata = new StructuralMetadata( rootExtension, textures, buffers, extension, child ); - - } else { - - child.userData.structuralMetadata = rootMetadata; - - } - - } - - } ); + super( ...args ); + console.warn( 'GLTFStructuralMetadataExtension: Plugins should now be imported from "3d-tiles-renderer/plugins" path.' ); } From 362f3ef544a1246fae41df1b3033c426749dcf5e Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Fri, 1 Nov 2024 21:46:03 +0900 Subject: [PATCH 04/10] Update package.json imports --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 113a96b33..2d7c56101 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,8 @@ ], "exports": { ".": "./src/index.js", - "./r3f": "./src/r3f/index.jsx" + "./r3f": "./src/r3f/index.jsx", + "./plugins": "./src/plugins/index.js" }, "scripts": { "start": "vite --config ./vite.config.js", From 8ede8267b51e6b8cda133038efc47eab6174ebeb Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Fri, 1 Nov 2024 21:47:50 +0900 Subject: [PATCH 05/10] README update --- src/plugins/README.md | 586 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 586 insertions(+) create mode 100644 src/plugins/README.md diff --git a/src/plugins/README.md b/src/plugins/README.md new file mode 100644 index 000000000..a97cc38d9 --- /dev/null +++ b/src/plugins/README.md @@ -0,0 +1,586 @@ +Documentation for plugins and extensions provided by the `3d-tiles-renderer/plugins` export. + +# GLTF Plugins + +Set of three.js GLTFLoader plugins to be registered via `GLTFLoader.register`. To use with the TilesRenderer: + +```js +const tiles = new TilesRenderer( url ); +const loader = new GLTFLoader( tiles.manager ); +loader.register( () => new GLTFMeshFeaturesExtension() ); +loader.register( () => new GLTFStructuralMetadataExtension() ); +loader.register( () => new GLTFCesiumRTCExtension() ); +tiles.manager.addHandler( /(gltf|glb)$/g, loader ); +``` + +## GLTFMeshFeaturesExtension + +Plugin that adds support for the [EXT_mesh_features](https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_mesh_features) extension. +Adds a `Object3D.userData.meshFeatures` to each object with the extension that provides the following API: + +### .getTextures + +```js +getTextures() : Array +``` + +Returns an indexed list of all textures used by features in the extension. + +### .getFeatureInfo + +```js +getFeatureInfo() : { + label: string | null, + propertyTable: string | null, + nullFeatureId: number | null, + texture?: { + texCoord: number, + channels: Array, + } +} +``` + +Returns the feature information information associated with all features on the object. + +### .getFeatures + +```js +getFeatures( triangle : number, barycoord : Vector3 ) : Array +``` + +Takes the triangle index from something like a raycast hit as well as the calculated barycentric coordinate and returns the list of feature ids extracted from +the object at the given point. Indexed in the same order as the list of feature info in the extension. + +```js +const barycoord = new Vector3(); +const triangle = new Triangle(); +const hit = raycaster.raycast( object ); +if ( hit ) { + + const { face, point, faceIndex } = hit; + triangle.setFromAttributeAndIndices( object.geometry.attributes.position, face.a, face.b, face.c ); + triangle.a.applyMatrix4( object.matrixWorld ); + triangle.b.applyMatrix4( object.matrixWorld ); + triangle.c.applyMatrix4( object.matrixWorld ); + triangle.getBarycoord( point, barycoord ); + + const features = meshFeatures.getFeatures( faceIndex, barycoord ); + // ... + +} +``` + +### .getFeaturesAsync + +```js +getFeaturesAsync( triangle : number, barycoord : Vector3 ) : Promise> +``` + +Performs the same function as `getFeatures` but with the texture asynchronous texture read operation. + +## GLTFStructuralMetadataExtension + +Plugin that adds support for the [EXT_structural_metadata](https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_structural_metadata) extension. Adds a `Object3D.userData.structuralMetadata` to each object with the extension that provides the following API. + +_Note that 64 bit integer types are not fully supported._ + +### .textures + +```js +textures: Array +``` + +Returns an indexed list of all textures used by metadata accessors in the extension. + +### .schema + +```js +schema: Object +``` + +The extension schema object. + +### .getPropertyTableData + +```js +getPropertyTableData( + tableIndices : Array, + ids : Array, + target = [] : Array, +) : target +``` + +Returns data stored in property tables. Takes a list of table ids and ids from those tables, and returns a list of objects adhering to the structure class referenced in the table schema. + +### .getPropertyTableInfo + +```js +getPropertyTableInfo( tableIndices = null : Array ) : Array<{ + name: string, + className: string, +}> +``` + +Returns information about the tables. + +### .getPropertyTextureData + +```js +getPropertyTextureData( + triangle : number, + barycoord : Vector3, + target = [] : Array, +) : target +``` + +Returns data stored in property textures. Takes a triangle index and barycentric coordinate, and returns a list of objects adhering to the structure class referenced in the table schema. See `MeshFeatures.getFeatures` for how to calculate the index and barycoord. + +### .getPropertyTextureDataAsync + +```js +getPropertyTextureDataAsync( + triangle : number, + barycoord : Vector3, + target = [] : Array, +) : Promise +``` + +Returns the same data from `getPropertyTextureData` but performs texture read operations asynchronously. + +### .getPropertyTextureInfo + +```js +getPropertyTextureInfo() : Array<{ + name: string, + className: string, + properties: { + [name]: { + channels: Array, + index: number | null, + texCoord: number | null, + }, + }, +}> +``` + +Returns information about the property texture accessors from the extension. + +### .getPropertyAttributeData + +```js +getPropertyAttributeData( attributeIndex : number, target = [] : Array) : target +``` + +Returns data stored as property attributes. Takes the index of an index from length of the attributes, and returns a list of objects adhering to the structure class referenced in the table schema. + +### .getPropertyAttributeInfo + +```js +getPropertyAttributeInfo() : Array<{ + name: string, + className: string, +}> +``` + +Returns information about the attribute accessors from the extension. + +## GLTFCesiumRTCExtension + +Plugin that adds support for [CESIUM_RTC](https://github.com/KhronosGroup/glTF/blob/main/extensions/1.0/Vendor/CESIUM_RTC/README.md) extension. + +# TilesRenderer Plugins + +Plugins to register to the TilesRenderer instance to modify behavior. + +```js +const tiles = new TilesRenderer( url ); +tiles.registerPlugin( new TilesCompressionPlugin() ); +tiles.registerPlugin( new TilesFadePlugin() ); +``` + +## ImplicitTilingPlugin + +Plugin that adds support for 3d tiles [implicit tiling](https://github.com/CesiumGS/3d-tiles/tree/main/specification/ImplicitTiling) feature. + +## DebugTilesPlugin + +Plugin TilesRenderer that includes helpers for debugging and visualizing the various tiles in the tile set. Material overrides will not work as expected with this plugin. The plugin includes additional logic and initialization code which can cause performance loss so it's recommended to only use this when needed. + +### .colorMode + +```js +colorMode = NONE : ColorMode +``` + +Which color mode to use when rendering the tile set. The following exported enumerations can be used: + +```js +// No special color mode. Uses the default materials. +NONE + +// Render the screenspace error from black to white with errorTarget +// being the maximum value. +SCREEN_ERROR + +// Render the geometric error from black to white with maxDebugError +// being the maximum value. +GEOMETRIC_ERROR + +// Render the distance from the camera to the tile as black to white +// with maxDebugDistance being the maximum value. +DISTANCE + +// Render the depth of the tile relative to the root as black to white +// with maxDebugDepth being the maximum value. +DEPTH + +// Render the depth of the tile relative to the nearest rendered parent +// as black to white with maxDebugDepth being the maximum value. +RELATIVE_DEPTH + +// Render leaf nodes as white and parent nodes as black. +IS_LEAF + +// Render the tiles with a random color to show tile edges clearly. +RANDOM_COLOR + +// Render every individual mesh in the scene with a random color. +RANDOM_NODE_COLOR + +// Sets a custom color using the customColorCallback call back. +CUSTOM_COLOR +``` + +### .customColorCallback + +```js +customColorCallback: (tile: Tile, child: Object3D) => void +``` + +The callback used if `debugColor` is set to `CUSTOM_COLOR`. Value defaults to `null` and must be set explicitly. + +### .displayBoxBounds + +```js +displayBoxBounds = false : Boolean +``` + +Display wireframe bounding boxes from the tiles `boundingVolume.box` (or derived from the region bounds) for every visible tile. + +### .displaySphereBounds + +```js +displaySphereBounds = false : Boolean +``` + +Display wireframe bounding boxes from the tiles `boundingVolume.sphere` (or derived from the bounding box / region bounds) for every visible tile. + +### .displayRegionBounds + +```js +displayRegionBounds = false : Boolean +``` + +Display wireframe bounding rgions from the tiles `boundingVolume.region` for every visible tile if it exists. + +### .maxDebugDepth + +```js +maxDebugDepth = - 1 : Number +``` + +The depth value that represents white when rendering with `DEPTH` or `RELATIVE_DEPTH` [colorMode](#colorMode). If `maxDebugDepth` is `-1` then the maximum depth of the tile set is used. + +### .maxDebugError + +```js +maxDebugError = - 1 : Number +``` + +The error value that represents white when rendering with `GEOMETRIC_ERROR` [colorMode](#colorMode). If `maxDebugError` is `-1` then the maximum geometric error in the tile set is used. + +### .maxDebugDistance + +```js +maxDebugDistance = - 1 : Number +``` + +The distance value that represents white when rendering with `DISTANCE` [colorMode](#colorMode). If `maxDebugDistance` is `-1` then the radius of the tile set is used. + +### .constructor + +```js +constructor( options = {} ) +``` + +Takes a set of options to initialize to. + +### .getDebugColor + +```js +getDebugColor : ( val : Number, target : Color ) => void +``` + +The function used to map a [0, 1] value to a color for debug visualizations. By default the color is mapped from black to white. + +## GoogleCloudAuthPlugin + +### constructor + +```js +constructor( { accessToken : String, autoRefreshToken = false : Boolean, logoUrl = null : String | null, useRecommendedSettings = true : Boolean } ) +``` + +Takes the Google Cloud access token. If `autoRefreshToken` is set to true then the plugin will automatically perform a new root tile request once the existing token has expired after four hours. +This plugin changes below values to be more efficient for the photorealistic tiles if `useRecommendedSettings = true (default)`: +```js +tiles.parseQueue.maxJobs = 10; +tiles.downloadQueue.maxJobs = 30; +tiles.errorTarget = 40; +``` + +## CesiumIonAuthPlugin + +### constructor + +```js +constructor( { apiToken : String, assetId = null : String | null, autoRefreshToken = false : Boolean } ) +``` + +Takes the CesiumIon access token and optionally the asset id. If the asset id is not provided then the Cesium Ion URL is expected to have been passed into the `TilesRenderer` constructor. If `autoRefreshToken` is set to true then the plugin will automatically perform a new root tile request once the existing token has expired after an hour. + +## TextureOverlayPlugin + +_available in the examples directory_ + +Plugin for loading alternate texture sets and assigning them to geometry in the tile set. + +### .textureUpdateCallback + +``` +textureUpdateCallback : ( tile, model, plugin ) => void; +``` + +Callback fired when the textures for a specific tile has been loaded. This function is required. + +### .waitForLoadCompletion + +```js +waitForLoadCompletion : Boolean +``` + +If true then the update callback will only fire for tiles once all the associated textures have loaded. + +### constructor + +``` +constructor( options = { + textureUpdateCallback: null, + waitForLoadCompletion: true, +} ); +``` + +### .getTexturesForTile + +```js +getTexturesForTile( tile : Tile, target = {} : Object ) : target +``` + +### .registerLayer + +```js +registerLayer( name : string, customTextureCallback : Function ) : void +``` + +### .unregisterLayer + +```js +unregisterLayer( name : string ) : void +``` + +### .hasLayer + +```js +hasLayer( name : string ) : boolean +``` + +## TilesCompressionPlugin + +_available in the examples directory_ + +Plugin that processes geometry buffer attributes into smaller data types on load and disables texture mipmaps to save memory. The default compression is fairly aggressive and may cause artifacts. Can reduce geometry memory footprint by more than half and texture memory by around a third. + +### .constructor + +```js +constructor( options : Object ) +``` + +Available options are as follows: + +```js +{ + // Whether to generate normals if they don't already exist. + generateNormals: false, + + // Whether to disable use of mipmaps on all textures since they are typically + // not necessary. + disableMipmaps: true, + + // Whether to compress and quantize attributes. + compressIndex: true, + compressNormals: true, + compressUvs: true, + compressPosition: false, + + // The TypedArray type to use when compressing attributes. + uvType: Int8Array, + normalType: Int8Array, + positionType: Int16Array, +} +``` + +## TilesFadePlugin + +_available in the examples directory_ + +Plugin that overrides material shaders to fade tile geometry in and out as tile LODs change. Based on [this Cesium article](https://cesium.com/blog/2022/10/20/smoother-lod-transitions-in-cesium-for-unreal/) on the topic. + +The plugin will dispatch `fade-change`, `fade-start`, and `fade-end` events per tile on the TilesRenderer when the animation updates. These events should be used in addition to any others required when performing on-demand rendering. + +### .fadeDuration + +```js +fadeDuration = 250 : number +``` + +Amount of time a tile takes to fade in and out. + +### .maximumFadeOutTiles + +```js +maximumFadeOutTiles = 50 : number +``` + +Maximum number of tiles to be fading at once. If this quantity is exceeded the animation ends and tiles pop in. + +### .fadeRootTiles + +```js +fadeRootTiles = false : boolean +``` + +Whether to fade the root tile objects in. + +## GLTFExtensionsPlugin + +_available in the examples directory_ + +Plugin for automatically adding common extensions and loaders for 3d tiles to the GLTFLoader used for parsing tile geometry. Additionally, a DRACOLoader is added, as well, to support loading compressed point cloud files. + +### .constructor + +```js +constructor( options : Object ) +``` + +Available options are as follows: + +```js +{ + // If true then the StructuralMetadata and MeshFeatures extensions are included. + metadata: true, + + // If true then the Cesium RTC Center extension is included. + rtc: true, + + // A list of other extensions to include in the loader. All elements are passed to the "GLTFLoader.register" function. + plugins: [], + + // DRACOLoader and KTX2Loader instances to add to the loader. + dracoLoader: null, + ktxLoader: null, + + // Whether to automatically dispose of the DRACO and KTX Loaders when the plugin is disposed. + autoDispose: true, +} +``` + +## ReorientationPlugin + +_available in the examples directory_ + +Plugin for automatically re-orienting and re-centering the tile set to make it visible near the origin and facing the right direction. + +### .constructor + +```js +constructor( options : Object ) +``` + +Available options are as follows: + +```js +{ + // The latitude, longitude, and height of the point on the surface to orient to. Lat and lon are in radians. If + // no coordinates are provided then the plugin tries to determine if the tile set is a tile set on the globe surface + // and estimates the coordinates. + lat: null, + lon: null, + height: 0, + + // If a set of lat and lon coordinates cannot be determined then the tile set is simple oriented so the provided axes + // is oriented to three.js' +Y up direction. Valid values are positive or negative x, y, or z. + up: '+z', + + // Whether or not to recenter the tile set. + recenter: true, +} +``` + +### transformLatLonHeightToOrigin + +```js +transformLatLonHeightToOrigin( lat, lon, height = 0 ) : void +``` + +Transforms the centers the tile set such that the given coordinates and height are positioned at the origin with "X" facing west and "Z" facing north. + +## BatchedTilesPlugin + +_available in the examples directory_ + +Plugin that uses three.js' BatchedMesh to limit the number of draw calls required and improve performance. The BatchedMesh geometry and instance size are automatically resized and optimized as new geometry is added and removed. The max number of instances to generate is limited by the max size of a 3d texture. + +> [!WARNING] +> All tile geometry rendered with BatchedMesh will use the same material and only a single material "map" is supported. Only tiles geometry containing a single mesh are supported. Not compatible with other plugins that modify mesh materials or rely on other bespoke mesh data (eg TilesFadePlugin, DebugTilesPlugin, GLTF Metadata extensions). + +### .constructor + + +```js +constructor( options : Object ) +``` + +Available options are as follows: + +```js +{ + // WebGLRenderer used for generating a WebGLArrayRenderTarget + renderer, + + // The initial number of instances to use for rendering + instanceCount: 500, + + // The minimum amount of vertex and index space to save per tile geometry added. If adequate tile space is already allocated + // when a new tile geometry is added then it can prevent more expensive geometry resizing and optimization. + vertexCount: 1000, + indexCount: 1000, + + // The amount to increase the geometry and instance allocation when the operations must occur + expandPercent: 0.25, + + // The material to use for the BatchedMesh. The material of the first tile rendered with be used if not set. + material: null, +} +``` From 0f6f491b0e09941dedc05a564c79b4ce1c413882 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Fri, 1 Nov 2024 21:49:22 +0900 Subject: [PATCH 06/10] docs update --- PLUGINS.md | 587 +---------------------------------------------------- 1 file changed, 2 insertions(+), 585 deletions(-) diff --git a/PLUGINS.md b/PLUGINS.md index 6c735598b..7e5386fce 100644 --- a/PLUGINS.md +++ b/PLUGINS.md @@ -1,589 +1,6 @@ -Documentation for plugins and extensions provided by the project and in the examples folder. +Documentation for addons provided by the project and in the examples folder. -# GLTF Plugins - -Set of three.js GLTFLoader plugins to be registered via `GLTFLoader.register`. To use with the TilesRenderer: - -```js -const tiles = new TilesRenderer( url ); -const loader = new GLTFLoader( tiles.manager ); -loader.register( () => new GLTFMeshFeaturesExtension() ); -loader.register( () => new GLTFStructuralMetadataExtension() ); -loader.register( () => new GLTFCesiumRTCExtension() ); -tiles.manager.addHandler( /(gltf|glb)$/g, loader ); -``` - -## GLTFMeshFeaturesExtension - -Plugin that adds support for the [EXT_mesh_features](https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_mesh_features) extension. -Adds a `Object3D.userData.meshFeatures` to each object with the extension that provides the following API: - -### .getTextures - -```js -getTextures() : Array -``` - -Returns an indexed list of all textures used by features in the extension. - -### .getFeatureInfo - -```js -getFeatureInfo() : { - label: string | null, - propertyTable: string | null, - nullFeatureId: number | null, - texture?: { - texCoord: number, - channels: Array, - } -} -``` - -Returns the feature information information associated with all features on the object. - -### .getFeatures - -```js -getFeatures( triangle : number, barycoord : Vector3 ) : Array -``` - -Takes the triangle index from something like a raycast hit as well as the calculated barycentric coordinate and returns the list of feature ids extracted from -the object at the given point. Indexed in the same order as the list of feature info in the extension. - -```js -const barycoord = new Vector3(); -const triangle = new Triangle(); -const hit = raycaster.raycast( object ); -if ( hit ) { - - const { face, point, faceIndex } = hit; - triangle.setFromAttributeAndIndices( object.geometry.attributes.position, face.a, face.b, face.c ); - triangle.a.applyMatrix4( object.matrixWorld ); - triangle.b.applyMatrix4( object.matrixWorld ); - triangle.c.applyMatrix4( object.matrixWorld ); - triangle.getBarycoord( point, barycoord ); - - const features = meshFeatures.getFeatures( faceIndex, barycoord ); - // ... - -} -``` - -### .getFeaturesAsync - -```js -getFeaturesAsync( triangle : number, barycoord : Vector3 ) : Promise> -``` - -Performs the same function as `getFeatures` but with the texture asynchronous texture read operation. - -## GLTFStructuralMetadataExtension - -Plugin that adds support for the [EXT_structural_metadata](https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_structural_metadata) extension. Adds a `Object3D.userData.structuralMetadata` to each object with the extension that provides the following API. - -_Note that 64 bit integer types are not fully supported._ - -### .textures - -```js -textures: Array -``` - -Returns an indexed list of all textures used by metadata accessors in the extension. - -### .schema - -```js -schema: Object -``` - -The extension schema object. - -### .getPropertyTableData - -```js -getPropertyTableData( - tableIndices : Array, - ids : Array, - target = [] : Array, -) : target -``` - -Returns data stored in property tables. Takes a list of table ids and ids from those tables, and returns a list of objects adhering to the structure class referenced in the table schema. - -### .getPropertyTableInfo - -```js -getPropertyTableInfo( tableIndices = null : Array ) : Array<{ - name: string, - className: string, -}> -``` - -Returns information about the tables. - -### .getPropertyTextureData - -```js -getPropertyTextureData( - triangle : number, - barycoord : Vector3, - target = [] : Array, -) : target -``` - -Returns data stored in property textures. Takes a triangle index and barycentric coordinate, and returns a list of objects adhering to the structure class referenced in the table schema. See `MeshFeatures.getFeatures` for how to calculate the index and barycoord. - -### .getPropertyTextureDataAsync - -```js -getPropertyTextureDataAsync( - triangle : number, - barycoord : Vector3, - target = [] : Array, -) : Promise -``` - -Returns the same data from `getPropertyTextureData` but performs texture read operations asynchronously. - -### .getPropertyTextureInfo - -```js -getPropertyTextureInfo() : Array<{ - name: string, - className: string, - properties: { - [name]: { - channels: Array, - index: number | null, - texCoord: number | null, - }, - }, -}> -``` - -Returns information about the property texture accessors from the extension. - -### .getPropertyAttributeData - -```js -getPropertyAttributeData( attributeIndex : number, target = [] : Array) : target -``` - -Returns data stored as property attributes. Takes the index of an index from length of the attributes, and returns a list of objects adhering to the structure class referenced in the table schema. - -### .getPropertyAttributeInfo - -```js -getPropertyAttributeInfo() : Array<{ - name: string, - className: string, -}> -``` - -Returns information about the attribute accessors from the extension. - -## GLTFCesiumRTCExtension - -Plugin that adds support for [CESIUM_RTC](https://github.com/KhronosGroup/glTF/blob/main/extensions/1.0/Vendor/CESIUM_RTC/README.md) extension. - -# TilesRenderer Plugins - -Plugins to register to the TilesRenderer instance to modify behavior. - -```js -const tiles = new TilesRenderer( url ); -tiles.registerPlugin( new TilesCompressionPlugin() ); -tiles.registerPlugin( new TilesFadePlugin() ); -``` - -## ImplicitTilingPlugin - -Plugin that adds support for 3d tiles [implicit tiling](https://github.com/CesiumGS/3d-tiles/tree/main/specification/ImplicitTiling) feature. - -## DebugTilesPlugin - -Plugin TilesRenderer that includes helpers for debugging and visualizing the various tiles in the tile set. Material overrides will not work as expected with this plugin. The plugin includes additional logic and initialization code which can cause performance loss so it's recommended to only use this when needed. - -### .colorMode - -```js -colorMode = NONE : ColorMode -``` - -Which color mode to use when rendering the tile set. The following exported enumerations can be used: - -```js -// No special color mode. Uses the default materials. -NONE - -// Render the screenspace error from black to white with errorTarget -// being the maximum value. -SCREEN_ERROR - -// Render the geometric error from black to white with maxDebugError -// being the maximum value. -GEOMETRIC_ERROR - -// Render the distance from the camera to the tile as black to white -// with maxDebugDistance being the maximum value. -DISTANCE - -// Render the depth of the tile relative to the root as black to white -// with maxDebugDepth being the maximum value. -DEPTH - -// Render the depth of the tile relative to the nearest rendered parent -// as black to white with maxDebugDepth being the maximum value. -RELATIVE_DEPTH - -// Render leaf nodes as white and parent nodes as black. -IS_LEAF - -// Render the tiles with a random color to show tile edges clearly. -RANDOM_COLOR - -// Render every individual mesh in the scene with a random color. -RANDOM_NODE_COLOR - -// Sets a custom color using the customColorCallback call back. -CUSTOM_COLOR -``` - -### .customColorCallback - -```js -customColorCallback: (tile: Tile, child: Object3D) => void -``` - -The callback used if `debugColor` is set to `CUSTOM_COLOR`. Value defaults to `null` and must be set explicitly. - -### .displayBoxBounds - -```js -displayBoxBounds = false : Boolean -``` - -Display wireframe bounding boxes from the tiles `boundingVolume.box` (or derived from the region bounds) for every visible tile. - -### .displaySphereBounds - -```js -displaySphereBounds = false : Boolean -``` - -Display wireframe bounding boxes from the tiles `boundingVolume.sphere` (or derived from the bounding box / region bounds) for every visible tile. - -### .displayRegionBounds - -```js -displayRegionBounds = false : Boolean -``` - -Display wireframe bounding rgions from the tiles `boundingVolume.region` for every visible tile if it exists. - -### .maxDebugDepth - -```js -maxDebugDepth = - 1 : Number -``` - -The depth value that represents white when rendering with `DEPTH` or `RELATIVE_DEPTH` [colorMode](#colorMode). If `maxDebugDepth` is `-1` then the maximum depth of the tile set is used. - -### .maxDebugError - -```js -maxDebugError = - 1 : Number -``` - -The error value that represents white when rendering with `GEOMETRIC_ERROR` [colorMode](#colorMode). If `maxDebugError` is `-1` then the maximum geometric error in the tile set is used. - -### .maxDebugDistance - -```js -maxDebugDistance = - 1 : Number -``` - -The distance value that represents white when rendering with `DISTANCE` [colorMode](#colorMode). If `maxDebugDistance` is `-1` then the radius of the tile set is used. - -### .constructor - -```js -constructor( options = {} ) -``` - -Takes a set of options to initialize to. - -### .getDebugColor - -```js -getDebugColor : ( val : Number, target : Color ) => void -``` - -The function used to map a [0, 1] value to a color for debug visualizations. By default the color is mapped from black to white. - -## GoogleCloudAuthPlugin - -### constructor - -```js -constructor( { accessToken : String, autoRefreshToken = false : Boolean, logoUrl = null : String | null, useRecommendedSettings = true : Boolean } ) -``` - -Takes the Google Cloud access token. If `autoRefreshToken` is set to true then the plugin will automatically perform a new root tile request once the existing token has expired after four hours. -This plugin changes below values to be more efficient for the photorealistic tiles if `useRecommendedSettings = true (default)`: -```js -tiles.parseQueue.maxJobs = 10; -tiles.downloadQueue.maxJobs = 30; -tiles.errorTarget = 40; -``` - -## CesiumIonAuthPlugin - -### constructor - -```js -constructor( { apiToken : String, assetId = null : String | null, autoRefreshToken = false : Boolean } ) -``` - -Takes the CesiumIon access token and optionally the asset id. If the asset id is not provided then the Cesium Ion URL is expected to have been passed into the `TilesRenderer` constructor. If `autoRefreshToken` is set to true then the plugin will automatically perform a new root tile request once the existing token has expired after an hour. - -## TextureOverlayPlugin - -_available in the examples directory_ - -Plugin for loading alternate texture sets and assigning them to geometry in the tile set. - -### .textureUpdateCallback - -``` -textureUpdateCallback : ( tile, model, plugin ) => void; -``` - -Callback fired when the textures for a specific tile has been loaded. This function is required. - -### .waitForLoadCompletion - -```js -waitForLoadCompletion : Boolean -``` - -If true then the update callback will only fire for tiles once all the associated textures have loaded. - -### constructor - -``` -constructor( options = { - textureUpdateCallback: null, - waitForLoadCompletion: true, -} ); -``` - -### .getTexturesForTile - -```js -getTexturesForTile( tile : Tile, target = {} : Object ) : target -``` - -### .registerLayer - -```js -registerLayer( name : string, customTextureCallback : Function ) : void -``` - -### .unregisterLayer - -```js -unregisterLayer( name : string ) : void -``` - -### .hasLayer - -```js -hasLayer( name : string ) : boolean -``` - -## TilesCompressionPlugin - -_available in the examples directory_ - -Plugin that processes geometry buffer attributes into smaller data types on load and disables texture mipmaps to save memory. The default compression is fairly aggressive and may cause artifacts. Can reduce geometry memory footprint by more than half and texture memory by around a third. - -### .constructor - -```js -constructor( options : Object ) -``` - -Available options are as follows: - -```js -{ - // Whether to generate normals if they don't already exist. - generateNormals: false, - - // Whether to disable use of mipmaps on all textures since they are typically - // not necessary. - disableMipmaps: true, - - // Whether to compress and quantize attributes. - compressIndex: true, - compressNormals: true, - compressUvs: true, - compressPosition: false, - - // The TypedArray type to use when compressing attributes. - uvType: Int8Array, - normalType: Int8Array, - positionType: Int16Array, -} -``` - -## TilesFadePlugin - -_available in the examples directory_ - -Plugin that overrides material shaders to fade tile geometry in and out as tile LODs change. Based on [this Cesium article](https://cesium.com/blog/2022/10/20/smoother-lod-transitions-in-cesium-for-unreal/) on the topic. - -The plugin will dispatch `fade-change`, `fade-start`, and `fade-end` events per tile on the TilesRenderer when the animation updates. These events should be used in addition to any others required when performing on-demand rendering. - -### .fadeDuration - -```js -fadeDuration = 250 : number -``` - -Amount of time a tile takes to fade in and out. - -### .maximumFadeOutTiles - -```js -maximumFadeOutTiles = 50 : number -``` - -Maximum number of tiles to be fading at once. If this quantity is exceeded the animation ends and tiles pop in. - -### .fadeRootTiles - -```js -fadeRootTiles = false : boolean -``` - -Whether to fade the root tile objects in. - -## GLTFExtensionsPlugin - -_available in the examples directory_ - -Plugin for automatically adding common extensions and loaders for 3d tiles to the GLTFLoader used for parsing tile geometry. Additionally, a DRACOLoader is added, as well, to support loading compressed point cloud files. - -### .constructor - -```js -constructor( options : Object ) -``` - -Available options are as follows: - -```js -{ - // If true then the StructuralMetadata and MeshFeatures extensions are included. - metadata: true, - - // If true then the Cesium RTC Center extension is included. - rtc: true, - - // A list of other extensions to include in the loader. All elements are passed to the "GLTFLoader.register" function. - plugins: [], - - // DRACOLoader and KTX2Loader instances to add to the loader. - dracoLoader: null, - ktxLoader: null, - - // Whether to automatically dispose of the DRACO and KTX Loaders when the plugin is disposed. - autoDispose: true, -} -``` - -## ReorientationPlugin - -_available in the examples directory_ - -Plugin for automatically re-orienting and re-centering the tile set to make it visible near the origin and facing the right direction. - -### .constructor - -```js -constructor( options : Object ) -``` - -Available options are as follows: - -```js -{ - // The latitude, longitude, and height of the point on the surface to orient to. Lat and lon are in radians. If - // no coordinates are provided then the plugin tries to determine if the tile set is a tile set on the globe surface - // and estimates the coordinates. - lat: null, - lon: null, - height: 0, - - // If a set of lat and lon coordinates cannot be determined then the tile set is simple oriented so the provided axes - // is oriented to three.js' +Y up direction. Valid values are positive or negative x, y, or z. - up: '+z', - - // Whether or not to recenter the tile set. - recenter: true, -} -``` - -### transformLatLonHeightToOrigin - -```js -transformLatLonHeightToOrigin( lat, lon, height = 0 ) : void -``` - -Transforms the centers the tile set such that the given coordinates and height are positioned at the origin with "X" facing west and "Z" facing north. - -## BatchedTilesPlugin - -_available in the examples directory_ - -Plugin that uses three.js' BatchedMesh to limit the number of draw calls required and improve performance. The BatchedMesh geometry and instance size are automatically resized and optimized as new geometry is added and removed. The max number of instances to generate is limited by the max size of a 3d texture. - -> [!WARNING] -> All tile geometry rendered with BatchedMesh will use the same material and only a single material "map" is supported. Only tiles geometry containing a single mesh are supported. Not compatible with other plugins that modify mesh materials or rely on other bespoke mesh data (eg TilesFadePlugin, DebugTilesPlugin, GLTF Metadata extensions). - -### .constructor - - -```js -constructor( options : Object ) -``` - -Available options are as follows: - -```js -{ - // WebGLRenderer used for generating a WebGLArrayRenderTarget - renderer, - - // The initial number of instances to use for rendering - instanceCount: 500, - - // The minimum amount of vertex and index space to save per tile geometry added. If adequate tile space is already allocated - // when a new tile geometry is added then it can prevent more expensive geometry resizing and optimization. - vertexCount: 1000, - indexCount: 1000, - - // The amount to increase the geometry and instance allocation when the operations must occur - expandPercent: 0.25, - - // The material to use for the BatchedMesh. The material of the first tile rendered with be used if not set. - material: null, -} -``` +Plugin documentation has been moved to the [plugins directory](./src/plugins/README.md). # Controls From 7268d9609c87fdefa6df0c71a6494d77dda50631 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Fri, 1 Nov 2024 21:59:16 +0900 Subject: [PATCH 07/10] Fixes --- src/index.js | 3 +-- src/plugins/base/SUBTREELoader.js | 2 +- src/plugins/index.d.ts | 8 ++++---- src/plugins/index.js | 14 +++++++------- src/plugins/three/DebugTilesPlugin.js | 4 ++-- .../three/objects/EllipsoidRegionHelper.js | 5 ++--- src/{ => plugins}/three/objects/SphereHelper.js | 0 src/three/plugins/DebugTilesPlugin.js | 14 ++++++++++++++ 8 files changed, 31 insertions(+), 19 deletions(-) rename src/{ => plugins}/three/objects/EllipsoidRegionHelper.js (96%) rename src/{ => plugins}/three/objects/SphereHelper.js (100%) diff --git a/src/index.js b/src/index.js index ada9af0e0..96350ed49 100644 --- a/src/index.js +++ b/src/index.js @@ -9,8 +9,7 @@ export { GLTFCesiumRTCExtension } from './three/loaders/gltf/GLTFCesiumRTCExtens export { GLTFStructuralMetadataExtension } from './three/loaders/gltf/GLTFStructuralMetadataExtension.js'; export { GLTFMeshFeaturesExtension } from './three/loaders/gltf/GLTFMeshFeaturesExtension.js'; export { GLTFExtensionLoader } from './three/loaders/GLTFExtensionLoader.js'; -export { EllipsoidRegionHelper, EllipsoidRegionLineHelper } from './three/objects/EllipsoidRegionHelper.js'; -export { SphereHelper } from './three/objects/SphereHelper.js'; + export * from './three/math/Ellipsoid.js'; export * from './three/math/EllipsoidRegion.js'; export * as GeoUtils from './three/math/GeoUtils.js'; diff --git a/src/plugins/base/SUBTREELoader.js b/src/plugins/base/SUBTREELoader.js index 7203c058f..705e63e96 100644 --- a/src/plugins/base/SUBTREELoader.js +++ b/src/plugins/base/SUBTREELoader.js @@ -2,7 +2,7 @@ * Structure almost identical to Cesium, also the comments and the names are kept * https://github.com/CesiumGS/cesium/blob/0a69f67b393ba194eefb7254600811c4b712ddc0/packages/engine/Source/Scene/Implicit3DTileContent.js */ -import { LoaderBase } from '../loaders/LoaderBase.js'; +import { LoaderBase } from '../../base/loaders/LoaderBase.js'; import { readMagicBytes } from '../../utilities/readMagicBytes.js'; import { arrayToString } from '../../utilities/arrayToString.js'; diff --git a/src/plugins/index.d.ts b/src/plugins/index.d.ts index 777c088d4..2538f89ae 100644 --- a/src/plugins/index.d.ts +++ b/src/plugins/index.d.ts @@ -1,10 +1,10 @@ // three.js plugins -export { CesiumIonAuthPlugin } from './three/plugins/CesiumIonAuthPlugin'; -export { GoogleCloudAuthPlugin } from './three/plugins/GoogleCloudAuthPlugin'; -export * from './three/plugins/DebugTilesPlugin'; +export { CesiumIonAuthPlugin } from './three/CesiumIonAuthPlugin'; +export { GoogleCloudAuthPlugin } from './three/GoogleCloudAuthPlugin'; +export * from './three/DebugTilesPlugin'; // common plugins -export { ImplicitTilingPlugin } from './base/plugins/ImplicitTilingPlugin'; +export { ImplicitTilingPlugin } from './base/ImplicitTilingPlugin'; // gltf extensions export { GLTFCesiumRTCExtension } from './three/gltf/GLTFCesiumRTCExtension'; diff --git a/src/plugins/index.js b/src/plugins/index.js index ce7e58bc2..22e83cb67 100644 --- a/src/plugins/index.js +++ b/src/plugins/index.js @@ -1,12 +1,12 @@ // three.js plugins -export { CesiumIonAuthPlugin } from './three/plugins/CesiumIonAuthPlugin.js'; -export { GoogleCloudAuthPlugin } from './three/plugins/GoogleCloudAuthPlugin.js'; -export * from './three/plugins/DebugTilesPlugin.js'; +export { CesiumIonAuthPlugin } from './three/CesiumIonAuthPlugin.js'; +export { GoogleCloudAuthPlugin } from './three/GoogleCloudAuthPlugin.js'; +export * from './three/DebugTilesPlugin.js'; // common plugins -export { ImplicitTilingPlugin } from './base/plugins/ImplicitTilingPlugin.js'; +export { ImplicitTilingPlugin } from './base/ImplicitTilingPlugin.js'; // gltf extensions -export { GLTFCesiumRTCExtension } from './three/loaders/gltf/GLTFCesiumRTCExtension.js'; -export { GLTFStructuralMetadataExtension } from './three/loaders/gltf/GLTFStructuralMetadataExtension.js'; -export { GLTFMeshFeaturesExtension } from './three/loaders/gltf/GLTFMeshFeaturesExtension.js'; +export { GLTFCesiumRTCExtension } from './three/gltf/GLTFCesiumRTCExtension.js'; +export { GLTFStructuralMetadataExtension } from './three/gltf/GLTFStructuralMetadataExtension.js'; +export { GLTFMeshFeaturesExtension } from './three/gltf/GLTFMeshFeaturesExtension.js'; diff --git a/src/plugins/three/DebugTilesPlugin.js b/src/plugins/three/DebugTilesPlugin.js index 920d2f336..c1c69e073 100644 --- a/src/plugins/three/DebugTilesPlugin.js +++ b/src/plugins/three/DebugTilesPlugin.js @@ -1,6 +1,6 @@ import { Box3Helper, Group, MeshStandardMaterial, PointsMaterial, Sphere, Color } from 'three'; -import { SphereHelper } from '../objects/SphereHelper.js'; -import { EllipsoidRegionLineHelper } from '../objects/EllipsoidRegionHelper.js'; +import { SphereHelper } from './objects/SphereHelper.js'; +import { EllipsoidRegionLineHelper } from './objects/EllipsoidRegionHelper.js'; const ORIGINAL_MATERIAL = Symbol( 'ORIGINAL_MATERIAL' ); const HAS_RANDOM_COLOR = Symbol( 'HAS_RANDOM_COLOR' ); diff --git a/src/three/objects/EllipsoidRegionHelper.js b/src/plugins/three/objects/EllipsoidRegionHelper.js similarity index 96% rename from src/three/objects/EllipsoidRegionHelper.js rename to src/plugins/three/objects/EllipsoidRegionHelper.js index 6dd7d0d19..2b9a09159 100644 --- a/src/three/objects/EllipsoidRegionHelper.js +++ b/src/plugins/three/objects/EllipsoidRegionHelper.js @@ -1,6 +1,5 @@ -import { EllipsoidRegion } from '../math/EllipsoidRegion.js'; -import { Mesh, Vector3, MathUtils, BoxGeometry, BufferGeometry, EdgesGeometry, LineSegments } from 'three'; -import { BufferAttribute } from 'three'; +import { EllipsoidRegion } from '../../../three/math/EllipsoidRegion.js'; +import { Mesh, Vector3, MathUtils, BoxGeometry, BufferGeometry, EdgesGeometry, LineSegments, BufferAttribute } from 'three'; const _norm = new Vector3(); const _norm2 = new Vector3(); diff --git a/src/three/objects/SphereHelper.js b/src/plugins/three/objects/SphereHelper.js similarity index 100% rename from src/three/objects/SphereHelper.js rename to src/plugins/three/objects/SphereHelper.js diff --git a/src/three/plugins/DebugTilesPlugin.js b/src/three/plugins/DebugTilesPlugin.js index 71c272253..166b61f55 100644 --- a/src/three/plugins/DebugTilesPlugin.js +++ b/src/three/plugins/DebugTilesPlugin.js @@ -1,5 +1,19 @@ import { DebugTilesPlugin as DebugTilesPluginImpl } from '../../plugins/three/DebugTilesPlugin.js'; +export { + NONE, + SCREEN_ERROR, + GEOMETRIC_ERROR, + DISTANCE, + DEPTH, + RELATIVE_DEPTH, + IS_LEAF, + RANDOM_COLOR, + RANDOM_NODE_COLOR, + CUSTOM_COLOR, + LOAD_ORDER, +} from '../../plugins/three/DebugTilesPlugin.js'; + export class DebugTilesPlugin extends DebugTilesPluginImpl { constructor( ...args ) { From 28d4a0a1aef868801f7100628aafdea5e95c7558 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Fri, 1 Nov 2024 22:03:50 +0900 Subject: [PATCH 08/10] Update examples --- example/googleMapsAerial.js | 3 ++- example/googleMapsExample.js | 2 +- example/index.js | 6 ++++-- example/ionExample.js | 3 ++- example/ionLunar.js | 2 +- example/mars.js | 6 ++---- example/metadata.js | 6 ++++-- example/r3f/globe.jsx | 2 +- example/r3f/ion.jsx | 2 +- 9 files changed, 18 insertions(+), 14 deletions(-) diff --git a/example/googleMapsAerial.js b/example/googleMapsAerial.js index 18bfa2384..5a24a8d06 100644 --- a/example/googleMapsAerial.js +++ b/example/googleMapsAerial.js @@ -1,4 +1,5 @@ -import { GeoUtils, WGS84_ELLIPSOID, TilesRenderer, GoogleCloudAuthPlugin } from '3d-tiles-renderer'; +import { GeoUtils, WGS84_ELLIPSOID, TilesRenderer } from '3d-tiles-renderer'; +import { GoogleCloudAuthPlugin } from '3d-tiles-renderer/plugins'; import { Scene, WebGLRenderer, diff --git a/example/googleMapsExample.js b/example/googleMapsExample.js index 254d89fd4..49c8e7735 100644 --- a/example/googleMapsExample.js +++ b/example/googleMapsExample.js @@ -4,8 +4,8 @@ import { GeoUtils, GlobeControls, TilesRenderer, - GoogleCloudAuthPlugin, } from '3d-tiles-renderer'; +import { GoogleCloudAuthPlugin } from '3d-tiles-renderer/plugins'; import { Scene, WebGLRenderer, diff --git a/example/index.js b/example/index.js index b0891ab41..c8f27e990 100644 --- a/example/index.js +++ b/example/index.js @@ -1,7 +1,5 @@ import { TilesRenderer, - DebugTilesPlugin, - ImplicitTilingPlugin, GLTFCesiumRTCExtension, NONE, SCREEN_ERROR, @@ -15,6 +13,10 @@ import { CUSTOM_COLOR, LOAD_ORDER, } from '3d-tiles-renderer'; +import { + DebugTilesPlugin, + ImplicitTilingPlugin, +} from '3d-tiles-renderer/plugins'; import { Scene, DirectionalLight, diff --git a/example/ionExample.js b/example/ionExample.js index e2eb51458..df539b987 100644 --- a/example/ionExample.js +++ b/example/ionExample.js @@ -1,4 +1,5 @@ -import { CesiumIonAuthPlugin, EnvironmentControls, TilesRenderer } from '3d-tiles-renderer'; +import { EnvironmentControls, TilesRenderer } from '3d-tiles-renderer'; +import { CesiumIonAuthPlugin } from '3d-tiles-renderer/plugin'; import { Scene, WebGLRenderer, diff --git a/example/ionLunar.js b/example/ionLunar.js index 0feeb0a3b..fca045fb8 100644 --- a/example/ionLunar.js +++ b/example/ionLunar.js @@ -2,8 +2,8 @@ import { GlobeControls, TilesRenderer, LUNAR_ELLIPSOID, - CesiumIonAuthPlugin, } from '3d-tiles-renderer'; +import { CesiumIonAuthPlugin } from '3d-tiles-renderer/plugin'; import { Scene, WebGLRenderer, diff --git a/example/mars.js b/example/mars.js index 6cb96ec35..7d0faa2b2 100644 --- a/example/mars.js +++ b/example/mars.js @@ -1,7 +1,5 @@ -import { - TilesRenderer, - DebugTilesPlugin, -} from '3d-tiles-renderer'; +import { TilesRenderer } from '3d-tiles-renderer'; +import { DebugTilesPlugin } from '3d-tiles-renderer/plugins'; import { Scene, DirectionalLight, diff --git a/example/metadata.js b/example/metadata.js index 92e1d5572..42d5ce2ab 100644 --- a/example/metadata.js +++ b/example/metadata.js @@ -13,11 +13,13 @@ import { } from 'three'; import { EnvironmentControls, + TilesRenderer, +} from '3d-tiles-renderer'; +import { GLTFMeshFeaturesExtension, GLTFStructuralMetadataExtension, - TilesRenderer, CesiumIonAuthPlugin, -} from '..'; +} from '3d-tiles-renderer/plugins'; import { MeshFeaturesMaterialMixin } from './src/MeshFeaturesMaterial'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'; import GUI from 'three/examples/jsm/libs/lil-gui.module.min.js'; diff --git a/example/r3f/globe.jsx b/example/r3f/globe.jsx index 32a4fb672..d64b55870 100644 --- a/example/r3f/globe.jsx +++ b/example/r3f/globe.jsx @@ -13,7 +13,7 @@ import { import { CameraTransition } from './components/CameraTransition.jsx'; // Plugins -import { GoogleCloudAuthPlugin } from '3d-tiles-renderer'; +import { GoogleCloudAuthPlugin } from '3d-tiles-renderer/plugins'; import { GLTFExtensionsPlugin } from '../src/plugins/GLTFExtensionsPlugin.js'; import { TilesFadePlugin } from '../src/plugins/fade/TilesFadePlugin.js'; import { TileCompressionPlugin } from '../src/plugins/TileCompressionPlugin.js'; diff --git a/example/r3f/ion.jsx b/example/r3f/ion.jsx index 57884c168..630aefad8 100644 --- a/example/r3f/ion.jsx +++ b/example/r3f/ion.jsx @@ -3,7 +3,7 @@ import { createRoot } from 'react-dom/client'; // TilesRenderer, controls and attribution imports import { TilesPlugin, TilesRenderer, TilesAttributionOverlay, EnvironmentControls } from '3d-tiles-renderer/r3f'; -import { CesiumIonAuthPlugin } from '3d-tiles-renderer'; +import { CesiumIonAuthPlugin } from '3d-tiles-renderer/plugins'; // Plugins import { GLTFExtensionsPlugin } from '../src/plugins/GLTFExtensionsPlugin.js'; From b394f373ee87a81884637d147a8bf0bd5674d40f Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Sat, 2 Nov 2024 00:16:58 +0900 Subject: [PATCH 09/10] Fix examples --- example/ellipsoid.js | 3 ++- example/ionExample.js | 2 +- example/ionLunar.js | 2 +- example/src/plugins/GLTFExtensionsPlugin.js | 2 +- example/src/plugins/TileCompressionPlugin.js | 3 +-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/example/ellipsoid.js b/example/ellipsoid.js index bb8641622..91713511f 100644 --- a/example/ellipsoid.js +++ b/example/ellipsoid.js @@ -1,4 +1,5 @@ -import { SphereHelper, EllipsoidRegionLineHelper, EllipsoidRegionHelper } from '3d-tiles-renderer'; +import { SphereHelper } from '../src/plugins/three/objects/SphereHelper.js'; +import { EllipsoidRegionHelper, EllipsoidRegionLineHelper } from '../src/plugins/three/objects/EllipsoidRegionHelper.js'; import { Scene, Group, diff --git a/example/ionExample.js b/example/ionExample.js index df539b987..b0d2ac122 100644 --- a/example/ionExample.js +++ b/example/ionExample.js @@ -1,5 +1,5 @@ import { EnvironmentControls, TilesRenderer } from '3d-tiles-renderer'; -import { CesiumIonAuthPlugin } from '3d-tiles-renderer/plugin'; +import { CesiumIonAuthPlugin } from '3d-tiles-renderer/plugins'; import { Scene, WebGLRenderer, diff --git a/example/ionLunar.js b/example/ionLunar.js index fca045fb8..b1f49c877 100644 --- a/example/ionLunar.js +++ b/example/ionLunar.js @@ -3,7 +3,7 @@ import { TilesRenderer, LUNAR_ELLIPSOID, } from '3d-tiles-renderer'; -import { CesiumIonAuthPlugin } from '3d-tiles-renderer/plugin'; +import { CesiumIonAuthPlugin } from '3d-tiles-renderer/plugins'; import { Scene, WebGLRenderer, diff --git a/example/src/plugins/GLTFExtensionsPlugin.js b/example/src/plugins/GLTFExtensionsPlugin.js index d1469d411..1de9333e6 100644 --- a/example/src/plugins/GLTFExtensionsPlugin.js +++ b/example/src/plugins/GLTFExtensionsPlugin.js @@ -1,5 +1,5 @@ import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'; -import { GLTFStructuralMetadataExtension, GLTFMeshFeaturesExtension, GLTFCesiumRTCExtension } from '3d-tiles-renderer'; +import { GLTFStructuralMetadataExtension, GLTFMeshFeaturesExtension, GLTFCesiumRTCExtension } from '3d-tiles-renderer/plugins'; export class GLTFExtensionsPlugin { diff --git a/example/src/plugins/TileCompressionPlugin.js b/example/src/plugins/TileCompressionPlugin.js index 791908451..cdd120c43 100644 --- a/example/src/plugins/TileCompressionPlugin.js +++ b/example/src/plugins/TileCompressionPlugin.js @@ -1,5 +1,4 @@ -import { Vector3, LinearFilter } from 'three'; -import { BufferAttribute, MathUtils } from 'three'; +import { Vector3, LinearFilter, BufferAttribute, MathUtils } from 'three'; const _vec = new Vector3(); function compressAttribute( attribute, arrayType ) { From e7c1e283d7a22ff5ee908e2f56543956e403abd3 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Sun, 3 Nov 2024 10:06:43 +0900 Subject: [PATCH 10/10] Use 3d-tiles-renderer import paths in sub packages --- src/base/plugins/ImplicitTilingPlugin.js | 2 +- src/plugins/three/objects/EllipsoidRegionHelper.js | 2 +- src/r3f/components/CameraControls.jsx | 4 ++-- src/r3f/components/CompassGizmo.jsx | 2 +- src/r3f/components/TilesRenderer.jsx | 2 +- src/three/loaders/gltf/GLTFCesiumRTCExtension.js | 2 +- src/three/loaders/gltf/GLTFMeshFeaturesExtension.js | 2 +- src/three/loaders/gltf/GLTFStructuralMetadataExtension.js | 2 +- src/three/plugins/CesiumIonAuthPlugin.js | 2 +- src/three/plugins/DebugTilesPlugin.js | 4 ++-- src/three/plugins/GoogleCloudAuthPlugin.js | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/base/plugins/ImplicitTilingPlugin.js b/src/base/plugins/ImplicitTilingPlugin.js index d8d6054e6..f5adf9a3f 100644 --- a/src/base/plugins/ImplicitTilingPlugin.js +++ b/src/base/plugins/ImplicitTilingPlugin.js @@ -1,4 +1,4 @@ -import { ImplicitTilingPlugin as ImplicitTilingPluginImpl } from '../../plugins/index.js'; +import { ImplicitTilingPlugin as ImplicitTilingPluginImpl } from '3d-tiles-renderer/plugins'; export class ImplicitTilingPlugin extends ImplicitTilingPluginImpl { diff --git a/src/plugins/three/objects/EllipsoidRegionHelper.js b/src/plugins/three/objects/EllipsoidRegionHelper.js index 2b9a09159..db38f91fb 100644 --- a/src/plugins/three/objects/EllipsoidRegionHelper.js +++ b/src/plugins/three/objects/EllipsoidRegionHelper.js @@ -1,4 +1,4 @@ -import { EllipsoidRegion } from '../../../three/math/EllipsoidRegion.js'; +import { EllipsoidRegion } from '3d-tiles-renderer'; import { Mesh, Vector3, MathUtils, BoxGeometry, BufferGeometry, EdgesGeometry, LineSegments, BufferAttribute } from 'three'; const _norm = new Vector3(); diff --git a/src/r3f/components/CameraControls.jsx b/src/r3f/components/CameraControls.jsx index 200fc6324..1dce85f56 100644 --- a/src/r3f/components/CameraControls.jsx +++ b/src/r3f/components/CameraControls.jsx @@ -1,7 +1,7 @@ import { forwardRef, useMemo, useEffect, useContext } from 'react'; import { useThree, useFrame } from '@react-three/fiber'; -import { EnvironmentControls as EnvironmentControlsImpl } from '../../three/controls/EnvironmentControls.js'; -import { GlobeControls as GlobeControlsImpl } from '../../three/controls/GlobeControls.js'; +import { EnvironmentControls as EnvironmentControlsImpl } from '3d-tiles-renderer'; +import { GlobeControls as GlobeControlsImpl } from '3d-tiles-renderer'; import { useShallowOptions } from '../utilities/useOptions.jsx'; import { TilesRendererContext } from './TilesRenderer.jsx'; diff --git a/src/r3f/components/CompassGizmo.jsx b/src/r3f/components/CompassGizmo.jsx index e968f33fb..bbfe9517a 100644 --- a/src/r3f/components/CompassGizmo.jsx +++ b/src/r3f/components/CompassGizmo.jsx @@ -2,7 +2,7 @@ import { createPortal, useFrame, useThree } from '@react-three/fiber'; import { useContext, useEffect, useMemo, useRef, useState } from 'react'; import { BackSide, Matrix4, OrthographicCamera, Ray, Scene, Vector3 } from 'three'; import { TilesRendererContext } from './TilesRenderer'; -import { closestRayEllipsoidSurfacePointEstimate } from '../../three/controls/utils'; +import { closestRayEllipsoidSurfacePointEstimate } from '../../three/controls/utils.js'; // Based in part on @pmndrs/drei's Gizmo component diff --git a/src/r3f/components/TilesRenderer.jsx b/src/r3f/components/TilesRenderer.jsx index 8e9b5b9eb..819a464de 100644 --- a/src/r3f/components/TilesRenderer.jsx +++ b/src/r3f/components/TilesRenderer.jsx @@ -1,7 +1,7 @@ import { createContext, useContext, useState, useEffect, useRef, forwardRef, useMemo } from 'react'; import { useThree, useFrame } from '@react-three/fiber'; import { Vector3 } from 'three'; -import { TilesRenderer as TilesRendererImpl } from '../../three/TilesRenderer.js'; +import { TilesRenderer as TilesRendererImpl } from '3d-tiles-renderer'; import { useDeepOptions, useShallowOptions } from '../utilities/useOptions.jsx'; import { useObjectDep } from '../utilities/useObjectDep.jsx'; import { useForceUpdate } from '../utilities/useForceUpdate.jsx'; diff --git a/src/three/loaders/gltf/GLTFCesiumRTCExtension.js b/src/three/loaders/gltf/GLTFCesiumRTCExtension.js index 51c011cca..0e1d3b493 100644 --- a/src/three/loaders/gltf/GLTFCesiumRTCExtension.js +++ b/src/three/loaders/gltf/GLTFCesiumRTCExtension.js @@ -1,4 +1,4 @@ -import { GLTFCesiumRTCExtension as GLTFCesiumRTCExtensionImpl } from '../../../plugins/index.js'; +import { GLTFCesiumRTCExtension as GLTFCesiumRTCExtensionImpl } from '3d-tiles-renderer/plugins'; export class GLTFCesiumRTCExtension extends GLTFCesiumRTCExtensionImpl { diff --git a/src/three/loaders/gltf/GLTFMeshFeaturesExtension.js b/src/three/loaders/gltf/GLTFMeshFeaturesExtension.js index b000c3aa8..162674a76 100644 --- a/src/three/loaders/gltf/GLTFMeshFeaturesExtension.js +++ b/src/three/loaders/gltf/GLTFMeshFeaturesExtension.js @@ -1,4 +1,4 @@ -import { GLTFMeshFeaturesExtension as GLTFMeshFeaturesExtensionImpl } from '../../../plugins/index.js'; +import { GLTFMeshFeaturesExtension as GLTFMeshFeaturesExtensionImpl } from '3d-tiles-renderer/plugins'; export class GLTFMeshFeaturesExtension extends GLTFMeshFeaturesExtensionImpl { diff --git a/src/three/loaders/gltf/GLTFStructuralMetadataExtension.js b/src/three/loaders/gltf/GLTFStructuralMetadataExtension.js index 55833f3ff..59ae6095c 100644 --- a/src/three/loaders/gltf/GLTFStructuralMetadataExtension.js +++ b/src/three/loaders/gltf/GLTFStructuralMetadataExtension.js @@ -1,4 +1,4 @@ -import { GLTFStructuralMetadataExtension as GLTFStructuralMetadataExtensionImpl } from '../../../plugins/index.js'; +import { GLTFStructuralMetadataExtension as GLTFStructuralMetadataExtensionImpl } from '3d-tiles-renderer/plugins'; export class GLTFStructuralMetadataExtension extends GLTFStructuralMetadataExtensionImpl { diff --git a/src/three/plugins/CesiumIonAuthPlugin.js b/src/three/plugins/CesiumIonAuthPlugin.js index 002a8fed4..25f4d1f04 100644 --- a/src/three/plugins/CesiumIonAuthPlugin.js +++ b/src/three/plugins/CesiumIonAuthPlugin.js @@ -1,4 +1,4 @@ -import { CesiumIonAuthPlugin as CesiumIonAuthPluginImpl } from '../../plugins/index.js'; +import { CesiumIonAuthPlugin as CesiumIonAuthPluginImpl } from '3d-tiles-renderer/plugins'; export class CesiumIonAuthPlugin extends CesiumIonAuthPluginImpl { diff --git a/src/three/plugins/DebugTilesPlugin.js b/src/three/plugins/DebugTilesPlugin.js index 166b61f55..da797ae9e 100644 --- a/src/three/plugins/DebugTilesPlugin.js +++ b/src/three/plugins/DebugTilesPlugin.js @@ -1,4 +1,4 @@ -import { DebugTilesPlugin as DebugTilesPluginImpl } from '../../plugins/three/DebugTilesPlugin.js'; +import { DebugTilesPlugin as DebugTilesPluginImpl } from '3d-tiles-renderer/plugins'; export { NONE, @@ -12,7 +12,7 @@ export { RANDOM_NODE_COLOR, CUSTOM_COLOR, LOAD_ORDER, -} from '../../plugins/three/DebugTilesPlugin.js'; +} from '3d-tiles-renderer/plugins'; export class DebugTilesPlugin extends DebugTilesPluginImpl { diff --git a/src/three/plugins/GoogleCloudAuthPlugin.js b/src/three/plugins/GoogleCloudAuthPlugin.js index f94988d07..bf9dd1481 100644 --- a/src/three/plugins/GoogleCloudAuthPlugin.js +++ b/src/three/plugins/GoogleCloudAuthPlugin.js @@ -1,4 +1,4 @@ -import { GoogleCloudAuthPlugin as GoogleCloudAuthPluginImpl } from '../../plugins/index.js'; +import { GoogleCloudAuthPlugin as GoogleCloudAuthPluginImpl } from '3d-tiles-renderer/plugins'; export class GoogleCloudAuthPlugin extends GoogleCloudAuthPluginImpl {