void ArcTerrain::diamondSquare(int tL[], int tR[], int bL[], int bR[], int level) { // PROBLEM: ACCESSING UNASSIGNED VALUES FOR AVERAGE //std::cout << "bR = " << bR[0] << ", " << bR[1] << std::endl; //std::cout << "bL = " << bL[0] << ", " << bL[1] << std::endl; // find average float average = (mMap[tL[0]][tL[1]] + mMap[tR[0]][tR[1]] + mMap[bL[0]][bL[1]] + mMap[bR[0]][bR[1]]) / 4; // find midPoint int cX = (tL[0] + bR[0]) / 2; int cY = (tL[1] + bR[1]) / 2; int C[] = {cX, cY}; mMap[cX][cY] = average + randomHeight(level--); if (mMap[cX][cY] > mMax) mMax = mMap[cX][cY]; if (mMap[cX][cY] < mMin) mMin = mMap[cX][cY]; int T[] = {cX, tL[1]}; double tA = (mMap[tL[0]][tL[1]] + mMap[tR[0]][tR[1]] + mMap[cX][cY]) / 3; //std::cout << cX << ", " << bL[1] << std::endl; int B[] = {cX, bL[1]}; double bA = (mMap[bL[0]][bL[1]] + mMap[bR[0]][bR[1]] + mMap[cX][cY]) / 3; int L[] = {tL[0], cY}; double lA = (mMap[tL[0]][tL[1]] + mMap[bL[0]][bL[1]] + mMap[cX][cY]) / 3; int R[] = {tR[0], cY}; double rA = (mMap[tR[0]][tR[1]] + mMap[bR[0]][bR[1]] + mMap[cX][cY]) / 3; // Set midpoint to average + random height mMap[T[0]][T[1]] = tA; mMap[B[0]][B[1]] = bA; mMap[L[0]][L[1]] = lA; mMap[R[0]][R[1]] = rA; //level--; if (level > 0) { diamondSquare(tL, T, L, C, level); // TL diamondSquare(T, tR, C, R, level); // TR diamondSquare(L, C, bL, B, level); // BL diamondSquare(C, R, B, bR, level); // BR } }
void ArcTerrain::square(int T[], int B[], int L[], int R[], int level) { //std::cout << "Square " << level << ":\n"; int num2Average = 4; float sum = 0; float average = 0; bool top = true, bottom = true, left = true, right = true; // Error Check / find average if (((T[0] >= 0) && (T[1] >= 0)) && (((T[0] < mSize) && (T[1] < mSize)))) sum += mMap[T[0]][T[1]]; else {num2Average--; top = false;} if (((B[0] >= 0) && (B[1] >= 0)) && (((B[0] < mSize) && (B[1] < mSize)))) sum += mMap[B[0]][B[1]]; else {num2Average--; bottom = false;} if (((R[0] >= 0) && (R[1] >= 0)) && (((R[0] < mSize) && (R[1] < mSize)))) sum += mMap[R[0]][R[1]]; else {num2Average--; right = false;} if (((L[0] >= 0) && (L[1] >= 0)) && (((L[0] < mSize) && (L[1] < mSize)))) sum += mMap[L[0]][L[1]]; else {num2Average--; left = false;} if (num2Average != 0) average = sum / num2Average; //std::cout << average << " "; // Find midpoint int midX = T[0]; int midY = L[1]; // Set midpoint to average + random height mMap[midX][midY] = average+ randomHeight(level--); if (mMap[midX][midY] > mMax) mMax = mMap[midX][midY]; if (mMap[midX][midY] < mMin) mMin = mMap[midX][midY]; //level--; if (level > 0) { // find corners int mid[2] = {midX, midY}; int tL[2] = {L[0], T[1]}; int tR[2] = {R[0], T[1]}; int bL[2] = {L[0], B[1]}; int bR[2] = {R[0], B[1]}; // diamond each quadrant if they exist if (top && left) {diamond(tL, T, L, mid, level);} if (top && right) {diamond(T, tR, mid, R, level);} if (bottom && left) {diamond(L, mid, bL, B, level);} if (bottom && right) {diamond(mid, R, B, bR, level);} } }
void ArcTerrain::diamond(int tL[], int tR[], int bL[], int bR[], int level) { //std::cout << "Diamond level " << level << ":\n"; // find average float average = (mMap[tL[0]][tL[1]] + mMap[tR[0]][tR[1]] + mMap[bL[0]][bL[1]] + mMap[bR[0]][bR[1]]) / 4; //std::cout << average << " "; // find midPoint int midX = (tL[0] + bR[0]) / 2; int midY = (tL[1] + bR[1]) / 2; // Set midpoint to average + random height mMap[midX][midY] = average + randomHeight(level--); if (mMap[midX][midY] > mMax) mMax = mMap[midX][midY]; if (mMap[midX][midY] < mMin) mMin = mMap[midX][midY]; //level--; if (level > 0) { // Find Diamonds int leftX = 2 * tL[0] - midX; int rightX = 2 * tR[0] - midX; int topY = 2 * tL[1] - midY; int bottomY = 2 * bL[1] - midY; int left [2] = {leftX , midY}; int right [2] = {rightX, midY}; int top [2] = {midX, topY}; int bottom [2] = {midX, bottomY}; int mid [2] = {midX, midY}; // Square diamonds square(top, mid, tL, tR, level); // top diamond square(mid, bottom, bL, bR, level); // bottom diamond square(tL, bL, left, mid, level); // left diamond square(tR, bR, mid, right, level); // right diamond } }
// creates a random, fractal heightfield static void setFractal ( byte_t * grid, int bytesPerElement, PHY_ScalarType type, int step ) { btAssert(grid); btAssert(bytesPerElement > 0); btAssert(step > 0); btAssert(step < s_gridSize); int newStep = step / 2; // std::cerr << "Computing grid with step = " << step << ": before\n"; // dumpGrid(grid, bytesPerElement, type, step + 1); // special case: starting (must set four corners) if (s_gridSize - 1 == step) { // pick a non-zero (possibly negative) base elevation for testing float base = randomHeight(step / 2); convertFromFloat(grid, base, type); convertFromFloat(grid + step * bytesPerElement, base, type); convertFromFloat(grid + step * s_gridSize * bytesPerElement, base, type); convertFromFloat(grid + (step * s_gridSize + step) * bytesPerElement, base, type); } // determine elevation of each corner float c00 = convertToFloat(grid, type); float c01 = convertToFloat(grid + step * bytesPerElement, type); float c10 = convertToFloat(grid + (step * s_gridSize) * bytesPerElement, type); float c11 = convertToFloat(grid + (step * s_gridSize + step) * bytesPerElement, type); // set top middle updateHeight(grid + newStep * bytesPerElement, 0.5 * (c00 + c01) + randomHeight(step), type); // set left middle updateHeight(grid + (newStep * s_gridSize) * bytesPerElement, 0.5 * (c00 + c10) + randomHeight(step), type); // set right middle updateHeight(grid + (newStep * s_gridSize + step) * bytesPerElement, 0.5 * (c01 + c11) + randomHeight(step), type); // set bottom middle updateHeight(grid + (step * s_gridSize + newStep) * bytesPerElement, 0.5 * (c10 + c11) + randomHeight(step), type); // set middle updateHeight(grid + (newStep * s_gridSize + newStep) * bytesPerElement, 0.25 * (c00 + c01 + c10 + c11) + randomHeight(step), type); // std::cerr << "Computing grid with step = " << step << ": after\n"; // dumpGrid(grid, bytesPerElement, type, step + 1); // terminate? if (newStep < 2) { return; } // recurse setFractal(grid, bytesPerElement, type, newStep); setFractal(grid + newStep * bytesPerElement, bytesPerElement, type, newStep); setFractal(grid + (newStep * s_gridSize) * bytesPerElement, bytesPerElement, type, newStep); setFractal(grid + ((newStep * s_gridSize) + newStep) * bytesPerElement, bytesPerElement, type, newStep); }