Currently, I am making a 360 video app in Unity. I successfully make the video to render by using the 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 of equirectangular projection and saw the equations. I assume φ1 and λ0 to be zero since there is no rotation? So the λ (longitude) and φ (latitude) are just y (horizontal coordinate) and -x (vertical coordinate) in the calculation. Since longitude and latitude are also just θ and φ in spherical coordinates, I calculate the coordinates using this C# program:
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);
}
}
The program will calculate two 2D coordinates (left top corner and right bottom corner) of the button. Then generates two sphere on the 3D positions. However, the 3D coordinates calculated are not on the correct position. Did I do something wrong?
P.S.: I found another equations that it said it is an inverse mapping one. I tried but still got wrong positions. The equations look like these:
float x = rho * Mathf.Cos (theta) * Mathf.Cos (phi);
float y = rho * Mathf.Sin (theta) * Mathf.Cos (phi);
float z = rho * Mathf.Sin (theta);
Now, I am going to answer myself. There are several issues in this code:
LONPERPIXEL
.Cos
and Sin
functions use radian, so the theta and phi have to multiply Mathf.Deg2Rad
.GetPoint()
are completely wrong.So here are the correct code:
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);
}
}