目标:仅在Z轴上 移动摄像机位置,以使截锥体适合2个对象。
条件:
到目前为止,我所做的是:
使用三角函数可以将其视为:
Knowing that, the objective is to find the Adjacent side, which will be the distance between the camera and the black point that will still fit the yellow one.
TECHNICALLY this piece of code should find the adjacent value:
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;
}
as the camera object is positioned at 0, I simply add the return value to the gameObject.transform.position.z
And someone could say "but this is looking for the vertical FOV, you need the horizontal one", okey, I've also tried with the horizontal one, finded with:
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;
And it's not working, in some cases the camera position is to far of the espected position, sometimes it fits well and others it just goes to close.
Any help will be apreciated, thank you.
我会避免使用角度,而不会使用向量和平面。
确定黄点在相机的哪一侧:
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);
这种方法的好处是,无论相机的方向如何,还是相机上的点的相对位置如何,它都可以工作。
感谢@Ruzhim,您的方法有效。我不喜欢这个事实并不能真正解决我对“为什么我的方法不起作用”的疑问(因此,如果您知道为什么,我会很感激的解释),但至少可以解决目标。
@Lotan很难说,因为您的计算包括黑点的局部位置,并且问题未提及其父节点,因此我不知道该怎么做。
好吧,它是localPosition,但是它也可以是位置本身,因为这两个球体没有父级