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 🙂