浏览代码

GLTFExporter WebWorker Support (#23857)

* Make GLTFExporter work in a WebWorker

* Fix formatting

* Fix canvas.toBlob

* Fix OffscreenCanvas check

* Fix promise

* Update examples/jsm/exporters/GLTFExporter.js

Co-authored-by: Don McCurdy <[email protected]>

Co-authored-by: Don McCurdy <[email protected]>
Robert Long 3 年之前
父节点
当前提交
88ef71eb93
共有 1 个文件被更改,包括 49 次插入40 次删除
  1. 49 40
      examples/jsm/exporters/GLTFExporter.js

+ 49 - 40
examples/jsm/exporters/GLTFExporter.js

@@ -225,24 +225,7 @@ function equalArray( array1, array2 ) {
  */
 function stringToArrayBuffer( text ) {
 
-	if ( window.TextEncoder !== undefined ) {
-
-		return new TextEncoder().encode( text ).buffer;
-
-	}
-
-	const array = new Uint8Array( new ArrayBuffer( text.length ) );
-
-	for ( let i = 0, il = text.length; i < il; i ++ ) {
-
-		const value = text.charCodeAt( i );
-
-		// Replacing multi-byte character with space(0x20).
-		array[ i ] = value > 0xFF ? 0x20 : value;
-
-	}
-
-	return array.buffer;
+	return new TextEncoder().encode( text ).buffer;
 
 }
 
@@ -356,6 +339,28 @@ function getPaddedArrayBuffer( arrayBuffer, paddingByte = 0 ) {
 
 let cachedCanvas = null;
 
+function getCanvas() {
+
+	if ( cachedCanvas ) {
+
+		return cachedCanvas;
+
+	}
+
+	if ( typeof OffscreenCanvas !== 'undefined' ) {
+
+		const canvas = new OffscreenCanvas( 1, 1 );
+		cachedCanvas = canvas;
+		return canvas;
+
+	}
+
+	const canvas = document.createElement( 'canvas' );
+	cachedCanvas = canvas;
+	return canvas;
+
+}
+
 /**
  * Writer
  */
@@ -454,7 +459,7 @@ class GLTFWriter {
 
 			// https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#glb-file-format-specification
 
-			const reader = new window.FileReader();
+			const reader = new FileReader();
 			reader.readAsArrayBuffer( blob );
 			reader.onloadend = function () {
 
@@ -488,7 +493,7 @@ class GLTFWriter {
 					binaryChunk
 				], { type: 'application/octet-stream' } );
 
-				const glbReader = new window.FileReader();
+				const glbReader = new FileReader();
 				glbReader.readAsArrayBuffer( glbBlob );
 				glbReader.onloadend = function () {
 
@@ -502,7 +507,7 @@ class GLTFWriter {
 
 			if ( json.buffers && json.buffers.length > 0 ) {
 
-				const reader = new window.FileReader();
+				const reader = new FileReader();
 				reader.readAsDataURL( blob );
 				reader.onloadend = function () {
 
@@ -701,7 +706,7 @@ class GLTFWriter {
 		const width = Math.max( metalness?.width || 0, roughness?.width || 0 );
 		const height = Math.max( metalness?.height || 0, roughness?.height || 0 );
 
-		const canvas = document.createElement( 'canvas' );
+		const canvas = getCanvas();
 		canvas.width = width;
 		canvas.height = height;
 
@@ -901,7 +906,7 @@ class GLTFWriter {
 
 		return new Promise( function ( resolve ) {
 
-			const reader = new window.FileReader();
+			const reader = new FileReader();
 			reader.readAsArrayBuffer( blob );
 			reader.onloadend = function () {
 
@@ -1053,7 +1058,7 @@ class GLTFWriter {
 
 		if ( options.embedImages ) {
 
-			const canvas = cachedCanvas = cachedCanvas || document.createElement( 'canvas' );
+			const canvas = getCanvas();
 
 			canvas.width = Math.min( image.width, options.maxTextureSize );
 			canvas.height = Math.min( image.height, options.maxTextureSize );
@@ -1067,14 +1072,7 @@ class GLTFWriter {
 
 			}
 
-			if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
-				( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
-				( typeof OffscreenCanvas !== 'undefined' && image instanceof OffscreenCanvas ) ||
-				( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
-
-				ctx.drawImage( image, 0, 0, canvas.width, canvas.height );
-
-			} else {
+			if ( image.data !== undefined ) { // THREE.DataTexture
 
 				if ( format !== RGBAFormat ) {
 
@@ -1101,24 +1099,35 @@ class GLTFWriter {
 
 				ctx.putImageData( new ImageData( data, image.width, image.height ), 0, 0 );
 
+			} else {
+
+				ctx.drawImage( image, 0, 0, canvas.width, canvas.height );
+
 			}
 
 			if ( options.binary === true ) {
 
-				pending.push( new Promise( function ( resolve ) {
+				let toBlobPromise;
+
+				if ( canvas.toBlob !== undefined ) {
+
+					toBlobPromise = new Promise( ( resolve ) => canvas.toBlob( resolve, mimeType ) );
 
-					canvas.toBlob( function ( blob ) {
+				} else {
+
+					toBlobPromise = canvas.convertToBlob( { type: mimeType } );
+
+				}
 
-						writer.processBufferViewImage( blob ).then( function ( bufferViewIndex ) {
+				pending.push( toBlobPromise.then( blob =>
 
-							imageDef.bufferView = bufferViewIndex;
-							resolve();
+					writer.processBufferViewImage( blob ).then( bufferViewIndex => {
 
-						} );
+						imageDef.bufferView = bufferViewIndex;
 
-					}, mimeType );
+					} )
 
-				} ) );
+				) );
 
 			} else {