Get actual camera field of view in AR?

I need to get the camera’s FOV in my AR app however the Camera.fieldOfView parameter is incorrect and remains at whatever value is set in the Unity editor, regardless of the actual FOV on the device. I understand that AR takes over the camera matrix. I am not trying to change it, just need the real FOV value to calculate screen relative placements. I’ve reviewed this other thread and tried a number of different methods for calculating the FOV with no solution found yet.

Debug.Log("Camera.fieldOfView:" + Camera.fieldOfView); 
// Always the same (incorrect) value set in the editor, not the actual FOV rendered

// FOV calculated from projection matrix is also incorrect and results 
// in same value as above
float t = Camera.projectionMatrix.m11;
float fov = Mathf.Atan(1.0f / t) * 2.0f * Mathf.Rad2Deg;
float z = 0.5f / Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad);
transform.localPosition = new Vector3(0f, 0f, z);


// The screen width and scale do correctly report the device's screen resolution
Debug.Log("Screen.width:" + Screen.width + " height:" + Screen.height);

// The following is from the Vuforia, but alas does not work either
Ray ray = Camera.main.ScreenPointToRay(new Vector3(Screen.width / 2.0f, Screen.height, 0));
float angle = Vector3.Angle(Camera.main.transform.forward, ray.direction);
fov = angle * 2.0f;
Debug.Log("fov:" + fov);

// I've also tried placing 3D objects in screen space, but the
// ScreenToWorldPoint calculation is incorrect based again on the wrong FOV, 
// not the actual FOV being displayed
Vector3 start = Camera.ScreenToWorldPoint(new Vector3(0f, 0f, z));
Vector3 end = Camera.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, z));
StartMarker.transform.position = start;
EndMarker.transform.position = end;
}

Any ideas?

The question is, when are you doing all those calculations? Try on LateUpdate after the ARCameraManager has done it’s job.

Also you could take a look at the configurations of the camera if that helps:

https://docs.unity3d.com/Packages/com.unity.xr.arsubsystems@4.0/api/UnityEngine.XR.ARSubsystems.XRCameraConfiguration.html

Thanks for the suggestions! I originally had the above code running upon Start but tried it during LateUpdate instead and got the same result. All three of the methods for calculating the FOV return the same value, which is whatever value is assigned to the camera in the Editor.

I looked at XRCameraConfiguration which in itself didn’t provide the answer but lead me to look at XRCameraSubsystem where I found the XR projection matrix and found the solution!

Below is the method I’m using and it works as expected on the device. Because the camera subsystem doesn’t start up right away, it tries repeatedly until it succeeds. CameraManager is a reference to ARCameraManager in the scene. ARCameraManager also has a frameReceived event, though I opted to do it this way instead.

void Update()
{
    if (!HasFOV) {
        XRCameraParams cameraParams = new XRCameraParams {
            zNear = Camera.nearClipPlane,
            zFar = Camera.farClipPlane,
            screenWidth = Screen.width,
            screenHeight = Screen.height,
            screenOrientation = Screen.orientation
        };

        XRCameraFrame cameraFrame;
        if (CameraManager.subsystem.TryGetLatestFrame(cameraParams, out cameraFrame)) {
            t = cameraFrame.projectionMatrix.m11;
            fov = Mathf.Atan(1.0f / t) * 2.0f * Mathf.Rad2Deg;
            Debug.Log("AR matrix fov:" + fov);
            HasFOV = true;
        }
        else {
            Debug.Log("AR matrix fov: FAILED");
            HasFOV = false;
        }
    }
}

Ah great! Glad to know I could help in some way I guess haha

Maybe using the FrameReceived would be better to make sure you get the first frame that is handled by the CameraManager otherwise before that you can’t get the camera projection matrix right? At least not the right camera projection matrix.

But glad that worked out!

This feature is available starting from AR Foundation 4.1.3:
https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@4.1/changelog/CHANGELOG.html#413---2021-01-05

2 Likes

@KyryloKuzyk Oh great! thanks for the info! :slight_smile:

Hi . I need to do a zoom in zoom out function in the ar camara using the real camara. Is this possible? Ive tried with the fov but it doesnt have any effect. Any help?

Camera zoom is not possible with ARCore. ARKit 6 introduces a capability to zoom the camera on iOS, but AR Foundation does not yet support this. So it is possible, but there is currently no C# API to do so.

When will unity update this function??

We currently don’t have plans to do this. You can request this feature on our Road Map by selecting AR Foundation and scrolling down to Submit an Idea! XR roadmap | Unity

1 Like