Determining the camera.fov from a projection matrix from a XR headset

I am well aware that setting fov on a XR camera is ignored, but when working on parts of scenes on a desktop, like people, I was using a 120mm lens to be more like videos / photo shoots. It seemed like a good idea at the time.

camera.fov = 0.265103; // 120mm focal length, source Blender

Now that I am now assembling a scene on a Quest 2, the characters look pretty amazing in PBR, especially with random expression idling, eye movement, & involuntary blinking. She / it looks.narrow though, especially in the head, and everything looks just a little small. I am generating everything in meters, so I think stuff is scaled right.

Think it comes down to that I am not used to looking at stuff with that fov. The default for fov, .80, is better, but still not the same as the headset. I wonder has anyone taken a projection matrix supplied from a Quest and somehow worked out what this camera property would be, if manually set? Think I would switch to that in dev, so that things would look more like they will when in XR.

Also, there are 3 width settings for the headset lenses. Think they are more than mechanical, and change the projection matrices supplied?

Well, I tracked down how fov is used in the computation of the projection matrix, here in math.vector.ts:

    /**
     * Stores a left-handed perspective projection into a given matrix with depth reversed
     * @param fov defines the horizontal field of view
     * @param aspect defines the aspect ratio
     * @param znear defines the near clip plane
     * @param zfar not used as infinity is used as far clip
     * @param result defines the target matrix
     * @param isVerticalFovFixed defines it the fov is vertically fixed (default) or horizontally
     */
    public static PerspectiveFovReverseLHToRef(fov: number, aspect: number, znear: number, zfar: number, result: Matrix, isVerticalFovFixed = true): void {
        let t = 1.0 / (Math.tan(fov * 0.5));
        let a = isVerticalFovFixed ? (t / aspect) : t;
        let b = isVerticalFovFixed ? t : (t * aspect);
        Matrix.FromValuesToRef(
            a, 0.0, 0.0, 0.0,
            0.0, b, 0.0, 0.0,
            0.0, 0.0, -znear, 1.0,
            0.0, 0.0, 1.0, 0.0,
            result
        );
        result._updateIdentityStatus(false);
    }

Seems to me the cleanest way to get the fov from a projection matrix is to look at _m[5] if fov is vertically fixed, and _m[0] if horizontal. Not sure for Quest, guess I’ll just get both.

Shown is for left handed. I do not know which hand is provided, but looking at the right handed way computation, it does not change in this respect.

Reading the private member _m would be a problem in typescript, but only need to do this once per headset, so pg seems that throws up an alert is like the perfect vehicle.

https://playground.babylonjs.com/#SM0W68#1

Works. Alerts do not display in XR mode, so you have to hit the “Oculus” button to exit, first, then the alert is displayed. Not going to publish what I actually got to be on the safe side of that NDA to get a developer account.

1 Like