数学:墨卡托投影将360视频像素坐标转换为球面曲面坐标

时间:2017-10-11 19:53:34

标签: c# math unity3d

我试图将360视频像素坐标映射到球体表面坐标,但我无法得到正确的结果......它只是映射到错误的位置我已经知道360个视频像素的XY数据点。 / p>

how map 2d grid points (x,y) onto sphere as 3d points (x,y,z)

我检查了这个链接,我从这里复制了方法,但是我得到的并没有映射到所需的位置。

如何从像素中获得半径?

我不确定我是否正在为imageRadius传递正确的半径,但我认为它将是圆周/ PI以获得半径,视频比率为4096x2048。我也尝试传递数字1因为UV是0-1但是它不对......

方法错了吗?

也许方法是错误的。我将随机数传递给imageRadius,但无法获得正确的位置...如果我将X设为负数,那么看起来有点接近结果......?

当前结果

https://youtu.be/t0I7Hlb-tbk 它使用我在网上找到的方法映射到正确的位置......

项目文件

https://drive.google.com/a/swordfish-sf.com/file/d/0B45RYzVs0t0_VVdaaHdmNHRWTk0/view?usp=sharing 如果有人可以检查Unity项目文件那将是伟大的......

当前代码

public class mapScript : MonoBehaviour {

public int input = 4098;
float imageRadius = 4098f / Mathf.PI; //2098? 3072? 4098?
float radius;
public GameObject testSphere;

void Start () {
    radius = this.transform.localScale.x;
}


void Update () {
    imageRadius = input / Mathf.PI;
    int currentFrame = (int)this.GetComponent<VideoPlayer>().frame;

    testSphere.transform.position = MercatorProjection(mapVals[currentFrame,0],mapVals[currentFrame,1]);
}

Vector3 MercatorProjection(float xVal, float yVal)
{
    float lon = (xVal / imageRadius);
    float lat = (2 * Mathf.Atan(Mathf.Exp(yVal / imageRadius)) - Mathf.PI / 2);


    float calcX = radius * Mathf.Cos(lat) * Mathf.Cos(lon);
    float calcY = radius * Mathf.Cos(lat) * Mathf.Sin(lon);
    float calcZ = radius * Mathf.Sin(lat);

    Vector3 result = new Vector3(calcX,calcY,calcZ);
    Debug.Log(result);
    return result;
}



float[,] mapVals = new float[,] {
{1969.21f, 928.625f},
{1969.6f, 928.533f},
{1968.92f, 928.825f},
{1968.68f, 929f},
{1968.47f, 929.067f},
{1968.41f, 929.025f},
{1968.48f, 928.992f},
....
};
}

谢谢。

1 个答案:

答案 0 :(得分:1)

作为旁注,半径是任意的。像素坐标仅映射到方向坐标(极[θ]和方位角[ϕ]角度)。

我们可以通过将每个像素映射到相等的θϕ间隔来实现此目的。下图说明了低分辨率设置:

enter image description here

让我们采用以下惯例:对于W的图片,ϕ = 0对应于:

  • W:在X = floor((W - 1) / 2)X = ceil((W - 1) / 2)
  • 之间的中间位置
  • 奇数W:位于X = floor((W - 1) / 2)
  • 的像素列中间

Y处的像素行映射到θ = (Y + 0.5) / H * π处的等角线。

要映射完整中的所有像素,请X-0.5开始,而不是0,并以W - 0.5结束;同样适用于Y。由于整数坐标映射到上面所示像素区域的中心,因此可以对任何特定像素的整个区域进行寻址。如果您计划对例如多采样过滤进行多次采样过滤,则稍后可能需要此操作。抗混叠

代码:

Vector3 Mercator(float x, float y, int w, int h)
{
   // outside of valid pixel region
   if (x < -0.5f || x >= w - 0.5f || y < -0.5f || y >= h - 0.5f)
      return new Vector3();

   float theta = (y + 0.5f) / h * Math.PI;
   float phi = ((x + 0.5f) / w - 0.5f) * 2.0 * Math.PI;

   float c_t = Math.Cos(theta);
   return new Vector3(c_t * Math.Cos(phi), c_t * Math.Sin(phi), Math.Sin(theta));
}

...并将得到的方向向量乘以你喜欢的任何“半径”,因为它(基本上)与映射无关。