Check if a vertex is seen by the camera



  • On 08/02/2018 at 09:25, xxxxxxxx wrote:

    How can I check if a specific vertex in a polygonal object is seen by a camera?
    I just need to know if it is inside the camera fov.
    I found a COFFEE code snippet that would do that but I can't seem to be able to re-write it in python



  • On 08/02/2018 at 09:33, xxxxxxxx wrote:

    Ok, never mind.
    I got it 😄



  • On 09/02/2018 at 01:57, xxxxxxxx wrote:

    Hi Rui,

    Could you quickly share with the community the solution for your problem?



  • On 09/02/2018 at 04:05, xxxxxxxx wrote:

    Actually, I found out that it works fine when the camera is facing some directions but it stops working when it faces others.
    Still trying to fix that.



  • On 09/02/2018 at 04:32, xxxxxxxx wrote:

    This is my code, and it works fine, except when I rotate the camera around as some points are not considered inside the cone, at some camera orientations:

      
    camm=cam.GetMg()   
    campos=cam.GetAbsPos()   
    camrot=cam.GetAbsRot()   
      
    fov=cam[c4d.CAMERAOBJECT_FOV]/2.0   
    render=doc.GetFirstRenderData()   
    xres=render[c4d.RDATA_XRES_VIRTUAL]   
    yres=render[c4d.RDATA_YRES_VIRTUAL]   
    yfov=fov*((1.0/xres)*yres)   
      
    pol_obj_mt=pol_obj.GetMg()   
    points=pol_obj.GetAllPoints()   
      
    for pp in points:   
            
         pt_pos=pp*pol_obj_mt   
      
         angle=utils.VectorToHPB(pt_pos-campos)   
         dangle=angle-camrot   
         locpos=pt_pos*~camm   
      
         if (locpos.z<=0 or dangle.x>=fov or dangle.x<=-fov or dangle.y>=yfov or dangle.y<=-yfov) :   
              continue   
      
         if(locpos.z>0 and (dangle.x<=fov or dangle.x>=-fov or dangle.y<=yfov or dangle.y>=-yfov)) :   
              # the point is inside the camera cone   
      
    


  • On 10/02/2018 at 06:47, xxxxxxxx wrote:

    Maybe in this movie the problem becomes clearer:

    https://youtu.be/onnJ6SDK2Z4



  • On 11/02/2018 at 07:10, xxxxxxxx wrote:

    Ok, made it work.
    Had to make sure that the angle remained in the range 0 to PI*2 in some occasions and converted to the range -PI to +PI in others, like this:

      
    pi=3.1415926   
    pi2*2.0*pi   
      
    def mod_angle(a) :   
         if a<0: return (pi2+a)%pi2   
         return a%pi2   
      
    def mod_angle2(a) :   
         a=mod_angle(a)   
         if a>pi: return -pi2+a   
         return a   
      
    # ********************************************   
      
    camm=cam.GetMg()   
    campos=cam.GetAbsPos()   
    camrot=cam.GetAbsRot()   
      
    camrot.x=mod_angle(camrot.x)   
    camrot.y=mod_angle(camrot.y)   
    camrot.z=mod_angle(camrot.z)   
      
    fov=(cam[c4d.CAMERAOBJECT_FOV]+(2*tag[SBC_EXTRA]))/2.0   
    render=doc.GetFirstRenderData()   
    xres=render[c4d.RDATA_XRES_VIRTUAL]   
    yres=render[c4d.RDATA_YRES_VIRTUAL]   
    yfov=fov*((1.0/xres)*yres)   
      
    pol_obj_mt=pol_obj.GetMg()   
      
    for i,pp in enumerate(points) :   
            
         pt_pos=pp*pol_obj_mt   
      
         angle=utils.VectorToHPB(pt_pos-campos)   
      
         angle.x=mod_angle(angle.x)   
         angle.y=mod_angle(angle.y)   
         angle.z=mod_angle(angle.z)   
      
         dangle=angle-camrot   
      
         dangle.x=mod_angle2(dangle.x)   
         dangle.y=mod_angle2(dangle.y)   
         dangle.z=mod_angle2(dangle.z)   
      
         locpos=pt_pos*~camm   
      
         if (locpos.z<=0 or dangle.x>=fov or dangle.x<=-fov or dangle.y>=yfov or dangle.y<=-yfov) :   
              continue   
      
         if(locpos.z>0 and (dangle.x<=fov and dangle.x>=-fov and dangle.y<=yfov and dangle.y>=-yfov)) :   
              # the point in within the camera cone   
    

    The problem now is that this seems to fail for vertical camera angles that are pointing downwards.
    Can someone that is much more knowledgeable than me, check out if I'm doing something wrong.
    I just need to make sure a point is within the camera cone, no matter how the camera is oriented.



  • On 16/02/2018 at 07:59, xxxxxxxx wrote:

    Hi Rui!

    Sorry for the late reply.

    It seems the camera for the calculation is used in the active view so you can rely on BaseView calculations.
    So retrieve the active view, convert the point coordinate to camera space to check its Z (BaseView.WC()+BaseView.TestPointZ()), then to screen space to test its view visibility ((BaseView.CS()+BaseView.TestPoint())).
    In the following code, point is the point coordinate in world space:

    visible = False
    pointCam = bd.WC(point)
    if bd.TestPointZ(pointCam) :
        pointScr = bd.CS(pointCam, False)
        visible = bd.TestPoint(pointScr.x, pointScr.y)
    

    Note the code doesn't check for back-face culling.


Log in to reply