Calculate Latitude and Longitude using UV Coordinates of a sphere

I want to calculate a world position point on the sphere using only the UV coordinates of a 3D mesh sphere.

Not my code:

    // Convert UV coordinate to World Coordinate
    public Vector3 UVTo3D(Vector2 uv, Mesh mesh, Transform transform)
    {
        int[] tris = mesh.triangles;
        Vector2[] uvs = mesh.uv;
        Vector3[] verts = mesh.vertices;
       
        for (int i = 0; i < tris.Length; i += 3)
        {
            Vector2 u1 = uvs[tris[i]];      // get the triangle UVs*
            Vector2 u2 = uvs[tris[i + 1]];
            Vector2 u3 = uvs[tris[i + 2]];

            // Calculate triangle area - if zero, skip it
            float a = Area(u1, u2, u3);
            if (a == 0)
                continue;

            // Calculate barycentric coordinates of u1, u2 and u3
            // If any is negative then point is outside the triangle, skip it

            float a1 = Area(u2, u3, uv)/a;
            if (a1 < 0)
                continue;

            float a2 = Area(u3, u1, uv)/a;
            if (a2 < 0)
                continue;

            float a3 = Area(u1, u2, uv)/a;
            if (a3 < 0)
                continue;

            // Point inside the triangle - find mesh position by interpolation…
            Vector3 p3D = a1 * verts[tris[i]] + a2 * verts[tris[i + 1]] + a3 * verts[tris[i + 2]];

            // return it in world coordinates:
            return transform.TransformPoint(p3D);
        }
        return Vector3.zero;
    }

    /// Calculate signed triangle area using a kind of “2D cross product”:
    private float Area(Vector2 p1, Vector2 p2, Vector2 p3)
    {
        Vector2 v1 = p1 - p3;
        Vector2 v2 = p2 - p3;
        return (v1.x * v2.y - v1.y * v2.x) / 2;
    }

What type of sphere?
It must be a two-pole sphere (so called UV sphere) otherwise UVs don’t correlate with lat/long.
I’ve recently posted a full spherical angle solution so you can grab that. I’ll try to find it.

I’ve found the post .

Barycentric Coordinates was the exact thing I was looking for.
Thank you so much for the response.

Ah ok I see now what you meant. Mentioning a 3D mesh sphere was not really important. You could’ve said on a triangle or mesh in general.

But then I’m not sure what you meant by “Latitude and Longitude” in the title. World position has nothing to do with lat/long.

Anyway you can also use Unity API for what you’re doing, which is likely faster. Just do Physics.Raycast (against a static collider, you don’t have to actually simulate physics for this to work), and you’ll get both barycentric coord and world position. It is especially easy to build a probing ray for the sphere mesh, because it just points towards the center.

// returns false if point is inside the sphere
bool GetPointOnMesh(Vector3 point, Vector3 sphereOrigin, float sphereRadius, out Vector3 hit) {
  hit = new Vector3(float.NaN, float.NaN, float.NaN);
  var delta = sphereOrigin - point;
  if(delta.sqrMagnitude < sphereRadius * sphereRadius) return false;
  var ray = new Ray(point, delta.normalized);
  if(Physics.Raycast(ray, out var rcHit)) { hit = rcHit.point; return true; }
  return false; // << this shouldn't actually happen
}

Of course, mesh is not perfect, so you should set sphereRadius to a minimum value so it doesn’t clip through mesh and give you false negatives.

Edit:
And browse Physics.Raycast for more info, especially with how to configure collision layers via layer masks in order for the ray cast to interact with the desired collider.

And you can also extract the triangle index, barycentric coordinates, distance, surface normal and so on. See RaycastHit struct.