how to load multiple models in three.js
HTML Javascript

How to Load Multiple Models in Three.js using Promise

In this post, we’re going to talk about how to load multiple 3D model (or texture, objects, etc) using Promise.

Normally, if we want to load 3D model in three.js, we would do something like this.

new THREE.GLTFLoader().load('model/scene.gltf', result => { 
  model = result.scene.children[0]; //select first object in the model file
  model.position.set(0,0,0); //set model position
  scene.add(model); //add model to the scene
  // continue processing
});

Since the load method execute asynchronously, we’ll need to pass the callback function to continue the process once the loading is finished. So if we want to load multiple models, then your code would probably look like this.

//load first model
new THREE.GLTFLoader().load('model1/scene.gltf', result => { 
    doSomething();

  //load another model
  new THREE.GLTFLoader().load('model2/scene.gltf', result => {
      doSomething();

      // continue processing
      startRenderLoop();
      });
});

There is nothing wrong loading model this way. The problem is when you start to have more than couple things to load. You can’t start the rendering loop until everything is loaded. But how do we really know when? The answer is using Promise.

Instead of using callback function to continue the process, we’ll return a new Promise instead. So our new loader function should look like this.

function loadModel(url) {
  return new Promise(resolve => {
    new THREE.GLTFLoader().load(url, resolve);
  });
}

Suppose we want to load 3 models, we can do it like this.

let model1, model2, model3;

let p1 = loadModel('model1/scene.gltf').then(result => {  model1 = result.scene.children[0]; });
let p2 = loadModel('model2/scene.gltf').then(result => {  model2 = result.scene.children[0]; });
let p3 = loadModel('model3/scene.gltf').then(result => {  model3 = result.scene.children[0]; });

As you can see above, we’ll use then method to keep the loaded model with our variables. We also  keep the Promise returned from the loadModel function.

So now we can know when all models are loaded by checking those Promises in Promise.all()

//if all Promises resolved 
Promise.all([p1,p2,p3]).then(() => {
   //do something to the model
   model1.position.set(0,0,0);
   model2.position.set(0,20,0);
   model3.position.set(0,50,0);

   //add model to the scene
   scene.add(model1);
   scene.add(model2);
   scene.add(model3);
   
   //continue the process
   startRenderLoop();
});

The code might be longer than the traditional method but trust me it’s much less headache when you have lots of things to load in the scene. We can do this for other loaders like TextureLoader too.

function loadTexture(url) {
  return new Promise(resolve => {
    new THREE.TextureLoader().load(url, resolve);
  });
}

And that’s all for this post. Have fun creating stunning 3D website 🙂

Written By

Leave a Reply

Your email address will not be published. Required fields are marked *