Scripting: Python: Trouble with raycolider and matrixes

Become a member of the CGSociety

Connect, Share, and Learn with our Large Growing CG Art Community. It's Free!

THREAD CLOSED
 
Thread Tools Search this Thread Display Modes
  02 February 2013
Scripting: Python: Trouble with raycolider and matrixes

I started to dive into the raycolider utility from python and the first steps are made, but after cleaning the code and trying to evaluate which object is nearest to a start point I get weird koordniates from raycolider.

As you can see in the screenshot, the collision point of the initial target is ok, but from the obviously closer cube the collision point is somewhere in free space. I painted where it should be.
import c4d
from c4d import gui
from c4d.documents   import GetActiveDocument
from c4d import utils

def GetNextObject(op):    
    if not op: return
    if op.GetDown(): return op.GetDown()
    while op.GetUp() and not op.GetNext():
        op = op.GetUp()
    return op.GetNext()

def numberofobjects(op):
    all_list = list()
    while op:         
        all_list.append(op) 
        op = GetNextObject(op)
    return all_list

def GetActiveObjects(doc):
    lst = list()
    op = doc.GetFirstObject()
    while op:
        if op.GetType() == 5100: # get all poly objects
            lst.append(op)
        op = GetNextObject(op)
    return lst

# create nulls for visualizing the hitpos
def create_null (coordinates, null_name):    
    mynull = c4d.BaseObject(c4d.Onull)    
    mynull[c4d.ID_BASEOBJECT_USECOLOR] = True
    mynull[c4d.ID_BASEOBJECT_COLOR] = c4d.Vector(255,0,0)
    mynull.SetAbsPos(coordinates)    
    mynull.SetName(null_name)
    doc.InsertObject(mynull)
    return

def firerayat (start, direction, length, optemp_test): # startpoint, direction, length, object to colide
    collider = c4d.utils.GeRayCollider()    
    collider.Init(optemp_test, True) #force cache rebuild with true
    did_intersect = collider.Intersect(start.GetAbsPos(), direction, length)
    if did_intersect:
        create_null(collider.GetNearestIntersection()["hitpos"], optemp_test.GetName()) # creates null objects at the hitpos to visualize for debugging
        return collider.GetNearestIntersection()["distance"]
    else:        
        return

def raylength (startray, endray):
    return (startray.GetAbsPos() - endray.GetAbsPos()).GetLength()

def ray_direction (start, optarget):
    return -(start.GetAbsPos() - optarget.GetAbsPos()).GetNormalized()
    
def main():
    c4d.CallCommand(13957) # Konsole löschen
    now = c4d.GeGetTimer() # start stopwatch
    
    if GetActiveDocument():
        doc     = GetActiveDocument()
        if doc.GetFirstObject():
            c4d.StatusSetSpin()
            op = doc.GetFirstObject()
            myobject = op
            all_objects = numberofobjects(op) # list off all objects
            counter = len(all_objects)
            secondcounter = 0
            c4d.StatusSetText ('%s Objects are processed.' %(counter))
            opactive = None
        else:
            print "Error: No Objects"
            return False
    else:
        print "Error: No Document"
        return False
    
    opstart = doc.SearchObject("Start")
    optarget = doc.SearchObject("Target")    
    
    lst = GetActiveObjects(doc)
    print "Polygon Obects: ", len(lst)
    hit_or_tested = []
    never_hit = []

    # delet all Nulls exept my start this is just for debugging
    n = 0
    while n < len(all_objects):
        optempdelete = all_objects[n]
        if optempdelete.GetType() == 5140 and not optempdelete.GetName() == "Start":
            optempdelete.Remove()
        n = n+1  
    c4d.EventAdd()
    # end       
     
    length = raylength(optarget, opstart) # two times just in case
    direction = ray_direction(opstart, optarget)
    print "Ray length: ", length
    print "Direction: ", direction
    print "-------------------------------------------------------------"
    temp_distance_list = []
    temp_op_tested_list = []
    
    i = 0    
    
    while i < len(lst):
        optemp = lst[i]        
        distance = None
        temp_op_tested_list.append(optemp)
        distance = firerayat(opstart, direction, length, optemp) # target and testobject check ????     
        print optemp.GetName(), ": Collision at length: ", distance
        temp_distance_list.append(distance)
        i = i+1
    
    nearest_distance = min(x for x in temp_distance_list if x is not None)
    print nearest_distance
    index_of_list = temp_distance_list.index(nearest_distance)        
    print "Nearest Object: ", temp_op_tested_list[index_of_list].GetName()        
    print "-------------------------------------------------------------"
    print temp_op_tested_list
    print temp_distance_list
    print "-------------------------------------------------------------"
    print 'END OF SCRIPT %s ms ' %(c4d.GeGetTimer() - now)
    c4d.EventAdd()  
    c4d.StatusClear()
if __name__=='__main__':
    main()


I think the trouble is somewhere here:
snippet from above ...
def firerayat (start, direction, length, optemp_test): # startpoint, direction, length, object to colide
    collider = c4d.utils.GeRayCollider()    
    collider.Init(optemp_test, True) #force cache rebuild with true, dont know if it helps 
    did_intersect = collider.Intersect(start.GetAbsPos(), direction, length)
    if did_intersect:
        create_null(collider.GetNearestIntersection()["hitpos"], optemp_test.GetName()) # creates null objects at the hitpos to visualize for debugging
        return collider.GetNearestIntersection()["distance"]
    else:        
        return

def raylength (startray, endray):
    return (startray.GetAbsPos() - endray.GetAbsPos()).GetLength() #is this ok?

def ray_direction (start, optarget):
    return -(start.GetAbsPos() - optarget.GetAbsPos()).GetNormalized() #is this right?


If you want to test the above script put a Null called "Start" and some randomly placed polygon objects one called Target in your scene.

The script puts Null Objects at the collision points but the AbsSpace does not match or something entirely different ... I am stuck at the moment.

Any Ideas?
Attached Images
File Type: png screenshot_all.png (25.2 KB, 15 views)
__________________
R17 Visualize - Flickr Album - Website

Last edited by mogh : 02 February 2013 at 07:56 AM.
 
  02 February 2013
i will take a closer look at it later, at the first look the code looks ok, just one thing.
the absolute coordinates are NOT the world coordinates. abs/rel coords are tied to
the freeze coords system. calculating a normal out of two coords in local space does
not really make sense.

you are trying to do this object culls object thing, right ?

Last edited by littledevil : 02 February 2013 at 01:12 PM.
 
  02 February 2013
I haven't had time to test the script but one issue appears to be the coordinate space used for the ray collison calculation.

The start point and ray direction passed to Intersect() must be in the coordinate space of the object passed to Init(). This is 'optemp' in the while loop.

The inverted global matrix of 'optemp' must be multiplied with the global positions of the start and end objects, e.g.
startPoint = ~optemp.GetMg() * opstart.GetMg().off 

This will involve some restructuring of your code.
 
  02 February 2013
Darter your code works somehow, now i have points floating somewhere in space, need to check my nulls generation two - I hate matrices can't wrap my head around it ---- but I am on track again

yes little devil I'am trying to get the impossible done ...

which me luck ---

Update:
def create_null (coordinates, null_name, optemp_test): 
    print coordinates, optemp_test
    wc = ~optemp_test.GetMg() * coordinates 
    print wc 
    mynull = c4d.BaseObject(c4d.Onull) 
    mynull[c4d.ID_BASEOBJECT_USECOLOR] = True 
    mynull[c4d.ID_BASEOBJECT_COLOR] = c4d.Vector(255,0,0) 
    mynull.SetAbsPos(coordinates) 
    mynull.SetName(null_name + " Point") 
    doc.InsertObject(mynull) 
    return


this is oviusly wrong ... but how do i transfer the local Matrix to the other Nulls representing a position in my c4D scene? I read matrix fundamentals 5 times and still can't understand how to tackle my Nulls ...
__________________
R17 Visualize - Flickr Album - Website

Last edited by mogh : 02 February 2013 at 02:34 PM.
 
  02 February 2013
obj_global_matrix = parent_global_matrix * obj_local_matrix,

but again , SetAbsPosition is local space, which is correct, as you do insert the
new nulls under your root null, so i do not really understand your question, i guess
 
  02 February 2013
You've gone the wrong way. The hit position is converted from goal object to global coordinates like this:
def create_null (coordinates, null_name, optemp):
    	wc = optemp.GetMg() * coordinates	 
    	mynull = c4d.BaseObject(c4d.Onull)	
    	mynull[c4d.ID_BASEOBJECT_USECOLOR] = True
    	mynull[c4d.ID_BASEOBJECT_COLOR] = c4d.Vector(255,0,0)
    	mynull.SetAbsPos(wc)	
    	mynull.SetName(null_name)
    	doc.InsertObject(mynull)
    	return

The start point and ray direction still needed to be converted to goal object coordinate space:
def get_ray(start_obj, end_obj, goal):
    	start = ~goal.GetMg() * start_obj.GetMg().off
    	end =  ~goal.GetMg() * end_obj.GetMg().off
    	return {'ray_p' : start, 'ray_length' : (end - start).GetLength(), 'ray_dir' : (end - start).GetNormalized()}

The updated script seems to be working okay with various hierarchy configurations.

Originally Posted by Little_Devil: obj_global_matrix = parent_global_matrix * obj_local_matrix

I'm aware of the calculation under Freeze Transformation in the SDK but find that GetMg() usually suffices. Most usage examples on Plugin Cafe since R12 support this.
 
  02 February 2013
Thanks to both of you I did already incoporate the changes and streamlined it even more.

@Darter: Are you returning a list of lists with the get_ray def?

How do I create a List of Lists (e.g. Object : Distance) and the get the Min Value with the coresponding Object.

At the moment I have two lists which are stored seperatly and I have to get the ID of List one and the get the object with the ID of List Two. Is there a better way to do this ?


kind regards
__________________
R17 Visualize - Flickr Album - Website
 
  02 February 2013
get_ray() returns a dictionary.
 
  02 February 2013
Thanks Darter.


i found a inconsistancy between
R14 and R13 of the get Ray function

R13 works but in R14 it seems as if the direction is the opposite but nevertheless the script gives positive hits ... weird ...

have to go to bed ... but I am already excluding obects yay
good night
__________________
R17 Visualize - Flickr Album - Website
 
  02 February 2013
forget the previous post, I seem to have broken it somewhere else on the code ...



suddenly not the nearest object but all objects are considerated as a near object and then the script jumps over all the other loops because the list "hit_list" was already filled with all objects in the scene.

FYI:
To get that script going you only need a 2 point spline called "ray" and some poly objects to fire at. The rest is generated automatically.

import c4d
from c4d import gui
from c4d.documents   import GetActiveDocument
from c4d import utils
# import math

def GetNextObject(op):    
    if not op: return
    if op.GetDown(): return op.GetDown()
    while op.GetUp() and not op.GetNext():
        op = op.GetUp()
    return op.GetNext()

def numberofobjects(op):
    all_list = list()
    poly_list = list()
    while op:         
        all_list.append(op)
        if op.GetType() == 5100 and op.GetName() != "Start Point Cloud": # get all poly objects
            poly_list.append(op)
        op = GetNextObject(op)
    return {'all_objects_list' : all_list, 'polygon_obj_list' : poly_list }

def find_layer(layername):
    root = doc.GetLayerObjectRoot() #Gets the layer manager
    myLayersList = root.GetChildren()
    foundname = False
    for lname in myLayersList:       
        if lname.GetName() == str(layername): 
            return lname
    
def create_layer(name, color, display_seen):
    root = doc.GetLayerObjectRoot()#Gets the layer manager
    c4d.CallCommand(100004738) #create new layer
    mynewLayersList = root.GetChildren() # get the new list 
    newlayer = mynewLayersList[-1] # get the last index of a list in this case layer    
    newlayer[c4d.ID_LAYER_COLOR] = color # Sets layer color
    newlayer.SetName(name) # Sets layer name
    newlayer[c4d.ID_LAYER_VIEW] = display_seen #set layer view setting
    newlayer[c4d.ID_LAYER_RENDER] = display_seen #set layer render setting    
    return newlayer
        
