Jump to content

  • Log In with Google      Sign In   
  • Create Account


#ActualRiztro

Posted 28 December 2012 - 05:37 PM


Thankyou very much for this! I like the randomness and I love the code but do you know if there is any way to make it less "holey". There are specks of water all over the terrain and what I am going for is more of a solid island surrounded by water


You're probably better off writing your own noise function if you want that amount of control. The problem is both with the perlin noise and the island mask. Some fixes that make it a bit better:
//Little program to generate test map with only 0 and 1 tile#include #include #include "noiseutils.h"#include #include #include #define MAP_SIZE 512using namespace std;using namespace noise;template  string tostring (T v) {    ostringstream ss;    ss << v;    return ss.str();}void generate_island(int iseed) {    module::Perlin myModule;    myModule.SetSeed (iseed);    utils::NoiseMap heightMap;    utils::NoiseMapBuilderPlane heightMapBuilder;    heightMapBuilder.SetSourceModule(myModule);    heightMapBuilder.SetDestNoiseMap(heightMap);    heightMapBuilder.SetDestSize(MAP_SIZE, MAP_SIZE);    heightMapBuilder.SetBounds(2.0, 6.0, 1.0, 5.0);    heightMapBuilder.Build();    float islandMap[MAP_SIZE][MAP_SIZE];    srand(iseed);    for (int count = 0; count < 1; count++ ){        //Initialize values for a new map        for (int i = 0; i < MAP_SIZE; i++) {            for (int j = 0; j < MAP_SIZE; j++) {                islandMap[j][i] = 0;            }        }        //Choose a random location, travel in random directions        int x = 0, y = 0;        int sx = 0, sy = 0;        int size = MAP_SIZE / 2;        int distance = 0;        for (int i = 0; i < 1000000; i++) {            int dx = x - sx;            int dy = y - sy;            distance = dx * dx + dy * dy;            if((y > MAP_SIZE - 1) || y < 0 || (x > MAP_SIZE - 1) || x < 0 || distance > 5000) {                x = rand() % size / 2 + rand() % size / 2 + MAP_SIZE / 2 - size / 2;                y = rand() % size / 2 + rand() % size / 2 + MAP_SIZE / 2 - size / 2;                sx = x;                sy = y;            }            ++islandMap[x][y];            switch(rand() % 4) {                case 0:                    ++x;                    break;                case 1:                    --y;                    break;                case 2:                    --x;                    break;                case 3:                    ++y;                    break;                default:                    break;            }        }        //find max value for normalizing        for (int i = 0; i < MAP_SIZE; i++) {            for (int j = 0; j < MAP_SIZE; j++) {                islandMap[i][j] = islandMap[i][j] * 2 - 1;            }        }        int max = 0;        int min = 0;        for (int i = 0; i < MAP_SIZE; i++) {            for (int j = 0; j < MAP_SIZE; j++) {                if(max < islandMap[i][j]) {                    max = islandMap[i][j];                }                if(min > islandMap[i][j]) {                    min = islandMap[i][j];                }            }        }        //Multiply values of original by new maps generated        for (int i = 0; i < MAP_SIZE; i++) {            for (int j = 0; j < MAP_SIZE; j++) {                float islandValue = (islandMap[i][j] - min) / (max - min);                float mapValue = (heightMap.GetValue(i, j) + 1) / 2;                float newValue = 2 * islandValue * mapValue - 1;                heightMap.SetValue(i, j, newValue);            }        }    }    utils::RendererImage renderer;    utils::Image image;    renderer.SetSourceNoiseMap (heightMap);    renderer.SetDestImage (image);    renderer.ClearGradient ();    renderer.AddGradientPoint (-1.0000, utils::Color (  0,   0, 255, 255)); // shallow    renderer.AddGradientPoint (-0.9701, utils::Color (  0,   0, 255, 255)); // shallow    renderer.AddGradientPoint (-0.9700, utils::Color (  0, 128, 255, 255)); // shore    renderer.AddGradientPoint (-0.9690, utils::Color (  0, 128, 255, 255)); // shore    renderer.AddGradientPoint (-0.9689, utils::Color (240, 240,  64, 255)); // sand    renderer.AddGradientPoint (-0.9601, utils::Color (240, 240,  64, 255)); // sand    renderer.AddGradientPoint (-0.9600, utils::Color ( 32, 160,   0, 255)); // grass    renderer.AddGradientPoint (-0.4991, utils::Color ( 32, 160,   0, 255)); // grass    renderer.AddGradientPoint (-0.4990, utils::Color ( 0, 0,   0, 255)); // pines    renderer.AddGradientPoint (-0.4987, utils::Color ( 0, 0,   0, 255)); // pines    renderer.AddGradientPoint (-0.3986, utils::Color (96, 63,   0, 255)); // dirt    renderer.AddGradientPoint ( 0.0000, utils::Color (96, 63,   0, 255)); // dirt    renderer.AddGradientPoint ( 0.0001, utils::Color (128, 128, 128, 255)); // rock    renderer.AddGradientPoint ( 1.0000, utils::Color (128, 128, 128, 255)); // rock    renderer.EnableLight ();    renderer.SetLightContrast (3.0);    renderer.SetLightBrightness (2.0);    renderer.Render ();    utils::WriterBMP writer;    writer.SetSourceImage (image);    writer.SetDestFilename ("tutorial" + tostring(iseed) + ".bmp");    writer.WriteDestFile ();}int main() {    for(int i=0; i<10; ++i){        generate_island(i);    }    return 0;}.h>
The island mask consists of many random walks added together. The random walks scale poorly with size of the map (change the MAP_SIZE to see for yourself) because they tend to diverge very quickly. With the above code I've applied two methods two remedy this a bit:
  • Terminate any random walk if they get beyond a certain distance away from their origin.
     
  • Make the starting point of any random walk more likely to be in the middle with a triangular distribution and within a smaller region (controlled with the 'size' variable).
Play a bit with the numbers to see if you can improve the results.

If you want to try something else try this instead: http://en.wikipedia.org/wiki/Diamond-square_algorithm If you set the first N levels yourself instead of randomly generating them you get much more control over the final output.

Here are my results when I put it in my engine! Looks good! biggrin.png Thanks a ton!!! biggrin.png


#1Riztro

Posted 28 December 2012 - 05:36 PM

Thankyou very much for this! I like the randomness and I love the code but do you know if there is any way to make it less "holey". There are specks of water all over the terrain and what I am going for is more of a solid island surrounded by water

 

 

You're probably better off writing your own noise function if you want that amount of control. The problem is both with the perlin noise and the island mask. Some fixes that make it a bit better:

//Little program to generate test map with only 0 and 1 tile

#include <iostream>
#include <noise/noise.h>
#include "noiseutils.h"
#include <stdlib.h>
#include <string>
#include <sstream>

#define MAP_SIZE 512

using namespace std;
using namespace noise;

template <typename T> string tostring (T v) {
    ostringstream ss;
    ss << v;
    return ss.str();
}

void generate_island(int iseed) {
    module::Perlin myModule;

    myModule.SetSeed (iseed);
    utils::NoiseMap heightMap;
    utils::NoiseMapBuilderPlane heightMapBuilder;
    heightMapBuilder.SetSourceModule(myModule);
    heightMapBuilder.SetDestNoiseMap(heightMap);
    heightMapBuilder.SetDestSize(MAP_SIZE, MAP_SIZE);
    heightMapBuilder.SetBounds(2.0, 6.0, 1.0, 5.0);
    heightMapBuilder.Build();

    float islandMap[MAP_SIZE][MAP_SIZE];
    srand(iseed);

    for (int count = 0; count < 1; count++ ){
        //Initialize values for a new map
        for (int i = 0; i < MAP_SIZE; i++) {
            for (int j = 0; j < MAP_SIZE; j++) {
                islandMap[j][i] = 0;
            }
        }

        //Choose a random location, travel in random directions
        int x = 0, y = 0;
        int sx = 0, sy = 0;
        int size = MAP_SIZE / 2;
        int distance = 0;

        for (int i = 0; i < 1000000; i++) {
            int dx = x - sx;
            int dy = y - sy;
            distance = dx * dx + dy * dy;
            if((y > MAP_SIZE - 1) || y < 0 || (x > MAP_SIZE - 1) || x < 0 || distance > 5000) {
                x = rand() % size / 2 + rand() % size / 2 + MAP_SIZE / 2 - size / 2;
                y = rand() % size / 2 + rand() % size / 2 + MAP_SIZE / 2 - size / 2;
                sx = x;
                sy = y;
            }

            ++islandMap[x][y];

            switch(rand() % 4) {
                case 0:
                    ++x;
                    break;
                case 1:
                    --y;
                    break;
                case 2:
                    --x;
                    break;
                case 3:
                    ++y;
                    break;
                default:
                    break;
            }
        }

        //find max value for normalizing
        for (int i = 0; i < MAP_SIZE; i++) {
            for (int j = 0; j < MAP_SIZE; j++) {
                islandMap[i][j] = islandMap[i][j] * 2 - 1;
            }
        }

        int max = 0;
        int min = 0;
        for (int i = 0; i < MAP_SIZE; i++) {
            for (int j = 0; j < MAP_SIZE; j++) {
                if(max < islandMap[i][j]) {
                    max = islandMap[i][j];
                }

                if(min > islandMap[i][j]) {
                    min = islandMap[i][j];
                }
            }
        }

        //Multiply values of original by new maps generated
        for (int i = 0; i < MAP_SIZE; i++) {
            for (int j = 0; j < MAP_SIZE; j++) {
                float islandValue = (islandMap[i][j] - min) / (max - min);
                float mapValue = (heightMap.GetValue(i, j) + 1) / 2;
                float newValue = 2 * islandValue * mapValue - 1;
                heightMap.SetValue(i, j, newValue);
            }
        }
    }

    utils::RendererImage renderer;
    utils::Image image;
    renderer.SetSourceNoiseMap (heightMap);
    renderer.SetDestImage (image);
    renderer.ClearGradient ();
    renderer.AddGradientPoint (-1.0000, utils::Color (  0,   0, 255, 255)); // shallow
    renderer.AddGradientPoint (-0.9701, utils::Color (  0,   0, 255, 255)); // shallow
    renderer.AddGradientPoint (-0.9700, utils::Color (  0, 128, 255, 255)); // shore
    renderer.AddGradientPoint (-0.9690, utils::Color (  0, 128, 255, 255)); // shore
    renderer.AddGradientPoint (-0.9689, utils::Color (240, 240,  64, 255)); // sand
    renderer.AddGradientPoint (-0.9601, utils::Color (240, 240,  64, 255)); // sand
    renderer.AddGradientPoint (-0.9600, utils::Color ( 32, 160,   0, 255)); // grass
    renderer.AddGradientPoint (-0.4991, utils::Color ( 32, 160,   0, 255)); // grass
    renderer.AddGradientPoint (-0.4990, utils::Color ( 0, 0,   0, 255)); // pines
    renderer.AddGradientPoint (-0.4987, utils::Color ( 0, 0,   0, 255)); // pines
    renderer.AddGradientPoint (-0.3986, utils::Color (96, 63,   0, 255)); // dirt
    renderer.AddGradientPoint ( 0.0000, utils::Color (96, 63,   0, 255)); // dirt
    renderer.AddGradientPoint ( 0.0001, utils::Color (128, 128, 128, 255)); // rock
    renderer.AddGradientPoint ( 1.0000, utils::Color (128, 128, 128, 255)); // rock
    renderer.EnableLight ();
    renderer.SetLightContrast (3.0);
    renderer.SetLightBrightness (2.0);
    renderer.Render ();

    utils::WriterBMP writer;
    writer.SetSourceImage (image);
    writer.SetDestFilename ("tutorial" + tostring(iseed) + ".bmp");
    writer.WriteDestFile ();
}

int main() {
    for(int i=0; i<10; ++i){
        generate_island(i);
    }
    return 0;
}

The island mask consists of many random walks added together. The random walks scale poorly with size of the map (change the MAP_SIZE to see for yourself) because they tend to diverge very quickly. With the above code I've applied two methods two remedy this a bit:

  1. Terminate any random walk if they get beyond a certain distance away from their origin.
  2. Make the starting point of any random walk more likely to be in the middle with a triangular distribution and within a smaller region (controlled with the 'size' variable).

Play a bit with the numbers to see if you can improve the results.

 

If you want to try something else try this instead: http://en.wikipedia.org/wiki/Diamond-square_algorithm If you set the first N levels yourself instead of randomly generating them you get much more control over the final output.

Here are my results when I put it in my engine! Looks good! :D Thanks a ton!!! :D


PARTNERS