Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I smooth out my terrain generator?

I am experimenting with a new algorithm for random landscape generation. This method was my idea, so it may turn out to be impossible. In the meantime, I'm trying to smooth this thing out.

    public static void generate(){
    for(int x = -64; x <= 64; x++){
        for(int y = -64; y <= 64; y++){
            double val = 2d;
            for(int i = x - 4; i <= x + 4; i++){
                for(int j = y - 4; j <= y + 4; j++){
                    double w = Math.pow(hypotenuse(x, y, i, j), 1);
                    val += (1 * (random(i, j) / w));
                }
            }
            tileSet(x, y, val);
        }
    }
}

Before I explain this code, let me say that this is a 2D game, and so the heightmap is types of tiles instead of actual height. Water is lowest (0), then sand, grass, and tree (3). For testing, I am looping from -64 to 64 in both dimensions. For each tile, a value (starting with 2 or grass) is declared. Then we loop around this tile (-4 to 4 is an arbitrary amount, I have not been able to achieve significant differences in results by modifying this value, but 4 seems okay). Now, variable w stands for weight. The farther away each (i, j) point is from (x, y) the less weight the random value is given before it is added onto val. I have experimented with different exponents for w, and different multipliers for the next line (in the example both cases are 1); lower exponents and multipliers seem to widen the end result without necessarily smoothing, higher ones do the opposite and you get more trees closer to water with less grass and sand in between.

Here is the method random()

public static double random(int x, int y){
    Random random = new Random(seed * 17717171L + x * 22222223L + y * 111181111L);
    return random.nextGaussian() / 2d;
}

After those inner loops finished, the value of x, y is set.

Here's one run

too much roughness

Here's a multiplier of .5, meaning val += (.5 * (random(i, j) / w));

still too much roughness

As you can see, there is more sand and grass, significantly less trees (and water overall), but still just as many little bumps. It does not effectively change the scale therefore.

Thank you for your time!

like image 547
Joe Johnson Avatar asked Apr 03 '14 23:04

Joe Johnson


People also ask

How do you make parts into terrain on Roblox?

Yes There is, Use a Terrain Plugin so when you have a Part you only click on the plugin, select type of terrain and click on the part you will see how it turn a into the terrain.


1 Answers

What you're doing is known as inverse distance weighting. As the article points out, the key parameter is the exponent of the weight. So in your code, try

double w = Math.pow(hypotenuse(x, y, i, j), p);

taking p to be 0.25, 0.5, 1.0, 2.0, etc.

Also a slight variant on your algorithm that'd probably make reasoning about the algorithm easier: rather than generating a random value for each cell and adding to to neighbouring cells, start off by generating a random value at each cell corner, then use inverse distance weighting measured from the cell centres to calculate your cell values.

Using this scheme, the random values that contribute to a cell's value are all treated in a uniform manner, rather than one random value getting a weighting of 1 and the others getting inverse-distance weighted.

You might also be interested in gradient noise if you haven't encountered it already.

like image 84
Andy Jones Avatar answered Sep 22 '22 23:09

Andy Jones