Ejemplo n.º 1
0
        public static void CreateOreVeins(TerrainData terrain, Random random, double xk, double yk)
        {
            var veinMaterials = Materials.GetMaterials(MaterialCategory.Mineral).Select(mi => mi.ID).ToArray();

            for (int i = 0; i < 100; ++i)
            {
                var start = GetRandomSubterraneanLocation(terrain, random);
                var mat = veinMaterials[random.Next(veinMaterials.Length)];
                int len = random.Next(20) + 3;
                int thickness = random.Next(4) + 1;

                var vx = random.NextDouble() * 2 - 1;
                var vy = random.NextDouble() * 2 - 1;
                var vz = vx * xk + vy * yk;

                var v = new DoubleVector3(vx, vy, -vz).Normalize();

                for (double t = 0.0; t < len; t += 1)
                {
                    var p = start + (v * t).ToIntVector3();

                    CreateOreSphere(terrain, random, p, thickness, mat, random.NextDouble() * 0.75, 0);
                }
            }
        }
Ejemplo n.º 2
0
        public static TerrainData CreateBallMap(IntSize3 size, int innerSide = 0)
        {
            var map = new TerrainData(size);

            int side = MyMath.Min(size.Width, size.Height, size.Depth);

            int r = side / 2 - 1;
            int ir = innerSide / 2 - 1;

            Parallel.For(0, size.Depth, z =>
            {
                for (int y = 0; y < size.Height; ++y)
                    for (int x = 0; x < size.Width; ++x)
                    {
                        var pr = Math.Sqrt((x - r) * (x - r) + (y - r) * (y - r) + (z - r) * (z - r));

                        var p = new IntVector3(x, y, z);

                        if (pr < r && pr >= ir)
                            map.SetTileDataNoHeight(p, TileData.GetNaturalWall(MaterialID.Granite));
                        else
                            map.SetTileDataNoHeight(p, TileData.EmptyTileData);
                    }
            });

            map.RescanLevelMap();

            return map;
        }
Ejemplo n.º 3
0
        public static void CreateGrass(TerrainData terrain, Random random, int grassLimit)
        {
            var grid = terrain.TileGrid;
            var heightMap = terrain.HeightMap;

            int w = terrain.Width;
            int h = terrain.Height;

            var materials = Materials.GetMaterials(MaterialCategory.Grass).ToArray();
            for (int y = 0; y < h; ++y)
            {
                for (int x = 0; x < w; ++x)
                {
                    int z = heightMap[y, x];

                    var p = new IntPoint3(x, y, z);

                    if (z < grassLimit)
                    {
                        var td = grid[p.Z, p.Y, p.X];

                        if (Materials.GetMaterial(td.TerrainMaterialID).Category == MaterialCategory.Soil &&
                            (td.TerrainID.IsFloor() || td.TerrainID.IsSlope()))
                        {
                            td.InteriorID = InteriorID.Grass;
                            td.InteriorMaterialID = materials[random.Next(materials.Length)].ID;

                            grid[p.Z, p.Y, p.X] = td;
                        }
                    }
                }
            }
        }
Ejemplo n.º 4
0
        public static TerrainData CreateNoiseTerrain(IntSize3 size, Random random)
        {
            var terrain = new TerrainData(size);

            var noise = CreateTerrainNoise();
            var noisemap = CreateTerrainNoiseMap(noise, new IntSize2(size.Width, size.Height));

            FillFromNoiseMap(terrain, noisemap);

            terrain.RescanLevelMap();

            double xk = (random.NextDouble() * 2 - 1) * 0.01;
            double yk = (random.NextDouble() * 2 - 1) * 0.01;
            TerrainHelpers.CreateBaseMinerals(terrain, random, xk, yk);

            TerrainHelpers.CreateOreVeins(terrain, random, xk, yk);

            TerrainHelpers.CreateOreClusters(terrain, random);

            RiverGen.Generate(terrain, random);

            int soilLimit = size.Depth * 4 / 5;
            TerrainHelpers.CreateSoil(terrain, soilLimit);

            int grassLimit = terrain.Depth * 4 / 5;
            TerrainHelpers.CreateVegetation(terrain, random, grassLimit);

            return terrain;
        }
Ejemplo n.º 5
0
 public static void CreateOreClusters(TerrainData terrain, Random random)
 {
     var clusterMaterials = Materials.GetMaterials(MaterialCategory.Gem).Select(mi => mi.ID).ToArray();
     for (int i = 0; i < 100; ++i)
     {
         var p = GetRandomSubterraneanLocation(terrain, random);
         CreateOreCluster(terrain, random, p, clusterMaterials[random.Next(clusterMaterials.Length)]);
     }
 }
Ejemplo n.º 6
0
 public void Render(TerrainData terrain, IntVector3 pos)
 {
     if (pos.Z == m_size.Depth)
         RenderTerrain(terrain);
     else
         RenderSliceXY(terrain, pos.Z);
     RenderSliceXZ(terrain, pos.Y);
     RenderSliceYZ(terrain, pos.X);
 }
Ejemplo n.º 7
0
        public static void CreateSlopes(TerrainData data, int baseSeed)
        {
            var plane = data.Size.Plane;

            plane.Range().AsParallel().ForAll(p =>
            {
                int z = data.GetHeight(p);

                int count = 0;
                Direction dir = Direction.None;

                var r = new MWCRandom(p, baseSeed);

                int offset = r.Next(8);

                // Count the tiles around this tile which are higher. Create slope to a random direction, but skip
                // the slope if all 8 tiles are higher.
                // Count to 10. If 3 successive slopes, create one in the middle
                int successive = 0;
                for (int i = 0; i < 10; ++i)
                {
                    var d = DirectionExtensions.PlanarDirections[(i + offset) % 8];

                    var t = p + d;

                    if (plane.Contains(t) && data.GetHeight(t) > z)
                    {
                        if (i < 8)
                            count++;
                        successive++;

                        if (successive == 3)
                        {
                            dir = DirectionExtensions.PlanarDirections[((i - 1) + offset) % 8];
                        }
                        else if (dir == Direction.None)
                        {
                            dir = d;
                        }
                    }
                    else
                    {
                        successive = 0;
                    }
                }

                if (count > 0 && count < 8)
                {
                    var p3d = new IntPoint3(p, z);

                    var td = data.GetTileData(p3d);
                    td.TerrainID = dir.ToSlope();
                    data.SetTileData(p3d, td);
                }
            });
        }
Ejemplo n.º 8
0
 public static void Generate(TerrainData terrain, Random random)
 {
     var riverGen = new RiverGen(terrain, random);
     if (riverGen.CreateRiverPath())
     {
         riverGen.AdjustRiver();
     }
     else
     {
         Trace.TraceError("Failed to create river");
     }
 }
Ejemplo n.º 9
0
        public static unsafe TerrainData LoadTerrain(string path, string expectedName, IntSize3 expectedSize)
        {
            if (File.Exists(path) == false)
                return null;

            using (var stream = File.OpenRead(path))
            {
                TerrainData terrain;

                using (var br = new BinaryReader(stream, Encoding.Default, true))
                {
                    var name = br.ReadString();

                    if (name != expectedName)
                        return null;

                    int w = br.ReadInt32();
                    int h = br.ReadInt32();
                    int d = br.ReadInt32();

                    var size = new IntSize3(w, h, d);

                    if (size != expectedSize)
                        return null;

                    terrain = new TerrainData(size);
                }

                fixed (TileData* v = terrain.m_tileGrid)
                {
                    byte* p = (byte*)v;

                    int len = terrain.Size.Volume * sizeof(TileData);

                    using (var memStream = new UnmanagedMemoryStream(p, 0, len, FileAccess.Write))
                        CopyTo(stream, memStream, len);
                }

                fixed (byte* p = terrain.m_levelMap)
                {
                    int len = terrain.Size.Plane.Area * sizeof(byte);

                    using (var memStream = new UnmanagedMemoryStream(p, 0, len, FileAccess.Write))
                        CopyTo(stream, memStream, len);
                }

                return terrain;
            }
        }
Ejemplo n.º 10
0
        public static void CreateBaseMinerals(TerrainData terrain, Random random, double xk, double yk)
        {
            int width = terrain.Width;
            int height = terrain.Height;
            int depth = terrain.Depth;

            var rockMaterials = Materials.GetMaterials(MaterialCategory.Rock).ToArray();
            var layers = new MaterialID[20];

            {
                int rep = 0;
                MaterialID mat = MaterialID.Undefined;
                for (int z = 0; z < layers.Length; ++z)
                {
                    if (rep == 0)
                    {
                        rep = random.Next(4) + 1;
                        mat = rockMaterials[random.Next(rockMaterials.Length - 1)].ID;
                    }

                    layers[z] = mat;
                    rep--;
                }
            }

            Parallel.For(0, height, y =>
            {
                for (int x = 0; x < width; ++x)
                {
                    int surface = terrain.GetSurfaceLevel(x, y);

                    for (int z = 0; z < surface; ++z)
                    {
                        var p = new IntVector3(x, y, z);

                        int _z = MyMath.Round(z + x * xk + y * yk);

                        _z = _z % layers.Length;

                        if (_z < 0)
                            _z += layers.Length;

                        terrain.SetTileDataNoHeight(p, TileData.GetNaturalWall(layers[_z]));
                    }
                }
            });
        }
Ejemplo n.º 11
0
        public MainWindow()
        {
            const int depth = 5;
            const int sizeExp = 9;
            int side = (int)Math.Pow(2, sizeExp);

            m_size = new IntSize3(side, side, depth);
            m_terrain = new TerrainData(m_size);
            m_terrainGen = new DungeonTerrainGenerator(m_terrain, new Random(1));
            m_renderer = new Renderer(m_size);

            this.SliceBmpXY = m_renderer.SliceBmpXY;
            this.SliceBmpXZ = m_renderer.SliceBmpXZ;
            this.SliceBmpYZ = m_renderer.SliceBmpYZ;

            InitializeComponent();
        }
Ejemplo n.º 12
0
        void CreateTerrain(IntSize3 size)
        {
            TerrainData terrain;

            switch (m_mapMode)
            {
                case GameMap.Ball:
                    terrain = ArtificialGen.CreateBallMap(size);
                    break;
                case GameMap.Cube:
                    terrain = ArtificialGen.CreateCubeMap(size, 2);
                    break;
                default:
                    throw new NotImplementedException();
            }

            m_terrainData = terrain;
        }
Ejemplo n.º 13
0
        public static TerrainData CreateCubeMap(IntSize3 size, int margin)
        {
            var map = new TerrainData(size);

            Parallel.For(0, size.Depth, z =>
            {
                for (int y = 0; y < size.Height; ++y)
                    for (int x = 0; x < size.Width; ++x)
                    {
                        var p = new IntVector3(x, y, z);

                        if (x < margin || y < margin || z < margin ||
                            x >= size.Width - margin || y >= size.Height - margin || z >= size.Depth - margin)
                            map.SetTileDataNoHeight(p, TileData.EmptyTileData);
                        else
                            map.SetTileDataNoHeight(p, TileData.GetNaturalWall(MaterialID.Granite));
                    }
            });

            map.RescanLevelMap();

            return map;
        }
Ejemplo n.º 14
0
		static TerrainData CreateTerrain(IntSize3 size)
		{
			//var random = Helpers.Random;
			var random = new Random(1);

			var terrain = new TerrainData(size);

			var tg = new TerrainGenerator(terrain, random);

			var corners = new DiamondSquare.CornerData()
			{
				NE = 15,
				NW = 10,
				SW = 10,
				SE = 10,
			};

			tg.Generate(corners, 5, 0.75, 2);

			int grassLimit = terrain.Depth * 4 / 5;
			TerrainHelpers.CreateVegetation(terrain, random, grassLimit);

			return terrain;
		}
Ejemplo n.º 15
0
 public RiverGen(TerrainData terrain, Random random)
 {
     m_terrain = terrain;
     m_random = random;
 }
Ejemplo n.º 16
0
        static bool CreateOre(TerrainData terrain, IntVector3 p, MaterialID oreMaterialID)
        {
            if (!terrain.Contains(p))
                return false;

            var td = terrain.GetTileData(p);

            if (td.ID != TileID.NaturalWall)
                return false;

            if (Materials.GetMaterial(td.MaterialID).Category != MaterialCategory.Rock)
                return false;

            td.SecondaryMaterialID = oreMaterialID;
            terrain.SetTileDataNoHeight(p, td);

            return true;
        }
