ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/noise.C
Revision: 1.1
Committed: Sun Jul 11 04:01:48 2010 UTC (13 years, 11 months ago) by root
Content type: text/plain
Branch: MAIN
Log Message:
add noise library, as of yet, unused

File Contents

# Content
1 /*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 *
4 * Copyright (©) 2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 *
6 * Deliantra is free software: you can redistribute it and/or modify it under
7 * the terms of the Affero GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the Affero GNU General Public License
17 * and the GNU General Public License along with this program. If not, see
18 * <http://www.gnu.org/licenses/>.
19 *
20 * The authors can be reached via e-mail to <support@deliantra.net>
21 */
22
23 #include "noise.h"
24
25 noise_gen::noise_gen (uint32_t seed)
26 {
27 seedable_rand_gen rng (seed);
28
29 for (int i = 0; i < 256; ++i)
30 {
31 for (int j = 0; j < 2; ++j)
32 rvec [i][j] = rng () - 0.5f;
33
34 // normalise
35 float mag = 1.f / sqrtf (rvec [i][0] * rvec [i][0] + rvec [i][1] * rvec [i][1]);
36
37 rvec [i][0] *= mag;
38 rvec [i][1] *= mag;
39 }
40
41 rvmap [0].seed (rng);
42 rvmap [1].seed (rng);
43 }
44
45 float
46 noise_gen::noise (float x, float y)
47 {
48 int ix = floorf (x); float fx = x - ix;
49 int iy = floorf (y); float fy = y - iy;
50
51 float v = 0;
52
53 for (int j = -1; j <= 2; ++j)
54 for (int i = -1; i <= 2; ++i)
55 {
56 float Ax = fx - i;
57 float Ay = fy - j;
58
59 float d = Ax * Ax + Ay * Ay;
60
61 if (d < 4)
62 {
63 int h = rvmap [0](ix + i) ^ rvmap [1](iy + j);
64 float *G = rvec [h & 0xff];
65
66 float t1 = 1 - d / 4;
67 float t2 = t1 * t1;
68 float t4 = t2 * t2;
69
70 float p = (4 * t1 - 3) * t4;
71 v += (Ax * G[0] + Ay * G[1]) * p;
72 }
73 }
74
75 return clamp (v * 2, -.9999999f, .9999999f);
76 }
77
78 frac_gen::frac_gen (float hurst_expo, float lacunarity)
79 : h (hurst_expo), lac (lacunarity), noise_gen (0)
80 {
81 float exsum = 0;
82
83 for (int i = 0; i < MAX_OCTAVES; ++i)
84 {
85 ex [i] = powf (lac, -h * i);
86 exsum += ex [i];
87 fbm_mul [i] = 0.5f / (exsum * 0.75f); // .75f is a heuristic
88 rot [i].set (0.4488f * i);
89 }
90 }
91
92 float
93 frac_gen::fBm (float x, float y, int octaves)
94 {
95 float v = 0.f;
96
97 for (int i = 0; i < octaves; ++i)
98 {
99 rot [i](x, y);
100
101 v += noise (x + i, y) * ex [i];
102
103 x *= lac;
104 y *= lac;
105 }
106
107 return clamp (v * fbm_mul [octaves - 1] + 0.5f, 0.f, .9999999f);
108 }
109
110 float
111 frac_gen::turbulence (float x, float y, int octaves)
112 {
113 float v = 0.f;
114
115 for (int i = 0; i < octaves; ++i)
116 {
117 rot [i](x, y);
118
119 v += fabsf (noise (x + i, y)) * ex [i];
120
121 x *= lac;
122 y *= lac;
123 }
124
125 return clamp (v * fbm_mul [octaves - 1] * 2.f, 0.f, .9999999f);
126 }
127
128 float
129 frac_gen::multifractal (float x, float y, int octaves, float offset)
130 {
131 float v = 1.f;
132
133 for (int i = 0; i < octaves; ++i)
134 {
135 rot [i](x, y);
136
137 v *= noise (x, y) * ex [i] + offset;
138
139 x *= lac;
140 y *= lac;
141 }
142
143 return clamp (v * 0.5f, 0.f, .9999999f);
144 }
145
146 float
147 frac_gen::heterofractal (float x, float y, int octaves, float offset)
148 {
149 float v = noise (x, y) + offset;
150 int i;
151
152 for (i = 1; i < octaves; ++i)
153 {
154 rot [i](x, y);
155
156 x *= lac;
157 y *= lac;
158
159 v += v * (noise (x, y) * ex [i] + offset);
160 }
161
162 return v / powf (2., octaves);
163 }
164
165 float
166 frac_gen::hybridfractal (float x, float y, int octaves, float offset, float gain)
167 {
168 float v = (noise (x, y) + offset) * ex [0];
169 float weight = v;
170 int i;
171
172 for (i = 1; i < octaves; ++i)
173 {
174 rot [i](x, y);
175
176 x *= lac;
177 y *= lac;
178
179 min_it (weight, 1.f);
180
181 float sig = (noise (x, y) + offset) * ex [i];
182 v += weight * sig;
183 weight *= gain * sig;
184 }
185
186 return clamp (v * 0.5f + 0.5f, 0.f, .9999999f);
187 }
188
189 // http://www.gamasutra.com/view/feature/3098/a_realtime_procedural_universe_.php?page=2
190 float
191 frac_gen::terrain (float x, float y, int octaves)
192 {
193 float v = 0.f;
194
195 for (int i = 0; i < octaves; ++i)
196 {
197 rot[i] (x, y);
198
199 v += noise (x + i, y) * ex [i];
200
201 x *= lac;
202 y *= lac;
203 }
204
205 v *= fbm_mul [octaves - 1];
206
207 return v <= 0.f ? - powf (-v, 0.7f) : powf (v, 1. + noise (x, y) * v);
208 }
209
210 float
211 frac_gen::terrain2 (float x, float y, int octaves)
212 {
213 float a = fBm (x, y, octaves);
214 float b = ridgedmultifractal (x, y, octaves, 1, 8);
215 float fade = fBm (x + 10.3, y + 10.3, octaves);
216
217 const float width = 0.05f;
218
219 if (fade > 0.5f + width)
220 return a;
221 else if (fade < 0.5f - width)
222 return b;
223
224 fade = (fade - 0.5f + width) / (width * 2);
225
226 // sigmoidal curve
227 fade = fade * fade * 2 * (1.5f - fade);
228
229 return a * fade + b * (1 - fade);
230 }
231
232 float
233 frac_gen::ridgedmultifractal (float x, float y, int octaves, float offset, float gain)
234 {
235 float sig = offset - fabsf (noise (x, y));
236 sig *= sig;
237 float v = sig;
238
239 for (int i = 1; i < octaves; ++i)
240 {
241 rot [i](x, y);
242
243 x *= lac;
244 y *= lac;
245
246 float w = clamp (sig * gain, 0.f, 1.f);
247
248 sig = offset - fabsf (noise (x, y));
249 sig *= sig;
250 sig *= w;
251
252 v += sig * ex [i];
253 }
254
255 return clamp (v * 0.25f, 0.f, .9999999f);
256 }
257
258 #if 0
259 void hack()
260 {
261 frac_gen gen (0.5, 2);
262
263 int N = 1024;
264
265 printf ("P5 %d %d 255\n", N, N);
266 // pmake&&server/deliantra-server >x&&convert -depth 8 -size 512xx512 gray:x x.ppm&& cv x.ppm
267 for (int y = 0; y < N; ++y)
268 {
269 if (!(y&63))fprintf (stderr, "y %d\n", y);//D
270 for (int x = 0; x < N; ++x)
271 {
272 //putc (128 + 128 * gen.noise (x * 0.04, y * 0.04), stdout);
273 putc (256 * gen.terrain2 (x * 0.004, y * 0.004, 8), stdout);
274 //putc (256 * gen.fBm (x * 0.001, y * 0.001, 3), stdout);
275 //putc (256 * gen.turbulence (x * 0.004 - 1, y * 0.004 - 1, 8), stdout);
276 //putc (256 * gen.heterofractal (x * 0.008, y * 0.008, 8, -1.1, 2.0), stdout);
277 //putc (256 * gen.ridgedmultifractal (x * 0.001, y * 0.001, 32, 1.001, 32), stdout);
278 }
279 }
280
281 exit (0);
282 }
283 #endif