LOD implementation not working

Hello I think I’ve put enough time in this matter and didn’t found the answer. Maybe some one will get this clear for me.

Here is the code simple first of all.

spa[15] = assetManager.loadModel("Models/Environment/Rock/BigRock/GiantRock.j3o"); spa[15].setLocalTranslation(0, -6, 0); spa[15].setLocalScale(3f); Node test = (Node)spa[15];
    for (Spatial spatial : test.getChildren()) {
        if (spatial instanceof Geometry) {
            
             spatial.addControl(lc);
             spatial.setLodLevel(4);
             System.out.println("Adding control");
        }
    }
    rockBody  = new RigidBodyControl(0);
    spa[15].addControl(rockBody);

I used the SDK to generate the LOD on the model, it seem to work. I can see multiple LOD in it property.
But the problem seem to be the activation of the LodControl.
I Travel the Node to get the geometry. (I would suggest to make a support for spatial inside the LODControl class to simplify the thing)

Anyway it doesn’t seem to work at all, there is no variation in the model inside the game, i went far far far away of it and nothing seem to change at all. If anyone as an idea of what i am doing wrong. Then please tell me I will do anything to make this work. My game need more visible model and this would increase my fps greatly!

Just at a glance, it looks like you are adding the same control instance to multiple spatials. You can’t do that. So something you are doing is backwards.

1 Like

Good to know, but if I clone the spatial multiple time, do I need to make a new control or will it clone by it self?

I would suggest to write what you just said in the Tutorial! I didn’t see anything that specified this :S

@n3cr0 said: Good to know, but if I clone the spatial multiple time, do I need to make a new control or will it clone by it self?

All controls get cloned automatically.
Clones of geometries share meshes unless they are animated, then they get cloned too

I didn’t get to make it work. Here’s the spatial i am using and the LOD pre generated.

I only wonder what I’m doing wrong. I’ve try to add the Lod control before cloning, then after but none of the two worked. Maybe i am not getting the right Geometry?

I did a small modification on the code to get the geometry.

    spa[15] = assetManager.loadModel("Models/Environment/Rock/BigRock/GiantRock.j3o");        
    LodControl lc = new LodControl();
    Node test = (Node)spa[15];
    Geometry mygeo = (Geometry) test.getChild(0);
    mygeo.addControl(lc);

How do you know that it doesn’t work? I mean, it can be hard to notice sometimes.(which is good btw).

Look at TestLodStress in the repo it does exactly what you want to do.
you don’t need this ->spatial.setLodLevel(4);
the control will change lod levels according to camera distance. So you have to get the camera away from the objects and you should see the number of triangle get down (maybe test with a scene with only the rock)

This will increase performance, but maybe not as much as you wish. Imo for rocks you should go with a batch+paging strategy instead.

@nehon said: This will increase performance, but maybe not as much as you wish. Imo for rocks you should go with a batch+paging strategy instead.

I can confirm this, batching vastly improved my performance just recently.

However I have a question about the current Lod implementation myself. I hope it doesn’t derail the topic too much - it kinda fits the title.

I have quite a lot of trees in my scene with about 912 triangles. However they can easily be replaced by cross-shaped trees like this:

Those obviously only have 8 triangles.

They have a different material than the original tree, so they can’t be handled by the stock Lod Control, can they?
So the solution is to write my own Lod Control which swaps out the models and rebatch the section of the map when LODs change?

This is the way I’m doing it right now and I just wondered if it is a good way to optimize in my situation or if I maybe missed something in the stock functionality.

Nope you’re doing the right thing.

Stock Lod implementation doesn’t switch meshes, it switches index buffers. That means that the number of vertices in the mesh is the same but the vertices are linked together differently resulting in less vertices and faces rendered.
For more advanced lod like the use case you describe you have to make your own control.

@nehon said: Nope you're doing the right thing.

Stock Lod implementation doesn’t switch meshes, it switches index buffers. That means that the number of vertices in the mesh is the same but the vertices are linked together differently resulting in less vertices and faces rendered.
For more advanced lod like the use case you describe you have to make your own control.

