more changes on terrain edit. Silent ignore comand if busy (large area smooth can take ages), brush changes, etc

0.9.1.1
UbitUmarov 2019-11-12 03:16:53 +00:00
parent 01832b3e3c
commit 9eb5fd4330
8 changed files with 135 additions and 113 deletions

View File

@ -36,18 +36,23 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
public void FloodEffect(ITerrainChannel map, bool[,] fillArea, float height, float strength, public void FloodEffect(ITerrainChannel map, bool[,] fillArea, float height, float strength,
int startX, int endX, int startY, int endY) int startX, int endX, int startY, int endY)
{ {
double area = 4; int sx = (endX - startX + 1) / 2;
double step = 1; if (sx > 4)
sx = 4;
int sy = (endY - startY + 1) / 2;
if (sy > 4)
sy = 4;
strength *= 0.002f; strength *= 0.002f;
if(strength > 1.0f) if(strength > 1.0f)
strength = 1.0f; strength = 1.0f;
double[,] manipulate = new double[map.Width,map.Height]; double[,] tweak = new double[endX - startX + 1, endX - startX + 1];
int x, y;
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]) if (!fillArea[x, y])
continue; continue;
@ -55,65 +60,31 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
double average = 0.0; double average = 0.0;
int avgsteps = 0; int avgsteps = 0;
double n; for (int n = x - sx; n <= x + sx; ++n)
for (n = -area; n < area; n += step)
{ {
double l; for (int l = y - sy; l < y + sy; ++l)
for (l = -area; l < area; l += step)
{ {
avgsteps++; 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; 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 #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;
}
}
} }

View File

@ -39,22 +39,26 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
float size, float strength, int startX, int endX, int startY, int endY) float size, float strength, int startX, int endX, int startY, int endY)
{ {
int x, y; int x, y;
size *= 2;
float distancefactor; float distancefactor;
float dx2;
size *= 2 * size;
// blend in map // blend in map
for (x = startX; x <= endX; ++x) for (x = startX; x <= endX; ++x)
{ {
dx2 = (x - rx) * (x - rx);
for (y = startY; y <= endY; ++y) for (y = startY; y <= endY; ++y)
{ {
if (!mask[x,y]) if (!mask[x,y])
continue; continue;
distancefactor = strength * TerrainUtil.SphericalFactor(x - rx, y - ry, size); distancefactor = (dx2 + (y - ry) * (y - ry)) / size;
if(distancefactor > 1.0f)
continue;
if(distancefactor >= 1.0f) distancefactor = strength * (1.0f - distancefactor);
if (distancefactor >= 1.0f)
map[x, y] = rz; map[x, y] = rz;
else else
map[x, y] += (rz - (float)map[x, y]) * distancefactor; map[x, y] += (rz - (float)map[x, y]) * distancefactor;

View File

@ -38,18 +38,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
float size, float strength, int startX, int endX, int startY, int endY) float size, float strength, int startX, int endX, int startY, int endY)
{ {
size = 0.5f * (float)Math.PI / size; 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]) if (!mask[x, y])
continue; continue;
// Calculate a cos-sphere and add it to the heighmap // 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); double distancefactor = Math.Cos(r * size);
if (distancefactor > 0.0) if (distancefactor > 0.0)
{ {

View File

@ -39,21 +39,27 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
float size, float strength, int startX, int endX, int startY, int endY) float size, float strength, int startX, int endX, int startY, int endY)
{ {
int x, y; int x, y;
float distancefactor;
float dx2;
size *= size;
for (x = startX; x <= endX; x++) for (x = startX; x <= endX; x++)
{ {
dx2 = (x - rx) * (x - rx);
for (y = startY; y <= endY; y++) for (y = startY; y <= endY; y++)
{ {
if (!mask[x, y]) if (!mask[x, y])
continue; continue;
// Calculate a sphere and add it to the heighmap // 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); double noise = TerrainUtil.PerlinNoise2D(x / (double) map.Width, y / (double) map.Height, 8, 1.0);
map[x, y] += noise * distancefactor;
if (distancefactor > 0.0)
map[x, y] += noise * distancefactor * strength;
} }
} }
} }

View File

@ -39,19 +39,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
float size, float strength, int startX, int endX, int startY, int endY) float size, float strength, int startX, int endX, int startY, int endY)
{ {
size = 0.5f *(float)Math.PI / size; size = 0.5f *(float)Math.PI / size;
strength *= 2;
int x, y; float dx2;
for (int x = startX; x <= endX; ++x)
for (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]) if (!mask[x, y])
continue; continue;
// Calculate a cos-sphere and add it to the heighmap // 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); double distancefactor = Math.Cos(r * size);
if (distancefactor > 0.0) if (distancefactor > 0.0)
map[x, y] += distancefactor * strength; map[x, y] += distancefactor * strength;

View File

@ -50,24 +50,28 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
if (strength > 1.0f) if (strength > 1.0f)
strength = 1.0f; strength = 1.0f;
int x,y; int x, y;
float distancefactor;
float dx2;
for (x = startX; x <= endX; x++) for (x = startX; x <= endX; x++)
{ {
dx2 = (x - rx) * (x - rx);
for (y = startY; y <= endY; y++) for (y = startY; y <= endY; y++)
{ {
if (!mask[x, y]) if (!mask[x, y])
continue; continue;
// Calculate a sphere and add it to the heighmap // Calculate a sphere and add it to the heighmap
double distancefactor = TerrainUtil.SphericalFactor(x - rx, y - ry, size); distancefactor = (dx2 + (y - ry) * (y - ry)) / size;
if (distancefactor > 0.0) if (distancefactor > 1.0f)
{ continue;
distancefactor *= strength;
distancefactor = strength * (1.0f - distancefactor);
map[x, y] = (map[x, y] * (1.0 - distancefactor)) + (m_revertmap[x, y] * distancefactor); map[x, y] = (map[x, y] * (1.0 - distancefactor)) + (m_revertmap[x, y] * distancefactor);
} }
} }
} }
}
#endregion #endregion
} }

View File

@ -35,60 +35,66 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
#region ITerrainPaintableEffect Members #region ITerrainPaintableEffect Members
public void PaintEffect(ITerrainChannel map, bool[,] mask, float rx, float ry, float rz, 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; float distancefactor;
double[,] tweak = new double[map.Width, map.Height]; 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) size *= size;
strengh = 1.0f;
if (strength > 1.0f)
strength = 1.0f;
// compute delta map // 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]) if (!mask[x, y])
continue; continue;
double z = TerrainUtil.SphericalFactor(x - rx, y - ry, size); distancefactor = (dx2 + (y - ry) * (y - ry)) / size;
if (distancefactor <= 1.0f)
if (z > 0) // add in non-zero amount
{ {
distancefactor = strength * (1.0f - distancefactor);
double average = 0.0; double average = 0.0;
int avgsteps = 0; int avgsteps = 0;
double n; for (int n = x - ssize; n <= x + ssize; ++n)
for (n =- size; n < size; n += step)
{ {
double l; if(n > 0 && n < map.Width)
for (l = -size; l < size; l += step) {
for (int l = y - ssize; l <= y + ssize; ++l)
{
if (l > 0 && l < map.Height)
{ {
avgsteps++; avgsteps++;
average += TerrainUtil.GetBilinearInterpolate(x + n, y + l, map); average += map[n, l];
} }
} }
tweak[x, y] = average / avgsteps; }
}
average /= avgsteps;
tweak[i, j] = distancefactor * (map[x, y] - average);
} }
} }
} }
// blend in map // 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]) double tz = tweak[i, j];
continue; if(tz != 0.0)
float distancefactor = TerrainUtil.SphericalFactor(x - rx, y - ry, size);
if (distancefactor > 0) // add in non-zero amount
{ {
double a = (map[x, y] - tweak[x, y]) * distancefactor; double newz = map[x, y] - tz;
double newz = map[x, y] - (a * strengh);
if (newz > 0.0) if (newz > 0.0)
map[x, y] = newz; map[x, y] = newz;
} }

View File

@ -516,12 +516,35 @@ namespace OpenSim.Region.CoreModules.World.Terrain
/// <param name="agentId">UUID of script-owner</param> /// <param name="agentId">UUID of script-owner</param>
public void ModifyTerrain(UUID user, Vector3 pos, byte size, byte action) public void ModifyTerrain(UUID user, Vector3 pos, byte size, byte action)
{ {
float duration = 0.25f; float duration;
float brushSize; float brushSize;
if(action == (byte)StandardTerrainEffects.Lower || action == (byte)StandardTerrainEffects.Raise) if (size > 2)
brushSize = (int)(Math.Pow(2, size) + 0.5); {
size = 3;
brushSize = 4.0f;
}
else 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); 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; return ret;
} }
private double NextModifyTerrainTime = double.MinValue;
private void client_OnModifyTerrain(UUID user, float height, float seconds, float brushSize, byte action, private void client_OnModifyTerrain(UUID user, float height, float seconds, float brushSize, byte action,
float north, float west, float south, float east, int parcelLocalID) 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); //m_log.DebugFormat("brushs {0} seconds {1} height {2}, parcel {3}", brushSize, seconds, height, parcelLocalID);
bool god = m_scene.Permissions.IsGod(user); bool god = m_scene.Permissions.IsGod(user);
bool allowed = false; bool allowed = false;
@ -1454,6 +1485,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
m_log.Debug("Unknown terrain flood type " + action); m_log.Debug("Unknown terrain flood type " + action);
} }
} }
NextModifyTerrainTime = Util.GetTimeStamp() + 0.02; // 20ms cooldown
} }
private void client_OnBakeTerrain(IClientAPI remoteClient) private void client_OnBakeTerrain(IClientAPI remoteClient)