Skip to content

Multiple DRACOLoader instances to load multiple GLB files fails on iOS #22445

@manmohanbishnoi

Description

@manmohanbishnoi

Describe the bug

When trying to load multiple GLB files that are DRACO compressed the DRACOLoader crashes sometimes. (no errors in console)

To Reproduce

Steps to reproduce the behavior:

  1. Create an array with file names for GLB files
  2. Create new instance of DRACOLoaer for when loading each file
  3. Refresh a few times.

I noticed that sometimes just one file loaded, sometimes 2 but as per my code below they were not added to the scene because DRACOLoader for the remaining file did not finish.
Additionally, which file(s) failed to load was also random from the array.
At random page refresh sometimes it was able to load all three GLB files and they were properly added to the screen.

Fix: @manthrax suggested to initialize a DRACOLoader instance in global state and reuse that in loadModelFile() instead of creating a new DRACOLoader instance for each file.

Code

// this array holds file names to load
const ModelList = [
    {
      fileName: "file1.glb",
    },
    {
      fileName: "file2.glb",
    },
    {
      fileName: "file3.glb",
    },
  ];
var loadedModels = []; // used to store scenes for later manipulation

loadModelFile = (fileName, path) => {
    return new Promise((resolve) => {
      let dracoLoader = new DRACOLoader();
      dracoLoader.setDecoderPath("assets/js/libs/draco/gltf/");
      let loader = new GLTFLoader();

      loader.setDRACOLoader(dracoLoader);

      loader.load(`${path}${fileName}`, (gltf) => {
        console.info("GLTF file load complete");

        gltf.scene.rotateY(this.modelRot * THREE.Math.DEG2RAD);
        gltf.scene.scale.set(this.modelScale, this.modelScale, this.modelScale);

        gltf.scene.traverse((child) => {
          if (child.isMesh) {
            console.log(`Material: ${child.material.name}`);

            // this HDR image is already loaded
            child.material.envMap = hdrBackground;
            child.frustumCulled = false;
          }
        });
        console.log(`DONE ${fileName}`);

        resolve({ fileName: fileName, gltf: gltf });
      });
    });
  };

  load3DModels = (list, destination, path = "assets/3d/") => {
    let promises = [];

    for (let j in list) {
      let mt = list[j];

      promises.push(this.loadModelFile(mt.fileName, path));
    }

    return Promise.all(promises).then((result) => {
      console.log("All 3D files loaded: ", result);

      for (let r in result) {
        let res = result[r];
        console.log(res);

        // save in associative array for easy manipulation
        destination[res.fileName] = res.gltf;
      }

      return new Promise((resolve) => {
        resolve(destination);
      });
    });
  };

loadHDRTexture = (filename) => {
    return new Promise((resolve) => {
      new RGBELoader()
        .setDataType(THREE.UnsignedByteType)
        .setPath("assets/3d/textures/envMaps/")
        .load(filename, (texture) => {
          resolve(texture);
        });
    });
  };

loadHDRTexture(HDRIMap).then((hdrTexture) => {
     hdrCubeRenderTarget =
        pmremGenerator.fromEquirectangular(hdrTexture);
        hdrBackground =hdrCubeRenderTarget.texture; // we use this HDRi later
        // load 3D models
        load3DModels(ModelList, loadedModels);.then(() => {
        animate(); // start render loop
      });
    });

Expected behavior

All GLB files should have loaded.

Platform:

  • Device: Mobile
  • OS: iOS
  • Browser: Chrome, Safari (I did not test on others)
  • Three.js version: r132

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions