Homade LOD and Light hook manager

I have this written and it’s working well,

however there is some complex math I will need.

I have most of what is needed to “score” a light based on distance and angle,

but I don’t really know how to do it…

I want to populate closest few lights, and then a few mid range lights in the angle

lets say 6 lights…

how would you all do this?


import bge




def main():


    cont = bge.logic.getCurrentController()
    own = cont.owner
    LODlist=[]
    len=-1
    
    
    ## get list of all objects with LOD
    if 'LODList' not in own:
        for objects in bge.logic.getCurrentScene().objects:
            if 'LOD' in objects:
                
                LODlist+=[objects]
                len+=1
                
        own['LODList']=LODlist
        own['Len']=len
        own['index']=0
        
    else:
        
        
        s = own['index']
        x=0
        ##proccess 10 piece of the list per frame
        while (x<10):
            item = own['LODList'][own['index']]
            
            V= own.getVectTo(item)
            Distance = V[0]
            
           
            ##print(str(own['index'])+" Distance is "+str(Distance))
            ## set LOD if the unit is less then 100 units
            if Distance<100:
                ## get angle offset from player axis if its a light
                if 'Light' in item:
                    Ang = own.worldOrientation.col[2]-V[1]
                    Ang = Ang.magnitude
                    print(str(Ang))
                    
                if Distance > item['2']:
                    if item['LOD']!=3:
                        item.replaceMesh(item['Mesh3'],1,0)
                        item['LOD']=3
                if Distance > item['1'] and Distance <= item['2']:
                    if item['LOD']!=2:
                        item.replaceMesh(item['Mesh2'],1,0)
                        item['LOD']=2
                if Distance < item['1']:
                    if item['LOD']!=1:
                        item.replaceMesh(item['Mesh1'],1,0)
                        item['LOD']=1       
            else:
                if item['LOD']!=4:
                    item.replaceMesh('Empty',1,0)
                    item['LOD']=4            
            own['index']+=1
            if own['index']==s:
                x=25
            if own['index']>own['Len']:
                own['index']=0      
            x+=1
                
                                


main()



Attachments

LOD4GeoP2.blend (1.57 MB)

Rather than using “while x < 10” it may be better to use “for x in range(10):”.

If a “while” function throws an error blender can become locked, so you cant quit even using esc, but a “for” loop will just exit at the end of the loop.

You can also process chunks in a loop by using:

for x in range(index,index+10)

Then do something and next tic:
index +=10.

Also the built in LOD system blender has now is pretty fast and easy to use. Why not use that one?

(Sorry no code tags because of writing this on my phone)

I am going to use the LOD manager to change objects states as well as populate light hooks,

Also, how do you snipe with Kupoman LOD?
with my idea I control the levels of detail.

and then sniping modifies its behavior.

but I still need to get the light hooks working.

first is my math right?

 V= own.getVectTo(item)
            Distance = V[0]
            
           
            ##print(str(own['index'])+" Distance is "+str(Distance))
            ## set LOD if the unit is less then 100 units
            if Distance&lt;100:
                ## get angle offset from player axis if its a light
                if 'Light' in item:
                    Ang = own.worldOrientation.col[2]-V[1]
                    Ang = Ang.magnitude
                    print(str(Ang))

this should get the difference in angle from the y axis of the player to the vector to the object

(off angle amount)

second off, after I get it all working and have 2 lists, that are ‘scored’

can some one help me get sorted working? I am still having some trouble.

Try to format the code indentation properly next time.

By the way, you can use str.format to produce readable values, or even just use the comma delimiter in the function call


x = 10.0
print("Distance is", x, "meters")


x = 10.0
print("Distance is {} meters".format(x))

You’re not getting the angle there … Why do you think that is the angle?

You can get the angle between two vectors in radians as Vector.angle(other).

V = own.getVectTo(object)

Yaxis = own.worldOrienation.col[1]

AngVectDiff = V[1] - Yaxis

Diff = angVectDiff.magnitude

Diff= the difference in angle from Y axis, to the getVectTo(target)[1]

I thought it was correct… Difference in Y axis vs VectTo(world)

Vector.angle(other) = useful for sure.

http://tapatalk.imageshack.com/v2/15/03/05/fa68092e0b3d242063c68eddf0e00604.jpg
Here’s a drawing of the operations you perform

Here’s something like what you’re trying to get


other = scene.objects[...]
own = ...

to_other = other.worldPosition - own.worldPosition
forward_axis = own.getAxisVect((0, 1, 0))

depth = to_other.dot(forward_axis)
angle = to_other.angle(forward_axis)
distance = to_other.length # Might want to use length_squared if you do this a lot, and make sure to remember it's the length squared

Thank you AGoose.

The idea is to score light hooks closer by distance more, and further ones by angle,

I am still needing to create a system to do this, that is meaningful.

This is not for the LOD but for the dynamic lighting manager.

http://www.blender.org/api/blender_python_api_2_73_8/mathutils.html?highlight=mathutils#module-mathutils

Mathutils has a whole lot of useful functions, you should do a few experiments and see what you can do with them. That’s the best way to digest new functions for me.

Ok, I have the light placer working, and the angle and distance in a tuple in a list.


import bge




def main():


    cont = bge.logic.getCurrentController()
    own = cont.owner
    LODlist=[]
    len=-1
    
    
    ## get list of all objects with LOD
    if 'LODList' not in own:
        for objects in bge.logic.getCurrentScene().objects:
            if 'LOD' in objects:
                
                LODlist+=[objects]
                len+=1
                
        own['LODList']=LODlist
        own['Len']=len
        own['index']=0
        own['Lights']=[]
        
        own['LightNum']=-1
        for child in own.children:
            if 'Lights' in child:
                own['Lights']+=[child]
                own['LightNum']+=1
    else:
        
        
        s = own['index']
        x=0
        ##proccess 10 piece of the list per frame
        while (x&lt;10):
            item = own['LODList'][own['index']]
            
            V= own.getVectTo(item)
            Distance = V[0]
            
           
            ##print(str(own['index'])+" Distance is "+str(Distance))
            ## set LOD if the unit is less then 100 units
            lights =[]
            if Distance&lt;100:
                ## get angle offset from player axis if its a light
                if 'Light' in item:
                    Ang = V[1].angle(own.worldOrientation.col[1])
                    print(Ang)
                    ## store the angle and the distance and the light object in a list
                    lights += [[Ang, V[0], item]]
                if Distance &gt; item['2']:
                    if item['LOD']!=3:
                        item.replaceMesh(item['Mesh3'],1,0)
                        item['LOD']=3
                if Distance &gt; item['1'] and Distance &lt;= item['2']:
                    if item['LOD']!=2:
                        item.replaceMesh(item['Mesh2'],1,0)
                        item['LOD']=2
                if Distance &lt; item['1']:
                    if item['LOD']!=1:
                        item.replaceMesh(item['Mesh1'],1,0)
                        item['LOD']=1       
            else:
                if item['LOD']!=4:
                    item.replaceMesh('Empty',1,0)
                    item['LOD']=4            
            own['index']+=1
            if own['index']==s:
                x=25
            if own['index']&gt;own['Len']:
                own['index']=0      
            x+=1
        
        if lights!=[]:
            ## this is where I need to sort the list somehow with distance and angle where
            ## the more lights are placed near the player, the less distance matters and the more
            ## angle matters (So there are lights near the player, and in the midground)
            ## and I need to do it in a manner where it is not too... twitchy....
            
            
            print('Lights')
            index=0
            x2 = own['LightNum']
            print(x2)
            while x2&gt;-1:
                print('Light is'+own['Lights'][x2].name)
                
                own['Lights'][x2].worldPosition=lights[index][2].worldPosition
                
                print(own['Lights'][x2].name+" was placed at "+lights[index][2].name+"'s world position")        
                x2-=1
                index +=1
                
            
                
                                


main()



I am still wondering how I will sort them so the first few are set on the list for distance, and the next few are set for distance and angle off view angle…

The idea is to hopefully populate a few close lights, and a few midfield lights at the same time without too much popping lights around…

I just noticed I named the list of lights own[‘Lights’] and the list of light hooks lights.

Sorry if this is confusing.

The idea is most lights will be over X units apart, and in a grid

So there only needs to be Y lights at a time, and a hook is always populated where I need it.

Attachments

LightLodWorkingButNotSorted.blend (1.61 MB)


if this makes any sense…

I think you might find this significantly easier if you write two different functions. One for lights and one for LOD.
I don’t think it will help the script to run any faster if you try to do everything in one pass. As long as you’ve got a good list of lights and LOD relevant objects to work with and you keep it updated (remove zombie objects and add new objects to the list as they are spawned) you shouldn’t have any trouble with speed.

You can put both actions in to separate functions then you can call both from your main game loop:

def game_turn(cont):
    do_level_of_detail(cont)
    do_light_manager(cont)
    do_foo(cont)

