最大缩放距离以适合2个对象

问题描述 投票:2回答:1

目标:在Z轴上移动相机位置ONLY,以使平截头体适合2个对象。

条件:

  • 其中一个对象将始终与相机X位置对齐
  • 相机设置为透视模式,而不是按地形。
  • 2个球体没有父级
从顶视图的地形学模式中看到的

结果应该如下所示:enter image description here

到目前为止我所做的:

使用三角函数可以将其视为:

enter image description here

知道目标是找到相邻面,这是相机与黑点之间的距离,该黑点仍将适合黄色的那一侧。

TECHNICALLY此段代码应找到相邻的值:

private float CalculateMaxZoomDistanceToBall()
{
    //Calculate angle from camera, should be divided of 2 cause it's placed on the middle of the line
    Camera currentCamera = cameraComp;
    angleDegrees = currentCamera.fieldOfView / 2; //(degrees)

    //pass the angle to radians 
    angleRadians = angleDegrees * Mathf.Deg2Rad;

    //Calculate the SinAngle
    sinAngle = Mathf.Sin(angleRadians);

    //Calculate Opposite       
    opposite = Mathf.Abs(blackPoint.transform.localPosition.x - yellowPoint.transform.position.x);

    //Calculate hypotenuse
    hypotenuse = opposite / sinAngle;

    //Calculate CosX
    cosAngle = Mathf.Cos(angleRadians);

    //Calculate adjacent distance
    adjacent = cosAngle * hypotenuse;

    return adjacent;
}

由于相机对象位于0,我只需将返回值添加到gameObject.transform.position.z

而且有人会说“,但这是在寻找垂直的FOV,您需要水平的FOV”,好吧,我也尝试过使用水平的FOV,找到了:

float vFOVrad = currentCamera.fieldOfView * Mathf.Deg2Rad; 
float cameraHeightAt1 = Mathf.Tan(vFOVrad * 0.5f);
float hFOVrad = Mathf.Atan(cameraHeightAt1 * currentCamera.aspect) * 2;
hFOV = hFOVrad * Mathf.Rad2Deg;

并且它不起作用,在某些情况下,摄像机的位置距离预期的位置很远,有时它很合适,而其他的恰好接近。

感谢您的帮助,谢谢。

c# unity3d camera trigonometry fieldofview
1个回答
1
投票

我将避免使用角度,而是在向量和平面的世界中工作。

确定黄点在相机的哪一侧:

Camera cam = cameraComp;
Transform camTransform = cam.transform;
Vector3 yellowPos = yellowPoint.transform.position;

// <0 if on left, >0 if on right
float camDirection = Vector3.Dot(camTransform.right, yellowPos - camTransform.position);

// if it's directly straight ahead, do nothing.
if (Mathf.Approximately(camDirection, 0f)) return;

在黄点的同一侧找到相机视口边缘的光线。视口中的高度无关紧要。

Ray edgeRay = cam.ViewportPointToRay(camDirection < 0f ? Vector3.zero : Vector3.right);

定义垂直于相机右侧并经过黄点位置的代数平面(不是物理平面:

Plane yellowPlane = new Plane(camTransform.right, yellowPos);

使用代数射线投射(不是物理射线投射)找到射线与平面的交点:

float raycastDistance;
if (! yellowPlane.Raycast(edgeRay, out raycastDistance)) return; // should not return

Vector3 raycastPoint = edgeRay.GetPoint(raycastDistance);

找到相交点到yellowPoint位置的差,并与照相机的前进方向进行点积,以找到如何沿照相机的前进方向移动照相机:

float forwardDelta = Vector3.Dot(camTransform.forward, yellowPos - raycastPoint);

camTransform.Translate(0f, 0f, forwardDelta);

所以,总共:

Camera cam = cameraComp;
Transform camTransform = cam.transform;
Vector3 yellowPos = yellowPoint.transform.position;

// <0 if on left, >0 if on right
float camDirection = Vector3.Dot(camTransform.right, yellowPos - camTransform.position);

// if it's directly straight ahead, do nothing.
if (Mathf.Approximately(camDirection, 0f)) return;

Ray edgeRay = cam.ViewportPointToRay(camDirection < 0f ? Vector3.zero : Vector3.right);

Plane yellowPlane = new Plane(camTransform.right, yellowPos);

float raycastDistance;
if (! yellowPlane.Raycast(edgeRay, out raycastDistance)) return; // should not return

Vector3 raycastPoint = edgeRay.GetPoint(raycastDistance);

float forwardDelta = Vector3.Dot(camTransform.forward, yellowPos - raycastPoint);

camTransform.Translate(0f, 0f, forwardDelta);

关于这种方法的好处是,不管相机的方向如何,或与相机的相对位置如何,它都可以使用。

© www.soinside.com 2019 - 2024. All rights reserved.