Home About Recent Martial Responsibility For Safety The Buffalo Trap Longsword Solo Drills - Meÿer Square Starting Historical European Martial Arts Group Historical European Martial Arts - Equipment Game development Generic A* for Games Procedural Island Generation Data-Oriented Design Matters Misconceptions of Component-Based Entity Systems Level of Detail Experiments Planet Generation - Part II Planet Generation - Part I Procedural Generation in Games Oculus Rift Integration Android Favorite Android Games NDK with Android Studio Android NDK Programming - Part III Android NDK Programming - Part II Android NDK Programming - Part I Personal Personal Stuff: Running! Global Game Jam 2014 Experiences Anime Claymore The Twelve Kingdoms Games Favorite Android Games Dungeons & dragons D&D Journal: I Historical european martial arts Martial Responsibility For Safety The Buffalo Trap Longsword Solo Drills - Meÿer Square Starting Historical European Martial Arts Group Historical European Martial Arts - Equipment Longsword Martial Responsibility For Safety The Buffalo Trap Longsword Solo Drills - Meÿer Square

I have always been a fan of procedural content generation; it allows you to create ever changing games with potentially endless content. It also compensates for my lack of artistic talent.

Procedural landscape generation is useful for many games, from Skirmish mode in strategy games to a dungeon in a Roguelike. At this time I am going to explore how to generate planets.

Planet Rendering

Doing planar and voxel terrain generation in the past made me familiar with quite a few rendering generation algorithms but I have never made a planet before and I decided it is time to change that fact.

The plan

Planets in the real world contain a lot of information. The surface area of the earth is about 510 million square kilometers, almost two third of it is water and one third land. This is a lot of terrain data that you might want to generate.

Across the land we have rivers, lakes and different types of biome, representing deserts, jungles, tundra and more. The biome information can tell you what type of animals live at different areas.

There is also the matter of lighting. Our light comes from the sun which could be thought of as a simple directional light, but in fact the light breaks in the atmosphere and the light particles called photons bounce off particles in the Earth's atmosphere and reflect more blue and yellow colors. This is called Atmospheric Scattering.

For this chapter I will start by making the simple geometry for the basis of the planet. At later posts I will add more detail including height data, lighting, atmospheric scattering and level of detail which will allow the amount of data the planet contains to increase dramatically.

Geometry

The first thing I did was to create a sphere with simple longitude latitude algorithm:

Sphere wireframe 10deg 6r.svg

The problem with this method is that the vertices converge towards the poles, leading to non-uniform distribution of the vertices and causing visual distortions, especially when trying to add textures.

So I looked for a different algorithm and found a few useful ones including Geodesic and Cube Mapping.

Geodesic grids seems to offer really good results, keeping the grid uniform and without distortions while delivering a good spherical shape.

Geodesic grids can be created by subdividing an icosahedron, adding additional triangles and pushing them toward the sphere's radius. Enough tessellation will create a smooth spherical shape with a uniform grid that has no distortion.

IcosaSplit5

For simplicity and speed I decided to go with a Cube Mapping algorithm. Following a formula I found online by Philip Nowell I could easily collapse a cube grid into a sphere using just a few lines of code:

// For every vertex in the mesh
// Where vertices form 6 grids making a cube
// With bounds of [-1, -1, -1] to [1, 1, 1]
void MapCubeToSphere( Vector3& vPosition )
{
    float x2 = vPosition.x * vPosition.x;
    float y2 = vPosition.y * vPosition.y;
    float z2 = vPosition.z * vPosition.z;

    vPosition.x = vPosition.x * sqrt( 1.0f - ( y2 * 0.5f ) - ( z2 * 0.5f ) + ( (y2 * z2) / 3.0f ) );
    vPosition.y = vPosition.y * sqrt( 1.0f - ( z2 * 0.5f ) - ( x2 * 0.5f ) + ( (z2 * x2) / 3.0f ) );
    vPosition.z = vPosition.z * sqrt( 1.0f - ( x2 * 0.5f ) - ( y2 * 0.5f ) + ( (x2 * y2) / 3.0f ) );
}

After creating a grid for each face of the cube and applying the code above for every vertex, the cube collapses into a sphere as shown in the following image:

This sample code shows creating one face of the cube grid and collapsing it into the sphere:

// Declared Variables
// width         - number of vertices across the x axis
// height        - number of vertices across the y axis
// radius        - sphere's radius
// pVertexBuffer - vertex buffer array

// Grid facing negative z
Vector3 vMinPosition( -1.0f, -1.0f, -1.0f );

for ( int y = 0; y < height; ++y )
{
    for ( int x = 0; x < width; ++x )
    {
        Vector3 vPosition = vMinPosition;
        vPosition.x += (float)x / (float)(width-1) * 2.0f; // Multiply by 2.0f to map position from -1 to +1
        vPosition.y +- (float)y / (float)(height-1) * 2.0f; // Multiply by 2.0f to map position from -1 to +1

        // Map the grid position into a sphere position
        MapCubeToSphere( vPosition );

        // The normal is just the vector from the center of the sphere.
        Vector3 vNormal = vPosition.Normal();

        // Extrude the sphere by the radius
        vPosition *= radius;

        // Assign to vertex buffer
        pVertexBuffer[ y * width + x ].Position = vPosition;
        pVertexBuffer[ y * width + x ].Normal = vNormal;
    }
}

Cube Mapping Advantages

There are some advantages I am hoping to use with cube mapping:

  1. The grid is uniform and similar to a planar grid terrain, making it easy to handle.
  2. Treating the terrain as a grid allows one to render each face with level of detail algorithms such as Chunked LOD and Geometry Clipmaps.
  3. It allows use of cube mapping for texture mapping, possibly increasing performance.

More on the advantages in future posts.

Next

The next stage was to add additional detail to the planet, as currently it is just a simple sphere. In planar grids it is common to create a heightmap to displace the vertices Y coordinate.

Height maps require additional work before they can be applied on a sphere so that the map will wrap around nicely between the different faces.

In the next post I will detail how I generate the height map and some techniques to improve the detail.

The next post is now up! Find it here.

Back
Home About Recent Martial Responsibility For Safety The Buffalo Trap Longsword Solo Drills - Meÿer Square Starting Historical European Martial Arts Group Historical European Martial Arts - Equipment Game development Generic A* for Games Procedural Island Generation Data-Oriented Design Matters Misconceptions of Component-Based Entity Systems Level of Detail Experiments Planet Generation - Part II Planet Generation - Part I Procedural Generation in Games Oculus Rift Integration Android Favorite Android Games NDK with Android Studio Android NDK Programming - Part III Android NDK Programming - Part II Android NDK Programming - Part I Personal Personal Stuff: Running! Global Game Jam 2014 Experiences Anime Claymore The Twelve Kingdoms Games Favorite Android Games Dungeons & dragons D&D Journal: I Historical european martial arts Martial Responsibility For Safety The Buffalo Trap Longsword Solo Drills - Meÿer Square Starting Historical European Martial Arts Group Historical European Martial Arts - Equipment Longsword Martial Responsibility For Safety The Buffalo Trap Longsword Solo Drills - Meÿer Square