public static void RunMeterScaleMapScenario() { var wta = new WaterTableArgs(); var waters = new FieldFromBitmap(new Bitmap(wta.inputPath + "rivers.png")); var heights = new FieldFromBitmap(new Bitmap(wta.inputPath + "base_heights.png")); var msmArgs = new MeterScaleMap.Args(waters, heights, heights, null); msmArgs.seed = System.DateTime.UtcNow.Ticks; msmArgs.metersPerPixel = 1600; msmArgs.riverCapacityToMetersWideFunc = c => (float)Math.Sqrt(msmArgs.metersPerPixel * SplineTree.CAPACITY_DIVISOR * c); var msm = new MeterScaleMap(msmArgs); msm.OutputHighLevelMaps(new Bitmap(waters.Width, waters.Height), "C:\\Users\\Justin Murray\\Desktop\\terrain\\"); msm.OutputMapGrid(100, "C:\\Users\\Justin Murray\\Desktop\\terrain\\", "submap"); }
public static void RunMeterScaleMapScenarioUR() { var wta = new WaterTableArgs(); var waters = new FieldFromBitmap(new Bitmap(wta.inputPath + "rivers_ur_alt.png")); var heights = new FieldFromBitmap(new Bitmap(wta.inputPath + "base_heights_ur_alt.png")); var roughness = new FieldFromBitmap(new Bitmap(wta.inputPath + "base_heights_ur_alt.png")); var msmArgs = new MeterScaleMap.Args(waters, heights, roughness, null); msmArgs.seed = System.DateTime.UtcNow.Ticks; msmArgs.metersPerPixel = 1600 / 5; msmArgs.riverCapacityToMetersWideFunc = c => (float)Math.Pow(msmArgs.metersPerPixel * SplineTree.CAPACITY_DIVISOR * c, 0.5f) / 4f; msmArgs.baseHeightMaxInMeters = 800f; msmArgs.mountainHeightMaxInMeters = 3000f; msmArgs.valleyStrength = 0.98f; // TODO: Enable a function to control valley width, strength, and glaciation. var msm = new MeterScaleMap(msmArgs); msm.OutputHighLevelMaps(new Bitmap(waters.Width, waters.Height), "C:\\Users\\Justin Murray\\Desktop\\terrain\\"); msm.OutputMapGrid(100, "C:\\Users\\Justin Murray\\Desktop\\terrain\\", "submap", 256); }
public static void RunWaterHeightScenario(string simpleWatersMapName, string simpleAltitudesMapName) { WaterTableArgs args = new WaterTableArgs(); args.seed = System.DateTime.UtcNow.Ticks; Random random = new Random((int)args.seed); Bitmap jranjana = new Bitmap(args.inputPath + simpleWatersMapName); Field2d <float> field = new Utils.FieldFromBitmap(jranjana); IField2d <float> bf = new Utils.FieldFromBitmap(new Bitmap(args.inputPath + simpleAltitudesMapName)); bf = new NormalizedComposition2d <float>(bf, new ScaleTransform(new Simplex2D(bf.Width, bf.Height, args.baseNoiseScale, args.seed), args.baseNoiseScalar)); Utils.OutputField(bf, jranjana, args.outputPath + "basis.png"); BrownianTree tree = BrownianTree.CreateFromOther(field, (x) => x > 0.5f ? BrownianTree.Availability.Available : BrownianTree.Availability.Unavailable, random); tree.RunDefaultTree(); Utils.OutputField(new Transformation2d <BrownianTree.Availability, float>(tree, val => val == BrownianTree.Availability.Available ? 1f : 0f), jranjana, args.outputPath + "rivers.png"); HydrologicalField hydro = new HydrologicalField(tree, args.hydroSensitivity, args.hydroShoreThreshold); WaterTableField wtf = new WaterTableField(bf, hydro, args.wtfShore, args.wtfIt, args.wtfLen, args.wtfGrade, () => { return((float)(args.wtfCarveAdd + random.NextDouble() * args.wtfCarveMul)); }); Utils.OutputAsTributaryMap(wtf.GeographicFeatures, wtf.RiverSystems, wtf.DrainageField, jranjana, args.outputPath + "tributaries.png"); Utils.OutputField(new NormalizedComposition2d <float>(new Transformation2d <float, float, float>(bf, wtf, (b, w) => Math.Abs(b - w))), jranjana, args.outputPath + "errors.png"); Utils.SerializeMap(hydro, wtf, args.seed, args.outputPath + "serialization.bin"); Utils.OutputField(wtf, jranjana, args.outputPath + "heightmap.png"); Utils.OutputAsColoredMap(wtf, wtf.RiverSystems, jranjana, args.outputPath + "colored_map.png"); }
public static WaterTableField GenerateWaters(Bitmap bmp, IField2d <float> baseField = null, WaterTableArgs args = null, Random random = null) { args = args ?? new WaterTableArgs() { seed = System.DateTime.UtcNow.Ticks }; random = random ?? new Random((int)args.seed); baseField = baseField ?? new Simplex2D(bmp.Width, bmp.Height, args.baseNoiseScale, args.seed); Field2d <float> field = new FieldFromBitmap(bmp); baseField = new NormalizedComposition2d <float>(baseField, new ScaleTransform(new Simplex2D(baseField.Width, baseField.Height, args.baseNoiseScale, args.seed), args.baseNoiseScalar)); BrownianTree tree = BrownianTree.CreateFromOther(field, (x) => x > 0.5f ? BrownianTree.Availability.Available : BrownianTree.Availability.Unavailable, random); tree.RunDefaultTree(); HydrologicalField hydro = new HydrologicalField(tree, args.hydroSensitivity, args.hydroShoreThreshold); WaterTableField wtf = new WaterTableField(baseField, hydro, args.wtfShore, args.wtfIt, args.wtfLen, args.wtfGrade, () => { return((float)(args.wtfCarveAdd + random.NextDouble() * args.wtfCarveMul)); }); return(wtf); }
public static void RunZoomedInScenario() { // 32x32 up to 1024x1024 will, from the fifth-of-a-mile-per-pixel source, get us approximately 10m per pixel. // 16x16 would get us 5 // 8x8 would get us 2.5 // 4x4 would get us 1.25 // 2x2 would get us .75 // 1x1 would get us .375, which is slightly over 1 foot. // I think 16x16 is the sweet spot. That's just over 9 square miles per small map. const int SMALL_MAP_SIDE_LEN = 64; const float STARTING_SCALE = 0.005f * SMALL_MAP_SIDE_LEN / 32; const int SMALL_MAP_RESIZED_LEN = 1024; Random random = new Random(); WaterTableArgs args = new WaterTableArgs(); Bitmap bmp = new Bitmap(args.inputPath + "rivers.png"); IField2d <float> baseMap = new Utils.FieldFromBitmap(new Bitmap(args.inputPath + "base_heights.png")); baseMap = new ReResField(baseMap, (float)bmp.Width / baseMap.Width); var wtf = Utils.GenerateWaters(bmp, baseMap); Utils.OutputAsColoredMap(wtf, wtf.RiverSystems, bmp, args.outputPath + "colored_map.png"); var hasWater = new Transformation2d <HydrologicalField.LandType, float>(wtf.HydroField, t => t == HydrologicalField.LandType.Land ? 0f : 1f); var noiseDamping = new Transformation2d(new BlurredField(hasWater, 2f), v => 3.5f * v); // Create the spline map. SparseField2d <List <SplineTree> > relevantSplines = new SparseField2d <List <SplineTree> >(wtf.Width, wtf.Height, null); { //HashSet<TreeNode<Point2d>> relevantRivers = new HashSet<TreeNode<Point2d>>(); foreach (var system in wtf.RiverSystems) { SplineTree tree = null; foreach (var p in system.value) { if (relevantSplines[p.value.y, p.value.x] == null) { relevantSplines[p.value.y, p.value.x] = new List <SplineTree>(); } relevantSplines[p.value.y, p.value.x].Add(tree ?? (tree = new SplineTree(system.value, wtf, random))); } } } Rectangle rect = new Rectangle(518 + 15, 785 + 45, SMALL_MAP_SIDE_LEN, SMALL_MAP_SIDE_LEN); var smallMap = new SubField <float>(wtf, rect); var scaledUp = new BlurredField(new ReResField(smallMap, SMALL_MAP_RESIZED_LEN / smallMap.Width), SMALL_MAP_RESIZED_LEN / (4 * SMALL_MAP_SIDE_LEN)); var smallDamp = new SubField <float>(noiseDamping, rect); var scaledDamp = new BlurredField(new ReResField(smallDamp, SMALL_MAP_RESIZED_LEN / smallMap.Width), SMALL_MAP_RESIZED_LEN / (4 * SMALL_MAP_SIDE_LEN)); // Do spline-y things. Field2d <float> riverbeds; List <SplineTree> splines = new List <SplineTree>(); { // Collect a comprehensive list of the spline trees for the local frame. for (int y = rect.Top - 1; y <= rect.Bottom + 1; y++) { for (int x = rect.Left - 1; x <= rect.Right + 1; x++) { List <SplineTree> trees = relevantSplines[y, x]; if (trees != null) { splines.AddRange(trees); } } } // Crafts the actual river kernel. Probably not the best way to go about this. riverbeds = new Field2d <float>(new ConstantField <float>(SMALL_MAP_RESIZED_LEN, SMALL_MAP_RESIZED_LEN, float.MaxValue)); foreach (var s in splines) { var samples = s.GetSamplesPerControlPoint(1f * SMALL_MAP_RESIZED_LEN / SMALL_MAP_SIDE_LEN); int priorX = int.MinValue; int priorY = int.MinValue; foreach (var p in samples) { int x = (int)((p[0] - rect.Left) * SMALL_MAP_RESIZED_LEN / SMALL_MAP_SIDE_LEN); int y = (int)((p[1] - rect.Top) * SMALL_MAP_RESIZED_LEN / SMALL_MAP_SIDE_LEN); if (x == priorX && y == priorY) { continue; } else { priorX = x; priorY = y; } if (0 <= x && x < SMALL_MAP_RESIZED_LEN && 0 <= y && y < SMALL_MAP_RESIZED_LEN) { const int r = 1024 / SMALL_MAP_SIDE_LEN; for (int j = -r; j <= r; j++) { for (int i = -r; i <= r; i++) { int xx = x + i; int yy = y + j; if (0 <= xx && xx < SMALL_MAP_RESIZED_LEN && 0 <= yy && yy < SMALL_MAP_RESIZED_LEN) { float dSq = i * i + j * j; riverbeds[yy, xx] = Math.Min(riverbeds[yy, xx], p[2] + dSq / (512f * 32 / SMALL_MAP_SIDE_LEN)); //scaledDamp[yy, xx] = 1f; //scaledUp[yy, xx] = Math.Min(scaledUp[yy, xx], p[2] + (float)Math.Sqrt(xx * xx + yy * yy) / 1f); } } } } } } //Utils.OutputField(riverbeds, new Bitmap(riverbeds.Width, riverbeds.Height), args.outputPath + "river_field.png"); } var mountainous = new ScaleTransform(new MountainNoise(1024, 1024, STARTING_SCALE), 1f); var hilly = new ScaleTransform(new Simplex2D(1024, 1024, STARTING_SCALE * 4), 0.1f); var terrainNoise = new Transformation2d <float, float, float>(mountainous, hilly, (x, y, m, h) => { float a = scaledUp[y, x]; float sh = Math.Max(-2f * Math.Abs(a - 0.2f) / 3f + 1f, 0f); float sm = Math.Min(1.3f * a, 1f); return(h * sh + m * sm); }); IField2d <float> combined = new NormalizedComposition2d <float>( new Transformation2d <float, float, float>(riverbeds, new Composition2d <float>(scaledUp, new Transformation2d <float, float, float>(scaledDamp, terrainNoise, (s, m) => (1 - Math.Min(1, s)) * m) ), (r, c) => r == float.MaxValue ? c : Math.Min(r, c)) ); Bitmap img = new Bitmap(combined.Width, combined.Height); Utils.OutputField(combined, img, args.outputPath + "combined.png"); Utils.OutputAsOBJ(combined, splines, rect, img, args.outputPath); }
public static void RunPopulationScenario() { WaterTableArgs args = new WaterTableArgs(); Bitmap bmp = new Bitmap(args.inputPath + "rivers.png"); IField2d <float> baseMap = new Utils.FieldFromBitmap(new Bitmap(args.inputPath + "base_heights.png")); baseMap = new ReResField(baseMap, (float)bmp.Width / baseMap.Width); var wtf = Utils.GenerateWaters(bmp, baseMap); Utils.OutputAsColoredMap(wtf, wtf.RiverSystems, bmp, args.outputPath + "colored_map.png"); IField2d <float> rainfall = new Utils.FieldFromBitmap(new Bitmap(args.inputPath + "rainfall.png")); rainfall = new ReResField(rainfall, (float)wtf.Width / rainfall.Width); IField2d <float> wateriness = Utils.GetWaterinessMap(wtf, rainfall); Utils.OutputField(new NormalizedComposition2d <float>(wateriness), bmp, args.outputPath + "wateriness.png"); var locations = Utils.GetSettlementLocations(wtf, wateriness); SparseField2d <float> settlementMap = new SparseField2d <float>(wtf.Width, wtf.Height, 0f); foreach (var loc in locations) { settlementMap.Add(loc, wateriness[loc.y, loc.x]); } Utils.OutputField(settlementMap, bmp, args.outputPath + "settlements.png"); TriangleNet.Geometry.InputGeometry pointSet = new TriangleNet.Geometry.InputGeometry(); foreach (var loc in locations) { pointSet.AddPoint(loc.x, loc.y); } TriangleNet.Mesh mesh = new TriangleNet.Mesh(); mesh.Triangulate(pointSet); //TriangleNet.Tools.AdjacencyMatrix mat = new TriangleNet.Tools.AdjacencyMatrix(mesh); Field2d <float> meshField = new Field2d <float>(settlementMap); foreach (var e in mesh.Edges) { var v0 = mesh.GetVertex(e.P0); var v1 = mesh.GetVertex(e.P1); float distance = (float)Math.Sqrt(Math.Pow(v0.X - v1.X, 2) + Math.Pow(v0.Y - v1.Y, 2)); for (float t = 0f; t <= 1f; t += 0.5f / distance) { int x = (int)Math.Round((1f - t) * v0.X + t * v1.X); int y = (int)Math.Round((1f - t) * v0.Y + t * v1.Y); meshField[y, x] = 0.5f; } meshField[(int)v0.Y, (int)v0.X] = 1f; meshField[(int)v1.Y, (int)v1.X] = 1f; } Utils.OutputField(meshField, bmp, args.outputPath + "mesh.png"); }