- Home /
Discrepency between calculation in console program and Unity
When I was experimenting with prerendered backgrounds I came across a formula to match Unity's camera to Blender's, which is necessary to properly align the colliders. Since a FoV of 49 appears different in Blender than it does in Unity you can't just copy the value over.
Since the calculator that comes with Windows 7 seems to be missing the atan function and the calculator I used in high school 20 years ago is no longer working I wrote a console program that requires you to type in Blender's focal length, the x resolution, and the y resolution.
Here's the meat of the console program:
double UFoV = 2*Math.Atan(16.0/(aspect*BFoV)) * (180/Math.PI);
Where UFoV is the result you put into Unity, aspect is just width/height (originally made to work with prerendered images), and BFoV is the focal length in millimeters, which defaults to 35. At 35mm with a 16:9 aspect ratio the result is 28.something. When you export stand-in geometry from Blender to test the alignment it lines up perfectly.
I decided to integrate this into a Unity script to handle various aspect ratios and screen resizing. Here's the meat of the Unity script:
cam.fieldOfView = 2 * Mathf.Atan(16f / ((res.width/res.height) * focal_length)) *(180 / Mathf.PI);
Where res is a Resolution struct that captures the current resolution at start and whenever the window is resized and focal_length is the focal length of Blender's camera.
When I run the game it sets the FoV to exactly match Blender's FoV at the focal length entered, which defaults to 49.something. Numerically it matches but 49 in Unity seems to be a much wider viewing angle than it is in Blender.
As best as I can tell I didn't change anything in the formula, other than calculating the aspect ratio on that line instead of in a preceding line, I just used different variable names. I have no idea what's causing the discrepancy between the console program and Unity.
Thank you both for your help.
@coolraiman Your suggestion didn't sound nearly as stupid as the actual cause of the problem. I forgot to factor in the resolution being integers, so res.width/res.height was returning 1. I found that out when I decided to hard code the values into the console program to test it out, where previously the width and height were doubles since I had to use the convert class with user input. Casting them to floats in Unity gave me the right result.
@Bunny83 I always wondered about the difference between $$anonymous$$ath and $$anonymous$$athf. From a calculation standpoint I don't fully understand vertical FoV (took me two tries to get through basic Algebra in high school, barely passing the second time) and I never would have been able to calculate the formula I used, ins$$anonymous$$d just stumbling across it in a tutorial and figuring out through trial and error that I needed to convert it to degrees (the (180/pi) wasn't on the source site). It does explain why you can't simply copy the FoV from Blender over to Unity, though, and I get what it means from an implementation standpoint.
I've moved away from prerendered backgrounds. Thought they'd be great for the background full motion videos without taking away player control like you saw in Final Fantasy VIII, but it was too limiting for what I wanted to do overall and advances in real time rendering, including allowing free users access to the formerly pro only whistles and bells, have pretty much rendered them useless (pun intended).
That means I don't think I have to worry about the aspect for the background images (the initial plan was to detect the resolution at startup then assign the appropriate image), but it's real handy for setting up a scene entirely in Blender and getting a near perfect translation when I import the scene, since I'm still using semi-static cameras in a lot of places.
DO NOT POST CO$$anonymous$$$$anonymous$$ENTS AS ANSWERS
Answer by coolraiman · Jan 26, 2016 at 02:07 PM
it may sound stupid but on the first line of code you use the class Math and on the second one you use the class Mathf.
You should check if pi return the same number of numbers after the floating point and if mathf.Atan is calculated the exact same way as Math.Atan
Sometimes errors come from where you never expect them
The $$anonymous$$athf class is just a wrapper with some casts for the System.$$anonymous$$ath class ^^. Unity implemented it since Unity almost exclusively uses float values while all System.$$anonymous$$ath functions work with double values. The conversion float to double is implicit but not the reverse. The $$anonymous$$athf class just simplifies:
float a = (float)$$anonymous$$ath.PI;
float b = (float)$$anonymous$$ath.Sin(a);
to
float a = $$anonymous$$athf.PI;
float b = $$anonymous$$athf.Sin(a);
ps: $$anonymous$$athf.PI does not return a float casted double constant. They simply declared PI as a float constant:
public const float PI = 3.14159274f;
pps: The $$anonymous$$athf class also has predefined conversion factors for radians:
public const float Deg2Rad = 0.0174532924f; // equals "PI / 180"
public const float Rad2Deg = 57.29578f; // equals "180 / PI"
Answer by Bunny83 · Jan 26, 2016 at 08:25 PM
Keep in mind that the FOV only depends on the height. It's called the vertical FOV. The horizontal FOV will change depending on your screen size. Just undock the gameview in the editor and try resizing it. You will notice if you change the height of the window, things grow and shrink along with the height of the window. However if you change the width of the window the image will stay the same you just gain or loose view space at the sides.
If you want to test for specific aspect ratios, you can set the gameview to a certain aspect ratio which might add "cinema scope" bars either at the top and bottom or at the sides to achieve a certain aspect ratio. If you want to set the horizontal FOV you need to multiply the calculated angle by the aspect ratio.
Keep in mind that when using the horizontal FOV on a wide screen screen you will have less space at the top and bottom than on a 4:3 screen. You can't have both FOVs set at the same time unless you want a stretched or distorted image. In that case you need to calculate the projection matrix yourself as Unity always calculates an aspect ratio fixed view.
ps: the windows calculator does have an atan function. All you have to do is press the "inv" (inverse) button at the top. It will change all the trigonometry functions to their inverse function as well as "ln" to "ex"
Your answer
Follow this Question
Related Questions
How to make camera position relative to a specific target. 1 Answer
One camera sees a GUI texture but the other camera does not. I need them both to. 1 Answer
ratchet and clank style camera 0 Answers
Scene Camera continues to move after letting go of W 2 Answers
Unity 5.2 camera not recognised 1 Answer