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

# 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     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