diff --git a/src/loaders/BufferGeometryLoader.js b/src/loaders/BufferGeometryLoader.js index de11fd0595e1a30406af59c30f03214d1677e6a3..f8c63b9bddf596c15b7228a37cd9cacbc141591b 100644 --- a/src/loaders/BufferGeometryLoader.js +++ b/src/loaders/BufferGeometryLoader.js @@ -8,6 +8,7 @@ import { InstancedBufferGeometry } from '../core/InstancedBufferGeometry.js'; import { InstancedBufferAttribute } from '../core/InstancedBufferAttribute.js'; import { InterleavedBufferAttribute } from '../core/InterleavedBufferAttribute.js'; import { InterleavedBuffer } from '../core/InterleavedBuffer.js'; +import { getTypedArray } from '../utils.js'; function BufferGeometryLoader( manager ) { @@ -67,7 +68,7 @@ BufferGeometryLoader.prototype = Object.assign( Object.create( Loader.prototype const buffer = getArrayBuffer( json, interleavedBuffer.buffer ); - const array = new TYPED_ARRAYS[ interleavedBuffer.type ]( buffer ); + const array = getTypedArray( interleavedBuffer.type, buffer ); const ib = new InterleavedBuffer( array, interleavedBuffer.stride ); ib.uuid = interleavedBuffer.uuid; @@ -98,7 +99,7 @@ BufferGeometryLoader.prototype = Object.assign( Object.create( Loader.prototype if ( index !== undefined ) { - const typedArray = new TYPED_ARRAYS[ index.type ]( index.array ); + const typedArray = getTypedArray( index.type, index.array ); geometry.setIndex( new BufferAttribute( typedArray, 1 ) ); } @@ -117,7 +118,7 @@ BufferGeometryLoader.prototype = Object.assign( Object.create( Loader.prototype } else { - const typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array ); + const typedArray = getTypedArray( attribute.type, attribute.array ); const bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute; bufferAttribute = new bufferAttributeConstr( typedArray, attribute.itemSize, attribute.normalized ); @@ -150,7 +151,7 @@ BufferGeometryLoader.prototype = Object.assign( Object.create( Loader.prototype } else { - const typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array ); + const typedArray = getTypedArray( attribute.type, attribute.array ); bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized ); } @@ -213,17 +214,4 @@ BufferGeometryLoader.prototype = Object.assign( Object.create( Loader.prototype } ); -const TYPED_ARRAYS = { - Int8Array: Int8Array, - Uint8Array: Uint8Array, - // Workaround for IE11 pre KB2929437. See #11440 - Uint8ClampedArray: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : Uint8Array, - Int16Array: Int16Array, - Uint16Array: Uint16Array, - Int32Array: Int32Array, - Uint32Array: Uint32Array, - Float32Array: Float32Array, - Float64Array: Float64Array -}; - export { BufferGeometryLoader }; diff --git a/src/loaders/ObjectLoader.js b/src/loaders/ObjectLoader.js index 167a15dbd12edbf5fe1c3851ca7eac1ce73cd64d..cb6c431148f575928146e9bb13719083b09979f8 100644 --- a/src/loaders/ObjectLoader.js +++ b/src/loaders/ObjectLoader.js @@ -48,6 +48,7 @@ import { PerspectiveCamera } from '../cameras/PerspectiveCamera.js'; import { Scene } from '../scenes/Scene.js'; import { CubeTexture } from '../textures/CubeTexture.js'; import { Texture } from '../textures/Texture.js'; +import { DataTexture } from '../textures/DataTexture.js'; import { ImageLoader } from './ImageLoader.js'; import { LoadingManager } from './LoadingManager.js'; import { AnimationClip } from '../animation/AnimationClip.js'; @@ -58,6 +59,7 @@ import { Loader } from './Loader.js'; import { FileLoader } from './FileLoader.js'; import * as Geometries from '../geometries/Geometries.js'; import * as Curves from '../extras/curves/Curves.js'; +import { getTypedArray } from '../utils.js'; class ObjectLoader extends Loader { @@ -579,6 +581,36 @@ class ObjectLoader extends Loader { } + function deserializeImage( image ) { + + if ( typeof image === 'string' ) { + + const url = image; + + const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url; + + return loadImage( 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 ) { const manager = new LoadingManager( onLoad ); @@ -601,9 +633,23 @@ class ObjectLoader extends Loader { const currentUrl = url[ j ]; - const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( currentUrl ) ? currentUrl : scope.resourcePath + currentUrl; + const deserializedImage = deserializeImage( currentUrl ); + + if ( deserializedImage !== null ) { - images[ image.uuid ].push( loadImage( path ) ); + 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 ) ); + + } + + } } @@ -611,9 +657,13 @@ class ObjectLoader extends Loader { // load single image - const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.resourcePath + image.url; + const deserializedImage = deserializeImage( image.url ); + + if ( deserializedImage !== null ) { + + images[ image.uuid ] = deserializedImage; - images[ image.uuid ] = loadImage( path ); + } } @@ -658,18 +708,29 @@ class ObjectLoader extends Loader { } let texture; + const image = images[ data.image ]; + + if ( Array.isArray( image ) ) { - if ( Array.isArray( images[ data.image ] ) ) { + texture = new CubeTexture( image ); - texture = new CubeTexture( images[ data.image ] ); + if ( image.length === 6 ) texture.needsUpdate = true; } else { - texture = new Texture( images[ data.image ] ); + if ( image && image.data ) { - } + texture = new DataTexture( image.data, image.width, image.height ); + + } else { + + texture = new Texture( image ); - texture.needsUpdate = true; + } + + if ( image ) texture.needsUpdate = true; // textures can have undefined image data + + } texture.uuid = data.uuid; diff --git a/src/textures/Texture.js b/src/textures/Texture.js index 417c7f542734ad9e45448dccb15204ae4c1faa91..4ac58004be6bcd67b7c7d02a426e810b42f1819f 100644 --- a/src/textures/Texture.js +++ b/src/textures/Texture.js @@ -195,7 +195,17 @@ Texture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { for ( let i = 0, l = image.length; i < l; i ++ ) { - url.push( ImageUtils.getDataURL( image[ i ] ) ); + // check cube texture with data textures + + if ( image[ i ].isDataTexture ) { + + url.push( serializeImage( image[ i ].image ) ); + + } else { + + url.push( serializeImage( image[ i ] ) ); + + } } @@ -203,7 +213,7 @@ Texture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { // process single image - url = ImageUtils.getDataURL( image ); + url = serializeImage( image ); } @@ -326,5 +336,38 @@ Object.defineProperty( Texture.prototype, "needsUpdate", { } ); +function serializeImage( image ) { + + if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || + ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || + ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { + + // default images + + return ImageUtils.getDataURL( image ); + + } else { + + if ( image.data ) { + + // images of DataTexture + + return { + data: Array.prototype.slice.call( image.data ), + width: image.width, + height: image.height, + type: image.data.constructor.name + }; + + } else { + + console.warn( 'THREE.Texture: Unable to serialize Texture.' ); + return {}; + + } + + } + +} export { Texture }; diff --git a/src/utils.js b/src/utils.js index b01720dd6e59bdf9bc76452516b41681215d0480..7a1349f5b1057b10fbbc2760e12b091e41c0292f 100644 --- a/src/utils.js +++ b/src/utils.js @@ -30,4 +30,23 @@ function arrayMax( array ) { } -export { arrayMin, arrayMax }; +const TYPED_ARRAYS = { + Int8Array: Int8Array, + Uint8Array: Uint8Array, + // Workaround for IE11 pre KB2929437. See #11440 + Uint8ClampedArray: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : Uint8Array, + Int16Array: Int16Array, + Uint16Array: Uint16Array, + Int32Array: Int32Array, + Uint32Array: Uint32Array, + Float32Array: Float32Array, + Float64Array: Float64Array +}; + +function getTypedArray( type, buffer ) { + + return new TYPED_ARRAYS[ type ]( buffer ); + +} + +export { arrayMin, arrayMax, getTypedArray };