Я реализовал алгоритм алмазного квадрата в соответствии с этой статьей: http://www.lighthouse3d.com/opengl/terrain/index.php?mpd2
Проблема в том, что я получаю эти крутые скалы по всей карте. Это происходит по краям, когда ландшафт рекурсивно подразделяется:
Вот источник:
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
}
Параметры: (x1, y1), (x2, y2) - координаты, которые определяют регион на карте высот (по умолчанию (0,0) (128,128)). дальность действия - в основном макс. рост. (по умолчанию 32)
Помощь будет принята с благодарностью.
Ответы:
На каждом уровне подразделения «квадратный» шаг зависит от результатов «алмазного шага». Но это также влияет на алмазную ступеньку, произведенную в соседней ячейке, которую вы не учитываете. Я бы переписал функцию DiamondSquare для итерации в ширину, а не в глубину, как у вас сейчас.
Ваша первая проблема заключается в том, что, поскольку вы дважды пересчитываете квадратные ребра, он игнорирует вклад соседней центральной точки. Например, в статье, на которую вы ссылаетесь,
но ваш код эффективно делает
т.е. это факторы в текущем центральную точку дважды, а не центральную точку прилегания. Вот почему вам нужно идти в ширину, чтобы вычислить предыдущие центральные точки.
Вот мой код и вывод:
источник
Одна из возможностей заключается в том, что вы используете ярлык с вашей реализацией, которого нет на алгоритме на вашей связанной странице.
Для квадрата вы рассчитываете высоту точек с
который алгоритм страницы указывает на использование, если вы оборачиваете свою карту. Это создает впечатление, что вы используете значение высоты "next square over" для вычисления этого значения. В простейшем первом случае центральная точка (с высотой 'e') используется как слева, так и справа для вычисления f.
Однако алгоритм, на который вы ссылаетесь, использует фактические значения других квадратов / ромбов, чтобы помочь вам вычислить значение высоты этой квадратной точки. В их алгоритме точка второго уровня вычисляется по следующей формуле:
Заметили отсутствие дублирования значения там?
Я думаю, что вы, возможно, захотите попробовать использовать неконвертирующие версии приведенных формул, которые, я думаю, будут повторяться лучше.
источник