Hi, I'm having problems again with another algorithm. This time it is the Diamond-Square algorithm(htpp://www.gameprogrammer.com/fractal.html if you are interested)
It is producing the desired effect, sort of. It is suppose to randomize all y values to non-zero values, however it only does about a quarter of them. Any help would be much appriciated.
Code:
// Brad Galloway
// Diamond-Square Implementation
// First compile: April 16th, 2005
#include<fstream>
#include<iostream>
#include<ctime>
#include<cstdlib>
#include<cmath>
using namespace std;
const int ARRAY_SIZE = 33;
struct point{
float x;
float y;
float z;
};
point array[ARRAY_SIZE][ARRAY_SIZE];
float random_number(){
//Generates a random floating point number
srand(time(NULL));
int random = (rand() % 200) - 100;
float return_value = (float)random / 100.0f;
return return_value;
}
void create_array(){
for(int i = 0; i < ARRAY_SIZE; i++){
for(int j = 0; j < ARRAY_SIZE; j++){
array[i][j].x = (float)j - (float)(ARRAY_SIZE/2);
array[i][j].y = 0.0f;
array[i][j].z = (float)i - (float)(ARRAY_SIZE/2);
}
}
}
void diamond_step(int s, int n) //s = size of squares in this step, n = number of squares
{
int count = 0; //keeps track of the column we are modifying.
int xstart = 0; //Keeps track of the starting location for this square x
int zstart = 0; //Keeps track of the starting location for this square z
float average; //Holds the average of the for corners
for(int i = 0; i < n; i++){ //Loops equal to the number of squares to be done in this time
// average = (corner1 + corner2 + corner3 + corner4)/4
average = (array[xstart][zstart].y + array[xstart + s][zstart].y +
array[xstart][zstart + s].y + array[xstart + s][zstart + s].y)/4.0f;
if(array[s/2 + 1 + xstart][s/2 + 1 + zstart].y == 0)
array[s/2 + 1 + xstart][s/2 + 1 + zstart].y += average + random_number();
count++; //Add one to count
if(count^2 == n){ //If count squared equals n
count = 0; //then set count to 0
xstart = 0; //set xstart back to 0
zstart += s; //increment zstart
}
else{
xstart += s; //if not, increment xstart and do the next square
};
}
}
void square_step(int half_size, int n){// Note xspot and zspot correspond to the points in the array that contain the data, not the data itself.
int count_dia = 0;
int test_number = (int)sqrt((float)n);
if(test_number == 0)
test_number = 1;
int xspot = (((ARRAY_SIZE/test_number)/2)+1);
int zspot = (((ARRAY_SIZE/test_number)/2)+1);
int xbegin = xspot;
float average_dia_left; //Keeps track of the average heights for the four diamonds
float average_dia_top; //around the axis.
float average_dia_right;
float average_dia_bottom;
for(int i = 0; i < n; i++){
if(xspot >= (half_size * 2)){ //Left
average_dia_left = array[xspot][zspot].y + array[xspot - half_size][zspot + half_size].y
+ array[xspot - (half_size * 2)][zspot].y + array[xspot - half_size][zspot - half_size].y;
}
else{ //If the axis is on next to the outside of the array
average_dia_left = array[xspot][zspot].y + array[xspot - half_size][zspot + half_size].y
+ array[xspot - half_size][zspot - half_size].y;
}
if(zspot >= (half_size * 2)){ //Top
average_dia_top = array[xspot][zspot].y + array[xspot - half_size][zspot - half_size].y
+ array[xspot][zspot - (half_size * 2)].y + array[xspot + half_size][zspot + half_size].y;
}
else{ //If the axis is on next to the outside of the array
average_dia_top = array[xspot][zspot].y + array[xspot - half_size][zspot - half_size].y
+ array[xspot + half_size][zspot + half_size].y;
}
if(xspot + (half_size * 2) <= ARRAY_SIZE){ //Right
average_dia_right = array[xspot][zspot].y + array[xspot + half_size][zspot - half_size].y
+ array[xspot + (half_size * 2)][zspot].y + array[xspot + half_size][zspot + half_size].y;
}
else{ //If the axis is on next to the outside of the array
average_dia_right = array[xspot][zspot].y + array[xspot + half_size][zspot - half_size].y
+ array[xspot + half_size][zspot + half_size].y;
}
if(zspot + (half_size * 2) <= ARRAY_SIZE){ //Bottom
average_dia_bottom = array[xspot][zspot].y + array[xspot + half_size][zspot + half_size].y
+ array[xspot][zspot + (half_size * 2)].y + array[xspot - half_size][zspot + half_size].y;
}
else{ //If the axis is on next to the outside of the array
average_dia_bottom = array[xspot][zspot].y + array[xspot + half_size][zspot + half_size].y
+ array[xspot - half_size][zspot + half_size].y;
}
if(array[xspot - half_size][zspot].y == 0){ //Left
array[xspot - half_size][zspot].y += average_dia_left + random_number();
}
if(array[xspot][zspot - half_size].y == 0){ //Top
array[xspot][zspot - half_size].y += average_dia_top + random_number();
}
if(array[xspot + half_size][zspot].y == 0){ //Right
array[xspot + half_size][zspot].y += average_dia_right + random_number();
}
if(array[xspot][zspot + half_size].y == 0){ //Bottom
array[xspot][zspot + half_size].y += average_dia_bottom + random_number();
}
count_dia++; //Add one to count
if(count_dia^2 == n){ //If count squared equals n
count_dia = 0; //then set count to 0
xspot = xbegin; //set xspot back to Initial step
zspot += half_size * 2; //increment zstart
}
else{
xspot += half_size * 2; //if not, increment xstart and do the next square
};
}
}
void print_array(){
char filename[11] = "output.txt";
ofstream outFile( filename );
for(int j = 0; j < ARRAY_SIZE; j++){
for(int i = 0; i < ARRAY_SIZE; i++){
outFile << "(" << array[i][j].x << ", " << array[i][j].y << ", " << array[i][j].z << ") ";
}
outFile << endl;
}
cout << "File created 'output.txt'";
}
int main(){
int num_cells = (ARRAY_SIZE - 1)^2;
bool done = false;
int q = 1; //quotient for figuring the size of the squares and number of squares
create_array();
while(!done){
diamond_step(num_cells/q, q^2);
square_step((num_cells/q)/2, q^2);
q *= 2;
if(q > num_cells)
done = true;
}
print_array();
return 1;
}