commit
message
finally got complex erosion working!
author
Ben Vogt <[email protected]>
date
2016-05-14 03:01:46
stats
2 file(s) changed,
156 insertions(+),
12 deletions(-)
files
index.html
main.js
1diff --git a/index.html b/index.html
2index 7ec84cf..a12c080 100644
3--- a/index.html
4+++ b/index.html
5@@ -6,6 +6,7 @@
6 <script type="text/javascript" src="main.js"></script>
7 </head>
8 <body>
9+ <!-- header -->
10 <div class="container">
11 <div class="row">
12 <h1>Terrain Maps</h1>
13@@ -13,6 +14,7 @@
14 <p>I've been messing around with different terrain smoothing algorithms to run on Diamond-Square-generated maps. I'm putting them here to so I remember them and write them out a little more clearly.</p>
15 </div>
16 </div>
17+ <!-- container-1 -->
18 <div class="container">
19 <hr>
20 <div class="row">
21@@ -25,6 +27,7 @@
22 <div class="set-of" id="container-1"></div>
23 <hr>
24 </div>
25+ <!-- container-2 -->
26 <div class="container">
27 <div class="row">
28 <h2>Combining Diamond-Square maps</h2>
29@@ -43,6 +46,7 @@
30 <div class="set-of" id="container-2"></div>
31 <hr>
32 </div>
33+ <!-- container-3 -->
34 <div class="container">
35 <div class="row">
36 <h2>Greedy Raindrop Erosion Algorithm</h2>
37@@ -54,17 +58,31 @@
38 <div class="set-of" id="container-3"></div>
39 <hr>
40 </div>
41+ <!-- container-4 -->
42 <div class="container">
43 <div class="row">
44- <h2>Soil Erosion Algorithm</h2>
45+ <h2>Simple Erosion Algorithm</h2>
46 <p>
47 Randomly place a "droplet" of water on the map. For a number of iterations, let the droplet roll to it's nearest neighbor, eroding it's current point on the map if the droplet has not reached it carrying-capacity of sediment. If it has reached
48 it's carrying capacity, deposit sediment on that point. Repeat this process with many more droplets.
49- <button class="run button-primary" id="erosion">RUN</button>
50+ <button class="run button-primary" id="simpleErosion">RUN</button>
51 </p>
52 </div>
53 <div class="set-of" id="container-4"></div>
54+ <hr>
55+ </div>
56+ <!-- container-5 -->
57+ <div class="container">
58+ <div class="row">
59+ <h2>Complex Erosion Algorithm</h2>
60+ <p>
61+ <button class="run button-primary" id="complexErosion">RUN</button>
62+ </p>
63+ </div>
64+ <div class="set-of" id="container-5"></div>
65+ <hr>
66 </div>
67+ <!-- hidden canvas for rendering-->
68 <canvas class="hidden" id="tmp" width="256" height="256"></canvas>
69 </body>
70 </html>
71diff --git a/main.js b/main.js
72index e8f0a94..113bdbe 100644
73--- a/main.js
74+++ b/main.js
75@@ -262,14 +262,13 @@ $(document).ready(function() {
76 }
77 };
78
79- LandMap.prototype.erosion = function(options) {
80+ LandMap.prototype.simpleErosion = function(options) {
81 var Kq = options.carryingCapacity;
82 var Kd = options.depositionSpeed;
83 var iterations = options.iterations;
84 var drops = options.drops;
85 var one = options.one;
86 var two = options.two;
87- var ds = 0;
88
89 var HeightMap = new Array(this.size * this.size);
90 for (var y = 0; y < this.size; y++) {
91@@ -289,18 +288,14 @@ $(document).ready(function() {
92 return HeightMap[(x + HMAP_SIZE * y)];
93 }
94
95-
96- var MAX_PATH_LEN = this.size * 4;
97-
98 function DEPOSIT_AT(X, Y) {
99 var c = 0.0;
100 var v = 1.05;
101- var g = 1.4;
102- var mv = 10.0;
103+ var maxVelocity = 10.0;
104
105 // For the number of iterations
106 for (var iter = 0; iter < iterations; iter++) {
107- var v = Math.min(v, mv); // limiting velocity
108+ v = Math.min(v, maxVelocity); // limiting velocity
109 var val = HMAP_VALUE(X, Y);
110 var nv = [
111 HMAP_VALUE(X, Y - 1), //NORTH
112@@ -371,8 +366,115 @@ $(document).ready(function() {
113 DEPOSIT_AT(Math.floor(Math.random() * this.size), Math.floor(Math.random() * this.size));
114 this.maps[two] = HeightMap;
115 }
116- }
117+ };
118+
119+ LandMap.prototype.complexErosion = function(options) {
120+ var Kq = options.carryingCapacity;
121+ var Kd = options.depositionSpeed;
122+ var iterations = options.iterations;
123+ var drops = options.drops;
124+ var one = options.one;
125+ var two = options.two;
126+
127+ var HeightMap = new Array(this.size * this.size);
128+ for (var y = 0; y < this.size; y++) {
129+ for (var x = 0; x < this.size; x++) {
130+ HeightMap[(x + this.size * y)] = this.get(one, x, y);
131+ }
132+ }
133+
134+ var HMAP_SIZE = this.size;
135+
136+ function HMAP_INDEX(x, y) {
137+ var val = (x + HMAP_SIZE * y)
138+ return val;
139+ }
140+
141+ function HMAP_VALUE(x, y) {
142+ return HeightMap[(x + HMAP_SIZE * y)];
143+ }
144+
145+ function DEPOSIT_AT(X, Y) {
146+ var c = 0.0;
147+ var v = 1.05;
148+ var minSlope = 1.15;
149+ var maxVelocity = 10.0;
150+
151+ // For the number of iterations
152+ for (var iter = 0; iter < iterations; iter++) {
153+ v = Math.min(v, maxVelocity); // limiting velocity
154+ var val = HMAP_VALUE(X, Y);
155+ var nv = [
156+ HMAP_VALUE(X, Y - 1), //NORTH
157+ HMAP_VALUE(X, Y + 1), //SOUTH
158+ HMAP_VALUE(X + 1, Y), //EAST
159+ HMAP_VALUE(X - 1, Y) //WEST
160+ ];
161+
162+ var minInd = indexOfMin(nv);
163+ // if the lowest neighbor is NOT greater than the current value
164+ if (nv[minInd] < val) {
165+ //deposit or erode
166+ var slope = Math.min(minSlope, val - nv[minInd])
167+ var vtc = Kd * v * slope; // value to steal is depositionSpeed * velocity * abs(slope);
168+ // if carrying amount is greater than Kq
169+ if (c > Kq) {
170+ //DEPOSIT
171+ c -= vtc;
172+ HeightMap[HMAP_INDEX(X, Y)] += vtc;
173+ } else {
174+ //ERODE
175+ // if carrying + value to steal > carrying cap
176+ if (c + vtc > Kq) {
177+ var delta = c + vtc - Kq;
178+ c += delta;
179+ HeightMap[HMAP_INDEX(X, Y)] -= delta;
180+ } else {
181+ c += vtc;
182+ HeightMap[HMAP_INDEX(X, Y)] -= vtc;
183+ }
184+ }
185+
186+ // move to next value
187+ if (minInd == 0) {
188+ //NORTH
189+ Y -= 1
190+ }
191+ if (minInd == 1) {
192+ //SOUTH
193+ Y += 1
194+ }
195+ if (minInd == 2) {
196+ //EAST
197+ X += 1
198+ }
199+ if (minInd == 3) {
200+ //WEST
201+ X -= 1
202+ }
203
204+ // limiting to edge of map
205+ if (X > this.size - 1) {
206+ X = this.size;
207+ }
208+ if (Y > this.size - 1) {
209+ Y = this.size;
210+ }
211+ if (Y < 0) {
212+ Y = 0;
213+ }
214+ if (X < 0) {
215+ X = 0;
216+ }
217+ }
218+ }
219+ }
220+
221+ for (var drop = 0; drop < drops; drop++) {
222+ DEPOSIT_AT(Math.floor(Math.random() * this.size), Math.floor(Math.random() * this.size));
223+ this.maps[two] = HeightMap;
224+ }
225+ };
226
227 LandMap.prototype.draw = function() {
228 var html = '<div class="row">';
229@@ -467,20 +569,34 @@ $(document).ready(function() {
230 });
231
232
233- $("#erosion").click(function() {
234+ $("#simpleErosion").click(function() {
235 var terrain = new LandMap({
236 containerId: "container-4"
237 });
238 terrain.generate(0.75, "standard");
239- terrain.erosion({
240+ terrain.simpleErosion({
241 carryingCapacity: 1.5,
242 depositionSpeed: 0.03,
243 iterations: 10,
244 drops: 1000000,
245 one: "standard",
246- two: "erosion"
247+ two: "simpleErosion"
248 });
249 terrain.draw();
250 });
251
252+ var terrain = new LandMap({
253+ containerId: "container-5"
254+ });
255+ terrain.generate(0.75, "standard");
256+ terrain.complexErosion({
257+ carryingCapacity: 1.5,
258+ depositionSpeed: 0.03,
259+ iterations: 10,
260+ drops: 1000000,
261+ one: "standard",
262+ two: "complexErosion"
263+ });
264+ terrain.draw();
265+
266 })