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."); }
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); }
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 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)."); }
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); }
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)."); }
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); }
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); }
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); }
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); }
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); }
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); }
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); } }
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]; } } } }
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); }
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 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); }
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); }
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); }
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]; } } } }
/// <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); }