Zaimplementowałem algorytm kwadratu diamentowego zgodnie z tym artykułem: http://www.lighthouse3d.com/opengl/terrain/index.php?mpd2
Problem polega na tym, że te strome klify dostaję na całej mapie. Zdarza się to na krawędziach, gdy teren jest rekurencyjnie podzielony:
Oto źródło:
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
}
Parametry: (x1, y1), (x2, y2) - współrzędne, które definiują region na mapie wysokości (domyślnie (0,0) (128 128). zasięg - w zasadzie maks. wysokość. (domyślnie 32)
Pomoc byłaby bardzo mile widziana.
Odpowiedzi:
Na każdym poziomie podziału krok „kwadratowy” opiera się na wynikach „kroku diamentowego”. Ale ma to również wpływ na krok diamentu wytworzony w sąsiedniej komórce, którego nie rozliczasz. Przepisałbym funkcję DiamondSquare, aby iterować najpierw szerokość, a nie głębokość tak, jak ją obecnie masz.
Pierwszym problemem jest to, że ponieważ dwukrotnie obliczyłeś kwadratowe krawędzie, ignoruje on udział sąsiedniego punktu środkowego. Na przykład w artykule, do którego się odwołujesz,
ale twój kod działa skutecznie
tzn. dwukrotnie uwzględnia bieżący punkt środkowy, a nie sąsiedni punkt środkowy. Dlatego musisz przejść na szerokość, aby obliczyć poprzednie punkty środkowe.
Oto mój kod i wynik:.
źródło
Jedną z możliwości jest to, że używasz skrótu do implementacji, którego nie robi algorytm na połączonej stronie.
W przypadku kwadratu obliczasz wysokość punktów za pomocą
którego algorytm strony wskazuje, że ma być używany podczas owijania mapy. Daje to wrażenie, że używasz wartości wysokości „następny kwadrat nad” do obliczenia tego. W najprostszym pierwszym przypadku punkt środkowy (o wysokości „e”) jest używany zarówno po lewej, jak i po prawej stronie do obliczenia f.
Jednak w algorytmie, do którego się odwołujesz, używasz rzeczywistych wartości innych kwadratów / diamentów, aby pomóc ci obliczyć wartość wysokości tego punktu kwadratowego. W ich algorytmie punkt drugiego poziomu jest obliczany według następującego wzoru:
Czy zauważysz brak duplikacji wartości?
Myślę, że powinieneś spróbować użyć nie zawijających się wersji podanych formuł. Myślę, że te będą się powtarzać lepiej.
źródło