def create_sphere(sub, radius): 
    obj = c4d.BaseObject(c4d.Osphere)
    obj[c4d.PRIM_SPHERE_RAD] = radius
    obj[c4d.PRIM_SPHERE_SUB] = sub
    obj[c4d.PRIM_SPHERE_TYPE] = 4
    obj[c4d.PRIM_SPHERE_PERFECT] = False
    obj.SetName("Start Point Cloud")
    # obj.SetMg(c4d.Matrix(c4d.Vector(1,1,1)))
    doc.InsertObject(obj)           # Insert object in document
    obj.SetBit(c4d.BIT_ACTIVE)
    c4d.CallCommand(12236) # Grundobjekt konvertieren        
    # obj.Message(c4d.MSG_UPDATE)    
    newobj = doc.SearchObject("Start Point Cloud")
    create_display_tag(newobj)   
    p_positions = newobj.GetAllPoints()
    """
    for p in p_positions:
        print p_positions.index(p), p, obj.GetUpMg()
        p_positions[p_positions.index(p)] = obj.GetUpMg()*p # gloabl coordinates
        #print p_positions[p_positions.index(p)]
    """    
    # newobj.Remove()
    obj.DelBit(c4d.BIT_ACTIVE)
    c4d.EventAdd()                  # Send global event message
    return p_positions

def create_display_tag(myobject):
    mytag = myobject.MakeTag(c4d.Tdisplay)
    mytag[c4d.DISPLAYTAG_AFFECT_DISPLAYMODE] = True
    mytag[c4d.DISPLAYTAG_SDISPLAYMODE] = 6
    return

# create nulls for visualizing the hitpos
def create_null (coordinates, null_name, optemp_test):    
    wc = optemp_test.GetMg() * coordinates
    mynull = c4d.BaseObject(c4d.Onull)    
    mynull[c4d.ID_BASEOBJECT_USECOLOR] = True
    mynull[c4d.ID_BASEOBJECT_COLOR] = c4d.Vector(1,0,0)
    mynull.SetAbsPos(wc)    
    mynull.SetName(null_name + " Point")
    doc.InsertObject(mynull)
    return

def firerayat (start, direction, length, optemp_test): # startpoint, direction, length, object to colide
    collider = c4d.utils.GeRayCollider()    
    collider.Init(optemp_test) #force cache rebuild with , True    
    did_intersect = collider.Intersect(start, direction, length) #(start.GetAbsPos(), direction, length)
    if did_intersect:
        # creates null objects at the hitpos to visualize for debugging
        create_null(collider.GetNearestIntersection()["hitpos"], optemp_test.GetName(), optemp_test)
        return collider.GetIntersection(0)["distance"]
    else:        
        return False
    
""" Darter original
def get_ray(start_obj, end_obj, goal):
    start = ~goal.GetMg() * start_obj.GetMg().off
    end =  ~goal.GetMg() * end_obj.GetMg().off
    return {'ray_p' : start, 'ray_length' : (end - start).GetLength(), 'ray_dir' : (end - start).GetNormalized()}
"""

def get_ray(start_obj, end_obj, goal): #modified to accept vectors as start instead of object Global Mg
    start = ~goal.GetMg() * c4d.Vector(start_obj)
    end =  ~goal.GetMg() * end_obj.GetMg().off
    return {'ray_p' : start, 'ray_length' : (end - start).GetLength(), 'ray_dir' : (end - start).GetNormalized()}


def f2(seq): 
   # order preserving
   checked = []
   for e in seq:
       if e not in checked:
           checked.append(e)
   return checked

def statusbar (counter, secondcounter):
    #c4d.StatusSetText ('%s - %s Objects are processed.' %(secondcounter, counter))    # very slow
    c4d.StatusSetBar(100*secondcounter/counter) #statusbar

def put_on_layer (objlist, layer):
    nr = 0
    while nr < len(objlist):
        objlist[nr].SetLayerObject(layer)
        objlist[nr][c4d.ID_BASEOBJECT_USECOLOR]=3
        nr = nr+1

def delete_nulls (all_objects_list): # delet all Nulls exept my start this is just for debugging
    n = 0
    while n < len(all_objects_list):
        optempdelete = all_objects_list[n]
        if optempdelete.GetType() == 5140 and not optempdelete.GetName() == "Start" and len(optempdelete.GetChildren())<1 :
            optempdelete.Remove()
        n = n+1
    c4d.EventAdd()
        
