简体   繁体   English

给定 4 个世界点,我如何计算相机 position?

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

So I have 4 world points as Vector3 objects.所以我有 4 个世界点作为Vector3对象。

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.我想保持相机的旋转,并将其保持在0,0,0的中心,并且可以保证我的点将允许这样做,因为它们也是围绕原点生成的。 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?我是 Unity 的新手,一般都在思考 3D,所以我不太确定我在这里要找什么,但我觉得这应该很容易吗?

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.我想我可以将相机向后移动,直到我得到一个介于0 - 1之间的WorldToViewportPoint但我想应用现有的平滑移动 function 我有一个起点和终点,所以我想要一种计算方法在移动相机之前。

Any pointers would be appreciated.任何指针将不胜感激。
Thanks谢谢

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.然后,go 沿相机前方的距离。

The advantage of this method is that the only requirement is that the camera be looking directly at (or away from) the origin.这种方法的优点是唯一的要求是相机直接看(或远离)原点。 The camera can have any rotation.相机可以有任何旋转。

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 is from origin along camera's axes
    float Yp = Vector3.Dot(point, cam.transform.up);
    float Xp = Vector3.Dot(point, cam.transform.right);
    float Zp = Vector3.Dot(point, cam.transform.forward);

    // 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(Yp) / Mathf.Tan(vFov/2f),
            Mathf.Abs(Xp) / 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 Zp - d; 
}

Vector3 GetClosestCameraPos(Camera cam, List<Vector3> points)
{
    // calculate lowest needed distance from origin to cam along cam forward
    // lowest because the larger this is, the more forward camera is
    float c = points.Select(p => GetClosestCameraDist(cam, p)).Min();

    // go that distance along cam forward to find closest-to-points position.
    return c * cam.transform.forward;
}

Surely not the most efficient algorithm but with only 4 points it shouldn't be horrible.当然不是最有效的算法,但只有 4 分它不应该是可怕的。 It could be faster by only doing the 2 points that are most distant from the origin along the camera's up/right axes.通过仅沿相机的上/右轴执行距离原点最远的 2 个点,它可能会更快。


And... I think this change to the outer function should work for any relative positioning of camera/origin (!) :而且...我认为对外部 function 的这种更改应该适用于相机/原点的任何相对定位(!)

Vector3 GetClosestCameraPosOffset(Camera cam, List<Vector3> points)
{
    // Project origin onto camera forward
    Vector3 originOffset = cam.transform.position + cam.transform.forward 
            * Vector3.Dot(cam.transform.forward, 
                -cam.transform.position
            ).normalized;

    // calculate lowest needed distance from origin to cam along cam forward
    // lowest because the larger this is, the more forward camera is.
    // Only first... pretend the camera and point are shifted so the camera is 
    // pointing at/away from origin for easier calculation.
    float c = points.Select(p => GetClosestCameraDist(cam, p - originOffset)).Min();

    // go that distance along cam forward to find closest-to-points position.
    // Add the offset back in to stop pretending
    return c * cam.transform.forward + originOffset;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM