Search code examples
java3dcameralwjgl

Calculating points visibility in 3D space


I am experimenting with LWJGL2 and I want to be able to tell if the camera is able to see a certain point in 3D space. I was trying on my own to see if I could do it, and ended up with something that kinda works and only for rotation on the Y axis.

This code works, but not in both axes. I am not sure if this is the correct way to do it either.

public boolean isInFrame(float x, float y, float z){ //The z isn't used

    float camera = rotation.y; //The cameras y rotation
    double object = Math.atan2(y, x)*(180/Math.PI);

    object += (180 - camera);
    if (object <0 ) object += 360;
    if (object >360 ) object -= 360;

    return 270>object&&90<object; //set to 180˚ for test


}

For the code, I am assuming the camera is centered around 0,0,0.

I just want to know how I could change this so that it works for x and y rotation of the camera. For example, it could tell me if if a point is visible regardless of the cameras rotation.

NOTE: I am not worrying about anything obstructing the view of the point.

Thanks for the help in advance.


Solution

  • If you have the view and projection matrices of the camera (let's call them V, P), you can just apply the transformations to your point and check whether the result lies within the clip volume of the camera.

    Say your point is at (x, y, z). Construct a vector p = (x, y, z, 1) and apply the camera transform to it:

    q = P * V * p
    

    The view transform V applies the transformation of the world relative to the camera, based on the camera position and orientation. Then, the projection P deforms the camera's view frustum (i.e., the visible space of the camera) into a unit cube, like this:

    enter image description here
    (Image source: Song Ho Ahn)

    In order to read off the coordinate values of the resulting point, we must first de-homogenize it by dividing by its w component:

    r = q / q.w
    

    Now, the components r.x, r.y, r.z tell you whether the point lies within the visible range of the camera:

    • If r.x < -1, the point lies beyond the left border of the screen.
    • If r.x > 1, the point lies beyond the right border of the screen.
    • If r.y < -1, the point lies beyond the bottom border of the screen.
    • If r.y > 1, the point lies beyond the top border of the screen.
    • If r.z < -1, the point lies beyond the near plane of the camera, i.e., the point is behind the camera or too close for the camera to see.
    • If r.z > 1, the point lies beyond the far plane of the camera, i.e., the point is too far away for the camera to see.
    • Otherwise, the point is in the visible range of the camera.