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