def main():
    c4d.CallCommand(13957) # Konsole löschen
    now = c4d.GeGetTimer() # start stopwatch
    
    if GetActiveDocument():
        doc = GetActiveDocument()
        if doc.GetFirstObject():
            c4d.StatusSetSpin()
            op = doc.GetFirstObject()
            myobject = op
            all_objects = numberofobjects(op) # list off all objects            
            counter = len(all_objects['all_objects_list'])
            all_objects_list = all_objects['all_objects_list']
            poly_obj_list = all_objects['polygon_obj_list']
            print "Polygon Objects: ", len(poly_obj_list)            
            secondcounter = 0
            c4d.StatusSetText ('%s Objects are processed.' %(counter))
            opactive = None
        else:
            print "Error: No Objects"
            return False
    else:
        print "Error: No Document"
        return False
    
    delete_nulls (all_objects_list) # delet all Nulls exept my start this is just for debugging        
    rayspline = doc.SearchObject("ray")
    
    if find_layer("Not hit"):        
        layer_not_hit = find_layer("Not hit")        
    else:
        layer_not_hit = create_layer("Not hit", c4d.Vector(0.5,0,0), True)
        
    if find_layer("Seen"):        
        layer_seen = find_layer("Seen")
    else:
        layer_seen = create_layer("Seen", c4d.Vector(0,0.75,0), True)
        
    if find_layer("checked"):        
        layer_checked = find_layer("checked")
    else:
        layer_checked = create_layer("checked", c4d.Vector(0,0,0.5), True)
        
    if doc.SearchObject("Start Point Cloud"):
        oldsphere = doc.SearchObject("Start Point Cloud")
        oldsphere.Remove()
    
    start_point_list = create_sphere(5, 500) # Subdivisions, Radius

    hit_list = []
    never_hit = []
    tested = []    
    
    print "Startpoint positions: ", len(start_point_list)
    print "-------------------------------------------------------------"
    c4d.EventAdd()
    
    si = 0
    while si < len(start_point_list):        
        statusbar(len(start_point_list), si)  

        c4d.StatusSetText ('%s Objects and %s Ray Start Points are processed.' %(len(poly_obj_list), len(start_point_list)))

        nr_index = 0        
        while nr_index < len(poly_obj_list):

            optarget = poly_obj_list[nr_index]
            # print "Target: ",optarget.GetName()
            
            if optarget not in hit_list:
                
                tested.append(optarget)
                               
                temp_op_tested_list = []
                temp_distance_list = []
                
                i = 0
                while i < len(poly_obj_list):
                    temp_op_tested_list.append(poly_obj_list[i])
                    
                    if poly_obj_list[i] not in hit_list:
                        ray = get_ray(start_point_list[si], optarget, poly_obj_list[i])
                        distance = firerayat(ray['ray_p'], ray['ray_dir'], ray['ray_length'], poly_obj_list[i])
                        temp_distance_list.append(distance)
                    else:                        
                        temp_distance_list.append(None)
                        #print "Jumped: ", poly_obj_list[i].GetName()
                    i = i+1 
                
                # print "temp_distance_list: ", temp_distance_list
                atuple = filter(None, tuple(temp_distance_list))
                # print "Tuple: ", atuple
                
                if 0 != len(atuple):
                    nearest_distance = min(x for x in atuple if x is not None)
                    # attention min() is a generator and can only be called once for a list !
                    # Can this be done better - List Of List or similar?            
                    near_obj = temp_op_tested_list[temp_distance_list.index(nearest_distance)]
                
                    print "Nearest Object: ", near_obj.GetName(), nearest_distance
                
                    if near_obj not in hit_list:
                        hit_list.append(near_obj)
            
            else:
                print "OpTarget was in hitlist - jumped: ", optarget.GetName()
            
            nr_index = nr_index + 1
        si = si+1
    # after loops 
    
    never_hit = temp_op_tested_list + never_hit
    never_hit = f2(never_hit) # here or later have to watch memmory consumption !!!    
    tested = f2(tested)
    
    for x in hit_list:
        if x in tested:
            tested.remove(x)
            
    for z in hit_list:
        if z in never_hit:
            never_hit.remove(z)
            
    # put on layer    
    put_on_layer (hit_list, layer_seen)
    put_on_layer (never_hit, layer_not_hit)
    put_on_layer (tested, layer_checked)
    
    print "-------------------------------------------------------------"
    print "Tested count: ", len(tested)    
    print "Hitlist count: ", len(hit_list)
    # print hit_list
    print "Never Hit: ", len(never_hit)
    print "Ray length: ", ray['ray_length']
    print "Direction: ", ray['ray_dir']    
    rayspline.SetPoint(0, ~rayspline.GetMg() * -start_point_list[si-1] ) # si - 1
    rayspline.SetPoint(1, ~(ray['ray_length'] * ray['ray_dir']) * rayspline.GetMg() ) # something wrong here ... 
    rayspline.Message(c4d.MSG_UPDATE)  
    print "-------------------------------------------------------------"        
    print 'END OF SCRIPT - Duration: %s s ' %((c4d.GeGetTimer() - now)/1000)
    c4d.EventAdd()  
    c4d.StatusClear()

if __name__=='__main__':
    main()
__________________
R17 Visualize - Flickr Album - Website
 
  02 February 2013
Updated script Splines for debugging are generated automatically ...

otherwise still a lot of stuff wrong ...


import c4d
from c4d import gui
from c4d.documents   import GetActiveDocument
from c4d import utils
# import math

def GetNextObject(op):    
    if not op: return
    if op.GetDown(): return op.GetDown()
    while op.GetUp() and not op.GetNext():
        op = op.GetUp()
    return op.GetNext()

def numberofobjects(op):
    all_list = list()
    poly_list = list()
    while op:         
        all_list.append(op)
        if op.GetType() == 5100 and op.GetName() != "Start Point Cloud": # get all poly objects
            poly_list.append(op)
        op = GetNextObject(op)
    return {'all_objects_list' : all_list, 'polygon_obj_list' : poly_list }

def find_layer(layername):
    root = doc.GetLayerObjectRoot() #Gets the layer manager
    myLayersList = root.GetChildren()
    foundname = False
    for lname in myLayersList:       
        if lname.GetName() == str(layername): 
            return lname
    
def create_layer(name, color, display_seen):
    root = doc.GetLayerObjectRoot()#Gets the layer manager
    c4d.CallCommand(100004738) #create new layer
    mynewLayersList = root.GetChildren() # get the new list 
    newlayer = mynewLayersList[-1] # get the last index of a list in this case layer    
    newlayer[c4d.ID_LAYER_COLOR] = color # Sets layer color
    newlayer.SetName(name) # Sets layer name
    newlayer[c4d.ID_LAYER_VIEW] = display_seen #set layer view setting
    newlayer[c4d.ID_LAYER_RENDER] = display_seen #set layer render setting    
    return newlayer

# ray spline
def create_spline_ray (goal, start, ray_dir, ray_length):
    spl = c4d.SplineObject(2,c4d.SPLINETYPE_LINEAR)  #Create a 2pt. Bezier spline in memory only ~goal.GetMg() *
    spl.SetPoint(0, start * spl.GetMg() )
    spl.SetPoint(1,  ~spl.GetMg() * (ray_dir*ray_length)) # something wrong here ... ? 
    spl.Message(c4d.MSG_POINTS_CHANGED)
    spl[c4d.ID_BASEOBJECT_USECOLOR] = True
    spl[c4d.ID_BASEOBJECT_COLOR] = c4d.Vector(1,1,0)
    spl.SetName("Ray to - " + goal.GetName())    
    doc.InsertObject(spl)
    c4d.EventAdd()
        
