aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Terrain.BasicTerrain/TerrainEngine.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Terrain.BasicTerrain/TerrainEngine.cs1906
1 files changed, 953 insertions, 953 deletions
diff --git a/OpenSim/Region/Terrain.BasicTerrain/TerrainEngine.cs b/OpenSim/Region/Terrain.BasicTerrain/TerrainEngine.cs
index f017e44..6f3afea 100644
--- a/OpenSim/Region/Terrain.BasicTerrain/TerrainEngine.cs
+++ b/OpenSim/Region/Terrain.BasicTerrain/TerrainEngine.cs
@@ -1,954 +1,954 @@
1/* 1/*
2* Copyright (c) Contributors, http://www.openmetaverse.org/ 2* Copyright (c) Contributors, http://www.openmetaverse.org/
3* See CONTRIBUTORS.TXT for a full list of copyright holders. 3* See CONTRIBUTORS.TXT for a full list of copyright holders.
4* 4*
5* Redistribution and use in source and binary forms, with or without 5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met: 6* modification, are permitted provided that the following conditions are met:
7* * Redistributions of source code must retain the above copyright 7* * Redistributions of source code must retain the above copyright
8* notice, this list of conditions and the following disclaimer. 8* notice, this list of conditions and the following disclaimer.
9* * Redistributions in binary form must reproduce the above copyright 9* * Redistributions in binary form must reproduce the above copyright
10* notice, this list of conditions and the following disclaimer in the 10* notice, this list of conditions and the following disclaimer in the
11* documentation and/or other materials provided with the distribution. 11* documentation and/or other materials provided with the distribution.
12* * Neither the name of the OpenSim Project nor the 12* * Neither the name of the OpenSim Project nor the
13* names of its contributors may be used to endorse or promote products 13* names of its contributors may be used to endorse or promote products
14* derived from this software without specific prior written permission. 14* derived from this software without specific prior written permission.
15* 15*
16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY 16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY
17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26* 26*
27*/ 27*/
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Drawing; 30using System.Drawing;
31using System.Drawing.Imaging; 31using System.Drawing.Imaging;
32using System.IO; 32using System.IO;
33using libTerrain; 33using libTerrain;
34using OpenJPEGNet; 34using OpenJPEGNet;
35 35
36namespace OpenSim.Region.Terrain 36namespace OpenSim.Region.Terrain
37{ 37{
38 public class TerrainCommand 38 public class TerrainCommand
39 { 39 {
40 public virtual bool run(string[] cmdargs, ref string output) 40 public virtual bool run(string[] cmdargs, ref string output)
41 { 41 {
42 return false; 42 return false;
43 } 43 }
44 44
45 public string args; 45 public string args;
46 public string help; 46 public string help;
47 } 47 }
48 48
49 public class TerrainEngine 49 public class TerrainEngine
50 { 50 {
51 /// <summary> 51 /// <summary>
52 /// Plugin library for scripts 52 /// Plugin library for scripts
53 /// </summary> 53 /// </summary>
54 public FilterHost customFilters = new FilterHost(); 54 public FilterHost customFilters = new FilterHost();
55 55
56 /// <summary> 56 /// <summary>
57 /// A [normally] 256x256 heightmap 57 /// A [normally] 256x256 heightmap
58 /// </summary> 58 /// </summary>
59 public Channel heightmap; 59 public Channel heightmap;
60 60
61 /// <summary> 61 /// <summary>
62 /// A copy of heightmap at the last save point (for reverting) 62 /// A copy of heightmap at the last save point (for reverting)
63 /// </summary> 63 /// </summary>
64 public Channel revertmap; 64 public Channel revertmap;
65 65
66 /// <summary> 66 /// <summary>
67 /// Water heightmap (needs clientside mods to work) 67 /// Water heightmap (needs clientside mods to work)
68 /// </summary> 68 /// </summary>
69 public Channel watermap; 69 public Channel watermap;
70 70
71 /// <summary> 71 /// <summary>
72 /// Whether or not the terrain has been modified since it was last saved and sent to the Physics engine. 72 /// Whether or not the terrain has been modified since it was last saved and sent to the Physics engine.
73 /// Counts the number of modifications since the last save. (0 = Untainted) 73 /// Counts the number of modifications since the last save. (0 = Untainted)
74 /// </summary> 74 /// </summary>
75 public int tainted; 75 public int tainted;
76 76
77 int w, h; 77 int w, h;
78 78
79 /// <summary> 79 /// <summary>
80 /// Generate a new TerrainEngine instance and creates a new heightmap 80 /// Generate a new TerrainEngine instance and creates a new heightmap
81 /// </summary> 81 /// </summary>
82 public TerrainEngine() 82 public TerrainEngine()
83 { 83 {
84 w = 256; 84 w = 256;
85 h = 256; 85 h = 256;
86 heightmap = new Channel(w, h); 86 heightmap = new Channel(w, h);
87 87
88 tainted++; 88 tainted++;
89 } 89 }
90 90
91 /// <summary> 91 /// <summary>
92 /// Converts the heightmap to a 65536 value 1D floating point array 92 /// Converts the heightmap to a 65536 value 1D floating point array
93 /// </summary> 93 /// </summary>
94 /// <returns>A float[65536] array containing the heightmap</returns> 94 /// <returns>A float[65536] array containing the heightmap</returns>
95 public float[] getHeights1D() 95 public float[] getHeights1D()
96 { 96 {
97 float[] heights = new float[w * h]; 97 float[] heights = new float[w * h];
98 int i; 98 int i;
99 99
100 for (i = 0; i < w * h; i++) 100 for (i = 0; i < w * h; i++)
101 { 101 {
102 heights[i] = (float)heightmap.map[i / w, i % w]; 102 heights[i] = (float)heightmap.map[i / w, i % w];
103 } 103 }
104 104
105 return heights; 105 return heights;
106 } 106 }
107 107
108 /// <summary> 108 /// <summary>
109 /// Converts the heightmap to a 256x256 value 2D floating point array. 109 /// Converts the heightmap to a 256x256 value 2D floating point array.
110 /// </summary> 110 /// </summary>
111 /// <returns>An array of 256,256 values containing the heightmap</returns> 111 /// <returns>An array of 256,256 values containing the heightmap</returns>
112 public float[,] getHeights2D() 112 public float[,] getHeights2D()
113 { 113 {
114 float[,] heights = new float[w, h]; 114 float[,] heights = new float[w, h];
115 int x, y; 115 int x, y;
116 for (x = 0; x < w; x++) 116 for (x = 0; x < w; x++)
117 { 117 {
118 for (y = 0; y < h; y++) 118 for (y = 0; y < h; y++)
119 { 119 {
120 heights[x, y] = (float)heightmap.map[x, y]; 120 heights[x, y] = (float)heightmap.map[x, y];
121 } 121 }
122 } 122 }
123 return heights; 123 return heights;
124 } 124 }
125 125
126 /// <summary> 126 /// <summary>
127 /// Converts the heightmap to a 256x256 value 2D floating point array. Double precision version. 127 /// Converts the heightmap to a 256x256 value 2D floating point array. Double precision version.
128 /// </summary> 128 /// </summary>
129 /// <returns>An array of 256,256 values containing the heightmap</returns> 129 /// <returns>An array of 256,256 values containing the heightmap</returns>
130 public double[,] getHeights2DD() 130 public double[,] getHeights2DD()
131 { 131 {
132 return heightmap.map; 132 return heightmap.map;
133 } 133 }
134 134
135 /// <summary> 135 /// <summary>
136 /// Imports a 1D floating point array into the 2D heightmap array 136 /// Imports a 1D floating point array into the 2D heightmap array
137 /// </summary> 137 /// </summary>
138 /// <param name="heights">The array to import (must have 65536 members)</param> 138 /// <param name="heights">The array to import (must have 65536 members)</param>
139 public void setHeights1D(float[] heights) 139 public void setHeights1D(float[] heights)
140 { 140 {
141 int i; 141 int i;
142 for (i = 0; i < w * h; i++) 142 for (i = 0; i < w * h; i++)
143 { 143 {
144 heightmap.map[i / w, i % w] = heights[i]; 144 heightmap.map[i / w, i % w] = heights[i];
145 } 145 }
146 146
147 tainted++; 147 tainted++;
148 } 148 }
149 149
150 /// <summary> 150 /// <summary>
151 /// Loads a 2D array of values into the heightmap 151 /// Loads a 2D array of values into the heightmap
152 /// </summary> 152 /// </summary>
153 /// <param name="heights">An array of 256,256 float values</param> 153 /// <param name="heights">An array of 256,256 float values</param>
154 public void setHeights2D(float[,] heights) 154 public void setHeights2D(float[,] heights)
155 { 155 {
156 int x, y; 156 int x, y;
157 for (x = 0; x < w; x++) 157 for (x = 0; x < w; x++)
158 { 158 {
159 for (y = 0; y < h; y++) 159 for (y = 0; y < h; y++)
160 { 160 {
161 heightmap.set(x, y, (double)heights[x, y]); 161 heightmap.set(x, y, (double)heights[x, y]);
162 } 162 }
163 } 163 }
164 tainted++; 164 tainted++;
165 } 165 }
166 166
167 /// <summary> 167 /// <summary>
168 /// Loads a 2D array of values into the heightmap (Double Precision Version) 168 /// Loads a 2D array of values into the heightmap (Double Precision Version)
169 /// </summary> 169 /// </summary>
170 /// <param name="heights">An array of 256,256 float values</param> 170 /// <param name="heights">An array of 256,256 float values</param>
171 public void setHeights2D(double[,] heights) 171 public void setHeights2D(double[,] heights)
172 { 172 {
173 int x, y; 173 int x, y;
174 for (x = 0; x < w; x++) 174 for (x = 0; x < w; x++)
175 { 175 {
176 for (y = 0; y < h; y++) 176 for (y = 0; y < h; y++)
177 { 177 {
178 heightmap.set(x, y, heights[x, y]); 178 heightmap.set(x, y, heights[x, y]);
179 } 179 }
180 } 180 }
181 tainted++; 181 tainted++;
182 } 182 }
183 183
184 /// <summary> 184 /// <summary>
185 /// Swaps the two heightmap buffers (the 'revert map' and the heightmap) 185 /// Swaps the two heightmap buffers (the 'revert map' and the heightmap)
186 /// </summary> 186 /// </summary>
187 public void swapRevertMaps() 187 public void swapRevertMaps()
188 { 188 {
189 Channel backup = heightmap.copy(); 189 Channel backup = heightmap.copy();
190 heightmap = revertmap; 190 heightmap = revertmap;
191 revertmap = backup; 191 revertmap = backup;
192 } 192 }
193 193
194 /// <summary> 194 /// <summary>
195 /// Saves the current heightmap into the revertmap 195 /// Saves the current heightmap into the revertmap
196 /// </summary> 196 /// </summary>
197 public void saveRevertMap() 197 public void saveRevertMap()
198 { 198 {
199 revertmap = heightmap.copy(); 199 revertmap = heightmap.copy();
200 } 200 }
201 201
202 /// <summary> 202 /// <summary>
203 /// Processes a terrain-specific command 203 /// Processes a terrain-specific command
204 /// </summary> 204 /// </summary>
205 /// <param name="args">Commandline arguments (space seperated)</param> 205 /// <param name="args">Commandline arguments (space seperated)</param>
206 /// <param name="resultText">Reference that returns error or help text if returning false</param> 206 /// <param name="resultText">Reference that returns error or help text if returning false</param>
207 /// <returns>If the operation was successful (if not, the error is placed into resultText)</returns> 207 /// <returns>If the operation was successful (if not, the error is placed into resultText)</returns>
208 public bool RunTerrainCmd(string[] args, ref string resultText, string simName) 208 public bool RunTerrainCmd(string[] args, ref string resultText, string simName)
209 { 209 {
210 string command = args[0]; 210 string command = args[0];
211 211
212 try 212 try
213 { 213 {
214 214
215 switch (command) 215 switch (command)
216 { 216 {
217 case "help": 217 case "help":
218 resultText += "terrain regenerate - rebuilds the sims terrain using a default algorithm\n"; 218 resultText += "terrain regenerate - rebuilds the sims terrain using a default algorithm\n";
219 resultText += "terrain voronoi <points> <blocksize> - generates a worley fractal with X points per block"; 219 resultText += "terrain voronoi <points> <blocksize> - generates a worley fractal with X points per block";
220 resultText += "terrain seed <seed> - sets the random seed value to <seed>\n"; 220 resultText += "terrain seed <seed> - sets the random seed value to <seed>\n";
221 resultText += "terrain load <type> <filename> - loads a terrain from disk, type can be 'F32', 'F64', 'RAW' or 'IMG'\n"; 221 resultText += "terrain load <type> <filename> - loads a terrain from disk, type can be 'F32', 'F64', 'RAW' or 'IMG'\n";
222 resultText += "terrain save <type> <filename> - saves a terrain to disk, type can be 'F32', 'F64', 'PNG', 'RAW' or 'HIRAW'\n"; 222 resultText += "terrain save <type> <filename> - saves a terrain to disk, type can be 'F32', 'F64', 'PNG', 'RAW' or 'HIRAW'\n";
223 resultText += "terrain save grdmap <filename> <gradient map> - creates a PNG snapshot of the region using a named gradient map\n"; 223 resultText += "terrain save grdmap <filename> <gradient map> - creates a PNG snapshot of the region using a named gradient map\n";
224 resultText += "terrain rescale <min> <max> - rescales a terrain to be between <min> and <max> meters high\n"; 224 resultText += "terrain rescale <min> <max> - rescales a terrain to be between <min> and <max> meters high\n";
225 resultText += "terrain erode aerobic <windspeed> <pickupmin> <dropmin> <carry> <rounds> <lowest>\n"; 225 resultText += "terrain erode aerobic <windspeed> <pickupmin> <dropmin> <carry> <rounds> <lowest>\n";
226 resultText += "terrain erode thermal <talus> <rounds> <carry>\n"; 226 resultText += "terrain erode thermal <talus> <rounds> <carry>\n";
227 resultText += "terrain multiply <val> - multiplies a terrain by <val>\n"; 227 resultText += "terrain multiply <val> - multiplies a terrain by <val>\n";
228 resultText += "terrain revert - reverts the terrain to the stored original\n"; 228 resultText += "terrain revert - reverts the terrain to the stored original\n";
229 resultText += "terrain bake - saves the current terrain into the revert map\n"; 229 resultText += "terrain bake - saves the current terrain into the revert map\n";
230 resultText += "terrain csfilter <filename.cs> - loads a new filter from the specified .cs file\n"; 230 resultText += "terrain csfilter <filename.cs> - loads a new filter from the specified .cs file\n";
231 resultText += "terrain jsfilter <filename.js> - loads a new filter from the specified .js file\n"; 231 resultText += "terrain jsfilter <filename.js> - loads a new filter from the specified .js file\n";
232 foreach (KeyValuePair<string, ITerrainFilter> filter in customFilters.filters) 232 foreach (KeyValuePair<string, ITerrainFilter> filter in customFilters.filters)
233 { 233 {
234 resultText += filter.Value.Help(); 234 resultText += filter.Value.Help();
235 } 235 }
236 236
237 return false; 237 return false;
238 238
239 case "revert": 239 case "revert":
240 swapRevertMaps(); 240 swapRevertMaps();
241 saveRevertMap(); 241 saveRevertMap();
242 break; 242 break;
243 243
244 case "bake": 244 case "bake":
245 saveRevertMap(); 245 saveRevertMap();
246 break; 246 break;
247 247
248 case "seed": 248 case "seed":
249 setSeed(Convert.ToInt32(args[1])); 249 setSeed(Convert.ToInt32(args[1]));
250 break; 250 break;
251 251
252 case "erode": 252 case "erode":
253 return consoleErosion(args, ref resultText); 253 return consoleErosion(args, ref resultText);
254 254
255 case "voronoi": 255 case "voronoi":
256 double[] c = new double[2]; 256 double[] c = new double[2];
257 c[0] = -1; 257 c[0] = -1;
258 c[1] = 1; 258 c[1] = 1;
259 heightmap.voronoiDiagram(Convert.ToInt32(args[1]), Convert.ToInt32(args[2]), c); 259 heightmap.voronoiDiagram(Convert.ToInt32(args[1]), Convert.ToInt32(args[2]), c);
260 break; 260 break;
261 261
262 case "hills": 262 case "hills":
263 return consoleHills(args, ref resultText); 263 return consoleHills(args, ref resultText);
264 264
265 case "regenerate": 265 case "regenerate":
266 hills(); 266 hills();
267 break; 267 break;
268 268
269 case "rescale": 269 case "rescale":
270 setRange(Convert.ToSingle(args[1]), Convert.ToSingle(args[2])); 270 setRange(Convert.ToSingle(args[1]), Convert.ToSingle(args[2]));
271 break; 271 break;
272 272
273 case "multiply": 273 case "multiply":
274 heightmap *= Convert.ToDouble(args[1]); 274 heightmap *= Convert.ToDouble(args[1]);
275 break; 275 break;
276 276
277 case "load": 277 case "load":
278 args[2].Replace("%name%", simName); 278 args[2].Replace("%name%", simName);
279 switch (args[1].ToLower()) 279 switch (args[1].ToLower())
280 { 280 {
281 case "f32": 281 case "f32":
282 loadFromFileF32(args[2]); 282 loadFromFileF32(args[2]);
283 break; 283 break;
284 284
285 case "f64": 285 case "f64":
286 loadFromFileF64(args[2]); 286 loadFromFileF64(args[2]);
287 break; 287 break;
288 288
289 case "raw": 289 case "raw":
290 loadFromFileSLRAW(args[2]); 290 loadFromFileSLRAW(args[2]);
291 break; 291 break;
292 292
293 case "img": 293 case "img":
294 heightmap.loadImage(args[2]); 294 heightmap.loadImage(args[2]);
295 return false; 295 return false;
296 296
297 default: 297 default:
298 resultText = "Unknown image or data format"; 298 resultText = "Unknown image or data format";
299 return false; 299 return false;
300 } 300 }
301 break; 301 break;
302 302
303 case "save": 303 case "save":
304 args[2].Replace("%name%", simName); 304 args[2].Replace("%name%", simName);
305 switch (args[1].ToLower()) 305 switch (args[1].ToLower())
306 { 306 {
307 case "f32": 307 case "f32":
308 writeToFileF32(args[2]); 308 writeToFileF32(args[2]);
309 break; 309 break;
310 310
311 case "f64": 311 case "f64":
312 writeToFileF64(args[2]); 312 writeToFileF64(args[2]);
313 break; 313 break;
314 314
315 case "grdmap": 315 case "grdmap":
316 exportImage(args[2], args[3]); 316 exportImage(args[2], args[3]);
317 break; 317 break;
318 318
319 case "png": 319 case "png":
320 heightmap.saveImage(args[2]); 320 heightmap.saveImage(args[2]);
321 break; 321 break;
322 322
323 case "raw": 323 case "raw":
324 writeToFileRAW(args[2]); 324 writeToFileRAW(args[2]);
325 break; 325 break;
326 326
327 case "hiraw": 327 case "hiraw":
328 writeToFileHiRAW(args[2]); 328 writeToFileHiRAW(args[2]);
329 break; 329 break;
330 330
331 default: 331 default:
332 resultText = "Unknown image or data format"; 332 resultText = "Unknown image or data format";
333 return false; 333 return false;
334 } 334 }
335 break; 335 break;
336 336
337 case "csfilter": 337 case "csfilter":
338 customFilters.LoadFilterCSharp(args[1]); 338 customFilters.LoadFilterCSharp(args[1]);
339 break; 339 break;
340 case "jsfilter": 340 case "jsfilter":
341 customFilters.LoadFilterJScript(args[1]); 341 customFilters.LoadFilterJScript(args[1]);
342 break; 342 break;
343 343
344 default: 344 default:
345 // Run any custom registered filters 345 // Run any custom registered filters
346 if (customFilters.filters.ContainsKey(command)) 346 if (customFilters.filters.ContainsKey(command))
347 { 347 {
348 customFilters.filters[command].Filter(heightmap, args); 348 customFilters.filters[command].Filter(heightmap, args);
349 break; 349 break;
350 } 350 }
351 else 351 else
352 { 352 {
353 resultText = "Unknown terrain command"; 353 resultText = "Unknown terrain command";
354 return false; 354 return false;
355 } 355 }
356 } 356 }
357 return true; 357 return true;
358 } 358 }
359 catch (Exception e) 359 catch (Exception e)
360 { 360 {
361 resultText = "Error running terrain command: " + e.ToString(); 361 resultText = "Error running terrain command: " + e.ToString();
362 return false; 362 return false;
363 } 363 }
364 } 364 }
365 365
366 private bool consoleErosion(string[] args, ref string resultText) 366 private bool consoleErosion(string[] args, ref string resultText)
367 { 367 {
368 switch (args[1].ToLower()) 368 switch (args[1].ToLower())
369 { 369 {
370 case "aerobic": 370 case "aerobic":
371 // WindSpeed, PickupMinimum,DropMinimum,Carry,Rounds,Lowest 371 // WindSpeed, PickupMinimum,DropMinimum,Carry,Rounds,Lowest
372 heightmap.AerobicErosion(Convert.ToDouble(args[2]), Convert.ToDouble(args[3]), Convert.ToDouble(args[4]), Convert.ToDouble(args[5]), Convert.ToInt32(args[6]), Convert.ToBoolean(args[7])); 372 heightmap.AerobicErosion(Convert.ToDouble(args[2]), Convert.ToDouble(args[3]), Convert.ToDouble(args[4]), Convert.ToDouble(args[5]), Convert.ToInt32(args[6]), Convert.ToBoolean(args[7]));
373 break; 373 break;
374 case "thermal": 374 case "thermal":
375 heightmap.thermalWeathering(Convert.ToDouble(args[2]), Convert.ToInt32(args[3]), Convert.ToDouble(args[4])); 375 heightmap.thermalWeathering(Convert.ToDouble(args[2]), Convert.ToInt32(args[3]), Convert.ToDouble(args[4]));
376 break; 376 break;
377 default: 377 default:
378 resultText = "Unknown erosion type"; 378 resultText = "Unknown erosion type";
379 return false; 379 return false;
380 } 380 }
381 return true; 381 return true;
382 } 382 }
383 383
384 private bool consoleHills(string[] args, ref string resultText) 384 private bool consoleHills(string[] args, ref string resultText)
385 { 385 {
386 int count; 386 int count;
387 double sizeMin; 387 double sizeMin;
388 double sizeRange; 388 double sizeRange;
389 bool island; 389 bool island;
390 bool additive; 390 bool additive;
391 bool noisy; 391 bool noisy;
392 392
393 if (args.GetLength(0) > 2) 393 if (args.GetLength(0) > 2)
394 { 394 {
395 count = Convert.ToInt32(args[2]); 395 count = Convert.ToInt32(args[2]);
396 sizeMin = Convert.ToDouble(args[3]); 396 sizeMin = Convert.ToDouble(args[3]);
397 sizeRange = Convert.ToDouble(args[4]); 397 sizeRange = Convert.ToDouble(args[4]);
398 island = Convert.ToBoolean(args[5]); 398 island = Convert.ToBoolean(args[5]);
399 additive = Convert.ToBoolean(args[6]); 399 additive = Convert.ToBoolean(args[6]);
400 noisy = Convert.ToBoolean(args[7]); 400 noisy = Convert.ToBoolean(args[7]);
401 } 401 }
402 else 402 else
403 { 403 {
404 count = 200; 404 count = 200;
405 sizeMin = 20; 405 sizeMin = 20;
406 sizeRange = 40; 406 sizeRange = 40;
407 island = true; 407 island = true;
408 additive = true; 408 additive = true;
409 noisy = false; 409 noisy = false;
410 } 410 }
411 411
412 switch (args[1].ToLower()) 412 switch (args[1].ToLower())
413 { 413 {
414 case "blocks": 414 case "blocks":
415 heightmap.hillsBlocks(count, sizeMin, sizeRange, island, additive, noisy); 415 heightmap.hillsBlocks(count, sizeMin, sizeRange, island, additive, noisy);
416 break; 416 break;
417 case "cones": 417 case "cones":
418 heightmap.hillsCones(count, sizeMin, sizeRange, island, additive, noisy); 418 heightmap.hillsCones(count, sizeMin, sizeRange, island, additive, noisy);
419 break; 419 break;
420 case "spheres": 420 case "spheres":
421 heightmap.hillsSpheres(count, sizeMin, sizeRange, island, additive, noisy); 421 heightmap.hillsSpheres(count, sizeMin, sizeRange, island, additive, noisy);
422 break; 422 break;
423 case "squared": 423 case "squared":
424 heightmap.hillsSquared(count, sizeMin, sizeRange, island, additive, noisy); 424 heightmap.hillsSquared(count, sizeMin, sizeRange, island, additive, noisy);
425 break; 425 break;
426 default: 426 default:
427 resultText = "Unknown hills type"; 427 resultText = "Unknown hills type";
428 return false; 428 return false;
429 } 429 }
430 return true; 430 return true;
431 } 431 }
432 432
433 /// <summary> 433 /// <summary>
434 /// Renormalises the array between min and max 434 /// Renormalises the array between min and max
435 /// </summary> 435 /// </summary>
436 /// <param name="min">Minimum value of the new array</param> 436 /// <param name="min">Minimum value of the new array</param>
437 /// <param name="max">Maximum value of the new array</param> 437 /// <param name="max">Maximum value of the new array</param>
438 public void setRange(float min, float max) 438 public void setRange(float min, float max)
439 { 439 {
440 heightmap.normalise((double)min, (double)max); 440 heightmap.normalise((double)min, (double)max);
441 tainted++; 441 tainted++;
442 } 442 }
443 443
444 /// <summary> 444 /// <summary>
445 /// Loads a file consisting of 256x256 doubles and imports it as an array into the map. 445 /// Loads a file consisting of 256x256 doubles and imports it as an array into the map.
446 /// </summary> 446 /// </summary>
447 /// <remarks>TODO: Move this to libTerrain itself</remarks> 447 /// <remarks>TODO: Move this to libTerrain itself</remarks>
448 /// <param name="filename">The filename of the double array to import</param> 448 /// <param name="filename">The filename of the double array to import</param>
449 public void loadFromFileF64(string filename) 449 public void loadFromFileF64(string filename)
450 { 450 {
451 FileInfo file = new FileInfo(filename); 451 FileInfo file = new FileInfo(filename);
452 FileStream s = file.Open(FileMode.Open, FileAccess.Read); 452 FileStream s = file.Open(FileMode.Open, FileAccess.Read);
453 BinaryReader bs = new BinaryReader(s); 453 BinaryReader bs = new BinaryReader(s);
454 int x, y; 454 int x, y;
455 for (x = 0; x < w; x++) 455 for (x = 0; x < w; x++)
456 { 456 {
457 for (y = 0; y < h; y++) 457 for (y = 0; y < h; y++)
458 { 458 {
459 heightmap.map[x, y] = bs.ReadDouble(); 459 heightmap.map[x, y] = bs.ReadDouble();
460 } 460 }
461 } 461 }
462 462
463 bs.Close(); 463 bs.Close();
464 s.Close(); 464 s.Close();
465 465
466 tainted++; 466 tainted++;
467 } 467 }
468 468
469 /// <summary> 469 /// <summary>
470 /// Loads a file consisting of 256x256 floats and imports it as an array into the map. 470 /// Loads a file consisting of 256x256 floats and imports it as an array into the map.
471 /// </summary> 471 /// </summary>
472 /// <remarks>TODO: Move this to libTerrain itself</remarks> 472 /// <remarks>TODO: Move this to libTerrain itself</remarks>
473 /// <param name="filename">The filename of the float array to import</param> 473 /// <param name="filename">The filename of the float array to import</param>
474 public void loadFromFileF32(string filename) 474 public void loadFromFileF32(string filename)
475 { 475 {
476 FileInfo file = new FileInfo(filename); 476 FileInfo file = new FileInfo(filename);
477 FileStream s = file.Open(FileMode.Open, FileAccess.Read); 477 FileStream s = file.Open(FileMode.Open, FileAccess.Read);
478 BinaryReader bs = new BinaryReader(s); 478 BinaryReader bs = new BinaryReader(s);
479 int x, y; 479 int x, y;
480 for (x = 0; x < w; x++) 480 for (x = 0; x < w; x++)
481 { 481 {
482 for (y = 0; y < h; y++) 482 for (y = 0; y < h; y++)
483 { 483 {
484 heightmap.map[x, y] = (double)bs.ReadSingle(); 484 heightmap.map[x, y] = (double)bs.ReadSingle();
485 } 485 }
486 } 486 }
487 487
488 bs.Close(); 488 bs.Close();
489 s.Close(); 489 s.Close();
490 490
491 tainted++; 491 tainted++;
492 } 492 }
493 493
494 /// <summary> 494 /// <summary>
495 /// Loads a file formatted in the SL .RAW Format used on the main grid 495 /// Loads a file formatted in the SL .RAW Format used on the main grid
496 /// </summary> 496 /// </summary>
497 /// <remarks>This file format stinks and is best avoided.</remarks> 497 /// <remarks>This file format stinks and is best avoided.</remarks>
498 /// <param name="filename">A path to the .RAW format</param> 498 /// <param name="filename">A path to the .RAW format</param>
499 public void loadFromFileSLRAW(string filename) 499 public void loadFromFileSLRAW(string filename)
500 { 500 {
501 FileInfo file = new FileInfo(filename); 501 FileInfo file = new FileInfo(filename);
502 FileStream s = file.Open(FileMode.Open, FileAccess.Read); 502 FileStream s = file.Open(FileMode.Open, FileAccess.Read);
503 BinaryReader bs = new BinaryReader(s); 503 BinaryReader bs = new BinaryReader(s);
504 int x, y; 504 int x, y;
505 for (x = 0; x < w; x++) 505 for (x = 0; x < w; x++)
506 { 506 {
507 for (y = 0; y < h; y++) 507 for (y = 0; y < h; y++)
508 { 508 {
509 heightmap.map[x, y] = (double)bs.ReadByte() * ((double)bs.ReadByte() / 127.0); 509 heightmap.map[x, y] = (double)bs.ReadByte() * ((double)bs.ReadByte() / 127.0);
510 bs.ReadBytes(11); // Advance the stream to next bytes. 510 bs.ReadBytes(11); // Advance the stream to next bytes.
511 } 511 }
512 } 512 }
513 513
514 bs.Close(); 514 bs.Close();
515 s.Close(); 515 s.Close();
516 516
517 tainted++; 517 tainted++;
518 } 518 }
519 519
520 /// <summary> 520 /// <summary>
521 /// Writes the current terrain heightmap to disk, in the format of a 65536 entry double[] array. 521 /// Writes the current terrain heightmap to disk, in the format of a 65536 entry double[] array.
522 /// </summary> 522 /// </summary>
523 /// <param name="filename">The desired output filename</param> 523 /// <param name="filename">The desired output filename</param>
524 public void writeToFileF64(string filename) 524 public void writeToFileF64(string filename)
525 { 525 {
526 FileInfo file = new FileInfo(filename); 526 FileInfo file = new FileInfo(filename);
527 FileStream s = file.Open(FileMode.CreateNew, FileAccess.Write); 527 FileStream s = file.Open(FileMode.CreateNew, FileAccess.Write);
528 BinaryWriter bs = new BinaryWriter(s); 528 BinaryWriter bs = new BinaryWriter(s);
529 529
530 int x, y; 530 int x, y;
531 for (x = 0; x < w; x++) 531 for (x = 0; x < w; x++)
532 { 532 {
533 for (y = 0; y < h; y++) 533 for (y = 0; y < h; y++)
534 { 534 {
535 bs.Write(heightmap.get(x, y)); 535 bs.Write(heightmap.get(x, y));
536 } 536 }
537 } 537 }
538 538
539 bs.Close(); 539 bs.Close();
540 s.Close(); 540 s.Close();
541 } 541 }
542 542
543 /// <summary> 543 /// <summary>
544 /// Writes the current terrain heightmap to disk, in the format of a 65536 entry float[] array 544 /// Writes the current terrain heightmap to disk, in the format of a 65536 entry float[] array
545 /// </summary> 545 /// </summary>
546 /// <param name="filename">The desired output filename</param> 546 /// <param name="filename">The desired output filename</param>
547 public void writeToFileF32(string filename) 547 public void writeToFileF32(string filename)
548 { 548 {
549 FileInfo file = new FileInfo(filename); 549 FileInfo file = new FileInfo(filename);
550 FileStream s = file.Open(FileMode.CreateNew, FileAccess.Write); 550 FileStream s = file.Open(FileMode.CreateNew, FileAccess.Write);
551 BinaryWriter bs = new BinaryWriter(s); 551 BinaryWriter bs = new BinaryWriter(s);
552 552
553 int x, y; 553 int x, y;
554 for (x = 0; x < w; x++) 554 for (x = 0; x < w; x++)
555 { 555 {
556 for (y = 0; y < h; y++) 556 for (y = 0; y < h; y++)
557 { 557 {
558 bs.Write((float)heightmap.get(x, y)); 558 bs.Write((float)heightmap.get(x, y));
559 } 559 }
560 } 560 }
561 561
562 bs.Close(); 562 bs.Close();
563 s.Close(); 563 s.Close();
564 } 564 }
565 565
566 /// <summary> 566 /// <summary>
567 /// A very fast LL-RAW file output mechanism - lower precision mechanism but wont take 5 minutes to run either. 567 /// A very fast LL-RAW file output mechanism - lower precision mechanism but wont take 5 minutes to run either.
568 /// (is also editable in an image application) 568 /// (is also editable in an image application)
569 /// </summary> 569 /// </summary>
570 /// <param name="filename">Filename to write to</param> 570 /// <param name="filename">Filename to write to</param>
571 public void writeToFileRAW(string filename) 571 public void writeToFileRAW(string filename)
572 { 572 {
573 FileInfo file = new FileInfo(filename); 573 FileInfo file = new FileInfo(filename);
574 FileStream s = file.Open(FileMode.CreateNew, FileAccess.Write); 574 FileStream s = file.Open(FileMode.CreateNew, FileAccess.Write);
575 BinaryWriter bs = new BinaryWriter(s); 575 BinaryWriter bs = new BinaryWriter(s);
576 576
577 int x, y; 577 int x, y;
578 578
579 // Used for the 'green' channel. 579 // Used for the 'green' channel.
580 byte avgMultiplier = (byte)heightmap.avg(); 580 byte avgMultiplier = (byte)heightmap.avg();
581 byte backupMultiplier = (byte)revertmap.avg(); 581 byte backupMultiplier = (byte)revertmap.avg();
582 582
583 // Limit the multiplier so it can represent points >64m. 583 // Limit the multiplier so it can represent points >64m.
584 if (avgMultiplier > 196) 584 if (avgMultiplier > 196)
585 avgMultiplier = 196; 585 avgMultiplier = 196;
586 if(backupMultiplier > 196) 586 if(backupMultiplier > 196)
587 backupMultiplier = 196; 587 backupMultiplier = 196;
588 // Make sure it's at least one to prevent a div by zero 588 // Make sure it's at least one to prevent a div by zero
589 if (avgMultiplier < 1) 589 if (avgMultiplier < 1)
590 avgMultiplier = 1; 590 avgMultiplier = 1;
591 if(backupMultiplier < 1) 591 if(backupMultiplier < 1)
592 backupMultiplier = 1; 592 backupMultiplier = 1;
593 593
594 for (x = 0; x < w; x++) 594 for (x = 0; x < w; x++)
595 { 595 {
596 for (y = 0; y < h; y++) 596 for (y = 0; y < h; y++)
597 { 597 {
598 byte red = (byte)(heightmap.get(x, y) / ((double)avgMultiplier / 128.0)); 598 byte red = (byte)(heightmap.get(x, y) / ((double)avgMultiplier / 128.0));
599 byte green = avgMultiplier; 599 byte green = avgMultiplier;
600 byte blue = (byte)watermap.get(x, y); 600 byte blue = (byte)watermap.get(x, y);
601 byte alpha1 = 0; // Land Parcels 601 byte alpha1 = 0; // Land Parcels
602 byte alpha2 = 0; // For Sale Land 602 byte alpha2 = 0; // For Sale Land
603 byte alpha3 = 0; // Public Edit Object 603 byte alpha3 = 0; // Public Edit Object
604 byte alpha4 = 0; // Public Edit Land 604 byte alpha4 = 0; // Public Edit Land
605 byte alpha5 = 255; // Safe Land 605 byte alpha5 = 255; // Safe Land
606 byte alpha6 = 255; // Flying Allowed 606 byte alpha6 = 255; // Flying Allowed
607 byte alpha7 = 255; // Create Landmark 607 byte alpha7 = 255; // Create Landmark
608 byte alpha8 = 255; // Outside Scripts 608 byte alpha8 = 255; // Outside Scripts
609 byte alpha9 = (byte)(revertmap.get(x, y) / ((double)backupMultiplier / 128.0)); 609 byte alpha9 = (byte)(revertmap.get(x, y) / ((double)backupMultiplier / 128.0));
610 byte alpha10 = backupMultiplier; 610 byte alpha10 = backupMultiplier;
611 611
612 bs.Write(red); 612 bs.Write(red);
613 bs.Write(green); 613 bs.Write(green);
614 bs.Write(blue); 614 bs.Write(blue);
615 bs.Write(alpha1); 615 bs.Write(alpha1);
616 bs.Write(alpha2); 616 bs.Write(alpha2);
617 bs.Write(alpha3); 617 bs.Write(alpha3);
618 bs.Write(alpha4); 618 bs.Write(alpha4);
619 bs.Write(alpha5); 619 bs.Write(alpha5);
620 bs.Write(alpha6); 620 bs.Write(alpha6);
621 bs.Write(alpha7); 621 bs.Write(alpha7);
622 bs.Write(alpha8); 622 bs.Write(alpha8);
623 bs.Write(alpha9); 623 bs.Write(alpha9);
624 bs.Write(alpha10); 624 bs.Write(alpha10);
625 } 625 }
626 } 626 }
627 bs.Close(); 627 bs.Close();
628 s.Close(); 628 s.Close();
629 } 629 }
630 630
631 /// <summary> 631 /// <summary>
632 /// Outputs to a LL compatible RAW in the most efficient manner possible 632 /// Outputs to a LL compatible RAW in the most efficient manner possible
633 /// </summary> 633 /// </summary>
634 /// <remarks>Does not calculate the revert map</remarks> 634 /// <remarks>Does not calculate the revert map</remarks>
635 /// <param name="filename">The filename to output to</param> 635 /// <param name="filename">The filename to output to</param>
636 public void writeToFileHiRAW(string filename) 636 public void writeToFileHiRAW(string filename)
637 { 637 {
638 FileInfo file = new FileInfo(filename); 638 FileInfo file = new FileInfo(filename);
639 FileStream s = file.Open(FileMode.CreateNew, FileAccess.Write); 639 FileStream s = file.Open(FileMode.CreateNew, FileAccess.Write);
640 BinaryWriter bs = new BinaryWriter(s); 640 BinaryWriter bs = new BinaryWriter(s);
641 641
642 // Generate a smegging big lookup table to speed the operation up (it needs it) 642 // Generate a smegging big lookup table to speed the operation up (it needs it)
643 double[] lookupTable = new double[65536]; 643 double[] lookupTable = new double[65536];
644 int i, j, x, y; 644 int i, j, x, y;
645 for (i = 0; i < 256; i++) 645 for (i = 0; i < 256; i++)
646 { 646 {
647 for (j = 0; j < 256; j++) 647 for (j = 0; j < 256; j++)
648 { 648 {
649 lookupTable[i + (j * 256)] = ((double)i * ((double)j / 127.0)); 649 lookupTable[i + (j * 256)] = ((double)i * ((double)j / 127.0));
650 } 650 }
651 } 651 }
652 652
653 // Output the calculated raw 653 // Output the calculated raw
654 for (x = 0; x < w; x++) 654 for (x = 0; x < w; x++)
655 { 655 {
656 for (y = 0; y < h; y++) 656 for (y = 0; y < h; y++)
657 { 657 {
658 double t = heightmap.get(x, y); 658 double t = heightmap.get(x, y);
659 double min = double.MaxValue; 659 double min = double.MaxValue;
660 int index = 0; 660 int index = 0;
661 661
662 for (i = 0; i < 65536; i++) 662 for (i = 0; i < 65536; i++)
663 { 663 {
664 if (Math.Abs(t - lookupTable[i]) < min) 664 if (Math.Abs(t - lookupTable[i]) < min)
665 { 665 {
666 min = Math.Abs(t - lookupTable[i]); 666 min = Math.Abs(t - lookupTable[i]);
667 index = i; 667 index = i;
668 } 668 }
669 } 669 }
670 670
671 byte red = (byte)(index & 0xFF); 671 byte red = (byte)(index & 0xFF);
672 byte green = (byte)((index >> 8) & 0xFF); 672 byte green = (byte)((index >> 8) & 0xFF);
673 byte blue = (byte)watermap.get(x, y); 673 byte blue = (byte)watermap.get(x, y);
674 byte alpha1 = 0; // Land Parcels 674 byte alpha1 = 0; // Land Parcels
675 byte alpha2 = 0; // For Sale Land 675 byte alpha2 = 0; // For Sale Land
676 byte alpha3 = 0; // Public Edit Object 676 byte alpha3 = 0; // Public Edit Object
677 byte alpha4 = 0; // Public Edit Land 677 byte alpha4 = 0; // Public Edit Land
678 byte alpha5 = 255; // Safe Land 678 byte alpha5 = 255; // Safe Land
679 byte alpha6 = 255; // Flying Allowed 679 byte alpha6 = 255; // Flying Allowed
680 byte alpha7 = 255; // Create Landmark 680 byte alpha7 = 255; // Create Landmark
681 byte alpha8 = 255; // Outside Scripts 681 byte alpha8 = 255; // Outside Scripts
682 byte alpha9 = red; 682 byte alpha9 = red;
683 byte alpha10 = green; 683 byte alpha10 = green;
684 684
685 bs.Write(red); 685 bs.Write(red);
686 bs.Write(green); 686 bs.Write(green);
687 bs.Write(blue); 687 bs.Write(blue);
688 bs.Write(alpha1); 688 bs.Write(alpha1);
689 bs.Write(alpha2); 689 bs.Write(alpha2);
690 bs.Write(alpha3); 690 bs.Write(alpha3);
691 bs.Write(alpha4); 691 bs.Write(alpha4);
692 bs.Write(alpha5); 692 bs.Write(alpha5);
693 bs.Write(alpha6); 693 bs.Write(alpha6);
694 bs.Write(alpha7); 694 bs.Write(alpha7);
695 bs.Write(alpha8); 695 bs.Write(alpha8);
696 bs.Write(alpha9); 696 bs.Write(alpha9);
697 bs.Write(alpha10); 697 bs.Write(alpha10);
698 } 698 }
699 } 699 }
700 700
701 bs.Close(); 701 bs.Close();
702 s.Close(); 702 s.Close();
703 } 703 }
704 704
705 /// <summary> 705 /// <summary>
706 /// Sets the random seed to be used by procedural functions which involve random numbers. 706 /// Sets the random seed to be used by procedural functions which involve random numbers.
707 /// </summary> 707 /// </summary>
708 /// <param name="val">The desired seed</param> 708 /// <param name="val">The desired seed</param>
709 public void setSeed(int val) 709 public void setSeed(int val)
710 { 710 {
711 heightmap.seed = val; 711 heightmap.seed = val;
712 } 712 }
713 713
714 /// <summary> 714 /// <summary>
715 /// Raises land in a sphere around the specified coordinates 715 /// Raises land in a sphere around the specified coordinates
716 /// </summary> 716 /// </summary>
717 /// <param name="rx">Center of the sphere on the X axis</param> 717 /// <param name="rx">Center of the sphere on the X axis</param>
718 /// <param name="ry">Center of the sphere on the Y axis</param> 718 /// <param name="ry">Center of the sphere on the Y axis</param>
719 /// <param name="size">The radius of the sphere</param> 719 /// <param name="size">The radius of the sphere</param>
720 /// <param name="amount">Scale the height of the sphere by this amount (recommended 0..2)</param> 720 /// <param name="amount">Scale the height of the sphere by this amount (recommended 0..2)</param>
721 public void raise(double rx, double ry, double size, double amount) 721 public void raise(double rx, double ry, double size, double amount)
722 { 722 {
723 lock (heightmap) 723 lock (heightmap)
724 { 724 {
725 heightmap.raise(rx, ry, size, amount); 725 heightmap.raise(rx, ry, size, amount);
726 } 726 }
727 727
728 tainted++; 728 tainted++;
729 } 729 }
730 730
731 /// <summary> 731 /// <summary>
732 /// Lowers the land in a sphere around the specified coordinates 732 /// Lowers the land in a sphere around the specified coordinates
733 /// </summary> 733 /// </summary>
734 /// <param name="rx">The center of the sphere at the X axis</param> 734 /// <param name="rx">The center of the sphere at the X axis</param>
735 /// <param name="ry">The center of the sphere at the Y axis</param> 735 /// <param name="ry">The center of the sphere at the Y axis</param>
736 /// <param name="size">The radius of the sphere in meters</param> 736 /// <param name="size">The radius of the sphere in meters</param>
737 /// <param name="amount">Scale the height of the sphere by this amount (recommended 0..2)</param> 737 /// <param name="amount">Scale the height of the sphere by this amount (recommended 0..2)</param>
738 public void lower(double rx, double ry, double size, double amount) 738 public void lower(double rx, double ry, double size, double amount)
739 { 739 {
740 lock (heightmap) 740 lock (heightmap)
741 { 741 {
742 heightmap.lower(rx, ry, size, amount); 742 heightmap.lower(rx, ry, size, amount);
743 } 743 }
744 744
745 tainted++; 745 tainted++;
746 } 746 }
747 747
748 /// <summary> 748 /// <summary>
749 /// Flattens the land under the brush of specified coordinates (spherical mask) 749 /// Flattens the land under the brush of specified coordinates (spherical mask)
750 /// </summary> 750 /// </summary>
751 /// <param name="rx">Center of sphere</param> 751 /// <param name="rx">Center of sphere</param>
752 /// <param name="ry">Center of sphere</param> 752 /// <param name="ry">Center of sphere</param>
753 /// <param name="size">Radius of the sphere</param> 753 /// <param name="size">Radius of the sphere</param>
754 /// <param name="amount">Thickness of the mask (0..2 recommended)</param> 754 /// <param name="amount">Thickness of the mask (0..2 recommended)</param>
755 public void flatten(double rx, double ry, double size, double amount) 755 public void flatten(double rx, double ry, double size, double amount)
756 { 756 {
757 lock (heightmap) 757 lock (heightmap)
758 { 758 {
759 heightmap.flatten(rx, ry, size, amount); 759 heightmap.flatten(rx, ry, size, amount);
760 } 760 }
761 761
762 tainted++; 762 tainted++;
763 } 763 }
764 764
765 /// <summary> 765 /// <summary>
766 /// Creates noise within the specified bounds 766 /// Creates noise within the specified bounds
767 /// </summary> 767 /// </summary>
768 /// <param name="rx">Center of the bounding sphere</param> 768 /// <param name="rx">Center of the bounding sphere</param>
769 /// <param name="ry">Center of the bounding sphere</param> 769 /// <param name="ry">Center of the bounding sphere</param>
770 /// <param name="size">The radius of the sphere</param> 770 /// <param name="size">The radius of the sphere</param>
771 /// <param name="amount">Strength of the mask (0..2) recommended</param> 771 /// <param name="amount">Strength of the mask (0..2) recommended</param>
772 public void noise(double rx, double ry, double size, double amount) 772 public void noise(double rx, double ry, double size, double amount)
773 { 773 {
774 lock (heightmap) 774 lock (heightmap)
775 { 775 {
776 Channel smoothed = new Channel(); 776 Channel smoothed = new Channel();
777 smoothed.noise(); 777 smoothed.noise();
778 778
779 Channel mask = new Channel(); 779 Channel mask = new Channel();
780 mask.raise(rx, ry, size, amount); 780 mask.raise(rx, ry, size, amount);
781 781
782 heightmap.blend(smoothed, mask); 782 heightmap.blend(smoothed, mask);
783 } 783 }
784 784
785 tainted++; 785 tainted++;
786 } 786 }
787 787
788 /// <summary> 788 /// <summary>
789 /// Reverts land within the specified bounds 789 /// Reverts land within the specified bounds
790 /// </summary> 790 /// </summary>
791 /// <param name="rx">Center of the bounding sphere</param> 791 /// <param name="rx">Center of the bounding sphere</param>
792 /// <param name="ry">Center of the bounding sphere</param> 792 /// <param name="ry">Center of the bounding sphere</param>
793 /// <param name="size">The radius of the sphere</param> 793 /// <param name="size">The radius of the sphere</param>
794 /// <param name="amount">Strength of the mask (0..2) recommended</param> 794 /// <param name="amount">Strength of the mask (0..2) recommended</param>
795 public void revert(double rx, double ry, double size, double amount) 795 public void revert(double rx, double ry, double size, double amount)
796 { 796 {
797 lock (heightmap) 797 lock (heightmap)
798 { 798 {
799 Channel mask = new Channel(); 799 Channel mask = new Channel();
800 mask.raise(rx, ry, size, amount); 800 mask.raise(rx, ry, size, amount);
801 801
802 heightmap.blend(revertmap, mask); 802 heightmap.blend(revertmap, mask);
803 } 803 }
804 804
805 tainted++; 805 tainted++;
806 } 806 }
807 807
808 /// <summary> 808 /// <summary>
809 /// Smooths land under the brush of specified coordinates (spherical mask) 809 /// Smooths land under the brush of specified coordinates (spherical mask)
810 /// </summary> 810 /// </summary>
811 /// <param name="rx">Center of the sphere</param> 811 /// <param name="rx">Center of the sphere</param>
812 /// <param name="ry">Center of the sphere</param> 812 /// <param name="ry">Center of the sphere</param>
813 /// <param name="size">Radius of the sphere</param> 813 /// <param name="size">Radius of the sphere</param>
814 /// <param name="amount">Thickness of the mask (0..2 recommended)</param> 814 /// <param name="amount">Thickness of the mask (0..2 recommended)</param>
815 public void smooth(double rx, double ry, double size, double amount) 815 public void smooth(double rx, double ry, double size, double amount)
816 { 816 {
817 lock (heightmap) 817 lock (heightmap)
818 { 818 {
819 Channel smoothed = heightmap.copy(); 819 Channel smoothed = heightmap.copy();
820 smoothed.smooth(amount); 820 smoothed.smooth(amount);
821 821
822 Channel mask = new Channel(); 822 Channel mask = new Channel();
823 mask.raise(rx,ry,size,amount); 823 mask.raise(rx,ry,size,amount);
824 824
825 heightmap.blend(smoothed, mask); 825 heightmap.blend(smoothed, mask);
826 } 826 }
827 827
828 tainted++; 828 tainted++;
829 } 829 }
830 830
831 /// <summary> 831 /// <summary>
832 /// Generates a simple set of hills in the shape of an island 832 /// Generates a simple set of hills in the shape of an island
833 /// </summary> 833 /// </summary>
834 public void hills() 834 public void hills()
835 { 835 {
836 lock (heightmap) 836 lock (heightmap)
837 { 837 {
838 heightmap.hillsSpheres(200, 20, 40, true, true, false); 838 heightmap.hillsSpheres(200, 20, 40, true, true, false);
839 heightmap.normalise(); 839 heightmap.normalise();
840 heightmap *= 60.0; // Raise to 60m 840 heightmap *= 60.0; // Raise to 60m
841 } 841 }
842 842
843 tainted++; 843 tainted++;
844 } 844 }
845 845
846 /// <summary> 846 /// <summary>
847 /// Wrapper to heightmap.get() 847 /// Wrapper to heightmap.get()
848 /// </summary> 848 /// </summary>
849 /// <param name="x">X coord</param> 849 /// <param name="x">X coord</param>
850 /// <param name="y">Y coord</param> 850 /// <param name="y">Y coord</param>
851 /// <returns>Height at specified coordinates</returns> 851 /// <returns>Height at specified coordinates</returns>
852 public double get(int x, int y) 852 public double get(int x, int y)
853 { 853 {
854 return heightmap.get(x, y); 854 return heightmap.get(x, y);
855 } 855 }
856 856
857 /// <summary> 857 /// <summary>
858 /// Multiplies the heightfield by val 858 /// Multiplies the heightfield by val
859 /// </summary> 859 /// </summary>
860 /// <param name="meep">The heightfield</param> 860 /// <param name="meep">The heightfield</param>
861 /// <param name="val">The multiplier</param> 861 /// <param name="val">The multiplier</param>
862 /// <returns></returns> 862 /// <returns></returns>
863 public static TerrainEngine operator *(TerrainEngine meep, Double val) 863 public static TerrainEngine operator *(TerrainEngine meep, Double val)
864 { 864 {
865 meep.heightmap *= val; 865 meep.heightmap *= val;
866 meep.tainted++; 866 meep.tainted++;
867 return meep; 867 return meep;
868 } 868 }
869 869
870 /// <summary> 870 /// <summary>
871 /// Exports the current heightmap to a PNG file 871 /// Exports the current heightmap to a PNG file
872 /// </summary> 872 /// </summary>
873 /// <param name="filename">The destination filename for the image</param> 873 /// <param name="filename">The destination filename for the image</param>
874 /// <param name="gradientmap">A 1x*height* image which contains the colour gradient to export with. Must be at least 1x2 pixels, 1x256 or more is ideal.</param> 874 /// <param name="gradientmap">A 1x*height* image which contains the colour gradient to export with. Must be at least 1x2 pixels, 1x256 or more is ideal.</param>
875 public void exportImage(string filename, string gradientmap) 875 public void exportImage(string filename, string gradientmap)
876 { 876 {
877 try 877 try
878 { 878 {
879 Bitmap gradientmapLd = new Bitmap(gradientmap); 879 Bitmap gradientmapLd = new Bitmap(gradientmap);
880 880
881 int pallete = gradientmapLd.Height; 881 int pallete = gradientmapLd.Height;
882 882
883 Bitmap bmp = new Bitmap(heightmap.w, heightmap.h); 883 Bitmap bmp = new Bitmap(heightmap.w, heightmap.h);
884 Color[] colours = new Color[pallete]; 884 Color[] colours = new Color[pallete];
885 885
886 for (int i = 0; i < pallete; i++) 886 for (int i = 0; i < pallete; i++)
887 { 887 {
888 colours[i] = gradientmapLd.GetPixel(0, i); 888 colours[i] = gradientmapLd.GetPixel(0, i);
889 } 889 }
890 890
891 Channel copy = heightmap.copy(); 891 Channel copy = heightmap.copy();
892 for (int x = 0; x < copy.w; x++) 892 for (int x = 0; x < copy.w; x++)
893 { 893 {
894 for (int y = 0; y < copy.h; y++) 894 for (int y = 0; y < copy.h; y++)
895 { 895 {
896 // 512 is the largest possible height before colours clamp 896 // 512 is the largest possible height before colours clamp
897 int colorindex = (int)(Math.Max(Math.Min(1.0, copy.get(x, y) / 512.0), 0.0) * pallete); 897 int colorindex = (int)(Math.Max(Math.Min(1.0, copy.get(x, y) / 512.0), 0.0) * pallete);
898 bmp.SetPixel(x, y, colours[colorindex]); 898 bmp.SetPixel(x, y, colours[colorindex]);
899 } 899 }
900 } 900 }
901 901
902 bmp.Save(filename, ImageFormat.Png); 902 bmp.Save(filename, ImageFormat.Png);
903 } 903 }
904 catch (Exception e) 904 catch (Exception e)
905 { 905 {
906 Console.WriteLine("Failed generating terrain map: " + e.ToString()); 906 Console.WriteLine("Failed generating terrain map: " + e.ToString());
907 } 907 }
908 } 908 }
909 909
910 /// <summary> 910 /// <summary>
911 /// Exports the current heightmap in Jpeg2000 format to a byte[] 911 /// Exports the current heightmap in Jpeg2000 format to a byte[]
912 /// </summary> 912 /// </summary>
913 /// <param name="gradientmap">A 1x*height* image which contains the colour gradient to export with. Must be at least 1x2 pixels, 1x256 or more is ideal.</param> 913 /// <param name="gradientmap">A 1x*height* image which contains the colour gradient to export with. Must be at least 1x2 pixels, 1x256 or more is ideal.</param>
914 public byte[] exportJpegImage(string gradientmap) 914 public byte[] exportJpegImage(string gradientmap)
915 { 915 {
916 byte[] imageData = null; 916 byte[] imageData = null;
917 try 917 try
918 { 918 {
919 Bitmap gradientmapLd = new Bitmap(gradientmap); 919 Bitmap gradientmapLd = new Bitmap(gradientmap);
920 920
921 int pallete = gradientmapLd.Height; 921 int pallete = gradientmapLd.Height;
922 922
923 Bitmap bmp = new Bitmap(heightmap.w, heightmap.h); 923 Bitmap bmp = new Bitmap(heightmap.w, heightmap.h);
924 Color[] colours = new Color[pallete]; 924 Color[] colours = new Color[pallete];
925 925
926 for (int i = 0; i < pallete; i++) 926 for (int i = 0; i < pallete; i++)
927 { 927 {
928 colours[i] = gradientmapLd.GetPixel(0, i); 928 colours[i] = gradientmapLd.GetPixel(0, i);
929 } 929 }
930 930
931 Channel copy = heightmap.copy(); 931 Channel copy = heightmap.copy();
932 for (int x = 0; x < copy.w; x++) 932 for (int x = 0; x < copy.w; x++)
933 { 933 {
934 for (int y = 0; y < copy.h; y++) 934 for (int y = 0; y < copy.h; y++)
935 { 935 {
936 // 512 is the largest possible height before colours clamp 936 // 512 is the largest possible height before colours clamp
937 int colorindex = (int)(Math.Max(Math.Min(1.0, copy.get(copy.h - y, x) / 512.0), 0.0) * pallete); 937 int colorindex = (int)(Math.Max(Math.Min(1.0, copy.get(copy.h - y, x) / 512.0), 0.0) * pallete);
938 bmp.SetPixel(x, y, colours[colorindex]); 938 bmp.SetPixel(x, y, colours[colorindex]);
939 } 939 }
940 } 940 }
941 941
942 //bmp.Save(filename, System.Drawing.Imaging.ImageFormat.Png); 942 //bmp.Save(filename, System.Drawing.Imaging.ImageFormat.Png);
943 imageData = OpenJPEG.EncodeFromImage(bmp, true ); 943 imageData = OpenJPEG.EncodeFromImage(bmp, true );
944 944
945 } 945 }
946 catch (Exception e) 946 catch (Exception e)
947 { 947 {
948 Console.WriteLine("Failed generating terrain map: " + e.ToString()); 948 Console.WriteLine("Failed generating terrain map: " + e.ToString());
949 } 949 }
950 950
951 return imageData; 951 return imageData;
952 } 952 }
953 } 953 }
954} \ No newline at end of file 954} \ No newline at end of file