# Generating spherical world from heightmapped terrain

I am using a standard heightmapped procedural terrain in my project. However, I want the terrain to appear spherical when the user zooms out. This is an attempt to simulate the appearance of a spherical planet. Here is my current algorithm:

        //get the direction from the "planet" center to this vert
Vector3 sphereCentertoVertPosition = vert.Position - SphereCenter;
sphereCentertoVertPosition.Normalize();

//our rotation axis is the cross between the direction from this vert to the planet center and the root (center of the terrain) to the planet center
RotationAxis = Vector3.Cross(sphereCentertoVertPosition, sphereCenterToRootPosition);

//the amount we rotate is based on the distance of this vert from the center of the terrain
Vector3 fromCenter = vert.Position - Root.Position;
float amount = (fromCenter.Length() / ((myTextureWidth / Scale) / 2)) * (float)Math.PI;

Quaternion rot = Quaternion.CreateFromAxisAngle(RotationAxis, amount);

Vector3.Transform(ref vert.Position, ref rot, out vert.Position);


My main concern is that the rotation axis is not correct. Theoretically, should it be the cross between the vert-to-planet-center and the terrain-center-to-planet-center?

• What kind of result is this producing? – MichaelHouse Dec 18 '11 at 6:54
• – khayman218 Dec 18 '11 at 9:47
• In case anyone googles this, there were three problems. First, the rotation axis should be Vector3.Cross(vert.Position - Root.Position, Vector3.Up); And second, Vector3.Transform will rotate around the origin. To rotate around the heightmap center, you need to subtract Root.Position, transform, and add Root.Position back. Third, you should only rotate PI/4 radians at the farthest points. – khayman218 Dec 19 '11 at 17:40

Hmm, I'm not so sure about rotating the vertices. Perhaps this is not the answer you're looking for, but I can suggest an alternate method.

I've done something similar with maps in my game. I wrote a shader to wrap terrain into a sphere, but it can easily be done outside the graphics card too. It's as simple as mapping the Cartesian coordinates to spherical coordinates. The code would look something like:

public static Vector3f MapToSphere(Vector3f coords, WorldMap MAP) {
float pi = 3.14159265f;
float thetaDelta = ((2 * pi) / (MAP.XSize - 1));
float phiDelta = ((pi) / (MAP.ZSize - .5f));
float RadiusBase = ((MAP.XSize) / pi / 2f);
float theta = (coords.z * thetaDelta);
float phi = (coords.x * phiDelta);

//Limit the map to half a sphere
if(theta > pi) {theta = theta - (pi);}

if(theta < 0.0)    {theta = theta + (pi);}

if (phi > 2*pi) {phi = phi - (2*pi);}

if (phi < 0.0) {phi = phi + (2*pi);}

Vector3f coords2 = new Vector3f();
coords2.x = (float) (((RadiusBase) * Math.sin(theta) * Math.cos(phi)) + MAP.XSize / 2f);
coords2.y = (float) ((RadiusBase) * Math.sin(theta) * Math.sin(phi));
coords2.z = (float) (((RadiusBase) * Math.cos(theta)) + MAP.ZSize / 2f);
return coords2;
}


This maybe "too spherical" for you. If so, you can try padding the edges of your map so that the portion turned into a sphere only represents a portion of the surface of the sphere.

Below is an example of the spherical mapping results.

A "flat" map:

And a spherical world, created by wrapping the vertices into a sphere:

Note that there will be a large amount of distortion at the poles if you don't follow the suggestion above to limit the surface area of the sphere this map is stretched over.