Load in Meshes one after another without nesting

Hey,

I’m struggling a bit with trying to give meshes a loading order. I had it all up and running with nested functions, but turns out this impacts performance quite a lot the deeper the function calls go and animated models won’t animate untill all functions return.
I figured maybe promises will do the trick, but that turned to nesting too. I’m most likely too much of a newbie in JS to get them working correctly.

Now I’m getting my wanted prioritized loading like this:

var currentLoadingExponatNumber = 1;

function loadNext() {
    if (exponatLoaded) {
        exponatLoaded = false;
        // TODO: MAKE THIS DYNAMIC
        switch (currentLoadingExponatNumber) {
            case 1: 
                loadExponat2();
                break;
            case 2:
                loadExponat3();
                break;
            case 3:
                loadExponat4();
                break;
            case 4:
                loadExponat5();
                break;
            case 5:
                loadExponat6();
                break;
            case 6:
                loadExponat7();
                break;
            case 7:
                loadExponat8();
                break;
            case 8:
                scene.unregisterAfterRender(loadNext);
                break;
        }
        currentLoadingExponatNumber++;
    } 
}
loadExponat1();
scene.registerAfterRender(loadNext);

Everytime the SceneLoader has onSuccess I set exponatLoaded to true and get my wanted “loading one after another” effect.
However this seems very unlikely to be the best approach to me, as I would like to avoid to use scene.registerAfterRender. So maybe someone could lead me in a better direction.

Feel free to play around with my playground if you want https://playground.babylonjs.com/#59FFHD#48

Do you feel something bad in this function?
You may also use scene.onAfterRenderObservable if it suits you more :slight_smile: - https://playground.babylonjs.com/#59FFHD#55

var observer = scene.onAfterRenderObservable.add(function () {
    loadNext();
      if (scene.onAfterRenderObservable.hasObservers && currentLoadingExponatNumber >= 9) {
        scene.onAfterRenderObservable.remove(observer);
      }
});

I just don’t think I need to have a comparison every frame if I could just chain the different loading functions one after another. I mean it works and essentially it’s not too bad. I’m just looking at it from an optimization point of view.

What about using await?
https://playground.babylonjs.com/#RAUZ3Y
Edit: Whoops… https://playground.babylonjs.com/#RAUZ3Y#1

There’s ImportMeshAsync as well, but haven’t tried that myself.

1 Like

Await could be a good choice.


The article - Promise chaining is dead. Long live async/await - LogRocket Blog
From the user perspective I would just hide all loading assets behind a nice loading screen until they are ready. If you test your PG with average or low end laptop you’ll see that the scene is almost frozen anyway until all assets are loaded.

1 Like

Hi,

correct me if I’m wrong, but if you use await the scene freezes and you can’t interact with it anymore untill the await is through, right?

If you have low bandwidth the loading may take some time for bigger models. That’s why I want the user to be able to interact with an already loaded model. Waiting for everything to be loaded in is not really an option.

Here is short video illustrating my experience with your PG with average laptop and good bandwidth:

As you may notice, until all models are loaded (0:36) it is almost impossble to interact with the scene.

I know this is how it will be if the meshes are downloaded quickly. I don’t mind that you aren’t able to interact with a visible scene instead of not being able to interact with a loading screen (even on a relative powerful PC there’s lag :sweat_smile:).
But if you try chromes throttling the models won’t all get loaded at basically the same time. Even more so if I was to load other models that are bigger. And then the advantage of being able to interact with the first model will come forth.

You may use your PhotoDome instead of loading screen.

I don’t really get what you’re saying. The only loading screen there will be is for initialization of the scene and loading in the PhotoDome. Afterwards it’s going to be as discussed.

But what about my original question. Is there really no other way of chaining my loadings, substituting a every frame comparison check?

Promise chaining like in @Raggar example seems to be better.

Although Raggar uses await, which freezes the scene. :confused:

I think you are better off staying with your current solution.
I can’t really think of other ways of keeping responsiveness while loading meshes in a specific order - without nesting.

In my current project I’m planning on doing something like this:
https://playground.babylonjs.com/#CQ0B7V#2
Importing the meshes in a worker, and sending the VertexData instead of a serialized mesh. This prevents most hiccups and loading screens of sending and loading a serialized mesh. But my use-case is different than yours, as I need real-time dynamic loading of small meshes that all share the same material. (I tried serializing the material from the worker, but couldn’t quite get it to work).

If your current code works, keep it unless it presents an issue.

2 Likes

Hm, I will stay with the current solution and update this thread if I find another.

Thank you though for your playground Raggar! I read about worker threads, but don’t have the knowledge to utilize them. Your example is really interesting and helps understanding the workflow.

2 Likes