• 11
• 9
• 10
• 9
• 10

# Mapping a Sphere to a Cube

This topic is 708 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hello,

I'm working on my planet renderer for a while now, and i'm stuck with the quadtree sphere.

So i constructed 6 quadtrees and formed a cube, but how can i map my sphere to this cube?

For instance, think of a line tangent to the surface of my sphere; the center of the line is the closest point to the sphere,

the more you go sideways, the more the distance increases. But that's for a sphere, for the cube all the points are equally distanced from the

side of the cube.

In order to make this work i'm thinking to somehow project a position from sphere space to cube space (excuse my terminology, i'm a self taught programmer).

Now, getting back to my tangent line, if projected to a cube, my tangent line should look like a parabola,but how can this be achieved for an arbitrary point around the sphere?

In other words, a circular orbit around my planet should describe a square path in the "deformed" space.

I need an algorithm that takes a vec3 as input, representing the local space (sphere space) and to output a vec3 representing the "deformed" cube space.

vec3 cubify(vec3 p);

I've noticed that the quadtree way of managing the sphere level of detail is used almost everywhere, and it makes most sense, however i couldn't find any information about this particular issue.

Thank you so much for your help!

Edited by Cristian D.

##### Share on other sites
assuming you use the simple transfrom from cube surface to sphere surface: vec3 sphereS = cubeS.Unit(),
going from sphere to cube is very easy - i'll show two methods:

1. intersection ray - plane

vec3 ray = (playerPos - planitCenter).Unit();
Find the largest dimension of (fabs(ray.x), fabs(ray.y), fabs(ray.z)) and it's sign to classify which cubeface to select.
Build a plane for that face, e.g. planeNormal = vec3(1,0,0) of positive x has been chosen.
Assuming the cube has a side length of 2, we can use the normal also for the plane position.

vec3 intersectionPoint = IntersectRayPlane (qVec3 (0,0,0), ray, planeNormal, planeNormal);

Get the coords for the quadtree from y&z, still assuming normal is x:
float u = (intersectionPoint.y + 1.0f) / 2.0f;
float v = (intersectionPoint.z + 1.0f) / 2.0f;

inline float IntersectRayPlane (qVec3 &rO, qVec3 &rD, qVec3 &pO, qVec3 &pN)
{
// rD does not need to be unit length
float d = pN.Dot(rD);
float n = pN.Dot(pO - rO);

if (fabs(d) < FP_EPSILON) // ray parallel to plane
{
if (fabs(n) < FP_EPSILON) return 0; // ray lies in plane
else return FLT_MAX; // no intersection
}
float t = n / d;
return t;
}

... you can optimize and remove the branches because those case will not happen.

2. interstion ray - box

struct AABox
{
vec minmax[2]; // would be [(-1,-1,-1), (1,1,1)] for the same cube as above

void DistanceRayFrontAndBackface (float &ffd, float& bfd, const vec& rayOrigin, const vec& rayInvDirection)
{
vec t0 = vec(minmax[0] - rayOrigin).MulPerElem (rayInvDirection);
vec t1 = vec(minmax[1] - rayOrigin).MulPerElem (rayInvDirection);
vec tMin = t0.MinPerElem (t1);
vec tMax = t0.MaxPerElem (t1);
ffd = tMin.MaxElem(); // front face distance (behind origin if inside box)
bfd = tMax.MinElem(); // back face distance
}

bool IntersectRay (float& t, const vec& rayOrigin, const vec& rayInvDirection, float rayLength)
{
float ffd, bfd;
DistanceRayFrontAndBackface (ffd, bfd, rayOrigin, rayInvDirection);
t = (ffd > 0) ? ffd : bfd; // always the first intersection with a face
return (ffd <= bfd) & (bfd >= 0.0f) & (ffd <= rayLength);
}
}


That's an optimization utilizing the fact our planes always match the coordinate system directions.
So no dot products, but the division is still there:
vec rayInvDirection = vec (1.0 / ray.x, 1.0 / ray.y, 1.0 / ray.z);

The math here is pretty basic so i wonder you ask.
Be sure to understand how it works if you can use it.
Should become second nature and you should also end with a simpler way than what i've shown here ;)

A more interesting question would be:
How can i do that sphere <-> cube mapping in a way, that all cube texels have similar area.
Currently there is more detail near the cube corners, and you don't want this.
I plan to work on this soon, in case i can't find a solution somewhere...