aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/ErodeSphere.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/ErodeSphere.cs')
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/ErodeSphere.cs622
1 files changed, 311 insertions, 311 deletions
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/ErodeSphere.cs b/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/ErodeSphere.cs
index 29448aa..e036988 100644
--- a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/ErodeSphere.cs
+++ b/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/ErodeSphere.cs
@@ -1,312 +1,312 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright 9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the 12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using OpenSim.Region.Environment.Interfaces; 29using OpenSim.Region.Environment.Interfaces;
30 30
31namespace OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes 31namespace OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes
32{ 32{
33 /// <summary> 33 /// <summary>
34 /// Hydraulic Erosion Brush 34 /// Hydraulic Erosion Brush
35 /// </summary> 35 /// </summary>
36 public class ErodeSphere : ITerrainPaintableEffect 36 public class ErodeSphere : ITerrainPaintableEffect
37 { 37 {
38 private double rainHeight = 0.2; 38 private double rainHeight = 0.2;
39 private int rounds = 10; 39 private int rounds = 10;
40 private NeighbourSystem type = NeighbourSystem.Moore; // Parameter 40 private NeighbourSystem type = NeighbourSystem.Moore; // Parameter
41 private double waterSaturation = 0.30; // Can carry 1% of water in height 41 private double waterSaturation = 0.30; // Can carry 1% of water in height
42 42
43 #region Supporting Functions 43 #region Supporting Functions
44 44
45 private int[] Neighbours(NeighbourSystem type, int index) 45 private int[] Neighbours(NeighbourSystem type, int index)
46 { 46 {
47 int[] coord = new int[2]; 47 int[] coord = new int[2];
48 48
49 index++; 49 index++;
50 50
51 switch (type) 51 switch (type)
52 { 52 {
53 case NeighbourSystem.Moore: 53 case NeighbourSystem.Moore:
54 switch (index) 54 switch (index)
55 { 55 {
56 case 1: 56 case 1:
57 coord[0] = -1; 57 coord[0] = -1;
58 coord[1] = -1; 58 coord[1] = -1;
59 break; 59 break;
60 60
61 case 2: 61 case 2:
62 coord[0] = -0; 62 coord[0] = -0;
63 coord[1] = -1; 63 coord[1] = -1;
64 break; 64 break;
65 65
66 case 3: 66 case 3:
67 coord[0] = +1; 67 coord[0] = +1;
68 coord[1] = -1; 68 coord[1] = -1;
69 break; 69 break;
70 70
71 case 4: 71 case 4:
72 coord[0] = -1; 72 coord[0] = -1;
73 coord[1] = -0; 73 coord[1] = -0;
74 break; 74 break;
75 75
76 case 5: 76 case 5:
77 coord[0] = -0; 77 coord[0] = -0;
78 coord[1] = -0; 78 coord[1] = -0;
79 break; 79 break;
80 80
81 case 6: 81 case 6:
82 coord[0] = +1; 82 coord[0] = +1;
83 coord[1] = -0; 83 coord[1] = -0;
84 break; 84 break;
85 85
86 case 7: 86 case 7:
87 coord[0] = -1; 87 coord[0] = -1;
88 coord[1] = +1; 88 coord[1] = +1;
89 break; 89 break;
90 90
91 case 8: 91 case 8:
92 coord[0] = -0; 92 coord[0] = -0;
93 coord[1] = +1; 93 coord[1] = +1;
94 break; 94 break;
95 95
96 case 9: 96 case 9:
97 coord[0] = +1; 97 coord[0] = +1;
98 coord[1] = +1; 98 coord[1] = +1;
99 break; 99 break;
100 100
101 default: 101 default:
102 break; 102 break;
103 } 103 }
104 break; 104 break;
105 105
106 case NeighbourSystem.VonNeumann: 106 case NeighbourSystem.VonNeumann:
107 switch (index) 107 switch (index)
108 { 108 {
109 case 1: 109 case 1:
110 coord[0] = 0; 110 coord[0] = 0;
111 coord[1] = -1; 111 coord[1] = -1;
112 break; 112 break;
113 113
114 case 2: 114 case 2:
115 coord[0] = -1; 115 coord[0] = -1;
116 coord[1] = 0; 116 coord[1] = 0;
117 break; 117 break;
118 118
119 case 3: 119 case 3:
120 coord[0] = +1; 120 coord[0] = +1;
121 coord[1] = 0; 121 coord[1] = 0;
122 break; 122 break;
123 123
124 case 4: 124 case 4:
125 coord[0] = 0; 125 coord[0] = 0;
126 coord[1] = +1; 126 coord[1] = +1;
127 break; 127 break;
128 128
129 case 5: 129 case 5:
130 coord[0] = -0; 130 coord[0] = -0;
131 coord[1] = -0; 131 coord[1] = -0;
132 break; 132 break;
133 133
134 default: 134 default:
135 break; 135 break;
136 } 136 }
137 break; 137 break;
138 } 138 }
139 139
140 return coord; 140 return coord;
141 } 141 }
142 142
143 private enum NeighbourSystem 143 private enum NeighbourSystem
144 { 144 {
145 Moore, 145 Moore,
146 VonNeumann 146 VonNeumann
147 } ; 147 } ;
148 148
149 #endregion 149 #endregion
150 150
151 #region ITerrainPaintableEffect Members 151 #region ITerrainPaintableEffect Members
152 152
153 public void PaintEffect(ITerrainChannel map, double rx, double ry, double strength, double duration) 153 public void PaintEffect(ITerrainChannel map, double rx, double ry, double strength, double duration)
154 { 154 {
155 strength = TerrainUtil.MetersToSphericalStrength(strength); 155 strength = TerrainUtil.MetersToSphericalStrength(strength);
156 156
157 int x, y; 157 int x, y;
158 // Using one 'rain' round for this, so skipping a useless loop 158 // Using one 'rain' round for this, so skipping a useless loop
159 // Will need to adapt back in for the Flood brush 159 // Will need to adapt back in for the Flood brush
160 160
161 ITerrainChannel water = new TerrainChannel(map.Width, map.Height); 161 ITerrainChannel water = new TerrainChannel(map.Width, map.Height);
162 ITerrainChannel sediment = new TerrainChannel(map.Width, map.Height); 162 ITerrainChannel sediment = new TerrainChannel(map.Width, map.Height);
163 163
164 // Fill with rain 164 // Fill with rain
165 for (x = 0; x < water.Width; x++) 165 for (x = 0; x < water.Width; x++)
166 for (y = 0; y < water.Height; y++) 166 for (y = 0; y < water.Height; y++)
167 water[x, y] = Math.Max(0.0, TerrainUtil.SphericalFactor(x, y, rx, ry, strength) * rainHeight * duration); 167 water[x, y] = Math.Max(0.0, TerrainUtil.SphericalFactor(x, y, rx, ry, strength) * rainHeight * duration);
168 168
169 for (int i = 0; i < rounds; i++) 169 for (int i = 0; i < rounds; i++)
170 { 170 {
171 // Erode underlying terrain 171 // Erode underlying terrain
172 for (x = 0; x < water.Width; x++) 172 for (x = 0; x < water.Width; x++)
173 { 173 {
174 for (y = 0; y < water.Height; y++) 174 for (y = 0; y < water.Height; y++)
175 { 175 {
176 double solConst = (1.0 / rounds); 176 double solConst = (1.0 / rounds);
177 double sedDelta = water[x, y] * solConst; 177 double sedDelta = water[x, y] * solConst;
178 map[x, y] -= sedDelta; 178 map[x, y] -= sedDelta;
179 sediment[x, y] += sedDelta; 179 sediment[x, y] += sedDelta;
180 } 180 }
181 } 181 }
182 182
183 // Move water 183 // Move water
184 for (x = 0; x < water.Width; x++) 184 for (x = 0; x < water.Width; x++)
185 { 185 {
186 for (y = 0; y < water.Height; y++) 186 for (y = 0; y < water.Height; y++)
187 { 187 {
188 if (water[x, y] <= 0) 188 if (water[x, y] <= 0)
189 continue; 189 continue;
190 190
191 // Step 1. Calculate average of neighbours 191 // Step 1. Calculate average of neighbours
192 192
193 int neighbours = 0; 193 int neighbours = 0;
194 double altitudeTotal = 0.0; 194 double altitudeTotal = 0.0;
195 double altitudeMe = map[x, y] + water[x, y]; 195 double altitudeMe = map[x, y] + water[x, y];
196 196
197 int NEIGHBOUR_ME = 4; 197 int NEIGHBOUR_ME = 4;
198 198
199 int NEIGHBOUR_MAX = type == NeighbourSystem.Moore ? 9 : 5; 199 int NEIGHBOUR_MAX = type == NeighbourSystem.Moore ? 9 : 5;
200 200
201 for (int j = 0; j < NEIGHBOUR_MAX; j++) 201 for (int j = 0; j < NEIGHBOUR_MAX; j++)
202 { 202 {
203 if (j != NEIGHBOUR_ME) 203 if (j != NEIGHBOUR_ME)
204 { 204 {
205 int[] coords = Neighbours(type, j); 205 int[] coords = Neighbours(type, j);
206 206
207 coords[0] += x; 207 coords[0] += x;
208 coords[1] += y; 208 coords[1] += y;
209 209
210 if (coords[0] > map.Width - 1) 210 if (coords[0] > map.Width - 1)
211 continue; 211 continue;
212 if (coords[1] > map.Height - 1) 212 if (coords[1] > map.Height - 1)
213 continue; 213 continue;
214 if (coords[0] < 0) 214 if (coords[0] < 0)
215 continue; 215 continue;
216 if (coords[1] < 0) 216 if (coords[1] < 0)
217 continue; 217 continue;
218 218
219 // Calculate total height of this neighbour 219 // Calculate total height of this neighbour
220 double altitudeNeighbour = water[coords[0], coords[1]] + map[coords[0], coords[1]]; 220 double altitudeNeighbour = water[coords[0], coords[1]] + map[coords[0], coords[1]];
221 221
222 // If it's greater than me... 222 // If it's greater than me...
223 if (altitudeNeighbour - altitudeMe < 0) 223 if (altitudeNeighbour - altitudeMe < 0)
224 { 224 {
225 // Add it to our calculations 225 // Add it to our calculations
226 neighbours++; 226 neighbours++;
227 altitudeTotal += altitudeNeighbour; 227 altitudeTotal += altitudeNeighbour;
228 } 228 }
229 } 229 }
230 } 230 }
231 231
232 if (neighbours == 0) 232 if (neighbours == 0)
233 continue; 233 continue;
234 234
235 double altitudeAvg = altitudeTotal / neighbours; 235 double altitudeAvg = altitudeTotal / neighbours;
236 236
237 // Step 2. Allocate water to neighbours. 237 // Step 2. Allocate water to neighbours.
238 for (int j = 0; j < NEIGHBOUR_MAX; j++) 238 for (int j = 0; j < NEIGHBOUR_MAX; j++)
239 { 239 {
240 if (j != NEIGHBOUR_ME) 240 if (j != NEIGHBOUR_ME)
241 { 241 {
242 int[] coords = Neighbours(type, j); 242 int[] coords = Neighbours(type, j);
243 243
244 coords[0] += x; 244 coords[0] += x;
245 coords[1] += y; 245 coords[1] += y;
246 246
247 if (coords[0] > map.Width - 1) 247 if (coords[0] > map.Width - 1)
248 continue; 248 continue;
249 if (coords[1] > map.Height - 1) 249 if (coords[1] > map.Height - 1)
250 continue; 250 continue;
251 if (coords[0] < 0) 251 if (coords[0] < 0)
252 continue; 252 continue;
253 if (coords[1] < 0) 253 if (coords[1] < 0)
254 continue; 254 continue;
255 255
256 // Skip if we dont have water to begin with. 256 // Skip if we dont have water to begin with.
257 if (water[x, y] < 0) 257 if (water[x, y] < 0)
258 continue; 258 continue;
259 259
260 // Calculate our delta average 260 // Calculate our delta average
261 double altitudeDelta = altitudeMe - altitudeAvg; 261 double altitudeDelta = altitudeMe - altitudeAvg;
262 262
263 if (altitudeDelta < 0) 263 if (altitudeDelta < 0)
264 continue; 264 continue;
265 265
266 // Calculate how much water we can move 266 // Calculate how much water we can move
267 double waterMin = Math.Min(water[x, y], altitudeDelta); 267 double waterMin = Math.Min(water[x, y], altitudeDelta);
268 double waterDelta = waterMin * ((water[coords[0], coords[1]] + map[coords[0], coords[1]]) 268 double waterDelta = waterMin * ((water[coords[0], coords[1]] + map[coords[0], coords[1]])
269 / altitudeTotal); 269 / altitudeTotal);
270 270
271 double sedimentDelta = sediment[x, y] * (waterDelta / water[x, y]); 271 double sedimentDelta = sediment[x, y] * (waterDelta / water[x, y]);
272 272
273 if (sedimentDelta > 0) 273 if (sedimentDelta > 0)
274 { 274 {
275 sediment[x, y] -= sedimentDelta; 275 sediment[x, y] -= sedimentDelta;
276 sediment[coords[0], coords[1]] += sedimentDelta; 276 sediment[coords[0], coords[1]] += sedimentDelta;
277 } 277 }
278 } 278 }
279 } 279 }
280 } 280 }
281 } 281 }
282 282
283 // Evaporate 283 // Evaporate
284 284
285 for (x = 0; x < water.Width; x++) 285 for (x = 0; x < water.Width; x++)
286 { 286 {
287 for (y = 0; y < water.Height; y++) 287 for (y = 0; y < water.Height; y++)
288 { 288 {
289 water[x, y] *= 1.0 - (rainHeight / rounds); 289 water[x, y] *= 1.0 - (rainHeight / rounds);
290 290
291 double waterCapacity = waterSaturation * water[x, y]; 291 double waterCapacity = waterSaturation * water[x, y];
292 292
293 double sedimentDeposit = sediment[x, y] - waterCapacity; 293 double sedimentDeposit = sediment[x, y] - waterCapacity;
294 if (sedimentDeposit > 0) 294 if (sedimentDeposit > 0)
295 { 295 {
296 sediment[x, y] -= sedimentDeposit; 296 sediment[x, y] -= sedimentDeposit;
297 map[x, y] += sedimentDeposit; 297 map[x, y] += sedimentDeposit;
298 } 298 }
299 } 299 }
300 } 300 }
301 } 301 }
302 302
303 // Deposit any remainder (should be minimal) 303 // Deposit any remainder (should be minimal)
304 for (x = 0; x < water.Width; x++) 304 for (x = 0; x < water.Width; x++)
305 for (y = 0; y < water.Height; y++) 305 for (y = 0; y < water.Height; y++)
306 if (sediment[x, y] > 0) 306 if (sediment[x, y] > 0)
307 map[x, y] += sediment[x, y]; 307 map[x, y] += sediment[x, y];
308 } 308 }
309 309
310 #endregion 310 #endregion
311 } 311 }
312} \ No newline at end of file 312} \ No newline at end of file