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,
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
}

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)
{
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 = 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;
else
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)
{
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)
{

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)
{
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;
}
}
}

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)
{
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;

View File

@ -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);
}
}
}

View File

@ -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;
}

View File

@ -516,12 +516,35 @@ namespace OpenSim.Region.CoreModules.World.Terrain
/// <param name="agentId">UUID of script-owner</param>
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)