def create_sphere(sub, radius): 
    obj = c4d.BaseObject(c4d.Osphere)
    obj[c4d.PRIM_SPHERE_RAD] = radius
    obj[c4d.PRIM_SPHERE_SUB] = sub
    obj[c4d.PRIM_SPHERE_TYPE] = 4
    obj[c4d.PRIM_SPHERE_PERFECT] = False
    obj.SetName("Start Point Cloud")
    # obj.SetMg(c4d.Matrix(c4d.Vector(1,1,1)))
    doc.InsertObject(obj)           # Insert object in document
    obj.SetBit(c4d.BIT_ACTIVE)
    c4d.CallCommand(12236) # Grundobjekt konvertieren        
    # obj.Message(c4d.MSG_UPDATE)    
    newobj = doc.SearchObject("Start Point Cloud")
    create_display_tag(newobj)   
    p_positions = newobj.GetAllPoints()
    """
    for p in p_positions:
        print p_positions.index(p), p, obj.GetUpMg()
        p_positions[p_positions.index(p)] = obj.GetUpMg()*p # gloabl coordinates
        #print p_positions[p_positions.index(p)]
    """    
    # newobj.Remove()
    obj.DelBit(c4d.BIT_ACTIVE)
    c4d.EventAdd()                  # Send global event message
    return p_positions

def create_display_tag(myobject):
    mytag = myobject.MakeTag(c4d.Tdisplay)
    mytag[c4d.DISPLAYTAG_AFFECT_DISPLAYMODE] = True
    mytag[c4d.DISPLAYTAG_SDISPLAYMODE] = 6
    return

# create nulls for visualizing the hitpos
def create_null (coordinates, null_name, optemp_test):    
    wc = optemp_test.GetMg() * coordinates
    mynull = c4d.BaseObject(c4d.Onull)    
    mynull[c4d.ID_BASEOBJECT_USECOLOR] = True
    mynull[c4d.ID_BASEOBJECT_COLOR] = c4d.Vector(1,0,0)
    mynull.SetAbsPos(wc)    
    mynull.SetName(null_name + " Point")
    doc.InsertObject(mynull)
    return

def firerayat (start, direction, length, optemp_test): # startpoint, direction, length, object to colide
    collider = c4d.utils.GeRayCollider()    
    collider.Init(optemp_test) #force cache rebuild with , True    
    did_intersect = collider.Intersect(start, direction, length) #(start.GetAbsPos(), direction, length)
    if did_intersect:
        # creates null objects at the hitpos to visualize for debugging
        # create_null(collider.GetNearestIntersection()["hitpos"], optemp_test.GetName(), optemp_test)
        return collider.GetIntersection(0)["distance"]
    else:        
        return False
    
""" Darter original
def get_ray(start_obj, end_obj, goal):
    start = ~goal.GetMg() * start_obj.GetMg().off
    end =  ~goal.GetMg() * end_obj.GetMg().off
    return {'ray_p' : start, 'ray_length' : (end - start).GetLength(), 'ray_dir' : (end - start).GetNormalized()}
"""

def get_ray(start_obj, end_obj, goal): #modified to accept vectors as start instead of object Global Mg
    start = ~goal.GetMg() * c4d.Vector(start_obj)
    end =  ~goal.GetMg() * end_obj.GetMg().off
    return {'ray_p' : start, 'ray_length' : (end - start).GetLength(), 'ray_dir' : (end - start).GetNormalized()}


def f2(seq): 
   # order preserving
   checked = []
   for e in seq:
       if e not in checked:
           checked.append(e)
   return checked

def statusbar (counter, secondcounter):
    #c4d.StatusSetText ('%s - %s Objects are processed.' %(secondcounter, counter))    # very slow
    c4d.StatusSetBar(100*secondcounter/counter) #statusbar

def put_on_layer (objlist, layer):
    nr = 0
    while nr < len(objlist):
        objlist[nr].SetLayerObject(layer)
        objlist[nr][c4d.ID_BASEOBJECT_USECOLOR]=3
        nr = nr+1

def delete_nulls (all_objects_list): # delet all Nulls exept my start this is just for debugging
    n = 0
    while n < len(all_objects_list):
        optempdelete = all_objects_list[n]
        if optempdelete.GetType() == 5140 and len(optempdelete.GetChildren()) == 0 or optempdelete.GetType() ==5101:
            optempdelete.Remove()
        n = n+1
    c4d.EventAdd()
        
