Skip to content

Commit

Permalink
USDZLoader: Distinguish between text (supported) and binary (not supp…
Browse files Browse the repository at this point in the history
…orted) usd files and fix UV parsing (mrdoob#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
  • Loading branch information
hybridherbst authored Sep 7, 2023
1 parent de9ab90 commit 1543d95
Showing 1 changed file with 54 additions and 7 deletions.
61 changes: 54 additions & 7 deletions examples/jsm/loaders/USDZLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand All @@ -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 ) );
Expand Down Expand Up @@ -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 ) {

Expand All @@ -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' ];

}

Expand Down

0 comments on commit 1543d95

Please sign in to comment.