ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/quadland.C
Revision: 1.1
Committed: Sun May 1 13:18:24 2011 UTC (13 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Log Message:
*** empty log message ***

File Contents

# Content
1 /*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 *
4 * Copyright (©) 2011 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 <global.h>
24
25 #include "noise.h"
26
27 #define FANCY_GRAPHICS 1
28
29 static void
30 gen_quadspace (int x, int y, int z)
31 {
32 vec2d P = vec2d (x, y);
33
34 const int deep_sea_z = -200;
35
36 static frac2d gen(13);
37
38 static frac2d vec_gen1 (6, 2, 0.5, 1);
39 static frac2d vec_gen2 (6, 2, 0.5, 2);
40
41 const float continent_scale = 0.00008;
42
43 vec2d perturb_pos = pow (P, 1.4) * 1e-5;
44
45 vec2d perturb (
46 vec_gen1.fBm (perturb_pos),
47 vec_gen2.fBm (perturb_pos)
48 );
49
50 float perturb_perturb = 1 - (P[1] - P[0]) * (1. / 25000 / 2);
51 perturb_perturb = perturb_perturb * perturb_perturb * 0.4;
52 perturb *= perturb_perturb;
53
54 vec2d P_continent = P * continent_scale + perturb;
55
56 static frac2d continent_gen (13, 2.13, 0.5);
57 float continent = continent_gen.fBm (P_continent) + 0.05f;
58
59 float x_gradient = P[0] * (1. / 25000);
60 float y_gradient = P[1] * (1. / 25000);
61 float xy_gradient = (P[0] + P[1]) * (0.5 / 25000);
62
63 const float N = (25000 - 1) * continent_scale;
64
65 // we clip a large border on the perturbed shape, to get irregular coastline
66 // and then clip a smaller border around the real shape
67 continent = border_blend (-1.f, continent, P_continent , N, 400 * continent_scale);
68 continent = border_blend (-1.f, continent, P * continent_scale + perturb * 0.1, N, 100 * continent_scale);
69
70 enum {
71 T_NONE,
72 T_OCEAN,
73 T_RIVER,
74 T_VALLEY,
75 T_MOUNTAIN,
76 T_UNDERGROUND,
77 T_ACQUIFER,
78 } t = T_NONE;
79
80 vec3d c;
81 int h = 1000000; // height form heightmap
82
83 // the continent increases in height from 0 to ~700 levels in the absence of anything else
84 // thats about one step every 7 maps.
85 int base_height = blend (0, 300, xy_gradient, 0.2f, 0.9f);
86 int river_height = base_height * 9 / 10;
87
88 // add this to rivers to "dry them out"
89 float dry_out = max (0.f, lerp (xy_gradient, 0.7f, 1.f, 0.f, 0.3f));
90
91 static frac2d river_gen (2);
92 float river1 = abs (river_gen.fBm (P * 0.001 + perturb * 4)) + dry_out;
93 float river2 = river_gen.ridgedmultifractal (P * 0.04, 0.8, 10) - y_gradient * 0.2 - 0.16 - dry_out;
94
95 float valley = river1 - 0.2f;
96
97 static frac2d mountain_gen (8, 2.14, 0.5);
98 float mountain = mountain_gen.ridgedmultifractal (P * 0.004);
99
100 //TODO: mountains should not lower the height, should they?
101 t = valley < 0 ? T_VALLEY : T_MOUNTAIN;
102 c = blend0 (vec3d (0, 0.8, 0), vec3d (0.8, 0, 0), valley, 0.1f);
103 h = blend0 (base_height + continent * 300, base_height + mountain * xy_gradient * 400, valley, 0.1f);
104
105 if (river1 < 0.01f)
106 {
107 // main rivers - they cut deeply into the mountains (base_height * 0.9f)
108 t = T_RIVER;
109 c = vec3d (0.2, 0.2, 1);
110 min_it (h, river_height + lerp<float> (river1, 0.f, 0.01f, -20, -1));
111 }
112
113 if (river2 > 0)
114 {
115 t = T_RIVER;
116 c = vec3d (0.2, 0.2, 1);
117 min_it (h, river_height + lerp<float> (river1, 0.f, 0.01f, -5, -1));
118 }
119
120 if (continent < 0)
121 {
122 t = T_OCEAN;
123 min_it (h, min (continent * 200, -1));
124 c = vec3d (0, 0, 1);
125 }
126
127 // now we have the base height, and base terrain
128
129 #if FANCY_GRAPHICS
130 z = h; // show the surface, not the given z layer
131 #endif
132
133 // everything below the surface is underground, or a variant
134 if (z < h)
135 {
136 t = T_UNDERGROUND;
137 }
138
139 // put acquifers a bit below the surface, to reduce them leaking out (will still happen)
140 if (z < h - 3)
141 {
142 static frac3d acquifer_gen (4);
143 float acquifer = acquifer_gen.ridgedmultifractal (vec3d (x * 0.001, y * 0.001, z * 0.01), 1.003, 2);
144
145 if (acquifer > 0.48)
146 {
147 t = T_ACQUIFER;
148 c = vec3d (1,1,1);
149 }
150 }
151
152 // TODO: caves
153 // TODO: chees areas
154 // TODO: minerals
155 // TODO: monsters
156
157 #if FANCY_GRAPHICS
158 float v = clamp (lerp<float> (h, deep_sea_z, 800, 0.f, 1.f), 0.f, 1.f);
159 c *= v;
160
161 putc (clamp<int> (255 * c[0], 0, 255), stdout);
162 putc (clamp<int> (255 * c[1], 0, 255), stdout);
163 putc (clamp<int> (255 * c[2], 0, 255), stdout);
164 #endif
165 }
166
167 void noise_test ();
168 void noise_test ()
169 {
170 #if 0
171 int Nw = 700;
172
173 printf ("P6 %d %d 255\n", Nw * 3, Nw * 2);
174 // pmake&&server/deliantra-server >x&&convert -depth 8 -size 512xx512 gray:x x.ppm&& cv x.ppm
175 for (int y = 0; y < Nw; ++y)
176 {
177 if (!(y&63))fprintf (stderr, "y %d\n", y * 50 / Nw);//D
178
179 for (int x = 0; x < Nw; ++x) gen_quadspace (x * 25000 / Nw, y * 25000 / Nw, 0);
180
181 for (int x = 0; x < Nw; ++x) gen_quadspace (x + 400, y, 0);
182 for (int x = 0; x < Nw; ++x) gen_quadspace (x + 22000, y + 2000, 0);
183 }
184 for (int y = 0; y < Nw; ++y)
185 {
186 if (!(y&63))fprintf (stderr, "y %d\n", y * 50 / Nw+50);//D
187
188 for (int x = 0; x < Nw; ++x) gen_quadspace (x + 1000, y + 22000, 0);
189 for (int x = 0; x < Nw; ++x) gen_quadspace (x + 12500, y + 12500, 0);
190 for (int x = 0; x < Nw; ++x) gen_quadspace (x + 22000, y + 22500, 0);
191 }
192
193 //putc (127 * gen.noise (vec2d (x * 0.01, y * 0.01)) + 128, stdout);
194 //putc (256 * gen.terrain2 (x * 0.004, y * 0.004, 8), stdout);
195 //putc (256 * gen.fBm (vec2d(x * 0.01, y * 0.01), 16), stdout);
196 //putc (256 * gen.turbulence (vec2d (x * 0.004 - 1, y * 0.004 - 1), 10), stdout);
197 //putc (256 * gen.heterofractal (vec2d (x * 0.008, y * 0.008), 8, 0.9), stdout);
198 //putc (256 * gen.hybridfractal (vec2d (x * 0.01, y * 0.01), 8, -.4, -4), stdout);
199 //putc (256 * gen.fBm (vec2d (x * 0.002, y * 0.002), 2), stdout);
200 //putc (127.49 * gen.billowfractal (vec2d (x * 0.01, y * 0.01), 9) + 128, stdout);
201 #elif 1
202 int N = 25000;
203
204 printf ("P6 %d %d 255\n", N, N);
205 for (int y = 0; y < N; ++y)
206 {
207 if (!(y&63))fprintf (stderr, "y %d\n", y);//D
208
209 for (int x = 0; x < N; ++x) gen_quadspace (x, y, 0);
210 }
211 #else
212 int N = 200;
213
214 //printf ("P6 %d %d 255\n", N, N);
215 // pmake&&server/deliantra-server >x&&convert -depth 8 -size 512xx512 gray:x x.ppm&& cv x.ppm
216 for (int z = 0; z < N; ++z)
217 {
218 if (!(z&7))fprintf (stderr, "z %d\n", z);//D
219 for (int y = 0; y < N; ++y)
220 for (int x = 0; x < N; ++x)
221 {
222 #if 0
223 float v = gen3.ridgedmultifractal (vec3d (x * 0.001 + 0.2, y * 0.001 + 0.2, z * 0.01 + 0.2), 1.03, 2) * 2;
224
225 if (z < 64)
226 v = v * (z * z) / (64 * 64);
227
228 if (v <= 0.9)
229 continue;
230 #endif
231 static frac3d gen3 (10);
232 //float v = gen3.turbulence (vec3d (x * 0.01, y * 0.01, z * 0.01));
233 float v = gen3.ridgedmultifractal (vec3d (x * 0.001, y * 0.001, z * 0.001), 1.003, 2);
234
235 if (v <= 0.48) continue;
236
237 float r[4];
238 int i[4];
239
240 r[0] = x;
241 r[1] = y;
242 r[2] = z;
243 r[3] = v;
244
245 memcpy (i, r, 16);
246
247 i[0] = htonl (i[0]);
248 i[1] = htonl (i[1]);
249 i[2] = htonl (i[2]);
250 i[3] = htonl (i[3]);
251
252 fwrite (i, 4*4, 1, stdout);
253 }
254 }
255 #endif
256
257 exit (0);
258 }