Beispiel #1
0
        public ITerrainChannel LoadFile (string filename, IScene scene, int offsetX, int offsetY, int fileWidth, int fileHeight,
                                        int sectionWidth, int sectionHeight)
        {
            TerrainChannel retval = new TerrainChannel (sectionWidth, sectionHeight, scene);

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

            int currFileYOffset = 0;

            // 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 * 4); // because the floats are 4 bytes in the file
                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 = 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 up to where we start
                while (currFileXOffset < offsetX) {
                    bs.ReadBytes (sectionWidth * 4); // 4 bytes = single
                    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.ReadSingle ();
                }
                // 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 * 4); // 4 bytes = single
                    currFileXOffset++;
                }
            }

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

            return retval;
        }
Beispiel #2
0
        public ITerrainChannel MakeCopy()
        {
            TerrainChannel copy = new TerrainChannel(false, m_scene)
            {
                m_map = (short[])m_map.Clone(), taint = (bool[, ])taint.Clone()
            };

            return(copy);
        }
        public void PaintEffect(ITerrainChannel map, UUID userID, float rx, float ry, float rz, float strength,
            float duration, float BrushSize)
        {
            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 neighbors

                        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 neighbor
                                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 neighbors.
                        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 don't 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 (!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];
                }
            }
        }
        protected virtual ITerrainChannel LoadBitmap(Bitmap bitmap)
        {
            ITerrainChannel retval = new TerrainChannel(bitmap.Width, bitmap.Height, null);

            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;
                }
            }

            return retval;
        }
 public ITerrainChannel MakeCopy()
 {
     TerrainChannel copy = new TerrainChannel(false, m_scene)
                               {m_map = (short[]) m_map.Clone(), taint = (bool[,]) taint.Clone()};
     return copy;
 }
