diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/SmoothArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/SmoothArea.cs index e5e6f4df85..c302c08caa 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/SmoothArea.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/SmoothArea.cs @@ -36,18 +36,23 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes public void FloodEffect(ITerrainChannel map, bool[,] fillArea, float height, float strength, int startX, int endX, int startY, int endY) { - double area = 4; - double step = 1; + int sx = (endX - startX + 1) / 2; + if (sx > 4) + sx = 4; + + int sy = (endY - startY + 1) / 2; + if (sy > 4) + sy = 4; strength *= 0.002f; if(strength > 1.0f) strength = 1.0f; - double[,] manipulate = new double[map.Width,map.Height]; - int x, y; - for (x = startX; x <= endX; x++) + double[,] tweak = new double[endX - startX + 1, endX - startX + 1]; + + for (int x = startX, i = 0; x <= endX; x++, i++) { - for (y = startY; y <= endY; y++) + for (int y = startY, j = 0; y <= endY; y++, j++) { if (!fillArea[x, y]) continue; @@ -55,65 +60,31 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes double average = 0.0; int avgsteps = 0; - double n; - for (n = -area; n < area; n += step) + for (int n = x - sx; n <= x + sx; ++n) { - double l; - for (l = -area; l < area; l += step) + for (int l = y - sy; l < y + sy; ++l) { avgsteps++; - average += GetBilinearInterpolate(x + n, y + l, map); + average += map[n, l]; } } - manipulate[x, y] = average / avgsteps; + tweak[i, j] = average / avgsteps; } } - for (x = startX; x <= endX; x++) + + for (int x = startX, i = 0; x <= endX; x++, i++) { - for (y = startY; y <= endY; y++) + for (int y = startY, j = 0; y <= endY; y++, j++) { - if (!fillArea[x, y]) + double ty = tweak[i, j]; + if (ty == 0.0) continue; - map[x, y] = (1.0 - strength) * map[x, y] + strength * manipulate[x, y]; + map[x, y] = (1.0 - strength) * map[x, y] + strength * ty; } } } - - #endregion - - private static double GetBilinearInterpolate(double x, double y, ITerrainChannel map) - { - int w = map.Width; - int h = map.Height; - - if (x > w - 2.0) - x = w - 2.0; - if (y > h - 2.0) - y = h - 2.0; - if (x < 0.0) - x = 0.0; - if (y < 0.0) - y = 0.0; - - const int stepSize = 1; - double h00 = map[(int) x, (int) y]; - double h10 = map[(int) x + stepSize, (int) y]; - double h01 = map[(int) x, (int) y + stepSize]; - double h11 = map[(int) x + stepSize, (int) y + stepSize]; - double h1 = h00; - double h2 = h10; - double h3 = h01; - double h4 = h11; - double a00 = h1; - double a10 = h2 - h1; - double a01 = h3 - h1; - double a11 = h1 - h2 - h3 + h4; - double partialx = x - (int) x; - double partialz = y - (int) y; - double hi = a00 + (a10 * partialx) + (a01 * partialz) + (a11 * partialx * partialz); - return hi; - } } + #endregion } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/FlattenSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/FlattenSphere.cs index 4c24e49b71..5e3e935964 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/FlattenSphere.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/FlattenSphere.cs @@ -39,22 +39,26 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes float size, float strength, int startX, int endX, int startY, int endY) { int x, y; - - size *= 2; - float distancefactor; + float dx2; + + size *= 2 * size; // blend in map for (x = startX; x <= endX; ++x) { + dx2 = (x - rx) * (x - rx); for (y = startY; y <= endY; ++y) { if (!mask[x,y]) continue; + + distancefactor = (dx2 + (y - ry) * (y - ry)) / size; + if(distancefactor > 1.0f) + continue; - distancefactor = strength * TerrainUtil.SphericalFactor(x - rx, y - ry, size); - - if(distancefactor >= 1.0f) + distancefactor = strength * (1.0f - distancefactor); + if (distancefactor >= 1.0f) map[x, y] = rz; else map[x, y] += (rz - (float)map[x, y]) * distancefactor; diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs index 5a31a603ee..4e1d0fc238 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs @@ -38,18 +38,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes float size, float strength, int startX, int endX, int startY, int endY) { size = 0.5f * (float)Math.PI / size; - strength *= 2; - int x, y; - for (x = startX; x <= endX; x++) + float dx2; + for (int x = startX; x <= endX; ++x) { - for (y = startY; y <= endY; y++) + dx2 = (x - rx) * (x - rx); + for (int y = startY; y <= endY; ++y) { if (!mask[x, y]) continue; // Calculate a cos-sphere and add it to the heighmap - double r = Math.Sqrt((x - rx) * (x - rx) + (y - ry) * (y - ry)); + double r = Math.Sqrt(dx2 + (y - ry) * (y - ry)); double distancefactor = Math.Cos(r * size); if (distancefactor > 0.0) { diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs index 010ca0c82e..ac6d1af853 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs @@ -39,21 +39,27 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes float size, float strength, int startX, int endX, int startY, int endY) { int x, y; + float distancefactor; + float dx2; + + size *= size; for (x = startX; x <= endX; x++) { + dx2 = (x - rx) * (x - rx); for (y = startY; y <= endY; y++) { if (!mask[x, y]) continue; // Calculate a sphere and add it to the heighmap - float distancefactor = TerrainUtil.SphericalFactor(x - rx, y - ry, size); + distancefactor = (dx2 + (y - ry) * (y - ry)) / size; + if (distancefactor > 1.0f) + continue; + distancefactor = strength * (1.0f - distancefactor); double noise = TerrainUtil.PerlinNoise2D(x / (double) map.Width, y / (double) map.Height, 8, 1.0); - - if (distancefactor > 0.0) - map[x, y] += noise * distancefactor * strength; + map[x, y] += noise * distancefactor; } } } diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs index e2773636d8..1946f271ea 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs @@ -39,19 +39,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes float size, float strength, int startX, int endX, int startY, int endY) { size = 0.5f *(float)Math.PI / size; - strength *= 2; - int x, y; - - for (x = startX; x <= endX; ++x) + float dx2; + for (int x = startX; x <= endX; ++x) { - for (y = startY; y <= endY; ++y) + dx2 = (x - rx) * (x - rx); + for (int y = startY; y <= endY; ++y) { if (!mask[x, y]) continue; - // Calculate a cos-sphere and add it to the heighmap - double r = Math.Sqrt((x - rx) * (x - rx) + (y - ry) * (y - ry)); + // Calculate a cos-sphere and add it to the heighmap + double r = Math.Sqrt(dx2 + (y - ry) * (y - ry)); double distancefactor = Math.Cos(r * size); if (distancefactor > 0.0) map[x, y] += distancefactor * strength; diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs index ab3c5b7973..4b7d9a18c4 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs @@ -50,21 +50,25 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes if (strength > 1.0f) strength = 1.0f; - int x,y; + int x, y; + float distancefactor; + float dx2; + for (x = startX; x <= endX; x++) { + dx2 = (x - rx) * (x - rx); for (y = startY; y <= endY; y++) { if (!mask[x, y]) continue; // Calculate a sphere and add it to the heighmap - double distancefactor = TerrainUtil.SphericalFactor(x - rx, y - ry, size); - if (distancefactor > 0.0) - { - distancefactor *= strength; - map[x, y] = (map[x, y] * (1.0 - distancefactor)) + (m_revertmap[x, y] * distancefactor); - } + distancefactor = (dx2 + (y - ry) * (y - ry)) / size; + if (distancefactor > 1.0f) + continue; + + distancefactor = strength * (1.0f - distancefactor); + map[x, y] = (map[x, y] * (1.0 - distancefactor)) + (m_revertmap[x, y] * distancefactor); } } } diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs index a952694816..69efdb9eb5 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs @@ -35,60 +35,66 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes #region ITerrainPaintableEffect Members public void PaintEffect(ITerrainChannel map, bool[,] mask, float rx, float ry, float rz, - float size, float strengh, int startX, int endX, int startY, int endY) + float size, float strength, int startX, int endX, int startY, int endY) { - int x, y; - double[,] tweak = new double[map.Width, map.Height]; + float distancefactor; + float dx2; - double step = size / 4.0; + double[,] tweak = new double[endX - startX + 1, endX - startX + 1]; + int ssize = (int)(size + 0.5); + if(ssize > 4) + ssize = 4; - if(strengh > 1.0f) - strengh = 1.0f; + size *= size; + + if (strength > 1.0f) + strength = 1.0f; // compute delta map - for (x = startX; x <= endX; x++) + for (int x = startX, i = 0; x <= endX; x++, i++) { - for (y = startY; y <= endY; y++) + dx2 = (x - rx) * (x - rx); + for (int y = startY, j = 0; y <= endY; y++, j++) { if (!mask[x, y]) continue; - double z = TerrainUtil.SphericalFactor(x - rx, y - ry, size); - - if (z > 0) // add in non-zero amount + distancefactor = (dx2 + (y - ry) * (y - ry)) / size; + if (distancefactor <= 1.0f) { + distancefactor = strength * (1.0f - distancefactor); + double average = 0.0; int avgsteps = 0; - double n; - for (n =- size; n < size; n += step) + for (int n = x - ssize; n <= x + ssize; ++n) { - double l; - for (l = -size; l < size; l += step) + if(n > 0 && n < map.Width) { - avgsteps++; - average += TerrainUtil.GetBilinearInterpolate(x + n, y + l, map); + for (int l = y - ssize; l <= y + ssize; ++l) + { + if (l > 0 && l < map.Height) + { + avgsteps++; + average += map[n, l]; + } + } } } - tweak[x, y] = average / avgsteps; + average /= avgsteps; + tweak[i, j] = distancefactor * (map[x, y] - average); } } } // blend in map - for (x = startX; x <= endX; x++) + for (int x = startX, i = 0; x <= endX; x++, i++) { - for (y = startY; y <= endY; y++) + for (int y = startY, j = 0; y <= endY; y++, j++) { - if (!mask[x, y]) - continue; - - float distancefactor = TerrainUtil.SphericalFactor(x - rx, y - ry, size); - - if (distancefactor > 0) // add in non-zero amount + double tz = tweak[i, j]; + if(tz != 0.0) { - double a = (map[x, y] - tweak[x, y]) * distancefactor; - double newz = map[x, y] - (a * strengh); - + double newz = map[x, y] - tz; if (newz > 0.0) map[x, y] = newz; } diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index 9e7237bdde..b98bc9df22 100755 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -516,12 +516,35 @@ namespace OpenSim.Region.CoreModules.World.Terrain /// UUID of script-owner public void ModifyTerrain(UUID user, Vector3 pos, byte size, byte action) { - float duration = 0.25f; + float duration; float brushSize; - if(action == (byte)StandardTerrainEffects.Lower || action == (byte)StandardTerrainEffects.Raise) - brushSize = (int)(Math.Pow(2, size) + 0.5); + if (size > 2) + { + size = 3; + brushSize = 4.0f; + } else - brushSize = (size + 1) * 1.35f; + { + size++; + brushSize = size; + } + + switch((StandardTerrainEffects)action) + { + case StandardTerrainEffects.Flatten: + duration = 7.29f * size * size; + break; + case StandardTerrainEffects.Smooth: + case StandardTerrainEffects.Revert: + duration = 0.06f * size * size; + break; + case StandardTerrainEffects.Noise: + duration = 0.46f * size * size; + break; + default: + duration = 0.25f; + break; + } client_OnModifyTerrain(user, pos.Z, duration, brushSize, action, pos.Y, pos.X, pos.Y, pos.X, -1); } @@ -1304,9 +1327,17 @@ namespace OpenSim.Region.CoreModules.World.Terrain return ret; } + private double NextModifyTerrainTime = double.MinValue; + private void client_OnModifyTerrain(UUID user, float height, float seconds, float brushSize, byte action, float north, float west, float south, float east, int parcelLocalID) { + double now = Util.GetTimeStamp(); + if(now < NextModifyTerrainTime) + return; + + NextModifyTerrainTime = double.MaxValue; // block it + //m_log.DebugFormat("brushs {0} seconds {1} height {2}, parcel {3}", brushSize, seconds, height, parcelLocalID); bool god = m_scene.Permissions.IsGod(user); bool allowed = false; @@ -1454,6 +1485,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain m_log.Debug("Unknown terrain flood type " + action); } } + NextModifyTerrainTime = Util.GetTimeStamp() + 0.02; // 20ms cooldown } private void client_OnBakeTerrain(IClientAPI remoteClient)