aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/ErodeSphere.cs678
1 files changed, 339 insertions, 339 deletions
diff --git a/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/ErodeSphere.cs b/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/ErodeSphere.cs
index 804c642..d6f666d 100644
--- a/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/ErodeSphere.cs
+++ b/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/ErodeSphere.cs
@@ -1,339 +1,339 @@
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 OpenSim.Region.Environment.Interfaces; 28using OpenSim.Region.Environment.Interfaces;
29using System; 29using System;
30 30
31namespace OpenSim.Region.Environment.Modules.Terrain.PaintBrushes 31namespace OpenSim.Region.Environment.Modules.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 NeighbourSystem type = NeighbourSystem.Moore; // Parameter 38 NeighbourSystem type = NeighbourSystem.Moore; // Parameter
39 39
40 double rainHeight = 1.0; 40 double rainHeight = 1.0;
41 int rounds = 10; 41 int rounds = 10;
42 double waterSaturation = 0.01; // Can carry 1% of water in height 42 double waterSaturation = 0.01; // Can carry 1% of water in height
43 43
44 #region Supporting Functions 44 #region Supporting Functions
45 private enum NeighbourSystem 45 private enum NeighbourSystem
46 { 46 {
47 Moore, 47 Moore,
48 VonNeumann 48 VonNeumann
49 } ; 49 } ;
50 50
51 private int[] Neighbours(NeighbourSystem type, int index) 51 private int[] Neighbours(NeighbourSystem type, int index)
52 { 52 {
53 int[] coord = new int[2]; 53 int[] coord = new int[2];
54 54
55 index++; 55 index++;
56 56
57 switch (type) 57 switch (type)
58 { 58 {
59 case NeighbourSystem.Moore: 59 case NeighbourSystem.Moore:
60 switch (index) 60 switch (index)
61 { 61 {
62 case 1: 62 case 1:
63 coord[0] = -1; 63 coord[0] = -1;
64 coord[1] = -1; 64 coord[1] = -1;
65 break; 65 break;
66 66
67 case 2: 67 case 2:
68 coord[0] = -0; 68 coord[0] = -0;
69 coord[1] = -1; 69 coord[1] = -1;
70 break; 70 break;
71 71
72 case 3: 72 case 3:
73 coord[0] = +1; 73 coord[0] = +1;
74 coord[1] = -1; 74 coord[1] = -1;
75 break; 75 break;
76 76
77 case 4: 77 case 4:
78 coord[0] = -1; 78 coord[0] = -1;
79 coord[1] = -0; 79 coord[1] = -0;
80 break; 80 break;
81 81
82 case 5: 82 case 5:
83 coord[0] = -0; 83 coord[0] = -0;
84 coord[1] = -0; 84 coord[1] = -0;
85 break; 85 break;
86 86
87 case 6: 87 case 6:
88 coord[0] = +1; 88 coord[0] = +1;
89 coord[1] = -0; 89 coord[1] = -0;
90 break; 90 break;
91 91
92 case 7: 92 case 7:
93 coord[0] = -1; 93 coord[0] = -1;
94 coord[1] = +1; 94 coord[1] = +1;
95 break; 95 break;
96 96
97 case 8: 97 case 8:
98 coord[0] = -0; 98 coord[0] = -0;
99 coord[1] = +1; 99 coord[1] = +1;
100 break; 100 break;
101 101
102 case 9: 102 case 9:
103 coord[0] = +1; 103 coord[0] = +1;
104 coord[1] = +1; 104 coord[1] = +1;
105 break; 105 break;
106 106
107 default: 107 default:
108 break; 108 break;
109 } 109 }
110 break; 110 break;
111 111
112 case NeighbourSystem.VonNeumann: 112 case NeighbourSystem.VonNeumann:
113 switch (index) 113 switch (index)
114 { 114 {
115 case 1: 115 case 1:
116 coord[0] = 0; 116 coord[0] = 0;
117 coord[1] = -1; 117 coord[1] = -1;
118 break; 118 break;
119 119
120 case 2: 120 case 2:
121 coord[0] = -1; 121 coord[0] = -1;
122 coord[1] = 0; 122 coord[1] = 0;
123 break; 123 break;
124 124
125 case 3: 125 case 3:
126 coord[0] = +1; 126 coord[0] = +1;
127 coord[1] = 0; 127 coord[1] = 0;
128 break; 128 break;
129 129
130 case 4: 130 case 4:
131 coord[0] = 0; 131 coord[0] = 0;
132 coord[1] = +1; 132 coord[1] = +1;
133 break; 133 break;
134 134
135 case 5: 135 case 5:
136 coord[0] = -0; 136 coord[0] = -0;
137 coord[1] = -0; 137 coord[1] = -0;
138 break; 138 break;
139 139
140 default: 140 default:
141 break; 141 break;
142 } 142 }
143 break; 143 break;
144 } 144 }
145 145
146 return coord; 146 return coord;
147 } 147 }
148 148
149 private double SphericalFactor(double x, double y, double rx, double ry, double size) 149 private double SphericalFactor(double x, double y, double rx, double ry, double size)
150 { 150 {
151 double z = size * size - ((x - rx) * (x - rx) + (y - ry) * (y - ry)); 151 double z = size * size - ((x - rx) * (x - rx) + (y - ry) * (y - ry));
152 return z; 152 return z;
153 } 153 }
154 154
155 private double GetBilinearInterpolate(double x, double y, ITerrainChannel map) 155 private double GetBilinearInterpolate(double x, double y, ITerrainChannel map)
156 { 156 {
157 int w = map.Width; 157 int w = map.Width;
158 int h = map.Height; 158 int h = map.Height;
159 159
160 if (x > w - 2.0) 160 if (x > w - 2.0)
161 x = w - 2.0; 161 x = w - 2.0;
162 if (y > h - 2.0) 162 if (y > h - 2.0)
163 y = h - 2.0; 163 y = h - 2.0;
164 if (x < 0.0) 164 if (x < 0.0)
165 x = 0.0; 165 x = 0.0;
166 if (y < 0.0) 166 if (y < 0.0)
167 y = 0.0; 167 y = 0.0;
168 168
169 int stepSize = 1; 169 int stepSize = 1;
170 double h00 = map[(int)x, (int)y]; 170 double h00 = map[(int)x, (int)y];
171 double h10 = map[(int)x + stepSize, (int)y]; 171 double h10 = map[(int)x + stepSize, (int)y];
172 double h01 = map[(int)x, (int)y + stepSize]; 172 double h01 = map[(int)x, (int)y + stepSize];
173 double h11 = map[(int)x + stepSize, (int)y + stepSize]; 173 double h11 = map[(int)x + stepSize, (int)y + stepSize];
174 double h1 = h00; 174 double h1 = h00;
175 double h2 = h10; 175 double h2 = h10;
176 double h3 = h01; 176 double h3 = h01;
177 double h4 = h11; 177 double h4 = h11;
178 double a00 = h1; 178 double a00 = h1;
179 double a10 = h2 - h1; 179 double a10 = h2 - h1;
180 double a01 = h3 - h1; 180 double a01 = h3 - h1;
181 double a11 = h1 - h2 - h3 + h4; 181 double a11 = h1 - h2 - h3 + h4;
182 double partialx = x - (int)x; 182 double partialx = x - (int)x;
183 double partialz = y - (int)y; 183 double partialz = y - (int)y;
184 double hi = a00 + (a10 * partialx) + (a01 * partialz) + (a11 * partialx * partialz); 184 double hi = a00 + (a10 * partialx) + (a01 * partialz) + (a11 * partialx * partialz);
185 return hi; 185 return hi;
186 } 186 }
187 187
188 #endregion 188 #endregion
189 189
190 #region ITerrainPaintableEffect Members 190 #region ITerrainPaintableEffect Members
191 191
192 public void PaintEffect(ITerrainChannel map, double rx, double ry, double strength, double duration) 192 public void PaintEffect(ITerrainChannel map, double rx, double ry, double strength, double duration)
193 { 193 {
194 int x, y; 194 int x, y;
195 // Using one 'rain' round for this, so skipping a useless loop 195 // Using one 'rain' round for this, so skipping a useless loop
196 // Will need to adapt back in for the Flood brush 196 // Will need to adapt back in for the Flood brush
197 197
198 ITerrainChannel water = new TerrainChannel(map.Width, map.Height); 198 ITerrainChannel water = new TerrainChannel(map.Width, map.Height);
199 ITerrainChannel sediment = new TerrainChannel(map.Width, map.Height); 199 ITerrainChannel sediment = new TerrainChannel(map.Width, map.Height);
200 200
201 // Fill with rain 201 // Fill with rain
202 for (x = 0; x < water.Width; x++) 202 for (x = 0; x < water.Width; x++)
203 for (y = 0; y < water.Height; y++) 203 for (y = 0; y < water.Height; y++)
204 water[x, y] = Math.Max(0.0, SphericalFactor(x, y, rx, ry, strength) * rainHeight * duration); 204 water[x, y] = Math.Max(0.0, SphericalFactor(x, y, rx, ry, strength) * rainHeight * duration);
205 205
206 for (int i = 0; i < rounds; i++) 206 for (int i = 0; i < rounds; i++)
207 { 207 {
208 // Erode underlying terrain 208 // Erode underlying terrain
209 for (x = 0; x < water.Width; x++) 209 for (x = 0; x < water.Width; x++)
210 { 210 {
211 for (y = 0; y < water.Height; y++) 211 for (y = 0; y < water.Height; y++)
212 { 212 {
213 double solConst = (1.0 / rounds); 213 double solConst = (1.0 / rounds);
214 double sedDelta = water[x, y] * solConst; 214 double sedDelta = water[x, y] * solConst;
215 map[x, y] -= sedDelta; 215 map[x, y] -= sedDelta;
216 sediment[x, y] += sedDelta; 216 sediment[x, y] += sedDelta;
217 } 217 }
218 } 218 }
219 219
220 // Move water 220 // Move water
221 for (x = 0; x < water.Width; x++) 221 for (x = 0; x < water.Width; x++)
222 { 222 {
223 for (y = 0; y < water.Height; y++) 223 for (y = 0; y < water.Height; y++)
224 { 224 {
225 if (water[x, y] <= 0) 225 if (water[x, y] <= 0)
226 continue; 226 continue;
227 227
228 // Step 1. Calculate average of neighbours 228 // Step 1. Calculate average of neighbours
229 229
230 int neighbours = 0; 230 int neighbours = 0;
231 double altitudeTotal = 0.0; 231 double altitudeTotal = 0.0;
232 double altitudeMe = map[x, y] + water[x, y]; 232 double altitudeMe = map[x, y] + water[x, y];
233 233
234 int NEIGHBOUR_ME = 4; 234 int NEIGHBOUR_ME = 4;
235 235
236 int NEIGHBOUR_MAX = type == NeighbourSystem.Moore ? 9 : 5; 236 int NEIGHBOUR_MAX = type == NeighbourSystem.Moore ? 9 : 5;
237 237
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 // Calculate total height of this neighbour 256 // Calculate total height of this neighbour
257 double altitudeNeighbour = water[coords[0], coords[1]] + map[coords[0], coords[1]]; 257 double altitudeNeighbour = water[coords[0], coords[1]] + map[coords[0], coords[1]];
258 258
259 // If it's greater than me... 259 // If it's greater than me...
260 if (altitudeNeighbour - altitudeMe > 0) 260 if (altitudeNeighbour - altitudeMe > 0)
261 { 261 {
262 // Add it to our calculations 262 // Add it to our calculations
263 neighbours++; 263 neighbours++;
264 altitudeTotal += altitudeNeighbour; 264 altitudeTotal += altitudeNeighbour;
265 } 265 }
266 } 266 }
267 } 267 }
268 268
269 if (neighbours == 0) 269 if (neighbours == 0)
270 continue; 270 continue;
271 271
272 double altitudeAvg = altitudeTotal / neighbours; 272 double altitudeAvg = altitudeTotal / neighbours;
273 273
274 // Step 2. Allocate water to neighbours. 274 // Step 2. Allocate water to neighbours.
275 for (int j = 0; j < NEIGHBOUR_MAX; j++) 275 for (int j = 0; j < NEIGHBOUR_MAX; j++)
276 { 276 {
277 if (j != NEIGHBOUR_ME) 277 if (j != NEIGHBOUR_ME)
278 { 278 {
279 int[] coords = Neighbours(type, j); 279 int[] coords = Neighbours(type, j);
280 280
281 coords[0] += x; 281 coords[0] += x;
282 coords[1] += y; 282 coords[1] += y;
283 283
284 if (coords[0] > map.Width - 1) 284 if (coords[0] > map.Width - 1)
285 continue; 285 continue;
286 if (coords[1] > map.Height - 1) 286 if (coords[1] > map.Height - 1)
287 continue; 287 continue;
288 if (coords[0] < 0) 288 if (coords[0] < 0)
289 continue; 289 continue;
290 if (coords[1] < 0) 290 if (coords[1] < 0)
291 continue; 291 continue;
292 292
293 // Calculate our delta average 293 // Calculate our delta average
294 double altitudeDelta = altitudeMe - altitudeAvg; 294 double altitudeDelta = altitudeMe - altitudeAvg;
295 295
296 // Calculate how much water we can move 296 // Calculate how much water we can move
297 double waterDelta = Math.Min(water[x, y], altitudeDelta) 297 double waterDelta = Math.Min(water[x, y], altitudeDelta)
298 * (water[coords[0], coords[1]] + map[coords[0], coords[1]]) 298 * (water[coords[0], coords[1]] + map[coords[0], coords[1]])
299 / altitudeTotal; 299 / altitudeTotal;
300 300
301 double sedimentDelta = sediment[x, y] * (waterDelta / water[x, y]); 301 double sedimentDelta = sediment[x, y] * (waterDelta / water[x, y]);
302 302
303 if (sedimentDelta > 0) 303 if (sedimentDelta > 0)
304 { 304 {
305 sediment[x, y] -= sedimentDelta; 305 sediment[x, y] -= sedimentDelta;
306 sediment[coords[0], coords[1]] += sedimentDelta; 306 sediment[coords[0], coords[1]] += sedimentDelta;
307 } 307 }
308 } 308 }
309 } 309 }
310 } 310 }
311 } 311 }
312 312
313 // Evaporate 313 // Evaporate
314 314
315 for (x = 0; x < water.Width; x++) 315 for (x = 0; x < water.Width; x++)
316 { 316 {
317 for (y = 0; y < water.Height; y++) 317 for (y = 0; y < water.Height; y++)
318 { 318 {
319 water[x, y] *= 1.0 - (rainHeight / rounds); 319 water[x, y] *= 1.0 - (rainHeight / rounds);
320 320
321 double waterCapacity = waterSaturation * water[x, y]; 321 double waterCapacity = waterSaturation * water[x, y];
322 322
323 double sedimentDeposit = Math.Max(0, sediment[x, y] - waterCapacity); 323 double sedimentDeposit = Math.Max(0, sediment[x, y] - waterCapacity);
324 sediment[x, y] -= sedimentDeposit; 324 sediment[x, y] -= sedimentDeposit;
325 map[x, y] += sedimentDeposit; 325 map[x, y] += sedimentDeposit;
326 } 326 }
327 } 327 }
328 } 328 }
329 329
330 // Deposit any remainder (should be minimal) 330 // Deposit any remainder (should be minimal)
331 for (x = 0; x < water.Width; x++) 331 for (x = 0; x < water.Width; x++)
332 for (y = 0; y < water.Height; y++) 332 for (y = 0; y < water.Height; y++)
333 if (sediment[x, y] > 0) 333 if (sediment[x, y] > 0)
334 map[x, y] += sediment[x, y]; 334 map[x, y] += sediment[x, y];
335 } 335 }
336 336
337 #endregion 337 #endregion
338 } 338 }
339} 339}