Example #1
0
        public ITerrainChannel LoadStream(Stream s)
        {
            // The raw format doesn't contain any dimension information.
            // Guess the square dimensions by using the length of the raw file.
            double dimension = Math.Sqrt((double)(s.Length / 4));
            // Regions are always multiples of 256.
            int trimmedDimension = (int)dimension - ((int)dimension % (int)Constants.RegionSize);

            if (trimmedDimension < Constants.RegionSize)
            {
                trimmedDimension = (int)Constants.RegionSize;
            }

            TerrainChannel retval = new TerrainChannel(trimmedDimension, trimmedDimension);

            BinaryReader bs = new BinaryReader(s);
            int          y;

            for (y = 0; y < retval.Height; y++)
            {
                int x;
                for (x = 0; x < retval.Width; x++)
                {
                    retval[x, y] = bs.ReadSingle();
                }
            }

            bs.Close();

            return(retval);
        }
        public void TerrainChannelTest()
        {
            TerrainChannel x = new TerrainChannel((int)Constants.RegionSize, (int)Constants.RegionSize);

            Assert.That(x[0, 0] == 0.0, "Terrain not initialising correctly.");

            x[0, 0] = 1.0;
            Assert.That(x[0, 0] == 1.0, "Terrain not setting values correctly.");

            x[0, 0]  = 0;
            x[0, 0] += 5.0;
            x[0, 0] -= 1.0;
            Assert.That(x[0, 0] == 4.0, "Terrain addition/subtraction error.");

            x[0, 0] = 1.0;
            float[] floatsExport = x.GetFloatsSerialised();
            Assert.That(floatsExport[0] == 1.0f, "Export to float[] not working correctly.");

            x[0, 0] = 1.0;
            Assert.That(x.Tainted(0, 0), "Terrain channel tainting not working correctly.");
            Assert.That(!x.Tainted(0, 0), "Terrain channel tainting not working correctly.");

            TerrainChannel y = x.Copy();

            Assert.That(!ReferenceEquals(x, y), "Terrain copy not duplicating correctly.");
            Assert.That(!ReferenceEquals(x.GetDoubles(), y.GetDoubles()), "Terrain array not duplicating correctly.");
        }
Example #3
0
        public ITerrainChannel LoadStream(Stream s)
        {
            // The raw format doesn't contain any dimension information.
            // Guess the square dimensions by using the length of the raw file.
            double dimension = Math.Sqrt((double)(s.Length / 13));
            // Regions are always multiples of 256.
            int trimmedDimension = (int)dimension - ((int)dimension % (int)Constants.RegionSize);

            if (trimmedDimension < Constants.RegionSize)
            {
                trimmedDimension = (int)Constants.RegionSize;
            }

            TerrainChannel retval = new TerrainChannel(trimmedDimension, trimmedDimension);

            using (BinaryReader bs = new BinaryReader(s))
            {
                int y;
                for (y = 0; y < retval.Height; y++)
                {
                    int x;
                    for (x = 0; x < retval.Width; x++)
                    {
                        retval[x, (retval.Height - 1) - y] = bs.ReadByte() * (bs.ReadByte() / 128.0f);
                        bs.ReadBytes(11); // Advance the stream to next bytes.
                    }
                }
            }

            return(retval);
        }
Example #4
0
        public void Generate(IScene scene, string[] s)
        {
            //string noiseGen = MainConsole.Instance.CmdPrompt("Noise generator (Perlin or Kosh)", "Perlin", new List<string>(new [] { "Perlin", "Kosh" }));
            //if(noiseGen == "Perlin")
            {
                _noiseGen = m_perlinNoise;
                PerlinNoiseSettings pns = new PerlinNoiseSettings();
                pns.ResultX        = scene.RegionInfo.RegionSizeX;
                pns.ResultY        = scene.RegionInfo.RegionSizeY;
                pns.RandomSeed     = int.Parse(MainConsole.Instance.Prompt("Random Seed (0-infinity)", "10"));
                pns.CorsenessX     = int.Parse(MainConsole.Instance.Prompt("Corseness (X direction) (2-1000)", "100"));
                pns.CorsenessY     = int.Parse(MainConsole.Instance.Prompt("Corseness (Y direction) (2-1000)", "100"));
                pns.FlatEdges      = MainConsole.Instance.Prompt("Flat Edges (recommended)", "true", new List <string>(new[] { "true", "false" })) == "true";
                pns.Octaves        = int.Parse(MainConsole.Instance.Prompt("Octaves (0-infinity)", "5"));
                pns.Persistence    = float.Parse(MainConsole.Instance.Prompt("Persistence", "0.8"));
                _noiseGen.Settings = pns;
            }

            /*else
             * {
             *  _noiseGen = m_kochLikeNoise;
             *  KochLikeNoiseSettings kns = new KochLikeNoiseSettings();
             *  kns.ResultX = MainConsole.Instance.Prompt.RegionInfo.RegionSizeX;
             *  kns.ResultY = MainConsole.Instance.Prompt.RegionInfo.RegionSizeY;
             *  kns.H = double.Parse(MainConsole.Instance.Prompt("H", "1.0"));
             *  kns.InitalGridX = int.Parse(MainConsole.Instance.Prompt("Initial Grid X", "2"));
             *  if(kns.InitalGridX < 2)
             *      kns.InitalGridX = 2;
             *  kns.InitalGridY = int.Parse(MainConsole.Instance.Prompt("Initial Grid Y", "2"));
             *  if(kns.InitalGridY < 2)
             *      kns.InitalGridY = 2;
             *  kns.RandomMin = int.Parse(MainConsole.Instance.Prompt("Random Min", "-1"));
             *  kns.RandomMax = int.Parse(MainConsole.Instance.Prompt("Random Max", "1"));
             *  kns.RandomSeed = int.Parse(MainConsole.Instance.Prompt("Random Seed", "0"));
             *  kns.Scale = double.Parse(MainConsole.Instance.Prompt("Scale", "1.0"));
             *  _noiseGen.Settings = kns;
             * }*/
            float scaling = float.Parse(MainConsole.Instance.Prompt("Fractal Scaling", "50"));

            float[,] land = _noiseGen.Generate();
            ITerrainChannel c = new TerrainChannel(scene);

            for (int x = 0; x < scene.RegionInfo.RegionSizeX; x++)
            {
                for (int y = 0; y < scene.RegionInfo.RegionSizeY; y++)
                {
                    c[x, y] = (land[x, y] * scaling) + (float)scene.RegionInfo.RegionSettings.WaterHeight + 10;
                }
            }
            scene.RequestModuleInterface <ITerrainModule>().TerrainMap = c;
            scene.RequestModuleInterface <ITerrainModule>().TaintTerrain();
            scene.RegisterModuleInterface <ITerrainChannel>(c);
        }
