more changes on terrain edit. Silent ignore comand if busy (large area smooth can take ages), brush changes, etc
parent
01832b3e3c
commit
9eb5fd4330
|
@ -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
|
|
||||||
|
|
||||||
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
|
||||||
}
|
}
|
|
@ -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 = (dx2 + (y - ry) * (y - ry)) / size;
|
||||||
|
if(distancefactor > 1.0f)
|
||||||
|
continue;
|
||||||
|
|
||||||
distancefactor = strength * TerrainUtil.SphericalFactor(x - rx, y - ry, size);
|
distancefactor = strength * (1.0f - distancefactor);
|
||||||
|
if (distancefactor >= 1.0f)
|
||||||
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;
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -50,21 +50,25 @@ 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;
|
|
||||||
map[x, y] = (map[x, y] * (1.0 - distancefactor)) + (m_revertmap[x, y] * distancefactor);
|
distancefactor = strength * (1.0f - distancefactor);
|
||||||
}
|
map[x, y] = (map[x, y] * (1.0 - distancefactor)) + (m_revertmap[x, y] * distancefactor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
|
||||||
{
|
{
|
||||||
avgsteps++;
|
for (int l = y - ssize; l <= y + ssize; ++l)
|
||||||
average += TerrainUtil.GetBilinearInterpolate(x + n, y + l, map);
|
{
|
||||||
|
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
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue