]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - fractalnoise.c
e9899a47f84771e4bc3e22c2514ad20d514d0575
[xonotic/darkplaces.git] / fractalnoise.c
1
2 #include "quakedef.h"
3
4 void fractalnoise(unsigned char *noise, int size, int startgrid)
5 {
6         int x, y, g, g2, amplitude, min, max, size1 = size - 1;
7         int *noisebuf;
8 #define n(x,y) noisebuf[((y)&size1)*size+((x)&size1)]
9         if (startgrid > size)
10                 startgrid = size;
11         noisebuf = qmalloc(size*size*sizeof(int));
12         memset(noisebuf, 0, size*size*sizeof(int));
13
14         amplitude = 32767;
15         // quick 1x1 case which the rest of the code can't handle
16         if (startgrid < 2)
17         {
18                 for (x = 0;x < size*size;x++)
19                         *noise++ = (rand()&255);
20                 return;
21         }
22         g2 = startgrid;
23         // clear the starting grid (the rest does not need to be cleared, it will simply be overwritten)
24         for (y = 0;y < size;y += g2)
25                 for (x = 0;x < size;x += g2)
26                         n(x,y) = 0;
27         for (;(g = g2 >> 1) >= 1;g2 >>= 1)
28         {
29                 // subdivide, diamond-square algorythm (really this has little to do with squares)
30                 // diamond
31                 for (y = 0;y < size;y += g2)
32                         for (x = 0;x < size;x += g2)
33                                 n(x+g,y+g) = (n(x,y) + n(x+g2,y) + n(x,y+g2) + n(x+g2,y+g2)) >> 2;
34                 // square
35                 for (y = 0;y < size;y += g2)
36                         for (x = 0;x < size;x += g2)
37                         {
38                                 n(x+g,y) = (n(x,y) + n(x+g2,y) + n(x+g,y-g) + n(x+g,y+g)) >> 2;
39                                 n(x,y+g) = (n(x,y) + n(x,y+g2) + n(x-g,y+g) + n(x+g,y+g)) >> 2;
40                         }
41                 // brownian motion theory
42                 amplitude >>= 1;
43                 for (y = 0;y < size;y += g)
44                         for (x = 0;x < size;x += g)
45                                 n(x,y) += (rand()&amplitude);
46         }
47         // find range of noise values
48         min = max = 0;
49         for (y = 0;y < size;y++)
50                 for (x = 0;x < size;x++)
51                 {
52                         if (n(x,y) < min) min = n(x,y);
53                         if (n(x,y) > max) max = n(x,y);
54                 }
55         max -= min;
56         // normalize noise and copy to output
57         for (y = 0;y < size;y++)
58                 for (x = 0;x < size;x++)
59                         *noise++ = (n(x,y) - min) * 255 / max;
60         qfree(noisebuf);
61 #undef n
62 }