From 2b42ea0a429c722bd7c5c67d3815c2ddc8399e78 Mon Sep 17 00:00:00 2001 From: MW Date: Wed, 25 Jul 2007 18:19:38 +0000 Subject: Start of the OpenSim library , for now only contains a few textures. --- .../Channel/Manipulators/AerobicErosion.cs | 424 +++++++------- .../Channel/Manipulators/HydraulicErosion.cs | 290 +++++----- .../Channel/Manipulators/NavierStokes.cs | 612 ++++++++++----------- .../Channel/Manipulators/ThermalWeathering.cs | 224 ++++---- 4 files changed, 775 insertions(+), 775 deletions(-) (limited to 'OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators') diff --git a/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/AerobicErosion.cs b/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/AerobicErosion.cs index 589d360..5d2b4d4 100644 --- a/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/AerobicErosion.cs +++ b/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/AerobicErosion.cs @@ -1,213 +1,213 @@ -/* -* Copyright (c) Contributors, http://www.openmetaverse.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -using System; -using System.Collections.Generic; -using System.Text; - -namespace libTerrain -{ - partial class Channel - { - // Ideas for Aerobic erosion - // - // Unlike thermal (gravity) and hydraulic (water suspension) - // aerobic erosion should displace mass by moving sediment - // in "hops". The length of the hop being dictated by the - // presence of sharp cliffs and wind speed. - - // The ability to pickup sediment is defined by the total - // surface area, such that: - // 0 0 0 - // 0 1 0 - // 0 0 0 - // Would be the best possible value for sediment to be - // picked up (total difference = 8) and flatter land - // will erode less quickly. - - // Suspended particles assist the erosion process by hitting - // the surface and chiselling additional particles off faster - // than alone. - - // Particles are deposited when one of two conditions is met - // First: - // When particles hit a wall - such that the - // wind direction points at a difference >= the - // deposition mininum talus. - // Second: - // When wind speed is lowered to below the minimum - // required for transit. An idea for this is to - // use the navier-stokes algorithms for simulating - // pressure across the terrain. - - /// - /// An experimental erosion algorithm developed by Adam. Moves sediment by factoring the surface area of each height point. - /// - /// 0..1 The speed of the wind - /// The minimum angle at which rock is eroded 0..1 (recommended: <= 0.30) - /// The minimum angle at which rock is dropped 0..1 (recommended: >= 0.00) - /// The percentage of rock which can be picked up to pickup 0..1 - /// The number of erosion rounds (recommended: 25+) - /// 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 = false; - - Channel wind = new Channel(w, h) ; - Channel sediment = new Channel(w, h); - int x, y, i, j; - - this.Normalise(); - - wind = this.Copy(); - wind.Noise(); - - if (debugImages) - wind.SaveImage("testimg/wind_start.png"); - - if (usingFluidDynamics) - { - wind.navierStokes(20, 0.1, 0.0, 0.0); - } - else - { - wind.Pertubation(30); - } - - if (debugImages) - wind.SaveImage("testimg/wind_begin.png"); - - for (i = 0; i < rounds; i++) - { - // Convert some rocks to sand - for (x = 1; x < w - 1; x++) - { - for (y = 1; y < h - 1; y++) - { - double me = Get(x, y); - double surfacearea = 0.3; // Everything will erode even if it's flat. Just slower. - - for (j = 0; j < 9; j++) - { - int[] coords = Neighbours(NeighbourSystem.Moore, j); - double target = Get(x + coords[0], y + coords[1]); - - surfacearea += Math.Abs(target - me); - } - - double amount = surfacearea * wind.map[x, y] * carry; - - if (amount < 0) - amount = 0; - - if (surfacearea > pickupTalusMinimum) - { - Set(x, y, map[x, y] - amount); - sediment.map[x, y] += amount; - } - } - } - - if (usingFluidDynamics) - { - sediment.navierStokes(7, 0.1, 0.0, 0.1); - - 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 - { - wind.Pertubation(15); // Can do better later - wind.seed++; - sediment.Pertubation(10); // Sediment is blown around a bit - sediment.seed++; - } - - if (debugImages) - wind.SaveImage("testimg/wind_" + i.ToString() + ".png"); - - // Convert some sand to rock - for (x = 1; x < w - 1; x++) - { - for (y = 1; y < h - 1; y++) - { - double me = Get(x, y); - double surfacearea = 0.01; // Flat land does not get deposition - double min = double.MaxValue; - int[] minside = new int[2]; - - for (j = 0; j < 9; j++) - { - int[] coords = Neighbours(NeighbourSystem.Moore, j); - double target = Get(x + coords[0], y + coords[1]); - - surfacearea += Math.Abs(target - me); - - if (target < min && lowest) - { - minside = (int[])coords.Clone(); - min = target; - } - } - - double amount = surfacearea * (1.0 - wind.map[x, y]) * carry; - - if (amount < 0) - amount = 0; - - if (surfacearea > dropTalusMinimum) - { - Set(x + minside[0], y + minside[1], map[x + minside[0], y + minside[1]] + amount); - sediment.map[x, y] -= amount; - } - } - } - - 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"); - } - } +/* +* Copyright (c) Contributors, http://www.openmetaverse.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace libTerrain +{ + partial class Channel + { + // Ideas for Aerobic erosion + // + // Unlike thermal (gravity) and hydraulic (water suspension) + // aerobic erosion should displace mass by moving sediment + // in "hops". The length of the hop being dictated by the + // presence of sharp cliffs and wind speed. + + // The ability to pickup sediment is defined by the total + // surface area, such that: + // 0 0 0 + // 0 1 0 + // 0 0 0 + // Would be the best possible value for sediment to be + // picked up (total difference = 8) and flatter land + // will erode less quickly. + + // Suspended particles assist the erosion process by hitting + // the surface and chiselling additional particles off faster + // than alone. + + // Particles are deposited when one of two conditions is met + // First: + // When particles hit a wall - such that the + // wind direction points at a difference >= the + // deposition mininum talus. + // Second: + // When wind speed is lowered to below the minimum + // required for transit. An idea for this is to + // use the navier-stokes algorithms for simulating + // pressure across the terrain. + + /// + /// An experimental erosion algorithm developed by Adam. Moves sediment by factoring the surface area of each height point. + /// + /// 0..1 The speed of the wind + /// The minimum angle at which rock is eroded 0..1 (recommended: <= 0.30) + /// The minimum angle at which rock is dropped 0..1 (recommended: >= 0.00) + /// The percentage of rock which can be picked up to pickup 0..1 + /// The number of erosion rounds (recommended: 25+) + /// 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 = false; + + Channel wind = new Channel(w, h) ; + Channel sediment = new Channel(w, h); + int x, y, i, j; + + this.Normalise(); + + wind = this.Copy(); + wind.Noise(); + + if (debugImages) + wind.SaveImage("testimg/wind_start.png"); + + if (usingFluidDynamics) + { + wind.navierStokes(20, 0.1, 0.0, 0.0); + } + else + { + wind.Pertubation(30); + } + + if (debugImages) + wind.SaveImage("testimg/wind_begin.png"); + + for (i = 0; i < rounds; i++) + { + // Convert some rocks to sand + for (x = 1; x < w - 1; x++) + { + for (y = 1; y < h - 1; y++) + { + double me = Get(x, y); + double surfacearea = 0.3; // Everything will erode even if it's flat. Just slower. + + for (j = 0; j < 9; j++) + { + int[] coords = Neighbours(NeighbourSystem.Moore, j); + double target = Get(x + coords[0], y + coords[1]); + + surfacearea += Math.Abs(target - me); + } + + double amount = surfacearea * wind.map[x, y] * carry; + + if (amount < 0) + amount = 0; + + if (surfacearea > pickupTalusMinimum) + { + Set(x, y, map[x, y] - amount); + sediment.map[x, y] += amount; + } + } + } + + if (usingFluidDynamics) + { + sediment.navierStokes(7, 0.1, 0.0, 0.1); + + 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 + { + wind.Pertubation(15); // Can do better later + wind.seed++; + sediment.Pertubation(10); // Sediment is blown around a bit + sediment.seed++; + } + + if (debugImages) + wind.SaveImage("testimg/wind_" + i.ToString() + ".png"); + + // Convert some sand to rock + for (x = 1; x < w - 1; x++) + { + for (y = 1; y < h - 1; y++) + { + double me = Get(x, y); + double surfacearea = 0.01; // Flat land does not get deposition + double min = double.MaxValue; + int[] minside = new int[2]; + + for (j = 0; j < 9; j++) + { + int[] coords = Neighbours(NeighbourSystem.Moore, j); + double target = Get(x + coords[0], y + coords[1]); + + surfacearea += Math.Abs(target - me); + + if (target < min && lowest) + { + minside = (int[])coords.Clone(); + min = target; + } + } + + double amount = surfacearea * (1.0 - wind.map[x, y]) * carry; + + if (amount < 0) + amount = 0; + + if (surfacearea > dropTalusMinimum) + { + Set(x + minside[0], y + minside[1], map[x + minside[0], y + minside[1]] + amount); + sediment.map[x, y] -= amount; + } + } + } + + 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/HydraulicErosion.cs b/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/HydraulicErosion.cs index 36da77c..fb9e21e 100644 --- a/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/HydraulicErosion.cs +++ b/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/HydraulicErosion.cs @@ -1,146 +1,146 @@ -/* -* Copyright (c) Contributors, http://www.openmetaverse.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -using System; -using System.Collections.Generic; -using System.Text; - -namespace libTerrain -{ - partial class Channel - { - public void HydraulicErosion(Channel rain, double evaporation, double solubility, int frequency, int rounds) - { - SetDiff(); - - Channel water = new Channel(w, h); - Channel sediment = new Channel(w, h); - Channel terrain = this; - Channel waterFlow = new Channel(w, h); - - NeighbourSystem type = NeighbourSystem.Moore; - int NEIGHBOUR_ME = 4; - - int NEIGHBOUR_MAX = type == NeighbourSystem.Moore ? 9 : 5; - - for (int i = 0; i < rounds; i++) - { - water += rain; - - sediment = terrain * water; - terrain -= sediment; - - for (int x = 1; x < w - 1; x++) - { - for (int y = 1; y < h - 1; y++) - { - double[] heights = new double[NEIGHBOUR_MAX]; - double[] diffs = new double[NEIGHBOUR_MAX]; - - double heightCenter = map[x, y]; - - for (int j = 0; j < NEIGHBOUR_MAX; j++) - { - if (j != NEIGHBOUR_ME) - { - int[] coords = Neighbours(type, j); - coords[0] += x; - coords[1] += y; - - heights[j] = map[coords[0], coords[1]] + water.map[coords[0], coords[1]] + sediment.map[coords[0], coords[1]]; - diffs[j] = heightCenter - heights[j]; - } - } - - double totalHeight = 0; - double totalHeightDiff = 0; - int totalCellsCounted = 1; - - for (int j = 0; j < NEIGHBOUR_MAX; j++) - { - if (j != NEIGHBOUR_ME) - { - if (diffs[j] > 0) - { - totalHeight += heights[j]; - totalHeightDiff += diffs[j]; - totalCellsCounted++; - } - } - } - - if (totalCellsCounted == 1) - continue; - - double averageHeight = totalHeight / totalCellsCounted; - double waterAmount = Math.Min(water.map[x, y], heightCenter - averageHeight); - - // TODO: Check this. - waterFlow.map[x, y] += waterFlow.map[x, y] - waterAmount; - - double totalInverseDiff = waterAmount / totalHeightDiff; - - for (int j = 0; j < NEIGHBOUR_MAX; j++) - { - if (j != NEIGHBOUR_ME) - { - int[] coords = Neighbours(type, j); - coords[0] += x; - coords[1] += y; - - if (diffs[j] > 0) - { - waterFlow.SetWrap(coords[0], coords[1], waterFlow.map[coords[0], coords[1]] + diffs[j] * totalInverseDiff); - } - } - } - } - } - - water += waterFlow; - waterFlow.Fill(0); - - water *= evaporation; - - for (int x = 0; x < w; x++) - { - for (int y = 0; y < h; y++) - { - double deposition = sediment.map[x, y] - water.map[x, y] * solubility; - if (deposition > 0) - { - sediment.map[x, y] -= deposition; - terrain.map[x, y] += deposition; - } - } - } - - } - } - } +/* +* Copyright (c) Contributors, http://www.openmetaverse.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace libTerrain +{ + partial class Channel + { + public void HydraulicErosion(Channel rain, double evaporation, double solubility, int frequency, int rounds) + { + SetDiff(); + + Channel water = new Channel(w, h); + Channel sediment = new Channel(w, h); + Channel terrain = this; + Channel waterFlow = new Channel(w, h); + + NeighbourSystem type = NeighbourSystem.Moore; + int NEIGHBOUR_ME = 4; + + int NEIGHBOUR_MAX = type == NeighbourSystem.Moore ? 9 : 5; + + for (int i = 0; i < rounds; i++) + { + water += rain; + + sediment = terrain * water; + terrain -= sediment; + + for (int x = 1; x < w - 1; x++) + { + for (int y = 1; y < h - 1; y++) + { + double[] heights = new double[NEIGHBOUR_MAX]; + double[] diffs = new double[NEIGHBOUR_MAX]; + + double heightCenter = map[x, y]; + + for (int j = 0; j < NEIGHBOUR_MAX; j++) + { + if (j != NEIGHBOUR_ME) + { + int[] coords = Neighbours(type, j); + coords[0] += x; + coords[1] += y; + + heights[j] = map[coords[0], coords[1]] + water.map[coords[0], coords[1]] + sediment.map[coords[0], coords[1]]; + diffs[j] = heightCenter - heights[j]; + } + } + + double totalHeight = 0; + double totalHeightDiff = 0; + int totalCellsCounted = 1; + + for (int j = 0; j < NEIGHBOUR_MAX; j++) + { + if (j != NEIGHBOUR_ME) + { + if (diffs[j] > 0) + { + totalHeight += heights[j]; + totalHeightDiff += diffs[j]; + totalCellsCounted++; + } + } + } + + if (totalCellsCounted == 1) + continue; + + double averageHeight = totalHeight / totalCellsCounted; + double waterAmount = Math.Min(water.map[x, y], heightCenter - averageHeight); + + // TODO: Check this. + waterFlow.map[x, y] += waterFlow.map[x, y] - waterAmount; + + double totalInverseDiff = waterAmount / totalHeightDiff; + + for (int j = 0; j < NEIGHBOUR_MAX; j++) + { + if (j != NEIGHBOUR_ME) + { + int[] coords = Neighbours(type, j); + coords[0] += x; + coords[1] += y; + + if (diffs[j] > 0) + { + waterFlow.SetWrap(coords[0], coords[1], waterFlow.map[coords[0], coords[1]] + diffs[j] * totalInverseDiff); + } + } + } + } + } + + water += waterFlow; + waterFlow.Fill(0); + + water *= evaporation; + + for (int x = 0; x < w; x++) + { + for (int y = 0; y < h; y++) + { + double deposition = sediment.map[x, y] - water.map[x, y] * solubility; + if (deposition > 0) + { + sediment.map[x, y] -= deposition; + terrain.map[x, y] += deposition; + } + } + } + + } + } + } } \ 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 8a111ed..1cd213b 100644 --- a/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/NavierStokes.cs +++ b/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/NavierStokes.cs @@ -1,307 +1,307 @@ -/* -* Copyright (c) Contributors, http://www.openmetaverse.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -using System; -using System.Collections.Generic; -using System.Text; - -namespace libTerrain -{ - partial class Channel - { - // Navier Stokes Algorithms ported from - // "Real-Time Fluid Dynamics for Games" by Jos Stam. - // presented at GDC 2003. - - // Poorly ported from C++. (I gave up making it properly native somewhere after nsSetBnd) - - private static int nsIX(int i, int j, int N) - { - return ((i) + (N + 2) * (j)); - } - - private static void nsSwap(ref double x0, ref double x) - { - double tmp = x0; - x0 = x; - x = tmp; - } - - private static void nsSwap(ref double[] x0, ref double[] x) - { - double[] tmp = x0; - x0 = x; - x = tmp; - } - - private void nsAddSource(int N, ref double[] x, ref double[] s, double dt) - { - int i; - int size = (N + 2) * (N + 2); - for (i = 0; i < size; i++) - { - x[i] += dt * s[i]; - } - } - - private void nsSetBnd(int N, int b, ref double[] x) - { - int i; - for (i = 0; i <= N; i++) - { - x[nsIX(0, i, N)] = b == 1 ? -x[nsIX(1, i, N)] : x[nsIX(1, i, N)]; - x[nsIX(0, N + 1, N)] = b == 1 ? -x[nsIX(N, i, N)] : x[nsIX(N, i, N)]; - x[nsIX(i, 0, N)] = b == 2 ? -x[nsIX(i, 1, N)] : x[nsIX(i, 1, N)]; - x[nsIX(i, N + 1, N)] = b == 2 ? -x[nsIX(i, N, N)] : x[nsIX(i, N, N)]; - } - x[nsIX(0, 0, N)] = 0.5f * (x[nsIX(1, 0, N)] + x[nsIX(0, 1, N)]); - x[nsIX(0, N + 1, N)] = 0.5f * (x[nsIX(1, N + 1, N)] + x[nsIX(0, N, N)]); - x[nsIX(N + 1, 0, N)] = 0.5f * (x[nsIX(N, 0, N)] + x[nsIX(N + 1, 1, N)]); - x[nsIX(N + 1, N + 1, N)] = 0.5f * (x[nsIX(N, N + 1, N)] + x[nsIX(N + 1, N, N)]); - } - - private void nsLinSolve(int N, int b, ref double[] x, ref double[] x0, double a, double c) - { - int i, j; - for (i = 1; i <= N; i++) - { - for (j = 1; j <= N; j++) - { - x[nsIX(i, j, N)] = (x0[nsIX(i, j, N)] + a * - (x[nsIX(i - 1, j, N)] + - x[nsIX(i + 1, j, N)] + - x[nsIX(i, j - 1, N)] + x[nsIX(i, j + 1, N)]) - ) / c; - } - } - - nsSetBnd(N, b, ref x); - } - - private void nsDiffuse(int N, int b, ref double[] x, ref double[] x0, double diff, double dt) - { - double a = dt * diff * N * N; - nsLinSolve(N, b, ref x, ref x0, a, 1 + 4 * a); - } - - private void nsAdvect(int N, int b, ref double[] d, ref double[] d0, ref double[] u, ref double[] v, double dt) - { - int i, j, i0, j0, i1, j1; - double x, y, s0, t0, s1, t1, dt0; - - dt0 = dt * N; - - for (i = 1; i <= N; i++) - { - for (j = 1; j <= N; j++) - { - x = i - dt0 * u[nsIX(i, j, N)]; - y = j - dt0 * v[nsIX(i, j, N)]; - - if (x < 0.5) - x = 0.5; - if (x > N + 0.5) - x = N + 0.5; - i0 = (int)x; - i1 = i0 + 1; - - if (y < 0.5) - y = 0.5; - if (y > N + 0.5) - y = N + 0.5; - j0 = (int)y; - j1 = j0 + 1; - - s1 = x - i0; - s0 = 1 - s1; - t1 = y - j0; - t0 = 1 - t1; - - d[nsIX(i, j, N)] = s0 * (t0 * d0[nsIX(i0, j0, N)] + t1 * d0[nsIX(i0, j1, N)]) + - s1 * (t0 * d0[nsIX(i1, j0, N)] + t1 * d0[nsIX(i1, j1, N)]); - } - } - - nsSetBnd(N, b, ref d); - } - - public void nsProject(int N, ref double[] u, ref double[] v, ref double[] p, ref double[] div) - { - int i, j; - - for (i = 1; i <= N; i++) - { - for (j = 1; j <= N; j++) - { - div[nsIX(i, j, N)] = -0.5 * (u[nsIX(i + 1, j, N)] - u[nsIX(i - 1, j, N)] + v[nsIX(i, j + 1, N)] - v[nsIX(i, j - 1, N)]) / N; - p[nsIX(i, j, N)] = 0; - } - } - - nsSetBnd(N, 0, ref div); - nsSetBnd(N, 0, ref p); - - nsLinSolve(N, 0, ref p, ref div, 1, 4); - - for (i = 1; i <= N; i++) - { - for (j = 1; j <= N; j++) - { - u[nsIX(i, j, N)] -= 0.5 * N * (p[nsIX(i + 1, j, N)] - p[nsIX(i - 1, j, N)]); - v[nsIX(i, j, N)] -= 0.5 * N * (p[nsIX(i, j + 1, N)] - p[nsIX(i, j - 1, N)]); - } - } - - nsSetBnd(N, 1, ref u); - nsSetBnd(N, 2, ref v); - } - - private void nsDensStep(int N, ref double[] x, ref double[] x0, ref double[] u, ref double[] v, double diff, double dt) - { - nsAddSource(N, ref x, ref x0, dt); - nsSwap(ref x0, ref x); - nsDiffuse(N, 0, ref x, ref x0, diff, dt); - nsSwap(ref x0, ref x); - nsAdvect(N, 0, ref x, ref x0, ref u, ref v, dt); - } - - private void nsVelStep(int N, ref double[] u, ref double[] v, ref double[] u0, ref double[] v0, double visc, double dt) - { - nsAddSource(N, ref u, ref u0, dt); - nsAddSource(N, ref v, ref v0, dt); - nsSwap(ref u0, ref u); - nsDiffuse(N, 1, ref u, ref u0, visc, dt); - nsSwap(ref v0, ref v); - nsDiffuse(N, 2, ref v, ref v0, visc, dt); - nsProject(N, ref u, ref v, ref u0, ref v0); - nsSwap(ref u0, ref u); - nsSwap(ref v0, ref v); - nsAdvect(N, 1, ref u, ref u0, ref u0, ref v0, dt); - nsAdvect(N, 2, ref v, ref v0, ref u0, ref v0, dt); - nsProject(N, ref u, ref v, ref u0, ref v0); - } - - private void nsBufferToDoubles(ref double[] dens, int N, ref double[,] doubles) - { - int i; - int j; - - for (i = 1; i <= N; i++) - { - for (j = 1; j <= N; j++) - { - doubles[i - 1, j - 1] = dens[nsIX(i, j, N)]; - } - } - } - - private void nsDoublesToBuffer(double[,] doubles, int N, ref double[] dens) - { - int i; - int j; - - for (i = 1; i <= N; i++) - { - for (j = 1; j <= N; j++) - { - dens[nsIX(i, j, N)] = doubles[i - 1, j - 1]; - } - } - } - - private void nsSimulate(int N, int rounds, double dt, double diff, double visc) - { - 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 dens, N, ref this.map); - } - - /// - /// Performs computational fluid dynamics on a channel - /// - /// The number of steps to perform (Recommended: 20) - /// Delta Time - The time between steps (Recommended: 0.1) - /// Fluid diffusion rate (Recommended: 0.0) - /// Fluid viscosity (Recommended: 0.0) - public void navierStokes(int rounds, double dt, double diff, double visc) - { - 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); - } - } +/* +* Copyright (c) Contributors, http://www.openmetaverse.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace libTerrain +{ + partial class Channel + { + // Navier Stokes Algorithms ported from + // "Real-Time Fluid Dynamics for Games" by Jos Stam. + // presented at GDC 2003. + + // Poorly ported from C++. (I gave up making it properly native somewhere after nsSetBnd) + + private static int nsIX(int i, int j, int N) + { + return ((i) + (N + 2) * (j)); + } + + private static void nsSwap(ref double x0, ref double x) + { + double tmp = x0; + x0 = x; + x = tmp; + } + + private static void nsSwap(ref double[] x0, ref double[] x) + { + double[] tmp = x0; + x0 = x; + x = tmp; + } + + private void nsAddSource(int N, ref double[] x, ref double[] s, double dt) + { + int i; + int size = (N + 2) * (N + 2); + for (i = 0; i < size; i++) + { + x[i] += dt * s[i]; + } + } + + private void nsSetBnd(int N, int b, ref double[] x) + { + int i; + for (i = 0; i <= N; i++) + { + x[nsIX(0, i, N)] = b == 1 ? -x[nsIX(1, i, N)] : x[nsIX(1, i, N)]; + x[nsIX(0, N + 1, N)] = b == 1 ? -x[nsIX(N, i, N)] : x[nsIX(N, i, N)]; + x[nsIX(i, 0, N)] = b == 2 ? -x[nsIX(i, 1, N)] : x[nsIX(i, 1, N)]; + x[nsIX(i, N + 1, N)] = b == 2 ? -x[nsIX(i, N, N)] : x[nsIX(i, N, N)]; + } + x[nsIX(0, 0, N)] = 0.5f * (x[nsIX(1, 0, N)] + x[nsIX(0, 1, N)]); + x[nsIX(0, N + 1, N)] = 0.5f * (x[nsIX(1, N + 1, N)] + x[nsIX(0, N, N)]); + x[nsIX(N + 1, 0, N)] = 0.5f * (x[nsIX(N, 0, N)] + x[nsIX(N + 1, 1, N)]); + x[nsIX(N + 1, N + 1, N)] = 0.5f * (x[nsIX(N, N + 1, N)] + x[nsIX(N + 1, N, N)]); + } + + private void nsLinSolve(int N, int b, ref double[] x, ref double[] x0, double a, double c) + { + int i, j; + for (i = 1; i <= N; i++) + { + for (j = 1; j <= N; j++) + { + x[nsIX(i, j, N)] = (x0[nsIX(i, j, N)] + a * + (x[nsIX(i - 1, j, N)] + + x[nsIX(i + 1, j, N)] + + x[nsIX(i, j - 1, N)] + x[nsIX(i, j + 1, N)]) + ) / c; + } + } + + nsSetBnd(N, b, ref x); + } + + private void nsDiffuse(int N, int b, ref double[] x, ref double[] x0, double diff, double dt) + { + double a = dt * diff * N * N; + nsLinSolve(N, b, ref x, ref x0, a, 1 + 4 * a); + } + + private void nsAdvect(int N, int b, ref double[] d, ref double[] d0, ref double[] u, ref double[] v, double dt) + { + int i, j, i0, j0, i1, j1; + double x, y, s0, t0, s1, t1, dt0; + + dt0 = dt * N; + + for (i = 1; i <= N; i++) + { + for (j = 1; j <= N; j++) + { + x = i - dt0 * u[nsIX(i, j, N)]; + y = j - dt0 * v[nsIX(i, j, N)]; + + if (x < 0.5) + x = 0.5; + if (x > N + 0.5) + x = N + 0.5; + i0 = (int)x; + i1 = i0 + 1; + + if (y < 0.5) + y = 0.5; + if (y > N + 0.5) + y = N + 0.5; + j0 = (int)y; + j1 = j0 + 1; + + s1 = x - i0; + s0 = 1 - s1; + t1 = y - j0; + t0 = 1 - t1; + + d[nsIX(i, j, N)] = s0 * (t0 * d0[nsIX(i0, j0, N)] + t1 * d0[nsIX(i0, j1, N)]) + + s1 * (t0 * d0[nsIX(i1, j0, N)] + t1 * d0[nsIX(i1, j1, N)]); + } + } + + nsSetBnd(N, b, ref d); + } + + public void nsProject(int N, ref double[] u, ref double[] v, ref double[] p, ref double[] div) + { + int i, j; + + for (i = 1; i <= N; i++) + { + for (j = 1; j <= N; j++) + { + div[nsIX(i, j, N)] = -0.5 * (u[nsIX(i + 1, j, N)] - u[nsIX(i - 1, j, N)] + v[nsIX(i, j + 1, N)] - v[nsIX(i, j - 1, N)]) / N; + p[nsIX(i, j, N)] = 0; + } + } + + nsSetBnd(N, 0, ref div); + nsSetBnd(N, 0, ref p); + + nsLinSolve(N, 0, ref p, ref div, 1, 4); + + for (i = 1; i <= N; i++) + { + for (j = 1; j <= N; j++) + { + u[nsIX(i, j, N)] -= 0.5 * N * (p[nsIX(i + 1, j, N)] - p[nsIX(i - 1, j, N)]); + v[nsIX(i, j, N)] -= 0.5 * N * (p[nsIX(i, j + 1, N)] - p[nsIX(i, j - 1, N)]); + } + } + + nsSetBnd(N, 1, ref u); + nsSetBnd(N, 2, ref v); + } + + private void nsDensStep(int N, ref double[] x, ref double[] x0, ref double[] u, ref double[] v, double diff, double dt) + { + nsAddSource(N, ref x, ref x0, dt); + nsSwap(ref x0, ref x); + nsDiffuse(N, 0, ref x, ref x0, diff, dt); + nsSwap(ref x0, ref x); + nsAdvect(N, 0, ref x, ref x0, ref u, ref v, dt); + } + + private void nsVelStep(int N, ref double[] u, ref double[] v, ref double[] u0, ref double[] v0, double visc, double dt) + { + nsAddSource(N, ref u, ref u0, dt); + nsAddSource(N, ref v, ref v0, dt); + nsSwap(ref u0, ref u); + nsDiffuse(N, 1, ref u, ref u0, visc, dt); + nsSwap(ref v0, ref v); + nsDiffuse(N, 2, ref v, ref v0, visc, dt); + nsProject(N, ref u, ref v, ref u0, ref v0); + nsSwap(ref u0, ref u); + nsSwap(ref v0, ref v); + nsAdvect(N, 1, ref u, ref u0, ref u0, ref v0, dt); + nsAdvect(N, 2, ref v, ref v0, ref u0, ref v0, dt); + nsProject(N, ref u, ref v, ref u0, ref v0); + } + + private void nsBufferToDoubles(ref double[] dens, int N, ref double[,] doubles) + { + int i; + int j; + + for (i = 1; i <= N; i++) + { + for (j = 1; j <= N; j++) + { + doubles[i - 1, j - 1] = dens[nsIX(i, j, N)]; + } + } + } + + private void nsDoublesToBuffer(double[,] doubles, int N, ref double[] dens) + { + int i; + int j; + + for (i = 1; i <= N; i++) + { + for (j = 1; j <= N; j++) + { + dens[nsIX(i, j, N)] = doubles[i - 1, j - 1]; + } + } + } + + private void nsSimulate(int N, int rounds, double dt, double diff, double visc) + { + 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 dens, N, ref this.map); + } + + /// + /// Performs computational fluid dynamics on a channel + /// + /// The number of steps to perform (Recommended: 20) + /// Delta Time - The time between steps (Recommended: 0.1) + /// Fluid diffusion rate (Recommended: 0.0) + /// Fluid viscosity (Recommended: 0.0) + public void navierStokes(int rounds, double dt, double diff, double visc) + { + 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 diff --git a/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/ThermalWeathering.cs b/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/ThermalWeathering.cs index 07c7d66..695d501 100644 --- a/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/ThermalWeathering.cs +++ b/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/ThermalWeathering.cs @@ -1,112 +1,112 @@ -/* -* Copyright (c) Contributors, http://www.openmetaverse.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -using System; -using System.Collections.Generic; -using System.Text; - -namespace libTerrain -{ - partial class Channel - { - /// - /// A thermal weathering implementation based on Musgrave's original 1989 algorithm. This is Adam's custom implementation which may differ slightly from the original. - /// - /// The rock angle (represented as a dy/dx ratio) at which point it will be succeptible to breakage - /// The number of erosion rounds - /// The amount of rock to carry each round - public Channel ThermalWeathering(double talus, int rounds, double c) - { - SetDiff(); - - double[,] lastFrame; - double[,] thisFrame; - - lastFrame = (double[,])map.Clone(); - thisFrame = (double[,])map.Clone(); - - NeighbourSystem type = NeighbourSystem.Moore; // Using moore neighbourhood (twice as computationally expensive) - int NEIGHBOUR_ME = 4; // I am always 4 in both systems. - - int NEIGHBOUR_MAX = type == NeighbourSystem.Moore ? 9 : 5; - - int frames = rounds; // Number of thermal erosion iterations to run - int i, j; - int x, y; - - for (i = 0; i < frames; i++) - { - for (x = 0; x < w; x++) - { - for (y = 0; y < h; y++) - { - for (j = 0; j < NEIGHBOUR_MAX; j++) - { - if (j != NEIGHBOUR_ME) - { - int[] coords = Neighbours(type, j); - - coords[0] += x; - coords[1] += y; - - if (coords[0] > w - 1) - coords[0] = w - 1; - if (coords[1] > h - 1) - coords[1] = h - 1; - if (coords[0] < 0) - coords[0] = 0; - if (coords[1] < 0) - coords[1] = 0; - - double heightF = thisFrame[x, y]; - double target = thisFrame[coords[0], coords[1]]; - - if (target > heightF + talus) - { - double calc = c * ((target - heightF) - talus); - heightF += calc; - target -= calc; - } - - thisFrame[x, y] = heightF; - thisFrame[coords[0], coords[1]] = target; - - } - } - } - } - lastFrame = (double[,])thisFrame.Clone(); - } - - map = thisFrame; - - Normalise(); // Just to guaruntee a smooth 0..1 value - return this; - } - } -} +/* +* Copyright (c) Contributors, http://www.openmetaverse.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace libTerrain +{ + partial class Channel + { + /// + /// A thermal weathering implementation based on Musgrave's original 1989 algorithm. This is Adam's custom implementation which may differ slightly from the original. + /// + /// The rock angle (represented as a dy/dx ratio) at which point it will be succeptible to breakage + /// The number of erosion rounds + /// The amount of rock to carry each round + public Channel ThermalWeathering(double talus, int rounds, double c) + { + SetDiff(); + + double[,] lastFrame; + double[,] thisFrame; + + lastFrame = (double[,])map.Clone(); + thisFrame = (double[,])map.Clone(); + + NeighbourSystem type = NeighbourSystem.Moore; // Using moore neighbourhood (twice as computationally expensive) + int NEIGHBOUR_ME = 4; // I am always 4 in both systems. + + int NEIGHBOUR_MAX = type == NeighbourSystem.Moore ? 9 : 5; + + int frames = rounds; // Number of thermal erosion iterations to run + int i, j; + int x, y; + + for (i = 0; i < frames; i++) + { + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + for (j = 0; j < NEIGHBOUR_MAX; j++) + { + if (j != NEIGHBOUR_ME) + { + int[] coords = Neighbours(type, j); + + coords[0] += x; + coords[1] += y; + + if (coords[0] > w - 1) + coords[0] = w - 1; + if (coords[1] > h - 1) + coords[1] = h - 1; + if (coords[0] < 0) + coords[0] = 0; + if (coords[1] < 0) + coords[1] = 0; + + double heightF = thisFrame[x, y]; + double target = thisFrame[coords[0], coords[1]]; + + if (target > heightF + talus) + { + double calc = c * ((target - heightF) - talus); + heightF += calc; + target -= calc; + } + + thisFrame[x, y] = heightF; + thisFrame[coords[0], coords[1]] = target; + + } + } + } + } + lastFrame = (double[,])thisFrame.Clone(); + } + + map = thisFrame; + + Normalise(); // Just to guaruntee a smooth 0..1 value + return this; + } + } +} -- cgit v1.1