mrdoob / three.js

JavaScript 3D Library.
https://threejs.org/
MIT License
101.71k stars 35.3k forks source link

USDZLoader.load() return TypeError #25743

Open ArzhMael opened 1 year ago

ArzhMael commented 1 year ago

Description

I get the following error while trying to use USDZLoader.load() on a .usdz file turned into a .zip file(*) or a .zip file.

TypeError: Cannot use 'in' operator to search for 'def ""' in undefined
    at findGeometry (three_examples_jsm_loaders_USDZLoader.js?v=2e1f0779:1873:17)
    at findMeshGeometry (three_examples_jsm_loaders_USDZLoader.js?v=2e1f0779:1866:16)
    at buildObject (three_examples_jsm_loaders_USDZLoader.js?v=2e1f0779:2043:38)
    at buildHierarchy (three_examples_jsm_loaders_USDZLoader.js?v=2e1f0779:2058:24)
    at buildHierarchy (three_examples_jsm_loaders_USDZLoader.js?v=2e1f0779:2063:11)
    at buildHierarchy (three_examples_jsm_loaders_USDZLoader.js?v=2e1f0779:2063:11)
    at buildHierarchy (three_examples_jsm_loaders_USDZLoader.js?v=2e1f0779:2063:11)
    at USDZLoader.parse (three_examples_jsm_loaders_USDZLoader.js?v=2e1f0779:2068:5)
    at Object.onLoad (three_examples_jsm_loaders_USDZLoader.js?v=2e1f0779:1813:22)
    at chunk-A3A6HU2X.js?v=2e1f0779:24244:20

(*) I did manually convert the .usdz file into a .zip file else if I don't do that - and use .usdz archive or extracted folder - I get invalid zip file error. seems it was due to a typo, but both the .zip and .usdz files still return me the same TypeError.

Reproduction steps

  1. Hosting local server with Vite.js : npx vite
  2. Trying to use USDZLoader.load() using path to .zip file

Code

import * as THREE from "three";
import { USDZLoader } from "three/examples/jsm/loaders/USDZLoader";

const scene = new THREE.Scene();

const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);
camera.position.set(3, 3, 3);
camera.lookAt(0, 0, 0);

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

const light = new THREE.SpotLight("#FFFFFF", 2);
scene.add(light);
light.position.set(3, 3, 3);

function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}
animate();

const usdzLoader = new USDZLoader();
usdzLoader.load(
  "./assets/RoomBureau.zip",
  (usdzScene) => {
    console.log(usdzScene);
    scene.add(usdzScene.scene);
  },
  undefined,
  (error) => {
    console.log(error);
  }
);

Live example

Screenshots

No response

Version

9.5.0

Device

Desktop

Browser

Chrome

OS

Windows

Mugen87 commented 1 year ago

(*) I did manually convert the .usdz file into a .zip file else if I don't do that - and use .usdz archive or extracted folder - I get invalid zip file error.

Do you mind sharing the original USDZ file in this thread?

ArzhMael commented 1 year ago

Here is a link to the complete repo. Thanks for your time ! https://github.com/Armel-WonderWalls/Import_USDZ_Test

Mugen87 commented 1 year ago

I can confirm that the asset RoomBureau.usdz can be displayed with preview on macOS but not with the three.js editor.

I'm not sure what's going wrong so far but it seems the asset is in a format that USDZLoader does currently not support.

ArzhMael commented 1 year ago

Okay.
I don't know if it may help but the asset has been generated using Apple's RoomPlan API.

dbt-lucka commented 1 year ago

prepend references is an array of wall references that three.js doesn't support. Actually the parser would need an implementation for [ first.

Here's another usdz that the editor couldn't load. room.zip

When changing the room0.usda by replacing the array with a direct reference to asset wall0.usda, I get the same error than OP.

Edit: This also is Apple Roomplan output.

Matt-McConway commented 9 months ago

Hey all,

I have managed to get a RoomPlan generated USDZ file loaded and rendering by patching the USDZLoader

This was just for a technical POC so it's very experimental, but it is possible! Good chance it breaks other stuff, and won't support all use cases, but for me I just wanted to render a CapturedRoom exported with the model export option

I've attached the room I was loading - fairly basic & no furniture - RoomModel.usdz.zip

Patch can be found in my gist

Just a couple of changes were required

  1. Change to the parser to check for array declaration
    • The issue I was having was the prepend references field in some of my .usda files being an array of asset paths instead of a single asset path
  2. Change to how geometries are built
    • Because there's now an array of assets, I merged them into a single BufferGeometry with the mergeGeometries util
    • I also added a check for finding the transform matrix, and apply it to the geometry being built
    • NOTE I doubt this change handles materials for each of these referenced assets, as the same material will be applied to the entire combined mesh

Hope this helps move things forward 😄