在 Unity 中旋转地球仪,同时保持正确的向上方向
Rotating a globe in Unity while keeping it the right way up
这是问题所在:
我有一个统一的地球仪,通过右键单击并拖动鼠标,它可以围绕赤道和与相机水平的平行轴旋转(在本例中为绝对 x 轴,保持YZ 平面上的极点),这工作正常,没问题。
另一种旋转地球仪的方法是单击标签,它会自动旋转地球仪以将标签置于相机的中心。地球开始以全球坐标 0,0 为中心。这是有效的,但是标签离本初子午线越远(所以从 0 纬度向东或向西越远),极点旋转越远离它们的预期轴(而不是沿着 YZ 平面)。有没有人知道如何实现这一目标?
相关代码如下:
public class LabelBehaviour : MonoBehaviour
{
[...]
public void HomeIn()
{
globe.transform.rotation = Quaternion.identity;
Vector3 fromDirection = transform.position;
Vector3 toDirection = mainCamera.transform.position;
InputController.Instance.rotateTo = Quaternion.FromToRotation(fromDirection, toDirection);
}
}
//InputController class is attached to the globe object
public class InputController : MonoBehaviour {
[...]
void Update()
{
if(Quaternion.Angle(rotateTo,transform.rotation) > .1f)
//rotate towards position in 1.5s
rotateTime = Mathf.Min(rotateTime + Time.deltaTime * .75f,1);
transform.rotation = Quaternion.Slerp(rotateFrom, rotateTo, rotateTime);
if (Quaternion.Angle(rotateTo, transform.rotation) <= .1f)
{
rotateTo = transform.rotation;
rotateFrom = transform.rotation;
rotateTime = 0;
}
UpdateLabelRotations();
}
}
}
经过一整天的数学运算,结果证明解决方案非常简单:
因为我知道了标签的球坐标(eg lat/long),所以我可以计算出我需要的对应的欧拉角,这里是相关代码:
InputController.Instance.rotateTo = Quaternion.Euler(
xzAngle * Mathf.Cos(Mathf.Deg2Rad * yAngle),
yAngle,
xzAngle * Mathf.Sin(Mathf.Deg2Rad * yAngle)
);
虽然是几天后发布的,但对于 90 度经度的倍数以外的点,这似乎不是特别准确
这是问题所在:
我有一个统一的地球仪,通过右键单击并拖动鼠标,它可以围绕赤道和与相机水平的平行轴旋转(在本例中为绝对 x 轴,保持YZ 平面上的极点),这工作正常,没问题。
另一种旋转地球仪的方法是单击标签,它会自动旋转地球仪以将标签置于相机的中心。地球开始以全球坐标 0,0 为中心。这是有效的,但是标签离本初子午线越远(所以从 0 纬度向东或向西越远),极点旋转越远离它们的预期轴(而不是沿着 YZ 平面)。有没有人知道如何实现这一目标?
相关代码如下:
public class LabelBehaviour : MonoBehaviour
{
[...]
public void HomeIn()
{
globe.transform.rotation = Quaternion.identity;
Vector3 fromDirection = transform.position;
Vector3 toDirection = mainCamera.transform.position;
InputController.Instance.rotateTo = Quaternion.FromToRotation(fromDirection, toDirection);
}
}
//InputController class is attached to the globe object
public class InputController : MonoBehaviour {
[...]
void Update()
{
if(Quaternion.Angle(rotateTo,transform.rotation) > .1f)
//rotate towards position in 1.5s
rotateTime = Mathf.Min(rotateTime + Time.deltaTime * .75f,1);
transform.rotation = Quaternion.Slerp(rotateFrom, rotateTo, rotateTime);
if (Quaternion.Angle(rotateTo, transform.rotation) <= .1f)
{
rotateTo = transform.rotation;
rotateFrom = transform.rotation;
rotateTime = 0;
}
UpdateLabelRotations();
}
}
}
经过一整天的数学运算,结果证明解决方案非常简单:
因为我知道了标签的球坐标(eg lat/long),所以我可以计算出我需要的对应的欧拉角,这里是相关代码:
InputController.Instance.rotateTo = Quaternion.Euler(
xzAngle * Mathf.Cos(Mathf.Deg2Rad * yAngle),
yAngle,
xzAngle * Mathf.Sin(Mathf.Deg2Rad * yAngle)
);
虽然是几天后发布的,但对于 90 度经度的倍数以外的点,这似乎不是特别准确