Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Given 4 world points, how do I calculate camera position?

So I have 4 world points as Vector3 objects.

I also have a perspective camera with a fixed rotation.

I'd like to keep my camera's rotation, and keep it centered on 0,0,0 and can guarantee that my points will allow this as they're generated around the origin as well. I just need to move the camera back until they're all in view.

I'm new to Unity and thinking in 3D generally, so I'm not really sure what I'm looking for here, but I feel like this should be easy enough?

I think I could move the camera back until I get a WorldToViewportPoint that's between 0 - 1 but I'd like to apply an existing smooth move function I have which takes a start and end point, so I'd like a way to calculate this before moving the camera.

Any pointers would be appreciated.
Thanks

like image 571
Kraiden Avatar asked Dec 05 '25 18:12

Kraiden


1 Answers

By using trigonometry and some camera functions to find the camera's horizontal and vertical fov, you can find the distance along camera's forward the camera needs to move to just view each point, then take the minimum. Then, move the camera that distance along its forward.

This will handle any orientation/position of the camera!

Further details are in comments:

using System.Linq; // convenience

float GetClosestCameraDist(Vector3 point, float vCot, float hCot)
{ 
    // point to view (camera's local space)
    // v/hCot = cotan of half fovs

    // how far point should be from cam along cam forward to ensure 
    //   point is within fov along camera x/y axes
    float d = Mathf.Max(Mathf.Abs(point.y) * vCot,
                        Mathf.Abs(point.x) * hCot);

    // return how far cam needs to move from its current position 
    //   along cam forward
    // should be negative if it goes cam->  ... origin 
    //           positive if it goes origin ... cam->
    return point.z - d; 
}

Vector3 GetClosestCameraPos(Camera cam, List<Vector3> points)
{
    Transform tCam = cam.transform;

    // cam vertical/horizontal fov in radians
    float vFov = cam.fieldOfView * Mathf.Deg2Rad;
    float hFov = Camera.VerticalToHorizontalFieldOfView(cam.fieldOfView,
            cam.aspect) * Mathf.Deg2Rad;

    float vCot = 1f / Mathf.Tan(0.5f*vFov);
    float hCot = 1f / Mathf.Tan(0.5f*hFov);

    // calculate lowest needed distance from current position to valid position 
    //   along cam forward
    // lowest because the larger this is, the more forward camera is
    float c = points.Select(p => GetClosestCameraDist(tCam.InverseTransformPoint(p),
            vCot, hCot)).Min();

    // go that distance along cam forward from current cam position 
    // to find closest-to-points valid position.
    return c * tCam.forward + tCam.position;
}

Furthermore, if you would like to have the camera be slightly further back, the simplest way is to just adjust the values of hFov and vFov to be smaller, to have the math act like the camera's view is smaller. Something like the below:

    float vFov = // ...
    float hFov = // ...

    // Will bring the camera back further such that each point is within 
    //   the middle 90% horizontal and 90% vertical rectangle.
    hFov *= 0.9f;
    vFov *= 0.9f;

    // rest of GetClosestCameraPos
like image 160
Ruzihm Avatar answered Dec 08 '25 07:12

Ruzihm



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!