home *** CD-ROM | disk | FTP | other *** search
- /* Test file to create Targa height fields for POVRay -- Alexander Enzmann */
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include <float.h>
- #include <string.h>
-
- /* Noise generator variables */
- #define LARGE 100000.0
- #define HASH_SIZE 78737
- #define spline(x) ((3 - 2 * (x)) * (x) * (x))
- static int mult_table_size = 5;
- static unsigned long mult_table[] = { 99137, 113713, 55237, 994472, 441973 };
-
- static float **height_buffer;
- static FILE *TargaFile;
- static int TargaBits = 24;
-
- static void
- TargaOpen(char *filename, int x, int y)
- {
- unsigned char tgaheader[18];
- if ((TargaFile = fopen(filename, "wb")) == NULL) {
- printf("Failed to open Targa file: %s\n", filename);
- exit(1);
- }
- memset(tgaheader, 0, 18);
- tgaheader[2] = 2;
- tgaheader[12] = (unsigned char)(x & 0xFF);
- tgaheader[13] = (unsigned char)((x >> 8) & 0xFF);
- tgaheader[14] = (unsigned char)(y & 0xFF);
- tgaheader[15] = (unsigned char)((y >> 8) & 0xFF);
- tgaheader[16] = TargaBits;
- tgaheader[17] = 0x20;
- fwrite(tgaheader, 18, 1, TargaFile);
- }
-
- static void
- TargaWrite(unsigned char r, unsigned char g, unsigned char b)
- {
- if (TargaBits == 16) {
- fputc(g, TargaFile);
- fputc(r, TargaFile);
- }
- else if (TargaBits == 24) {
- fputc(b, TargaFile);
- fputc(g, TargaFile);
- fputc(r, TargaFile);
- }
- else {
- fprintf(stderr, "Wrong # of bits/pixel for Targa file: %d\n",
- TargaBits);
- exit(1);
- }
- }
-
- static void
- TargaClose()
- {
- fclose(TargaFile);
- }
-
- static float
- hash3d(unsigned long x, unsigned long y, unsigned long z)
- {
- int i;
- unsigned long K, Kt, P;
- float result;
- K = ((x & 0x03ffL) << 20) |
- ((y & 0x03ffL) << 10) |
- (z & 0x03ffL);
- Kt = 0;
- for (i=0;i<mult_table_size;i++)
- Kt = ((Kt + K) * mult_table[i]) % HASH_SIZE;
- result = (float)Kt / (float)(HASH_SIZE - 1);
- return result;
- }
-
- static float
- flt_noise(float x, float y, float z)
- {
- unsigned long ix, iy, iz, jx, jy, jz;
- float sx0, sy0, sz0, sx1, sy1, sz1;
- float result;
-
- x += LARGE; y += LARGE; z += LARGE;
- ix = x; iy = y; iz = z;
- jx = ix + 1; jy = iy + 1; jz = iz + 1;
-
- /* Compute cubic interpolated influences of surrounding
- lattice points */
- sx0 = spline(x - ix);
- sy0 = spline(y - iy);
- sz0 = spline(z - iz);
- sx1 = 1.0 - sx0; sy1 = 1.0 - sy0; sz1 = 1.0 - sz0;
-
- result = hash3d(ix, iy, iz) * sx1 * sy1 * sz1;
- result += hash3d(ix, iy, jz) * sx1 * sy1 * sz0;
- result += hash3d(ix, jy, iz) * sx1 * sy0 * sz1;
- result += hash3d(ix, jy, jz) * sx1 * sy0 * sz0;
- result += hash3d(jx, iy, iz) * sx0 * sy1 * sz1;
- result += hash3d(jx, iy, jz) * sx0 * sy1 * sz0;
- result += hash3d(jx, jy, iz) * sx0 * sy0 * sz1;
- result += hash3d(jx, jy, jz) * sx0 * sy0 * sz0;
- return result;
- }
-
- static float
- noise3d(float x, float y, float z,
- float recursion_scale, int count)
- {
- float x1, y1, z1;
- float result = 0.0;
- float scale = 1.0;
- float iscale = 1.0 / recursion_scale;
- float magnitude = 0.0;
- int i;
-
- x1 = x;
- y1 = y;
- z1 = z;
- for (i=0;i<count;i++) {
- result += scale * flt_noise(x1, y1, z1);
- magnitude += scale;
- if (i < count-1) {
- x1 *= 2.0;
- y1 *= 2.0;
- z1 *= 2.0;
- scale *= recursion_scale;
- }
- }
- result /= magnitude;
- return result;
- }
-
- static write_height(float y)
- {
- unsigned char r, g, b;
- if (y < -127.0) y = -127.0;
- if (y > 127.0) y = 127.0;
- y += 128.0;
- r = (unsigned char)y;
- y -= (float)r;
- g = (unsigned char)(256.0 * y);
- b = 0;
- TargaWrite(r, g, b);
- }
-
- static void
- make_noise_field(int width, int height,
- float xlow, float xhigh,
- float zlow, float zhigh,
- float seed,
- float recursion_scale, int octaves)
- {
- float x, xdelta;
- float y;
- float z, zdelta;
- int i, j;
-
- xdelta = (xhigh - xlow) / ((float)(width-1));
- zdelta = (zhigh - zlow) / ((float)(height-1));
-
- /* Loop through all possible values of z and x, generating
- altitudes as we go. */
- for (i=0,z=zlow;i<height;i++,z+=zdelta) {
- printf("%d \r", i);
- for (j=0,x=xlow;j<width;j++,x+=xdelta) {
- /* Calculate the altitude */
- y = noise3d(x, seed, z, recursion_scale, octaves);
-
- /* Scale it to fit into -128 -> 128 */
- y = 256.0 * (y - 0.5);
-
- /* Write out the altitude */
- write_height(y);
- }
- }
- }
-
- void
- main(argc, argv)
- int argc;
- char **argv;
- {
- int h = 256; /* height of resulting height field */
- int w = 256; /* width of resulting height field */
- int oct = 3; /* # of octaves of noise to use */
- float x0 = -8.0; /* Low x to interpolate noise over */
- float x1 = 8.0; /* High x to interpolate noise over */
- float z0 = -8.0; /* Low z to interpolate noise over */
- float z1 = 8.0; /* High z to interpolate noise over */
- float seed = 1.11; /* Seed to change resulting pattern */
- float sc = 0.25; /* Contribution of each octave of noise */
-
- TargaOpen("fracthf.tga", h, w);
- make_noise_field(h, w, x0, x1, z0, z1, seed, sc, oct);
- TargaClose();
- }
-