From 1543d95d3e4f4d110d7269d50205f10f0f7662f8 Mon Sep 17 00:00:00 2001 From: hybridherbst Date: Thu, 7 Sep 2023 07:39:48 +0200 Subject: [PATCH] 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 --- examples/jsm/loaders/USDZLoader.js | 61 ++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 7 deletions(-) diff --git a/examples/jsm/loaders/USDZLoader.js b/examples/jsm/loaders/USDZLoader.js index b393577d61c064..7392e719a4bf68 100644 --- a/examples/jsm/loaders/USDZLoader.js +++ b/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' ]; }