1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
/// Cold to create noise through the Diamond method. Requires offset and better hash table to create random height_maps but repeatable
bool Procedural::generateDiamondMethod1 (float * inputData1,const int &width_, const int &height_, const float &maxYcoords,const float &minYcoords)
{
//an initial seed value for the corners of the data
float SEED = 0.4f;
static const unsigned int DATA_SIZE=width_+1;
std::vector< std::vector<float> > diamond( DATA_SIZE, std::vector<float>(DATA_SIZE) );
//initialise the values of the corners++
diamond[0][0] = SEED;
diamond[0][DATA_SIZE-1] = SEED;
diamond[DATA_SIZE-1][0] = SEED;
diamond[DATA_SIZE-1][DATA_SIZE-1] = SEED;
float h =300; //the range (-h -> h) for the average offset
srand(256); //seed the random generator
//side length is the distance of a single square side
//or distance of diagonal in diamond
//each iteration we are looking at smaller squares and diamonds, we decrease the variation of the offset
for (int sideLength = DATA_SIZE-1; sideLength >= 2; sideLength /= 2, h /= 2.0)
{
int halfSide = sideLength/2;
//generate new square values
for(int x=0; x<DATA_SIZE-1; x+=sideLength)
{
for(int y=0; y<DATA_SIZE-1; y+=sideLength)
{
//x,y is upper left corner of the square
//calculate average of existing corners
float avg = diamond[x][y] + //top left
diamond[(x+sideLength)%DATA_SIZE][y] + //top right
diamond[x][ (y+sideLength)%DATA_SIZE] + //lower left
diamond[(x+sideLength)%DATA_SIZE][(y+sideLength)%DATA_SIZE]; //lower right
avg /= 4.0;
//center is average plus random offset in the range (-h, h)
float offset = (-h) + (float)rand() * (h - (-h)) / RAND_MAX;
diamond[x+halfSide][y+halfSide] = avg + offset;
} //for y
} /// for x
//Generate the diamond values
//Since diamonds are staggered, we only move x by half side
//NOTE: if the data shouldn't wrap the x < DATA_SIZE and y < DATA_SIZE
for (int x=0; x<DATA_SIZE; x+=halfSide)
{
for (int y=(x+halfSide)%sideLength; y<DATA_SIZE; y+=sideLength)
{
//x,y is center of diamond
//we must use mod and add DATA_SIZE for subtraction
//so that we can wrap around the array to find the corners
float avg =
diamond[(x-halfSide+DATA_SIZE)%DATA_SIZE][y] + //left of center
diamond[(x+halfSide)%DATA_SIZE][y] + //right of center
diamond[x][(y+halfSide)%DATA_SIZE] + //below center
diamond[x][(y-halfSide+DATA_SIZE)%DATA_SIZE]; //above center
avg /= 4.0;
//new value = average plus random offset
//calc random value in the range (-h,+h)
float offset = (-h) + (float)rand() * (h - (-h)) / RAND_MAX;
avg = avg + offset;
//update value for center of diamond
diamond[x][y] = avg;
//wrap values on the edges
//remove this and adjust loop condition above
//for non-wrapping values
//if (x == 0) diamond[DATA_SIZE-1][y] = avg;
//if (y == 0) diamond[x][DATA_SIZE-1] = avg;
} //for y
} //for x
} //for sideLength
/// Set maxY and minY to 0.0f
float maxY = diamond[1][1];
float minY = diamond[1][1];
for (int x = 0; x<DATA_SIZE; x++)
{
for(int y = 0; y<DATA_SIZE; y++)
{
if ((float)diamond[x][y] > maxY)
{
maxY = diamond[x][y];
}
if ((float)diamond[x][y] < minY)
{
minY = diamond[x][y];
}
}
}
/// Calculate height_ from 0 to 1
for(int x=0; x < DATA_SIZE; x++)
{
for(int y=0; y < DATA_SIZE; y++)
{
//change range to 0..1
diamond[x][y] = (diamond[x][y] - minY) / (maxY - minY);
}
}
/// Copy color float from create texture
for(unsigned y = 0; y<width_; y++)
{
for(unsigned x = 0; x<height_; x++)
{
/// incremennt memory which seems to work
int index = (y*width_)+x;
inputData1[index]=diamond[x][y];
}
}
return true;
}
|