Random Terrain THREE.js

random terrain with perlin noise

by Konstantin Cryman

HTML

<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<div id="container">
  <div id="controls">
        <button id="reload">reload</button> <button id="fullScreenToggler">Toggle Fullscreen</button>
    <div id="SpeedBarContainer">
      Speed: <input id="Speed" type="range" min="0.01" max="1" step="0.01" value="0.1">
    </div>
    
    <div id="WorldScaleBar">
      WorldScale: <input id="WorldScale" type="range" min="0.0001" max="0.3" step="0.0001" value="0.11">
    </div>
  </div>

  
</div>

<script type="text/javascript">
/*
 * A speed-improved perlin and simplex noise algorithms for 2D.
 *
 * Based on example code by Stefan Gustavson ([email protected]).
 * Optimisations by Peter Eastman ([email protected]).
 * Better rank ordering method by Stefan Gustavson in 2012.
 * Converted to Javascript by Joseph Gentle.
 *
 * Version 2012-03-09
 *
 * This code was placed in the public domain by its original author,
 * Stefan Gustavson. You may use it as you see fit, but
 * attribution is appreciated.
 *
 */

(function(global){
  var module = global.noise = {};

  function Grad(x, y, z) {
    this.x = x; this.y = y; this.z = z;
  }
  
  Grad.prototype.dot2 = function(x, y) {
    return this.x*x + this.y*y;
  };

  Grad.prototype.dot3 = function(x, y, z) {
    return this.x*x + this.y*y + this.z*z;
  };

  var grad3 = [new Grad(1,1,0),new Grad(-1,1,0),new Grad(1,-1,0),new Grad(-1,-1,0),
               new Grad(1,0,1),new Grad(-1,0,1),new Grad(1,0,-1),new Grad(-1,0,-1),
               new Grad(0,1,1),new Grad(0,-1,1),new Grad(0,1,-1),new Grad(0,-1,-1)];

  var p = [151,160,137,91,90,15,
  131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
  190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
  88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
 ...

CSS

html, body {
  margin: 0;
  padding: 0;
  overflow: hidden;
}
#reload{
  position: absolute;
  top: 0px;
  left: 0px; 
}
#fullScreenToggler{
  position: absolute;
  top: 30px;
  left: 0px; 
}
#SpeedBarContainer{
  position: absolute;
  top: 0px;
  right: 0px; 
}
#WorldScaleBar{
  position: absolute;
  top: 30px;
  right: 0px; 
}

JavaScript

var camera, controls, scene, renderer, raycaster;

   
var WORLD = {
    seed: 0.15922414237675842,
    width: 50,
    height: 50,
    scale: 0.07,
    planeWidth: 30000,
    planeHeight: 30000,
    noise: noise,
    worldGeometry: null,
    init: function(){
    		this.worldGeometry = new THREE.PlaneGeometry( this.planeWidth, this.planeHeight, this.width-1, this.height-1 );
    },
    heightFactor: 1380,
    getData: function( x, y ){
      return ctreateNoise( this.noise, this.width, this.height, this.scale, this.seed, x, y  )
    },
    applyWorldToGeometry: function( geometry, worldOffsetX, worldOffsetY ){
    		var worldData = this.getData( worldOffsetX, worldOffsetY );
        for( var i = 0; i < geometry.vertices.length; i++ ){
            geometry.vertices[i].z = this.heightFactor * (worldData.data[i] );
        }
   			geometry.verticesNeedUpdate = true;
    },
    setPosition( x, y ){
    
      this.applyWorldToGeometry( this.worldGeometry, x, y );
    }
};

WORLD.init();

var worldGeo = new THREE.PlaneGeometry( 2500, 2500, WORLD.width-1, WORLD.height-1 );

init();
render();

function ctreateNoise( _noise, width, height, scale, seed, startX, startY ){


    var width = width || 100;
    var height = height || 100;
    var scale = scale || 1;
    var seed = seed || Math.random();
    var startX = startX || 0;
    var startY = startY || 0;
    
    _noise.seed( seed );
    
    var pixels = [];
    
    for( var YY = 0; YY < height; YY++ ){
    		for( var XX = 0; XX < width; XX++ ){
        		// pixels.push( parseFloat(_noise.simplex2( (startX+XX)*scale, (startY+YY)*scale ).toFixed(6) ) );
        		pixels.push( _noise.simplex2( (startX+XX)*scale, (startY+YY)*scale ) );
        }
    }
    
    return {
    	data: pixels,
      width: width,
      height: height,
      scale: scale,
      startX: startX,
      startY: startY
    };
};



function init() {
    
    console.log( 'test');
    
    // renderer
    renderer = new THREE.WebGLRenderer( {...