Search Unity

How to calculate horizontal field of view?

Discussion in 'Scripting' started by Jessy, Dec 22, 2008.

  1. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    Rodolfo-Rubens likes this.
  2. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    I think you want something like:-
    Code (csharp):
    1. var radAngle = cam.fieldOfView * Mathf.Deg2Rad;
    2. var radHFOV = 2 * Math.Atan(Mathf.Tan(radAngle / 2) * cam.aspect);
    3. var hFOV = Mathf.Rad2Deg * radHFOV;
    4.  
     
    Bunny83, quadrohead, Jargon and 9 others like this.
  3. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    Thanks!

    I figured out something quite similar on my own, but it took me some researching on Wikipedia about trigonometry, because I haven't really use trig for a decade. However, I didn't know about camera.aspect, so thanks for pointing me to that!

    Code (csharp):
    1. var vFOVrad : float = camera.fieldOfView * Mathf.Deg2Rad;
    2. var cameraHeightAt1 : float = Mathf.Tan(vFOVrad *.5);
    3. var hFOVrad : float = Mathf.Atan(cameraHeightAt1 * camera.aspect) * 2;
    4. var hFOV : float = hFOVrad * Mathf.Rad2Deg;
    You'd think that this would be included for convenience, in the API, if something as simple as camera.aspect is. How should I suggest this to UT?
     
  4. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    I think the Report Bug app has an option on the pop-up to send a feature request. UT are more likely to take notice of requests sent like this than Wish List posts, so they say.
     
    Rodolfo-Rubens likes this.
  5. drussilla

    drussilla

    Joined:
    Mar 20, 2014
    Posts:
    9
    If you want to have horizontal fiels of view instead of vertical you need this formula:
    camera.fieldOfView = horizontalFieldOfView * (16f/9f) / ((float)camera.pixelWidth / camera.pixelHeight);
     
    Last edited by a moderator: Feb 16, 2019
    Rodolfo-Rubens likes this.
  6. Helical

    Helical

    Joined:
    Mar 2, 2014
    Posts:
    50
    6 years later. I find this useful. Took me 10 minutes to understand what you did there. nice 1.
     
    Rodolfo-Rubens likes this.
  7. Taylor-Libonati

    Taylor-Libonati

    Joined:
    Jan 20, 2013
    Posts:
    16
    For anyone interested, I wrote a script that you can attach to a gameObject with a camera and it will log the horizontal FOV whenever it is updated. I used Jessy's formula which seems pretty accurate.

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. [RequireComponent( typeof( Camera ) )]
    6. public class ShowCameraHorizontalFOV : MonoBehaviour {
    7.     private Camera cam;
    8.     private float horizontalFOV = 0;
    9.     private float loggedFOV = 0;
    10. #if UNITY_EDITOR
    11.     public void OnDrawGizmos()
    12.     {
    13.         cam = gameObject.GetComponent<Camera>();
    14.         if (cam != null)
    15.         {
    16.             horizontalFOV = getHorizontalAngle(cam);
    17.             if(horizontalFOV != loggedFOV)
    18.             {
    19.                 loggedFOV = horizontalFOV;
    20.                 logFOV(horizontalFOV);
    21.             }
    22.         }
    23.     }
    24.    private  float getHorizontalAngle(Camera camera)
    25.     {
    26.         float vFOVrad = camera.fieldOfView * Mathf.Deg2Rad;
    27.         float cameraHeightAt1 = Mathf.Tan(vFOVrad * .5f);
    28.         return Mathf.Atan(cameraHeightAt1 * camera.aspect) * 2f * Mathf.Rad2Deg;
    29.     }
    30.  
    31.     void OnEnable()
    32.     {
    33.         if(loggedFOV != 0)
    34.         {
    35.             logFOV(loggedFOV);
    36.         }
    37.     }
    38.     private void logFOV(float value)
    39.     {
    40.         Debug.Log(name + "FOV: " + value);
    41.     }
    42. #endif
    43. }
     
  8. Nodrap

    Nodrap

    Joined:
    Nov 4, 2011
    Posts:
    83
    Found this thread really useful when I wanted to find a way to fix the horizontal field of view regardless of the aspect ratio of the camera. Here's the code by way of thanks. Just drop it onto your camera and set your fixed horizontal FOV.

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. // Lock the cameras horizontal field of view so it will frame the same view in the horizontal regardless of aspect ratio.
    4.  
    5. [RequireComponent (typeof(Camera))]
    6. public class HorizontalFOVLock : MonoBehaviour {
    7.  
    8.     public float fixedHorizontalFOV = 60;
    9.  
    10.     Camera cam;
    11.  
    12.     void Awake()
    13.     {
    14.         GetComponent<Camera>().fieldOfView = 2 * Mathf.Atan(Mathf.Tan(fixedHorizontalFOV * Mathf.Deg2Rad * 0.5f) / GetComponent<Camera>().aspect) * Mathf.Rad2Deg;
    15.     }
    16. }
     
    EZaca, AnTruong, sathya and 3 others like this.
  9. illa3d

    illa3d

    Joined:
    Dec 7, 2014
    Posts:
    17
    If anyone finds this useful, created an solution that keeps the horizontal FOV if device orientation changes to portrait.
    Just slap on your camera and define the aspect ratio where it starts keeping stuff horizontally visible.
    IE: You like how your fov horizontally looks at 16:9, just use the default HFovOnAspect of 1.777. Job done.

    Regular camera variant
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. [RequireComponent(typeof(Camera))]
    4. public class CameraFovSwitcher : MonoBehaviour {
    5.     Camera cam;
    6.     Camera Cam { get { if (!cam) cam = GetComponent<Camera>(); return cam; } }
    7.  
    8.     [Range(0.1f, 2)]
    9.     [Tooltip("Aspect treshold for switching to horizontal fov calculation")]
    10.     public float HFovOnAspect = 1.777f;
    11.    
    12.     float vFov;
    13.     float vFovNew;
    14.  
    15.     private void Awake() {
    16.         vFov = Cam.fieldOfView;
    17.     }
    18.  
    19.     void Update() {
    20.         if (Cam.aspect < HFovOnAspect) {
    21.             vFovNew = Camera.HorizontalToVerticalFieldOfView(Camera.VerticalToHorizontalFieldOfView(vFov, HFovOnAspect), Cam.aspect);
    22.             if (Cam.fieldOfView != vFovNew) {
    23.                 Cam.fieldOfView = vFovNew;
    24.             }
    25.         } else if (Cam.fieldOfView != vFov) {
    26.             Cam.fieldOfView = vFov;
    27.         }
    28.     }
    29. }
    Cinemachine Virtual Camera variant
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using Cinemachine;
    4.  
    5. [RequireComponent(typeof(CinemachineVirtualCamera))]
    6. public class CMCameraFovSwitcher : MonoBehaviour {
    7.     CinemachineVirtualCamera cam;
    8.     CinemachineVirtualCamera Cam { get { if (!cam) cam = GetComponent<CinemachineVirtualCamera>(); return cam; } }
    9.  
    10.     [Range(0.1f,2)]
    11.     [Tooltip("Aspect treshold for switching to horizontal fov calculation")]
    12.     public float HFovOnAspect = 1.777f;
    13.    
    14.     float vFov;
    15.     float vFovNew;
    16.  
    17.     private void Awake() {
    18.         vFov = Cam.m_Lens.FieldOfView;
    19.     }
    20.  
    21.     void Update() {
    22.         if (Cam.m_Lens.Aspect < HFovOnAspect) {
    23.             vFovNew = Camera.HorizontalToVerticalFieldOfView(Camera.VerticalToHorizontalFieldOfView(vFov, HFovOnAspect), Cam.m_Lens.Aspect);
    24.             if (Cam.m_Lens.FieldOfView != vFovNew) {
    25.                 Cam.m_Lens.FieldOfView = vFovNew;
    26.             }
    27.         } else if (Cam.m_Lens.FieldOfView != vFov) {
    28.             Cam.m_Lens.FieldOfView = vFov;
    29.         }
    30.     }
    31. }
     
    Last edited: Jun 14, 2022
    ooo8197 likes this.