Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // some content:
- // Written by: Paul E. Martz
- // Copyright 1997 by Paul E. Martz, all right reserved
- // Non-commercial use by individuals is permitted.
- // diamond square algorithm itself is public domain
- // float random
- float rndmf(float high) {
- return (high*rand()/(RAND_MAX+1.0));
- }
- static float randnum (float min, float max) {
- return ((float)(min + (max-min)*R_ONE));
- }
- /*
- * fractRand is a useful interface to randnum.
- */
- #define fractRand(v) randnum (-v, v)
- /*
- * avgEndpoints - Given the i location and a stride to the data
- * values, return the average those data values. "i" can be thought of
- * as the data value in the center of two line endpoints. We use
- * "stride" to get the values of the endpoints. Averaging them yields
- * the midpoint of the line.
- *
- * Called by fill1DFractArray.
- */
- static float avgEndpoints (int i, int stride, float *fa)
- {
- return ((float) (fa[i-stride] +
- fa[i+stride]) * .5f);
- }
- float distance (float i,float j,float k,float l)
- {
- return sqrt((i-j)*(i-j)+(k-l)*(k-l));
- }
- /*
- * avgDiamondVals - Given the i,j location as the center of a diamond,
- * average the data values at the four corners of the diamond and
- * return it. "Stride" represents the distance from the diamond center
- * to a diamond corner.
- *
- * Called by fill2DFractArray.
- */
- static float avgDiamondVals (int i, int j, int stride,
- int size, int subSize, float *fa)
- {
- /* In this diagram, our input stride is 1, the i,j location is
- indicated by "X", and the four value we want to average are
- "*"s:
- . * .
- * X *
- . * .
- */
- /* In order to support tiled surfaces which meet seamless at the
- edges (that is, they "wrap"), We need to be careful how we
- calculate averages when the i,j diamond center lies on an edge
- of the array. The first four 'if' clauses handle these
- cases. The final 'else' clause handles the general case (in
- which i,j is not on an edge).
- */
- if (i == 0)
- return ((float) (fa[(i*size) + j-stride] +
- fa[(i*size) + j+stride] +
- fa[((subSize-stride)*size) + j] +
- fa[((i+stride)*size) + j]) * .25f);
- else if (i == size-1)
- return ((float) (fa[(i*size) + j-stride] +
- fa[(i*size) + j+stride] +
- fa[((i-stride)*size) + j] +
- fa[((0+stride)*size) + j]) * .25f);
- else if (j == 0)
- return ((float) (fa[((i-stride)*size) + j] +
- fa[((i+stride)*size) + j] +
- fa[(i*size) + j+stride] +
- fa[(i*size) + subSize-stride]) * .25f);
- else if (j == size-1)
- return ((float) (fa[((i-stride)*size) + j] +
- fa[((i+stride)*size) + j] +
- fa[(i*size) + j-stride] +
- fa[(i*size) + 0+stride]) * .25f);
- else
- return ((float) (fa[((i-stride)*size) + j] +
- fa[((i+stride)*size) + j] +
- fa[(i*size) + j-stride] +
- fa[(i*size) + j+stride]) * .25f);
- }
- /*
- * avgSquareVals - Given the i,j location as the center of a square,
- * average the data values at the four corners of the square and return
- * it. "Stride" represents half the length of one side of the square.
- *
- * Called by fill2DFractArray.
- */
- static float avgSquareVals (int i, int j, int stride, int size, float *fa)
- {
- /* In this diagram, our input stride is 1, the i,j location is
- indicated by "*", and the four value we want to average are
- "X"s:
- X . X
- . * .
- X . X
- */
- return ((float) (fa[((i-stride)*size) + j-stride] +
- fa[((i-stride)*size) + j+stride] +
- fa[((i+stride)*size) + j-stride] +
- fa[((i+stride)*size) + j+stride]) * .25f);
- }
- // ifdef DEBUG
- /*
- * dump1DFractArray - Use for debugging.
- */
- void dump1DFractArray (float *fa, int size)
- {
- int i;
- for (i=0; i<size; i++)
- printf ("(%.2f) ", fa[i]);
- printf ("\n");
- }
- /*
- * dump2DFractArray - Use for debugging.
- */
- void dump2DFractArray (float *fa, int size)
- {
- int i, j;
- for (i=0; i<size; i++) {
- j=0;
- // printf ("[%d,%d]: ", i, j);
- for (; j<size; j++) {
- printf ("%.2f ",
- fa[(i*size)+j]);
- }
- printf ("\n");
- }
- }
- // endif
- /*
- * powerOf2 - Returns 1 if size is a power of 2. Returns 0 if size is
- * not a power of 2, or is zero.
- */
- static int powerOf2 (int size)
- {
- int i, bitcount = 0;
- /* Note this code assumes that (sizeof(int)*8) will yield the
- number of bits in an int. Should be portable to most
- platforms. */
- for (i=0; i<sizeof(int)*8; i++)
- if (size & (1<<i))
- bitcount++;
- if (bitcount == 1)
- /* One bit. Must be a power of 2. */
- return (1);
- else
- /* either size==0, or size not a power of 2. Sorry, Charlie. */
- return (0);
- }
- /*
- * fill1DFractArray - Tessalate an array of values into an
- * approximation of fractal Brownian motion.
- */
- void fill1DFractArray (float *fa, int size,
- int seedValue, float heightScale, float h)
- {
- int i;
- int stride;
- int subSize;
- float ratio, scale;
- if (!powerOf2(size) || (size==1)) {
- /* We can't tesselate the array if it is not a power of 2. */
- #ifdef DEBUG
- printf ("Error: fill1DFractArray: size %d is not a power of 2.\n");
- #endif /* DEBUG */
- return;
- }
- /* subSize is the dimension of the array in terms of connected line
- segments, while size is the dimension in terms of number of
- vertices. */
- subSize = size;
- size++;
- /* initialize random number generator */
- srandom (seedValue);
- #ifdef DEBUG
- printf ("initialized\n");
- dump1DFractArray (fa, size);
- #endif
- /* Set up our roughness constants.
- Random numbers are always generated in the range 0.0 to 1.0.
- 'scale' is multiplied by the randum number.
- 'ratio' is multiplied by 'scale' after each iteration
- to effectively reduce the randum number range.
- */
- ratio = (float) pow (2.,-h);
- scale = heightScale * ratio;
- /* Seed the endpoints of the array. To enable seamless wrapping,
- the endpoints need to be the same point. */
- stride = subSize / 2;
- fa[0] =
- fa[subSize] = 0.f;
- #ifdef DEBUG
- printf ("seeded\n");
- dump1DFractArray (fa, size);
- #endif
- while (stride) {
- for (i=stride; i<subSize; i+=stride) {
- fa[i] = scale * fractRand (.5f) +
- avgEndpoints (i, stride, fa);
- /* reduce random number range */
- scale *= ratio;
- i+=stride;
- }
- stride >>= 1;
- }
- #ifdef DEBUG
- printf ("complete\n");
- dump1DFractArray (fa, size);
- #endif
- }
- /*
- * fill2DFractArray - Use the diamond-square algorithm to tessalate a
- * grid of float values into a fractal height map.
- */
- void fill2DFractArray (float *fa, int size,
- int seedValue, float heightScale, float h)
- {
- int i, j;
- int stride;
- int oddline;
- int subSize;
- float ratio, scale;
- if (!powerOf2(size) || (size==1)) {
- /* We can't tesselate the array if it is not a power of 2. */
- #ifdef DEBUG
- printf ("Error: fill2DFractArray: size %d is not a power of 2.\n");
- #endif /* DEBUG */
- return;
- }
- /* subSize is the dimension of the array in terms of connected line
- segments, while size is the dimension in terms of number of
- vertices. */
- subSize = size;
- size++;
- /* initialize random number generator */
- srandom (seedValue);
- #ifdef DEBUG
- printf ("initialized\n");
- dump2DFractArray (fa, size);
- #endif
- /* Set up our roughness constants.
- Random numbers are always generated in the range 0.0 to 1.0.
- 'scale' is multiplied by the randum number.
- 'ratio' is multiplied by 'scale' after each iteration
- to effectively reduce the randum number range.
- */
- ratio = (float) pow (2.,-h);
- scale = heightScale * ratio;
- /* Seed the first four values. For example, in a 4x4 array, we
- would initialize the data points indicated by '*':
- * . . . *
- . . . . .
- . . . . .
- . . . . .
- * . . . *
- In terms of the "diamond-square" algorithm, this gives us
- "squares".
- We want the four corners of the array to have the same
- point. This will allow us to tile the arrays next to each other
- such that they join seemlessly. */
- stride = subSize / 2;
- fa[(0*size)+0] =
- fa[(subSize*size)+0] =
- fa[(subSize*size)+subSize] =
- fa[(0*size)+subSize] = 0.f;
- #ifdef DEBUG
- printf ("seeded\n");
- dump2DFractArray (fa, size);
- #endif
- /* Now we add ever-increasing detail based on the "diamond" seeded
- values. We loop over stride, which gets cut in half at the
- bottom of the loop. Since it's an int, eventually division by 2
- will produce a zero result, terminating the loop. */
- while (stride) {
- /* Take the existing "square" data and produce "diamond"
- data. On the first pass through with a 4x4 matrix, the
- existing data is shown as "X"s, and we need to generate the
- "*" now:
- X . . . X
- . . . . .
- . . * . .
- . . . . .
- X . . . X
- It doesn't look like diamonds. What it actually is, for the
- first pass, is the corners of four diamonds meeting at the
- center of the array. */
- for (i=stride; i<subSize; i+=stride) {
- for (j=stride; j<subSize; j+=stride) {
- fa[(i * size) + j] =
- scale * fractRand (.5f) +
- avgSquareVals (i, j, stride, size, fa);
- j += stride;
- }
- i += stride;
- }
- #ifdef DEBUG
- printf ("Diamonds:\n");
- dump2DFractArray (fa, size);
- #endif
- /* Take the existing "diamond" data and make it into
- "squares". Back to our 4X4 example: The first time we
- encounter this code, the existing values are represented by
- "X"s, and the values we want to generate here are "*"s:
- X . * . X
- . . . . .
- * . X . *
- . . . . .
- X . * . X
- i and j represent our (x,y) position in the array. The
- first value we want to generate is at (i=2,j=0), and we use
- "oddline" and "stride" to increment j to the desired value.
- */
- oddline = 0;
- for (i=0; i<subSize; i+=stride) {
- oddline = (oddline == 0);
- for (j=0; j<subSize; j+=stride) {
- if ((oddline) && !j) j+=stride;
- /* i and j are setup. Call avgDiamondVals with the
- current position. It will return the average of the
- surrounding diamond data points. */
- fa[(i * size) + j] =
- scale * fractRand (.5f) +
- avgDiamondVals (i, j, stride, size, subSize, fa);
- /* To wrap edges seamlessly, copy edge values around
- to other side of array */
- if (i==0)
- fa[(subSize*size) + j] =
- fa[(i * size) + j];
- if (j==0)
- fa[(i*size) + subSize] =
- fa[(i * size) + j];
- j+=stride;
- }
- }
- #ifdef DEBUG
- printf ("Squares:\n");
- dump2DFractArray (fa, size);
- #endif
- /* reduce random number range. */
- scale *= ratio;
- stride >>= 1;
- }
- #ifdef DEBUG
- printf ("complete\n");
- dump2DFractArray (fa, size);
- #endif
- }
- /*
- * alloc1DFractArray - Allocate float-sized data points for a 1D strip
- * containing size line segments.
- */
- float *alloc1DFractArray (int size)
- {
- /* Increment size (see comment in alloc2DFractArray, below, for an
- explanation). */
- size++;
- return ((float *) malloc (sizeof(float) * size));
- }
- /*
- * alloc2DFractArray - Allocate float-sized data points for a sizeXsize
- * mesh.
- */
- float *alloc2DFractArray (int size)
- {
- /* For a sizeXsize array, we need (size+1)X(size+1) space. For
- example, a 2x2 mesh needs 3x3=9 data points:
- * * *
- * * *
- * * *
- To account for this, increment 'size'. */
- size++;
- return ((float *) malloc (sizeof(float) * size * size));
- }
- /*
- * freeFractArray - Takes a pointer to float and frees it. Can be used
- * to free data that was allocated by either alloc1DFractArray or
- * alloc2DFractArray.
- */
- void freeFractArray (float *fa)
- {
- free (fa);
- }
- static void genNormal (float x1, float y1, float z1,
- float x2, float y2, float z2,
- float x3, float y3, float z3,
- float *normal)
- {
- float len;
- float v1x, v1y, v1z;
- float v2x, v2y, v2z;
- v1x = x2 - x1;
- v1y = y2 - y1;
- v1z = z2 - z1;
- v2x = x3 - x1;
- v2y = y3 - y1;
- v2z = z3 - z1;
- normal[0] = v1y*v2z - v1z*v2y;
- normal[1] = v1z*v2x - v1x*v2z;
- normal[2] = v1x*v2y - v1y*v2x;
- len = (float) sqrt (normal[0]*normal[0] + normal[1]*normal[1] +
- normal[2]*normal[2]);
- normal[0] /= len;
- normal[1] /= len;
- normal[2] /= len;
- }
- void segment(float * arr, float s0, float s1, int nsegs)
- {
- // fills in already allocated array of floats
- int i;
- float l[nsegs], ls=0;
- for (i=0; i<nsegs; i++) {
- l[i] = rand()%1000;
- ls += l[i];
- }
- arr[0] = s0;
- for (i=1; i<nsegs; i++) arr[i] = arr[i-1] + l[i]*(s1-s0)/ls;
- // expects there to be one more point, to be set to s1
- arr[nsegs] = s1;
- }
- /*
- // quickSort
- //
- // This public-domain C implementation by Darel Rex Finley.
- //
- // * Returns YES if sort was successful, or NO if the nested
- // pivots went too deep, in which case your array will have
- // been re-ordered, but probably not sorted correctly.
- //
- // * This function assumes it is called with valid parameters.
- //
- // * Example calls:
- // quickSort(&myArray[0],5); // sorts elements 0, 1, 2, 3, and 4
- // quickSort(&myArray[3],5); // sorts elements 3, 4, 5, 6, and 7
- bool quickSort(int *arr, int elements) {
- #define MAX_LEVELS 1000
- int piv, beg[MAX_LEVELS], end[MAX_LEVELS], i=0, L, R ;
- beg[0]=0; end[0]=elements;
- while (i>=0) {
- L=beg[i]; R=end[i]-1;
- if (L<R) {
- piv=arr[L]; if (i==MAX_LEVELS-1) return NO;
- while (L<R) {
- while (arr[R]>=piv && L<R) R--; if (L<R) arr[L++]=arr[R];
- while (arr[L]<=piv && L<R) L++; if (L<R) arr[R--]=arr[L]; }
- arr[L]=piv; beg[i+1]=L+1; end[i+1]=end[i]; end[i++]=L; }
- else {
- i--; }}
- return YES; }
- */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement