How would I go about implementing a globe-like “ballish” map?

I am new to 3D development and I have this idea of having the game world like our globe is - a ball. So, there would be no corners in the map and the game is top-down RTS game. I would like the camera to go on and on and never stop even though you are moving the camera to the same direction all the time.

I am not sure if this is even possible, but I would really like to build a globe-like map without borders. Can this be done, and how exactly? I am using XNA, C#, and DirectX. Any tutorials or links or help is greatly appreciated!

• everything is possible in a game... it's just the amount of time you want to invest. – Spooks Mar 18 '11 at 19:34
• Are you sure you want a globe? Going "up" 10 units, then "left" 10 units, "down" 10 units and "right" 10 units on a sphere will usually not land you at your starting point. However, doing so on a torus will. – sam hocevar Mar 18 '11 at 20:45
• @Sam: I think you are right. I would definitely use a torus instead of a globe if it solves that "problem". – rFactor Mar 18 '11 at 20:57
• You might want to take a look at Populous 3 game for a working example. There are globe worlds/maps there. Very neat :) – Kromster says support Monica Mar 19 '11 at 8:55

4 Answers

At the GGJ '11 in Berlin one team developed a game using a globus that was freely rotateable.

They made the game and the entire source available. It was made in C# and even XNA if I am not mistaken, so this might be a good reference for you.

Check it out here. The download link is beneath the group's picture.

Yes, it's very possible. I found though that making a true orbital camera was rather confusing. It was better to leave the Y (Up) axis locked and stop the camera at the poles. Otherwise it was easy to get disoriented. Google around for orbit cameras. Back when I was working on something like this, dhpoware's sample was useful. This old one might be useful too.

For the 3d Mesh, look into subdividing icosahedrons (sometimes called a geosphere). They give you a relatively uniform triangle size for texturing.

• A bit of clarification on the disorientation subject. Say that you are at the equator and scroll along it. You will end up on the other side of the world. You sense of UP will be north. BUT, if you are at the equator and scroll north, you will end up on the other side of the world and your UP will be south. In order to avoid this you can stop the camera at the poles (as Leniency says) or having the camera auto rotate so that UP always is north. In the latter case, battling around the poles will be difficult since the camera will always rotate to point up. – Gunslinger Mar 19 '11 at 7:33
• Interesting. However, I don't find that disorientation a problem. It actually does not matter where the north is in my game. It's just some map that you can view and play on. – rFactor Mar 19 '11 at 10:39

Whether you go with the torus option or not, you will need to do some wrap around, which will be the root of all the problems you will need to solve. However, they’ll be easier to address on a torus.

The idea is that your world is a grid that repeats itself along both the X and Y axes.

Position wrap around

When an object’s X or Y position goes over 1.0f (or whatever the world size is), it wraps around to 0.0f. Where you generally do computations such as:

position += velocity * time;


You add wrap around logic:

position += velocity * time;
if (position.x >= 1.0f) position.x -= 1.0f;
else if (position.x < 0.0f) position.x += 1.0f;
if (position.y >= 1.0f) position.y -= 1.0f;
else if (position.y < 0.0f) position.y += 1.0f;


Or, avoiding tests and securely handling the large velocity cases:

position += velocity * time;
position.x -= floorf(position.x);
position.y -= floorf(position.y);


Having 1.0f as the world size allows you to use floorf(), roundf() etc. immediately. Otherwise, you will need to use constructs such as WORLD_SIZE * floorf(value * (1.0f / WORLD_SIZE)) instead.

Distance computation

Computing distances changes, too. If you have two objects and one of them has position.x = 0.1f and the other has position.y = 0.9f then the distance is 0.2f, not 0.8f. So instead of the following distance function:

float distance(vec2 p1, vec2 p2)
{
vec2 d = p2 - p1;
return sqrtf(d.x * d.x + d.y * d.y);
}


You need to account for wrap around:

float distance(vec2 p1, vec2 p2)
{
vec2 d = p2 - p1;
d.x -= roundf(d.x);
d.y -= roundf(d.y);
return sqrtf(d.x * d.x + d.y * d.y);
}


Rendering

Rendering will be tricky, too. You have several possibilities:

• when the camera reaches 0.0f or 1.0f, render the necessary parts from the other side of the map translated by combinations of (1.0f, 0.0f) or (0.0f, 1.0f).
• always leave the camera at (0.5f, 0.5f) and move the whole world instead of the camera at each frame

These are fundamentally the same, but the way you see it will dictate your data structures. The best strategy here will probably depend on the culling mechanism you have.

Edit: sorry, I didn’t realise this was XNA. You will need to replace roundf and others with the equivalent Math.Round() etc.

Might I ask, do you really need a globe? Is your world small enough that the curvature would be visible? Why not approximate the globe with a bunch of rectangles? It will make your life easier, and presuming your world is large enough and if implemented well, can give the illusion of a fully connected world to boot.

Think of some games which have large open worlds, for the most part, they consist of "zones" where each "zone" borders other "zones." There is typically ocean surrounding groups of these "zones" which the player cannot manually cross, but the player is free to walk from zone to zone without restriction. For example, think of WoW's two continents and the dividing ocean.

• I think what I want is more like a torus as pointed by Sam in the comments. Yes, I would want that to happen, but I am afraid it is too complex to achieve. – rFactor Mar 18 '11 at 20:59