]> icculus.org git repositories - divverent/darkplaces.git/blob - fractalnoise.c
Initial revision
[divverent/darkplaces.git] / fractalnoise.c
1
2 #include <stdlib.h>
3
4 void fractalnoise(unsigned char *noise, int size)
5 {
6         int x, y, g, g2, amplitude, amplitude2, min, max, size1 = size - 1;
7         int *noisebuf;
8 #define n(x,y) noisebuf[((y)&size1)*size+((x)&size1)]
9         noisebuf = calloc(size*size, sizeof(int));
10
11         amplitude = 32767;
12         g2 = size;
13         n(0,0) = 0;
14         for (;(g = g2 >> 1) >= 1;g2 >>= 1)
15         {
16                 // subdivide, diamond-square algorythm (really this has little to do with squares)
17                 // diamond
18                 for (y = 0;y < size;y += g2)
19                         for (x = 0;x < size;x += g2)
20                                 n(x+g,y+g) = (n(x,y) + n(x+g2,y) + n(x,y+g2) + n(x+g2,y+g2)) >> 2;
21                 // square
22                 for (y = 0;y < size;y += g2)
23                         for (x = 0;x < size;x += g2)
24                         {
25                                 n(x+g,y) = (n(x,y) + n(x+g2,y) + n(x+g,y-g) + n(x+g,y+g)) >> 2;
26                                 n(x,y+g) = (n(x,y) + n(x,y+g2) + n(x-g,y+g) + n(x+g,y+g)) >> 2;
27                         }
28                 // brownian motion theory
29                 amplitude >>= 1;
30                 amplitude2 = amplitude >> 1;
31                 for (y = 0;y < size;y += g)
32                         for (x = 0;x < size;x += g)
33                                 n(x,y) += (rand()&amplitude) - amplitude2;
34         }
35         // find range of noise values
36         min = max = 0;
37         for (y = 0;y < size;y++)
38                 for (x = 0;x < size;x++)
39                 {
40                         if (n(x,y) < min) min = n(x,y);
41                         if (n(x,y) > max) max = n(x,y);
42                 }
43         max -= min;
44         // normalize noise and copy to output
45         for (y = 0;y < size;y++)
46                 for (x = 0;x < size;x++)
47                         *noise++ = (n(x,y) - min) * 255 / max;
48         free(noisebuf);
49 #undef n
50 }