目标:在Z轴上移动相机位置ONLY,以使平截头体适合2个对象。
条件:
到目前为止我所做的:
使用三角函数可以将其视为:
知道目标是找到相邻面,这是相机与黑点之间的距离,该黑点仍将适合黄色的那一侧。
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;
并且它不起作用,在某些情况下,摄像机的位置距离预期的位置很远,有时它很合适,而其他的恰好接近。
感谢您的帮助,谢谢。
我将避免使用角度,而是在向量和平面的世界中工作。
确定黄点在相机的哪一侧:
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);
关于这种方法的好处是,不管相机的方向如何,或与相机的相对位置如何,它都可以使用。