Mapping a Sphere to a Cube

Started by
0 comments, last by JoeJ 7 years, 11 months ago

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!

Advertisement
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...

This topic is closed to new replies.

Advertisement