- Home /

# Using Equirectangular Projection to convert 2D coordinates to 3D coordinates failed. What is wrong?

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);
```

just ouf of curiosity can you show us the math values and results?

@FernandoHC On the picture, the two 2d coordinates are (10, 160) and (25, 180). However, on the game scene, the two balls look like they are a bit too far away, and should be around the Chinese characters in the left hand side. Also, the "Start" ball should be supposedly at the left top corner and the "End" ball should be at the right bottom corner, but in the game scene, the position is reversed.

Thanks. I'm not very good with maths, but since you have a relative position already calculated, wouldn't it be possible to get the desired results by inverting that y(the world position y) for each sphere. After your calculation, just try: y *=-1;

**Answer** by ysleungrockman
·
Aug 14, 2018 at 12:59 PM

Now, I am going to answer myself. There are several issues in this code:

The conversion does not need

`LONPERPIXEL`

.Unity

`Cos`

and`Sin`

functions use radian, so the theta and phi have to multiply`Mathf.Deg2Rad`

.The equations in 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);
}
}
```

### Your answer

### Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.

### Follow this Question

### Related Questions

SmoothDamp Issue with Large Values 0 Answers

Placing object in scene 2 Answers

"Moving" skybox closer, to emulate a smaller room? (VR 360 degree app) 2 Answers

Select audiosource from camera angle 1 Answer