Skip to content

Commit

Permalink
USDZLoader: Support files created with USDZExporter.
Browse files Browse the repository at this point in the history
  • Loading branch information
mrdoob committed Sep 6, 2022
1 parent 920d4c3 commit 7358181
Showing 1 changed file with 151 additions and 96 deletions.
247 changes: 151 additions & 96 deletions examples/jsm/loaders/USDZLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,106 @@ import {

import * as fflate from '../libs/fflate.module.js';

class USDAParser {

parse( text ) {

const data = {};

const lines = text.split( '\n' );
const length = lines.length;

let current = 0;
let string = null;
let target = data;

const stack = [ data ];

// debugger;

function parseNextLine() {

const line = lines[ current ];

// console.log( line );

if ( line.includes( '=' ) ) {

const assignment = line.split( '=' );

const lhs = assignment[ 0 ].trim();
const rhs = assignment[ 1 ].trim();

if ( rhs.endsWith( '{' ) ) {

const group = {};
stack.push( group );

target[ lhs ] = group;
target = group;

} else {

target[ lhs ] = rhs;

}

} else if ( line.endsWith( '{' ) ) {

const group = target[ string ] || {};
stack.push( group );

target[ string ] = group;
target = group;

} else if ( line.endsWith( '}' ) ) {

stack.pop();

if ( stack.length === 0 ) return;

target = stack[ stack.length - 1 ];

} else if ( line.endsWith( '(' ) ) {

const meta = {};
stack.push( meta );

string = line.split( '(' )[ 0 ].trim() || string;

target[ string ] = meta;
target = meta;

} else if ( line.endsWith( ')' ) ) {

stack.pop();

target = stack[ stack.length - 1 ];

} else {

string = line.trim();

}

current ++;

if ( current < length ) {

parseNextLine();

}

}

parseNextLine();

return data;

}

}

class USDZLoader extends Loader {

constructor( manager ) {
Expand Down Expand Up @@ -56,7 +156,9 @@ class USDZLoader extends Loader {

parse( buffer ) {

function createImages( zip ) {
const parser = new USDAParser();

function parseAssets( zip ) {

const data = {};
const loader = new FileLoader();
Expand All @@ -71,6 +173,13 @@ class USDZLoader extends Loader {

}

if ( filename.endsWith( 'usd' ) ) {

const text = fflate.strFromU8( zip[ filename ] );
data[ filename ] = parser.parse( text );

}

}

return data;
Expand All @@ -95,7 +204,10 @@ class USDZLoader extends Loader {

// console.log( zip );

const images = createImages( zip );
const assets = parseAssets( zip );

// console.log( assets )

const file = findUSD( zip );

if ( file === undefined ) {
Expand All @@ -106,108 +218,51 @@ class USDZLoader extends Loader {

}


// Parse file

const text = fflate.strFromU8( file );
const lines = text.split( '\n' );
const length = lines.length;

const data = {};
const data = parser.parse( text );

let current = 0;
let string = null;
let target = data;

const stack = [ data ];

// debugger;

function parseNextLine() {
// Build scene

const line = lines[ current ];
function findGeometry( data, id ) {

// console.log( line );
if ( 'prepend references' in data ) {

if ( line.includes( '=' ) ) {
const reference = data[ 'prepend references' ];
const parts = reference.split( '@' );
const path = parts[ 1 ].replace( /^.\//, '' );
const id = parts[ 2 ].replace( /^<\//, '' ).replace( />$/, '' );
return findGeometry( assets[ path ], id );

const assignment = line.split( '=' );

const lhs = assignment[ 0 ].trim();
const rhs = assignment[ 1 ].trim();

if ( rhs.endsWith( '{' ) ) {
}

const group = {};
stack.push( group );
if ( id !== undefined ) {

target[ lhs ] = group;
target = group;
const def = `def "%{id}"`;

} else {
if ( def in data ) {

target[ lhs ] = rhs;
return data[ def ];

}

} else if ( line.endsWith( '{' ) ) {

const group = target[ string ] || {};
stack.push( group );

target[ string ] = group;
target = group;

} else if ( line.endsWith( '}' ) ) {

stack.pop();

if ( stack.length === 0 ) return;

target = stack[ stack.length - 1 ];

} else if ( line.endsWith( '(' ) ) {

const meta = {};
stack.push( meta );

string = line.split( '(' )[ 0 ].trim() || string;

target[ string ] = meta;
target = meta;

} else if ( line.endsWith( ')' ) ) {

stack.pop();

target = stack[ stack.length - 1 ];

} else {

string = line.trim();

}

current ++;

if ( current < length ) {

parseNextLine();

}

}
for ( const name in data ) {

parseNextLine();
const object = data[ name ];

// Build scene
if ( name.startsWith( 'def Mesh' ) ) {

function findGeometry( data ) {
// Move points to Mesh

for ( const name in data ) {
if ( data[ 'point3f[] points' ] ) {

const object = data[ name ];
object[ 'point3f[] points' ] = data[ 'point3f[] points' ];

if ( name.startsWith( 'def Mesh' ) ) {
}

// Move st indices to Mesh

Expand Down Expand Up @@ -241,7 +296,7 @@ class USDZLoader extends Loader {
const positions = JSON.parse( data[ 'point3f[] points' ].replace( /[()]*/g, '' ) );
const attribute = new BufferAttribute( new Float32Array( positions ), 3 );

if ( data[ 'int[] faceVertexIndices' ] ) {
if ( 'int[] faceVertexIndices' in data ) {

const indices = JSON.parse( data[ 'int[] faceVertexIndices' ] );
geometry.setAttribute( 'position', toFlatBufferAttribute( attribute, indices ) );
Expand All @@ -252,13 +307,12 @@ class USDZLoader extends Loader {

}


if ( data[ 'texCoord2f[] primvars:st' ] ) {
if ( 'texCoord2f[] primvars:st' in data ) {

const uvs = JSON.parse( data[ 'texCoord2f[] primvars:st' ].replace( /[()]*/g, '' ) );
const attribute = new BufferAttribute( new Float32Array( uvs ), 2 );

if ( data[ 'int[] primvars:st:indices' ] ) {
if ( 'int[] primvars:st:indices' in data ) {

const indices = JSON.parse( data[ 'int[] primvars:st:indices' ] );
geometry.setAttribute( 'uv', toFlatBufferAttribute( attribute, indices ) );
Expand Down Expand Up @@ -331,26 +385,27 @@ class USDZLoader extends Loader {

const material = new MeshStandardMaterial();

// console.log( data );
if ( data !== undefined ) {

if ( data[ 'def Shader "diffuseColor_texture"' ] ) {
if ( 'def Shader "diffuseColor_texture"' in data ) {

const texture = data[ 'def Shader "diffuseColor_texture"' ];
const file = texture[ 'asset inputs:file' ].replace( /@*/g, '' );
const texture = data[ 'def Shader "diffuseColor_texture"' ];
const file = texture[ 'asset inputs:file' ].replace( /@*/g, '' );

material.map = new TextureLoader().load( images[ file ] );
material.map = new TextureLoader().load( assets[ file ] );

}
}

if ( data[ 'def Shader "normal_texture"' ] ) {
if ( 'def Shader "normal_texture"' in data ) {

const texture = data[ 'def Shader "normal_texture"' ];
const file = texture[ 'asset inputs:file' ].replace( /@*/g, '' );
const texture = data[ 'def Shader "normal_texture"' ];
const file = texture[ 'asset inputs:file' ].replace( /@*/g, '' );

material.normalMap = new TextureLoader().load( images[ file ] );
material.normalMap = new TextureLoader().load( assets[ file ] );

}
}

}

return material;

Expand Down

0 comments on commit 7358181

Please sign in to comment.