Ejemplo n.º 17
0
 static void CreateOreCluster(TerrainData terrain, Random random, IntVector3 p, MaterialID oreMaterialID)
 {
     CreateOreCluster(terrain, p, oreMaterialID, random.Next(6) + 1);
 }
Ejemplo n.º 18
0
 public MyTarget(TerrainData terrain, IntVector3 origin, SideEdge sourceSide)
 {
     m_terrain = terrain;
     m_origin = origin;
     m_sourceSide = sourceSide;
 }
Ejemplo n.º 19
0
        public static void CreateTrees(TerrainData terrain, Random random)
        {
            var grid = terrain.TileGrid;
            var heightMap = terrain.HeightMap;

            var materials = Materials.GetMaterials(MaterialCategory.Wood).ToArray();

            int baseSeed = random.Next();
            if (baseSeed == 0)
                baseSeed = 1;

            terrain.Size.Plane.Range().AsParallel().ForAll(p2d =>
            {
                int z = heightMap[p2d.Y, p2d.X];

                var p = new IntPoint3(p2d, z);

                var td = grid[p.Z, p.Y, p.X];

                if (td.InteriorID == InteriorID.Grass)
                {
                    var r = new MWCRandom(p, baseSeed);

                    if (r.Next(8) == 0)
                    {
                        td.InteriorID = r.Next(2) == 0 ? InteriorID.Tree : InteriorID.Sapling;
                        td.InteriorMaterialID = materials[r.Next(materials.Length)].ID;
                        grid[p.Z, p.Y, p.X] = td;
                    }
                }
            });
        }
Ejemplo n.º 20
0
        static void CreateOreCluster(TerrainData terrain, IntVector3 p, MaterialID oreMaterialID, int count)
        {
            bool b = CreateOre(terrain, p, oreMaterialID);
            if (b == false)
                return;

            if (count > 0)
            {
                foreach (var d in DirectionExtensions.CardinalUpDownDirections)
                    CreateOreCluster(terrain, p + d, oreMaterialID, count - 1);
            }
        }
Ejemplo n.º 21
0
        static void CreateOreSphere(TerrainData terrain, Random random, IntVector3 center, int r, MaterialID oreMaterialID, double probIn, double probOut)
        {
            // adjust r, so that r == 1 gives sphere of one tile
            r -= 1;

            // XXX split the sphere into 8 parts, and mirror

            var bb = new IntGrid3(center.X - r, center.Y - r, center.Z - r, r * 2 + 1, r * 2 + 1, r * 2 + 1);

            var rs = MyMath.Square(r);

            foreach (var p in bb.Range())
            {
                var y = p.Y;
                var x = p.X;
                var z = p.Z;

                var v = MyMath.Square(x - center.X) + MyMath.Square(y - center.Y) + MyMath.Square(z - center.Z);

                if (rs >= v)
                {
                    var rr = Math.Sqrt(v);

                    double rel;

                    if (r == 0)
                        rel = 1;
                    else
                        rel = 1 - rr / r;

                    var prob = (probIn - probOut) * rel + probOut;

                    if (random.NextDouble() <= prob)
                        CreateOre(terrain, p, oreMaterialID);
                }
            }
        }
Ejemplo n.º 22
0
        public static void CreateSoil(TerrainData data, int soilLimit)
        {
            int w = data.Width;
            int h = data.Height;

            for (int y = 0; y < h; ++y)
            {
                for (int x = 0; x < w; ++x)
                {
                    int z = data.GetHeight(x, y);

                    var p = new IntPoint3(x, y, z);

                    if (z < soilLimit)
                    {
                        var td = data.GetTileData(p);

                        td.TerrainMaterialID = MaterialID.Loam;

                        data.SetTileData(p, td);
                    }
                }
            }
        }
Ejemplo n.º 23
0
        void RenderTerrain(TerrainData terrain)
        {
            int w = m_size.Width;
            int h = m_size.Height;

            TileData[,,] tileGrid;
            byte[,] levelMap;
            terrain.GetData(out tileGrid, out levelMap);

            int min = levelMap.Min();
            int max = levelMap.Max();

            m_sliceBmpXY.Lock();

            unsafe
            {
                var pBackBuffer = (uint*)m_sliceBmpXY.BackBuffer;
                int stride = m_sliceBmpXY.BackBufferStride / 4;

                Parallel.For(0, h, y =>
                {
                    for (int x = 0; x < w; ++x)
                    {
                        int z = terrain.GetSurfaceLevel(x, y);

                        TileData td;

                        while (true)
                        {
                            var p = new IntVector3(x, y, z);
                            td = terrain.GetTileData(p);

                            if (td.IsEmptyNoWater)
                            {
                                z--;
                                continue;
                            }

                            if (this.ShowWaterEnabled && td.WaterLevel > 0)
                            {
                                var wl = terrain.GetWaterLevel(p + Direction.Up);
                                if (wl > 0)
                                {
                                    z++;
                                    continue;
                                }
                            }

                            break;
                        }

                        int m = MyMath.Round(MyMath.LinearInterpolation(min, max, 100, 255, z));

                        var cv = GetTileColor(td);

                        int r = cv.X;
                        int g = cv.Y;
                        int b = cv.Z;

                        r = r * m / 255;
                        g = g * m / 255;
                        b = b * m / 255;

                        var ptr = pBackBuffer + y * stride + x;

                        *ptr = (uint)((r << 16) | (g << 8) | (b << 0));
                    }
                });
            }

            m_sliceBmpXY.AddDirtyRect(new Int32Rect(0, 0, m_sliceBmpXY.PixelWidth, m_sliceBmpXY.PixelHeight));
            m_sliceBmpXY.Unlock();
        }
Ejemplo n.º 24
0
        void RenderSliceYZ(TerrainData terrain, int x)
        {
            int w = m_size.Width;
            int h = m_size.Height;
            int d = m_size.Depth;

            m_sliceBmpYZ.Lock();

            unsafe
            {
                var pBackBuffer = (uint*)m_sliceBmpYZ.BackBuffer;
                int stride = m_sliceBmpYZ.BackBufferStride / 4;

                Parallel.For(0, d, z =>
                {
                    for (int y = 0; y < h; ++y)
                    {
                        int mz = d - z - 1;

                        var p = new IntVector3(x, y, mz);
                        var td = terrain.GetTileData(p);

                        uint c;

                        if (td.IsEmpty && td.WaterLevel == 0)
                            c = ColorToRaw(Colors.SkyBlue);
                        else
                            c = IntVector3ToRaw(GetTileColor(td));

                        var ptr = pBackBuffer + y * stride + z;

                        *ptr = c;
                    }
                });
            }

            m_sliceBmpYZ.AddDirtyRect(new Int32Rect(0, 0, m_sliceBmpYZ.PixelWidth, m_sliceBmpYZ.PixelHeight));
            m_sliceBmpYZ.Unlock();
        }
Ejemplo n.º 25
0
        static IntVector3 GetRandomSubterraneanLocation(TerrainData data, Random random)
        {
            int x = random.Next(data.Width);
            int y = random.Next(data.Height);
            int maxZ = data.GetSurfaceLevel(x, y);
            int z = random.Next(maxZ);

            return new IntVector3(x, y, z);
        }
Ejemplo n.º 26
0
        void OnTimerTick(object sender, EventArgs e)
        {
            m_timer.IsEnabled = false;

            if (m_needCreate)
            {
                Stopwatch sw = Stopwatch.StartNew();

                int depth = this.Depth;
                int side = this.Side;

                m_size = new IntSize3(side, side, depth);

                this.X = side / 2;
                this.Y = side / 2;
                this.Z = depth;

                //m_terrain = new TerrainData(m_size);
                this.Renderer = new Renderer(m_size);
                Notify("Renderer");

                sw.Stop();

                Trace.TraceInformation("Create took {0} ms", sw.ElapsedMilliseconds);

                levelSlider.Minimum = 0;
                levelSlider.Maximum = m_size.Depth;
                this.Z = m_size.Depth;

                m_needCreate = false;
            }

            if (m_needGenerate)
            {
                Stopwatch sw = Stopwatch.StartNew();

                var random = new Random(1);

                m_terrain = NoiseTerrainGen.CreateNoiseTerrain(m_size, random);

                sw.Stop();

                Trace.TraceInformation("Generate took {0} ms", sw.ElapsedMilliseconds);

                m_needGenerate = false;
            }

            if (m_needRender)
            {
                Stopwatch sw = Stopwatch.StartNew();

                this.Renderer.ShowWaterEnabled = this.ShowWaterEnabled;
                this.Renderer.Render(m_terrain, new IntVector3(this.X, this.Y, this.Z));

                sw.Stop();

                Trace.TraceInformation("Render took {0} ms", sw.ElapsedMilliseconds);

                m_needRender = false;
            }
        }
