public static void Main(String[] args) { Console.WriteLine("Procedurality CLI - (c)2009 Rob \"N3X15\" Nelson"); Console.WriteLine("_______________________________________________________________\n"); foreach (String s in args) { //Console.WriteLine(s); } Arguments CommandLine = new Arguments(args); String action = "help"; String file = "in.png"; String ofile = "out"; int seed = DateTime.Now.Millisecond; Size = 256; bool FlipV = false; if (CommandLine["flip-v"] != null) { FlipV = true; } // --help if (CommandLine["help"] != null) { Help(); } // --seed=1234567890 if (CommandLine["seed"] != null) { seed = int.Parse(CommandLine["seed"]); } Console.WriteLine(" * Random seed: " + seed.ToString()); if (CommandLine["size"] != null) { Size = uint.Parse(CommandLine["size"]); } Channel terrain; if (CommandLine["perlin"] != null) { Console.Write("Generating terrain with perlin noise..."); terrain = new Mountain((int)Size, Utils.powerOf2Log2((int)Size) - 6, 0.5f, seed).toChannel(); Console.WriteLine(" DONE!"); } else if (CommandLine["in"] != null) { Console.Write("Loading " + file + "..."); terrain = LoadTerrain(CommandLine["in"]); if (FlipV) { terrain = terrain.flipV(); } Console.WriteLine(" Done!"); if (CommandLine["tiledir"] != null && CommandLine["tilesize"] != null) { string tiledir = CommandLine["tiledir"]; if (!Directory.Exists(tiledir)) { Directory.CreateDirectory(tiledir); } MakeTiles(terrain, uint.Parse(CommandLine["tilesize"]), tiledir); } } else if (CommandLine["hills"] != null) { Console.Write("Generating " + CommandLine["hills"] + " hills..."); terrain = HillsAlgo((int)Size, int.Parse(CommandLine["hills"]), seed); Console.WriteLine(" DONE!"); } else if (CommandLine["craters"] != null) { Console.Write("Generating " + CommandLine["craters"] + " craters..."); terrain = CratersAlgo((int)Size, int.Parse(CommandLine["craters"]), seed); Console.WriteLine(" DONE!"); } else { Console.WriteLine("Please use --perlin, --in, --hills, or --craters to load some terrain."); return; } ofile = args[args.Length - 1]; if (CommandLine["addcliffs"] != null) { int features = 4; if (CommandLine["features"] != null) { features = int.Parse(CommandLine["features"]); } Console.WriteLine("Adding cliffs."); // add mountain peaks Voronoi voronoi = new Voronoi(256, 4, 4, 1, 1f, seed); Channel cliffs = voronoi.getDistance(-1f, 1f, 0f).brightness(1.5f).multiply(0.33f); terrain.multiply(0.67f).channelAdd(cliffs); terrain.channelSubtract(voronoi.getDistance(1f, 0f, 0f).gamma(.5f).flipV().rotate(90)); } if (CommandLine["iceage"] != null) { float hills = 0.5f; if (CommandLine["hillratio"] != null) { hills = float.Parse(CommandLine["hillratio"]); } Console.WriteLine("Ice age erosion in progress."); terrain.perturb(new Midpoint((int)Size, 2, hills, seed).toChannel(), 0.25f); } if (CommandLine["thermal"] != null) { float hills = 0.5f; if (CommandLine["hillratio"] != null) { hills = float.Parse(CommandLine["hillratio"]); } terrain.erodeThermal((24f - hills * 12f) / (int)Size, (int)Size >> 2); } // Hydraulic Erosion if (CommandLine["hydraulic"] != null) { Console.WriteLine("Hydraulic erosion in progress."); // let it rain for a couple of thousand years float hills = 0.5f; if (CommandLine["hillratio"] != null) { hills = float.Parse(CommandLine["hillratio"]); } terrain.erode((24f - hills * 12f) / (int)Size, (int)Size >> 2); } if (CommandLine["slow-hydro"] != null) { terrain = ErosionHydraulic.erode1(terrain, terrain.copy().multiply(0.01f), 0.1f, 1, 100); terrain = ErosionHydraulic.erode2(terrain, terrain.copy().multiply(0.01f), 0.1f, 1, 100); terrain = ErosionHydraulic.erode3(terrain, terrain.copy().multiply(0.01f), 0.1f, 1, 100); terrain = ErosionHydraulic.erode4(terrain, 0.01f, 0.1f, 1, 100); terrain = ErosionHydraulic.erode5(terrain, terrain.copy().multiply(0.01f), 0.1f, 0.1f, 0.1f, 20f, 0.5f, 1, 100); } if (CommandLine["add-silt"] != null) { float wl = 20f / 256f; wl = float.Parse(CommandLine["add-silt"]); terrain = terrain.silt(wl, true); } if (CommandLine["add-river"] != null) { terrain.normalize(1f, 0.3f); List <PathFinderNode> path; terrain = (new RiverBuilder(terrain)).GenerateRiver(20f, seed, out path).toChannel(); terrain.normalize(); string rpath = ""; foreach (PathFinderNode p in path) { rpath += string.Format("{0},{1}\n", p.X, p.Y); } File.WriteAllText(ofile + ".river.txt", rpath); } terrain.smooth(1); float nm = 0f; float nM = 1f; if (CommandLine["range-max"] != null) { nM = float.Parse(CommandLine["range-max"]); } if (CommandLine["range-min"] != null) { nm = float.Parse(CommandLine["range-min"]); } if (nm > 1f || nM > 1f) { nm = nm / 256f; nM = nM / 256f; } terrain.normalize(nm, nM).toLayer().saveAsPNG(ofile); }
private void Gen(int size, int base_freq, float pers, long seed, int x_o, int y_o) { if (!Utils.isPowerOf2(size)) { throw new Exception("size must be power of 2"); } int iterations = Utils.powerOf2Log2(size); base_freq = Math.Max(base_freq, 0); base_freq = Math.Min(base_freq, iterations); random = new Random((int)seed); channel = new Channel(size, size); int x_block, y_block, x, y; if (base_freq > 0) { int block_size = size >> base_freq; for (int x_b = 0; x_b < (1 << base_freq); x_b++) { for (int y_b = 0; y_b < (1 << base_freq); y_b++) { x = x_b * block_size; y = y_b * block_size; channel.putPixel(x, y, (float)random.NextDouble()); } } } float v1, v2, v3, v4, v5, v6, v7, v8, v9; for (int i = base_freq; i < iterations; i++) { int block_size = size >> i; int block_size_half = size >> (i + 1); float amp = (float)Math.Pow(pers, i - base_freq); float amp_half = 0.5f * amp; float avr; // calculate center midpoints if (i < 2) { for (x_block = 0, x = 0; x_block < (1 << i); x_block++) { for (y_block = 0, y = 0; y_block < (1 << i); y_block++) { v1 = channel.getPixel(x, y); v2 = channel.getPixel((x + block_size) % size, y); v3 = channel.getPixel(x, (y + block_size) % size); v4 = channel.getPixel((x + block_size) % size, (y + block_size) % size); avr = 0.25f * (v1 + v2 + v3 + v4); v5 = avr * (1f + (float)random.NextDouble() * amp - amp_half); channel.putPixel(x + block_size_half, y + block_size_half, v5); y += block_size; } x += block_size; } } else { // safe blocks for (x_block = 1, x = block_size; x_block < (1 << i) - 1; x_block++) { for (y_block = 1, y = block_size; y_block < (1 << i) - 1; y_block++) { v1 = channel.getPixel(x, y); v2 = channel.getPixel(x + block_size, y); v3 = channel.getPixel(x, y + block_size); v4 = channel.getPixel(x + block_size, y + block_size); avr = 0.25f * (v1 + v2 + v3 + v4); v5 = avr * (1f + (float)random.NextDouble() * amp - amp_half); channel.putPixel(x + block_size_half, y + block_size_half, v5); y += block_size; } x += block_size; } // left and right edge blocks for (x_block = 0; x_block < (1 << i); x_block += (1 << i) - 1) { x = x_block * block_size; for (y_block = 0, y = 0; y_block < (1 << i); y_block++) { v1 = channel.getPixel(x, y); v2 = channel.getPixel((x + block_size) % size, y); v3 = channel.getPixel(x, (y + block_size) % size); v4 = channel.getPixel((x + block_size) % size, (y + block_size) % size); avr = 0.25f * (v1 + v2 + v3 + v4); v5 = avr * (1f + (float)random.NextDouble() * amp - amp_half); channel.putPixel(x + block_size_half, y + block_size_half, v5); y += block_size; } } // top and bottom edge blocks for (x_block = 1, x = block_size; x_block < (1 << i) - 1; x_block++) { for (y_block = 0; y_block < (1 << i); y_block += (1 << i) - 1) { y = y_block * block_size; v1 = channel.getPixel(x, y); v2 = channel.getPixel((x + block_size) % size, y); v3 = channel.getPixel(x, (y + block_size) % size); v4 = channel.getPixel((x + block_size) % size, (y + block_size) % size); avr = 0.25f * (v1 + v2 + v3 + v4); v5 = avr * (1f + (float)random.NextDouble() * amp - amp_half); channel.putPixel(x + block_size_half, y + block_size_half, v5); } x += block_size; } } // calculate left and bottom edge midpoints if (i < 2) { for (x_block = 0, x = 0; x_block < (1 << i); x_block++) { for (y_block = 0, y = 0; y_block < (1 << i); y_block++) { v1 = channel.getPixel(x, y); v5 = channel.getPixel(x + block_size_half, y + block_size_half); v2 = channel.getPixel((x + block_size) % size, y); v3 = channel.getPixel(x, (y + block_size) % size); v6 = channel.getPixel(((x - block_size_half) + size) % size, (y + block_size_half) % size); v7 = channel.getPixel((x + block_size_half) % size, ((y - block_size_half) + size) % size); avr = 0.25f * (v1 + v3 + v5 + v6); v8 = avr * (1f + (float)random.NextDouble() * amp - amp_half); avr = 0.25f * (v1 + v2 + v5 + v7); v9 = avr * (1f + (float)random.NextDouble() * amp - amp_half); channel.putPixel(x, y + block_size_half, v8); channel.putPixel(x + block_size_half, y, v9); y += block_size; } x += block_size; } } else { // safe blocks for (x_block = 1, x = block_size; x_block < (1 << i) - 1; x_block++) { for (y_block = 1, y = block_size; y_block < (1 << i) - 1; y_block++) { v1 = channel.getPixel(x, y); v5 = channel.getPixel(x + block_size_half, y + block_size_half); v2 = channel.getPixel(x + block_size, y); v3 = channel.getPixel(x, y + block_size); v6 = channel.getPixel(x - block_size_half, y + block_size_half); v7 = channel.getPixel(x + block_size_half, y - block_size_half); avr = 0.25f * (v1 + v3 + v5 + v6); v8 = avr * (1f + (float)random.NextDouble() * amp - amp_half); avr = 0.25f * (v1 + v2 + v5 + v7); v9 = avr * (1f + (float)random.NextDouble() * amp - amp_half); channel.putPixel(x, y + block_size_half, v8); channel.putPixel(x + block_size_half, y, v9); y += block_size; } x += block_size; } // left and right edge blocks for (x_block = 0; x_block < (1 << i); x_block += (1 << i) - 1) { x = x_block * block_size; for (y_block = 0, y = 0; y_block < (1 << i); y_block++) { v1 = channel.getPixel(x, y); v5 = channel.getPixel(x + block_size_half, y + block_size_half); v2 = channel.getPixel((x + block_size) % size, y); v3 = channel.getPixel(x, (y + block_size) % size); v6 = channel.getPixel(((x - block_size_half) + size) % size, (y + block_size_half) % size); v7 = channel.getPixel((x + block_size_half) % size, ((y - block_size_half) + size) % size); avr = 0.25f * (v1 + v3 + v5 + v6); v8 = avr * (1f + (float)random.NextDouble() * amp - amp_half); avr = 0.25f * (v1 + v2 + v5 + v7); v9 = avr * (1f + (float)random.NextDouble() * amp - amp_half); channel.putPixel(x, y + block_size_half, v8); channel.putPixel(x + block_size_half, y, v9); y += block_size; } } // top and bottom edge blocks for (x_block = 1, x = block_size; x_block < (1 << i) - 1; x_block++) { for (y_block = 0; y_block < (1 << i); y_block += (1 << i) - 1) { y = y_block * block_size; v1 = channel.getPixel(x, y); v5 = channel.getPixel(x + block_size_half, y + block_size_half); v2 = channel.getPixel((x + block_size) % size, y); v3 = channel.getPixel(x, (y + block_size) % size); v6 = channel.getPixel(((x - block_size_half) + size) % size, (y + block_size_half) % size); v7 = channel.getPixel((x + block_size_half) % size, ((y - block_size_half) + size) % size); avr = 0.25f * (v1 + v3 + v5 + v6); v8 = avr * (1f + (float)random.NextDouble() * amp - amp_half); avr = 0.25f * (v1 + v2 + v5 + v7); v9 = avr * (1f + (float)random.NextDouble() * amp - amp_half); channel.putPixel(x, y + block_size_half, v8); channel.putPixel(x + block_size_half, y, v9); } x += block_size; } } } float[] mm = channel.findMinMax(); Console.WriteLine("Range Mountain->[{0},{1}]", mm[0], mm[1]); channel.normalize(); mm = channel.findMinMax(); Console.WriteLine("Range Mountain->[{0},{1}]", mm[0], mm[1]); }