Eu implementei um algoritmo de diamante quadrado de acordo com este artigo: http://www.lighthouse3d.com/opengl/terrain/index.php?mpd2
O problema é que eu tenho esses penhascos íngremes por todo o mapa. Isso acontece nas bordas, quando o terreno é subdividido recursivamente:
Aqui está a fonte:
void DiamondSquare(unsigned x1,unsigned y1,unsigned x2,unsigned y2,float range)
{
int c1 = (int)x2 - (int)x1;
int c2 = (int)y2 - (int)y1;
unsigned hx = (x2 - x1)/2;
unsigned hy = (y2 - y1)/2;
if((c1 <= 1) || (c2 <= 1))
return;
// Diamond stage
float a = m_heightmap[x1][y1];
float b = m_heightmap[x2][y1];
float c = m_heightmap[x1][y2];
float d = m_heightmap[x2][y2];
float e = (a+b+c+d) / 4 + GetRnd() * range;
m_heightmap[x1 + hx][y1 + hy] = e;
// Square stage
float f = (a + c + e + e) / 4 + GetRnd() * range;
m_heightmap[x1][y1+hy] = f;
float g = (a + b + e + e) / 4 + GetRnd() * range;
m_heightmap[x1+hx][y1] = g;
float h = (b + d + e + e) / 4 + GetRnd() * range;
m_heightmap[x2][y1+hy] = h;
float i = (c + d + e + e) / 4 + GetRnd() * range;
m_heightmap[x1+hx][y2] = i;
DiamondSquare(x1, y1, x1+hx, y1+hy, range / 2.0); // Upper left
DiamondSquare(x1+hx, y1, x2, y1+hy, range / 2.0); // Upper right
DiamondSquare(x1, y1+hy, x1+hx, y2, range / 2.0); // Lower left
DiamondSquare(x1+hx, y1+hy, x2, y2, range / 2.0); // Lower right
}
Parâmetros: (x1, y1), (x2, y2) - coordenadas que definem uma região em um mapa de altura (padrão (0,0) (128,128)). gama - basicamente max. altura. (padrão 32)
A ajuda seria muito apreciada.
Respostas:
Em cada nível de subdivisão, a etapa "quadrada" depende dos resultados da "etapa de diamante". Mas isso também leva em consideração o passo do diamante produzido na célula adjacente, que você não está respondendo. Eu reescreveria a função DiamondSquare para iterar a largura primeiro, em vez da profundidade primeiro, como você a possui atualmente.
Seu primeiro problema é que, como você recalcula as arestas quadradas duas vezes, ele ignora a contribuição do ponto central adjacente. Por exemplo, no artigo que você faz referência,
mas seu código efetivamente
isto é , leva em consideração o ponto central atual duas vezes, não o ponto central correspondente. É por isso que você precisa ir em primeiro lugar, para que você tenha os pontos centrais anteriores calculados.
Aqui está o meu código e a saída:.
fonte
Uma possibilidade é que você esteja usando um atalho com sua implementação que o algoritmo da sua página vinculada não possui.
Para o estágio quadrado, você está calculando a altura dos pontos com
que o algoritmo da página indica para usar se você estiver agrupando seu mapa. Isso mostra que você está usando o valor da altura do "próximo quadrado sobre" para calcular esse. No primeiro caso mais simples, o ponto central (com altura 'e') é usado nos lados esquerdo e direito para calcular f.
No entanto, o algoritmo que você faz referência usa os valores reais dos outros quadrados / diamantes para ajudá-lo a calcular o valor da altura desse ponto quadrado. Em seu algoritmo, o segundo ponto de nível é calculado com a seguinte fórmula:
Percebe a falta de duplicação de um valor lá?
Eu acho que você pode querer tentar usar as versões não empacotáveis das fórmulas fornecidas, essas serão melhores, eu acho.
fonte