rev |
line source |
nuclear@0
|
1 #include <stdlib.h>
|
nuclear@0
|
2 #include <math.h>
|
nuclear@0
|
3 #include "noise.h"
|
nuclear@0
|
4
|
nuclear@0
|
5 typedef struct vec2 {
|
nuclear@0
|
6 float x, y;
|
nuclear@0
|
7 } vec2_t;
|
nuclear@0
|
8
|
nuclear@0
|
9 typedef struct vec3 {
|
nuclear@0
|
10 float x, y, z;
|
nuclear@0
|
11 } vec3_t;
|
nuclear@0
|
12
|
nuclear@0
|
13 /* ---- Ken Perlin's implementation of noise ---- */
|
nuclear@0
|
14
|
nuclear@0
|
15 #define B 0x100
|
nuclear@0
|
16 #define BM 0xff
|
nuclear@0
|
17 #define N 0x1000
|
nuclear@0
|
18 #define NP 12 /* 2^N */
|
nuclear@0
|
19 #define NM 0xfff
|
nuclear@0
|
20
|
nuclear@0
|
21 #define lerp(a, b, t) ((a) + ((b) - (a)) * t)
|
nuclear@0
|
22 #define s_curve(t) (t * t * (3.0f - 2.0f * t))
|
nuclear@0
|
23
|
nuclear@0
|
24 #define setup(elem, b0, b1, r0, r1) \
|
nuclear@0
|
25 do { \
|
nuclear@0
|
26 float t = elem + N; \
|
nuclear@0
|
27 b0 = ((int)t) & BM; \
|
nuclear@0
|
28 b1 = (b0 + 1) & BM; \
|
nuclear@0
|
29 r0 = t - (int)t; \
|
nuclear@0
|
30 r1 = r0 - 1.0f; \
|
nuclear@0
|
31 } while(0)
|
nuclear@0
|
32
|
nuclear@0
|
33
|
nuclear@0
|
34 static int perm[B + B + 2]; /* permuted index from g_n onto themselves */
|
nuclear@0
|
35 static vec3_t grad3[B + B + 2]; /* 3D random gradients */
|
nuclear@0
|
36 static vec2_t grad2[B + B + 2]; /* 2D random gradients */
|
nuclear@0
|
37 static float grad1[B + B + 2]; /* 1D random ... slopes */
|
nuclear@0
|
38 static int tables_valid;
|
nuclear@0
|
39
|
nuclear@0
|
40 static vec2_t v2_normalize(vec2_t v)
|
nuclear@0
|
41 {
|
nuclear@0
|
42 vec2_t res;
|
nuclear@0
|
43 float len = sqrt(v.x * v.x + v.y * v.y);
|
nuclear@0
|
44 if(len != 0.0f) {
|
nuclear@0
|
45 res.x = v.x / len;
|
nuclear@0
|
46 res.y = v.y / len;
|
nuclear@0
|
47 } else {
|
nuclear@0
|
48 res = v;
|
nuclear@0
|
49 }
|
nuclear@0
|
50 return res;
|
nuclear@0
|
51 }
|
nuclear@0
|
52
|
nuclear@0
|
53 static vec3_t v3_normalize(vec3_t v)
|
nuclear@0
|
54 {
|
nuclear@0
|
55 vec3_t res;
|
nuclear@0
|
56 float len = sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
|
nuclear@0
|
57 if(len != 0.0f) {
|
nuclear@0
|
58 res.x = v.x / len;
|
nuclear@0
|
59 res.y = v.y / len;
|
nuclear@0
|
60 res.z = v.z / len;
|
nuclear@0
|
61 } else {
|
nuclear@0
|
62 res = v;
|
nuclear@0
|
63 }
|
nuclear@0
|
64 return res;
|
nuclear@0
|
65 }
|
nuclear@0
|
66
|
nuclear@0
|
67 static void init_noise()
|
nuclear@0
|
68 {
|
nuclear@0
|
69 int i;
|
nuclear@0
|
70
|
nuclear@0
|
71 /* calculate random gradients */
|
nuclear@0
|
72 for(i=0; i<B; i++) {
|
nuclear@0
|
73 perm[i] = i; /* .. and initialize permutation mapping to identity */
|
nuclear@0
|
74
|
nuclear@0
|
75 grad1[i] = (float)((rand() % (B + B)) - B) / B;
|
nuclear@0
|
76
|
nuclear@0
|
77 grad2[i].x = (float)((rand() % (B + B)) - B) / B;
|
nuclear@0
|
78 grad2[i].y = (float)((rand() % (B + B)) - B) / B;
|
nuclear@0
|
79 grad2[i] = v2_normalize(grad2[i]);
|
nuclear@0
|
80
|
nuclear@0
|
81 grad3[i].x = (float)((rand() % (B + B)) - B) / B;
|
nuclear@0
|
82 grad3[i].y = (float)((rand() % (B + B)) - B) / B;
|
nuclear@0
|
83 grad3[i].z = (float)((rand() % (B + B)) - B) / B;
|
nuclear@0
|
84 grad3[i] = v3_normalize(grad3[i]);
|
nuclear@0
|
85 }
|
nuclear@0
|
86
|
nuclear@0
|
87 /* permute indices by swapping them randomly */
|
nuclear@0
|
88 for(i=0; i<B; i++) {
|
nuclear@0
|
89 int rand_idx = rand() % B;
|
nuclear@0
|
90
|
nuclear@0
|
91 int tmp = perm[i];
|
nuclear@0
|
92 perm[i] = perm[rand_idx];
|
nuclear@0
|
93 perm[rand_idx] = tmp;
|
nuclear@0
|
94 }
|
nuclear@0
|
95
|
nuclear@0
|
96 /* fill up the rest of the arrays by duplicating the existing gradients */
|
nuclear@0
|
97 /* and permutations */
|
nuclear@0
|
98 for(i=0; i<B+2; i++) {
|
nuclear@0
|
99 perm[B + i] = perm[i];
|
nuclear@0
|
100 grad1[B + i] = grad1[i];
|
nuclear@0
|
101 grad2[B + i] = grad2[i];
|
nuclear@0
|
102 grad3[B + i] = grad3[i];
|
nuclear@0
|
103 }
|
nuclear@0
|
104 }
|
nuclear@0
|
105
|
nuclear@0
|
106
|
nuclear@0
|
107 float noise1(float x)
|
nuclear@0
|
108 {
|
nuclear@0
|
109 int bx0, bx1;
|
nuclear@0
|
110 float rx0, rx1, sx, u, v;
|
nuclear@0
|
111
|
nuclear@0
|
112 if(!tables_valid) {
|
nuclear@0
|
113 init_noise();
|
nuclear@0
|
114 tables_valid = 1;
|
nuclear@0
|
115 }
|
nuclear@0
|
116
|
nuclear@0
|
117 setup(x, bx0, bx1, rx0, rx1);
|
nuclear@0
|
118 sx = s_curve(rx0);
|
nuclear@0
|
119 u = rx0 * grad1[perm[bx0]];
|
nuclear@0
|
120 v = rx1 * grad1[perm[bx1]];
|
nuclear@0
|
121
|
nuclear@0
|
122 return lerp(u, v, sx);
|
nuclear@0
|
123 }
|
nuclear@0
|
124
|
nuclear@0
|
125 float fbm1(float x, int octaves)
|
nuclear@0
|
126 {
|
nuclear@0
|
127 int i;
|
nuclear@0
|
128 float res = 0.0f, freq = 1.0f;
|
nuclear@0
|
129 for(i=0; i<octaves; i++) {
|
nuclear@0
|
130 res += noise1(x * freq) / freq;
|
nuclear@0
|
131 freq *= 2.0f;
|
nuclear@0
|
132 }
|
nuclear@0
|
133 return res;
|
nuclear@0
|
134 }
|
nuclear@0
|
135
|
nuclear@0
|
136 float turbulence1(float x, int octaves)
|
nuclear@0
|
137 {
|
nuclear@0
|
138 int i;
|
nuclear@0
|
139 float res = 0.0f, freq = 1.0f;
|
nuclear@0
|
140 for(i=0; i<octaves; i++) {
|
nuclear@0
|
141 res += fabs(noise1(x * freq) / freq);
|
nuclear@0
|
142 freq *= 2.0f;
|
nuclear@0
|
143 }
|
nuclear@0
|
144 return res;
|
nuclear@0
|
145 }
|
nuclear@0
|
146
|