最大化缩放距离以适合 2 objects
Maximize zoom distance to fit 2 objects
Objective:
在 Z 轴上移动相机位置 ONLY,使平截头体适合 2 objects。
条件:
- 其中一个 object 将始终与相机 X 位置对齐
- 相机设置为透视模式,而非正交模式。
- 2个球体没有parent
top-view 在正交模式下看到的结果 应该如下所示:
到目前为止我做了什么:
使用三角函数可以将其视为:
知道了,objective就是找相邻的边,也就是相机到黑点的距离,还是会和黄点相配.
技术上这段代码应该找到相邻的值:
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;
}
由于相机 object 位于 0,我只需将 return 值添加到 gameObject.transform.position.z
有人会说 “但这是在寻找垂直视场,你需要水平视场”,好吧,我也试过水平视场,找到了:
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);
这种方法的好处在于,无论相机的方向如何,或者点与相机的相对位置如何,它都会起作用。
Objective: 在 Z 轴上移动相机位置 ONLY,使平截头体适合 2 objects。
条件:
- 其中一个 object 将始终与相机 X 位置对齐
- 相机设置为透视模式,而非正交模式。
- 2个球体没有parent
top-view 在正交模式下看到的结果 应该如下所示:
到目前为止我做了什么:
使用三角函数可以将其视为:
知道了,objective就是找相邻的边,也就是相机到黑点的距离,还是会和黄点相配.
技术上这段代码应该找到相邻的值:
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;
}
由于相机 object 位于 0,我只需将 return 值添加到 gameObject.transform.position.z
有人会说 “但这是在寻找垂直视场,你需要水平视场”,好吧,我也试过水平视场,找到了:
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);
这种方法的好处在于,无论相机的方向如何,或者点与相机的相对位置如何,它都会起作用。