public TerrainController(SceneInterface scene) { uint x; uint y; uint xPatches = scene.SizeX / LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES; uint yPatches = scene.SizeY / LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES; LowerLimit = (float)scene.RegionSettings.TerrainLowerLimit; RaiseLimit = (float)scene.RegionSettings.TerrainRaiseLimit; m_Scene = scene; m_TerrainPatches = new LayerPatch[yPatches, xPatches]; for (y = 0; y < yPatches; ++y) { for (x = 0; x < xPatches; ++x) { m_TerrainPatches[y, x] = new LayerPatch(22) { X = x, Y = y }; } } Patch = new PatchesAccessor(m_TerrainPatches, xPatches, yPatches); }
bool ISimulationDataTerrainStorageInterface.TryGetDefault(UUID regionID, List <LayerPatch> list) { using (var connection = new MySqlConnection(m_ConnectionString)) { connection.Open(); using (var cmd = new MySqlCommand("SELECT PatchID, TerrainData FROM defaultterrains WHERE RegionID = @regionid", connection)) { cmd.Parameters.AddParameter("@regionid", regionID); cmd.CommandTimeout = 3600; using (MySqlDataReader dbReader = cmd.ExecuteReader()) { while (dbReader.Read()) { var patch = new LayerPatch { ExtendedPatchID = dbReader.GetUInt32("PatchID"), Serialization = dbReader.GetBytes("TerrainData") }; list.Add(patch); } } } } return(list.Count != 0); }
public double this[uint x, uint y] { get { if (x >= m_Scene.SizeX || y >= m_Scene.SizeY) { throw new KeyNotFoundException(); } return(m_TerrainPatches[x / LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES, y / LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES].Data[y % LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES, x % LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES]); } set { LayerPatch lp = null; if (x >= m_Scene.SizeX || y >= m_Scene.SizeY) { throw new KeyNotFoundException(); } m_TerrainRwLock.AcquireWriterLock(() => { lp = m_TerrainPatches[x / LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES, y / LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES]; lp.Data[y % LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES, x % LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES] = (float)value; lp.IncrementSerial(); }); if (lp != null) { lp.Dirty = true; } } }
public static void NoiseArea(UGUI agentOwner, SceneInterface scene, ModifyLand modify, ModifyLand.Data data) { var changed = new List <LayerPatch>(); for (int x = (int)data.West; x < (int)data.East; x++) { for (int y = (int)data.South; y < (int)data.North; y++) { if (!scene.CanTerraform(agentOwner, new Vector3(x, y, 0))) { continue; } double noise = PerlinNoise2D((double)x / scene.SizeX, (double)y / scene.SizeY, 8, 1); LayerPatch lp = scene.Terrain.AdjustTerrain((uint)x, (uint)y, noise * modify.Size); if (lp != null && !changed.Contains(lp)) { changed.Add(lp); } } } if (changed.Count != 0) { foreach (LayerPatch lp in changed) { lp.IncrementSerial(); scene.Terrain.UpdateTerrainListeners(lp); } scene.Terrain.UpdateTerrainDataToClients(); } }
public static List <LayerPatch> ToPatchesFromGrayscale(this Bitmap bitmap) { var patches = new List <LayerPatch>(); if ((bitmap.Width % LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES) != 0 || (bitmap.Height % LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES) != 0) { throw new ArgumentException("bitmap wxh is not dividable by LAYER_PATCH_NUM_XY_ENTRIES"); } for (uint y = 0; y < bitmap.Height / LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES; ++y) { for (uint x = 0; x < bitmap.Width / LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES; ++x) { var patch = new LayerPatch { X = x, Y = (uint)bitmap.Height / LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES - 1 - y }; for (uint py = 0; py < LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES; ++py) { for (uint px = 0; px < LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES; ++px) { long lx = x * LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES + px; long ly = bitmap.Height - (long)y * LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES - py - 1; patch[px, py] = bitmap.GetPixel((int)lx, (int)ly).GetBrightness() * 128f; } } patches.Add(patch); } } return(patches); }
List <LayerPatch> ISimulationDataTerrainStorageInterface.this[UUID regionID] { get { var patches = new List <LayerPatch>(); using (var connection = new NpgsqlConnection(m_ConnectionString)) { connection.Open(); using (var cmd = new NpgsqlCommand("SELECT \"PatchID\", \"TerrainData\" FROM terrains WHERE \"RegionID\" = @regionid", connection)) { cmd.Parameters.AddParameter("@regionid", regionID); cmd.CommandTimeout = 3600; using (NpgsqlDataReader dbReader = cmd.ExecuteReader()) { while (dbReader.Read()) { var patch = new LayerPatch { ExtendedPatchID = (uint)(int)dbReader["PatchID"], Serialization = dbReader.GetBytes("TerrainData") }; patches.Add(patch); } } } } return(patches); } }
public void UpdateTerrainListeners(LayerPatch layerpatch) { layerpatch = new LayerPatch(layerpatch); foreach (ITerrainListener listener in TerrainListeners) { listener.TerrainUpdate(layerpatch); } }
public void UpdateWithSerial(LayerPatch p) { if (p.X >= m_NumXPatches || p.Y >= m_NumYPatches) { throw new KeyNotFoundException(); } m_TerrainPatches[p.Y, p.X].UpdateWithSerial(p); }
public void TerrainUpdate(LayerPatch layerpatch) { if (layerpatch == null) { throw new ArgumentNullException(nameof(layerpatch)); } m_StorageTerrainRequestQueue.Enqueue(layerpatch); }
private List <LayerData> CompileWindData(Vector3 basepos) { var mlist = new List <LayerData>(); var patchesList = new List <LayerPatch>(); var patchX = new LayerPatch(); var patchY = new LayerPatch(); /* round to nearest low pos */ bool rX = basepos.X % 256 >= 128; bool rY = basepos.Y % 256 >= 128; basepos.X = Math.Floor(basepos.X / 256) * 256; basepos.Y = Math.Floor(basepos.Y / 256) * 256; for (int y = 0; y < 16; ++y) { for (int x = 0; x < 16; ++x) { Vector3 actpos = basepos; actpos.X += x * 4; actpos.Y += y * 4; if (rX && x < 8) { actpos.X += 128; } if (rY && y < 8) { actpos.Y += 128; } Vector3 w = Wind[actpos]; patchX[x, y] = (float)w.X; patchY[x, y] = (float)w.Y; } } patchesList.Add(patchX); patchesList.Add(patchY); var layerType = LayerData.LayerDataType.Wind; if (BASE_REGION_SIZE < m_Scene.SizeX || BASE_REGION_SIZE < m_Scene.SizeY) { layerType = LayerData.LayerDataType.WindExtended; } int offset = 0; while (offset < patchesList.Count) { int remaining = Math.Min(patchesList.Count - offset, LayerCompressor.MESSAGES_PER_WIND_LAYER_PACKET); int actualused; mlist.Add(LayerCompressor.ToLayerMessage(patchesList, layerType, offset, remaining, out actualused)); offset += actualused; } return(mlist); }
public static void FlattenArea(UGUI agentOwner, SceneInterface scene, ModifyLand modify, ModifyLand.Data data) { var changed = new List <LayerPatch>(); double sum = 0; double steps = 0; for (var x = (int)data.West; x < (int)data.East; x++) { for (var y = (int)data.South; y < (int)data.North; y++) { if (!scene.CanTerraform(agentOwner, new Vector3(x, y, 0))) { continue; } sum += scene.Terrain[(uint)x, (uint)y]; steps++; } } double avg = sum / steps; double str = 0.1f * modify.Size; // == 0.2 in the default client for (var x = (int)data.West; x < (int)data.East; x++) { for (var y = (int)data.South; y < (int)data.North; y++) { if (scene.CanTerraform(agentOwner, new Vector3(x, y, 0))) { LayerPatch lp = scene.Terrain.BlendTerrain((uint)x, (uint)y, avg, str); if (lp != null && !changed.Contains(lp)) { changed.Add(lp); } } } } if (changed.Count != 0) { foreach (LayerPatch lp in changed) { lp.IncrementSerial(); scene.Terrain.UpdateTerrainListeners(lp); } scene.Terrain.UpdateTerrainDataToClients(); } }
public static void SmoothArea(UGUI agentOwner, SceneInterface scene, ModifyLand modify, ModifyLand.Data data) { var changed = new List <LayerPatch>(); double area = modify.Size; double step = area / 4; for (int x = (int)data.West; x < (int)data.East; x++) { for (int y = (int)data.South; y < (int)data.North; y++) { if (!scene.CanTerraform(agentOwner, new Vector3(x, y, 0))) { continue; } double average = 0; int avgsteps = 0; for (double n = 0 - area; n < area; n += step) { for (double l = 0 - area; l < area; l += step) { avgsteps++; average += GetBilinearInterpolate(x + n, y + l, scene); } } LayerPatch lp = scene.Terrain.BlendTerrain((uint)x, (uint)y, average / avgsteps, 1); if (lp != null && !changed.Contains(lp)) { changed.Add(lp); } } } if (changed.Count != 0) { foreach (LayerPatch lp in changed) { lp.IncrementSerial(); scene.Terrain.UpdateTerrainListeners(lp); } scene.Terrain.UpdateTerrainDataToClients(); } }
/* * public IList<TerrainPatch> GetTerrainDistanceSorted(Vector3 v) * { * SortedList<int, TerrainPatch> sorted = new SortedList<int, TerrainPatch>(); * uint x; * uint y; * * if(v.X < 0) * { * x = 0; * } * else if(v.X >= SizeX) * { * x = SizeX - 1; * } * else * { * x = (uint)v.X / TERRAIN_PATCH_SIZE; * } * * if (v.Y < 0) * { * y = 0; * } * else if(v.Y >= SizeY) * { * y = SizeY - 1; * } * else * { * y = (uint)v.Y / TERRAIN_PATCH_SIZE; * } * * int distance; * * for(uint py = 0; py < SizeY / TERRAIN_PATCH_SIZE; ++py) * { * for(uint px = 0; px < SizeX / TERRAIN_PATCH_SIZE; ++px) * { * distance = ((int)px - (int)x) * ((int)px - (int)x) + ((int)py - (int)y) * ((int)py - (int)y); * sorted.Add(distance, new TerrainPatch(px, py, m_Map[py * m_PatchCountX + px])); * } * } * * return sorted.Values; * } */ private List <LayerData> CompileTerrainData(IAgent agent) => m_TerrainRwLock.AcquireReaderLock(() => { int y; int x; var mlist = new List <LayerData>(); var dirtyPatches = new List <LayerPatch>(); RwLockedDictionary <uint, uint> agentSceneSerials = agent.TransmittedTerrainSerials[m_Scene.ID]; for (y = 0; y < m_Scene.SizeY / LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES; ++y) { for (x = 0; x < m_Scene.SizeX / LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES; ++x) { LayerPatch patch = m_TerrainPatches[y, x]; uint serial; if (agentSceneSerials.TryGetValue(patch.ExtendedPatchID, out serial)) { if (serial != patch.Serial) { agentSceneSerials[patch.ExtendedPatchID] = serial; dirtyPatches.Add(m_TerrainPatches[y, x]); } } else { dirtyPatches.Add(m_TerrainPatches[y, x]); } } } var layerType = LayerData.LayerDataType.Land; if (BASE_REGION_SIZE < m_Scene.SizeX || BASE_REGION_SIZE < m_Scene.SizeY) { layerType = LayerData.LayerDataType.LandExtended; } int offset = 0; while (offset < dirtyPatches.Count) { int remaining = dirtyPatches.Count - offset; int actualused = 0; mlist.Add(LayerCompressor.ToLayerMessage(dirtyPatches, layerType, offset, remaining, out actualused)); offset += actualused; } return(mlist); });
public bool TryGetDefault(UUID regionID, List <LayerPatch> list) { RwLockedDictionary <uint, byte[]> patchesData; if (m_DefaultTerrainData.TryGetValue(regionID, out patchesData)) { foreach (var kvp in patchesData) { var patch = new LayerPatch { ExtendedPatchID = kvp.Key, Serialization = kvp.Value }; list.Add(patch); } return(true); } return(false); }
List <LayerPatch> ISimulationDataTerrainStorageInterface.this[UUID regionID] { get { RwLockedDictionary <uint, byte[]> patchesData; var patches = new List <LayerPatch>(); if (m_TerrainData.TryGetValue(regionID, out patchesData)) { foreach (var kvp in patchesData) { var patch = new LayerPatch { ExtendedPatchID = kvp.Key, Serialization = kvp.Value }; patches.Add(patch); } } return(patches); } }
public static List <LayerPatch> LoadStream(Stream input, int suggested_width, int suggested_height) { var patches = new List <LayerPatch>(); var vals = new float[LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES, suggested_width]; using (var bs = new BinaryReader(input)) { for (uint patchy = 0; patchy < suggested_height / LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES; ++patchy) { /* we have to load 16 lines at a time */ for (uint liney = 0; liney < LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES; ++liney) { for (uint x = 0; x < suggested_width; ++x) { vals[liney, x] = bs.ReadSingle(); } } /* now build patches from those 16 lines */ for (uint patchx = 0; patchx < suggested_width / LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES; ++patchx) { var patch = new LayerPatch { X = patchx, Y = patchy }; for (uint y = 0; y < LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES; ++y) { for (uint x = 0; x < LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES; ++x) { patch[x, y] = vals[y, x + patchx * LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES]; } } patches.Add(patch); } } } return(patches); }
public LayerPatch AdjustTerrain(uint x, uint y, double change) { if (x >= m_Scene.SizeX || y >= m_Scene.SizeY) { throw new KeyNotFoundException(); } return(m_TerrainRwLock.AcquireWriterLock(() => { LayerPatch lp = m_TerrainPatches[x / LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES, y / LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES]; float val = lp.Data[y % LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES, x % LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES] + (float)change; if (val < LowerLimit) { val = LowerLimit; } else if (val > RaiseLimit) { val = RaiseLimit; } lp.Data[y % LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES, x % LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES] = val; return lp; })); }
public void Flush() { var updatedPatches = new List <LayerPatch>(); m_TerrainRwLock.AcquireReaderLock(-1); try { int x; int y; for (y = 0; y < m_Scene.SizeY / LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES; ++y) { for (x = 0; x < m_Scene.SizeX / LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES; ++x) { LayerPatch patch = m_TerrainPatches[y, x]; if (patch.Dirty) { updatedPatches.Add(patch); patch.Dirty = false; } } } } finally { m_TerrainRwLock.ReleaseReaderLock(); } UpdateTerrainDataToClients(); foreach (LayerPatch lp in updatedPatches) { foreach (ITerrainListener listener in TerrainListeners) { listener.TerrainUpdate(new LayerPatch(lp)); } } }
public List <LayerPatch> LoadStream(System.IO.Stream input, int suggested_width, int suggested_height) { Encoding ascii = Encoding.ASCII; var patches = new List <LayerPatch>(); using (var bs = new BinaryReader(input)) { if (ascii.GetString(bs.ReadBytes(16)) == "TERRAGENTERRAIN ") { for (; ;) { switch (ascii.GetString(bs.ReadBytes(4))) { case "SIZE": suggested_width = bs.ReadInt16() + 1; suggested_height = suggested_width; bs.ReadInt16(); break; case "XPTS": suggested_width = bs.ReadInt16(); bs.ReadInt16(); break; case "YPTS": suggested_height = bs.ReadInt16(); bs.ReadInt16(); break; case "ALTW": float heightScale = (float)bs.ReadInt16() / 65536f; var baseHeight = (float)bs.ReadInt16(); var vals = new float[LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES, suggested_width / LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES]; for (uint patchy = 0; patchy < suggested_height / LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES; ++patchy) { /* we have to load 16 lines at a time */ for (uint liney = 0; liney < LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES; ++liney) { for (uint x = 0; x < suggested_width; ++x) { vals[liney, x] = baseHeight + bs.ReadInt16() * heightScale; } } /* now build patches from those 16 lines */ for (uint patchx = 0; patchx < suggested_width / LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES; ++patchx) { var patch = new LayerPatch { X = patchx, Y = patchy }; for (uint y = 0; y < LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES; ++y) { for (uint x = 0; x < LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES; ++x) { patch[x, y] = vals[y, x + patchx * LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES]; } } patches.Add(patch); } } return(patches); default: bs.ReadInt32(); break; } } } else { throw new ArgumentException("Invalid file format"); } } }
public static uint XYToYNormal(this LayerPatch p, uint lineWidth, uint minY) => (p.Y - minY) * lineWidth + p.X;
public static void FlattenSphere(UGUI agentOwner, SceneInterface scene, ModifyLand modify, ModifyLand.Data data) { var changed = new List <LayerPatch>(); double strength = MetersToSphericalStrength(data.BrushSize); int xFrom = (int)(data.West - data.BrushSize + 0.5); int xTo = (int)(data.West + data.BrushSize + 0.5); int yFrom = (int)(data.South - data.BrushSize + 0.5); int yTo = (int)(data.South + data.BrushSize + 0.5); if (xFrom < 0) { xFrom = 0; } if (yFrom < 0) { yFrom = 0; } if (xTo >= scene.SizeX) { xTo = (int)scene.SizeX - 1; } if (yTo > scene.SizeY) { yTo = (int)scene.SizeY - 1; } for (int x = xFrom; x <= xTo; x++) { for (int y = yFrom; y <= yTo; y++) { var pos = new Vector3(x, y, 0); if (!scene.CanTerraform(agentOwner, pos)) { continue; } double z = (modify.Seconds < 4.0) ? SphericalFactor(x, y, data.West, data.South, strength) * modify.Seconds * 0.25f : 1; double delta = modify.Height - scene.Terrain[(uint)x, (uint)y]; if (Math.Abs(delta) > 0.1) { if (z > 1) { z = 1; } else if (z < 0) { z = 0; } delta *= z; } if (Math.Abs(delta) >= Double.Epsilon) // add in non-zero amount { LayerPatch lp = scene.Terrain.AdjustTerrain((uint)x, (uint)y, delta); if (lp != null && !changed.Contains(lp)) { changed.Add(lp); } } } } if (changed.Count != 0) { foreach (LayerPatch lp in changed) { lp.IncrementSerial(); } scene.Terrain.UpdateTerrainDataToClients(); } }
public static uint XYToYInverted(this LayerPatch p, uint lineWidth, uint maxY) => (maxY - p.Y) * lineWidth + p.X;
public static void LowerSphere(UGUI agentOwner, SceneInterface scene, ModifyLand modify, ModifyLand.Data data) { var changed = new List <LayerPatch>(); int xFrom = (int)(data.West - data.BrushSize + 0.5); int xTo = (int)(data.West + data.BrushSize + 0.5); int yFrom = (int)(data.South - data.BrushSize + 0.5); int yTo = (int)(data.South + data.BrushSize + 0.5); if (xFrom < 0) { xFrom = 0; } if (yFrom < 0) { yFrom = 0; } if (xTo >= scene.SizeX) { xTo = (int)scene.SizeX - 1; } if (yTo >= scene.SizeY) { yTo = (int)scene.SizeY - 1; } for (int x = xFrom; x <= xTo; x++) { for (int y = yFrom; y <= yTo; y++) { Vector3 pos = new Vector3(x, y, 0); if (!scene.CanTerraform(agentOwner, pos)) { continue; } // Calculate a cos-sphere and add it to the heightmap double r = Math.Sqrt((x - data.West) * (x - data.West) + ((y - data.South) * (y - data.South))); double z = Math.Cos(r * Math.PI / (data.BrushSize * 2)); if (z > 0.0) { LayerPatch lp = scene.Terrain.AdjustTerrain((uint)x, (uint)y, -z * modify.Seconds); if (lp != null && !changed.Contains(lp)) { changed.Add(lp); } } } } if (changed.Count != 0) { foreach (LayerPatch lp in changed) { lp.IncrementSerial(); scene.Terrain.UpdateTerrainListeners(lp); } scene.Terrain.UpdateTerrainDataToClients(); } }
public static void NoiseSphere(UGUI agentOwner, SceneInterface scene, ModifyLand modify, ModifyLand.Data data) { var changed = new List <LayerPatch>(); int n = (int)(data.BrushSize + 0.5f); if (data.BrushSize > 6) { data.BrushSize = 6; } double strength = MetersToSphericalStrength(data.BrushSize); double area = data.BrushSize; double step = data.BrushSize / 4; double duration = modify.Seconds * 0.01f; int zx = (int)(data.West + 0.5); int zy = (int)(data.South + 0.5); double average = 0; int avgsteps = 0; for (double nn = 0 - area; nn < area; nn += step) { for (double l = 0 - area; l < area; l += step) { avgsteps++; average += GetBilinearInterpolate(data.West + nn, data.South + l, scene); } } for (int dx = -n; dx <= n; dx++) { for (int dy = -n; dy <= n; dy++) { int x = zx + dx; int y = zy + dy; if (x >= 0 && y >= 0 && x < scene.SizeX && y < scene.SizeY) { Vector3 pos = new Vector3(x, y, 0); if (!scene.CanTerraform(agentOwner, pos)) { continue; } double z = SphericalFactor(x, y, data.West, data.South, strength) / (strength); if (z > 0) // add in non-zero amount { double a = scene.Terrain[(uint)x, (uint)y] - (average / avgsteps); LayerPatch lp = scene.Terrain.AdjustTerrain((uint)x, (uint)y, a * duration); if (lp != null && !changed.Contains(lp)) { changed.Add(lp); } } } } } if (changed.Count != 0) { foreach (LayerPatch lp in changed) { lp.IncrementSerial(); scene.Terrain.UpdateTerrainListeners(lp); } scene.Terrain.UpdateTerrainDataToClients(); } }