Skip to content

Instantly share code, notes, and snippets.

@Jacajack
Created October 9, 2016 12:49
Show Gist options
  • Save Jacajack/95b9f8149955f5f992d3e32d283a4cd5 to your computer and use it in GitHub Desktop.
Save Jacajack/95b9f8149955f5f992d3e32d283a4cd5 to your computer and use it in GitHub Desktop.
A simple, yet awesome (and messy) prototype terrain generator ❤️
<!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>
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