Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calculating the FOV for the Perspective camera #1239

Closed
Tobiasartz opened this issue Feb 2, 2012 · 19 comments
Closed

Calculating the FOV for the Perspective camera #1239

Tobiasartz opened this issue Feb 2, 2012 · 19 comments
Labels

Comments

@Tobiasartz
Copy link

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 :)

@WestLangley
Copy link
Collaborator

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.

@Tobiasartz
Copy link
Author

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 ;)

@WestLangley
Copy link
Collaborator

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

@Tobiasartz
Copy link
Author

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?

@WestLangley
Copy link
Collaborator

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.

@Tobiasartz
Copy link
Author

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

@WestLangley
Copy link
Collaborator

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.

@Tobiasartz
Copy link
Author

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

@WestLangley
Copy link
Collaborator

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

@Tobiasartz
Copy link
Author

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

@WestLangley
Copy link
Collaborator

@Tobiasartz :-)

@awe-schaffhausen
Copy link

West Langley. You are a king. Thank you.

@MatthewRayfield
Copy link

This was super helpful !! Thanks @WestLangley !

@Emanuele-Spatola
Copy link

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;

@WestLangley
Copy link
Collaborator

@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.

@Emanuele-Spatola
Copy link

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?

@WestLangley
Copy link
Collaborator

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?

@svcondor
Copy link

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.

@julianfrank
Copy link

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 ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants