1 /* coherent noise function over 1, 2 or 3 dimensions */
2 /* (copyright Ken Perlin) */
3
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <math.h>
7 #include <time.h>
8
9 #include "perlin.h"
10
11 #define B SAMPLE_SIZE
12 #define BM (SAMPLE_SIZE-1)
13
14 #define N 0x1000
15 #define NP 12 /* 2^N */
16 #define NM 0xfff
17
18 #define s_curve(t) ( t * t * (3.0f - 2.0f * t) )
19 #define lerp(t, a, b) ( a + t * (b - a) )
20
21 #define setup(i,b0,b1,r0,r1)\
22 t = vec[i] + N;\
23 b0 = ((int)t) & BM;\
24 b1 = (b0+1) & BM;\
25 r0 = t - (int)t;\
26 r1 = r0 - 1.0f;
27
noise1(float arg)28 float Perlin::noise1(float arg)
29 {
30 int bx0, bx1;
31 float rx0, rx1, sx, t, u, v, vec[1];
32
33 vec[0] = arg;
34
35 if (mStart)
36 {
37 srand(mSeed);
38 mStart = false;
39 init();
40 }
41
42 setup(0, bx0,bx1, rx0,rx1);
43
44 sx = s_curve(rx0);
45
46 u = rx0 * g1[ p[ bx0 ] ];
47 v = rx1 * g1[ p[ bx1 ] ];
48
49 return lerp(sx, u, v);
50 }
51
noise2(float vec[2])52 float Perlin::noise2(float vec[2])
53 {
54 int bx0, bx1, by0, by1, b00, b10, b01, b11;
55 float rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
56 int i, j;
57
58 if (mStart)
59 {
60 srand(mSeed);
61 mStart = false;
62 init();
63 }
64
65 setup(0,bx0,bx1,rx0,rx1);
66 setup(1,by0,by1,ry0,ry1);
67
68 i = p[bx0];
69 j = p[bx1];
70
71 b00 = p[i + by0];
72 b10 = p[j + by0];
73 b01 = p[i + by1];
74 b11 = p[j + by1];
75
76 sx = s_curve(rx0);
77 sy = s_curve(ry0);
78
79 #define at2(rx,ry) ( rx * q[0] + ry * q[1] )
80
81 q = g2[b00];
82 u = at2(rx0,ry0);
83 q = g2[b10];
84 v = at2(rx1,ry0);
85 a = lerp(sx, u, v);
86
87 q = g2[b01];
88 u = at2(rx0,ry1);
89 q = g2[b11];
90 v = at2(rx1,ry1);
91 b = lerp(sx, u, v);
92
93 return lerp(sy, a, b);
94 }
95
noise3(float vec[3])96 float Perlin::noise3(float vec[3])
97 {
98 int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
99 float rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
100 int i, j;
101
102 if (mStart)
103 {
104 srand(mSeed);
105 mStart = false;
106 init();
107 }
108
109 setup(0, bx0,bx1, rx0,rx1);
110 setup(1, by0,by1, ry0,ry1);
111 setup(2, bz0,bz1, rz0,rz1);
112
113 i = p[ bx0 ];
114 j = p[ bx1 ];
115
116 b00 = p[ i + by0 ];
117 b10 = p[ j + by0 ];
118 b01 = p[ i + by1 ];
119 b11 = p[ j + by1 ];
120
121 t = s_curve(rx0);
122 sy = s_curve(ry0);
123 sz = s_curve(rz0);
124
125 #define at3(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
126
127 q = g3[ b00 + bz0 ] ; u = at3(rx0,ry0,rz0);
128 q = g3[ b10 + bz0 ] ; v = at3(rx1,ry0,rz0);
129 a = lerp(t, u, v);
130
131 q = g3[ b01 + bz0 ] ; u = at3(rx0,ry1,rz0);
132 q = g3[ b11 + bz0 ] ; v = at3(rx1,ry1,rz0);
133 b = lerp(t, u, v);
134
135 c = lerp(sy, a, b);
136
137 q = g3[ b00 + bz1 ] ; u = at3(rx0,ry0,rz1);
138 q = g3[ b10 + bz1 ] ; v = at3(rx1,ry0,rz1);
139 a = lerp(t, u, v);
140
141 q = g3[ b01 + bz1 ] ; u = at3(rx0,ry1,rz1);
142 q = g3[ b11 + bz1 ] ; v = at3(rx1,ry1,rz1);
143 b = lerp(t, u, v);
144
145 d = lerp(sy, a, b);
146
147 return lerp(sz, c, d);
148 }
149
normalize2(float v[2])150 void Perlin::normalize2(float v[2])
151 {
152 float s;
153
154 s = (float)sqrt(v[0] * v[0] + v[1] * v[1]);
155 s = 1.0f/s;
156 v[0] = v[0] * s;
157 v[1] = v[1] * s;
158 }
159
normalize3(float v[3])160 void Perlin::normalize3(float v[3])
161 {
162 float s;
163
164 s = (float)sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
165 s = 1.0f/s;
166
167 v[0] = v[0] * s;
168 v[1] = v[1] * s;
169 v[2] = v[2] * s;
170 }
171
init(void)172 void Perlin::init(void)
173 {
174 int i, j, k;
175
176 for (i = 0 ; i < B ; i++)
177 {
178 p[i] = i;
179 g1[i] = (float)((rand() % (B + B)) - B) / B;
180 for (j = 0 ; j < 2 ; j++)
181 g2[i][j] = (float)((rand() % (B + B)) - B) / B;
182 normalize2(g2[i]);
183 for (j = 0 ; j < 3 ; j++)
184 g3[i][j] = (float)((rand() % (B + B)) - B) / B;
185 normalize3(g3[i]);
186 }
187
188 while (--i)
189 {
190 k = p[i];
191 p[i] = p[j = rand() % B];
192 p[j] = k;
193 }
194
195 for (i = 0 ; i < B + 2 ; i++)
196 {
197 p[B + i] = p[i];
198 g1[B + i] = g1[i];
199 for (j = 0 ; j < 2 ; j++)
200 g2[B + i][j] = g2[i][j];
201 for (j = 0 ; j < 3 ; j++)
202 g3[B + i][j] = g3[i][j];
203 }
204
205 }
206
207
perlin_noise_2D(float vec[2])208 float Perlin::perlin_noise_2D(float vec[2])
209 {
210 int terms = mOctaves;
211 float freq = mFrequency;
212 float result = 0.0f;
213 float amp = mAmplitude;
214
215 vec[0]*=freq;
216 vec[1]*=freq;
217
218 for( int i=0; i<terms; i++ )
219 {
220 result += noise2(vec)*amp;
221 vec[0] *= 2.0f;
222 vec[1] *= 2.0f;
223 amp*=0.5f;
224 }
225
226
227 return result;
228 }
229
230
231
Perlin(int octaves,float freq,float amp,int seed)232 Perlin::Perlin(int octaves,float freq,float amp,int seed)
233 {
234 mOctaves = octaves;
235 mFrequency = freq;
236 mAmplitude = amp;
237 mSeed = seed;
238 mStart = true;
239 }
240
~Perlin()241 Perlin::~Perlin()
242 {
243 srand(time(NULL));
244 }