Adding large object to the scene

Hello.
Now I have a problem when adding big objects to the scene. It can freeze the game up to 2 seconds, and It’s not right. I use attachChild() with app.enqueue, because in another way It’ll not work. What about partially adding objects, like 200 triangles per frame? How can I make something like that?

I use attachChild() with app.enqueue, because in another way It’ll not work.

Then you do something wrong if you dont know reason.
The reason is probably that use use different thread or somehow out of main thread.(that is fine if its intended)

suggestions:

  1. use .j3o format that load faster
  2. split model into parts
  3. use special thread to load model in this thread, and just add loaded model result in enqueue
  4. make “loading” screen?

note, i load 10 000 triangle models without single freeze, because i load them in thread.

I have tried copying attachChild() realization to use part of it in an asynchronous thread, bud method setParent() in the object which I want to add is packaged, so I cant use it. And I am generating models in a procedural way, so I cant use files to add them. The loading screen is not also my variant because its a procedural landscape that generates new terrain when the player walks.

well, i also use on-demand-load models and terrain.

all you need is just load it in “background”(asynchronous thread like you do) and put only “attachChild” within enqueue() block. Leave loading code out of enqueue so game will work without freeze, while model will load in asynchronius thread.

I already generate all objects in another thread, and in my enqueue is only attachChild with it

maybe you need put Thread.MIN_PRIORITY IDK…

myself i dont have freeze at all.

how many triangles it have? more than milion or 100k? It might also depend on how many materials it load. (each material take a time to load)

It probably hangs when the mesh is uploaded to the gpu. Is it a single mesh or multiple objects?

It has about ~3000 of triangles. But around 10 of them can be added within a second. Maybe making something like a queue for them can help. I copy material before applying it to the object.

3000 is really not that much. But is it for Android or CPU?

It is for PC, I don’t plan to support Android at all.

for some bigger models i were “preloading them” when game load.

but for models like 3k tris i load them on demand and didnt seen freeze so far.

maybe worth to check if you have some “synchronize thread” code that cause main(render) thread wait?

and how many materials/textures it have? also not sure here(not remember), but maybe 4k+ textures might take time to load into gpu

in your place i would try load this model without materials first and see

Also there were many topics, with stupid issues like where people were loading same model 100 times instead 1 time, so worth to debug all first.

Ok, so you have multiple objects with 3000 triangles each.

You can try something like this

ublic class ProgressiveLoaderAppstate extends AbstractAppState{
    private final RenderManager rm;
    private final ConcurrentLinkedQueue<Geometry> loadingQueue=new ConcurrentLinkedQueue<Geometry>();
    private final int spatialsToLoadPerFrame;

    public ProgressiveLoaderAppstate(RenderManager rm,int spatialsToLoadPerFrame){
        this.rm=rm;
        this.spatialsToLoadPerFrame=spatialsToLoadPerFrame;
    }
    
    public void loadScene(Node scene){
        scene.depthFirstTraversal(spatial->{
            if(spatial instanceof Geometry){
                loadingQueue.add((Geometry)spatial); // add geometries to loading queue
            }
        });
    }

    public boolean isReady(){
        return loadingQueue.size()==0;
    }

    @Override
    public void update(float tpf) {
        super.update(tpf);
        if(isReady())return;
        for(int i=0;i<spatialsToLoadPerFrame;i++)rm.preloadScene(loadingQueue.remove());
    }
    
}

Usage:

      // on init
        ProgressiveLoaderAppstate loader=new ProgressiveLoaderAppstate(renderManager, 1);
        stateManager.attach(loader);
        loader.loadScene(object1);
        loader.loadScene(object2);

        // on update
        if(loader.isReady()){
            //continue with game logic
        }

It will save a reference to each geometry composing your nodes and load one per frame using renderManager. preloadScene

When loader.isReady() returns true, you are free to do whatever you want with those nodes, since they will be already loaded on gpu, attaching/detaching them won’t change this

4 Likes

I have tried removing copying materials for each chunk, also I have moved all code from the main update to the game logic thread. Now it works A LOT better even with bigger chunks. Also thanks, @RiccardoBlb for that code. I will try to implement it with my logic.

Also try what Riccardo provided. Its ready solution that just manage split object loading.

because even if done in thread, putting/loading everything in same “frame” might be problematic.

But what about loading only a part of Geometry’s mesh’s triangles? To make it possible to load large objects on-demand.

it is possible, ofc. But i dont see reason. Only for models(single objects) like 100k+ tris i would see reason. IMO You should not see any freeze up to 10k models on good computer if you will attach it the way we said.

Also please note, even if you send part of triangles, second time you would probably need send “merged” parts anyway, so GPU will wait anyway. Thats why its better to split into “objects”, since they have separate GPU Draw call and separate mesh.

But here is also problem, because the more draw-calls you make, the slower game will work.

So you need have gold balance here between single-big-objects and a lot-small-objects.

There are also something like “batching” methods to make 1 object from 100 objects for example.

Anyway what you really need is to load multiple smaller-objects frame by frame

Thanks