-
-
Notifications
You must be signed in to change notification settings - Fork 36.1k
Description
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:
- Create an array with file names for GLB files
- Create new instance of DRACOLoaer for when loading each file
- 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