Beispiel #6
0
        public ITerrainChannel LoadStream(Stream s, IScene scene)
        {
            BinaryReader bs = new BinaryReader(s);
            int size = (int) 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;
        }
        public void GenerateTerrain(IScene scene, string[] s)
        {
            string noiseType = MainConsole.Instance.Prompt("Noise generator (Perlin or Kosh)", "Perlin");
            bool perlinNoise = noiseType.ToLower().StartsWith("p");
            int baseHeight;

            if (perlinNoise)
            {
                _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("Coarseness (X direction) (2-1000)", "100"));
                pns.CorsenessY = int.Parse(MainConsole.Instance.Prompt("Coarseness (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;
                baseHeight = 30;
            }
            else
            {
                _noiseGen = m_kochLikeNoise;
                KochLikeNoiseSettings kns = new KochLikeNoiseSettings();
                //kns.ResultX = MainConsole.Instance.Prompt.RegionInfo.RegionSizeX;
                //kns.ResultY = MainConsole.Instance.Prompt.RegionInfo.RegionSizeY;
                kns.ResultX = scene.RegionInfo.RegionSizeX * 2;
                kns.ResultY = scene.RegionInfo.RegionSizeY * 2;
                kns.H = double.Parse(MainConsole.Instance.Prompt("Smoothing (Higher values are smoother)", "1.5"));
                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;
                // grid X/Y divide the region so...
                //                kns.ResultX = kns.ResultX * kns.InitalGridX;
                //                kns.ResultY = kns.ResultY * kns.InitalGridY;

                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;
                baseHeight = 0;
            }

            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 + baseHeight;
                }
            }
            scene.RequestModuleInterface<ITerrainModule>().TerrainMap = c;
            scene.RequestModuleInterface<ITerrainModule>().TaintTerrain();
            scene.RegisterModuleInterface<ITerrainChannel>(c);
        }
        public ITerrainChannel LoadFile(string filename, IScene scene, int offsetX, int offsetY, int fileWidth, int fileHeight,
            int sectionWidth, int sectionHeight)
        {
            TerrainChannel retval = new TerrainChannel(sectionWidth, sectionHeight, scene);

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

            bool eof = false;

            int fileXPoints = 0;

            // Terragen file
            while (eof == false)
            {
                string tmp = Encoding.ASCII.GetString(bs.ReadBytes(4));
                switch (tmp)
                {
                    case "SIZE":
                        fileXPoints = bs.ReadInt16() + 1;
                        bs.ReadInt16();
                        break;
                    case "XPTS":
                        fileXPoints = bs.ReadInt16();
                        bs.ReadInt16();
                        break;
                    case "YPTS":
                        /*int 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()*heightScale/65536;
                            }
                            // 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;
        }
        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;
                            Int16 heightScale = bs.ReadInt16();
                            Int16 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;
        }
 /// <summary>
 ///     Reset the terrain of this region to the default
 /// </summary>
 public void ResetWater()
 {
     if (!m_noTerrain)
     {
         TerrainChannel channel = new TerrainChannel(m_scene);
         m_waterChannel = channel;
         m_scene.SimulationDataService.Tainted();
         CheckForTerrainUpdates(false, true, true);
     }
 }
 /// <summary>
 ///     Reset the terrain of this region to the default
 /// </summary>
 public void ResetTerrain()
 {
     if (!m_noTerrain)
     {
         TerrainChannel channel = new TerrainChannel(m_scene);
         m_channel = channel;
         m_scene.SimulationDataService.Tainted();
         m_scene.RegisterModuleInterface(m_channel);
         CheckForTerrainUpdates(false, true, false);
     }
 }
        /// <summary>
        ///     Loads a terrain file from a stream and installs it in the scene.
        /// </summary>
        /// <param name="filename">Filename to terrain file. Type is determined by extension.</param>
        /// <param name="stream"></param>
        /// <param name="offsetX"></param>
        /// <param name="offsetY"></param>
        /// <param name="update"></param>
        public ITerrainChannel InternalLoadFromStream(string filename, Stream stream, int offsetX, int offsetY,
            ITerrainChannel update)
        {
            ITerrainChannel channel = null;

            foreach (
                KeyValuePair<string, ITerrainLoader> loader in m_loaders.Where(loader => Path.GetExtension(filename.ToLower()) == loader.Key))
            {
                lock (m_scene)
                {
                    try
                    {
                        channel = loader.Value.LoadStream(stream, m_scene);
                        if (channel != null)
                        {
                            channel.Scene = m_scene;
                            if (update == null || (update.Height == channel.Height &&
                                                   update.Width == channel.Width))
                            {
                                if (m_scene.RegionInfo.RegionSizeX != channel.Width ||
                                    m_scene.RegionInfo.RegionSizeY != channel.Height)
                                {
                                    if ((channel.Width) > m_scene.RegionInfo.RegionSizeX ||
                                        (channel.Height) > m_scene.RegionInfo.RegionSizeY)
                                    {
                                        TerrainChannel c = new TerrainChannel(true, m_scene);
                                        for (int x = 0; x < m_scene.RegionInfo.RegionSizeX; x++)
                                        {
                                            for (int y = 0; y < m_scene.RegionInfo.RegionSizeY; y++)
                                            {
                                                c[x, y] = channel[x, y];
                                            }
                                        }
                                        return c;
                                    }
                                    return null;
                                }
                            }
                            else
                            {
                                //Make sure it is in bounds
                                if ((offsetX + channel.Width) > update.Width ||
                                    (offsetY + channel.Height) > update.Height)
                                {
                                    MainConsole.Instance.Error(
                                        "[TERRAIN]: Unable to load heightmap, the terrain you have given is larger than the current region.");
                                    return null;
                                }
                                else
                                {
                                    //Merge the terrains together at the specified offset
                                    for (int x = offsetX; x < offsetX + channel.Width; x++)
                                    {
                                        for (int y = offsetY; y < offsetY + channel.Height; y++)
                                        {
                                            update[x, y] = channel[x - offsetX, y - offsetY];
                                        }
                                    }
                                    return update;
                                }
                            }
                        }
                    }
                    catch (NotImplementedException)
                    {
                        MainConsole.Instance.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value +
                                                   " parser does not support file loading. (May be save only)");
                        throw new TerrainException(
                            String.Format("unable to load heightmap: parser {0} does not support loading",
                                          loader.Value));
                    }
                }

                MainConsole.Instance.Info("[TERRAIN]: File (" + filename + ") loaded successfully");
                return channel;
            }

            MainConsole.Instance.Error("[TERRAIN]: Unable to load heightmap, no file loader available for that format.");
            throw new TerrainException(
                String.Format("unable to load heightmap from file {0}: no loader available for that format", filename));
        }
        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;
        }