Example #5
0
        public void BrushTest()
        {
            int midRegion = (int)Constants.RegionSize / 2;

            // Create a mask that covers only the left half of the region
            bool[,] allowMask = new bool[(int)Constants.RegionSize, 256];
            int x;
            int y;

            for (x = 0; x < midRegion; x++)
            {
                for (y = 0; y < (int)Constants.RegionSize; y++)
                {
                    allowMask[x, y] = true;
                }
            }

            //
            // Test RaiseSphere
            //
            TerrainChannel          map    = new TerrainChannel((int)Constants.RegionSize, (int)Constants.RegionSize);
            ITerrainPaintableEffect effect = new RaiseSphere();

            effect.PaintEffect(map, allowMask, midRegion, midRegion, -1.0, 2, 6.0,
                               0, midRegion - 1, 0, (int)Constants.RegionSize - 1);
            Assert.That(map[127, midRegion] > 0.0, "Raise brush should raising value at this point (127,128).");
            Assert.That(map[125, midRegion] > 0.0, "Raise brush should raising value at this point (124,128).");
            Assert.That(map[120, midRegion] == 0.0, "Raise brush should not change value at this point (120,128).");
            Assert.That(map[128, midRegion] == 0.0, "Raise brush should not change value at this point (128,128).");
//            Assert.That(map[0, midRegion] == 0.0, "Raise brush should not change value at this point (0,128).");
            //
            // Test LowerSphere
            //
            map = new TerrainChannel((int)Constants.RegionSize, (int)Constants.RegionSize);
            for (x = 0; x < map.Width; x++)
            {
                for (y = 0; y < map.Height; y++)
                {
                    map[x, y] = 1.0;
                }
            }
            effect = new LowerSphere();

            effect.PaintEffect(map, allowMask, midRegion, midRegion, -1.0, 2, 6.0,
                               0, (int)Constants.RegionSize - 1, 0, (int)Constants.RegionSize - 1);
            Assert.That(map[127, midRegion] >= 0.0, "Lower should not lowering value below 0.0 at this point (127,128).");
            Assert.That(map[127, midRegion] == 0.0, "Lower brush should lowering value to 0.0 at this point (127,128).");
            Assert.That(map[125, midRegion] < 1.0, "Lower brush should lowering value at this point (124,128).");
            Assert.That(map[120, midRegion] == 1.0, "Lower brush should not change value at this point (120,128).");
            Assert.That(map[128, midRegion] == 1.0, "Lower brush should not change value at this point (128,128).");
//            Assert.That(map[0, midRegion] == 1.0, "Lower brush should not change value at this point (0,128).");
        }
Example #6
0
        public virtual ITerrainChannel LoadFile(string filename, int offsetX, int offsetY, int fileWidth, int fileHeight, int w, int h)
        {
            Bitmap          bitmap = new Bitmap(filename);
            ITerrainChannel retval = new TerrainChannel(true);

            for (int x = 0; x < retval.Width; x++)
            {
                for (int y = 0; y < retval.Height; y++)
                {
                    retval[x, y] = bitmap.GetPixel(offsetX * retval.Width + x, (bitmap.Height - (retval.Height * (offsetY + 1))) + retval.Height - y - 1).GetBrightness() * 128;
                }
            }

            return(retval);
        }
