From cd88a4914dc31779a13d673aaaa6a1327ebeb351 Mon Sep 17 00:00:00 2001 From: Adam Frisby Date: Wed, 25 Jul 2007 10:08:16 +0000 Subject: * Assorted terrain fixes --- .../Region/Terrain.BasicTerrain/TerrainEngine.cs | 10 ++- .../libTerrainBSD/Channel/Common.cs | 16 +++++ .../libTerrainBSD/Channel/File.cs | 5 +- .../libTerrainBSD/Channel/Grid.cs | 83 +++++++++++++++++++++- .../Channel/Manipulators/AerobicErosion.cs | 37 ++++++++-- .../Channel/Manipulators/NavierStokes.cs | 39 ++++++++-- 6 files changed, 176 insertions(+), 14 deletions(-) diff --git a/OpenSim/Region/Terrain.BasicTerrain/TerrainEngine.cs b/OpenSim/Region/Terrain.BasicTerrain/TerrainEngine.cs index a609623..f52d25a 100644 --- a/OpenSim/Region/Terrain.BasicTerrain/TerrainEngine.cs +++ b/OpenSim/Region/Terrain.BasicTerrain/TerrainEngine.cs @@ -277,7 +277,7 @@ namespace OpenSim.Region.Terrain resultText += "terrain save grdmap - creates a PNG snapshot of the region using a named gradient map\n"; resultText += "terrain rescale - rescales a terrain to be between and meters high\n"; resultText += "terrain fill - fills a terrain at the specified height\n"; - resultText += "terrain erode aerobic \n"; + resultText += "terrain erode aerobic \n"; resultText += "terrain erode thermal \n"; resultText += "terrain erode hydraulic \n"; resultText += "terrain multiply - multiplies a terrain by \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; } diff --git a/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Common.cs b/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Common.cs index e6e5a9a..1750418 100644 --- a/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Common.cs +++ b/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Common.cs @@ -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; + } } } diff --git a/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/File.cs b/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/File.cs index b147004..c0173c0 100644 --- a/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/File.cs +++ b/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/File.cs @@ -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); } diff --git a/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Grid.cs b/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Grid.cs index a39db50..e6b18f4 100644 --- a/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Grid.cs +++ b/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Grid.cs @@ -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; diff --git a/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/AerobicErosion.cs b/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/AerobicErosion.cs index f4dfe1d..fecb748 100644 --- a/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/AerobicErosion.cs +++ b/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/AerobicErosion.cs @@ -76,13 +76,19 @@ namespace libTerrain /// Drop sediment at the lowest point? 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"); } } } \ No newline at end of file diff --git a/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/NavierStokes.cs b/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/NavierStokes.cs index a035098..8a111ed 100644 --- a/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/NavierStokes.cs +++ b/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/NavierStokes.cs @@ -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); + } } } \ No newline at end of file -- cgit v1.1