def main():
    c4d.CallCommand(13957) # Konsole löschen
    now = c4d.GeGetTimer() # start stopwatch
    
    if GetActiveDocument():
        doc = GetActiveDocument()
        if doc.GetFirstObject():
            c4d.StatusSetSpin()
            op = doc.GetFirstObject()
            myobject = op
            all_objects = numberofobjects(op) # list off all objects            
            counter = len(all_objects['all_objects_list'])
            all_objects_list = all_objects['all_objects_list']
            poly_obj_list = all_objects['polygon_obj_list']
            print "Polygon Objects: ", len(poly_obj_list)            
            secondcounter = 0
            c4d.StatusSetText ('%s Objects are processed.' %(counter))
            opactive = None
        else:
            print "Error: No Objects"
            return False
    else:
        print "Error: No Document"
        return False
    
    delete_nulls (all_objects_list) # delet all Nulls exept my start this is just for debugging        
    rayspline = doc.SearchObject("ray")
    
    if find_layer("Not hit"):        
        layer_not_hit = find_layer("Not hit")        
    else:
        layer_not_hit = create_layer("Not hit", c4d.Vector(0.5,0,0), True)
        
    if find_layer("Seen"):        
        layer_seen = find_layer("Seen")
    else:
        layer_seen = create_layer("Seen", c4d.Vector(0,0.75,0), True)
        
    if find_layer("checked"):        
        layer_checked = find_layer("checked")
    else:
        layer_checked = create_layer("checked", c4d.Vector(0,0,0.5), True)
        
    if doc.SearchObject("Start Point Cloud"):
        oldsphere = doc.SearchObject("Start Point Cloud")
        oldsphere.Remove()
    
    start_point_list = create_sphere(5, 500) # Subdivisions, Radius

    hit_list = []
    never_hit = []
    tested = []    
    
    print "Startpoint positions: ", len(start_point_list)
    print "-------------------------------------------------------------"
    c4d.EventAdd()
    
    si = 0
    while si < len(start_point_list):        
        statusbar(len(start_point_list), si)  

        c4d.StatusSetText ('%s Objects and %s Ray Start Points are processed.' %(len(poly_obj_list), len(start_point_list)))

        nr_index = 0        
        while nr_index < len(poly_obj_list):

            optarget = poly_obj_list[nr_index]
            print "Target: ",optarget.GetName()
 
            temp_op_tested_list = []
            temp_distance_list = []
            
            if optarget not in hit_list:               
                tested.append(optarget)
                i = 0
                while i < len(poly_obj_list):
                    temp_op_tested_list.append(poly_obj_list[i])                   
                    
                    if poly_obj_list[i] not in hit_list:
                        
                        ray = get_ray(start_point_list[si], optarget, poly_obj_list[i])                  
                        distance = firerayat(ray['ray_p'], ray['ray_dir'], ray['ray_length'], poly_obj_list[i])
                        
                        create_spline_ray (poly_obj_list[i], start_point_list[si] , ray['ray_dir'], ray['ray_length'])  # slow just for debugging
                        
                        temp_distance_list.append(distance)
                        
                    else:                        
                        temp_distance_list.append(None)
                        #print "Jumped: ", poly_obj_list[i].GetName()
                    i = i+1

                # print ray['ray_p'] , "Direction: ", ray['ray_dir'], " Ray length: ", ray['ray_length']
                           
                print "temp_distance_list: ", temp_distance_list
                atuple = filter(None, tuple(temp_distance_list))
                # print "Tuple: ", i, atuple
                
                if 0 != len(atuple):
                    nearest_distance = min(x for x in atuple if x is not None)
                    # attention min() is a generator and can only be called once for a list !
                    # Can this be done better - List Of List or similar?            
                    near_obj = temp_op_tested_list[temp_distance_list.index(nearest_distance)]
                
                    #print "Nearest Object: ", near_obj.GetName(), nearest_distance
                
                    if near_obj not in hit_list:
                        hit_list.append(near_obj)
            
            # else: print "OpTarget was in hitlist - jumped: ", optarget.GetName()            
            nr_index = nr_index + 1
        si = si+1
    # after loops 
    
    never_hit = temp_op_tested_list + never_hit
    never_hit = f2(never_hit) # here or later have to watch memmory consumption !!!    
    tested = f2(tested)
    
    for x in hit_list:
        if x in tested:
            tested.remove(x)
            
    for z in hit_list:
        if z in never_hit:
            never_hit.remove(z)
            
    # put on layer    
    put_on_layer (hit_list, layer_seen)
    put_on_layer (never_hit, layer_not_hit)
    put_on_layer (tested, layer_checked)
    
    print "-------------------------------------------------------------"
    print "Tested count: ", len(tested)    
    print "Hitlist count: ", len(hit_list)
    # print hit_list
    print "Never Hit: ", len(never_hit)
    print "-------------------------------------------------------------"        
    print 'END OF SCRIPT - Duration: %s s ' %((c4d.GeGetTimer() - now)/1000)
    c4d.EventAdd()  
    c4d.StatusClear()
if __name__=='__main__':
    main()
__________________
R17 Visualize - Flickr Album - Website
 
  02 February 2013
I'm still not sure what you want to achieve.
If it is just hitting an object with the ray collidion, have a look at my blog for a short tutorial on using the Ray Collision Xpresso node and python.
The node is used to get the polygon that was ‘hit’ by the Ray.
Python is then used to get the neighbor polygons.
All these polygons are added to the Polygon Selection Tag.
__________________
Please have a look at Plugins4D for plugin development and free plugins.
 
  02 February 2013
I am trying to build an advanced "manual" occlusion script.

http://forums.cgsociety.org/showthr...?f=47&t=1091288

I am hunting bugs for several days now and I've gone back to an earlier version just to understand more whats going on.

but as soon as i replace the target with all objects in a loop it gets weird ...

- First thing is to get my Globals and local Positions spot on its a mess at the moment I think.
- second is to know why it gets messy when i replace targets and goals and start points.

I have a hunch that my lists are not resetted the right way ...

anyway its to much to ask for you guys to solve my problems hence the script is quiet big already

but perhaps is there a "visual" explanation of Global and Local conversions ? :
kind regards mogh
__________________
R17 Visualize - Flickr Album - Website
 
  02 February 2013
Yay, first working version,

be carefull with number of polyobjects in your scene hence it chekcs every object against every object at least 12 times !

to control the rays increase the sphere subdiv in the script

regards mogh


import c4d
from c4d import gui
from c4d.documents   import GetActiveDocument
from c4d import utils
# Version 0.18

def gime_time (time_start):
    milliseconds = c4d.GeGetTimer()-time_start
    hours,milliseconds = divmod(milliseconds, 3600000)
    minutes, milliseconds = divmod(milliseconds, 60000)
    seconds = float(milliseconds) / 1000
    s = "%i:%02i:%06.3f" % (hours, minutes, seconds)
    return s

def statusbar (counter, secondcounter):
    #c4d.StatusSetText ('%s - %s Objects are processed.' %(secondcounter, counter))    # very slow
    c4d.StatusSetBar(100*secondcounter/counter) #statusbar

def GetNextObject(op):    
    if not op: return
    if op.GetDown(): return op.GetDown()
    while op.GetUp() and not op.GetNext():
        op = op.GetUp()
    return op.GetNext()

def numberofobjects(op):
    all_list = list()
    poly_list = list()
    while op:         
        all_list.append(op)
        if op.GetType() == 5100 and op.GetName() != "Start Point Cloud": # get all poly objects
            obj_atribute = [op, 0, 0] # object, #_tested, #_hitcount_nearest
            poly_list.append(obj_atribute)
        op = GetNextObject(op)
    return {'all_objects_list' : all_list, 'polygon_obj_list' : poly_list }

# Layerstuff ----------------------------------------------------------------------------------
def find_layer(layername):
    root = doc.GetLayerObjectRoot() #Gets the layer manager
    myLayersList = root.GetChildren()
    foundname = False
    for lname in myLayersList:       
        if lname.GetName() == str(layername): 
            return lname
    
def create_layer(name, color, display_seen):
    root = doc.GetLayerObjectRoot()#Gets the layer manager
    c4d.CallCommand(100004738) #create new layer
    mynewLayersList = root.GetChildren() # get the new list 
    newlayer = mynewLayersList[-1] # get the last index of a list in this case layer    
    newlayer[c4d.ID_LAYER_COLOR] = color # Sets layer color
    newlayer.SetName(name) # Sets layer name
    newlayer[c4d.ID_LAYER_VIEW] = display_seen #set layer view setting
    newlayer[c4d.ID_LAYER_RENDER] = display_seen #set layer render setting    
    return newlayer

