Three.js: Calculating the FOV for the Perspective camera

Created on 2 Feb 2012  ·  19Comments  ·  Source: mrdoob/three.js

Since I have no previous experience with 3D I run in to some problems that might be common knowledge to you 3D pro's ;).
I have a wide variety of scene sizes (800x600, 1200x100 etc.).
What formula can I use to make sure that an object with a z position of 0 and a width and height that is the same as the scene fills up the entire scene.

E.g.: Object Mesh A is 1200x100 and is on Z position 0. The scene is 1200x100 as well. The camera is on z position 1500. What is the FOV to make the object fill the scene?

Something along the line of ((A / B ) * C) is what I'm looking for :D.

Infinite amount of kudos to whoever is brilliant enough to answer my question :)

Question

Most helpful comment

The visible height given the vertical field-of-view vFOV and distance from the camera dist is

height = 2 * Math.tan( ( vFOV / 2 ) ) * dist;

The visible width is

aspect = window_width / window_height;
hFOV = 2 * Math.atan( Math.tan( vFOV / 2 ) * aspect );
width  = 2 * Math.tan( ( hFOV / 2 ) ) * dist;

The field-of-view parameter for the camera in THREE.js is the vertical one.

Use the two sets of equations to calculate the required vFOV twice, and select the larger answer.

All 19 comments

The visible height given the vertical field-of-view vFOV and distance from the camera dist is

height = 2 * Math.tan( ( vFOV / 2 ) ) * dist;

The visible width is

aspect = window_width / window_height;
hFOV = 2 * Math.atan( Math.tan( vFOV / 2 ) * aspect );
width  = 2 * Math.tan( ( hFOV / 2 ) ) * dist;

The field-of-view parameter for the camera in THREE.js is the vertical one.

Use the two sets of equations to calculate the required vFOV twice, and select the larger answer.

Thank you so much for replying :)
I'm kind of confused though. Where do I get the variable vFOV from?
Is it the height of the object that should be filling the scene?
If so, I'm getting weird numbers ( in the 1000 range ) so how do I translate that to the eventual FOV.

I created a Fiddle http://jsfiddle.net/dmYgr/6/
Can you show me there how to do this?

Agains thank you so much. From your post I can already sense you're more of a genius than me ;)

Use the first equation and solve for vFOV, then use that as the fov parameter for the camera.

My scene is 800 * 600.
The distance of the camera is 1000.

How do I use these numbers in your formula.
I don't know what to fill in in vFOV.

height = 2 * Math.tan( ( vFOV / 2 ) ) * dist; <-- You're telling me to start here, but what number should replace vFOV?

Use the first equation and solve for vFOV like so

vFOV = 2 * Math.atan( height / ( 2 * distance ) );

then use that as the fov parameter for the camera.

var renderWidth = 800;
var renderHeight = 600;
var cameraPosition = 1000;
var vFOV = 2 * Math.atan( renderWidth / ( 2 * cameraPosition ) );
var height = 2 * Math.tan( ( vFOV / 2 ) ) * cameraPosition;
var aspect = renderWidth / renderHeight;
var hFOV = 2 * Math.atan( Math.tan( vFOV / 2 ) * aspect );
var width  = 2 * Math.tan( ( hFOV / 2 ) ) * cameraPosition;

Result:
vFOV = 0.7610127542247298 which is not a valid FOV

var vFOV = 2 * Math.atan( renderHeight / ( 2 * cameraPosition ) );
var height = 2 * Math.tan( ( vFOV / 2 ) ) * cameraPosition;

var aspect = renderWidth / renderHeight;
var hFOV = 2 * Math.atan( Math.tan( vFOV / 2 ) * aspect );
var width  = 2 * Math.tan( ( hFOV / 2 ) ) * cameraPosition;

vFOV = 0.5829135889557342 which is also not a valid FOV

Can you fill in the example for me and show an example that does give a valid FOV number?
The correct number of the above example is somewhere around 37

In your fiddle,

height = height of your plane mesh = 500.

distance = camera.z - plane.z = 1000 - 100 = 900.

vFOV = 2 * Math.atan( height / ( 2 * distance ) ) = 0.5419 radians, or 31.04 degrees.

2 * Math.atan( 500 / ( 2 * 900 ) ) = 0.5418937006768411 according to my browser (google chrome)

Sorry, I neglected to show the conversion from radians to degrees. I updated my previous post.

Thank you SO Much! :D
Hah, it took like 10 replies but it works now :).
Thanks again!

@Tobiasartz :-)

West Langley. You are a king. Thank you.

This was super helpful !! Thanks @WestLangley !

Thank you @WestLangley !!
Since it took me a while to realize I needed to add a conversion from radiants to degrees, I'm adding here an example with the final code:

var distance = 1000;
var FOV = 2 * Math.atan( window.innerHeight / ( 2 * distance ) ) * 180 / Math.PI;
var camera = new THREE.PerspectiveCamera( FOV, window.innerWidth/window.innerHeight, 0.1, distance );
camera.position.z = distance;

@Emanuele-Spatola Your formula does not make sense. window.innerHeight has units of pixels. distance most likely does not. Visible height must have the same units as distance.

I updated Tobiasartz's fiddle with that formula and it seems to work:
http://jsfiddle.net/dmYgr/63/
The canvas is 500px, the plane is 495x495 and there is approx 5px of border around it.
Why is 1000px not a valid distance?

http://jsfiddle.net/dmYgr/65/

Why is 1000px not a valid distance?

Have you ever placed a camera 1000 pixels in front of your subject?

You might place a real camera 10 feet away to look at a scene 10 feet wide. Similarly you could place a virtual camera 1000px away to view a scene 1000px wide.

I use this when I know the height, width of scene and distance of camera...

var distance = 1000,height=window.innerHeight,width=window.innerWidth
var diag = Math.sqrt((height*height)+(width*width))
var FOV = 2 * Math.atan( diag / ( 2 * distance ) ) * 180 / Math.PI;
var camera = new THREE.PerspectiveCamera( FOV, window.innerWidth/window.innerHeight, 0.1, distance );
camera.position.z = distance;

This way situations like height > width also get handled ...

Was this page helpful?
0 / 5 - 0 ratings

Related issues

scrubs picture scrubs  ·  3Comments

zsitro picture zsitro  ·  3Comments

seep picture seep  ·  3Comments

makc picture makc  ·  3Comments

filharvey picture filharvey  ·  3Comments