# How can I generate floating land masses for a Minecraft-like engine?

I am creating a Minecraft-like engine in XNA. What I want to do is create floating islands similar to the one shown in this video:

How would I replicate this using a world generator? Would I have to use some Perlin noise algorithm? I don't know how that would help me make land masses like that.

Here is the code for the perlin noise generator that I am using:

    private double[,] noiseValues;
private float amplitude = 1;    // Max amplitude of the function
private int frequency = 1;      // Frequency of the function

/// <summary>
/// Constructor
/// </summary>
///
public PerlinNoise(int freq, float _amp)
{
Random rand = new Random(System.Environment.TickCount);
noiseValues = new double[freq, freq];
amplitude = _amp;
frequency = freq;

// Generate our noise values
for (int i = 0; i < freq; i++)
{
for (int k = 0; k < freq; k++)
{
noiseValues[i, k] = rand.NextDouble();
}
}
}

/// <summary>
/// Get the interpolated point from the noise graph using cosine interpolation
/// </summary>
/// <returns></returns>
public double getInterpolatedPoint(int _xa, int _xb, int _ya, int _yb, double x, double y)
{
double i1 = interpolate(
noiseValues[_xa % Frequency, _ya % frequency],
noiseValues[_xb % Frequency, _ya % frequency]
, x);

double i2 = interpolate(
noiseValues[_xa % Frequency, _yb % frequency],
noiseValues[_xb % Frequency, _yb % frequency]
, x);

return interpolate(i1, i2, y);
}

public static double[,] SumNoiseFunctions(int width, int height, List<PerlinNoise> noiseFunctions)
{
double[,] summedValues = new double[width, height];

// Sum each of the noise functions
for (int i = 0; i < noiseFunctions.Count; i++)
{
double x_step = (float)width / (float)noiseFunctions[i].Frequency;
double y_step = (float)height / (float)noiseFunctions[i].Frequency;

for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
int a = (int)(x / x_step);
int b = a + 1;
int c = (int)(y / y_step);
int d = c + 1;

double intpl_val = noiseFunctions[i].getInterpolatedPoint(a, b, c, d, (x / x_step) - a, (y / y_step) - c);
summedValues[x, y] += intpl_val * noiseFunctions[i].Amplitude;
}
}
}
return summedValues;
}

/// <summary>
/// Get the interpolated point from the noise graph using cosine interpolation
/// </summary>
/// <returns></returns>
private double interpolate(double a, double b, double x)
{
double ft = x * Math.PI;
double f = (1 - Math.Cos(ft)) * .5;

// Returns a Y value between 0 and 1
return a * (1 - f) + b * f;
}

public float Amplitude { get { return amplitude; } }
public int Frequency { get { return frequency; } }


But the thing is the author of the code uses the following to generate noise, and I don't understand it in the least.

    private Block[, ,] GenerateLandmass()
{
Block[, ,] blocks = new Block[300, 400, 300];

List<PerlinNoise> perlins = new List<PerlinNoise>();

double[,] noisemap = PerlinNoise.SumNoiseFunctions(300, 300, perlins);

int centrey = 400 / 2;

for (short x = 0; x < blocks.GetLength(0); x++)
{
for (short y = 0; y < blocks.GetLength(1); y++)
{
for (short z = 0; z < blocks.GetLength(2); z++)
{
blocks[x, y, z] = new Block(BlockType.none);
}
}
}

for (short x = 0; x < blocks.GetLength(0); x++)
{
for (short z = 0; z < blocks.GetLength(2); z++)
{
blocks[x, centrey - (int)noisemap[x, z], z].BlockType = BlockType.stone;
}
}

//blocks = GrowLandmass(blocks);

return blocks;
}


And here is the site I am using: http://lotsacode.wordpress.com/2010/02/24/perlin-noise-in-c/.

And I am trying to implement perlin noise in the way specified by Martin Sojka.

Ok, so this is what I have got so far:

