ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/noise.C
Revision: 1.2
Committed: Fri Apr 22 02:03:10 2011 UTC (13 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.1: +199 -7 lines
Log Message:
move gridmap to arch, refactor cf.pm a bit

File Contents

# User Rev Content
1 root 1.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 root 1.2 /////////////////////////////////////////////////////////////////////////////
26    
27     noise2d::noise2d (uint32_t seed)
28 root 1.1 {
29     seedable_rand_gen rng (seed);
30    
31     for (int i = 0; i < 256; ++i)
32     {
33     for (int j = 0; j < 2; ++j)
34     rvec [i][j] = rng () - 0.5f;
35    
36     // normalise
37     float mag = 1.f / sqrtf (rvec [i][0] * rvec [i][0] + rvec [i][1] * rvec [i][1]);
38    
39     rvec [i][0] *= mag;
40     rvec [i][1] *= mag;
41     }
42    
43     rvmap [0].seed (rng);
44     rvmap [1].seed (rng);
45     }
46    
47     float
48 root 1.2 noise2d::noise (float x, float y)
49 root 1.1 {
50     int ix = floorf (x); float fx = x - ix;
51     int iy = floorf (y); float fy = y - iy;
52    
53     float v = 0;
54    
55     for (int j = -1; j <= 2; ++j)
56     for (int i = -1; i <= 2; ++i)
57     {
58     float Ax = fx - i;
59     float Ay = fy - j;
60    
61 root 1.2 float d = Ax * Ax + Ay * Ay;
62 root 1.1
63     if (d < 4)
64     {
65     int h = rvmap [0](ix + i) ^ rvmap [1](iy + j);
66     float *G = rvec [h & 0xff];
67    
68     float t1 = 1 - d / 4;
69     float t2 = t1 * t1;
70     float t4 = t2 * t2;
71    
72     float p = (4 * t1 - 3) * t4;
73     v += (Ax * G[0] + Ay * G[1]) * p;
74     }
75     }
76    
77     return clamp (v * 2, -.9999999f, .9999999f);
78     }
79    
80 root 1.2 #if 0||ABSTRACTION_PENALTY_IS_GONE
81     float
82     noise2d::noise (float x, float y)
83     {
84     vec2d X = vec2d (x, y);
85     gen_vec<2,int> I = floor (X);
86     vec2d F = X - I;
87    
88     float v = 0;
89    
90     for (int j = -1; j <= 2; ++j)
91     for (int i = -1; i <= 2; ++i)
92     {
93     vec2d A = F - vec2d (i, j);
94    
95     float d = A * A;
96    
97     if (d < 4)
98     {
99     int h = rvmap [0](I[0] + i) ^ rvmap [1](I[1] + j);
100     float *G = rvec [h & 0xff];
101    
102     float t1 = 1 - d / 4;
103     float t2 = t1 * t1;
104     float t4 = t2 * t2;
105    
106     float p = (4 * t1 - 3) * t4;
107     v += A * vec2d (G[0], G[1]) * p;
108     }
109     }
110    
111     return clamp (v * 2, -.9999999f, .9999999f);
112     }
113     #endif
114    
115     /////////////////////////////////////////////////////////////////////////////
116    
117     noise3d::noise3d (uint32_t seed)
118     {
119     seedable_rand_gen rng (seed);
120    
121     for (int i = 0; i < 256; ++i)
122     {
123     for (int j = 0; j < 3; ++j)
124     rvec [i][j] = rng () - 0.5f;
125    
126     // normalise
127     float mag = 1.f / sqrtf (rvec [i][0] * rvec [i][0]
128     + rvec [i][1] * rvec [i][1]
129     + rvec [i][2] * rvec [i][2]);
130    
131     rvec [i][0] *= mag;
132     rvec [i][1] *= mag;
133     rvec [i][2] *= mag;
134     }
135    
136     rvmap [0].seed (rng);
137     rvmap [1].seed (rng);
138     rvmap [2].seed (rng);
139     }
140    
141     float
142     noise3d::noise (float x, float y, float z)
143     {
144     int ix = floorf (x); float fx = x - ix;
145     int iy = floorf (y); float fy = y - iy;
146     int iz = floorf (z); float fz = z - iz;
147    
148     float v = 0;
149    
150     for (int j = -1; j <= 2; ++j)
151     for (int i = -1; i <= 2; ++i)
152     for (int k = -1; k <= 2; ++k)
153     {
154     float Ax = fx - i;
155     float Ay = fy - j;
156     float Az = fz - k;
157    
158     float d = Ax * Ax + Ay * Ay + Az * Az;
159    
160     if (d < 4)
161     {
162     int h = rvmap [0](ix + i) ^ rvmap [1](iy + j) ^ rvmap [2](iz + k);
163     float *G = rvec [h & 0xff];
164    
165     float t1 = 1 - d / 4;
166     float t2 = t1 * t1;
167     float t4 = t2 * t2;
168    
169     // (4t⁵ - 3t⁴)
170     float p = (4 * t1 - 3) * t4;
171     v += (Ax * G[0] + Ay * G[1] + Az * G[2]) * p;
172     }
173     }
174    
175     return clamp (v * 2, -.9999999f, .9999999f);
176     }
177    
178     float
179     noise3d::noise (float x, float y, float z, float nx, float ny, float nz)
180     {
181     int ix = floorf (x); float fx = x - ix;
182     int iy = floorf (y); float fy = y - iy;
183     int iz = floorf (z); float fz = z - iz;
184    
185     float v = 0;
186    
187     for (int j = -1; j <= 2; ++j)
188     for (int i = -1; i <= 2; ++i)
189     for (int k = -1; k <= 2; ++k)
190     {
191     float Dx = fx - i;
192     float Dy = fy - j;
193     float Dz = fz - k;
194    
195     float e = Dx * nx + Dy * ny + Dz * nz;
196    
197     float o = 1 - abs (e);
198    
199     if (o > 0)
200     {
201     float Ax = Dx - e * nx;
202     float Ay = Dy - e * ny;
203     float Az = Dz - e * nz;
204    
205     float d = Ax * Ax + Ay * Ay + Az * Az;
206    
207     if (d < 4)
208     {
209     int h = rvmap [0](ix + i) ^ rvmap [1](iy + j) ^ rvmap [2](iz + k);
210     float *G = rvec [h & 0xff];
211    
212     float t1 = 1 - d / 4;
213     float t2 = t1 * t1;
214     float t4 = t2 * t2;
215    
216     float o2 = o * o;
217    
218     // (4t⁵ - 3t⁴) * (3o³ - 2o²)
219     float p = (4 * t1 - 3) * t4 * (3 * o2 - 2 * o2 * o);
220     v += (Ax * G[0] + Ay * G[1] + Az * G[2]) * p;
221     }
222     }
223     }
224    
225     return clamp (v * 2, -.9999999f, .9999999f);
226     }
227    
228 root 1.1 frac_gen::frac_gen (float hurst_expo, float lacunarity)
229 root 1.2 : h (hurst_expo), lac (lacunarity), noise2d (0)
230 root 1.1 {
231     float exsum = 0;
232    
233     for (int i = 0; i < MAX_OCTAVES; ++i)
234     {
235     ex [i] = powf (lac, -h * i);
236     exsum += ex [i];
237     fbm_mul [i] = 0.5f / (exsum * 0.75f); // .75f is a heuristic
238     rot [i].set (0.4488f * i);
239     }
240     }
241    
242     float
243     frac_gen::fBm (float x, float y, int octaves)
244     {
245     float v = 0.f;
246    
247     for (int i = 0; i < octaves; ++i)
248     {
249     rot [i](x, y);
250    
251     v += noise (x + i, y) * ex [i];
252    
253     x *= lac;
254     y *= lac;
255     }
256    
257     return clamp (v * fbm_mul [octaves - 1] + 0.5f, 0.f, .9999999f);
258     }
259    
260     float
261     frac_gen::turbulence (float x, float y, int octaves)
262     {
263     float v = 0.f;
264    
265     for (int i = 0; i < octaves; ++i)
266     {
267     rot [i](x, y);
268    
269     v += fabsf (noise (x + i, y)) * ex [i];
270    
271     x *= lac;
272     y *= lac;
273     }
274    
275     return clamp (v * fbm_mul [octaves - 1] * 2.f, 0.f, .9999999f);
276     }
277    
278     float
279     frac_gen::multifractal (float x, float y, int octaves, float offset)
280     {
281     float v = 1.f;
282    
283     for (int i = 0; i < octaves; ++i)
284     {
285     rot [i](x, y);
286    
287     v *= noise (x, y) * ex [i] + offset;
288    
289     x *= lac;
290     y *= lac;
291     }
292    
293     return clamp (v * 0.5f, 0.f, .9999999f);
294     }
295    
296     float
297     frac_gen::heterofractal (float x, float y, int octaves, float offset)
298     {
299     float v = noise (x, y) + offset;
300     int i;
301    
302     for (i = 1; i < octaves; ++i)
303     {
304     rot [i](x, y);
305    
306     x *= lac;
307     y *= lac;
308    
309     v += v * (noise (x, y) * ex [i] + offset);
310     }
311    
312     return v / powf (2., octaves);
313     }
314    
315     float
316     frac_gen::hybridfractal (float x, float y, int octaves, float offset, float gain)
317     {
318     float v = (noise (x, y) + offset) * ex [0];
319     float weight = v;
320     int i;
321    
322     for (i = 1; i < octaves; ++i)
323     {
324     rot [i](x, y);
325    
326     x *= lac;
327     y *= lac;
328    
329     min_it (weight, 1.f);
330    
331     float sig = (noise (x, y) + offset) * ex [i];
332     v += weight * sig;
333     weight *= gain * sig;
334     }
335    
336     return clamp (v * 0.5f + 0.5f, 0.f, .9999999f);
337     }
338    
339     // http://www.gamasutra.com/view/feature/3098/a_realtime_procedural_universe_.php?page=2
340     float
341     frac_gen::terrain (float x, float y, int octaves)
342     {
343     float v = 0.f;
344    
345     for (int i = 0; i < octaves; ++i)
346     {
347     rot[i] (x, y);
348    
349     v += noise (x + i, y) * ex [i];
350    
351     x *= lac;
352     y *= lac;
353     }
354    
355     v *= fbm_mul [octaves - 1];
356    
357     return v <= 0.f ? - powf (-v, 0.7f) : powf (v, 1. + noise (x, y) * v);
358     }
359    
360     float
361     frac_gen::terrain2 (float x, float y, int octaves)
362     {
363     float a = fBm (x, y, octaves);
364     float b = ridgedmultifractal (x, y, octaves, 1, 8);
365     float fade = fBm (x + 10.3, y + 10.3, octaves);
366    
367     const float width = 0.05f;
368    
369     if (fade > 0.5f + width)
370     return a;
371     else if (fade < 0.5f - width)
372     return b;
373    
374     fade = (fade - 0.5f + width) / (width * 2);
375    
376     // sigmoidal curve
377     fade = fade * fade * 2 * (1.5f - fade);
378    
379     return a * fade + b * (1 - fade);
380     }
381    
382     float
383     frac_gen::ridgedmultifractal (float x, float y, int octaves, float offset, float gain)
384     {
385     float sig = offset - fabsf (noise (x, y));
386     sig *= sig;
387     float v = sig;
388    
389     for (int i = 1; i < octaves; ++i)
390     {
391     rot [i](x, y);
392    
393     x *= lac;
394     y *= lac;
395    
396     float w = clamp (sig * gain, 0.f, 1.f);
397    
398     sig = offset - fabsf (noise (x, y));
399     sig *= sig;
400     sig *= w;
401    
402     v += sig * ex [i];
403     }
404    
405     return clamp (v * 0.25f, 0.f, .9999999f);
406     }
407    
408     #if 0
409     void hack()
410     {
411     frac_gen gen (0.5, 2);
412 root 1.2 noise3d n(0);
413 root 1.1
414 root 1.2 #if 0
415 root 1.1 int N = 1024;
416    
417 root 1.2 printf ("P6 %d %d 255\n", N, N);
418 root 1.1 // pmake&&server/deliantra-server >x&&convert -depth 8 -size 512xx512 gray:x x.ppm&& cv x.ppm
419     for (int y = 0; y < N; ++y)
420     {
421     if (!(y&63))fprintf (stderr, "y %d\n", y);//D
422     for (int x = 0; x < N; ++x)
423     {
424 root 1.2 putc (128 + 128 * n.noise (x * 0.04 + 0.2, y * 0.04 + 0.2), stdout);
425     putc (128 + 128 * n.noise (x * 0.04 + 0.2, y * 0.08 + 0.2), stdout);
426     putc (128 + 128 * n.noise (x * 0.08 + 0.2, y * 0.04 + 0.2), stdout);
427     //putc (256 * gen.terrain2 (x * 0.004, y * 0.004, 8), stdout);
428 root 1.1 //putc (256 * gen.fBm (x * 0.001, y * 0.001, 3), stdout);
429     //putc (256 * gen.turbulence (x * 0.004 - 1, y * 0.004 - 1, 8), stdout);
430     //putc (256 * gen.heterofractal (x * 0.008, y * 0.008, 8, -1.1, 2.0), stdout);
431     //putc (256 * gen.ridgedmultifractal (x * 0.001, y * 0.001, 32, 1.001, 32), stdout);
432     }
433     }
434 root 1.2 #else
435     int N = 128;
436    
437     //printf ("P6 %d %d 255\n", N, N);
438     // pmake&&server/deliantra-server >x&&convert -depth 8 -size 512xx512 gray:x x.ppm&& cv x.ppm
439     for (int z = 0; z < N; ++z)
440     {
441     if (!(z&4))fprintf (stderr, "z %d\n", z);//D
442     for (int y = 0; y < N; ++y)
443     for (int x = 0; x < N; ++x)
444     {
445     float v = n.noise (x * 0.06 + 0.2, y * 0.06 + 0.2, z * 0.06 + 0.2) * 0.5 + 0.5;
446    
447     if (z < 64)
448     v = v * (z * z) / (64 * 64);
449    
450     if (v <= 0.1)
451     continue;
452    
453     float r[4];
454     int i[4];
455    
456     r[0] = x;
457     r[1] = y;
458     r[2] = z;
459     r[3] = v;
460    
461     memcpy (i, r, 16);
462    
463     i[0] = htonl (i[0]);
464     i[1] = htonl (i[1]);
465     i[2] = htonl (i[2]);
466     i[3] = htonl (i[3]);
467    
468     fwrite (i, 4*4, 1, stdout);
469     }
470     }
471     #endif
472 root 1.1
473     exit (0);
474     }
475     #endif