Bladeren bron

USDZExporter: Add option for onlyVisible (#31489)

Michael Blix 5 maanden geleden
bovenliggende
commit
e4139cf1eb

+ 1 - 0
docs/examples/en/exporters/USDZExporter.html

@@ -93,6 +93,7 @@
 		<ul>
 			<li>`maxTextureSize` - int. Restricts the image maximum size (both width and height) to the given value. Default is 1024.</li>
 			<li>`includeAnchoringProperties` - bool. Whether to include anchoring properties for AR. Default is true.</li>
+			<li>`onlyVisible` - bool. Export only visible 3D objects. Default is true.</li>
 			<li>`quickLookCompatible` - bool. Whether to make the exported USDZ compatible with Apple's QuickLook. Default is false.</li>
 			<li>`ar` - Object. AR-specific options including anchoring type and plane anchoring alignment.</li>
 		</ul>

+ 6 - 4
examples/jsm/exporters/USDZExporter.js

@@ -196,6 +196,7 @@ class USDZExporter {
 					planeAnchoring: { alignment: 'horizontal' },
 				},
 				includeAnchoringProperties: true,
+				onlyVisible: true,
 				quickLookCompatible: false,
 				maxTextureSize: 1024,
 			},
@@ -240,7 +241,7 @@ class USDZExporter {
 		const materials = {};
 		const textures = {};
 
-		buildHierarchy( scene, sceneNode, materials, usedNames, files );
+		buildHierarchy( scene, sceneNode, materials, usedNames, files, options );
 
 		const materialsNode = buildMaterials(
 			materials,
@@ -426,13 +427,13 @@ function buildHeader() {
 
 // Xform
 
-function buildHierarchy( object, parentNode, materials, usedNames, files ) {
+function buildHierarchy( object, parentNode, materials, usedNames, files, options ) {
 
 	for ( let i = 0, l = object.children.length; i < l; i ++ ) {
 
 		const child = object.children[ i ];
 
-		if ( ! child.visible ) continue;
+		if ( child.visible === false && options.onlyVisible === true ) continue;
 
 		let childNode;
 
@@ -489,7 +490,7 @@ function buildHierarchy( object, parentNode, materials, usedNames, files ) {
 		if ( childNode ) {
 
 			parentNode.addChild( childNode );
-			buildHierarchy( child, childNode, materials, usedNames, files );
+			buildHierarchy( child, childNode, materials, usedNames, files, options );
 
 		}
 
@@ -1203,6 +1204,7 @@ function buildCamera( camera, usedNames ) {
  * @typedef {Object} USDZExporter~Options
  * @property {number} [maxTextureSize=1024] - The maximum texture size that is going to be exported.
  * @property {boolean} [includeAnchoringProperties=true] - Whether to include anchoring properties or not.
+ * @property {boolean} [onlyVisible=true] - Export only visible 3D objects.
  * @property {Object} [ar] - If `includeAnchoringProperties` is set to `true`, the anchoring type and alignment
  * can be configured via `ar.anchoring.type` and `ar.planeAnchoring.alignment`.
  * @property {boolean} [quickLookCompatible=false] - Whether to make the exported USDZ compatible to QuickLook

+ 77 - 0
test/unit/addons/exporters/USDZExporter.tests.js

@@ -90,6 +90,83 @@ export default QUnit.module( 'Addons', () => {
 
 			} );
 
+			QUnit.test( 'export scene with onlyVisible option', async ( assert ) => {
+
+				const exporter = new USDZExporter( );
+
+				const scene = new Scene();
+
+				const geometry = new BoxGeometry( 1, 1, 1 );
+				const material1 = new MeshStandardMaterial( { color: 0xff0000 } );
+				const material2 = new MeshStandardMaterial( { color: 0x00ff00 } );
+
+				const box1 = new Mesh( geometry, material1 );
+				box1.name = 'box1';
+				box1.position.set( - 1, 0, 0 );
+
+				const box2 = new Mesh( geometry, material2 );
+				box2.name = 'box2';
+				box2.position.set( 1, 0, 0 );
+				box2.visible = false;
+
+				scene.add( box1 );
+				scene.add( box2 );
+
+				// onlyVisible = true
+
+				const options = {
+					onlyVisible: true,
+				};
+				const exportResult = await exporter.parseAsync( scene, options );
+
+				assert.ok(
+					exportResult.buffer instanceof ArrayBuffer,
+					'Export returns an ArrayBuffer'
+				);
+				assert.ok(
+					exportResult.buffer.byteLength > 0,
+					'ArrayBuffer has non-zero length'
+				);
+
+				const unzipped = unzipSync( exportResult );
+				const fileNames = Object.keys( unzipped );
+				const modelFileName = 'model.usda';
+
+				assert.ok( fileNames.includes( modelFileName ), `ZIP contains ${modelFileName}` );
+
+				const usdaContent = strFromU8( unzipped[ modelFileName ] );
+				assert.ok( isValidUSDA( usdaContent ), `${modelFileName} is valid USDA` );
+
+				assert.ok( usdaContent.includes( 'box1' ), 'USDA contains box1' );
+				assert.ok( ! usdaContent.includes( 'box2' ), 'USDA does not contain box2' );
+
+				// onlyVisible = false
+
+				options.onlyVisible = false;
+				const exportResult2 = await exporter.parseAsync( scene, options );
+
+				assert.ok(
+					exportResult2.buffer instanceof ArrayBuffer,
+					'Export returns an ArrayBuffer'
+				);
+				assert.ok(
+					exportResult2.buffer.byteLength > 0,
+					'ArrayBuffer has non-zero length'
+				);
+
+				const unzipped2 = unzipSync( exportResult2 );
+				const fileNames2 = Object.keys( unzipped2 );
+
+				assert.ok( fileNames2.includes( modelFileName ), `ZIP contains ${modelFileName}` );
+
+				const usdaContent2 = strFromU8( unzipped2[ modelFileName ] );
+				assert.ok( isValidUSDA( usdaContent2 ), `${modelFileName} is valid USDA` );
+
+				assert.ok( usdaContent2.includes( 'box1' ), 'USDA contains box1' );
+				assert.ok( usdaContent2.includes( 'box2' ), 'USDA contains box2' );
+
+			} );
+
 		} );
 
 	} );

粤ICP备19079148号