From 34d4516570c20e153f2d9644e2d07b6a9a7e600c Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Tue, 22 Jun 2021 18:08:03 +0200 Subject: [PATCH] ObjectLoader: Add async API. (#22031) --- editor/js/Editor.js | 12 +- examples/webgl_materials_lightmap.html | 11 +- src/loaders/ObjectLoader.js | 147 +++++++++++++++++++++++++ 3 files changed, 154 insertions(+), 16 deletions(-) diff --git a/editor/js/Editor.js b/editor/js/Editor.js index df76708681..393a621096 100644 --- a/editor/js/Editor.js +++ b/editor/js/Editor.js @@ -640,12 +640,10 @@ Editor.prototype = { // - fromJSON: function ( json ) { - - var scope = this; + fromJSON: async function ( json ) { var loader = new THREE.ObjectLoader(); - var camera = loader.parse( json.camera ); + var camera = await loader.parseAsync( json.camera ); this.camera.copy( camera ); this.signals.cameraResetted.dispatch(); @@ -653,11 +651,7 @@ Editor.prototype = { this.history.fromJSON( json.history ); this.scripts = json.scripts; - loader.parse( json.scene, function ( scene ) { - - scope.setScene( scene ); - - } ); + this.setScene( await loader.parseAsync( json.scene ) ); }, diff --git a/examples/webgl_materials_lightmap.html b/examples/webgl_materials_lightmap.html index 4873ed9123..4212bd4d35 100644 --- a/examples/webgl_materials_lightmap.html +++ b/examples/webgl_materials_lightmap.html @@ -56,10 +56,10 @@ let container, stats; let camera, scene, renderer; - init(); + await init(); animate(); - function init() { + async function init() { container = document.createElement( 'div' ); document.body.appendChild( container ); @@ -126,11 +126,8 @@ // MODEL const loader = new THREE.ObjectLoader(); - loader.load( "models/json/lightmap/lightmap.json", function ( object ) { - - scene.add( object ); - - } ); + const object = await loader.loadAsync( "models/json/lightmap/lightmap.json" ); + scene.add( object ); // diff --git a/src/loaders/ObjectLoader.js b/src/loaders/ObjectLoader.js index 63cd52f978..8f88f18e08 100644 --- a/src/loaders/ObjectLoader.js +++ b/src/loaders/ObjectLoader.js @@ -113,6 +113,34 @@ class ObjectLoader extends Loader { } + async loadAsync( url, onProgress ) { + + const scope = this; + + const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path; + this.resourcePath = this.resourcePath || path; + + const loader = new FileLoader( this.manager ); + loader.setPath( this.path ); + loader.setRequestHeader( this.requestHeader ); + loader.setWithCredentials( this.withCredentials ); + + const text = await loader.loadAsync( url, onProgress ); + + const json = JSON.parse( text ); + + const metadata = json.metadata; + + if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) { + + throw new Error( 'THREE.ObjectLoader: Can\'t load ' + url ); + + } + + return await scope.parseAsync( json ); + + } + parse( json, onLoad ) { const animations = this.parseAnimations( json.animations ); @@ -158,6 +186,26 @@ class ObjectLoader extends Loader { } + async parseAsync( json ) { + + const animations = this.parseAnimations( json.animations ); + const shapes = this.parseShapes( json.shapes ); + const geometries = this.parseGeometries( json.geometries, shapes ); + + const images = await this.parseImagesAsync( json.images ); + + const textures = this.parseTextures( json.textures, images ); + const materials = this.parseMaterials( json.materials, textures ); + + const object = this.parseObject( json.object, geometries, materials, textures, animations ); + const skeletons = this.parseSkeletons( json.skeletons, object ); + + this.bindSkeletons( object, skeletons ); + + return object; + + } + parseShapes( json ) { const shapes = {}; @@ -686,6 +734,105 @@ class ObjectLoader extends Loader { } + async parseImagesAsync( json ) { + + const scope = this; + const images = {}; + + let loader; + + async function deserializeImage( image ) { + + if ( typeof image === 'string' ) { + + const url = image; + + const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url; + + return await loader.loadAsync( path ); + + } else { + + if ( image.data ) { + + return { + data: getTypedArray( image.type, image.data ), + width: image.width, + height: image.height + }; + + } else { + + return null; + + } + + } + + } + + if ( json !== undefined && json.length > 0 ) { + + loader = new ImageLoader( this.manager ); + loader.setCrossOrigin( this.crossOrigin ); + + for ( let i = 0, il = json.length; i < il; i ++ ) { + + const image = json[ i ]; + const url = image.url; + + if ( Array.isArray( url ) ) { + + // load array of images e.g CubeTexture + + images[ image.uuid ] = []; + + for ( let j = 0, jl = url.length; j < jl; j ++ ) { + + const currentUrl = url[ j ]; + + const deserializedImage = await deserializeImage( currentUrl ); + + if ( deserializedImage !== null ) { + + if ( deserializedImage instanceof HTMLImageElement ) { + + images[ image.uuid ].push( deserializedImage ); + + } else { + + // special case: handle array of data textures for cube textures + + images[ image.uuid ].push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) ); + + } + + } + + } + + } else { + + // load single image + + const deserializedImage = await deserializeImage( image.url ); + + if ( deserializedImage !== null ) { + + images[ image.uuid ] = deserializedImage; + + } + + } + + } + + } + + return images; + + } + parseTextures( json, images ) { function parseConstant( value, type ) { -- GitLab