コード例 #1
0
ファイル: TestScenarios.cs プロジェクト: septagon/demiurge
        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");
        }
コード例 #2
0
ファイル: TestScenarios.cs プロジェクト: septagon/demiurge
        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);
        }
コード例 #3
0
ファイル: TestScenarios.cs プロジェクト: septagon/demiurge
        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");
        }
コード例 #4
0
ファイル: WaterTableUtils.cs プロジェクト: septagon/demiurge
        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);
        }
コード例 #5
0
ファイル: TestScenarios.cs プロジェクト: septagon/demiurge
        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);
        }
コード例 #6
0
ファイル: TestScenarios.cs プロジェクト: septagon/demiurge
        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");
        }