For the base land, make two 2D continuous noise fields (Perlin, Simplex, Wavelet, a combination thereof - whatever works for you), one with mostly low frequency. low amplitude parts for the upper limit of the land, the other with both high frequency, high amplitude parts and low frequency, high amplitude for the lower limit of the land. Where the lower limit is above higher limit, don't include any land voxels (or whatever your game will be using to represent the terrain). The end result looks roughly like this ...

• But this is for 2D is it not? – Darestium Dec 20 '11 at 23:45
• But I quite like it :) – Darestium Dec 21 '11 at 0:10
• 2D / 3D - same thing – Gavin Williams Dec 21 '11 at 3:21
• OK, ill attempt to implement it tommorow... Wish me luck ;) – Darestium Dec 21 '11 at 3:56
• @Darestium: It's a 2D example for easier visualisation. The same method works for any number of (algebraic) dimensions higher than one. – Martin Sojka Dec 21 '11 at 7:38

Would something like this be enough?

In order to get more interesting noise multiple octaves of simplex noise can be added together. [...] Since I want to get a roughly spherical floating rock of sorts, I need to multiply the noise with its distance from the center. [...] I also want the rock to be flatter on the top than on the bottom, hence a second multiplication factor is a gradient in y direction. Combining these together and stretching y for noise while compressing x and z a bit, we get something like a floating rock. [...] Excavating caves with another instance of noise offset a little also makes it more interesting.

• So basically you will start with a data set generated from simplex or perlin noise (or rather multiple octaves of noise added together).
• Then shape it into something closer to a floating landmass by making it more spherical (by multiplying the noise by its distance from the center).
• And create ground by making it flatter near the top (by multiplying it by a vertical gradient i.e. starting with low values at the top and getting higher towards the bottom).
• Combine these three and adjust the shape by scaling the noise along the X/Y/Z axes (the article suggests stretching on the Y axis and compressing on the X and Z axes).
• An additional pass of noise may be used to excavate caves.
• Yes, I think something like this is defiantly what I want. The thing is that I have little experience with perlin noise so the only thing I can generate is really basic mountains and would not have any ideas about how to add "multiple octaves of noise togther). For the perlin noise generation I am using the code that I got off stackoverflow.com/questions/4753055/… and ported it to C#. Ill add my version in the original post... Would you be willing to give me an example of how I would achieve such a land mass with that code? – Darestium Dec 21 '11 at 0:06
• That's why I linked the article. It has an explanation of all the steps, and source code at the end. You should try to study that. – David Gouveia Dec 21 '11 at 0:09
1. Using your existing 3D grid, decide on the height at which you want island tops to be. Create a set of islands in that 2D plane (lets call it the XY plane) by scattering points through the plane, then placing cubes at those points. Use cohesion to pull them closer together in clumps. Fill in any holes and you have a set of island-tops.
2. Use a CA-similar method to grow the islands downwards. (a) Starting at the Z level where you plotted your initial points, for each cell in that current Z level, determine the chance to extend down to the next lower level given the number of neighbours in the XY plane, from 0 to 8 (diagonal neighbors are included), e.g. assign a 10% chance for each neighbour, up to max 80% chance. Calculate this for each cell in the starting plane. (b) Then randomise against this chance and extend downward if you are within the percentage range. Rinse, repeat step 2 (go to next level, determine neighbours for each voxel, extend downwards for that voxel) until no more extensions occur. Your downwards extension should form a cone due to the number-of-neighbours approach, because those voxels towards the XY-centre of the island will typically have more neighbours.

Pseudocode for step 2:

int planeNeighbours[x][y]; //stores how many neighbours each voxel in this plane has

for each z level (starting at level where you plotted your points)
for each x, y voxel in z level
for each neighbour space bordering this voxel
if neighbour exists
++planeNeighbours[x][y];
for each x, y voxel in z level
chance = random(0,8); //depends on your RNG implementation
if chance < planeNeighbours[x][y]
worldGrid[x][y][z+1] = new cube


Once your islands are done generating, you can optionally shift them up and down in space to have them at different heights.

• OK, I had a crack at your method and it seems to be growing the terrain outward instead of inward. I'll post the code... – Darestium Dec 21 '11 at 1:08