def put_on_layer (objlist, layer):
    nr = 0
    while nr < len(objlist):
        objlist[nr].SetLayerObject(layer)
        objlist[nr][c4d.ID_BASEOBJECT_USECOLOR]=3
        nr = nr+1
# End Layerstuff /////////////////////////////////////////////////////////////////////////////


# ray spline ---------------------------------------------------------------------------------
def create_spline_ray (optarget, start):
    spl = c4d.SplineObject(2,c4d.SPLINETYPE_LINEAR)  #Create a 2pt. Bezier spline in memory only ~goal.GetMg() *
    spl.SetPoint(0, start * spl.GetMg() )
    spl.SetPoint(1,  optarget.GetMg().off * spl.GetMg() )
    spl.Message(c4d.MSG_POINTS_CHANGED)
    spl[c4d.ID_BASEOBJECT_USECOLOR] = True
    spl[c4d.ID_BASEOBJECT_COLOR] = c4d.Vector(1,1,0)
    spl.SetName("Ray to - " + optarget.GetName())    
    doc.InsertObject(spl)
    c4d.EventAdd()
# End ray spline /////////////////////////////////////////////////////////////////////////////

# sphere startpoints -------------------------------------------------------------------------
def create_sphere(sub, radius, cord_vec, delete_me): 
    obj = c4d.BaseObject(c4d.Osphere)
    obj[c4d.PRIM_SPHERE_RAD] = radius
    obj[c4d.PRIM_SPHERE_SUB] = sub
    obj[c4d.PRIM_SPHERE_TYPE] = 4
    obj[c4d.PRIM_SPHERE_PERFECT] = False
    obj.SetName("Start Point Cloud")
    obj.SetMg(c4d.Matrix(cord_vec))
    obj.Message(c4d.MSG_POINTS_CHANGED)
    doc.InsertObject(obj)           # Insert object in document
    obj.SetBit(c4d.BIT_ACTIVE)
    c4d.CallCommand(12236) # Grundobjekt konvertieren        
    # obj.Message(c4d.MSG_UPDATE)    
    newobj = doc.SearchObject("Start Point Cloud")
    if delete_me != True:
        create_display_tag(newobj)   
    p_positions = newobj.GetAllPoints()
    new_list = []
    for p in p_positions:
        # print p_positions.index(p), p, obj.GetMg()
        new_list.append(obj.GetMg() * p) # gloabl coordinates
        #print p_positions[p_positions.index(p)]
    if delete_me == True:
        newobj.Remove()
    obj.DelBit(c4d.BIT_ACTIVE)
    c4d.EventAdd()                  # Send global event message
    return new_list

def create_display_tag(myobject):
    mytag = myobject.MakeTag(c4d.Tdisplay)
    mytag[c4d.DISPLAYTAG_AFFECT_DISPLAYMODE] = True
    mytag[c4d.DISPLAYTAG_SDISPLAYMODE] = 6
    return
# End sphere startpoints //////////////////////////////////////////////////////////////////////

# create nulls for visualizing the hitpos -----------------------------------------------------
def create_null (coordinates, null_name, optemp_test):    
    wc = optemp_test.GetMg() * coordinates
    mynull = c4d.BaseObject(c4d.Onull)    
    mynull[c4d.ID_BASEOBJECT_USECOLOR] = True
    mynull[c4d.ID_BASEOBJECT_COLOR] = c4d.Vector(1,0,0)
    mynull.SetAbsPos(wc)    
    mynull.SetName(null_name + " Point")
    doc.InsertObject(mynull)
    return

def delete_nulls (all_objects_list): # delet all Nulls exept my start this is just for debugging
    n = 0
    while n < len(all_objects_list):
        optempdelete = all_objects_list[n]
        if optempdelete.GetType() == 5140 and len(optempdelete.GetChildren()) == 0 or optempdelete.GetType() == 5101:
            optempdelete.Remove()
        n = n+1
    c4d.EventAdd()
# End create nulls ///////////////////////////////////////////////////////////////////////////

def f2(seq): 
   # order preserving
   checked = []
   for e in seq:
       if e not in checked:
           checked.append(e)
   return checked


# Ray stuff and nearest obj -------------------------------------------------------------------------------------
    
""" Darter original
def get_ray(start_obj, end_obj, goal):
    start = ~goal.GetMg() * start_obj.GetMg().off
    end =  ~goal.GetMg() * end_obj.GetMg().off
    return {'ray_p' : start, 'ray_length' : (end - start).GetLength(), 'ray_dir' : (end - start).GetNormalized()}
"""

def get_ray(start_obj, end_obj, goal): #modified to accept vectors as start instead of object Global Mg
    start = ~goal.GetMg() * c4d.Vector(start_obj)
    end =  ~goal.GetMg() * end_obj.GetMg().off
    return {'ray_p' : start, 'ray_length' : (end - start).GetLength(), 'ray_dir' : (end - start).GetNormalized()}

def firerayat (start, direction, length, optemp_test): # startpoint, direction, length, object to colide
    collider = c4d.utils.GeRayCollider()    
    collider.Init(optemp_test) #force cache rebuild with , True    
    did_intersect = collider.Intersect(start, direction, length) #(start.GetAbsPos(), direction, length)
    if did_intersect:        
        create_null(collider.GetNearestIntersection()["hitpos"], optemp_test.GetName(), optemp_test) #debugging
        return collider.GetNearestIntersection()["distance"]
        #return collider.GetIntersection(0)["distance"]
    else:        
        return None

def get_nearest_obj_in_list (temp_op_distance_list):    
    temp_op_distance_list.sort(key=lambda x: x[1])
    #print temp_op_distance_list[0][0], temp_op_distance_list[0][1]
    if len(temp_op_distance_list) != 0 and temp_op_distance_list[0][1] != None:
        return temp_op_distance_list[0][0]