Ah, good to know.
Thank you.

@m41q I am in the same situation with the trees. I have also a normal model and one with 8 triangles.
I am using my own control to switch the models. But I try to avoid to rebatch so often (like you wrote in your other post). I am just rebatching when I have to add/remove a tree and not at a fixed time.

1 Like

@drothindev Haha, nice to hear :slight_smile:
I chose time based rebatching because I thought it might lead to less maintaining effort. (I don’t need to trigger rebatching if I program a woodcutter at some point).
I’ll see if
[java]
tile.attachChildAt(tile.detachChildAt(0), 0);
[/java]
fixes the issue. If not I’ll consider triggered rebatching as well.

I can explain how i know it doesnt work. My number of vertice never decrease event at 10k distance and over and i look at the model the whole time to see a change to it shape and i can’t see anything. So i must be doing something wrong during a part of the process (load model in concurrency, add lodcontrol, then clone it again using conccurency and to finish attach it to the scene Node) but nothing happen… :frowning: I have my own made flybycam but even if i use the original one i still see no change :S

package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.light.AmbientLight;
import com.jme3.math.ColorRGBA;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.LodControl;

/**

  • test

  • @author normenhansen
    */
    public class Main extends SimpleApplication {

    public static void main(String args) {
    Main app = new Main();
    app.start();
    }

    @Override
    public void simpleInitApp() {
    this.flyCam.setMoveSpeed(200);
    Spatial spa= assetManager.loadModel(“Models/GiantRock.j3o”);

     Node test = (Node)spa;
     
     Geometry mygeo = (Geometry) test.getChild(0);
     LodControl lc = new LodControl();
     mygeo.addControl(lc);
     
     spa.setLocalTranslation(0, -6, 0);
     spa.setLocalScale(5f);
     
     rootNode.attachChild(mygeo);
     
     
     AmbientLight ab = new AmbientLight();
     ab.setColor(ColorRGBA.White);
     rootNode.addLight(ab);
    

    }

    @Override
    public void simpleUpdate(float tpf) {
    //TODO: add update code
    }

    @Override
    public void simpleRender(RenderManager rm) {
    //TODO: add render code
    }
    }

I got to change the lod by my self and it worked! But not with the LodController >_> I know it s working in the stressLod.
Btw i am not the only one where it doesnt work. http://hub.jmonkeyengine.org/forum/topic/lod-in-jme/
And no one gave him an answer…

@nehon
I think I’ve found the “BUG”.
You can’t use Batch Geometry in the Sdk SceneExplorer… I tested the bug using the teapot, and the Lod Stopped to work with it.
(I will specify that I made a new LOD for the Teapot after I did the Batching, I am not that stupid!)

Now i got the LOD working.

But I still wonder, how am i supose to change the Distance at witch the LOD work? It seem the size of the object affect the distance for the Lod to get working. The distance is way to high when the model is huge.

Well the fact that you are batching the geoms was an important information. Indeed, you can’t use lod on a batched geometries for the good reason that batched objects may have different lod levels.

Also generating lod for the batched geom won’t give you good results because you may have some parts of the batch that are far away, but some close enough of the cam so that the Lod is never switched. I guess that’s the next issue you bumped into.

That’s why I was talking about batching and partitioning instead of using Lod. Lod is nice for independent objects like characters for example.

1 Like
@nehon said: Well the fact that you are batching the geoms was an important information. Indeed, you can't use lod on a batched geometries for the good reason that batched objects may have different lod levels.

Also generating lod for the batched geom won’t give you good results because you may have some parts of the batch that are far away, but some close enough of the cam so that the Lod is never switched. I guess that’s the next issue you bumped into.

That’s why I was talking about batching and partitioning instead of using Lod. Lod is nice for independent objects like characters for example.

Alright i got it tahnk you very much!

The only problem i get now is the distance increasing with the model size. Anyway I will probably use batch farther model instead!

Thank you @nehon