尝试使用 Equirectangular Projection 将 2D 坐标转换为 3D 坐标。但是失败了。我究竟做错了什么?
Try using Equirectangular Projection to convert 2D coordinates to 3D coordinates. But failed. What am I doing wrong?
目前,我正在Unity中制作一个360视频应用。我使用等距柱状投影的 Unity Skybox Panoramic shader that does equirectangular projection. Now I am trying to set some buttons on the video by some 2D points given. The 2D point system is a bit tricky and is different from the Cartesian one (my boss requested it...). The range of x-axis is from -90 (top) to 90 (bottom), and is used as vertical axis. The range of y-axis is from -180 to 180, and is used as horizontal axis. Now on the topic of calculating the 3D coordinates, I read the 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);
}
}
程序会计算按钮的两个二维坐标(左上角和右下角)。然后在 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);
现在,我要回答自己了。这段代码有几个问题:
- 转换不需要
LONPERPIXEL
。
- Unity
Cos
和 Sin
函数使用弧度,所以 theta 和 phi 必须相乘 Mathf.Deg2Rad
.
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);
}
}
目前,我正在Unity中制作一个360视频应用。我使用等距柱状投影的 Unity Skybox Panoramic shader that does equirectangular projection. Now I am trying to set some buttons on the video by some 2D points given. The 2D point system is a bit tricky and is different from the Cartesian one (my boss requested it...). The range of x-axis is from -90 (top) to 90 (bottom), and is used as vertical axis. The range of y-axis is from -180 to 180, and is used as horizontal axis. Now on the topic of calculating the 3D coordinates, I read the 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);
}
}
程序会计算按钮的两个二维坐标(左上角和右下角)。然后在 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);
现在,我要回答自己了。这段代码有几个问题:
- 转换不需要
LONPERPIXEL
。 - Unity
Cos
和Sin
函数使用弧度,所以 theta 和 phi 必须相乘Mathf.Deg2Rad
. 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);
}
}