onSuccess and onProgress callbacks not working well with incremental loading in terms of tracking completion

  • I am using incremental loading, which is great, definitely I need to use it
  • I am including two versions of the model, one in high detail and one in low detail created with the limited dissolve feature of blender. The high res weights 15 megabytes, the low res weights just 1 megabyte
  • the objective is that the incremental loading first makes the low res version appear quickly, and this works
  • seconds later the high res version is loaded and appears. This works
  • I can hide the low res version using “visibility” of that mesh. The problem is that I need to detect when the entire incremental loading has completed in order to do that.
  • and the onProgress function is not really working well with incremental loading as it automatically gives 100% from the beginning.

With the help of people from the community I have tried a few things but with no success. No matter what I try, with incremental loading, both the number of meshes loaded and the percentages just go to max from the beginning so its not possible to detect when the last stuff has loaded.

This really is a big issue, because in this way I cannot know when to hide the low res model, neither of course can I show intermediate loading percentages either.

I hope that you know some tricks to:

  • first display the loading percentage using incremental loading so that people can see how much is left to load
  • detect when the entire incremental loading has completed so that I can hide the low res mesh and keep just the high res one

thank you very much :slight_smile:

On progress is not something you should based your loading strategy from and it would be good to keep only one thread to discuss the same issue.

@bghgary, correct me if I am wrong but the progress is only handled by the GLTF loader ???

@sebavan thank you and sorry about that, I just thought I would bring it to the attention of the bugs threads, I understand you don’t see this as a bug; in my case this really blocks my project quite a lot, because the incremental loading is great and really necessary for me, but if you cannot detect anything about its temporal execution, neither middle stages neither completion, I think that’s something that should probably be provided in some manner, lets see what you think, thank you again for the great support of this community :slight_smile:

Full completion is available either in callback or when the promise return as explained on the other thread. The only issue is the percentage and in this case it would anyway not help you as it would not provide you with the current created objects but only the network related info of the download.

I believe that is correct, yes. The progress reported by the glTF loader is for the files being downloaded, so it does not mean that the asset has loaded 100%.

@javismiles Can you provide a playground of what you are trying to do?

@sebavan @bghgary thank you for your help, so:

  • interesting, I will check the promise option to see if that helps with detecting full completion, will explore it more
  • the project is already integrated with a lot of react stuff and different files, that’s why i cannot provide a playground, in any case really the part we are talking about is super simple, it’s just using sceneloader.append to load an incremental .babylon file that inside has a lowres and a highres model so that I first show quickly the low res model and seconds later the high res one replaces the low res one (well that’s the plan if i manage to detect the full completion of the loading :wink: )

We don’t need or want the full scenario. It would be a lot easier to help if there is a minimal scenario in a playground so that we can help with the code.

@bghgary @sebavan

  • I just implemented the promise with the async function successfully, but same issue happens, using incremental loading it immediately jumps to the promise and so I cannot hide the low res model when it truly fully loads the large one, same issue; seems that so far the only alternative would to be to load separately low res and high res files

  • I understand about the playground, I will see if I can create a small example of what Im trying to do

actually loading separately low and high res files won’t work either (with incremental loading), because the problem is that with incremental loading the promises jump immediately so you are not detecting completion, just beginning of loading apparently; the only way seems to be to get rid completely of the incremental loading unfortunately, which was such a great idea, but ok then it could be non incremental and separately in async two different files and then I guess I could detect loading percentage and completion finally

what im not sure about is that I am using createDefaultEnvironment in the callback on success, and:
" Since the createDefault... helpers take into account any models in the scene they can only be applied after the model is loaded and so are placed in the callback function"

if I split things in different loads, I wonder how the createdefaultEnv will behave

You should call it at the end of your first batch :slight_smile: and all will work as you wish

@sebavan @bghgary
Oh yes, this works, thank you very much for being with me all the way sorting this out, I got to a good solution which works like this:

  • No more incremental loading, good bye incremental loading

  • Async load of low resolution model with a promise that then establishes environment, etc, etc
    SceneLoader.AppendAsync(
    “./models/lr/lr.babylon”,
    “”,
    scene,
    function (evt) {}
    ).then((scene) => {… etc, etc

  • Async load of high resolution model with a onprogress function that updates the percentage of loading and now yes, now it works, I can see the intermediate percentages going up :wink:
    SceneLoader.AppendAsync("./models/hr/hr.babylon", “”, scene, function (evt) {
    var loadedPercent = 0;
    if (evt.lengthComputable) {
    loadedPercent = ((evt.loaded * 100) / evt.total).toFixed();
    } else {
    var dlCount = evt.loaded / (1024 * 1024);
    loadedPercent = Math.floor(dlCount * 100.0) / 100.0;
    }

    props.myprops.updatePer(loadedPercent);
    etc, etc

  • Finally, in the promise of the high res model I hide the low res model:
    }).then((scene) => {
    scene.meshes[7].material.backFaceCulling = false;
    scene.meshes[0].visibility = 0;
    });

Brilliant, this works really well, the low res model loads quickly, the percentage numbers move up gradually and when they reach 100, the high res model replaces the low res model.

Is there a way to do a nice cross fading to hide the low res and show the high res? at the moment its a sudden hiding and sudden appearing of low and high res model

thank you so much again for your great help, the babylon community is awesome! :slight_smile:

1 Like

just animate the opacity this would be the easiest: Introduction to Animations | Babylon.js Documentation

high res opacity from 0 to 1 and low res from 1 to 0

Cause you probably have a typo somewhere. Could you share a playground reproducing the issue ?

@sebavan now it works great with this:

Animation.CreateAndStartAnimation(
  "a1",
  scene.meshes[0],
  "visibility",
  30,
  300,
  1,
  0,
  0
); 

now I have to do the same for a fadein, I guess for fadein to work mmm the mesh should start with opacity 0 mmm, how can i make it have initial opacity of 0 i wonder

basically i need this but set initial condition

Animation.CreateAndStartAnimation(
“a1”,
scene.meshes[7],
“visibility”,
30,
100,
0,
1,
0
);

Animation.CreateAndStartAnimation(
  "a2",
  scene.meshes[0],
  "visibility",
  30,
  100,
  1,
  0,
  0
);

Not sure to understand but without playground to highlight the issue it will get pretty hard to help.

you are right, basically just wondering how can i load a mesh that is loaded hidden so it loads with visibility 0 from the beginning

just set the visibility to 0 in the onSuccess Callback or right after the async call

1 Like