Example #7
0
        public void BrushTest()
        {
            bool[,] allowMask = new bool[(int)Constants.RegionSize, 256];
            int x;
            int y;

            for (x = 0; x < (int)((int)Constants.RegionSize * 0.5f); x++)
            {
                for (y = 0; y < (int)Constants.RegionSize; y++)
                {
                    allowMask[x, y] = true;
                }
            }

            //
            // Test RaiseSphere
            //
            TerrainChannel          map    = new TerrainChannel((int)Constants.RegionSize, (int)Constants.RegionSize);
            ITerrainPaintableEffect effect = new RaiseSphere();

            effect.PaintEffect(map, allowMask, (int)Constants.RegionSize * 0.5f, (int)Constants.RegionSize * 0.5f, -1.0, 2, 0.1);
            Assert.That(map[127, (int)((int)Constants.RegionSize * 0.5f)] > 0.0, "Raise brush should raising value at this point (127,128).");
            Assert.That(map[124, (int)((int)Constants.RegionSize * 0.5f)] > 0.0, "Raise brush should raising value at this point (124,128).");
            Assert.That(map[123, (int)((int)Constants.RegionSize * 0.5f)] == 0.0, "Raise brush should not change value at this point (123,128).");
            Assert.That(map[128, (int)((int)Constants.RegionSize * 0.5f)] == 0.0, "Raise brush should not change value at this point (128,128).");
            Assert.That(map[0, (int)((int)Constants.RegionSize * 0.5f)] == 0.0, "Raise brush should not change value at this point (0,128).");

            //
            // Test LowerSphere
            //
            map = new TerrainChannel((int)Constants.RegionSize, (int)Constants.RegionSize);
            for (x = 0; x < map.Width; x++)
            {
                for (y = 0; y < map.Height; y++)
                {
                    map[x, y] = 1.0;
                }
            }
            effect = new LowerSphere();

            effect.PaintEffect(map, allowMask, ((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), -1.0, 2, 6.0);
            Assert.That(map[127, (int)((int)Constants.RegionSize * 0.5f)] >= 0.0, "Lower should not lowering value below 0.0 at this point (127,128).");
            Assert.That(map[127, (int)((int)Constants.RegionSize * 0.5f)] == 0.0, "Lower brush should lowering value to 0.0 at this point (127,128).");
            Assert.That(map[124, (int)((int)Constants.RegionSize * 0.5f)] < 1.0, "Lower brush should lowering value at this point (124,128).");
            Assert.That(map[123, (int)((int)Constants.RegionSize * 0.5f)] == 1.0, "Lower brush should not change value at this point (123,128).");
            Assert.That(map[128, (int)((int)Constants.RegionSize * 0.5f)] == 1.0, "Lower brush should not change value at this point (128,128).");
            Assert.That(map[0, (int)((int)Constants.RegionSize * 0.5f)] == 1.0, "Lower brush should not change value at this point (0,128).");
        }
Example #8
0
        public void BrushTest()
        {
            bool[,] allowMask = new bool[256, 256];
            int x;
            int y;

            for (x = 0; x < 128; x++)
            {
                for (y = 0; y < 256; y++)
                {
                    allowMask[x, y] = true;
                }
            }

            //
            // Test RaiseSphere
            //
            TerrainChannel          map    = new TerrainChannel(256, 256);
            ITerrainPaintableEffect effect = new RaiseSphere();

            effect.PaintEffect(map, allowMask, 128.0, 128.0, -1.0, 2, 0.1);
            Assert.That(map[127, 128] > 0.0, "Raise brush should raising value at this point (127,128).");
            Assert.That(map[124, 128] > 0.0, "Raise brush should raising value at this point (124,128).");
            Assert.That(map[123, 128] == 0.0, "Raise brush should not change value at this point (123,128).");
            Assert.That(map[128, 128] == 0.0, "Raise brush should not change value at this point (128,128).");
            Assert.That(map[0, 128] == 0.0, "Raise brush should not change value at this point (0,128).");

            //
            // Test LowerSphere
            //
            map = new TerrainChannel(256, 256);
            for (x = 0; x < map.Width; x++)
            {
                for (y = 0; y < map.Height; y++)
                {
                    map[x, y] = 1.0;
                }
            }
            effect = new LowerSphere();

            effect.PaintEffect(map, allowMask, 128.0, 128.0, -1.0, 2, 6.0);
            Assert.That(map[127, 128] >= 0.0, "Lower should not lowering value below 0.0 at this point (127,128).");
            Assert.That(map[127, 128] == 0.0, "Lower brush should lowering value to 0.0 at this point (127,128).");
            Assert.That(map[124, 128] < 1.0, "Lower brush should lowering value at this point (124,128).");
            Assert.That(map[123, 128] == 1.0, "Lower brush should not change value at this point (123,128).");
            Assert.That(map[128, 128] == 1.0, "Lower brush should not change value at this point (128,128).");
            Assert.That(map[0, 128] == 1.0, "Lower brush should not change value at this point (0,128).");
        }
        protected virtual ITerrainChannel LoadBitmap(Bitmap bitmap)
        {
            ITerrainChannel retval = new TerrainChannel(bitmap.Width, bitmap.Height);

            int x;

            for (x = 0; x < bitmap.Width; x++)
            {
                int y;
                for (y = 0; y < bitmap.Height; y++)
                {
                    retval[x, y] = bitmap.GetPixel(x, bitmap.Height - y - 1).GetBrightness() * 128;
                }
            }

            return(retval);
        }
Example #10
0
        protected virtual ITerrainChannel LoadBitmap(Bitmap bitmap, IScene scene)
        {
            ITerrainChannel retval = new TerrainChannel(bitmap.Width, bitmap.Height, scene);

            int x;
            int y;

            for (x = 0; x < bitmap.Width; x++)
            {
                for (y = 0; y < bitmap.Height; y++)
                {
                    retval [x, y] = bitmap.GetPixel(x, bitmap.Height - y - 1).GetBrightness() * 128;
                }
            }

            bitmap.Dispose();   // not needed anymore
            return(retval);
        }
Example #11
0
        public ITerrainChannel LoadStream(Stream s, IScene scene)
        {
            BinaryReader bs   = new BinaryReader(s);
            int          size = (int)System.Math.Sqrt(s.Length);

            size /= sizeof(short);
            TerrainChannel retval = new TerrainChannel(size, size, scene);

            for (int y = 0; y < retval.Height; y++)
            {
                for (int x = 0; x < retval.Width; x++)
                {
                    retval[x, y] = bs.ReadSingle();
                }
            }

            bs.Close();

            return(retval);
        }
Example #12
0
        public ITerrainChannel LoadStream(Stream s)
        {
            TerrainChannel retval = new TerrainChannel();

            BinaryReader bs = new BinaryReader(s);
            int          y;

            for (y = 0; y < retval.Height; y++)
            {
                int x;
                for (x = 0; x < retval.Width; x++)
                {
                    retval[x, y] = bs.ReadSingle();
                }
            }

            bs.Close();

            return(retval);
        }
Example #13
0
        public ITerrainChannel LoadStream(Stream s)
        {
            TerrainChannel retval = new TerrainChannel();

            BinaryReader bs = new BinaryReader(s);
            int          y;

            for (y = 0; y < retval.Height; y++)
            {
                int x;
                for (x = 0; x < retval.Width; x++)
                {
                    retval[x, (retval.Height - 1) - y] = bs.ReadByte() * (bs.ReadByte() / 128.0);
                    bs.ReadBytes(11); // Advance the stream to next bytes.
                }
            }

            bs.Close();

            return(retval);
        }
Example #14
0
        public ITerrainChannel LoadStream(Stream s, IScene scene)
        {
            int            size   = (int)System.Math.Sqrt(s.Length / 13);
            TerrainChannel retval = new TerrainChannel(size, size, scene);

            BinaryReader bs = new BinaryReader(s);
            int          y;

            for (y = 0; y < retval.Height; y++)
            {
                int x;
                for (x = 0; x < retval.Width; x++)
                {
                    retval[x, (retval.Height - 1) - y] = bs.ReadByte() * (bs.ReadByte() / 128);
                    bs.ReadBytes(11); // Advance the stream to next bytes.
                }
            }

            bs.Close();

            return(retval);
        }
Example #15
0
        public virtual short[] LoadTerrain(IScene scene, bool RevertMap, int RegionSizeX, int RegionSizeY)
        {
            if (!m_loaded)
            {
                m_loaded = true;
                ReadConfig(scene, scene.Config.Configs["FileBasedSimulationData"]);
                ReadBackup(scene);
            }
            ITerrainModule terrainModule = scene.RequestModuleInterface <ITerrainModule>();

            if (RevertMap)
            {
                ITerrainChannel channel = new TerrainChannel(false, scene);
                if (m_revertTerrain == null)
                {
                    if (m_shortrevertTerrain != null) //OpenSim style
                    {
                        terrainModule.TerrainRevertMap = new TerrainChannel(m_shortrevertTerrain, scene);
                    }
                    else if (m_oldstylerevertTerrain != null)
                    {
                        MemoryStream ms = new MemoryStream(m_oldstylerevertTerrain);
                        if (terrainModule != null)
                        {
                            terrainModule.LoadRevertMapFromStream(".r32", ms, 0, 0);
                        }
                    }
                }
                else
                {
                    //New style
                    terrainModule.TerrainRevertMap = ReadFromData(m_revertTerrain, scene);
                }
                //Make sure the size is right!
                if (terrainModule.TerrainRevertMap != null &&
                    terrainModule.TerrainRevertMap.Height != scene.RegionInfo.RegionSizeX)
                {
                    terrainModule.TerrainRevertMap = null;
                }
                m_revertTerrain         = null;
                m_oldstylerevertTerrain = null;
                m_shortrevertTerrain    = null;
                return(null);
            }
            else
            {
                if (m_terrain == null)
                {
                    if (m_shortterrain != null) //OpenSim style
                    {
                        terrainModule.TerrainMap = new TerrainChannel(m_shortterrain, scene);
                    }
                    else if (m_oldstyleterrain != null)
                    {
//Old style
                        ITerrainChannel channel = new TerrainChannel(false, scene);
                        MemoryStream    ms      = new MemoryStream(m_oldstyleterrain);
                        if (terrainModule != null)
                        {
                            terrainModule.LoadFromStream(".r32", ms, 0, 0);
                        }
                    }
                }
                else
                {
                    //New style
                    terrainModule.TerrainMap = ReadFromData(m_terrain, scene);
                }
                //Make sure the size is right!
                if (terrainModule.TerrainMap != null &&
                    terrainModule.TerrainMap.Height != scene.RegionInfo.RegionSizeX)
                {
                    terrainModule.TerrainMap = null;
                }
                m_terrain         = null;
                m_oldstyleterrain = null;
                m_shortterrain    = null;
                return(null);
            }
        }
Example #16
0
        public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration)
        {
            strength = TerrainUtil.MetersToSphericalStrength(strength);

            int x, y;
            // Using one 'rain' round for this, so skipping a useless loop
            // Will need to adapt back in for the Flood brush

            ITerrainChannel water    = new TerrainChannel(map.Width, map.Height);
            ITerrainChannel sediment = new TerrainChannel(map.Width, map.Height);

            // Fill with rain
            for (x = 0; x < water.Width; x++)
            {
                for (y = 0; y < water.Height; y++)
                {
                    water[x, y] = Math.Max(0.0, TerrainUtil.SphericalFactor(x, y, rx, ry, strength) * rainHeight * duration);
                }
            }

            for (int i = 0; i < rounds; i++)
            {
                // Erode underlying terrain
                for (x = 0; x < water.Width; x++)
                {
                    for (y = 0; y < water.Height; y++)
                    {
                        if (mask[x, y])
                        {
                            const double solConst = (1.0 / rounds);
                            double       sedDelta = water[x, y] * solConst;
                            map[x, y]      -= sedDelta;
                            sediment[x, y] += sedDelta;
                        }
                    }
                }

                // Move water
                for (x = 0; x < water.Width; x++)
                {
                    for (y = 0; y < water.Height; y++)
                    {
                        if (water[x, y] <= 0)
                        {
                            continue;
                        }

                        // Step 1. Calculate average of neighbours

                        int    neighbours    = 0;
                        double altitudeTotal = 0.0;
                        double altitudeMe    = map[x, y] + water[x, y];

                        const int NEIGHBOUR_ME  = 4;
                        const int NEIGHBOUR_MAX = 9;

                        for (int j = 0; j < NEIGHBOUR_MAX; j++)
                        {
                            if (j != NEIGHBOUR_ME)
                            {
                                int[] coords = Neighbours(type, j);

                                coords[0] += x;
                                coords[1] += y;

                                if (coords[0] > map.Width - 1)
                                {
                                    continue;
                                }
                                if (coords[1] > map.Height - 1)
                                {
                                    continue;
                                }
                                if (coords[0] < 0)
                                {
                                    continue;
                                }
                                if (coords[1] < 0)
                                {
                                    continue;
                                }

                                // Calculate total height of this neighbour
                                double altitudeNeighbour = water[coords[0], coords[1]] + map[coords[0], coords[1]];

                                // If it's greater than me...
                                if (altitudeNeighbour - altitudeMe < 0)
                                {
                                    // Add it to our calculations
                                    neighbours++;
                                    altitudeTotal += altitudeNeighbour;
                                }
                            }
                        }

                        if (neighbours == 0)
                        {
                            continue;
                        }

                        double altitudeAvg = altitudeTotal / neighbours;

                        // Step 2. Allocate water to neighbours.
                        for (int j = 0; j < NEIGHBOUR_MAX; j++)
                        {
                            if (j != NEIGHBOUR_ME)
                            {
                                int[] coords = Neighbours(type, j);

                                coords[0] += x;
                                coords[1] += y;

                                if (coords[0] > map.Width - 1)
                                {
                                    continue;
                                }
                                if (coords[1] > map.Height - 1)
                                {
                                    continue;
                                }
                                if (coords[0] < 0)
                                {
                                    continue;
                                }
                                if (coords[1] < 0)
                                {
                                    continue;
                                }

                                // Skip if we dont have water to begin with.
                                if (water[x, y] < 0)
                                {
                                    continue;
                                }

                                // Calculate our delta average
                                double altitudeDelta = altitudeMe - altitudeAvg;

                                if (altitudeDelta < 0)
                                {
                                    continue;
                                }

                                // Calculate how much water we can move
                                double waterMin   = Math.Min(water[x, y], altitudeDelta);
                                double waterDelta = waterMin * ((water[coords[0], coords[1]] + map[coords[0], coords[1]])
                                                                / altitudeTotal);

                                double sedimentDelta = sediment[x, y] * (waterDelta / water[x, y]);

                                if (sedimentDelta > 0)
                                {
                                    sediment[x, y] -= sedimentDelta;
                                    sediment[coords[0], coords[1]] += sedimentDelta;
                                }
                            }
                        }
                    }
                }

                // Evaporate

                for (x = 0; x < water.Width; x++)
                {
                    for (y = 0; y < water.Height; y++)
                    {
                        water[x, y] *= 1.0 - (rainHeight / rounds);

                        double waterCapacity = waterSaturation * water[x, y];

                        double sedimentDeposit = sediment[x, y] - waterCapacity;
                        if (sedimentDeposit > 0)
                        {
                            if (mask[x, y])
                            {
                                sediment[x, y] -= sedimentDeposit;
                                map[x, y]      += sedimentDeposit;
                            }
                        }
                    }
                }
            }

            // Deposit any remainder (should be minimal)
            for (x = 0; x < water.Width; x++)
            {
                for (y = 0; y < water.Height; y++)
                {
                    if (mask[x, y] && sediment[x, y] > 0)
                    {
                        map[x, y] += sediment[x, y];
                    }
                }
            }
        }
