Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!doctype html>
- <html>
- <head><title>Procedural Island</title></head>
- <body style="font-family: sans-serif;">
- <b id="date_readout">---</b>
- <b id="low_readout">---</b>
- <div id="mouse_elevation" style="position: fixed; z-index:1; background-color:transparent;"></div>
- <br>
- <canvas id="map_canvas" style="background-color: black;">
- </canvas>
- <!--<canvas id="river_canvas" style = "position: absolute; z-index: 1; background-color:transparent;">
- </canvas>-->
- <br>
- [1] 50kA steps [2] 20kA steps [3] 5kA steps
- [S] fix sea level
- <script src="noise.js"></script>
- <script src="utilities.js"></script>
- <script src="voronoi.js"></script>
- <script>
- "use strict";
- create_voronoi_tiling(256, 256, 4, 0, 3);
- let bedrock_thickness = new Float32Array(cell_count);
- let sediment_thickness = new Float32Array(cell_count);
- let lake_thickness = new Float32Array(cell_count);
- let cell_elevation = new Float32Array(cell_count);
- let uplift_array = new Float32Array(cell_count);
- let erodibility = new Float32Array(cell_count);
- const km3 = 1000*1000*1000;
- const pixel_length = 250; //meters
- const mean_sea_level = 2000;
- const rainfall = 0.3; // meters per year
- const sediment_erosion_distance = 60000; //meters
- const bedrock_erosion_distance = 120000;
- const fluvial_transport_coefficient = 60; //kg/m^3
- const sedimentation_distance = 25000; //meters
- const sediment_density = 2200; //kg/m^3
- const landscape_diffusion_coefficient = 2; //only applied underwater
- let time = 0;
- let timestep = 50000; //years
- /* Knickpoint retreat of 0.2-2mm/year, say 1mm.
- Implies 4km (~one cell) in 4Ma.
- --too slow */
- const lake_threshold = 5; //only display water if deeper than this
- </script>
- <script src="webgl.js"></script>
- <script src="drainage.js"></script>
- <script>
- //setup_canvas(river_canvas);
- //render_voronoi();
- //render_delauney();
- let sea_level = mean_sea_level;
- //canvas.style.transform = "scale(0.75)";
- setup_initial_relief();
- setup_uplift();
- fill_lakes();
- initialize_drainage();
- calculate_drainage_graph();
- render();
- var t0 = performance.now();
- //for (let i=0; i<30; i++) {step(timestep);}
- var t1 = performance.now();
- console.log(((t1 - t0)/30).toFixed(0) + " milliseconds.");
- function setup_initial_relief()
- {
- var shape = new SNoise(500, 400, -45+Math.random()*90); //-45);
- shape.octaves(6, 0.5);
- var chunks = new SNoise(500, 300, -45+Math.random()*90); //-45);
- chunks.octaves(6, 0.8);
- var surface = new SNoise(500, 300, -45+Math.random()*90); //45);
- surface.octaves(5, 0.6);
- var noise1 = new SNoise(500);
- noise1.octaves(2, 0.6);
- //var rifting = new SNoise(600, 200, -30+Math.random()*60);
- var rifting = new SNoise(200, 50, -30+Math.random()*60);
- rifting.octaves(4, 0.6);
- var mountain = new SNoise(4000, 2400, 90);
- mountain.octaves(10, 0.6);
- let slope_s = 0.1*(Math.random()-0.5);
- let slope_t = 0.1*(Math.random()-0.5);
- for (let cell=0; cell<cell_count; cell++)
- {
- bedrock_thickness[cell]=0;
- sediment_thickness[cell]=0;
- lake_thickness[cell]=0;
- erodibility[cell] = 0.5 + Math.random();
- let x = cell_x[cell];
- let y = cell_y[cell];
- var s = (x/pixel_width)*2-1;
- var t = (y/pixel_width)*2-1;
- var x_km = 2*x*pixel_length/1000;
- var y_km = 2*y*pixel_length/1000;
- var h=0;
- var r = 2*(rifting.get(x_km + noise1.get(2*x_km, 2*y_km)*60, y_km)+0.4);
- if (r>0) r *= -10;
- else r=r*2000;
- if (noise1.get(0.5*x_km, 0.5*y_km+10000000) + 0.1*noise1.get(3*x_km+30000, 3*y_km)>0)
- {
- x_km += 400;
- y_km -= 400;
- }
- var e = 1.3*(s*s + t*t)+ 0.8*shape.get(x_km, y_km);
- e = 0.7-e;
- e = Math.min(e,s*slope_s + t*slope_t);
- e *= 5;
- h += 2100*(1+e);
- h += r*0.6;
- if (h>=600)
- {
- h += Math.max(chunks.get(x_km + 99999 + noise1.get(x_km+45345.354, y_km + 45.234) * 200, y_km + noise1.get(x_km, y_km+20000)*200) * 1000, -10);
- h += shape.get(x_km*10, y_km*10)*100;
- h += Noise.simplex2(x/10, y/10)*20;
- h += Math.random()*1;
- }
- if (h<600) h = 600;
- bedrock_thickness[cell] = h;
- sediment_thickness[cell] += Math.random();
- if (shape.get(x, y)<0) { bedrock_thickness[cell]-=100; sediment_thickness[cell] +=200;}
- }
- }
- function setup_uplift()
- {
- for (let cell=0; cell<cell_count; cell++)
- {
- let x = cell_x[cell];
- let y = cell_y[cell];
- let s = (x/pixel_width)*2 -1;
- var t = (y/pixel_width)*2-1;
- let d=0;
- d += compression(x/2, y/2+100*Noise.simplex2(0.45*s,0*0.5*t+6055)+50*Noise.simplex2(s+4,0*t+4) + 18*Noise.simplex2(s*2+100, t*2+1034) + 5 * Noise.simplex2(x/30, y/30), 0);
- d += compression(x/2+y/2,x/2-y/2,1000) * 0.2;
- d += Noise.simplex2(x/4, y/4)*20;
- d += Math.random()*20;
- d*= Math.max(2*Noise.simplex2(0.5*s+100, 1.6*t+200)+Noise.simplex2(3*s+200, 5*t+400)*0.5, 0);
- d *= 0.5*(t+1);
- d += Noise.simplex2(0.5*s+50.3, 0.5*t+100.7)*100; //long wavelength change
- uplift_array[cell] = d/1600;
- }
- }
- function setup_test_uplift()
- {
- for (let cell=0; cell<cell_count; cell++)
- {
- let x = cell_x[cell];
- let y = cell_y[cell];
- let xx = (x-500)/200;
- let yy = (y-500)/200;
- let d = 1-Math.sqrt(xx*xx+yy*yy);
- //d += (0.2*Noise.simplex2(x/50, y/50))+ 0.3*Noise.simplex2(x/120, y/100) + 0.4*Noise.simplex2(x/250, y/200);
- if (d<0) d = 0;
- uplift_array[cell] = 2*d;
- /*if ((x>200 && x<700) && (y>300 && y<500))
- {
- uplift_array[cell] = 2;// -20* Math.abs(y-400);
- }*/
- }
- }
- function uplift(dt)
- {
- for (let cell = 0; cell < cell_count; cell++)
- {
- let x = cell_x[cell];
- let y = cell_y[cell];
- if (cell_elevation[cell] < 1500) continue;
- //var h = uplift_array[cell]*dt*0.000004;
- let h = uplift_array[cell] * 0.001*dt; //uplift is in mm/year
- bedrock_thickness[cell] += h;
- }
- }
- function compression(x,y, noise_offset)
- {
- var e =Noise.simplex2(x/1000+noise_offset, y/160+noise_offset)*y*(pixel_height-y)*1.3/pixel_height;
- e += Noise.simplex2(x/400-6+noise_offset, y/60+7+noise_offset)*y*(pixel_height-y)/pixel_height;
- e += Noise.simplex2(x/140-9+noise_offset, y/20+20+noise_offset)*y*(pixel_height-y)*0.8/pixel_height;
- if (e<0) e*=0.2;
- return e;
- }
- function setup_test_initial_relief()
- {
- let bumps = new SNoise(300, 800, 45+Math.random()*90);
- let twist = new SNoise(600);
- twist.octaves(2);
- let form = new SNoise(900, 900);
- form.octaves(5);
- bumps.octaves(7, 0.6);
- for (let cell=0; cell<cell_count; cell++)
- {
- bedrock_thickness[cell]=0;
- sediment_thickness[cell]=0;
- lake_thickness[cell]=0;
- erodibility[cell] = 0.75+0.5*Math.random();
- let x = cell_x[cell];
- let y = cell_y[cell];
- if (x <200) bedrock_thickness[cell] = 0;
- else if (x<300) bedrock_thickness[cell] = 3100*(x-200)/100;
- else bedrock_thickness[cell] = 3100 + 10*Math.random();
- /*let rift = (form.get(x,y) + 2*x/pixel_width-0.5)*2;
- rift = Math.min(1, Math.max(rift, 0));
- if (form.get(y+20130, x-23982)<0) y=y+4000;
- bedrock_thickness[cell] = rift*Math.max(2150,
- (2000+1000*bumps.get(x+100*twist.get(x,y), y + 200*twist.get(y/2, x/2))+0.5*x)); //10*Math.random();
- y = cell
- _y[cell];
- if (y<30) bedrock_thickness[cell] += 120-4*y;
- if (y>pixel_height-30) bedrock_thickness[cell] += 4*(y - pixel_height+30);
- bedrock_thickness[cell] += Math.random()*2;*/
- }
- }
- function old_setup_uplift()
- {
- let bumps = new SNoise(30, 10, 25);
- bumps.octaves(7, 0.6);
- for (let cell = 0; cell < cell_count; cell++)
- {
- uplift_array[cell] = 0.5*bumps.get(cell_x[cell], cell_y[cell]);
- uplift_array[cell] += 0.1*Math.random();
- }
- }
- let change_sea_level = true;
- function step(dt)
- {
- time += dt;
- if (time>2000000 && change_sea_level) sea_level = mean_sea_level + 50 * Math.sin(2*Math.PI*time / 500000);
- if (time>500000 && change_sea_level) uplift(dt);
- initialize_drainage();
- calculate_drainage_graph();
- run_drainage(dt);
- render();
- }
- function render()
- {
- //draw_GL_relief();
- draw_mesh(cell_elevation);
- draw_coastlines(1);
- draw_rivers(0.01*km3, 2*km3, 1);
- }
- let mouse_x = 0;
- let mouse_y = 0;
- let mouse_in_window = true;
- document.addEventListener('mousemove', mouse_move);
- document.addEventListener('mouseleave', function(){ mouse_in_window = false; mouse_elevation.innerHTML="";});
- document.addEventListener('mouseenter', function(){ mouse_in_window = true; });
- let animate_toggle=false;
- let auto_run = true;
- onkeydown = function(e)
- {
- e.preventDefault();
- console.log(e.keyCode);
- auto_run = false;
- if (e.keyCode === 32) {animate_toggle = true;}
- else if (e.keyCode === 51) { timestep = 5000; animate_toggle = true;} //3
- else if (e.keyCode === 50) { timestep = 20000; animate_toggle = true;} //2
- else if (e.keyCode === 49) { timestep = 50000; animate_toggle = true;} //1
- else if (e.keyCode === 83) { change_sea_level = !change_sea_level} //s
- }
- onkeyup = function(){animate_toggle = false; }
- function animate(t)
- {
- if (time < 4000000 && auto_run) step(50000);
- else if (time < 4200000 && auto_run) step(20000);
- else if (time < 4250000 && auto_run) step(5000);
- else if (animate_toggle) step(timestep);
- update_mouse();
- requestAnimationFrame(animate);
- }
- animate();
- function draw_GL_relief()
- {
- for (let i=0; i<cell_count; i++)
- {
- cell_elevation[i] = bedrock_thickness[i]+sediment_thickness[i];
- }
- draw_mesh(cell_elevation);
- }
- function mouse_move(event)
- {
- let rect = map_canvas.getBoundingClientRect();
- mouse_x = event.clientX - rect.left;
- mouse_y = event.clientY - rect.top;
- mouse_elevation.style.left = (event.clientX+20)+'px';
- mouse_elevation.style.top = (event.clientY+20)+'px';
- update_mouse();
- }
- function update_mouse()
- {
- let Ma = (time/1000000).toFixed(2);
- text = (time/1000000).toFixed(2)+" Ma";
- date_readout.innerHTML = text;
- let cell = get_nearest_cell(mouse_x, mouse_y);
- text = "";
- if (cell != -1 && mouse_in_window)
- {
- let elevation = bedrock_thickness[cell]+sediment_thickness[cell]-mean_sea_level;
- //let with_water = elevation + lake_thickness[i];
- text = "["+cell+"] "+elevation.toFixed(1)+"m";
- //if (with_water>elevation) text +=" ("+with_water.toFixed(0)+"m)";
- /*for (let i=0; i<cell_neighbour_count[cell]; i++)
- {
- let weight = neighbour_weights[cell*9+i];
- if (weight != -1) text += ", "+weight.toExponential(1);
- else text += ", _"
- }*/
- }
- mouse_elevation.innerHTML = text;
- }
- </script>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement