* Assorted terrain fixes

afrisby
Adam Frisby 2007-07-25 10:08:16 +00:00
parent aa704172d1
commit cd88a4914d
6 changed files with 176 additions and 14 deletions

View File

@ -277,7 +277,7 @@ namespace OpenSim.Region.Terrain
resultText += "terrain save grdmap <filename> <gradient map> - creates a PNG snapshot of the region using a named gradient map\n";
resultText += "terrain rescale <min> <max> - rescales a terrain to be between <min> and <max> meters high\n";
resultText += "terrain fill <val> - fills a terrain at the specified height\n";
resultText += "terrain erode aerobic <windspeed> <pickupmin> <dropmin> <carry> <rounds> <lowest>\n";
resultText += "terrain erode aerobic <windspeed> <pickupmin> <dropmin> <carry> <rounds> <lowest t/f> <fluid dynamics t/f>\n";
resultText += "terrain erode thermal <talus> <rounds> <carry>\n";
resultText += "terrain erode hydraulic <rain> <evaporation> <solubility> <frequency> <rounds>\n";
resultText += "terrain multiply <val> - multiplies a terrain by <val>\n";
@ -426,11 +426,14 @@ namespace OpenSim.Region.Terrain
private bool ConsoleErosion(string[] args, ref string resultText)
{
double min = heightmap.FindMin();
double max = heightmap.FindMax();
switch (args[1].ToLower())
{
case "aerobic":
// WindSpeed, PickupMinimum,DropMinimum,Carry,Rounds,Lowest
heightmap.AerobicErosion(Convert.ToDouble(args[2]), Convert.ToDouble(args[3]), Convert.ToDouble(args[4]), Convert.ToDouble(args[5]), Convert.ToInt32(args[6]), Convert.ToBoolean(args[7]), true);
heightmap.AerobicErosion(Convert.ToDouble(args[2]), Convert.ToDouble(args[3]), Convert.ToDouble(args[4]), Convert.ToDouble(args[5]), Convert.ToInt32(args[6]), Convert.ToBoolean(args[7]), Convert.ToBoolean(args[8]));
break;
case "thermal":
heightmap.ThermalWeathering(Convert.ToDouble(args[2]), Convert.ToInt32(args[3]), Convert.ToDouble(args[4]));
@ -444,6 +447,9 @@ namespace OpenSim.Region.Terrain
resultText = "Unknown erosion type";
return false;
}
heightmap.Normalise(min, max);
tainted++;
return true;
}

View File

@ -257,5 +257,21 @@ namespace libTerrain
{
return Sum() / (w * h);
}
public bool ContainsNaN()
{
int x, y;
for (x = 0; x < w; x++)
{
for (y = 0; y < h; y++)
{
double elm = map[x, y];
if (Double.IsNaN(elm))
return true;
}
}
return false;
}
}
}

View File

@ -57,13 +57,16 @@ namespace libTerrain
public void SaveImage(string filename)
{
Channel outmap = this.Copy();
outmap.Normalise();
Bitmap bit = new Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
int x, y;
for (x = 0; x < w; x++)
{
for (y = 0; y < h; y++)
{
int val = Math.Min(255, (int)(map[x,y] * 255));
int val = Math.Min(255, (int)(outmap.map[x,y] * 255));
Color col = Color.FromArgb(val,val,val);
bit.SetPixel(x, y, col);
}

View File

@ -43,13 +43,20 @@ namespace libTerrain
int x, y;
for (x = 0; x < w; x++)
if (max != min)
{
for (y = 0; y < h; y++)
for (x = 0; x < w; x++)
{
map[x, y] = (map[x, y] - min) * (1.0 / (max - min));
for (y = 0; y < h; y++)
{
map[x, y] = (map[x, y] - min) * (1.0 / (max - min));
}
}
}
else
{
this.Fill(0.5);
}
return this;
}
@ -244,6 +251,76 @@ namespace libTerrain
map = manipulated;
}
public void Distort(Channel mask, double str)
{
// Simple pertubation filter
double[,] manipulated = new double[w, h];
double amount;
int x, y;
for (x = 0; x < w; x++)
{
for (y = 0; y < h; y++)
{
amount = mask.map[x, y];
double offset_x = (double)x + (amount * str) - (0.5 * str);
double offset_y = (double)y + (amount * str) - (0.5 * str);
if (offset_x > w)
offset_x = w - 1;
if (offset_y > h)
offset_y = h - 1;
if (offset_y < 0)
offset_y = 0;
if (offset_x < 0)
offset_x = 0;
double p = GetBilinearInterpolate(offset_x, offset_y);
manipulated[x, y] = p;
SetDiff(x, y);
}
}
map = manipulated;
}
public void Distort(Channel mask, Channel mask2, double str)
{
// Simple pertubation filter
double[,] manipulated = new double[w, h];
double amountX;
double amountY;
int x, y;
for (x = 0; x < w; x++)
{
for (y = 0; y < h; y++)
{
amountX = mask.map[x, y];
amountY = mask2.map[x, y];
double offset_x = (double)x + (amountX * str) - (0.5 * str);
double offset_y = (double)y + (amountY * str) - (0.5 * str);
if (offset_x > w)
offset_x = w - 1;
if (offset_y > h)
offset_y = h - 1;
if (offset_y < 0)
offset_y = 0;
if (offset_x < 0)
offset_x = 0;
double p = GetBilinearInterpolate(offset_x, offset_y);
manipulated[x, y] = p;
SetDiff(x, y);
}
}
map = manipulated;
}
public Channel Blend(Channel other, double amount)
{
int x, y;

View File

@ -76,13 +76,19 @@ namespace libTerrain
/// <param name="lowest">Drop sediment at the lowest point?</param>
public void AerobicErosion(double windspeed, double pickupTalusMinimum, double dropTalusMinimum, double carry, int rounds, bool lowest, bool usingFluidDynamics)
{
bool debugImages = true;
Channel wind = new Channel(w, h) ;
Channel sediment = new Channel(w, h);
int x, y, i, j;
this.Normalise();
wind = this.Copy();
wind.Normalise(); // Cheap wind calculations
wind *= windspeed;
wind.Noise();
if (debugImages)
wind.SaveImage("testimg/wind_start.png");
if (usingFluidDynamics)
{
@ -90,9 +96,12 @@ namespace libTerrain
}
else
{
wind.Pertubation(30); // Can do better later
wind.Pertubation(30);
}
if (debugImages)
wind.SaveImage("testimg/wind_begin.png");
for (i = 0; i < rounds; i++)
{
// Convert some rocks to sand
@ -127,7 +136,14 @@ namespace libTerrain
if (usingFluidDynamics)
{
sediment.navierStokes(7, 0.1, 0.0, 0.1);
wind.navierStokes(10, 0.1, 0.0, 0.0);
Channel noiseChan = new Channel(w, h);
noiseChan.Noise();
wind.Blend(noiseChan, 0.01);
wind.navierStokes(10, 0.1, 0.01, 0.01);
sediment.Distort(wind, windspeed);
}
else
{
@ -137,6 +153,9 @@ namespace libTerrain
sediment.seed++;
}
if (debugImages)
wind.SaveImage("testimg/wind_" + i.ToString() + ".png");
// Convert some sand to rock
for (x = 1; x < w - 1; x++)
{
@ -174,11 +193,21 @@ namespace libTerrain
}
}
if (debugImages)
sediment.SaveImage("testimg/sediment_" + i.ToString() + ".png");
wind.Normalise();
wind *= windspeed;
this.Normalise();
}
Channel myself = this;
myself += sediment;
myself.Normalise();
if (debugImages)
this.SaveImage("testimg/output.png");
}
}
}

View File

@ -211,11 +211,11 @@ namespace libTerrain
int i;
int j;
for (i = 0; i <= N; i++)
for (i = 1; i <= N; i++)
{
for (j = 0; j <= N; j++)
for (j = 1; j <= N; j++)
{
doubles[i, j] = dens[nsIX(i, j, N)];
doubles[i - 1, j - 1] = dens[nsIX(i, j, N)];
}
}
}
@ -229,7 +229,7 @@ namespace libTerrain
{
for (j = 1; j <= N; j++)
{
dens[nsIX(i, j, N)] = doubles[i, j];
dens[nsIX(i, j, N)] = doubles[i - 1, j - 1];
}
}
}
@ -272,5 +272,36 @@ namespace libTerrain
{
nsSimulate(this.h, rounds, dt, diff, visc);
}
public void navierStokes(int rounds, double dt, double diff, double visc, ref double[,] uret, ref double[,] vret)
{
int N = this.h;
int size = (N * 2) * (N * 2);
double[] u = new double[size]; // Force, X axis
double[] v = new double[size]; // Force, Y axis
double[] u_prev = new double[size];
double[] v_prev = new double[size];
double[] dens = new double[size];
double[] dens_prev = new double[size];
nsDoublesToBuffer(this.map, N, ref dens);
nsDoublesToBuffer(this.map, N, ref dens_prev);
for (int i = 0; i < rounds; i++)
{
u_prev = u;
v_prev = v;
dens_prev = dens;
nsVelStep(N, ref u, ref v, ref u_prev, ref v_prev, visc, dt);
nsDensStep(N, ref dens, ref dens_prev, ref u, ref v, diff, dt);
}
nsBufferToDoubles(ref u, N, ref uret);
nsBufferToDoubles(ref v, N, ref vret);
nsBufferToDoubles(ref dens, N, ref this.map);
}
}
}