Example #17
0
        public ITerrainChannel LoadFile(string filename, int offsetX, int offsetY, int fileWidth, int fileHeight, int sectionWidth, int sectionHeight)
        {
            TerrainChannel retval = new TerrainChannel(sectionWidth, sectionHeight, null);

            FileInfo     file = new FileInfo(filename);
            FileStream   s    = file.Open(FileMode.Open, FileAccess.Read);
            BinaryReader bs   = new BinaryReader(s);

            int currFileYOffset = fileHeight - 1;

            // if our region isn't on the first Y section of the areas to be landscaped, then
            // advance to our section of the file
            while (currFileYOffset > offsetY)
            {
                // read a whole strip of regions
                int heightsToRead = sectionHeight * (fileWidth * sectionWidth);
                bs.ReadBytes(heightsToRead * 13); // because there are 13 fun channels
                currFileYOffset--;
            }

            // got to the Y start offset within the file of our region
            // so read the file bits associated with our region
            int y;

            // for each Y within our Y offset
            for (y = sectionHeight - 1; y >= 0; y--)
            {
                int currFileXOffset = 0;

                // if our region isn't the first X section of the areas to be landscaped, then
                // advance the stream to the X start pos of our section in the file
                // i.e. eat X upto where we start
                while (currFileXOffset < offsetX)
                {
                    bs.ReadBytes(sectionWidth * 13);
                    currFileXOffset++;
                }

                // got to our X offset, so write our regions X line
                int x;
                for (x = 0; x < sectionWidth; x++)
                {
                    // Read a strip and continue
                    retval[x, y] = bs.ReadByte() * (bs.ReadByte() / 128);
                    bs.ReadBytes(11);
                }
                // record that we wrote it
                currFileXOffset++;

                // if our region isn't the last X section of the areas to be landscaped, then
                // advance the stream to the end of this Y column
                while (currFileXOffset < fileWidth)
                {
                    // eat the next regions x line
                    bs.ReadBytes(sectionWidth * 13); //The 13 channels again
                    currFileXOffset++;
                }
            }

            bs.Close();
            s.Close();

            return(retval);
        }
Example #18
0
        public ITerrainChannel LoadStream(Stream s, IScene scene)
        {
            int            size   = (int)Math.Sqrt(s.Length);
            TerrainChannel retval = new TerrainChannel(size, size, scene);

            BinaryReader bs = new BinaryReader(s);

            bool eof = false;

            if (Encoding.ASCII.GetString(bs.ReadBytes(16)) == "TERRAGENTERRAIN ")
            {
                int fileWidth  = scene.RegionInfo.RegionSizeX;
                int fileHeight = scene.RegionInfo.RegionSizeY;

                // Terragen file
                while (eof == false)
                {
                    string tmp = Encoding.ASCII.GetString(bs.ReadBytes(4));
                    switch (tmp)
                    {
                    case "SIZE":
                        int sztmp = bs.ReadInt16() + 1;
                        fileWidth  = sztmp;
                        fileHeight = sztmp;
                        bs.ReadInt16();
                        break;

                    case "XPTS":
                        fileWidth = bs.ReadInt16();
                        bs.ReadInt16();
                        break;

                    case "YPTS":
                        fileHeight = bs.ReadInt16();
                        bs.ReadInt16();
                        break;

                    case "ALTW":
                        eof = true;
                        short heightScale = bs.ReadInt16();
                        short baseHeight  = bs.ReadInt16();
                        for (int y = 0; y < fileHeight; y++)
                        {
                            for (int x = 0; x < fileWidth; x++)
                            {
                                retval [x, y] = baseHeight + bs.ReadInt16() * heightScale / 65536;
                            }
                        }
                        break;

                    default:
                        bs.ReadInt32();
                        break;
                    }
                }
            }

            bs.Close();

            return(retval);
        }
Example #19
0
        public ITerrainChannel LoadFile(string filename, int offsetX, int offsetY, int fileWidth, int fileHeight, int sectionWidth, int sectionHeight)
        {
            TerrainChannel retval = new TerrainChannel(sectionWidth, sectionHeight);

            FileInfo     file = new FileInfo(filename);
            FileStream   s    = file.Open(FileMode.Open, FileAccess.Read);
            BinaryReader bs   = new BinaryReader(s);

            bool eof = false;

            int fileXPoints = 0;
            int fileYPoints = 0;

            // Terragen file
            while (eof == false)
            {
                string tmp = Encoding.ASCII.GetString(bs.ReadBytes(4));
                switch (tmp)
                {
                case "SIZE":
                    fileXPoints = bs.ReadInt16() + 1;
                    fileYPoints = fileXPoints;
                    bs.ReadInt16();
                    break;

                case "XPTS":
                    fileXPoints = bs.ReadInt16();
                    bs.ReadInt16();
                    break;

                case "YPTS":
                    fileYPoints = bs.ReadInt16();
                    bs.ReadInt16();
                    break;

                case "ALTW":
                    eof = true;
                    Int16 heightScale = bs.ReadInt16();
                    Int16 baseHeight  = bs.ReadInt16();

                    int currFileYOffset = 0;

                    // if our region isn't on the first X section of the areas to be landscaped, then
                    // advance to our section of the file
                    while (currFileYOffset < offsetY)
                    {
                        // read a whole strip of regions
                        int heightsToRead = sectionHeight * fileXPoints;
                        bs.ReadBytes(heightsToRead * 2);     // because the shorts are 2 bytes in the file
                        currFileYOffset++;
                    }

                    for (int y = 0; y < sectionHeight; y++)
                    {
                        int currFileXOffset = 0;

                        // if our region isn't the first X section of the areas to be landscaped, then
                        // advance the stream to the X start pos of our section in the file
                        // i.e. eat X upto where we start
                        while (currFileXOffset < offsetX)
                        {
                            bs.ReadBytes(sectionWidth * 2);     // 2 bytes = short
                            currFileXOffset++;
                        }

                        // got to our X offset, so write our regions X line
                        for (int x = 0; x < sectionWidth; x++)
                        {
                            // Read a strip and continue
                            retval[x, y] = baseHeight + bs.ReadInt16() * (float)heightScale / 65536.0f;
                        }
                        // record that we wrote it
                        currFileXOffset++;

                        // if our region isn't the last X section of the areas to be landscaped, then
                        // advance the stream to the end of this Y column
                        while (currFileXOffset < fileWidth)
                        {
                            // eat the next regions x line
                            bs.ReadBytes(sectionWidth * 2);     // 2 bytes = short
                            currFileXOffset++;
                        }
                        //eat the last additional point
                        bs.ReadInt16();
                    }

                    break;

                default:
                    bs.ReadInt32();
                    break;
                }
            }

            bs.Close();
            s.Close();

            return(retval);
        }
Example #20
0
        public ITerrainChannel LoadStream(Stream s)
        {
            // Set to default size
            int w = (int)Constants.RegionSize;
            int h = (int)Constants.RegionSize;

            // create a dummy channel (in case data is bad)
            TerrainChannel retval = new TerrainChannel(w, h);

            BinaryReader bs = new BinaryReader(s);

            bool eof = false;

            if (Encoding.ASCII.GetString(bs.ReadBytes(16)) == "TERRAGENTERRAIN ")
            {
                // Terragen file
                while (eof == false)
                {
                    string tmp = Encoding.ASCII.GetString(bs.ReadBytes(4));
                    switch (tmp)
                    {
                    case "SIZE":
                        w = bs.ReadInt16() + 1;
                        h = w;
                        bs.ReadInt16();
                        break;

                    case "XPTS":
                        w = bs.ReadInt16();
                        bs.ReadInt16();
                        break;

                    case "YPTS":
                        h = bs.ReadInt16();
                        bs.ReadInt16();
                        break;

                    case "ALTW":
                        eof = true;
                        // create new channel of proper size (now that we know it)
                        retval = new TerrainChannel(w, h);
                        float heightScale = bs.ReadInt16() / 65536.0f;
                        float baseHeight  = bs.ReadInt16();
                        for (int y = 0; y < h; y++)
                        {
                            for (int x = 0; x < w; x++)
                            {
                                retval[x, y] = baseHeight + bs.ReadInt16() * heightScale;
                            }
                        }
                        break;

                    default:
                        bs.ReadInt32();
                        break;
                    }
                }
            }
            bs.Close();
            return(retval);
        }
Example #21
0
        public ITerrainChannel LoadStream(Stream s)
        {
            TerrainChannel retval = new TerrainChannel();

            BinaryReader bs = new BinaryReader(s);

            bool eof = false;

            if (Encoding.ASCII.GetString(bs.ReadBytes(16)) == "TERRAGENTERRAIN ")
            {
                int w = 256;
                int h = 256;

                // Terragen file
                while (eof == false)
                {
                    string tmp = Encoding.ASCII.GetString(bs.ReadBytes(4));
                    switch (tmp)
                    {
                    case "SIZE":
                        int sztmp = bs.ReadInt16() + 1;
                        w = sztmp;
                        h = sztmp;
                        bs.ReadInt16();
                        break;

                    case "XPTS":
                        w = bs.ReadInt16();
                        bs.ReadInt16();
                        break;

                    case "YPTS":
                        h = bs.ReadInt16();
                        bs.ReadInt16();
                        break;

                    case "ALTW":
                        eof = true;
                        Int16 heightScale = bs.ReadInt16();
                        Int16 baseHeight  = bs.ReadInt16();
                        retval = new TerrainChannel(w, h);
                        int x;
                        for (x = 0; x < w; x++)
                        {
                            int y;
                            for (y = 0; y < h; y++)
                            {
                                retval[x, y] = baseHeight + bs.ReadInt16() * (double)heightScale / 65536.0;
                            }
                        }
                        break;

                    default:
                        bs.ReadInt32();
                        break;
                    }
                }
            }

            bs.Close();

            return(retval);
        }
Example #22
0
        public void PaintEffect(ITerrainChannel map, UUID userID, float rx, float ry, float rz, float strength, float duration, float BrushSize, List <Scene> scene)
        {
            strength = TerrainUtil.MetersToSphericalStrength(strength);

            int x, y;
            // Using one 'rain' round for this, so skipping a useless loop
            // Will need to adapt back in for the Flood brush

            ITerrainChannel water    = new TerrainChannel(map.Width, map.Height, null);
            ITerrainChannel sediment = new TerrainChannel(map.Width, map.Height, null);

            // Fill with rain
            for (x = 0; x < water.Width; x++)
            {
                for (y = 0; y < water.Height; y++)
                {
                    water[x, y] = (float)Math.Max(0.0, TerrainUtil.SphericalFactor(x, y, rx, ry, strength) * rainHeight * duration);
                }
            }

            for (int i = 0; i < rounds; i++)
            {
                // Erode underlying terrain
                for (x = 0; x < water.Width; x++)
                {
                    for (y = 0; y < water.Height; y++)
                    {
                        const float solConst = (1.0f / rounds);
                        float       sedDelta = water[x, y] * solConst;
                        map[x, y]      -= sedDelta;
                        sediment[x, y] += sedDelta;
                    }
                }

                // Move water
                for (x = 0; x < water.Width; x++)
                {
                    for (y = 0; y < water.Height; y++)
                    {
                        if (water[x, y] <= 0)
                        {
                            continue;
                        }

                        // Step 1. Calculate average of neighbours

                        int   neighbours    = 0;
                        float altitudeTotal = 0.0f;
                        float altitudeMe    = map[x, y] + water[x, y];

                        const int NEIGHBOUR_ME  = 4;
                        const int NEIGHBOUR_MAX = 9;

                        for (int j = 0; j < NEIGHBOUR_MAX; j++)
                        {
                            if (j != NEIGHBOUR_ME)
                            {
                                int[] coords = Neighbours(type, j);

                                coords[0] += x;
                                coords[1] += y;

                                if (coords[0] > map.Width - 1)
                                {
                                    continue;
                                }
                                if (coords[1] > map.Height - 1)
                                {
                                    continue;
                                }
                                if (coords[0] < 0)
                                {
                                    continue;
                                }
                                if (coords[1] < 0)
                                {
                                    continue;
                                }

                                // Calculate total height of this neighbour
                                float altitudeNeighbour = water[coords[0], coords[1]] + map[coords[0], coords[1]];

                                // If it's greater than me...
                                if (altitudeNeighbour - altitudeMe < 0)
                                {
                                    // Add it to our calculations
                                    neighbours++;
                                    altitudeTotal += altitudeNeighbour;
                                }
                            }
                        }

                        if (neighbours == 0)
                        {
                            continue;
                        }

                        float altitudeAvg = altitudeTotal / neighbours;

                        // Step 2. Allocate water to neighbours.
                        for (int j = 0; j < NEIGHBOUR_MAX; j++)
                        {
                            if (j != NEIGHBOUR_ME)
                            {
                                int[] coords = Neighbours(type, j);

                                coords[0] += x;
                                coords[1] += y;

                                if (coords[0] > map.Width - 1)
                                {
                                    continue;
                                }
                                if (coords[1] > map.Height - 1)
                                {
                                    continue;
                                }
                                if (coords[0] < 0)
                                {
                                    continue;
                                }
                                if (coords[1] < 0)
                                {
                                    continue;
                                }

                                // Skip if we dont have water to begin with.
                                if (water[x, y] < 0)
                                {
                                    continue;
                                }

                                // Calculate our delta average
                                float altitudeDelta = altitudeMe - altitudeAvg;

                                if (altitudeDelta < 0)
                                {
                                    continue;
                                }

                                // Calculate how much water we can move
                                float waterMin   = Math.Min(water[x, y], altitudeDelta);
                                float waterDelta = waterMin * ((water[coords[0], coords[1]] + map[coords[0], coords[1]])
                                                               / altitudeTotal);

                                float sedimentDelta = sediment[x, y] * (waterDelta / water[x, y]);

                                if (sedimentDelta > 0)
                                {
                                    sediment[x, y] -= sedimentDelta;
                                    sediment[coords[0], coords[1]] += sedimentDelta;
                                }
                            }
                        }
                    }
                }

                // Evaporate

                for (x = 0; x < water.Width; x++)
                {
                    for (y = 0; y < water.Height; y++)
                    {
                        water[x, y] *= 1.0f - (rainHeight / rounds);

                        float waterCapacity = waterSaturation * water[x, y];

                        float sedimentDeposit = sediment[x, y] - waterCapacity;
                        if (sedimentDeposit > 0)
                        {
                            sediment[x, y] -= sedimentDeposit;
                            map[x, y]      += sedimentDeposit;
                        }
                    }
                }
            }

            // Deposit any remainder (should be minimal)
            for (x = 0; x < water.Width; x++)
            {
                for (y = 0; y < water.Height; y++)
                {
                    if (!((Scene)map.Scene).Permissions.CanTerraformLand(userID, new Vector3(rx + x, ry + y, 0)))
                    {
                        continue;
                    }
                    if (sediment[x, y] > 0)
                    {
                        map[(int)rx + x, (int)ry + y] += sediment[x, y];
                    }
                }
            }
        }
