So I have 4 world points as Vector3
objects.
I also have a 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
CodePudding user response:
Can't test this at the moment but using trigonometry and some camera functions, you can find the distance from the origin along camera's forward you need to be to view each point, then take the minimum. Then, go that distance along camera's forward.
This should handle any orientation/position of the camera!
Further details are in comments:
using System.Linq; // convenience
float GetClosestCameraDist(Camera cam, Vector3 point)
{
// cam vertical/horizontal fov in radians
float vFov = cam.fieldOfView * Mathf.Deg2Rad;
float hFov = Camera.VerticalToHorizontalFieldOfView(cam.fieldOfView,
cam.aspect) * Mathf.Deg2Rad;
// how far point should be from cam along cam forward to ensure
// point is within fov along camera axes
float d = Mathf.Max(
Mathf.Abs(point.y) / Mathf.Tan(vFov/2f),
Mathf.Abs(point.x) / Mathf.Tan(hFov/2f) );
// return how far cam should be from origin 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;
// 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(cam,
tCam.InverseTransformPoint(p) )).Min();
// go that distance along cam forward from current cam position
// to find closest-to-points valid position.
return c * tCam.forward tCam.position;
}
Surely not the most efficient algorithm but with only 4 points it shouldn't be horrible. It could be faster by only doing the 2 points that are most distant from the camera's looking forward line along the camera's up/right axes.