Load multiple files fast

To our current situation. We work on finding a 3D-library in which we can load multiple .gltf or .glb files into. All those files together create one big model.

This is how we do it. First we get a json from the backend in which we can see how many objects are coming, their guid, their position and rotation and on which object they reffer to. After that we have a stream of objects which we will recieve from the backend. Based on the json we know how often we need to clone each object. Now we need to load with all this information the model into the scene.

We have already tried many different ways of loading.
AssetContainer
With the AssetContainer we where able to collect all Elements and load them in one command. But inside the container each file was loaded single and took over 3 minutes to load all.

Mesh Task
With the Task Loading we have the same problem as with the AssetContainer. Collecting all Elements in single Tasks and loading them in one go. But also here the loading process was the same.

LoadAsync
This is our current solution and also the best one so far. We load all the objects async and after that clone it and position it as many times as we need it. It currently takes about 30-40 seconds which we look to improve.

Now loading the model as one file is no option. The only way we could do this if we would be able to merge all the files or meshes together as one and then load it. When we load the model as one file it will take about 3-4 seconds. Loading it in our current solution (LoadAysnc and Clone) is about 30-40 seconds.

What are our options to make the loading process faster?

First you should have a look at the profile and see where the time is really spent (download vs runtime).

Then you could rely on MSFT_LOD extension @bghgary could provide guidance to have a LOD system where the assets would have several resolution helping in reducing your overall time to first frame.

All of these methods, when loading a glTF, loads using the same code. They are all asynchronous and should load in similar speeds.

+1

You can try looking at some documentation I wrote about MSFT_lod that might help?

Something looks out of place in your description. You say loading as a single file takes 3-4 seconds, but as multiples it takes 30-40. Really think you need do profiling as others have said. Chromeseems best for that.

There is also another way. That is SceneLoader.

BABYLON.SceneLoader.Append(url, "file1.glb", scene);
BABYLON.SceneLoader.Append(url, "file2.glb", scene);
BABYLON.SceneLoader.Append(url, "file3.glb", scene);
scene.executeWhenReady( () => {
    // do stuff
}

I never do .glb files. This works for .babylon files & think it should work.

@Patrick_Luthi, have you considered the example Loading two glTF assets in parallel in Use Promises - Babylon.js Documentation?

Currently we working just on the runtime progress. The Loading progress isnt yet a problem but i will definitely look into MSFT_LOD, but as I understand it wont help me speed up the process of loading the files into babylon.

Our current situation is that we have a big modell. We get all the elements (like walls, windows, doors, etc.) as a single gltf or glb file. Maybe you know a solution how to do this the best way (combine the gltf files or any other way of loading them together).

I forgot to mention that this is our current solution. We load them as promises. Below you will find our code solution.

var geometryPromises = [];
var positionMesh = function (mesh, pos, rot) {
    mesh.position.x = pos[0] / 1000;
    mesh.position.y = pos[1] / 1000;
    mesh.position.z = pos[2] / 1000;
    mesh.rotation.x = rot[1];
    mesh.rotation.y = rot[0];
    mesh.rotation.z = rot[2];
    // mesh.rotation.x = (rot[0] / Math.PI * 180);
    // mesh.rotation.y = (rot[2] / Math.PI * 180);
    // mesh.rotation.z = (-rot[1] / Math.PI * 180);
    mesh.rotationQuaternion = null;
    // mesh.rotationQuaternion = new Quaternion(-0.707107, 0, 0, 0.707107);
};
		for (let geom in geometryMap) {
			geometryPromises.push(
				function () {
					return BABYLON.SceneLoader.ImportMeshAsync(null, "data/", geom + ".glb", scene).then(function (result) {

						let bimProducts = geometryMap[geom];
						positionMesh(result.meshes[1], bimProducts[0].position, bimProducts[0].rotation);
						
						for (let i = 1; i < bimProducts.length; i++) {
							let clone = result.meshes[1].clone(bimProducts[i].GlobalId);
							
							positionMesh(clone, bimProducts[i].position, bimProducts[i].rotation);
							if (result.meshes[i] != undefined) meshArray.push(result.meshes[i]);
						}
					})
				}
			);
		}

		console.log("Total geometries: " + geometryPromises.length);
		let promises = geometryPromises;
		promises.forEach(f => f());
		console.log(promises);
		
		Promise.all(promises).then(() => {
			// console.log('Finished!');
		});

So i was able to find the problem, with the help of @bghgary, which was the reason for the long loading time.
It turned out that Scene.markAllMaterialsAsDirty was the problem. We have in every single .gltf file a materials assets which takes time to load. One option would be to add some unique id metadata to the glTF and load the materials using a loader extension to prevent duplicates.

For now we just called
scene.blockMaterialDirtyMechanism = true;
before loading and after it completed it we call
scene.blockMaterialDirtyMechanism = false;
again and set it to false. Now the loading time is down to couple seconds.

1 Like