Przeglądaj źródła

USDLoader: simplify asset parsing and avoid redundant work

Mr.doob 5 dni temu
rodzic
commit
80587e802b
1 zmienionych plików z 38 dodań i 43 usunięć
  1. 38 43
      examples/jsm/loaders/USDLoader.js

+ 38 - 43
examples/jsm/loaders/USDLoader.js

@@ -90,6 +90,21 @@ class USDLoader extends Loader {
 
 		const usda = new USDAParser();
 		const usdc = new USDCParser();
+		const textDecoder = new TextDecoder();
+
+		function toArrayBuffer( data ) {
+
+			if ( data instanceof ArrayBuffer ) return data;
+
+			if ( data.byteOffset === 0 && data.byteLength === data.buffer.byteLength ) {
+
+				return data.buffer;
+
+			}
+
+			return data.buffer.slice( data.byteOffset, data.byteOffset + data.byteLength );
+
+		}
 
 		function getLowercaseExtension( filename ) {
 
@@ -109,39 +124,26 @@ class USDLoader extends Loader {
 
 			for ( const filename in zip ) {
 
+				const fileBytes = zip[ filename ];
 				const ext = getLowercaseExtension( filename );
+
 				if ( ext === 'png' || ext === 'jpg' || ext === 'jpeg' || ext === 'avif' ) {
 
-					const type = ext === 'png' ? 'image/png' : ext === 'avif' ? 'image/avif' : 'image/jpeg';
-					const blob = new Blob( [ zip[ filename ] ], { type } );
-					data[ filename ] = URL.createObjectURL( blob );
+					// Keep raw image bytes and create object URLs lazily in USDComposer.
+					data[ filename ] = fileBytes;
+					continue;
 
 				}
 
-			}
+				if ( ext !== 'usd' && ext !== 'usda' && ext !== 'usdc' ) continue;
 
-			for ( const filename in zip ) {
-
-				const ext = getLowercaseExtension( filename );
-				if ( ext === 'usd' || ext === 'usda' || ext === 'usdc' ) {
-
-					if ( isCrateFile( zip[ filename ] ) ) {
-
-						// Store parsed data (specsByPath) for on-demand composition
-						const parsedData = usdc.parseData( zip[ filename ].buffer );
-						data[ filename ] = parsedData;
-						// Store raw buffer for re-parsing with variant selections
-						data[ filename + ':buffer' ] = zip[ filename ].buffer;
+				if ( isCrateFile( fileBytes ) ) {
 
-					} else {
+					data[ filename ] = usdc.parseData( toArrayBuffer( fileBytes ) );
 
-						const text = new TextDecoder().decode( zip[ filename ] );
-						// Store parsed data (specsByPath) for on-demand composition
-						data[ filename ] = usda.parseData( text );
-						// Store raw text for re-parsing with variant selections
-						data[ filename + ':text' ] = text;
+				} else {
 
-					}
+					data[ filename ] = usda.parseData( textDecoder.decode( fileBytes ) );
 
 				}
 
@@ -154,10 +156,9 @@ class USDLoader extends Loader {
 		function isCrateFile( buffer ) {
 
 			const crateHeader = new Uint8Array( [ 0x50, 0x58, 0x52, 0x2D, 0x55, 0x53, 0x44, 0x43 ] ); // PXR-USDC
+			const view = buffer instanceof Uint8Array ? buffer : new Uint8Array( buffer );
 
-			if ( buffer.byteLength < crateHeader.length ) return false;
-
-			const view = new Uint8Array( buffer, 0, crateHeader.length );
+			if ( view.byteLength < crateHeader.length ) return false;
 
 			for ( let i = 0; i < crateHeader.length; i ++ ) {
 
@@ -172,7 +173,7 @@ class USDLoader extends Loader {
 		function findUSD( zip ) {
 
 			const fileNames = Object.keys( zip );
-			if ( fileNames.length < 1 ) return { file: undefined, basePath: '' };
+			if ( fileNames.length < 1 ) return { file: undefined, filename: '', basePath: '' };
 
 			const firstFileName = fileNames[ 0 ];
 			const ext = getLowercaseExtension( firstFileName );
@@ -183,7 +184,7 @@ class USDLoader extends Loader {
 
 			// Per AOUSD core spec v1.0.1 section 16.4.1.2, the first ZIP entry is the root layer.
 			// ASCII files can end in either .usda or .usd.
-			if ( ext === 'usda' ) return { file: zip[ firstFileName ], basePath };
+			if ( ext === 'usda' ) return { file: zip[ firstFileName ], filename: firstFileName, basePath };
 
 			if ( ext === 'usdc' ) {
 
@@ -194,7 +195,7 @@ class USDLoader extends Loader {
 				// If this is not a crate file, we assume it is a plain USDA file.
 				if ( ! isCrateFile( zip[ firstFileName ] ) ) {
 
-					return { file: zip[ firstFileName ], basePath };
+					return { file: zip[ firstFileName ], filename: firstFileName, basePath };
 
 				} else {
 
@@ -206,11 +207,11 @@ class USDLoader extends Loader {
 
 			if ( isCrate ) {
 
-				return { file: zip[ firstFileName ], basePath };
+				return { file: zip[ firstFileName ], filename: firstFileName, basePath };
 
 			}
 
-			return { file: undefined, basePath: '' };
+			return { file: undefined, filename: '', basePath: '' };
 
 		}
 
@@ -231,7 +232,7 @@ class USDLoader extends Loader {
 		if ( isCrateFile( buffer ) ) {
 
 			const composer = new USDComposer( scope.manager );
-			const data = usdc.parseData( buffer );
+			const data = usdc.parseData( toArrayBuffer( buffer ) );
 			return composer.compose( data, {} );
 
 		}
@@ -244,7 +245,7 @@ class USDLoader extends Loader {
 
 			const zip = unzipSync( bytes );
 			const assets = parseAssets( zip );
-			const { file, basePath } = findUSD( zip );
+			const { file, filename, basePath } = findUSD( zip );
 
 			if ( ! file ) {
 
@@ -253,16 +254,10 @@ class USDLoader extends Loader {
 			}
 
 			const composer = new USDComposer( scope.manager );
-			let data;
-
-			if ( isCrateFile( file ) ) {
-
-				data = usdc.parseData( file.buffer );
-
-			} else {
+			const data = assets[ filename ];
+			if ( ! data ) {
 
-				const text = new TextDecoder().decode( file );
-				data = usda.parseData( text );
+				throw new Error( 'USDLoader: Failed to parse root layer "' + filename + '".' );
 
 			}
 
@@ -273,7 +268,7 @@ class USDLoader extends Loader {
 		// USDA (standalone, as ArrayBuffer)
 
 		const composer = new USDComposer( scope.manager );
-		const text = new TextDecoder().decode( bytes );
+		const text = textDecoder.decode( bytes );
 		const data = usda.parseData( text );
 		return composer.compose( data, {} );
 

粤ICP备19079148号