A new version of the old Channel class, simplified
Inheritance: ITerrainChannel
        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);
        }
 /// <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;

            // find the loader to use..
            //var fileExt = Path.GetExtension(filename.ToLower());
            //foreach (KeyValuePair<string, ITerrainLoader> floader in m_loaders)
               // {
            //	if (fileExt != floader.Key)
            //		continue;
            //
            //	ITerrainLoader loader = floader.Value;
            //{
            var loader = GetTerrainLoader (filename);
            if (loader != null)
            {
                lock (m_scene)
                {
                    try
                    {
                        channel = loader.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 +
                                                   " parser does not support file loading. (May be save only)");
                    }
                }

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

            MainConsole.Instance.ErrorFormat("[TERRAIN]: Unable to load heightmap from {0}, no file loader available for that format.", filename);
            return channel;
        }
        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;
            }

            return retval;
        }
Beispiel #7
0
        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];
                }
            }
        }
 public ITerrainChannel MakeCopy()
 {
     TerrainChannel copy = new TerrainChannel(false, m_scene)
                               {m_map = (short[]) m_map.Clone(), taint = (bool[,]) taint.Clone()};
     return copy;
 }
        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;
                    short heightScale = bs.ReadInt16 ();
                    short 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 up to 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;
                        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;
        }
        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;
        }