在 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 度经度的倍数以外的点,这似乎不是特别准确