Multiple Scenes with One Asset (glb) and Multiple Views (Scissors / Cameras)

Hi All,

Big time Babylon user, first time forum poster :wink:

I have a query regarding the ability to use one asset (an outside file .glb for example) for multiple scenes.

What I plan to do is to have different meshes from the same model appear in different scenes, for example one model loaded and scene 1 contains all meshes, scene 2 contains only 3/4 meshes, etc, etc
Then i would be able to switch through scenes to see each result.

Is this possible? At present, I can “ImportMesh” into a scene but I feel if I do this with multiple scenes then I would be loading the asset(s) (.glb file) more than once as Import mesh seems to be for a specific scene only.


I am also planning to be able to view the scene(s) through “enableScissor” and “splitting” the views through manipulating the engine width and height and using multiple cameras. I mention this to give more context.

1 Like

Hey you can maybe do it with one scene using Containers?
Asset Containers | Babylon.js Documentation

Here is the quick example - https://playground.babylonjs.com/#5NFRVE#61
Toggle Asset containers with any key press.
Actually in this example there is just one scene with two containers; if you need more you can add them through container.scene property.
If you are planning to use multiviews you may control cameras with container.cameras property.

Hi @Deltakosh and @labris

Thank you for the fast replies. I feel this approach is heading in the right direction but having looked at “asset containers” i feel this is still limited to a scene by scene basis.

Here is a quick PG to hopefully highlight what I’m trying to do.

You can see I’m using more than one scene to achieve this.

Here I have a split screen using “enableScissors” on the engine. (I will be animating the position of the split in a final draft). What I hope to achieve is to have one area of the engine show just a part of the model and the other area to show the whole model. But, I think that in this playground I am “loading” the model twice? When using ImportMesh?

By the way, wireframe isn’t necessary. I have just used this so you can see the split more clearly.

Correct. Not a bad thing per se (the browser network cache will make it almost transparent)

Would this be the same if there were more scenes like 4/5 on the same page?

The final output may have a .glb file that is quite large so I’m looking to optimise as much as I can.

Yes you will have multiple times in memory as scene are independent containers (hence my recommendation to use AssetContainer)

But from network side you should be covered

Can you share the containers across scenes?

e.g Add assets to container and then instead of addAllToScene() have a addToScene(scene)

or is there perhaps another way to get the scissor approach without using scenes?

Apologies for all the questions but I understand (as much as I can) the individual parts but just putting everything together for what I want is proving the more difficult part.

No unfortunately. Nothing can be shared between scenes (per design so you can delete a scene and be sure there is no leak)

scissor can happen anytime within the scene. YOu can turn it on and off per mesh if you want to (using mesh.onBeforeRenderObservable)

OK. Understood. Would it be ok to do something like this …

var container0 = new BABYLON.AssetContainer(scene0);
var container1 = new BABYLON.AssetContainer(scene1);

BABYLON.SceneLoader.ImportMesh(
        null,
        "https://models.babylonjs.com/Marble/marbleTower/",
        "marbleTower.gltf",
        scene0,
        function (meshes) {
            //console.log(meshes)
            for(let i=0; i < meshes.length; i++){
                container0.meshes.push(meshes[i]);
                if(meshes[i].name === "wheel"){
                    container1.meshes.push(meshes[i])
                }
            }
            container0.addAllToScene();
            container1.addAllToScene();
        }
    );

and then I can still use the same 1 engine many scenes approach

Or have 1 scene and add all the meshes and then run

mesh.onBeforeRenderObservable.add(()=>{
        var e = scene.getEngine();
        var w = e.getRenderWidth();
        var h = e.getRenderHeight();
        e.enableScissor(0,0,w,h)
        e.clear(scene0.clearColor, true, true, true);
    })

Yes, and disable it on mesh.onAfterRenderObservable

Sorry for dragging this topic up again but I have a problem that I can’t seem to get my head around. When using the above PG (specifically the code inside it) on a local rendition I seem to run into the fact that I lose the material. It seems to render in white.

It’s fine in the PG but not on my computer locally.

Any ideas?

This is really hard to tell without more information but at a first glance it is not related to the same problem of scissors

1 Like

Hi @sebavan Thanks for the reply. I moved the “before render” (with the enable scissor) code into the callback of the ImportMesh function and everything renders fine. I’m guessing it’s not loading completely before trying to enable scissor and render.

If I remove the scissor it renders fine. If I render one scene only it renders fine (i.e with all materials in model file) it’s just when I add the scissors code.

Just to clarify this is how it looks from a code perspective

BABYLON.SceneLoader.ImportMeshAsync(
    null,
    "https://models.babylonjs.com/Marble/marbleTower/",
    "marbleTower.gltf",
    scene0
)
.then(result => {
    scene0.onBeforeCameraRenderObservable.add(()=>{
        var e = scene0.getEngine();
        var w = e.getRenderWidth();
        var h = e.getRenderHeight();
        e.enableScissor(0,0,w,h)
        e.clear(scene0.clearColor, true, true, true);
    })
})

instead of

BABYLON.SceneLoader.ImportMeshAsync(
    null,
    "https://models.babylonjs.com/Marble/marbleTower/",
    "marbleTower.gltf",
    scene0
)
.then(result => {
    
})

scene0.onBeforeCameraRenderObservable.add(()=>{
    var e = scene0.getEngine();
    var w = e.getRenderWidth();
    var h = e.getRenderHeight();
    e.enableScissor(0,0,w,h)
    e.clear(scene0.clearColor, true, true, true);
})

A playground would definitely help here ?

1 Like

Hey Qamelian - did you manage to share one .glb asset between scenes in the end? I’m trying to do the same and can’t figure it out!

Thanks,
Adam

edit: for future reference…

The solution to this was to load and then .serialise the meshes / materials / geometries you want to share between scenes and then .parse them into each scene you want them in.

I had like 30 scenes and had to load my .glb asset for each of them, which took a while before this, and now I just load once and it’s waaay quicker.