diff options
Diffstat (limited to 'OpenSim/OpenSim.Terrain.BasicTerrain/TerrainEngine.cs')
-rw-r--r-- | OpenSim/OpenSim.Terrain.BasicTerrain/TerrainEngine.cs | 533 |
1 files changed, 0 insertions, 533 deletions
diff --git a/OpenSim/OpenSim.Terrain.BasicTerrain/TerrainEngine.cs b/OpenSim/OpenSim.Terrain.BasicTerrain/TerrainEngine.cs deleted file mode 100644 index 373d6ad..0000000 --- a/OpenSim/OpenSim.Terrain.BasicTerrain/TerrainEngine.cs +++ /dev/null | |||
@@ -1,533 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://www.openmetaverse.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
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 | ||
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 | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | * | ||
27 | */ | ||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Text; | ||
31 | using System.Drawing; | ||
32 | using libTerrain; | ||
33 | |||
34 | namespace OpenSim.Terrain | ||
35 | { | ||
36 | public class TerrainEngine | ||
37 | { | ||
38 | /// <summary> | ||
39 | /// A [normally] 256x256 heightmap | ||
40 | /// </summary> | ||
41 | public Channel heightmap; | ||
42 | |||
43 | /// <summary> | ||
44 | /// Whether or not the terrain has been modified since it was last saved and sent to the Physics engine. | ||
45 | /// Counts the number of modifications since the last save. (0 = Untainted) | ||
46 | /// </summary> | ||
47 | public int tainted; | ||
48 | |||
49 | int w, h; | ||
50 | |||
51 | /// <summary> | ||
52 | /// Generate a new TerrainEngine instance and creates a new heightmap | ||
53 | /// </summary> | ||
54 | public TerrainEngine() | ||
55 | { | ||
56 | w = 256; | ||
57 | h = 256; | ||
58 | heightmap = new Channel(w, h); | ||
59 | |||
60 | tainted++; | ||
61 | } | ||
62 | |||
63 | /// <summary> | ||
64 | /// Converts the heightmap to a 65536 value 1D floating point array | ||
65 | /// </summary> | ||
66 | /// <returns>A float[65536] array containing the heightmap</returns> | ||
67 | public float[] getHeights1D() | ||
68 | { | ||
69 | float[] heights = new float[w * h]; | ||
70 | int i; | ||
71 | |||
72 | for (i = 0; i < w * h; i++) | ||
73 | { | ||
74 | heights[i] = (float)heightmap.map[i / w, i % w]; | ||
75 | } | ||
76 | |||
77 | return heights; | ||
78 | } | ||
79 | |||
80 | /// <summary> | ||
81 | /// Converts the heightmap to a 256x256 value 2D floating point array. | ||
82 | /// </summary> | ||
83 | /// <returns>An array of 256,256 values containing the heightmap</returns> | ||
84 | public float[,] getHeights2D() | ||
85 | { | ||
86 | float[,] heights = new float[w, h]; | ||
87 | int x, y; | ||
88 | for (x = 0; x < w; x++) | ||
89 | { | ||
90 | for (y = 0; y < h; y++) | ||
91 | { | ||
92 | heights[x, y] = (float)heightmap.map[x, y]; | ||
93 | } | ||
94 | } | ||
95 | return heights; | ||
96 | } | ||
97 | |||
98 | /// <summary> | ||
99 | /// Imports a 1D floating point array into the 2D heightmap array | ||
100 | /// </summary> | ||
101 | /// <param name="heights">The array to import (must have 65536 members)</param> | ||
102 | public void setHeights1D(float[] heights) | ||
103 | { | ||
104 | int i; | ||
105 | for (i = 0; i < w * h; i++) | ||
106 | { | ||
107 | heightmap.map[i / w, i % w] = heights[i]; | ||
108 | } | ||
109 | |||
110 | tainted++; | ||
111 | } | ||
112 | |||
113 | /// <summary> | ||
114 | /// Loads a 2D array of values into the heightmap | ||
115 | /// </summary> | ||
116 | /// <param name="heights">An array of 256,256 float values</param> | ||
117 | public void setHeights2D(float[,] heights) | ||
118 | { | ||
119 | int x, y; | ||
120 | for (x = 0; x < w; x++) | ||
121 | { | ||
122 | for (y = 0; y < h; y++) | ||
123 | { | ||
124 | heightmap.set(x, y, (double)heights[x, y]); | ||
125 | } | ||
126 | } | ||
127 | tainted++; | ||
128 | } | ||
129 | |||
130 | /// <summary> | ||
131 | /// Processes a terrain-specific command | ||
132 | /// </summary> | ||
133 | /// <param name="args">Commandline arguments (space seperated)</param> | ||
134 | /// <param name="resultText">Reference that returns error or help text if returning false</param> | ||
135 | /// <returns>If the operation was successful (if not, the error is placed into resultText)</returns> | ||
136 | public bool RunTerrainCmd(string[] args, ref string resultText) | ||
137 | { | ||
138 | string command = args[0]; | ||
139 | |||
140 | try | ||
141 | { | ||
142 | |||
143 | switch (command) | ||
144 | { | ||
145 | case "help": | ||
146 | resultText += "terrain regenerate - rebuilds the sims terrain using a default algorithm\n"; | ||
147 | resultText += "terrain seed <seed> - sets the random seed value to <seed>\n"; | ||
148 | resultText += "terrain load <type> <filename> - loads a terrain from disk, type can be 'F32', 'F64', 'RAW' or 'IMG'\n"; | ||
149 | resultText += "terrain save <type> <filename> - saves a terrain to disk, type can be 'F32' or 'F64'\n"; | ||
150 | resultText += "terrain save grdmap <filename> <gradient map> - creates a PNG snapshot of the region using a named gradient map\n"; | ||
151 | resultText += "terrain rescale <min> <max> - rescales a terrain to be between <min> and <max> meters high\n"; | ||
152 | resultText += "terrain erode aerobic <windspeed> <pickupmin> <dropmin> <carry> <rounds> <lowest>\n"; | ||
153 | resultText += "terrain erode thermal <talus> <rounds> <carry>\n"; | ||
154 | resultText += "terrain multiply <val> - multiplies a terrain by <val>\n"; | ||
155 | return false; | ||
156 | |||
157 | case "seed": | ||
158 | setSeed(Convert.ToInt32(args[1])); | ||
159 | break; | ||
160 | |||
161 | case "erode": | ||
162 | switch (args[1].ToLower()) | ||
163 | { | ||
164 | case "aerobic": | ||
165 | // WindSpeed, PickupMinimum,DropMinimum,Carry,Rounds,Lowest | ||
166 | 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])); | ||
167 | break; | ||
168 | case "thermal": | ||
169 | heightmap.thermalWeathering(Convert.ToDouble(args[2]), Convert.ToInt32(args[3]), Convert.ToDouble(args[4])); | ||
170 | break; | ||
171 | default: | ||
172 | resultText = "Unknown erosion type"; | ||
173 | return false; | ||
174 | } | ||
175 | break; | ||
176 | |||
177 | case "regenerate": | ||
178 | hills(); | ||
179 | break; | ||
180 | |||
181 | case "rescale": | ||
182 | setRange(Convert.ToSingle(args[1]), Convert.ToSingle(args[2])); | ||
183 | break; | ||
184 | |||
185 | case "multiply": | ||
186 | heightmap *= Convert.ToDouble(args[1]); | ||
187 | break; | ||
188 | |||
189 | case "load": | ||
190 | switch (args[1].ToLower()) | ||
191 | { | ||
192 | case "f32": | ||
193 | loadFromFileF32(args[2]); | ||
194 | break; | ||
195 | |||
196 | case "f64": | ||
197 | loadFromFileF64(args[2]); | ||
198 | break; | ||
199 | |||
200 | case "raw": | ||
201 | loadFromFileSLRAW(args[2]); | ||
202 | break; | ||
203 | |||
204 | case "img": | ||
205 | loadFromFileIMG(args[2]); | ||
206 | return false; | ||
207 | |||
208 | default: | ||
209 | resultText = "Unknown image or data format"; | ||
210 | return false; | ||
211 | } | ||
212 | break; | ||
213 | |||
214 | case "save": | ||
215 | switch (args[1].ToLower()) | ||
216 | { | ||
217 | case "f32": | ||
218 | writeToFileF32(args[2]); | ||
219 | break; | ||
220 | |||
221 | case "f64": | ||
222 | writeToFileF64(args[2]); | ||
223 | break; | ||
224 | |||
225 | case "grdmap": | ||
226 | exportImage(args[2], args[3]); | ||
227 | break; | ||
228 | |||
229 | default: | ||
230 | resultText = "Unknown image or data format"; | ||
231 | return false; | ||
232 | } | ||
233 | break; | ||
234 | |||
235 | default: | ||
236 | resultText = "Unknown terrain command"; | ||
237 | return false; | ||
238 | } | ||
239 | return true; | ||
240 | } | ||
241 | catch (Exception e) | ||
242 | { | ||
243 | resultText = "Error running terrain command: " + e.ToString(); | ||
244 | return false; | ||
245 | } | ||
246 | } | ||
247 | |||
248 | /// <summary> | ||
249 | /// Renormalises the array between min and max | ||
250 | /// </summary> | ||
251 | /// <param name="min">Minimum value of the new array</param> | ||
252 | /// <param name="max">Maximum value of the new array</param> | ||
253 | public void setRange(float min, float max) | ||
254 | { | ||
255 | heightmap.normalise((double)min, (double)max); | ||
256 | tainted++; | ||
257 | } | ||
258 | |||
259 | /// <summary> | ||
260 | /// Loads a file from an image compatible with System.Drawing | ||
261 | /// </summary> | ||
262 | /// <param name="filename">File to load</param> | ||
263 | public void loadFromFileIMG(string filename) | ||
264 | { | ||
265 | System.Drawing.Bitmap bmp = new Bitmap(filename); | ||
266 | |||
267 | if (bmp.Width != heightmap.w && bmp.Height != heightmap.h) | ||
268 | throw new Exception("Wrong image size! Images for this region must be " + heightmap.w.ToString() + " by " + heightmap.h.ToString() + " pixels in dimension"); | ||
269 | |||
270 | int x, y; | ||
271 | |||
272 | for (x = 0; x < w; x++) | ||
273 | { | ||
274 | for (y = 0; y < h; y++) | ||
275 | { | ||
276 | Color c = bmp.GetPixel(x, y); | ||
277 | } | ||
278 | } | ||
279 | } | ||
280 | |||
281 | /// <summary> | ||
282 | /// Loads a file consisting of 256x256 doubles and imports it as an array into the map. | ||
283 | /// </summary> | ||
284 | /// <remarks>TODO: Move this to libTerrain itself</remarks> | ||
285 | /// <param name="filename">The filename of the double array to import</param> | ||
286 | public void loadFromFileF64(string filename) | ||
287 | { | ||
288 | System.IO.FileInfo file = new System.IO.FileInfo(filename); | ||
289 | System.IO.FileStream s = file.Open(System.IO.FileMode.Open, System.IO.FileAccess.Read); | ||
290 | System.IO.BinaryReader bs = new System.IO.BinaryReader(s); | ||
291 | int x, y; | ||
292 | for (x = 0; x < w; x++) | ||
293 | { | ||
294 | for (y = 0; y < h; y++) | ||
295 | { | ||
296 | heightmap.map[x, y] = bs.ReadDouble(); | ||
297 | } | ||
298 | } | ||
299 | |||
300 | bs.Close(); | ||
301 | s.Close(); | ||
302 | |||
303 | tainted++; | ||
304 | } | ||
305 | |||
306 | /// <summary> | ||
307 | /// Loads a file consisting of 256x256 floats and imports it as an array into the map. | ||
308 | /// </summary> | ||
309 | /// <remarks>TODO: Move this to libTerrain itself</remarks> | ||
310 | /// <param name="filename">The filename of the float array to import</param> | ||
311 | public void loadFromFileF32(string filename) | ||
312 | { | ||
313 | System.IO.FileInfo file = new System.IO.FileInfo(filename); | ||
314 | System.IO.FileStream s = file.Open(System.IO.FileMode.Open, System.IO.FileAccess.Read); | ||
315 | System.IO.BinaryReader bs = new System.IO.BinaryReader(s); | ||
316 | int x, y; | ||
317 | for (x = 0; x < w; x++) | ||
318 | { | ||
319 | for (y = 0; y < h; y++) | ||
320 | { | ||
321 | heightmap.map[x, y] = (double)bs.ReadSingle(); | ||
322 | } | ||
323 | } | ||
324 | |||
325 | bs.Close(); | ||
326 | s.Close(); | ||
327 | |||
328 | tainted++; | ||
329 | } | ||
330 | |||
331 | /// <summary> | ||
332 | /// Loads a file formatted in the SL .RAW Format used on the main grid | ||
333 | /// </summary> | ||
334 | /// <remarks>This file format stinks and is best avoided.</remarks> | ||
335 | /// <param name="filename">A path to the .RAW format</param> | ||
336 | public void loadFromFileSLRAW(string filename) | ||
337 | { | ||
338 | System.IO.FileInfo file = new System.IO.FileInfo(filename); | ||
339 | System.IO.FileStream s = file.Open(System.IO.FileMode.Open, System.IO.FileAccess.Read); | ||
340 | System.IO.BinaryReader bs = new System.IO.BinaryReader(s); | ||
341 | int x, y; | ||
342 | for (x = 0; x < w; x++) | ||
343 | { | ||
344 | for (y = 0; y < h; y++) | ||
345 | { | ||
346 | heightmap.map[x, y] = (double)bs.ReadByte() * ((double)bs.ReadByte() / 127.0); | ||
347 | bs.ReadBytes(11); // Advance the stream to next bytes. | ||
348 | } | ||
349 | } | ||
350 | |||
351 | bs.Close(); | ||
352 | s.Close(); | ||
353 | |||
354 | tainted++; | ||
355 | } | ||
356 | |||
357 | /// <summary> | ||
358 | /// Writes the current terrain heightmap to disk, in the format of a 65536 entry double[] array. | ||
359 | /// </summary> | ||
360 | /// <param name="filename">The desired output filename</param> | ||
361 | public void writeToFileF64(string filename) | ||
362 | { | ||
363 | System.IO.FileInfo file = new System.IO.FileInfo(filename); | ||
364 | System.IO.FileStream s = file.Open(System.IO.FileMode.CreateNew, System.IO.FileAccess.Write); | ||
365 | System.IO.BinaryWriter bs = new System.IO.BinaryWriter(s); | ||
366 | |||
367 | int x, y; | ||
368 | for (x = 0; x < w; x++) | ||
369 | { | ||
370 | for (y = 0; y < h; y++) | ||
371 | { | ||
372 | bs.Write(heightmap.get(x, y)); | ||
373 | } | ||
374 | } | ||
375 | |||
376 | bs.Close(); | ||
377 | s.Close(); | ||
378 | } | ||
379 | |||
380 | /// <summary> | ||
381 | /// Writes the current terrain heightmap to disk, in the format of a 65536 entry float[] array | ||
382 | /// </summary> | ||
383 | /// <param name="filename">The desired output filename</param> | ||
384 | public void writeToFileF32(string filename) | ||
385 | { | ||
386 | System.IO.FileInfo file = new System.IO.FileInfo(filename); | ||
387 | System.IO.FileStream s = file.Open(System.IO.FileMode.CreateNew, System.IO.FileAccess.Write); | ||
388 | System.IO.BinaryWriter bs = new System.IO.BinaryWriter(s); | ||
389 | |||
390 | int x, y; | ||
391 | for (x = 0; x < w; x++) | ||
392 | { | ||
393 | for (y = 0; y < h; y++) | ||
394 | { | ||
395 | bs.Write((float)heightmap.get(x, y)); | ||
396 | } | ||
397 | } | ||
398 | |||
399 | bs.Close(); | ||
400 | s.Close(); | ||
401 | } | ||
402 | |||
403 | /// <summary> | ||
404 | /// Sets the random seed to be used by procedural functions which involve random numbers. | ||
405 | /// </summary> | ||
406 | /// <param name="val">The desired seed</param> | ||
407 | public void setSeed(int val) | ||
408 | { | ||
409 | heightmap.seed = val; | ||
410 | } | ||
411 | |||
412 | /// <summary> | ||
413 | /// Raises land in a sphere around the specified coordinates | ||
414 | /// </summary> | ||
415 | /// <param name="rx">Center of the sphere on the X axis</param> | ||
416 | /// <param name="ry">Center of the sphere on the Y axis</param> | ||
417 | /// <param name="size">The radius of the sphere</param> | ||
418 | /// <param name="amount">Scale the height of the sphere by this amount (recommended 0..2)</param> | ||
419 | public void raise(double rx, double ry, double size, double amount) | ||
420 | { | ||
421 | lock (heightmap) | ||
422 | { | ||
423 | heightmap.raise(rx, ry, size, amount); | ||
424 | } | ||
425 | |||
426 | tainted++; | ||
427 | } | ||
428 | |||
429 | /// <summary> | ||
430 | /// Lowers the land in a sphere around the specified coordinates | ||
431 | /// </summary> | ||
432 | /// <param name="rx">The center of the sphere at the X axis</param> | ||
433 | /// <param name="ry">The center of the sphere at the Y axis</param> | ||
434 | /// <param name="size">The radius of the sphere in meters</param> | ||
435 | /// <param name="amount">Scale the height of the sphere by this amount (recommended 0..2)</param> | ||
436 | public void lower(double rx, double ry, double size, double amount) | ||
437 | { | ||
438 | lock (heightmap) | ||
439 | { | ||
440 | heightmap.lower(rx, ry, size, amount); | ||
441 | } | ||
442 | |||
443 | tainted++; | ||
444 | } | ||
445 | |||
446 | /// <summary> | ||
447 | /// Generates a simple set of hills in the shape of an island | ||
448 | /// </summary> | ||
449 | public void hills() | ||
450 | { | ||
451 | lock (heightmap) | ||
452 | { | ||
453 | heightmap.hillsSpheres(200, 20, 40, true, true, false); | ||
454 | heightmap.normalise(); | ||
455 | heightmap *= 60.0; // Raise to 60m | ||
456 | } | ||
457 | |||
458 | tainted++; | ||
459 | } | ||
460 | |||
461 | /// <summary> | ||
462 | /// Multiplies the heightfield by val | ||
463 | /// </summary> | ||
464 | /// <param name="meep">The heightfield</param> | ||
465 | /// <param name="val">The multiplier</param> | ||
466 | /// <returns></returns> | ||
467 | public static TerrainEngine operator *(TerrainEngine meep, Double val) | ||
468 | { | ||
469 | meep.heightmap *= val; | ||
470 | meep.tainted++; | ||
471 | return meep; | ||
472 | } | ||
473 | |||
474 | /// <summary> | ||
475 | /// Returns the height at the coordinates x,y | ||
476 | /// </summary> | ||
477 | /// <param name="x">X Coordinate</param> | ||
478 | /// <param name="y">Y Coordinate</param> | ||
479 | /// <returns></returns> | ||
480 | public float this[int x, int y] | ||
481 | { | ||
482 | get | ||
483 | { | ||
484 | return (float)heightmap.get(x, y); | ||
485 | } | ||
486 | set | ||
487 | { | ||
488 | tainted++; | ||
489 | heightmap.set(x, y, (double)value); | ||
490 | } | ||
491 | } | ||
492 | |||
493 | /// <summary> | ||
494 | /// Exports the current heightmap to a PNG file | ||
495 | /// </summary> | ||
496 | /// <param name="filename">The destination filename for the image</param> | ||
497 | /// <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> | ||
498 | public void exportImage(string filename, string gradientmap) | ||
499 | { | ||
500 | try | ||
501 | { | ||
502 | Bitmap gradientmapLd = new Bitmap(gradientmap); | ||
503 | |||
504 | int pallete = gradientmapLd.Height; | ||
505 | |||
506 | Bitmap bmp = new Bitmap(heightmap.w, heightmap.h); | ||
507 | Color[] colours = new Color[pallete]; | ||
508 | |||
509 | for (int i = 0; i < pallete; i++) | ||
510 | { | ||
511 | colours[i] = gradientmapLd.GetPixel(0, i); | ||
512 | } | ||
513 | |||
514 | Channel copy = heightmap.copy(); | ||
515 | for (int x = 0; x < copy.w; x++) | ||
516 | { | ||
517 | for (int y = 0; y < copy.h; y++) | ||
518 | { | ||
519 | // 512 is the largest possible height before colours clamp | ||
520 | int colorindex = (int)(Math.Max(Math.Min(1.0, copy.get(x, y) / 512.0), 0.0) * pallete); | ||
521 | bmp.SetPixel(y, 255 - x, colours[colorindex]); | ||
522 | } | ||
523 | } | ||
524 | |||
525 | bmp.Save(filename, System.Drawing.Imaging.ImageFormat.Png); | ||
526 | } | ||
527 | catch (Exception e) | ||
528 | { | ||
529 | Console.WriteLine("Failed generating terrain map: " + e.ToString()); | ||
530 | } | ||
531 | } | ||
532 | } | ||
533 | } \ No newline at end of file | ||