Possible to target particle geo with ray? [SOLVED]



  • On 18/03/2015 at 09:25, xxxxxxxx wrote:

    Hello all,

    GeRayCollider seems to only take a polygon object :\  I'm trying to hit thinking particle geometry, though, and, unfortunately, the only way I can make it work is to:

    1. Grab a clone of the Particle Geometry object (geoObject.GetClone())
    2. doc.InsertObject() it into the scene
    3. Make it the active object and use the CallCommand() that makes it an editable polygon object (12236)
    4. Use that as the ray's target, and delete it afterwards

    This seems infinitely silly, though.  Can any of you pro's confirm that there's no way to raycast against particle geometry, otherwise?  I suspect it's impossible, but I wanted to check with smarter people before giving up...

    Thanks so much!



  • On 18/03/2015 at 09:28, xxxxxxxx wrote:

    Oh, and I forgot to mention you'd have to connect and delete the thousands (number of particles) of objects that get created in step 3, too :'(



  • On 18/03/2015 at 10:15, xxxxxxxx wrote:

    Hello Whithers,

    you´re right, GeRayCollider needs a polygonal object, but the steps to calculate collisions could be done easier.
    With utils.SendModellingCommand(c4d.MCOMMAND_CURRENTSTATETOOBJECT) you can convert the particle geometry to polygon objects.
    You´ll have a null object with all the particle geometryclones as children than, which can be converted to a single object with utils.SendModellingCommand(c4d.MCOMMAND_JOIN)
    The first member of the result is your merged polygonal object which can be checked against rays.
    Hope this helps?

    Best wishes
    Martin

    A snippet

      
    import c4d  
    from c4d import gui, utils  
      
    def Intersect_Rc(op,p0,p1) :  
            
      ray = utils.GeRayCollider()            
      ray.Init(op, True)         
        
      matr = op.GetMg()        
      pos = p0  * matr  
        
      ldir = p1-p0  
      direction = ldir.GetNormalized()  
      raylength = ldir.GetLength()  
        
      CollisionState = ray.Intersect(pos, direction, raylength)  
      erg = []  
      count= ray.GetIntersectionCount()  
      print count  
      if count >0:  
          for i in xrange(count) :    
              result = ray.GetIntersection(i)["hitpos"]  
              erg.append(result)  
            
          return erg  
      
                
      else: return  
        
      
    def main() :  
        
      #_____________________________________  
      #particle geometry must be the active object  
      if not op: return  
      if not op.IsInstanceOf(1001414) : return  
        
            
      #_____________________________________  
      #prepare test line/ray to check  
      LINE=doc.SearchObject("LINE")   
      if not LINE: return         
      p0l = LINE.GetPoint(0)  
      p1l =  LINE.GetPoint(1)  
      Lmatr = LINE.GetMg()     
      ##line points  in rayobject local space  
      matr = op.GetMg()  
      p0 = p0l*Lmatr*~matr  
      p1 = p1l*Lmatr*~matr  
        
         
        
      #_____________________________________  
      #validate particle geometry  
      virtualop = utils.SendModelingCommand(command = c4d.MCOMMAND_CURRENTSTATETOOBJECT,  
                                              list = [op.GetClone()],  
                                              doc = doc)  
      if not virtualop: return       
      merge = utils.SendModelingCommand(command = c4d.MCOMMAND_JOIN,   
                                          list = virtualop,   
                                          doc = doc)   
      if not merge: return  
      print merge  
      geometry = merge[0]  
        
      #_____________________________________  
      #test insertion  
      #doc.InsertObject(merge[0])  
      #c4d.EventAdd()  
        
        
      #_____________________________________  
      #ray collision  
      print Intersect_Rc(geometry, p0, p1)      
      
    if __name__=='__main__':  
      main()  
      
    


  • On 18/03/2015 at 10:52, xxxxxxxx wrote:

    Yeah, that's a shame, but your example does help--thanks a million for taking the time!

    Like the Tom Waits quote :)



  • On 19/03/2015 at 09:41, xxxxxxxx wrote:

    Hello,

    an alternative to using the modeling commands may be to apply the collider to the objects stored in the generator's cache. This cache can be accessed using GetCache(). Please notice that GeRayCollider operates in object space, so one would have to adjust the start point and ray direction.

    Best wishes,
    Sebastian



  • On 19/03/2015 at 10:49, xxxxxxxx wrote:

    Hey, thanks, Bach!

    I had tried GetCache(), but it kept crashing me (GetCrache()? heheh...).

    As crazy as this sounds, I'm currently keeping a hidden polygon object at hand that I manually position into place (according to the particle's position and orientation) every time I need to cast the ray.



  • On 19/03/2015 at 16:54, xxxxxxxx wrote:

    Hey,

    @Sebastian
    thanks for the hint ! Should be faster than.

    @Whithers
    did some tests on Sebastians suggestion and on this side of the town it´s running great.
    Could you please give it a try with this code?

      
    import c4d  
    from c4d import gui, utils  
      
    def Intersect_Rc(op,p0,p1) :  
      #_____________________________________  
      #ray collider function  
      #requires an polygonal object   
      #and two points in objects local space  
                
      ray = utils.GeRayCollider()            
      ray.Init(op, True)         
              
      ldir = p1-p0  
      direction = ldir.GetNormalized()  
      raylength = ldir.GetLength()  
        
      CollisionState = ray.Intersect(p0, direction, raylength)  
      erg = []  
      count= ray.GetIntersectionCount()  
        
      if count >0:  
          for i in xrange(count) :    
              result = ray.GetIntersection(i)["hitpos"]  
              erg.append(result)  
            
          return erg              
      else: return  
      
      
      
    def main() :  
        
        
      #_____________________________________  
      #particle geometry must be the active object  
      if not op: return  
      if not op.IsInstanceOf(1001414) : return  
        
            
      #_____________________________________  
      #prepare test line/ray to check  
      LINE=doc.SearchObject("LINE")   
      if not LINE: return         
      p0l = LINE.GetPoint(0)  
      p1l =  LINE.GetPoint(1)  
      Lmatr = LINE.GetMg()     
      ##line points  in worldspace  
      matr = op.GetMg()  
      p0 = p0l*Lmatr  
      p1 = p1l*Lmatr  
             
        
      #_____________________________________  
      #validate particle geometry childs  
      partgeolist = op.GetCache().GetChildren()                                          
      
        
      #_____________________________________  
      #ray collision test with an inverted child list  
      erg2 = []  
      for i,o in enumerate(partgeolist[::-1]) :  
          ##ray points in objects local space  
          omatr = o.GetMg()  
          p10 = p0*~omatr  
          p11 = p1*~omatr  
          result = Intersect_Rc(o, p10, p11)  
          if result:  
              print result,"hit"  
              print i,"particle number from alive particles"  
              for r in result:  
                  erg2.append(r*omatr )    
      
                
      #_____________________________________  
      #insert test objects  
      null_2 = c4d.BaseObject(c4d.Onull)  
      null_2.SetName("hitpoints")  
      doc.InsertObject(null_2)  
      for i in xrange(len(erg2)) :  
          sphere = c4d.BaseObject(c4d.Osphere)  
          sphere[c4d.PRIM_SPHERE_RAD] = 20  
          sphere[c4d.PRIM_SPHERE_SUB] = 3  
          sphere.InsertUnder(null_2)  
          sphere.SetAbsPos(erg2[i])  
      c4d.EventAdd()  
    


  • On 20/03/2015 at 10:12, xxxxxxxx wrote:

    Oh, thanks monkey!  Yeah, it's only when I use astronomical amounts of particles after all, so I guess no surprise there.  I really appreciate you guys taking the time.

    With a high particle count my silly method of moving around one polygon object every time you raycast is actually a lot faster (no need to load all that geo at once), so long as you only need to check one particle at a time.  Fun stuff.



  • On 20/03/2015 at 11:21, xxxxxxxx wrote:

    Hey Whithers,

    I think the idea behind your poly method is everything else but silly.
    It´s basically the concept behind a BVH(Bounding volume hierarchy) to check a simplified version of your geometry.
    It might be an interesting exercise to build a corresponding Polygon (size = max diagonal expansion of the bounding box, orientated towards the ray) to cast the ray against and if there is a hit, testing the real geometry with another ray to specify the precise collision points.
    If you implement a unique id for your particles to point to the right particle geometry this should be an efficient approach.
    What do you think?

    Best wishes
    Martin



  • On 20/03/2015 at 14:09, xxxxxxxx wrote:

    Yeah, it's those methods that makes visualizing the behavior of large numbers of particles feasible.  I've been mucking about with octrees, to that end (Niklas' idea).  Gonna try to implement that soon--if anyone knows how to find what the neighbors of a given leaf are in an octree, lemme know, heheheh... it's really confusing.  (Mostly kidding, as that would require its own thread, but seriously lemme know.)


Log in to reply