|
@@ -240,59 +240,7 @@ class USDZExporter {
|
|
|
const materials = {};
|
|
const materials = {};
|
|
|
const textures = {};
|
|
const textures = {};
|
|
|
|
|
|
|
|
- scene.traverseVisible( ( object ) => {
|
|
|
|
|
-
|
|
|
|
|
- if ( object.isMesh ) {
|
|
|
|
|
-
|
|
|
|
|
- const geometry = object.geometry;
|
|
|
|
|
- const material = object.material;
|
|
|
|
|
-
|
|
|
|
|
- if ( material.isMeshStandardMaterial ) {
|
|
|
|
|
-
|
|
|
|
|
- const geometryFileName =
|
|
|
|
|
- 'geometries/Geometry_' + geometry.id + '.usda';
|
|
|
|
|
-
|
|
|
|
|
- if ( ! ( geometryFileName in files ) ) {
|
|
|
|
|
-
|
|
|
|
|
- const meshObject = buildMeshObject( geometry );
|
|
|
|
|
- files[ geometryFileName ] = strToU8(
|
|
|
|
|
- buildHeader() + '\n' + meshObject.toString()
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if ( ! ( material.uuid in materials ) ) {
|
|
|
|
|
-
|
|
|
|
|
- materials[ material.uuid ] = material;
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- const node = buildXform(
|
|
|
|
|
- object,
|
|
|
|
|
- geometry,
|
|
|
|
|
- materials[ material.uuid ],
|
|
|
|
|
- usedNames
|
|
|
|
|
- );
|
|
|
|
|
- sceneNode.addChild( node );
|
|
|
|
|
-
|
|
|
|
|
- } else {
|
|
|
|
|
-
|
|
|
|
|
- console.warn(
|
|
|
|
|
- 'THREE.USDZExporter: Unsupported material type (USDZ only supports MeshStandardMaterial)',
|
|
|
|
|
- object
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- } else if ( object.isCamera ) {
|
|
|
|
|
-
|
|
|
|
|
- const cameraNode = buildCamera( object, usedNames );
|
|
|
|
|
-
|
|
|
|
|
- sceneNode.addChild( cameraNode );
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- } );
|
|
|
|
|
|
|
+ buildHierarchy( scene, sceneNode, materials, usedNames, files );
|
|
|
|
|
|
|
|
const materialsNode = buildMaterials(
|
|
const materialsNode = buildMaterials(
|
|
|
materials,
|
|
materials,
|
|
@@ -478,12 +426,83 @@ function buildHeader() {
|
|
|
|
|
|
|
|
// Xform
|
|
// Xform
|
|
|
|
|
|
|
|
-function buildXform( object, geometry, material, usedNames ) {
|
|
|
|
|
|
|
+function buildHierarchy( object, parentNode, materials, usedNames, files ) {
|
|
|
|
|
+
|
|
|
|
|
+ for ( let i = 0, l = object.children.length; i < l; i ++ ) {
|
|
|
|
|
+
|
|
|
|
|
+ const child = object.children[ i ];
|
|
|
|
|
+
|
|
|
|
|
+ if ( ! child.visible ) continue;
|
|
|
|
|
+
|
|
|
|
|
+ let childNode;
|
|
|
|
|
+
|
|
|
|
|
+ if ( child.isMesh ) {
|
|
|
|
|
+
|
|
|
|
|
+ const geometry = child.geometry;
|
|
|
|
|
+ const material = child.material;
|
|
|
|
|
+
|
|
|
|
|
+ if ( material.isMeshStandardMaterial ) {
|
|
|
|
|
+
|
|
|
|
|
+ const geometryFileName = 'geometries/Geometry_' + geometry.id + '.usda';
|
|
|
|
|
+
|
|
|
|
|
+ if ( ! ( geometryFileName in files ) ) {
|
|
|
|
|
+
|
|
|
|
|
+ const meshObject = buildMeshObject( geometry );
|
|
|
|
|
+ files[ geometryFileName ] = strToU8(
|
|
|
|
|
+ buildHeader() + '\n' + meshObject.toString()
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if ( ! ( material.uuid in materials ) ) {
|
|
|
|
|
+
|
|
|
|
|
+ materials[ material.uuid ] = material;
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ childNode = buildMesh(
|
|
|
|
|
+ child,
|
|
|
|
|
+ geometry,
|
|
|
|
|
+ materials[ material.uuid ],
|
|
|
|
|
+ usedNames
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ } else {
|
|
|
|
|
+
|
|
|
|
|
+ console.warn(
|
|
|
|
|
+ 'THREE.USDZExporter: Unsupported material type (USDZ only supports MeshStandardMaterial)',
|
|
|
|
|
+ child
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ } else if ( child.isCamera ) {
|
|
|
|
|
+
|
|
|
|
|
+ childNode = buildCamera( child, usedNames );
|
|
|
|
|
+
|
|
|
|
|
+ } else {
|
|
|
|
|
+
|
|
|
|
|
+ childNode = buildXform( child, usedNames );
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if ( childNode ) {
|
|
|
|
|
+
|
|
|
|
|
+ parentNode.addChild( childNode );
|
|
|
|
|
+ buildHierarchy( child, childNode, materials, usedNames, files );
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function buildXform( object, usedNames ) {
|
|
|
|
|
|
|
|
const name = getName( object, usedNames );
|
|
const name = getName( object, usedNames );
|
|
|
- const transform = buildMatrix( object.matrixWorld );
|
|
|
|
|
|
|
+ const transform = buildMatrix( object.matrix );
|
|
|
|
|
|
|
|
- if ( object.matrixWorld.determinant() < 0 ) {
|
|
|
|
|
|
|
+ if ( object.matrix.determinant() < 0 ) {
|
|
|
|
|
|
|
|
console.warn(
|
|
console.warn(
|
|
|
'THREE.USDZExporter: USDZ does not support negative scales',
|
|
'THREE.USDZExporter: USDZ does not support negative scales',
|
|
@@ -494,15 +513,23 @@ function buildXform( object, geometry, material, usedNames ) {
|
|
|
|
|
|
|
|
const node = new USDNode( name, 'Xform' );
|
|
const node = new USDNode( name, 'Xform' );
|
|
|
|
|
|
|
|
|
|
+ node.addProperty( `matrix4d xformOp:transform = ${transform}` );
|
|
|
|
|
+ node.addProperty( 'uniform token[] xformOpOrder = ["xformOp:transform"]' );
|
|
|
|
|
+
|
|
|
|
|
+ return node;
|
|
|
|
|
+
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function buildMesh( object, geometry, material, usedNames ) {
|
|
|
|
|
+
|
|
|
|
|
+ const node = buildXform( object, usedNames );
|
|
|
|
|
+
|
|
|
node.addMetadata(
|
|
node.addMetadata(
|
|
|
'prepend references',
|
|
'prepend references',
|
|
|
`@./geometries/Geometry_${geometry.id}.usda@</Geometry>`
|
|
`@./geometries/Geometry_${geometry.id}.usda@</Geometry>`
|
|
|
);
|
|
);
|
|
|
node.addMetadata( 'prepend apiSchemas', '["MaterialBindingAPI"]' );
|
|
node.addMetadata( 'prepend apiSchemas', '["MaterialBindingAPI"]' );
|
|
|
|
|
|
|
|
- node.addProperty( `matrix4d xformOp:transform = ${transform}` );
|
|
|
|
|
- node.addProperty( 'uniform token[] xformOpOrder = ["xformOp:transform"]' );
|
|
|
|
|
-
|
|
|
|
|
node.addProperty(
|
|
node.addProperty(
|
|
|
`rel material:binding = </Materials/Material_${material.id}>`
|
|
`rel material:binding = </Materials/Material_${material.id}>`
|
|
|
);
|
|
);
|
|
@@ -879,7 +906,6 @@ function buildMaterial( material, textures, quickLookCompatible = false ) {
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Handle emissive
|
|
|
|
|
if ( material.emissiveMap !== null ) {
|
|
if ( material.emissiveMap !== null ) {
|
|
|
|
|
|
|
|
previewSurfaceNode.addProperty(
|
|
previewSurfaceNode.addProperty(
|
|
@@ -906,7 +932,6 @@ function buildMaterial( material, textures, quickLookCompatible = false ) {
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Handle normal
|
|
|
|
|
if ( material.normalMap !== null ) {
|
|
if ( material.normalMap !== null ) {
|
|
|
|
|
|
|
|
previewSurfaceNode.addProperty(
|
|
previewSurfaceNode.addProperty(
|
|
@@ -918,7 +943,6 @@ function buildMaterial( material, textures, quickLookCompatible = false ) {
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Handle ambient occlusion
|
|
|
|
|
if ( material.aoMap !== null ) {
|
|
if ( material.aoMap !== null ) {
|
|
|
|
|
|
|
|
previewSurfaceNode.addProperty(
|
|
previewSurfaceNode.addProperty(
|
|
@@ -1102,9 +1126,9 @@ function buildCamera( camera, usedNames ) {
|
|
|
|
|
|
|
|
const name = getName( camera, usedNames );
|
|
const name = getName( camera, usedNames );
|
|
|
|
|
|
|
|
- const transform = buildMatrix( camera.matrixWorld );
|
|
|
|
|
|
|
+ const transform = buildMatrix( camera.matrix );
|
|
|
|
|
|
|
|
- if ( camera.matrixWorld.determinant() < 0 ) {
|
|
|
|
|
|
|
+ if ( camera.matrix.determinant() < 0 ) {
|
|
|
|
|
|
|
|
console.warn(
|
|
console.warn(
|
|
|
'THREE.USDZExporter: USDZ does not support negative scales',
|
|
'THREE.USDZExporter: USDZ does not support negative scales',
|