Ejemplo n.º 27
0
        static void FillFromNoiseMap(TerrainData terrainData, SharpNoise.NoiseMap noiseMap)
        {
            var max = noiseMap.Data.Max();
            var min = noiseMap.Data.Min();

            Parallel.For(0, noiseMap.Data.Length, i =>
            {
                var v = noiseMap.Data[i];   // [-1 .. 1]

                v -= min;
                v /= (max - min);       // [0 .. 1]

                v *= terrainData.Depth * 8 / 10;
                v += terrainData.Depth * 2 / 10;

                noiseMap.Data[i] = v;
            });

            Parallel.For(0, terrainData.Height, y =>
            {
                for (int x = 0; x < terrainData.Width; ++x)
                {
                    var v = noiseMap[x, y];

                    int iv = (int)v;

                    for (int z = terrainData.Depth - 1; z >= 0; --z)
                    {
                        var p = new IntVector3(x, y, z);

                        /* above ground */
                        if (z > iv)
                        {
                            terrainData.SetTileDataNoHeight(p, TileData.EmptyTileData);
                        }
                        /* surface */
                        else if (z == iv)
                        {
                            terrainData.SetTileDataNoHeight(p, TileData.EmptyTileData);
                        }
                        /* underground */
                        else if (z < iv)
                        {
                            terrainData.SetTileDataNoHeight(p, TileData.GetNaturalWall(MaterialID.Granite));
                        }
                        else
                        {
                            throw new Exception();
                        }
                    }
                }
            });
        }
Ejemplo n.º 28
0
        void CreateTerrain()
        {
            var random = Helpers.Random;

            int side = MyMath.Pow2(MAP_SIZE);
            var size = new IntSize3(side, side, MAP_DEPTH);

            var terrain = new TerrainData(size);

            var tg = new DungeonTerrainGenerator(terrain, random);

            tg.Generate(1);

            TerrainHelpers.CreateSoil(terrain, 9999);
            TerrainHelpers.CreateGrass(terrain, random, 9999);
            TerrainHelpers.CreateTrees(terrain, random);

            m_rooms = tg.Rooms;
            m_terrainData = terrain;
        }
Ejemplo n.º 29
0
        void RenderSliceXY(TerrainData terrain, int level)
        {
            int w = m_size.Width;
            int h = m_size.Height;

            m_sliceBmpXY.Lock();

            unsafe
            {
                var pBackBuffer = (uint*)m_sliceBmpXY.BackBuffer;
                int stride = m_sliceBmpXY.BackBufferStride / 4;

                Parallel.For(0, h, y =>
                {
                    for (int x = 0; x < w; ++x)
                    {
                        var p = new IntVector3(x, y, level);
                        var td = terrain.GetTileData(p);

                        uint c;
                        if (td.IsEmpty && td.WaterLevel == 0)
                            c = ColorToRaw(Colors.SkyBlue);
                        else
                            c = IntVector3ToRaw(GetTileColor(td));

                        var ptr = pBackBuffer + y * stride + x;

                        *ptr = c;
                    }
                });
            }

            m_sliceBmpXY.AddDirtyRect(new Int32Rect(0, 0, m_sliceBmpXY.PixelWidth, m_sliceBmpXY.PixelHeight));
            m_sliceBmpXY.Unlock();
        }
Ejemplo n.º 30
0
 public DungeonTerrainGenerator(TerrainData data, Random random)
 {
     m_data = data;
     m_size = data.Size;
     m_random = random;
 }
 public DungeonTerrainGenerator(TerrainData data, Random random)
 {
     m_data   = data;
     m_size   = data.Size;
     m_random = random;
 }