better way, Level of detail?

hi again,

I use the BGE own LOD system for many trees I create. Three steps are (low, middle, high)

but is the range reached to the lowest replacement I want that the object after another distance completely disappears.

best way a script? with emptys?

If you know more please post it here. thanks

Surely scripts.

It consists of two operations:

A) removing objects - which is pretty simple
B) adding objects - which is more complex as you need to know what object, where to add, and when

Have fun working that out :smiley:

PS: a really simple way is to use a zero vertex mesh a lowest detail. It reduces render effort to nearly zero. The effort on other aspects remains (scene graph, logic, …).

If you want to do it in script, you can’t just have a scene made in 3D viewport. Whole your map must be stored in dictionary(like this:


{
    "objects": {
        "tree 1": {
            "world position": [3.0, 1.67, 0.2],
            "local orientation": [[1, 0, 0], [0, 1, 0], [0, 0, 1]],
            "some more parameters": somemorevaues
        }
    }
}

)
After that you can control whole objects through script(add, remove procedurally when needed). This method must be effecient for framerates. At least I think so. This way you can also store some additional data for objects.

nice, getting the object by an property isn’t that hard:


from bge import logic

def get_lod_obj(cont):
    own = cont.owner
    objlist = logic.getCurrentScene().objects
    obj_lod_list = [o for o in objlist if "LOD_object" in o]
    print(obj_lod_list)

but how can I get the distance to an obj from the camera?

ok get it


for a in obj_lod_list:
        distance = own.getDistanceTo(a)
        print(a, distance)

have some code, but is it efficient?


from bge import logic

def get_lod_obj(cont):
    own = cont.owner
    objlist = logic.getCurrentScene().objects
    obj_lod_list = [o for o in objlist if "LOD_object" in o]

    for a in obj_lod_list:
        distance = own.getDistanceTo(a)
        print(a, distance)
          
        if distance <= 10:
            own.sendMessage("LOD_step1", "placeholder", str(a))

you can modify them directly in code(e.g. a.replaceMesh(a[“step1”])).
I don’t know if this is the best way, but it might work well. I will try to setup LOD script by myself.

I try something like that what I post below but if you have really lots of objects in the scene I get a frame-rate under 1 fps
its not effective.
for big scenes I need something different but to store all objects in pure library is very costly.

is there another way? like low poly scene and high poly scene and than replace it by render distance <-- is this effective?

You mean the bueraki method? Where you set the lowpoly scene as background scene? I’ll set it up right now;)

Script Based LOD
Camera LOD
Made 2 methods. I’m not sure, though, why does 2nd method have that offset. Also, you propably don’t need physics in the background scene.

in addition to adriansnetlis examples you should also use settings to turn of physics and visibility.
here is a small script i wrote to do exactly that (dutch comment, but you can figure it out easy)

def physics_lod(cont):    
    own             = cont.owner
    scene_objects   = own.scene.objects


    #plaats alle objects met de lod property in een array    
    lod_objects = [obj for obj in scene_objects if 'lod' in obj]
      


    #doorzoek de array    
    for obj in lod_objects:
                
        distance = own.getDistanceTo(obj)
            
        if distance &gt; 15:
                    
            #maak ontzichtbaar en stop physics
            obj.visible = False
            obj.suspendDynamics()
                
        else:
                    
            #maak zichtbaar en re-activeer physics
            obj.restoreDynamics()
            obj.visible = True

i also recommend to use:

lod_objects = [obj for obj in scene_objects if 'lod' in obj]

to get all lod objects and put them in an array indtead of the example where you append every file one by one, just let python do it for you.

cool thank you adriansnetlis, I prefer the bueraki method (of course have seen it on youtube) scriptbased LOD is if you have many objects in scene really leggy.

now I only need to repair this delay/offset, if everyone have some tips so please post it. thanks

and if I combine the bueraki method with the bge own LOD system it should work performance light. thanks

@adriansnetlis
can you set up an demo file where I can test your first option by saving data meshes in dictionary and load it from there?

@the_cannibal

I doubt it will help much but try changing the following


# turn the list into generator, list are memory intensive
lod_objects = (obj for obj in scene_objects if 'lod' in obj)

# localization, funtion look up is slower inside a loop
getDist = own.getDistanceTo 
    for obj in lod_objects:
        distance = getDist(obj)

I believe BluePrintRandom just recently posted some resources using kdtree, they are likely faster than looking up each and everyone objects in the scene

I suggest to stay away from culling single objects (especially at a forest).

Better identify an area.
-> When you determine an area should pop in you add all objects that belong to this area.
-> When you determine an area should be culled away you remove all objects that belong to this area.

This way you just need to identify areas, rather than a huge amount of objects.

The basic concept is the same as with single objects.

@Monster,
but how can I define some areas and how is it possible to make an smooth interpolation between areas?

groups? <- not really
more meshes in one object?
define by another object -> plane, Cube?
or something else?

I just experimented with ocluder physics type…
I parented a giant plane that covers the whole camera area to the camera and set the plane’s object color to transparent (so that one does not see that giant plane in the game)
Then I set the physics type to ocluder. Objects behind it won’t be rendered at all.
It gave me about 5-10 more fps, which on my laptop is a lot!

Isn’t this a common method to use for no detail objects?

Your areas should mainly reside in python.

Each area knows of the objects they belong to it. For example, you organize your forest in squares (can be any shape). So every tree, rock, bush (game objects) are known by the area.

The area should knows enough to create these game objects when they are not there (position, scale, orientation, template object for addObject) [alternative the area might know how to LibLoad the game objects … but this is an advanced topic].

Now you can now focus on managing areas (rather than on game objects).

When the player is that far away from an area (an area has a location within the 3D world), that none of it’s objects can be seen in the near future, you can remove all game objects without the player will notice (assuming there is no logic/physics that is needed).

With the squares this should not be that difficult. Please do not make the mistake to calculate the distance to all squares all the time. This will eat too much time when your world increases. Better find an efficient way to identify areas that just left the range. It might sound the same but is not. You do not need to touch all areas when moving around. There is a very limited number of areas that can have this condition. With a clever method you just touch the possible areas, rather than all areas.

I would try to draw the “before” and “after” situation with pen and paper. E.g. move the camera forward until I need to switch areas. Then check what areas that are and if there is a formula. Try it with other operations too (circling, moving diagonal) and check if the formula still fits.

While you do that you might discover a formula that gives you the areas that are just entering the range around the camera. Here belongs the same … efficient as possible.

With that you should get two sets of data:

A) areas that left range
B) areas that entered range

[Both should not be visible to the camera at that stage]

Now you process culling:
A1) remove all objects from areas of A)

and unculling:
B1) addObject all objects from areas of B)

That is the basic concept.

Thoughts:

  • areas can have counterparts in the 3D scene, but many areas (even when invisible) eat still processing power
  • you can organize areas in larger areas the same way as with single objects. You will get super areas. This can help on managing planet-size worlds.
  • large areas are easier to manage, but cause more objects to exist at the same time
  • unculling (adding) many objects of an area, can cause short time lags.
  • many small areas increase management overhead.
  • Yes you will need Python to do this.

thanks Monster
of course Python, that’s not the problem.

will create some demos next time.

thanks to all