def get_nearest_obj (start_point, target, obj_list, jump): 
    #jump is bullshit we can't jump anything hence it could be in the line of sight
    temp_op_distance_list = [] #Reset
    for obj_rows in obj_list:
        opgoal = obj_rows[0]  # object, #_tested, #_counter_nearest      
        ray = get_ray( start_point, target, opgoal )
        distance = firerayat(ray['ray_p'], ray['ray_dir'], ray['ray_length'], opgoal)
        
        if distance != None:
            #print "Distance: ", distance, " - ", opgoal.GetName(), start_point
            temp_op_distance_list.append( [opgoal, distance] )
    
    near_obj = get_nearest_obj_in_list(temp_op_distance_list)    
    for i, row in enumerate(obj_list):
        if near_obj in row:
            print "Found Near Object at Row Index: ", i, "   Column: ", row.index(near_obj), " obj Name: ", obj_list[i][0].GetName()
            obj_list[i][2] = obj_list[i][2] + 1 # increment the hitcounter

# End ray //////////////////////////////////////////////////////////////////////

def layer_init (l_name, color, displayseen):
    if find_layer(l_name):        
        x_layer = find_layer(l_name)        
    else:
        x_layer = create_layer(l_name, color, displayseen)
    return x_layer
    
# Main ----------------------------------------------------------------------------------------
        
def main():
    c4d.CallCommand(13957) # Konsole löschen
    time_start = c4d.GeGetTimer() # start stopwatch
    
    if GetActiveDocument():
        doc = GetActiveDocument()
        if doc.GetFirstObject():
            c4d.StatusSetSpin()
            op = doc.GetFirstObject()
            all_objects = numberofobjects(op) # list off all objects            
            counter = len(all_objects['all_objects_list'])
            all_objects_list = all_objects['all_objects_list']
            poly_obj_list = all_objects['polygon_obj_list']
            c4d.StatusSetText ('%s Objects are processed.' %(counter))
        else:
            print "Error: No Objects"
            return False
    else:
        print "Error: No Document"
        return False
    
    # delete_nulls (all_objects_list) # delete all Nulls exept my start this is just for debugging        
    
    layer_not_hit = layer_init ("Not hit", c4d.Vector(0.5,0,0), True) # True layer seen display option
    layer_seen = layer_init ("Seen", c4d.Vector(0,0.25,0), True) 
    layer_seen_def = layer_init ("Seen more than once", c4d.Vector(0.5,0.75,0), True) 
    layer_checked = layer_init ("checked", c4d.Vector(0,0,0.75), True) 
        
    if doc.SearchObject("Start Point Cloud"):
        oldsphere = doc.SearchObject("Start Point Cloud")
        oldsphere.Remove()
    
    if doc.SearchObject("Manual_Target_01"):
        manual_target = doc.SearchObject("Manual_Target_01")
    else:
        manual_target = 0
    
    start_point_list = create_sphere(5, 500, c4d.Vector(100,1,1),  True) # Subdivisions, Radius, c4d.vector, deleteme=True False
    
    hit_list = []
    never_hit = []
    tested = []
    hit_list_definatly = []    
    jump = 3 # if an object was hit 2 times jump it for ray colision
	
    print "Polygon Objects: ", len(poly_obj_list)
    print "Startpoint positions: ", len(start_point_list)    
    print "-------------------------------------------------------------"
	
    count_a = 0
    count_b = 0
    count_c = 0
    si = 0
    for start_cord in start_point_list:
        #start_cord = start_point_list[5]  #manual for debugging
        
        c4d.StatusSetText ('%s Objects and %s Ray Start Points are processed.' %(len(poly_obj_list), len(start_point_list))) 
        count_a += 1
        
        if manual_target == 0:
            for row_obj in poly_obj_list:
                statusbar(len(poly_obj_list)*len(start_point_list)  , count_b)
                count_b += 1
                optarget = row_obj[0] # Target for Ray - may also be a coordinate in the future
                row_obj[1] += 1 # targetcounter in list of list +1
                # if optarget.GetName() == "should not": create_spline_ray (optarget, start_cord)  # slow just for debugging
                # this is the main function which dows the magic
                get_nearest_obj( start_cord, optarget, poly_obj_list, jump) # startpoint, target, objlist, jump
                # End magic //////////////////////////////////////////////////////////////////////
        else:
            print "Manual Target Used"
            statusbar(len(poly_obj_list)*len(start_point_list)  , count_b)
            count_b += 1
            optarget = manual_target # Target for Ray - may also be a coordinate in the future
            create_spline_ray (optarget, start_cord)  # slow just for debugging
            # this is the main function which dows the magic
            get_nearest_obj( start_cord, optarget, poly_obj_list, jump) # startpoint, target, objlist, jump
            # End magic //////////////////////////////////////////////////////////////////////            

    # after loops 
    
    print "--------------" 
    for row in poly_obj_list:
        print "Tested: ", row[1]," - Hitcounter: ", row[2], " - Name: ", row[0].GetName()
        if row[1] == 0:
            tested.append(row[0]) # append the object to the tested list this is not used at the moment just stored
        if row[2] == 0:
            never_hit.append(row[0])
        else:
            if row[2] == jump:
                hit_list.append(row[0])
            if row[2] >= jump:
                hit_list_definatly.append(row[0])
            
    put_on_layer (hit_list_definatly, layer_seen_def)  
    put_on_layer (hit_list, layer_seen)
    put_on_layer (never_hit, layer_not_hit)
    #put_on_layer (tested, layer_checked)
    
    print "-------------------------------------------------------------"
    print "Never Tested count: ", len(tested)    
    print "Hitlist count: ", len(hit_list)
    print "Hit more than %s times: " %jump, len(hit_list_definatly)
    print "Never Hit: ", len(never_hit)
    print "---------------------------------------------------------------------"        
    print 'END OF SCRIPT - Duration (H:MM:SS:ms):   %s' %(gime_time(time_start))
    c4d.EventAdd()  
    c4d.StatusClear()
    
if __name__=='__main__':
    main()
__________________
R17 Visualize - Flickr Album - Website
 
  02 February 2013
Thread automatically closed

This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.
__________________
CGTalk Policy/Legalities
Note that as CGTalk Members, you agree to the terms and conditions of using this website.
 
Thread Closed share thread



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
CGSociety
Society of Digital Artists
www.cgsociety.org

Powered by vBulletin
Copyright ©2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump
Miscellaneous

All times are GMT. The time now is 02:44 AM.


Powered by vBulletin
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.