1
\$\begingroup\$

I'm trying to implement the Diamond Square Algorithm. In order to do this I'm following this tutorial: Diamond Square | Procedural Generation | Game Development Tutorial

I store the height values into a 2D array and then I create a .ppm image using these values. The algorithm seems to work, but when I open the .ppm image, the result is very bad. The image has a lot of diamond artefacts. The image below shows the result:

Artefact example

The source code that implements the algorithm is this:

#include "DSSequential/DiamondSquareSEQ.h"
#include "iostream"

DiamondSquareSEQ::DiamondSquareSEQ(int NSize, float minHeightValue,
    float maxHeightValue, float randomValue) : N(NSize), minHeightValue(minHeightValue),
maxHeightValue(maxHeightValue), randomMagnitude(randomValue)
{
    //Height map size computation 
    HeightMapSize = static_cast<int>(std::pow(2, N) + 1);
    HeightMap.reserve(HeightMapSize);

    //Filling of the height map 
    for(int i = 0; i < HeightMapSize; i++)
    {
        for (int j = 0; j < HeightMapSize; j++)
        {
            HeightMap.emplace_back(0.0f);
        }
    }
    chunkSize = HeightMapSize - 1;
    half = 0;
    //Four corner value computation
    HeightMap[0] = randGen.GenerateFloatInARange(minHeightValue, maxHeightValue);
    HeightMap[0 * HeightMapSize + chunkSize] = randGen.GenerateFloatInARange(minHeightValue, maxHeightValue);
    HeightMap[chunkSize * HeightMapSize + 0] = randGen.GenerateFloatInARange(minHeightValue, maxHeightValue);
    HeightMap[chunkSize * HeightMapSize + chunkSize] = randGen.GenerateFloatInARange(minHeightValue, maxHeightValue);
    RunDiamondSquare();
}

void DiamondSquareSEQ::PrintMap()
{
    for (int i = 0; i < HeightMapSize; i++)
    {
        for (int j = 0; j < HeightMapSize; j++)
        {
            if (HeightMap[i * HeightMapSize + j] != 0.0f)
            {
                std::cout << HeightMap[i * HeightMapSize + j] << " ";
                continue;
            }
            std::cout << "0" << " ";
        }
        std::cout << "\n";
    }
}

std::vector<float> DiamondSquareSEQ::GetHeightMapData()
{
    return HeightMap;
}

void DiamondSquareSEQ::RunDiamondSquare()
{
    while (chunkSize > 1)
    {
        half = chunkSize / 2;
        DiamondStep();
        SquareStep();
        chunkSize /= 2;
        randomMagnitude/= 2;
    }
}

void DiamondSquareSEQ::DiamondStep()
{
    for(int i = 0; i < HeightMapSize - 1; i += chunkSize)
    {
        for(int j = 0; j < HeightMapSize - 1; j += chunkSize)
        {
            float value = 0.0f;
            const float randValue = randGen.GenerateFloat() * randomMagnitude;

            //Average computation
            value += HeightMap[i * HeightMapSize + j];
            value += HeightMap[i * HeightMapSize + (j + chunkSize)];
            value += HeightMap[(i + chunkSize) * HeightMapSize + j];
            value += HeightMap[(i + chunkSize) * HeightMapSize + (j + chunkSize)];
            value /= 4;

            value += randValue;

            HeightMap[(i + half) * HeightMapSize + (j + half)] = value;
        }
    }
}

void DiamondSquareSEQ::SquareStep()
{
    for (int i = 0; i < HeightMapSize; i += half)
    {
        for (int j = (i +half) % chunkSize; j < HeightMapSize; j += chunkSize)
        {
            float value = 0.0f;
            int count = 0;
            const float randValue = randGen.GenerateFloat() * randomMagnitude;
            int index = (i - half) * HeightMapSize + j;
            if(index >= 0)
            {
                value += HeightMap[index];
                count++;
            }

            index = i * HeightMapSize + (j - half);
            if (index >= 0)
            {
                value += HeightMap[index];
                count++;
            }

            index = half * HeightMapSize + (j + half);
            if (index < static_cast<int>(HeightMap.size()))
            {
                value += HeightMap[index];
                count++;
            }

            index = (i + half) * HeightMapSize + j;
            if (index < static_cast<int>(HeightMap.size()))
            {
                value += HeightMap[index];
                count++;
            }

            value /= count;
            value += randValue;
            HeightMap[i * HeightMapSize + j] = value;
        }
    }
}

How can I fix this?

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

I have solved the diamonds artefacts issue. I post the solution for the future. The error was in this piece of code:

index = half * HeightMapSize + (j + half);
if (index < static_cast<int>(HeightMap.size()))
{
   value += HeightMap[index];
   count++;
}

now the correct version is this:

index = i * HeightMapSize + (j + half);
if (index < static_cast<int>(HeightMap.size()))
{
  value += HeightMap[index];
  count++;
}

In the previous version the index var was: index = half * HeightMapSize + (j + half); now is index = i * HeightMapSize + (j + half);. This caused the diamonds artefacts. Now the result looks better!

Corrected noise

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .