Selaa lähdekoodia

BasisTextureLoader: Support repeated loading

Senya Pugach 5 vuotta sitten
vanhempi
commit
00607993c4

+ 47 - 4
examples/js/loaders/BasisTextureLoader.js

@@ -3,6 +3,7 @@ console.warn( "THREE.BasisTextureLoader: As part of the transition to ES6 Module
  * @author Don McCurdy / https://www.donmccurdy.com
  * @author Austin Eng / https://github.com/austinEng
  * @author Shrek Shao / https://github.com/shrekshao
+ * @author Senya Pugach / https://upisfr.ee
  */
 
 /**
@@ -40,6 +41,8 @@ THREE.BasisTextureLoader = function ( manager ) {
 
 };
 
+THREE.BasisTextureLoader.taskCache = new WeakMap();
+
 THREE.BasisTextureLoader.prototype = Object.assign( Object.create( THREE.Loader.prototype ), {
 
 	constructor: THREE.BasisTextureLoader,
@@ -109,7 +112,36 @@ THREE.BasisTextureLoader.prototype = Object.assign( Object.create( THREE.Loader.
 
 		loader.load( url, ( buffer ) => {
 
-			this._createTexture( buffer )
+			var taskKey = JSON.stringify( url );
+
+			// Check for an existing task using this buffer. A transferred buffer cannot be transferred
+			// again from this thread.
+			if ( THREE.BasisTextureLoader.taskCache.has( buffer ) ) {
+
+				var cachedTask = THREE.BasisTextureLoader.taskCache.get( buffer );
+
+				if ( cachedTask.key === taskKey ) {
+
+					return cachedTask.promise.then( onLoad ).catch( onError );
+
+				} else if ( buffer.byteLength === 0 ) {
+
+					// Technically, it would be possible to wait for the previous task to complete,
+					// transfer the buffer back, and decode again with the second configuration. That
+					// is complex, and I don't know of any reason to decode a Basis buffer twice in
+					// different ways, so this is left unimplemented.
+					throw new Error(
+
+						'THREE.BasisTextureLoader: Unable to re-decode a buffer with different ' +
+						'settings. Buffer has already been transferred.'
+
+					);
+
+				}
+
+			}
+
+			this._createTexture( buffer, url )
 				.then( onLoad )
 				.catch( onError );
 
@@ -118,10 +150,11 @@ THREE.BasisTextureLoader.prototype = Object.assign( Object.create( THREE.Loader.
 	},
 
 	/**
-	 * @param  {ArrayBuffer} buffer
+	 * @param	{ArrayBuffer} buffer
+	 * @param	{string} url
 	 * @return {Promise<THREE.CompressedTexture>}
 	 */
-	_createTexture: function ( buffer ) {
+	_createTexture: function ( buffer, url ) {
 
 		var worker;
 		var taskID;
@@ -200,6 +233,16 @@ THREE.BasisTextureLoader.prototype = Object.assign( Object.create( THREE.Loader.
 
 			} );
 
+		var taskKey = JSON.stringify( url );
+
+		// Cache the task result.
+		THREE.BasisTextureLoader.taskCache.set( buffer, {
+
+			key: taskKey,
+			promise: texturePending
+
+		} );
+
 		return texturePending;
 
 	},
@@ -466,7 +509,7 @@ THREE.BasisTextureLoader.BasisWorker = function () {
 		if ( ! width || ! height || ! levels ) {
 
 			cleanup();
-			throw new Error( 'THREE.BasisTextureLoader:  Invalid .basis file' );
+			throw new Error( 'THREE.BasisTextureLoader:	Invalid .basis file' );
 
 		}
 

+ 47 - 4
examples/jsm/loaders/BasisTextureLoader.js

@@ -2,6 +2,7 @@
  * @author Don McCurdy / https://www.donmccurdy.com
  * @author Austin Eng / https://github.com/austinEng
  * @author Shrek Shao / https://github.com/shrekshao
+ * @author Senya Pugach / https://upisfr.ee
  */
 
 import {
@@ -53,6 +54,8 @@ var BasisTextureLoader = function ( manager ) {
 
 };
 
+BasisTextureLoader.taskCache = new WeakMap();
+
 BasisTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 
 	constructor: BasisTextureLoader,
@@ -122,7 +125,36 @@ BasisTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ),
 
 		loader.load( url, ( buffer ) => {
 
-			this._createTexture( buffer )
+			var taskKey = JSON.stringify( url );
+
+			// Check for an existing task using this buffer. A transferred buffer cannot be transferred
+			// again from this thread.
+			if ( BasisTextureLoader.taskCache.has( buffer ) ) {
+
+				var cachedTask = BasisTextureLoader.taskCache.get( buffer );
+
+				if ( cachedTask.key === taskKey ) {
+
+					return cachedTask.promise.then( onLoad ).catch( onError );
+
+				} else if ( buffer.byteLength === 0 ) {
+
+					// Technically, it would be possible to wait for the previous task to complete,
+					// transfer the buffer back, and decode again with the second configuration. That
+					// is complex, and I don't know of any reason to decode a Basis buffer twice in
+					// different ways, so this is left unimplemented.
+					throw new Error(
+
+						'THREE.BasisTextureLoader: Unable to re-decode a buffer with different ' +
+						'settings. Buffer has already been transferred.'
+
+					);
+
+				}
+
+			}
+
+			this._createTexture( buffer, url )
 				.then( onLoad )
 				.catch( onError );
 
@@ -131,10 +163,11 @@ BasisTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ),
 	},
 
 	/**
-	 * @param  {ArrayBuffer} buffer
+	 * @param	{ArrayBuffer} buffer
+	 * @param	{string} url
 	 * @return {Promise<CompressedTexture>}
 	 */
-	_createTexture: function ( buffer ) {
+	_createTexture: function ( buffer, url ) {
 
 		var worker;
 		var taskID;
@@ -213,6 +246,16 @@ BasisTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ),
 
 			} );
 
+		var taskKey = JSON.stringify( url );
+
+		// Cache the task result.
+		BasisTextureLoader.taskCache.set( buffer, {
+
+			key: taskKey,
+			promise: texturePending
+
+		} );
+
 		return texturePending;
 
 	},
@@ -479,7 +522,7 @@ BasisTextureLoader.BasisWorker = function () {
 		if ( ! width || ! height || ! levels ) {
 
 			cleanup();
-			throw new Error( 'THREE.BasisTextureLoader:  Invalid .basis file' );
+			throw new Error( 'THREE.BasisTextureLoader:	Invalid .basis file' );
 
 		}