Created
October 9, 2016 12:49
-
-
Save Jacajack/95b9f8149955f5f992d3e32d283a4cd5 to your computer and use it in GitHub Desktop.
A simple, yet awesome (and messy) prototype terrain generator ❤️
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<script src=tgen.js></script> | |
<style> | |
canvas | |
{ | |
border: 1px solid black; | |
display: inline-block; | |
margin: 1px; | |
} | |
#out | |
{ | |
text-align: center; | |
} | |
#control | |
{ | |
text-align: center; | |
} | |
#obj | |
{ | |
} | |
body | |
{ | |
text-align: center; | |
} | |
</style> | |
<head> | |
<body onload=""> | |
<h1>Le Terrain Generator</h1> | |
<hr> | |
<div id=control> | |
Start nodes count: <input id=start type=text value=2></input><br> | |
Iterations count: <input id=iterations type=text value=8></input><br> | |
Initial distortion: <input id=smooth type=text value=1.0></input><br> | |
Damping: <input id=damp type=text value=2.0></input><br><br> | |
<button onclick="generate()">Generate</button> | |
</control> | |
<hr> | |
<div id=objctl> | |
Bumpiness: <input id=bump type=text value=10.0></input><br><br> | |
<button onclick="objgen()">Export obj file</button><br><br> | |
<textarea cols=80 rows=10 id=obj type=text></textarea> | |
</div> | |
<hr> | |
<div id=out></div> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var canvas; | |
var ctx; | |
var c1size = 800; | |
var map = | |
{ | |
size: 2, | |
data: [] | |
}; | |
function gfxinit( ) | |
{ | |
var out = document.getElementById( "out" ); | |
out.innerHTML = "<canvas id='gfx' width="+ c1size +"px height="+c1size+"px>Oopsy!</canvas>"; | |
gfx = document.getElementById( "gfx" ); | |
ctx = gfx.getContext( "2d" ); | |
} | |
function draw( ) | |
{ | |
var w = Math.round( c1size / map.size ); | |
var h = Math.round( c1size / map.size ); | |
var l; | |
ctx.clearRect( 0, 0, c1size, c1size ); | |
for ( var i = 0; i < map.size; i++ ) | |
{ | |
for ( var j = 0; j < map.size; j++ ) | |
{ | |
l = ( map.data[i][j] * 2.55 ).toFixed( 0 ); | |
ctx.strokeStyle = ctx.fillStyle = "rgb(" + l + "," + l + "," + l + ")"; | |
ctx.fillRect( i * w, j * h, w, h ); | |
} | |
} | |
} | |
function mapinit( ) | |
{ | |
map.data = []; | |
map.size = document.getElementById( "start" ).value ; | |
for ( var i = 0; i < map.size; i++ ) | |
{ | |
map.data.push( [] ); | |
for ( var j = 0; j < map.size; j++ ) | |
{ | |
map.data[i].push( Math.random( ) * 100 ); | |
} | |
} | |
//console.log( map ); | |
} | |
function step( dist = 20 ) | |
{ | |
var newdata = []; | |
var newsize = map.size * 2 - 1; | |
//Create array | |
for ( var i = 0; i < newsize; i++ ) | |
{ | |
newdata.push( new Array( map.size + 1 ).join( '0' ).split( '' ) ); | |
} | |
//Copy data | |
for ( var i = 0; i < map.size; i++ ) | |
{ | |
for ( var j = 0; j < map.size; j++ ) | |
{ | |
newdata[i * 2][j * 2] = map.data[i][j]; | |
} | |
} | |
/* | |
//This is slower! | |
//Do the real stuff | |
for ( var i = 0; i < newsize; i++ ) | |
{ | |
for ( var j = 0; j < newsize; j++ ) | |
{ | |
if ( i % 2 == 1 ) | |
{ | |
newdata[i][j] = ( newdata[i - 1][j] + newdata[i + 1][j] ) / 2 + dist * ( Math.random( ) - 0.5 ); | |
} | |
else if ( j % 2 == 1 ) | |
{ | |
newdata[i][j] = ( newdata[i][j - 1] + newdata[i][j + 1] ) / 2 + dist * ( Math.random( ) - 0.5 ); | |
} | |
} | |
} | |
*/ | |
//Interpolate X | |
for ( var i = 0; i < newsize; i += 2 ) | |
{ | |
for ( var j = 1; j < newsize; j += 2 ) | |
{ | |
newdata[i][j] = ( newdata[i][j - 1] + newdata[i][j + 1] ) / 2 + dist * ( Math.random( ) - 0.5 ); | |
} | |
} | |
//Interpolate Y | |
for ( var i = 0; i < newsize; i += 2 ) | |
{ | |
for ( var j = 1; j < newsize; j += 2 ) | |
{ | |
newdata[j][i] = ( newdata[j - 1][i] + newdata[j + 1][i] ) / 2 + dist * ( Math.random( ) - 0.5 ); | |
} | |
} | |
//Interpolate middle-fields | |
for ( var i = 1; i < newsize; i += 2 ) | |
{ | |
for ( var j = 1; j < newsize; j += 2 ) | |
{ | |
newdata[i][j] = newdata[i - 1][j] + newdata[i + 1][j] + | |
newdata[i][j - 1] + newdata[i][j + 1]; | |
newdata[i][j] /= 4; | |
newdata[i][j] += dist * ( Math.random( ) - 0.5 ) | |
} | |
} | |
map.size = newsize; | |
map.data = newdata; | |
} | |
function generate( ) | |
{ | |
gfxinit( ); | |
mapinit( ); | |
var dist = 60; | |
var damp = document.getElementById( "damp" ).value; | |
for ( var i = 0; i < document.getElementById( "iterations" ).value ; i++ ) | |
{ | |
step( dist * document.getElementById( "smooth" ).value ); | |
dist /= damp; | |
} | |
console.log( map ); | |
draw( ); | |
} | |
function objgen( ) | |
{ | |
if ( map.size == 0 ) return; | |
var obj = ""; | |
//calculate z-factor | |
var max = []; | |
var min = []; | |
for ( var i = 0; i < map.size; i++ ) | |
{ | |
max.push( Math.max.apply( Math, map.data[i] ) ); | |
min.push( Math.min.apply( Math, map.data[i] ) ); | |
} | |
max = Math.max.apply( Math, max ) | |
min = Math.max.apply( Math, min ) | |
var scale = max - min; | |
//console.log( min, max, scale ); | |
var bump = document.getElementById( "bump" ).value ; | |
//generate obj vertices | |
for ( var i = 0; i < map.size; i++ ) | |
{ | |
var x = ( i * 10 / map.size ).toFixed( 4 ); | |
for ( var j = 0; j < map.size; j++ ) | |
{ | |
obj += "v " + x + " " + ( map.data[i][j] / 20 / scale * bump ).toFixed( 4 ) + " " + ( j * 10 / map.size ).toFixed( 4 ) + "\n"; | |
} | |
} | |
var faces = ""; | |
//generate obj faces | |
for ( var i = 0; i < map.size - 1; i++ ) | |
for ( var j = 0; j < map.size - 1; j++ ) | |
{ | |
var s = i * map.size + j + 1; | |
faces += "f " + s + " " + ( s + 1 ) + " " + ( s + map.size + 1 ) + " " + ( s + map.size ) + "\n"; | |
} | |
obj += faces; | |
document.getElementById( "obj" ).value = obj; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment