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.