public ITerrainChannel MakeCopy() { TerrainChannel copy = new TerrainChannel(false, m_scene) { m_map = (short[])m_map.Clone(), taint = (bool[, ])taint.Clone() }; return(copy); }
protected virtual ITerrainChannel LoadBitmap(Bitmap bitmap) { ITerrainChannel retval = new TerrainChannel(bitmap.Width, bitmap.Height, null); 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; }
/// <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)); }
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 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 (!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 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); }
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 = 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 upto 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(); 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; }
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); 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(); 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; }