He implementado un algoritmo de diamante cuadrado de acuerdo con este artículo: http://www.lighthouse3d.com/opengl/terrain/index.php?mpd2
El problema es que consigo estos acantilados en todo el mapa. Ocurre en los bordes, cuando el terreno se subdivide recursivamente:
Aquí está la fuente:
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 definen una región en un mapa de altura (valor predeterminado (0,0) (128,128)). rango - básicamente máx. altura. (predeterminado 32)
La ayuda sería muy apreciada.
Respuestas:
En cada nivel de subdivisión, el paso "cuadrado" se basa en los resultados del "paso de diamante". Pero también tiene en cuenta el paso de diamante producido en la celda adyacente, que no tiene en cuenta. Reescribiría la función DiamondSquare para iterar Breadth-first, en lugar de profundidad-first como la tiene actualmente.
Su primer problema es que, dado que vuelve a calcular los bordes cuadrados dos veces, ignora la contribución del punto central adyacente. Por ejemplo, en el artículo al que hace referencia,
pero su código efectivamente lo hace
es decir, tiene en cuenta el punto central actual dos veces, no el punto central adyacente. Es por eso que debe ir primero en amplitud, de modo que tenga calculados los puntos centrales anteriores.
Aquí está mi código y la salida:.
fuente
Una posibilidad es que esté tomando un acceso directo con su implementación que el algoritmo en su página vinculada no.
Para la etapa cuadrada, está calculando la altura de los puntos con
que indica el algoritmo de la página para usar si está ajustando su mapa. Esto da la apariencia de que está utilizando el valor de altura del "siguiente cuadrado sobre" para calcular este. En el primer caso más simple, el punto central (con altura 'e') se usa en los lados izquierdo y derecho para calcular f.
Sin embargo, el algoritmo al que hace referencia le hace usar los valores reales de los otros cuadrados / diamantes para ayudarlo a calcular el valor de la altura de este punto cuadrado. En su algoritmo, el punto de segundo nivel se calcula con la siguiente fórmula:
¿Nota la falta de duplicación de un valor allí?
Creo que es posible que desee intentar usar las versiones no envolventes de las fórmulas dadas, creo que se repetirán mejor.
fuente