Ich habe eine grobe Interpretation der Diamond-Square-Algorithmus in C++, um einige semi-realistische fraktale Gelände zu erstellen, aber die Ausgabe scheint nur wie ein zufälliger y-Wert bei jeder Punkt eher als glatte felsige Formen. Ich habe die Parameter geändert, aber ich habe das Gefühl, dass ein Blick auf den Code von außen dazu beitragen könnte, das Problem zu verstehen. Hier sind Beispiele für die Ausgabe:C++ - Diamond-Square-Algorithmus Ausgabe ist zufällig und laut
ich diese bekam:
Und sollte wie folgt aussehen:
Der Code:
//Diamond-square algorithm
HeightMap::HeightMap(float maxY) {
//type = GL_POINTS;
//type = GL_LINES;
numVertices = RAW_WIDTH*RAW_HEIGHT; //256^2 squares => 257^2 vertices
numIndices = (RAW_WIDTH - 1)*(RAW_HEIGHT - 1) * 6; //each square is 2 triangles (6 indices)
vertices = new Vector3[numVertices];
textureCoords = new Vector2[numVertices];
indices = new GLuint[numIndices];
colours = new Vector4[numVertices];
int cornerA, cornerB, cornerC, cornerD; //Identify corners
cornerA = 0;
cornerB = RAW_WIDTH - 1;
cornerC = RAW_WIDTH*RAW_HEIGHT - RAW_WIDTH;
cornerD = RAW_WIDTH*RAW_HEIGHT - 1;
//Create vertices
for (int x = 0; x < RAW_WIDTH; ++x) {
for (int z = 0; z < RAW_HEIGHT; ++z) {
int offset = (x * RAW_WIDTH) + z;
float y = 0; //Start with vertices set flat
if (offset == cornerA ||
offset == cornerB ||
offset == cornerC ||
offset == cornerD) {
vertices[offset] = Vector3(x * HEIGHTMAP_X, maxY/2, z * HEIGHTMAP_Z); //Initialise corners to mid height
std::cout << "Corners: " << offset << std::endl;
}
if (vertices[offset] == Vector3(0, 0, 0)) {
vertices[offset] = Vector3(x * HEIGHTMAP_X, y * HEIGHTMAP_Y, z * HEIGHTMAP_Z);
}
// textureCoords[offset] = Vector2(x * HEIGHTMAP_TEX_X, z * HEIGHTMAP_TEX_Z);
}
}
Vector3 tl, tr, bl, br;
tl = vertices[cornerA];
tr = vertices[cornerB];
bl = vertices[cornerC];
br = vertices[cornerD];
float roughness = 1.0f;
Square square = Square(tl, tr, bl, br);
diamondSquare(vertices, numVertices, square, roughness);
//Colour
for (int x = 0; x < RAW_WIDTH; ++x) {
for (int z = 0; z < RAW_HEIGHT; ++z) {
int offset = (x*RAW_WIDTH) + z;
float shade;
if (vertices[offset].y > 0) {
shade = 1 - 1.0f/(vertices[offset].y/maxY * 2);
}
else {
shade = 0.1f;
}
colours[offset] = Vector4(shade, shade, shade, 1.0f);
//Colour any vertex that hasn't been passed over red
if (vertices[offset].y == maxY/2 + 100) {
colours[offset] = Vector4(1, 0, 0, 1);
}
}
}
//Create indices
numIndices = 0;
for (int x = 0; x < RAW_WIDTH - 1; ++x) {
for (int z = 0; z < RAW_HEIGHT - 1; ++z) {
int a = (x*(RAW_WIDTH)) + z;
int b = ((x + 1)*(RAW_WIDTH)) + z;
int c = ((x + 1)*(RAW_WIDTH)) + (z + 1);
int d = (x*(RAW_WIDTH)) + (z + 1);
indices[numIndices++] = c;
indices[numIndices++] = b;
indices[numIndices++] = a;
indices[numIndices++] = a;
indices[numIndices++] = d;
indices[numIndices++] = c;
}
}
BufferData();
}
void HeightMap::squareStep(Vector3 vertices[], int len, Vector3 tl, Vector3 tr, Vector3 bl, Vector3 br, float mid, float roughness) {
for (int i = 0; i < len; i++) {
Vector3 top = (tl + tr)/2;
Vector3 bot = (bl + br)/2;
Vector3 left = (tl + bl)/2;
Vector3 right = (tr + br)/2;
top.y = 0;
bot.y = 0;
left.y = 0;
right.y = 0;
if (vertices[i] == top ||
vertices[i] == bot ||
vertices[i] == left ||
vertices[i] == right) {
float y = rand() % (int)(mid/5);
y *= roughness;
vertices[i] = Vector3(vertices[i].x, mid + y, vertices[i].z); //Set Diamond centre points to mid height + rand
std::cout << "Square: " << vertices[i];
}
}
}
float HeightMap::diamondStep(Vector3 vertices[], int len, Vector3 tl, Vector3 tr, Vector3 bl, Vector3 br, float roughness) {
float avg;
float y;
for (int i = 0; i < len; i++) {
Vector3 corners = (tl + tr + bl + br)/4;
avg = corners.y;
y = rand() % (int)(avg/5);
y *= roughness;
corners.y = 0;
if (vertices[i] == corners) {
vertices[i] = Vector3(vertices[i].x, avg + y, vertices[i].z); //Set Square centre point to avg height of corners + rand
std::cout << "Diamond: " << vertices[i];
}
}
return avg + y;
}
void HeightMap::diamondSquare(Vector3 vertices[], int numVertices, Square s, float roughness) {
Vector3 tl = s.tl;
Vector3 tr = s.tr;
Vector3 bl = s.bl;
Vector3 br = s.br;
float mid = diamondStep(vertices, numVertices, tl, tr, bl, br, roughness);
squareStep(vertices, numVertices, tl, tr, bl, br, mid, roughness);
roughness *= 0.75f;
if (s.width > 2 * HEIGHTMAP_X) {
std::vector<Square> squares = s.split();
for (int i = 0; i < 4; i++) {
diamondSquare(vertices, numVertices, squares[i], roughness);
}
}
}
was meinst du mit "grobe Interpretation"? Vielleicht ist Ihr Beispiel eine grobe Interpretation dessen, wie es aussehen soll. – user463035818
Zu faul, um durch Ihren Code zu gehen, also nur Hinweise: 1. Rekursion ist wirklich schwierig, da Überlappungen und Kantenübergänge Unregelmäßigkeiten einfacher/schneller/besser Iteration stattdessen verwenden Sie meine [Iterative Diamond & Square in C++] (http: // stackoverflow.com/a/36258843/2521214) 2. Es sieht so aus, als ob Sie die Zufälligkeit nicht anpassen (die Magnitude sollte mit der Rekursionsebene geliebäugelt werden) oder nicht die durchschnittliche Position als Basis (Mittelpunktverschiebung), aber das ist nur der visuelle Eindruck, den Sie überprüfen müssen (könnte auch falsche Rekursion sein). Siehe auch [Inselgenerator] (http://stackoverflow.com/a/36647622/2521214) – Spektre