Skip to content

Commit 4a276d2

Browse files
authored
USDZExporter: Export scene hierarchy (#31448)
1 parent 6a0dab0 commit 4a276d2

File tree

1 file changed

+88
-64
lines changed

1 file changed

+88
-64
lines changed

examples/jsm/exporters/USDZExporter.js

Lines changed: 88 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -240,59 +240,7 @@ class USDZExporter {
240240
const materials = {};
241241
const textures = {};
242242

243-
scene.traverseVisible( ( object ) => {
244-
245-
if ( object.isMesh ) {
246-
247-
const geometry = object.geometry;
248-
const material = object.material;
249-
250-
if ( material.isMeshStandardMaterial ) {
251-
252-
const geometryFileName =
253-
'geometries/Geometry_' + geometry.id + '.usda';
254-
255-
if ( ! ( geometryFileName in files ) ) {
256-
257-
const meshObject = buildMeshObject( geometry );
258-
files[ geometryFileName ] = strToU8(
259-
buildHeader() + '\n' + meshObject.toString()
260-
);
261-
262-
}
263-
264-
if ( ! ( material.uuid in materials ) ) {
265-
266-
materials[ material.uuid ] = material;
267-
268-
}
269-
270-
const node = buildXform(
271-
object,
272-
geometry,
273-
materials[ material.uuid ],
274-
usedNames
275-
);
276-
sceneNode.addChild( node );
277-
278-
} else {
279-
280-
console.warn(
281-
'THREE.USDZExporter: Unsupported material type (USDZ only supports MeshStandardMaterial)',
282-
object
283-
);
284-
285-
}
286-
287-
} else if ( object.isCamera ) {
288-
289-
const cameraNode = buildCamera( object, usedNames );
290-
291-
sceneNode.addChild( cameraNode );
292-
293-
}
294-
295-
} );
243+
buildHierarchy( scene, sceneNode, materials, usedNames, files );
296244

297245
const materialsNode = buildMaterials(
298246
materials,
@@ -478,12 +426,83 @@ function buildHeader() {
478426

479427
// Xform
480428

481-
function buildXform( object, geometry, material, usedNames ) {
429+
function buildHierarchy( object, parentNode, materials, usedNames, files ) {
430+
431+
for ( let i = 0, l = object.children.length; i < l; i ++ ) {
432+
433+
const child = object.children[ i ];
434+
435+
if ( ! child.visible ) continue;
436+
437+
let childNode;
438+
439+
if ( child.isMesh ) {
440+
441+
const geometry = child.geometry;
442+
const material = child.material;
443+
444+
if ( material.isMeshStandardMaterial ) {
445+
446+
const geometryFileName = 'geometries/Geometry_' + geometry.id + '.usda';
447+
448+
if ( ! ( geometryFileName in files ) ) {
449+
450+
const meshObject = buildMeshObject( geometry );
451+
files[ geometryFileName ] = strToU8(
452+
buildHeader() + '\n' + meshObject.toString()
453+
);
454+
455+
}
456+
457+
if ( ! ( material.uuid in materials ) ) {
458+
459+
materials[ material.uuid ] = material;
460+
461+
}
462+
463+
childNode = buildMesh(
464+
child,
465+
geometry,
466+
materials[ material.uuid ],
467+
usedNames
468+
);
469+
470+
} else {
471+
472+
console.warn(
473+
'THREE.USDZExporter: Unsupported material type (USDZ only supports MeshStandardMaterial)',
474+
child
475+
);
476+
477+
}
478+
479+
} else if ( child.isCamera ) {
480+
481+
childNode = buildCamera( child, usedNames );
482+
483+
} else {
484+
485+
childNode = buildXform( child, usedNames );
486+
487+
}
488+
489+
if ( childNode ) {
490+
491+
parentNode.addChild( childNode );
492+
buildHierarchy( child, childNode, materials, usedNames, files );
493+
494+
}
495+
496+
}
497+
498+
}
499+
500+
function buildXform( object, usedNames ) {
482501

483502
const name = getName( object, usedNames );
484-
const transform = buildMatrix( object.matrixWorld );
503+
const transform = buildMatrix( object.matrix );
485504

486-
if ( object.matrixWorld.determinant() < 0 ) {
505+
if ( object.matrix.determinant() < 0 ) {
487506

488507
console.warn(
489508
'THREE.USDZExporter: USDZ does not support negative scales',
@@ -494,15 +513,23 @@ function buildXform( object, geometry, material, usedNames ) {
494513

495514
const node = new USDNode( name, 'Xform' );
496515

516+
node.addProperty( `matrix4d xformOp:transform = ${transform}` );
517+
node.addProperty( 'uniform token[] xformOpOrder = ["xformOp:transform"]' );
518+
519+
return node;
520+
521+
}
522+
523+
function buildMesh( object, geometry, material, usedNames ) {
524+
525+
const node = buildXform( object, usedNames );
526+
497527
node.addMetadata(
498528
'prepend references',
499529
`@./geometries/Geometry_${geometry.id}.usda@</Geometry>`
500530
);
501531
node.addMetadata( 'prepend apiSchemas', '["MaterialBindingAPI"]' );
502532

503-
node.addProperty( `matrix4d xformOp:transform = ${transform}` );
504-
node.addProperty( 'uniform token[] xformOpOrder = ["xformOp:transform"]' );
505-
506533
node.addProperty(
507534
`rel material:binding = </Materials/Material_${material.id}>`
508535
);
@@ -879,7 +906,6 @@ function buildMaterial( material, textures, quickLookCompatible = false ) {
879906

880907
}
881908

882-
// Handle emissive
883909
if ( material.emissiveMap !== null ) {
884910

885911
previewSurfaceNode.addProperty(
@@ -906,7 +932,6 @@ function buildMaterial( material, textures, quickLookCompatible = false ) {
906932

907933
}
908934

909-
// Handle normal
910935
if ( material.normalMap !== null ) {
911936

912937
previewSurfaceNode.addProperty(
@@ -918,7 +943,6 @@ function buildMaterial( material, textures, quickLookCompatible = false ) {
918943

919944
}
920945

921-
// Handle ambient occlusion
922946
if ( material.aoMap !== null ) {
923947

924948
previewSurfaceNode.addProperty(
@@ -1102,9 +1126,9 @@ function buildCamera( camera, usedNames ) {
11021126

11031127
const name = getName( camera, usedNames );
11041128

1105-
const transform = buildMatrix( camera.matrixWorld );
1129+
const transform = buildMatrix( camera.matrix );
11061130

1107-
if ( camera.matrixWorld.determinant() < 0 ) {
1131+
if ( camera.matrix.determinant() < 0 ) {
11081132

11091133
console.warn(
11101134
'THREE.USDZExporter: USDZ does not support negative scales',

0 commit comments

Comments
 (0)