Mathematical relation between zoom and camera position

Greetings!

I am currently working on a project which requires me to use an immobile camera to zoom in on an object based on a formula which tells me at what distance that object looks fine on my camera.
The problem arises the moment I want to modelize this concept, as I can only work with the camera FoV as a parameter, but i only have specifics on the optimal distance.
Thus I ask whether there is a mathematical relation between FoV (zoom) and the “hypothetical” camera position you would need to have to obtain the same zooming effect without touching the FoV

Sorry if I wasn’t clear enough, ask any question if you need to

the results won’t be exactly the same due to the difference in perspective however this should get you some reasonable results:

private Camera camera;

private float originalFov;

private float actualDistance;

public float MimickDistance;
    
void Start()
{
    camera = this.GetComponent<Camera>();
    originalFov = camera.fieldOfView;
    actualDistance = 10; //this probably needs to be set to the distance of the front face of your object from the camera
}

void Update()
{
    camera.fieldOfView = calculateFieldOfView(originalFov, actualDistance, MimickDistance);
}

private float calculateFieldOfView(float originalFov, float actualDistance, float mimickDistance)
{
    float theta = originalFov * Mathf.Deg2Rad;
    float y = 2 * mimickDistance * Mathf.Tan(theta / 2);
    float fov = 2 * Mathf.Atan2(y, 2 * actualDistance);
    return fov * Mathf.Rad2Deg;
}

You can see here in the first screenshot is the actual image, of a camera at a distance 5 from a cube, and in the second image is the camera at a distance 10 with a mimicked value of 5.


Why does this work?

Apparently I can’t have more than two screenshots on the answer otherwise I would have added this there!

It comes down to some reasonably straight forward trigonometry but it is applied a little confusingly. The best thing we can try to achieve is ‘change the field of view such that, object at a distance x are shown at the same size as moving the original camera to a distance y’.

So let’s first look at how the field of view triangle would look if we could move the camera to where we wanted (the number ‘1’ in the image below). We have our original field of view value a and we say that at distance x the ‘size’ of the view is y. This gives us a target of the shape of the new triangle we are going to create, that is we want at our new distance u, we also want the ‘size’ of the view to be y so y is the same in both the 1st and 2nd images.

We can then write two equations, one for each of the 2 triangles, the 3rd image gives some context to how these calculations come about:

  • y = 2*x*tan(a/2)
  • y = 2*u*tan(b/2)

Now we have values for a and x so we can find the value of y straight away, but our second equation needs rearranging so that we are solving for b.

  • y/(2*u) = tan(b/2)
  • atan(y/(2*u)) = b/2
  • 2*atan(y/(2*u)) = b

we have a value for y and u at this point, so substituting those values in gets an answer for b. The only change I made at this point is to use Unity’s useful Atan2 method instead of Atan which means I split up the argument y/(2*u) into two separate arguments, so that Unity handles dividing by zero for us.