Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Recent
    • Tags
    • Users
    • Login

    Possible to target particle geo with ray? [SOLVED]

    Scheduled Pinned Locked Moved PYTHON Development
    10 Posts 0 Posters 961 Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H Offline
      Helper
      last edited by

      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!

      1 Reply Last reply Reply Quote 0
      • H Offline
        Helper
        last edited by

        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 😢

        1 Reply Last reply Reply Quote 0
        • H Offline
          Helper
          last edited by

          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()  
            
          
          1 Reply Last reply Reply Quote 0
          • H Offline
            Helper
            last edited by

            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 🙂

            1 Reply Last reply Reply Quote 0
            • H Offline
              Helper
              last edited by

              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

              1 Reply Last reply Reply Quote 0
              • H Offline
                Helper
                last edited by

                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.

                1 Reply Last reply Reply Quote 0
                • H Offline
                  Helper
                  last edited by

                  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()  
                  
                  1 Reply Last reply Reply Quote 0
                  • H Offline
                    Helper
                    last edited by

                    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.

                    1 Reply Last reply Reply Quote 0
                    • H Offline
                      Helper
                      last edited by

                      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

                      1 Reply Last reply Reply Quote 0
                      • H Offline
                        Helper
                        last edited by

                        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.)

                        1 Reply Last reply Reply Quote 0
                        • First post
                          Last post