Sfoglia il codice sorgente

USDZLoader: Distinguish between text (supported) and binary (not supported) usd files and fix UV parsing (#26709)

* USDZLoader: Distinguish between text (supported) and binary (not supported) usd files

* USDZLoader: Load resources from both usd und usda files after checking that it's not binary (crate) files

* USDZLoader: Fix invalid mesh and UV definitions leading to files not being parsed
hybridherbst 1 anno fa
parent
commit
1543d95d3e
1 ha cambiato i file con 54 aggiunte e 7 eliminazioni
  1. 54 7
      examples/jsm/loaders/USDZLoader.js

+ 54 - 7
examples/jsm/loaders/USDZLoader.js

@@ -178,7 +178,14 @@ class USDZLoader extends Loader {
 
 				}
 
-				if ( filename.endsWith( 'usd' ) ) {
+				if ( filename.endsWith( 'usd' ) || filename.endsWith( 'usda' ) ) {
+
+					if ( isCrateFile( zip[ filename ] ) ) {
+
+						console.warn( 'THREE.USDZLoader: Crate files (.usdc or binary .usd) are not supported.' );
+						continue;
+
+					}
 
 					const text = fflate.strFromU8( zip[ filename ] );
 					data[ filename ] = parser.parse( text );
@@ -191,18 +198,56 @@ class USDZLoader extends Loader {
 
 		}
 
+		function isCrateFile( buffer ) {
+
+			// Check if this a crate file. First 7 bytes of a crate file are "PXR-USDC".
+			const fileHeader = buffer.slice( 0, 7 );
+			const crateHeader = new Uint8Array( [ 0x50, 0x58, 0x52, 0x2D, 0x55, 0x53, 0x44, 0x43 ] );
+
+			// If this is not a crate file, we assume it is a plain USDA file.
+			return fileHeader.every( ( value, index ) => value === crateHeader[ index ] );
+
+		}
+
 		function findUSD( zip ) {
 
-			for ( const filename in zip ) {
+			if ( zip.length < 1 ) return undefined;
+
+			const firstFileName = Object.keys( zip )[ 0 ];
+			let isCrate = false;
+
+			// As per the USD specification, the first entry in the zip archive is used as the main file ("UsdStage").
+			// ASCII files can end in either .usda or .usd.
+			// See https://openusd.org/release/spec_usdz.html#layout
+			if ( firstFileName.endsWith( 'usda' ) ) return zip[ firstFileName ];
+
+			if ( firstFileName.endsWith( 'usdc' ) ) {
 
-				if ( filename.endsWith( 'usda' ) ) {
+				isCrate = true;
 
-					return zip[ filename ];
+			} else if ( firstFileName.endsWith( 'usd' ) ) {
+
+				// If this is not a crate file, we assume it is a plain USDA file.
+				if ( ! isCrateFile( zip[ firstFileName ] ) ) {
+
+					return zip[ firstFileName ];
+
+				} else {
+
+					isCrate = true;
 
 				}
 
 			}
 
+			if ( isCrate ) {
+
+				console.warn( 'THREE.USDZLoader: Crate files (.usdc or binary .usd) are not supported.' );
+
+			}
+
+			return undefined;
+
 		}
 
 		const zip = fflate.unzipSync( new Uint8Array( buffer ) );
@@ -252,9 +297,11 @@ class USDZLoader extends Loader {
 
 		function findGeometry( data, id ) {
 
+			if ( ! data ) return undefined;
+
 			if ( id !== undefined ) {
 
-				const def = `def "${id}"`;
+				const def = `def Mesh "${id}"`;
 
 				if ( def in data ) {
 
@@ -280,9 +327,9 @@ class USDZLoader extends Loader {
 
 					// Move st to Mesh
 
-					if ( 'float2[] primvars:st' in data ) {
+					if ( 'texCoord2f[] primvars:st' in data ) {
 
-						object[ 'float2[] primvars:st' ] = data[ 'float2[] primvars:st' ];
+						object[ 'texCoord2f[] primvars:st' ] = data[ 'texCoord2f[] primvars:st' ];
 
 					}