Then you can manage the order of your functions, add or remove new ones, and do the actual scripting in individual functions.

Functions can be very useful for organizing your code, it’s like when you read a book about car maintenance, or any other technical activity. In the book each chapter contains useful things about a specific subject. If there’s a problem with your engine you turn to Chapter 4: Engine, if there’s a problem with the brakes you check out Chapter 6: Brakes.
If you don’t know which chapter covers windscreen wipers, you can look in the index.

The game loop above acts like an index. If you have a problem with your level of detail script, you can check out do_level_of_detail, if you have a problem with foo, you can check out foo*.

You wouldn’t want to open a car maintenance book and find only one subject in the index;

Chapter 1: Main

Such a book would only be useful to the person who wrote it (and I suspect even they might find it confusing after a while).

You can even put those functions in a different script for example LOD.py and import them:

from LOD import do_level_of_detail

Then you can run them as normal in your main game loop without everything getting cluttered up.

Also don’t forget the built in functions of Python. I see you use:

len = -1
own['Len']=len

And then maintain len by adding 1 each time you put something in the list, but you can also use:

own['Len']= len(LODlist)
###or:
own['Len']= len(LODlist) -1

If you need to get the length of the list for some reason (It seemed like you didn’t use that variable again in you script).

****foois a nonsense term used in programming examples in place of meaningful content. It’s usually found along with bar, and is not to be confused with FUBAR. It’s kind of like “blah, blah, blah”. Maybe you know about it already…

The script works as it is

Functions like.len are handy,

but what I need is a method of sorting that the distance matters less as you get further away, and then angle matters more,

but I don’t quite have the math for it in my brain this morning.

also, undertanding the sorted system is one of my problems.

also, If I dont add in something to check the length of the hooks and how many lights I have,
running out of lights is fine, but it will assign 2 lights to the same hook if there are more lights then hooks, so I will need someting to deal with that if it ever came up.

Python has sort method in lists.

list.sort()

You need make list index of distances and then sub list with objects.
example of sorted lamplist.sort()

lamplist[2.4][Halllamp]
lamplist[3.3][Kitchen lamp]
lamplist[4.6][Guys flashlight]

Sorting must do every frame, so I advice generate lampobjects list at gamestart,
Second stage generate list to be sorted only near lamps, drop out too far lamps. To keep active lamplist short.

I have used just empty object with properties ‘lamp’ and ‘switch’ on/off ‘energy’ ‘r’ ‘g’ ‘b’ as lamps.
Not real lamps at all in scene.

edit:
Hmm…
It may easier use dictionary list style.
lamplist={}

then genarate list every frame.
del lamplist[:] # flush existing list
for objects…

lamplist[distance]=object

lamplist.sort()

hmm…Is dictionary sortable???I need test that.

I generate a list that is a list of of lists

[[angle,distance,gameobject1],[angle,distance,gameobject2]] etc

I was thinking I could sort the whole list, by distance
and then all after 4 by angle…

sort the list,

then sort part of the list

but Again I suck at absorbing new code practices…

but yeah in my system

list[0][2] = game object

Make just one sort index ((angleangleimp)+(distdistimp))

anlgeimp=multiplier how important angles is
distimp=multiplier how important distance sorting is.

But angle??
Is it x y or z

the angle I already get,
its the angle distance from actor Y axis, which is camera -Z

( how far from the center of the camera a object is)

its under if ‘Light’ in object, that should probably say if ‘Hook’ in object…


lights =[]
if Distance<100:
## get angle offset from player axis if its a light
if ‘Light’ in item:
Ang = V[1].angle(own.worldOrientation.col[1])
print(Ang)
## store the angle and the distance and the light object in a list
lights += [[Ang, V[0], item]]
if Distance > item[‘2’]:
if item[‘LOD’]!=3:
item.replaceMesh(item[‘Mesh3’],1,0)
item[‘LOD’]=3
if Distance > item[‘1’] and Distance <= item[‘2’]:
if item[‘LOD’]!=2:
item.replaceMesh(item[‘Mesh2’],1,0)
item[‘LOD’]=2
if Distance < item[‘1’]:
if item[‘LOD’]!=1:
item.replaceMesh(item[‘Mesh1’],1,0)
item[‘LOD’]=1


Note V[1] = own.getVectTo(object)[1]


here is another diagram

you need to qualify how important the relationship between the two are, and at what distances they transition over, I.e is it quadratic

well the draw distance is 100, and lights more then 10 units behind you should not matter at all