Procedural Generated Worlds

Code revised. So, it takes less then a second compared to 5 seconds!!! I think it can be made faster.

Added diamond terrain generation with en.wikipedia.org/wiki/Diamond-square_algorithm

  1. Code need to be modified to use offset and offset, disable warping temporarily, divsion to scale density(maybe), and hash table for the random generation. (Have to be worked on since framework is made.)

  2. The new code you can use any amount of GeneratePerlinNoise and generateDiamondMethod using generateSelect as long as there is memory. (Have to be worked on since the framework is made.)

/// Cold to create noise through the Diamond method. Requires offset and better hash table to create random heightmaps but repeatable
bool Image::generateDiamondMethod1 (float * buffer,const int &width, const int &height, const float &maxYcoords,const float &minYcoords)
{
    //an initial seed value for the corners of the data
    float SEED = 0.4f;
    static const unsigned int DATA_SIZE=width+1;
    std::vector< std::vector<float> > diamond( DATA_SIZE, std::vector<float>(DATA_SIZE) );

    //initialise the values of the corners++
    diamond[0][0] = SEED;
    diamond[0][DATA_SIZE-1] = SEED;
    diamond[DATA_SIZE-1][0] = SEED;
    diamond[DATA_SIZE-1][DATA_SIZE-1] = SEED;

    float h =300; 	//the range (-h -> h) for the average offset
    srand(256);		//seed the random generator

    //side length is the distance of a single square side
    //or distance of diagonal in diamond
    //each iteration we are looking at smaller squares and diamonds, we decrease the variation of the offset
    for (int sideLength = DATA_SIZE-1; sideLength >= 2; sideLength /= 2, h /= 2.0)
    {

        int halfSide = sideLength/2;

        //generate new square values
        for(int x=0; x<DATA_SIZE-1; x+=sideLength)
        {
            for(int y=0; y<DATA_SIZE-1; y+=sideLength)
            {

                //x,y is upper left corner of the square
                //calculate average of existing corners
                float avg = diamond[x][y] + 				//top left
                            diamond[(x+sideLength)%DATA_SIZE][y]   +				//top right
                            diamond[x][ (y+sideLength)%DATA_SIZE]   + 				//lower left
                            diamond[(x+sideLength)%DATA_SIZE][(y+sideLength)%DATA_SIZE]; 	//lower right

                avg /= 4.0;

                //center is average plus random offset in the range (-h, h)
                float offset = (-h) + (float)rand() * (h - (-h))  / RAND_MAX;

                diamond[x+halfSide][y+halfSide] = avg + offset;

            } //for y
        } // for x

        //Generate the diamond values
        //Since diamonds are staggered, we only move x by half side
        //NOTE: if the data shouldn't wrap the x < DATA_SIZE and y < DATA_SIZE
        for (int x=0; x<DATA_SIZE-1; x+=halfSide)
        {
            for (int y=(x+halfSide)%sideLength; y<DATA_SIZE-1; y+=sideLength)
            {

                //x,y is center of diamond
                //we must use mod and add DATA_SIZE for subtraction
                //so that we can wrap around the array to find the corners

                float avg =
                    diamond[(x-halfSide+DATA_SIZE)%DATA_SIZE][y] +	//left of center
                    diamond[(x+halfSide)%DATA_SIZE][y]				+	//right of center
                    diamond[x][(y+halfSide)%DATA_SIZE]				+	//below center
                    diamond[x][(y-halfSide+DATA_SIZE)%DATA_SIZE];	//above center

                avg /= 4.0;

                //new value = average plus random offset
                //calc random value in the range (-h,+h)
                float offset = (-h) + (float)rand() * (h - (-h))  / RAND_MAX;

                avg = avg + offset;

                //update value for center of diamond
                diamond[x][y] = avg;

                //wrap values on the edges
                //remove this and adjust loop condition above
                //for non-wrapping values
                if (x == 0) diamond[DATA_SIZE-1][y] = avg;
                if (y == 0) diamond[x][DATA_SIZE-1] = avg;
            } //for y
        } //for x
    } //for sideLength


    /// Set maxY and minY to 0.0f
    float maxY = diamond[1][1];
    float minY = diamond[1][1];

    for (int x = 0; x<DATA_SIZE; x++)
    {
        for(int y = 0; y<DATA_SIZE; y++)
        {
            if ((float)diamond[x][y] > maxY)
            {
                maxY = diamond[x][y];
            }
            if ((float)diamond[x][y] < minY)
            {
                minY = diamond[x][y];
            }
        }
    }

    /// Calculate height from 0 to 1
    for(int x=0; x < DATA_SIZE; x++)
    {
        for(int y=0; y < DATA_SIZE; y++)
        {
            //change range to 0..1
            diamond[x][y] = (diamond[x][y] - minY) / (maxY - minY);
        }
    }

    /// Copy color float from create texture
    for(unsigned y = 0; y<width; y++)
    {
        for(unsigned x = 0; x<height; x++)
        {
            /// incremennt memory which seems to work
            int index = (y*width)+x;

            buffer[index]=diamond[x][y];
        }
    }

    return true;

As to textures, maybe someone has a idea of how to deal with textures for randomly generated terrain.

This is the latest code results. Once I get a smooth transistion function like (libnoise.sourceforge.net/tutoria … rial5.html) it will be added to the mix of things. The function is made but needs to be coded for floats and the algorithm currently used.