Example #23
0
        /// <summary>
        /// This method will produce a random city with the central region of the city being
        /// specified as a parameter. More parameters need to be made available for this method
        /// to produce a better quality city, note for now the minimum area for a city is a
        /// 3x3 grid of regions. This code is based on the original C++ version called pixel city.
        /// </summary>
        /// <param name="seed_value">Random integer seed value.</param>
        /// <returns>true / false indicator of success or failure.</returns>
        private bool doGenerate(int seed_value)
        {
            int rx, ry;

            //  Based on the initial seed value populate the regions that this shared module
            // is connected to, this means first get a list of the region, determine which
            // region is in the center of all the regions and set this as the hotzone, or
            // central part of the city (this is where the tallest/largest buildings will
            // be created) and will extend out to cover virtually all of the connected
            // regions if desired. No support for aging of the buildings or the city exists
            // yet it is a possible course for the future of this module.

            //  First quick check to see if the module is enabled or not.
            if (!m_fEnabled)
            {
                m_log.Info("[CITY BUILDER]: Disabled, aborting auto generation.");
                return(false);
            }

            m_log.Info("[CITY BUILDER]: Auto generating the city.");

            //  Now we need to ask some basic values for the city generation, we already have
            // the base seed value as this is part of the 'city generate' command, now what
            // about a name, position, size, densities etc. Some of this can be generated
            // based on the seed value, but then, it would need to be confirmed by the user
            // or allow them to change it. TODO move all requested data into the configuration file.
            if (m_UserAccountService == null)
            {
                m_UserAccountService = simulationBase.ApplicationRegistry.RequestModuleInterface <IUserAccountService>();
            }

            //  Decide where the city is to be placed within the server instance.
            int r = this.randomValue(10);

            string regionCount = MainConsole.Instance.CmdPrompt("Region Count ", r.ToString());

            r = Convert.ToInt32(regionCount);
            m_log.InfoFormat("[CITY BUILDER]: City area {0} x {1} regions ", r, r);

            cityName          = MainConsole.Instance.CmdPrompt("City Name ", cityName);
            cityOwner         = MainConsole.Instance.CmdPrompt("City Owner ", cityOwner);
            m_DefaultUserName = cityOwner;

            //  Make sure that the user and estate information specified in the configuration file
            // have been loaded and the information has either been found or has been created.
            m_DefaultUserAccount = m_UserAccountService.GetUserAccount(UUID.Zero, cityOwner);
            if (m_DefaultUserAccount == null)
            {
                m_log.InfoFormat("[CITY BUILDER]: Creating default account {0}", m_DefaultUserName);
                m_UserAccountService.CreateUser(m_DefaultUserName, Util.Md5Hash(m_DefaultUserPword), m_DefaultUserEmail);
                m_DefaultUserAccount = m_UserAccountService.GetUserAccount(UUID.Zero, m_DefaultUserName);
                cityOwner            = m_DefaultUserName;
            }
            else
            {
                m_log.InfoFormat("[CITY BUILDER]: Account found for {0}", m_DefaultUserName);
            }

            // Obtain the scene manager that the server instance is using.
            sceneManager = simulationBase.ApplicationRegistry.RequestModuleInterface <SceneManager>();

            //  Construct the data instance for a city map to hold the total regions in the simulation.
            cityMap               = new CityMap();
            citySeed              = seed_value;
            cityMap.cityRegions   = new Scene[r, r];
            cityMap.cityPlots     = new List <BuildingPlot>();
            cityMap.cityBuildings = new List <CityBuilding>();

            //  Construct land and estate data and update to reflect the found user or the newly created one.
            cityLandData = new LandData();
            RegionInfo regionInfo = new RegionInfo();

            regionInfo.RegionID = UUID.Random();

            //Create an estate
            m_DefaultEstate = new EstateSettings();

            m_log.InfoFormat("[CITY BUILDER]: No estates found for user {0}, constructing default estate.", m_DefaultUserAccount.Name);

            m_DefaultEstate.EstateOwner = m_DefaultUserAccount.PrincipalID;
            m_DefaultEstate.EstateName  = m_DefaultEstateName;
            m_DefaultEstate.EstatePass  = Util.Md5Hash(Util.Md5Hash(m_DefaultEstatePassword));
            m_DefaultEstate.EstateID    = (uint)this.randomValue(1000);

            regionInfo.EstateSettings = m_DefaultEstate; //Just set the estate, this module took care of the loading and the rest will leave it alone

            cityLandData.OwnerID  = m_DefaultUserAccount.PrincipalID;
            cityLandData.Name     = m_DefaultEstateName;
            cityLandData.GlobalID = UUID.Random();
            cityLandData.GroupID  = UUID.Zero;

            int regionPort = startPort;

            //  Construct the region.
            regionInfo.RegionSizeX    = cityConfig.GetInt("DefaultRegionSize", 256);
            regionInfo.RegionSizeY    = regionInfo.RegionSizeX;
            regionInfo.RegionType     = "Mainland";
            regionInfo.ObjectCapacity = 100000;
            regionInfo.Startup        = StartupType.Normal;
            regionInfo.ScopeID        = UUID.Zero;

            IParcelServiceConnector parcelService = Aurora.DataManager.DataManager.RequestPlugin <IParcelServiceConnector>();

            if (r == 1)
            {
                m_log.Info("[CITY BUILDER]: Single region city.");
                IPAddress address = IPAddress.Parse("0.0.0.0");
                regionInfo.ExternalHostName          = Aurora.Framework.Utilities.GetExternalIp();
                regionInfo.FindExternalAutomatically = true;
                regionInfo.InternalEndPoint          = new IPEndPoint(address, regionPort++);
                cityLandData.RegionID = regionInfo.RegionID;
                if (parcelService != null)
                {
                    parcelService.StoreLandObject(cityLandData.LandData);
                }
                regionInfo.RegionName = "Region00";
                regionInfo.RegionLocX = (int)m_DefaultStartLocation.X;
                regionInfo.RegionLocY = (int)m_DefaultStartLocation.Y;
                if (!createRegion(0, 0, regionInfo))
                {
                    m_log.Info("[CITY BUILDER]: Failed to construct region.");
                    return(false);
                }
            }
            else if (r > 1)
            {
                m_log.Info("[CITY BUILDER]: Multi-region city.");
                IPAddress address = IPAddress.Parse("0.0.0.0");
                regionInfo.ExternalHostName          = Aurora.Framework.Utilities.GetExternalIp();
                regionInfo.FindExternalAutomatically = true;
                //  Construct the regions for the city.
                regionPort = startPort;
                for (rx = 0; rx < r; rx++)
                {
                    for (ry = 0; ry < r; ry++)
                    {
                        regionInfo.InternalEndPoint = new IPEndPoint(address, regionPort++);
                        cityLandData.RegionID       = regionInfo.RegionID;
                        if (parcelService != null)
                        {
                            parcelService.StoreLandObject(cityLandData.LandData);
                        }
                        regionInfo.RegionName = "Region" + rx + ry;
                        regionInfo.RegionLocX = (int)(m_DefaultStartLocation.X + rx);
                        regionInfo.RegionLocY = (int)(m_DefaultStartLocation.Y + ry);
                        m_log.InfoFormat("[CITY BUILDER]: '{0}' @ {1},{2}, http://{3}/", regionInfo.RegionName,
                                         regionInfo.RegionLocX, regionInfo.RegionLocY, regionInfo.InternalEndPoint);
                        //We already set the estate before, we don't need to deal with linking it or anything
                        //EstateConnector.LinkRegion(regionInfo.RegionID, (int)m_DefaultEstate.EstateID, m_DefaultEstate.EstatePass);
                        if (!createRegion(rx, ry, regionInfo))
                        {
                            m_log.InfoFormat("[CITY BUILDER]: Failed to construct region at {0},{1}", rx, ry);
                            return(false);
                        }
                    }
                }
            }

            //  Either generate the terrain or loading from an existing file, DEM for example.
            m_log.Info("[CITY BUILDER]: [TERRAIN]");

            //  For each region, just fill the terrain to be 21. This is just above the default
            // water level for Aurora.
            float[,] tHeight = new float[256, 256];
            for (rx = 0; rx < 256; rx++)
            {
                for (ry = 0; ry < 256; ry++)
                {
                    tHeight[rx, ry] = 21.0f;
                }
            }
            //  Construct the new terrain for each region and pass the height map to it.
            for (rx = 0; rx < r; rx++)
            {
                for (ry = 0; ry < r; ry++)
                {
                    Scene           region   = cityMap.cityRegions[rx, ry];
                    ITerrainChannel tChannel = new TerrainChannel(true, region);
                    ITerrain        terrain  = null;
                    try
                    {
                        region.TryRequestModuleInterface <ITerrain>(out terrain);
                        terrain.SetHeights2D(tHeight);
                    }
                    catch
                    {
                    }
                }
            }

            //  Rivers and other waterways.

            //  From the total number of regions pick a number of regions that will be 'centers'
            // for the entire city, record these in the centralRegions list.
            m_log.Info("[CITY BUILDER]: [CENTERS]");
            //  ( region count * region count ) / 3
            int aNum = this.randomValue((cityMap.cityRegions.GetUpperBound(0) * cityMap.cityRegions.GetUpperBound(1)) / 3);

            if (aNum == 0)
            {
                aNum = 1;
            }
            m_log.InfoFormat("[CITY BUILDER]: Total regions {0}, selecting {1} regions for centers.", (r * r), aNum);
            int prevRegionX = 0;
            int prevRegionY = 0;

            while (aNum > 0)
            {
                int currRegionX = randomValue(cityMap.cityRegions.GetUpperBound(0)) / 2;
                int currRegionY = randomValue(cityMap.cityRegions.GetUpperBound(1)) / 2;

                // If the location selected is the same as the previous location try again.
                if (currRegionX == prevRegionX && currRegionY == prevRegionY)
                {
                    aNum--;
                    continue;
                }

                m_log.InfoFormat("[CITY BUILDER]: Region {0}, located {1},{2}", aNum, prevRegionX, prevRegionY);

                try
                {
                    Scene region = cityMap.centralRegions[(prevRegionX * cityMap.cityRegions.GetUpperBound(0)) + prevRegionY];
                    if (region != null)
                    {
                        cityMap.centralRegions.Add(region);
                    }
                }
                catch
                {
                }
                aNum--;
                prevRegionX = currRegionX;
                prevRegionY = currRegionY;
            }

            m_log.Info("[CITY BUILDER]: [DENSITY]");
            float avgDensity = 0.0f;

            avgDensity += cityDensities[0];
            avgDensity += cityDensities[1];
            avgDensity += cityDensities[2];
            avgDensity += cityDensities[3];
            avgDensity /= 4;

            //  Before ANYTHING else is created construct the transport systems, priority is given
            // to the road network before the rail network, perhaps a configuration option to allow
            // for the prioritisation value of the transport system is possible.
            m_log.Info("[CITY BUILDER]: [FREEWAYS]");
            m_log.Info("[CITY BUILDER]: [HIGHWAYS]");
            m_log.Info("[CITY BUILDER]: [STREETS]");
            m_log.Info("[CITY BUILDER]: [RAILWAYS]");

            m_log.InfoFormat("[CITY BUILDER]: [RESIDENTIAL DENSITY] {0}%", cityDensities[0] * 100);
            m_log.InfoFormat("[CITY BUILDER]: [COMMERCIAL DENSITY] {0}%", cityDensities[1] * 100);
            m_log.InfoFormat("[CITY BUILDER]: [CORPORATE DENSITY] {0}%", cityDensities[2] * 100);
            m_log.InfoFormat("[CITY BUILDER]: [INDUSTRIAL DENISTY] {0}%", cityDensities[3] * 100);
            m_log.InfoFormat("[CITY BUILDER]: [AVERAGE DENSITY] {0}%", avgDensity);

            m_log.Info("[CITY BUILDER]: [BLOCKS]");
            m_log.Info("[CITY BUILDER]: [ALLOTMENT PLOTS]");
            m_log.Info("[CITY BUILDER]: [BUILDINGS]");

            return(true);
        }