Shallow Water Simulation

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/three.js/r58/three.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/stats.js/r11/Stats.js"></script>
<input type="checkbox" id="play" checked="checked"><label for="play">Play</label>

JavaScript

var stats = new Stats();

stats.domElement.style.position = 'absolute';
stats.domElement.style.right = '0';
stats.domElement.style.bottom = '0';

document.body.appendChild( stats.domElement );

var G = 0.2,
    H = 3,
    DAMP = 0.05,
    TIMESTEP = 0.1;

var scene = new THREE.Scene();

var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 10000);
camera.position = new THREE.Vector3(60, 60, 60);
camera.lookAt(new THREE.Vector3(0, -20, 0));
scene.add(camera);

var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(3, 3, 3).normalize();
scene.add(directionalLight);

var pointLight = new THREE.PointLight(0xffffff);
pointLight.position.set(3, 3, 3).normalize();
scene.add(pointLight);

var rowsAndCols = 120;

var mesh = new THREE.Mesh(
    new THREE.SphereGeometry(80, 80, rowsAndCols-1, rowsAndCols-1),
    new THREE.MeshPhongMaterial({ 
        color: 0x0000AA, 
        wireframe: true
    })
);
mesh.rotation.x = -Math.PI / 2;
scene.add(mesh);

var vertices = mesh.geometry.vertices;
for (var i = 0; i < rowsAndCols; i++) {
    for (var j = 0; j < rowsAndCols; j++) {
        var v = vertices[i*rowsAndCols + j];
        v.edge = false;
        
        var firstRow = (i === 0), lastRow = (i === rowsAndCols-1),
            firstCol = (j === 0), lastCol = (j === rowsAndCols-1);
        
        v.edge = firstRow || lastRow || firstCol || lastCol;

        v.above = firstRow ? null : vertices[(i-1)*rowsAndCols + j];
        v.below = lastRow ? null : vertices[(i+1)*rowsAndCols + j];
        v.left = firstCol ? null : vertices[i*rowsAndCols + j-1];
        v.right = lastCol ? null : vertices[i*rowsAndCols + j+1];
        
        v.z = H;
        v.u = v.v = 0;
    }
}

function disturb(v, disturbance, size) {
    --size;
    if (!v.edge) v.z = disturbance;
   ...