How to add multiple GLB models in the same scene?

Does there have some ways to load multiple GLB files in the same scene, and set their attributes like position, scale, cast/receive shadows etc. sperately?
So far, I only can write code like this:

loader.load( 'models/gltf/model.glb', function (gltf) {
					gltf.scene.position.x = 0;
					gltf.scene.position.y = 0;
					gltf.scene.position.z = 0;

					gltf.scene.rotation.y = Math.PI * 1.25;

					gltf.scene.scale.set(0.5,0.5,0.5);

					gltf.scene.traverse(function(node){
						if(node instanceof THREE.Mesh){
							node.castShadow = true;
							node.receiveShadow = true;
						}else{
							node.layers.disableAll();
						}
					});

					scene.add( gltf.scene );

But this is only one model in the scene.

Take a look at this example.
BeginnerExample step3 + step15

From the Collection of examples from discourse.threejs.org

1 Like

Thanks for your help, the problem of loading mutiple GLB models has solved.
And I have another question:
How to read the progress of loading these models in the scene?
Best can read all of files in the scene including models and HDR environment texture. Because I want to make a progress-bar of the whole scene, for now, the code I wrote like this, but I think it’s not right:

// Progrerss-bar
var manager = new THREE.LoadingManager();

function onProgress( xhr ) {
	if ( xhr.lengthComputable ) {

		var temp = xhr.loaded / xhr.total * 100;
		let loadingPercentage = Math.round(temp);

		progressBar.style.width = loadingPercentage + "%";

		if(xhr.loaded === xhr.total){
			progress.style.display = "none"   // hide the progress bar when the model loads done
		}
	}
}

function onError(){}
// model 1
const cbt = new THREE.Object3D();

loader.load('models/gltf/cpt0826zhiwu.glb',function (gltf){
cbt.add(gltf.scene);
cbt.scale.set(1,1,1);
cbt.position.set(0,0,0);
gltf.scene.traverse(function(node){
	if(node instanceof THREE.Mesh){
		node.castShadow = true;
		node.receiveShadow = true;
	}else{
		node.layers.disableAll();
		}
	});
// glass material in the model 1
const glass = cbt.getObjectByName('ćŻčè±Ą20866');
glass.material = new THREE.MeshPhysicalMaterial({
	color: 0x25282a, metalness: 0.02, roughness: 0.01, transmission: 1.0
});

scene.add(cbt);

},onProgress,onError);
// model 2
const ball = new THREE.Object3D();

loader.load('models/gltf/ball.glb',function(gltf){
	ball.add(gltf.scene);
	ball.scale.set(1,1,1);
	ball.position.set(25,0,25);
	gltf.scene.traverse(function(node){
	if(node instanceof THREE.Mesh){
		node.castShadow = true;
		node.receiveShadow = true;
	}else{
		node.layers.disableAll();
	}
});
scene.add(ball);
},onProgress,onError);

i don’t think your problem is solved tbh, it’s just deferred. each file loads async, how do you plan to respond to this? with polling? a timeout? in javascript if something is async the language gives you async/await and promises, i wonder why you don’t use that?

i’ll copy over from here: Npm run build does not include three.js dependencies - #14 by drcmda

async function app() {
  const loader = new GLTFLoader()
  const gltf = await new Promise((res, rej) => loader.load("/model.glb", res, rej))
  scene.add(gltf.scene)
  ...

if you have multiple assets avoid waterfalls like this (a waterfall is when assets load one after the other which is a waste of time, with promise.all everything loads concurrently, at the same time)

const [font, hdri, gltf] = await Promise.all([
  new Promise((res, rej) => fontLoader.load("/font.json", res, rej)),
  new Promise((res, rej) => rgbeLoader.load("/warehouse.hdr", res, rej)),
  new Promise((res, rej) => gltfLoader.load("/model.glb", res, rej)),
])
scene.add(gltf.scene)
scene.background = hdri
const font = new TextGeometry('hello', { font })
...

this already gives you a primitive way of dealing with loading status:

const status = document.querySelector('.status')
status.innerText = "Loading"
const [font, image, model] = await Promise.all(...)
status.innerText = ""
2 Likes