尝试使用等角投影将2D坐标转换为3D坐标。但是失败了。我究竟做错了什么?

时间:2018-08-12 12:12:21

标签: c# unity3d projection 360-degrees 360-panorama

当前,我正在Unity中制作一个360度视频应用。我通过使用进行等角矩形投影的Unity Skybox Panoramic shader成功制作了视频以进行渲染。现在,我尝试通过给定的2D点在视频上设置一些按钮。 2D点系统有些棘手,与笛卡尔坐标系统有所不同(我的老板要求使用...)。 x轴的范围是-90(顶部)到90(底部),并且用作垂直轴。 y轴的范围是-180至180,并用作水平轴。现在,在计算3D坐标的主题上,我阅读了等角投影的wiki page并看到了这些方程。由于没有旋转,我假设φ1和λ0为零?因此,计算中的λ(经度)和φ(纬度)仅为y(水平坐标)和-x(垂直坐标)。由于经度和纬度在球坐标中也只是θ和φ,因此我使用此C#程序计算坐标:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CreateButtons : MonoBehaviour {

    public GameObject testObject;
    public Vector2 generatePositionStart;
    public Vector2 generatePositionEnd;
    public float radius = 50f;
    const float LONPERPIXEL = 3840f / 360f;

    // Use this for initialization
    void Start () {
        Vector3 pointS = GetPoint (radius, generatePositionStart.y * LONPERPIXEL, -generatePositionStart.x * LONPERPIXEL);
        GameObject start = Instantiate (testObject, pointS, Quaternion.identity) as GameObject;
        start.name = "Start";
        Vector3 pointE = GetPoint (radius, generatePositionEnd.y * LONPERPIXEL, -generatePositionEnd.x * LONPERPIXEL);
        GameObject end = Instantiate (testObject, pointE, Quaternion.identity) as GameObject;
        end.name = "End";
    }

    Vector3 GetPoint (float rho, float theta, float phi) {
        float x = rho * Mathf.Sin (theta) * Mathf.Cos (phi);
        float y = rho * Mathf.Sin (theta) * Mathf.Sin (phi);
        float z = rho * Mathf.Cos (theta);
        return new Vector3 (x, y, z);
    }
}

程序将计算按钮的两个2D坐标(左上角和右下角)。然后在3D位置上生成两个球体。但是,计算出的3D坐标不在正确的位置上。我做错什么了吗?

P.S .:我发现了另一个方程式,它说这是一个逆映射。我尝试过,但位置仍然错误。等式如下所示:

float x = rho * Mathf.Cos (theta) * Mathf.Cos (phi);
float y = rho * Mathf.Sin (theta) * Mathf.Cos (phi);
float z = rho * Mathf.Sin (theta);

1 个答案:

答案 0 :(得分:2)

现在,我要回答自己。这段代码中有几个问题:

  1. 该转换不需要LONPERPIXEL
  2. 单位CosSin函数使用弧度,因此theta和phi必须乘以Mathf.Deg2Rad
  3. GetPoint()中的方程是完全错误的。

这是正确的代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CreateButtons : MonoBehaviour {

    public GameObject testObject;
    public Vector2 generatePositionStart;
    public Vector2 generatePositionEnd;
    public float radius = 50f;

    // Use this for initialization
    void Start () {
        Vector3 pointS = GetPoint (radius, generatePositionStart.y * Mathf.Deg2Rad, -generatePositionStart.x * Mathf.Deg2Rad);
        GameObject start = Instantiate (testObject, pointS, Quaternion.identity) as GameObject;
        start.name = "Start";
        Vector3 pointE = GetPoint (radius, generatePositionEnd.y * Mathf.Deg2Rad, -generatePositionEnd.x * Mathf.Deg2Rad);
        GameObject end = Instantiate (testObject, pointE, Quaternion.identity) as GameObject;
        end.name = "End";
    }

    // Update is called once per frame
    void Update () {

    }

    Vector3 GetPoint (float rho, float theta, float phi) {
        float x = rho * Mathf.Sin (theta) * Mathf.Cos (phi);
        float y = rho * Mathf.Sin (phi);
        float z = rho * Mathf.Cos (theta) * Mathf.Cos (phi);
        return new Vector3 (x, y, z);
    }
}