media/js/terrain1.js @ 749ec5a03533

Recursive MPD
author Steve Losh <steve@stevelosh.com>
date Sat, 05 Mar 2016 21:26:30 +0000
parents e2b8f5dc9ae4
children 2d9281a1f7e7
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
var width = exports.width = 610;
var height = exports.height = 400;
var wireframe = exports.wireframe = true;
var wireframeWidth = exports.wireframeWidth = 1.2;
var terrainHeight = exports.terrainHeight = 50;
var terrainSize = exports.terrainSize = 100;
void 0;
void 0;
void 0;
void 0;
void 0;
void 0;
var l = exports.l = function l(v) {
    return console.log(v);
};
var midpoint = exports.midpoint = function midpoint(a, b) {
    return (a + b) / 2;
};
var average2 = exports.average2 = function average2(a, b) {
    return (a + b) / 2;
};
var average4 = exports.average4 = function average4(a, b, c, d) {
    return (a + b + c + d) / 4;
};
var safeAverage = exports.safeAverage = function safeAverage(a, b, c, d) {
    return function () {
        var totalø1 = 0;
        var countø1 = 0;
        a ? (function () {
            totalø1 = totalø1 + a;
            return countø1 = countø1 + 1;
        })() : void 0;
        b ? (function () {
            totalø1 = totalø1 + b;
            return countø1 = countø1 + 1;
        })() : void 0;
        c ? (function () {
            totalø1 = totalø1 + c;
            return countø1 = countø1 + 1;
        })() : void 0;
        d ? (function () {
            totalø1 = totalø1 + d;
            return countø1 = countø1 + 1;
        })() : void 0;
        return totalø1 / countø1;
    }.call(this);
};
var rand = exports.rand = function rand() {
    return Math.random();
};
var randAroundZero = exports.randAroundZero = function randAroundZero(spread) {
    return spread * rand() * 2 - spread;
};
var jitter = exports.jitter = function jitter(value, spread) {
    return value + randAroundZero(spread);
};
void 0;
var heightmapGetSafe = exports.heightmapGetSafe = function heightmapGetSafe(hm, x, y) {
    return 0 <= x && x <= hm.last && (0 <= y && y <= hm.last) ? (function () {
        return hm[y * hm.resolution + x];
    })() : void 0;
};
void 0;
var normalize = exports.normalize = function normalize(hm) {
    return function () {
        var maxø1 = 0 - Infinity;
        var minø1 = Infinity;
        (function () {
            var G__1ø1 = hm.length;
            return function loop() {
                var recur = loop;
                var iø1 = 0;
                do {
                    recur = iø1 < G__1ø1 ? (function () {
                        (function () {
                            var elø1 = hm[iø1];
                            maxø1 < elø1 ? (function () {
                                return maxø1 = elø1;
                            })() : void 0;
                            return minø1 > elø1 ? (function () {
                                return minø1 = elø1;
                            })() : void 0;
                        }.call(this));
                        return loop[0] = 1 + iø1, loop;
                    })() : void 0;
                } while (iø1 = loop[0], recur === loop);
                return recur;
            }.call(this);
        }.call(this));
        return function () {
            var spanø1 = maxø1 - minø1;
            return function () {
                var G__2ø1 = hm.length;
                return function loop() {
                    var recur = loop;
                    var iø1 = 0;
                    do {
                        recur = iø1 < G__2ø1 ? (function () {
                            hm[iø1] = (hm[iø1] - minø1) / spanø1;
                            return loop[0] = 1 + iø1, loop;
                        })() : void 0;
                    } while (iø1 = loop[0], recur === loop);
                    return recur;
                }.call(this);
            }.call(this);
        }.call(this);
    }.call(this);
};
var zeroHeightmap = exports.zeroHeightmap = function zeroHeightmap(heightmap) {
    (function () {
        var G__3ø1 = heightmap.length;
        return function loop() {
            var recur = loop;
            var iø1 = 0;
            do {
                recur = iø1 < G__3ø1 ? (function () {
                    heightmap[iø1] = 0;
                    return loop[0] = 1 + iø1, loop;
                })() : void 0;
            } while (iø1 = loop[0], recur === loop);
            return recur;
        }.call(this);
    }.call(this));
    return heightmap;
};
var makeHeightmap = exports.makeHeightmap = function makeHeightmap(exponent) {
    return function () {
        var resolutionø1 = 1 + Math.pow(2, exponent);
        l('Creating ' + resolutionø1 + ' by ' + resolutionø1 + ' heightmap...');
        var heightmap = new Array(resolutionø1 * resolutionø1);
        heightmap.resolution = resolutionø1;
        heightmap.exponent = exponent;
        heightmap.last = resolutionø1 - 1;
        return zeroHeightmap(heightmap);
    }.call(this);
};
var randomNoise = exports.randomNoise = function randomNoise(heightmap) {
    return function () {
        var G__4ø1 = heightmap.length;
        return function loop() {
            var recur = loop;
            var iø1 = 0;
            do {
                recur = iø1 < G__4ø1 ? (function () {
                    heightmap[iø1] = rand();
                    return loop[0] = 1 + iø1, loop;
                })() : void 0;
            } while (iø1 = loop[0], recur === loop);
            return recur;
        }.call(this);
    }.call(this);
};
var mpdInitCorners = exports.mpdInitCorners = function mpdInitCorners(heightmap) {
    heightmap[0 * heightmap.resolution + 0] = rand();
    heightmap[heightmap.last * heightmap.resolution + 0] = rand();
    heightmap[0 * heightmap.resolution + heightmap.last] = rand();
    return heightmap[heightmap.last * heightmap.resolution + heightmap.last] = rand();
};
var mpdDisplace = exports.mpdDisplace = function mpdDisplace(heightmap, lx, rx, by, ty, spread) {
    return function () {
        var cxø1 = midpoint(lx, rx);
        var cyø1 = midpoint(by, ty);
        var bottomLeftø1 = heightmap[by * heightmap.resolution + lx];
        var bottomRightø1 = heightmap[by * heightmap.resolution + rx];
        var topLeftø1 = heightmap[ty * heightmap.resolution + lx];
        var topRightø1 = heightmap[ty * heightmap.resolution + rx];
        var topø1 = average2(topLeftø1, topRightø1);
        var leftø1 = average2(bottomLeftø1, topLeftø1);
        var bottomø1 = average2(bottomLeftø1, bottomRightø1);
        var rightø1 = average2(bottomRightø1, topRightø1);
        var centerø1 = average4(topø1, leftø1, bottomø1, rightø1);
        heightmap[by * heightmap.resolution + cxø1] = jitter(bottomø1, spread);
        heightmap[ty * heightmap.resolution + cxø1] = jitter(topø1, spread);
        heightmap[cyø1 * heightmap.resolution + lx] = jitter(leftø1, spread);
        heightmap[cyø1 * heightmap.resolution + rx] = jitter(rightø1, spread);
        return heightmap[cyø1 * heightmap.resolution + cxø1] = jitter(centerø1, spread);
    }.call(this);
};
var midpointDisplacement = exports.midpointDisplacement = function midpointDisplacement(heightmap) {
    mpdInitCorners(heightmap);
    (function loop() {
        var recur = loop;
        var iterø1 = 0;
        var spreadø1 = 0.3;
        do {
            recur = iterø1 < heightmap.exponent ? (function () {
                (function () {
                    var chunksø1 = Math.pow(2, iterø1);
                    var chunkWidthø1 = (heightmap.resolution - 1) / chunksø1;
                    return function () {
                        var G__5ø1 = chunksø1;
                        return function () {
                            var G__6ø1 = G__5ø1;
                            return function loop() {
                                var recur = loop;
                                var xchunkø1 = 0;
                                do {
                                    recur = xchunkø1 < G__6ø1 ? (function () {
                                        (function () {
                                            var G__7ø1 = G__5ø1;
                                            return function loop() {
                                                var recur = loop;
                                                var ychunkø1 = 0;
                                                do {
                                                    recur = ychunkø1 < G__7ø1 ? (function () {
                                                        (function () {
                                                            var leftXø1 = chunkWidthø1 * xchunkø1;
                                                            var rightXø1 = leftXø1 + chunkWidthø1;
                                                            var bottomYø1 = chunkWidthø1 * ychunkø1;
                                                            var topYø1 = bottomYø1 + chunkWidthø1;
                                                            return mpdDisplace(heightmap, leftXø1, rightXø1, bottomYø1, topYø1, spreadø1);
                                                        }.call(this));
                                                        return loop[0] = 1 + ychunkø1, loop;
                                                    })() : void 0;
                                                } while (ychunkø1 = loop[0], recur === loop);
                                                return recur;
                                            }.call(this);
                                        }.call(this));
                                        return loop[0] = 1 + xchunkø1, loop;
                                    })() : void 0;
                                } while (xchunkø1 = loop[0], recur === loop);
                                return recur;
                            }.call(this);
                        }.call(this);
                    }.call(this);
                }.call(this));
                return loop[0] = 1 + iterø1, loop[1] = spreadø1 * 0.5, loop;
            })() : void 0;
        } while (iterø1 = loop[0], spreadø1 = loop[1], recur === loop);
        return recur;
    }.call(this));
    return normalize(heightmap);
};
var midpointDisplacementFinal = exports.midpointDisplacementFinal = function midpointDisplacementFinal(heightmap) {
    mpdInitCorners(heightmap);
    (function loop() {
        var recur = loop;
        var iterø1 = 0;
        var spreadø1 = 0 + $('#input-starting-spread').val();
        do {
            recur = iterø1 < heightmap.exponent ? (function () {
                (function () {
                    var chunksø1 = Math.pow(2, iterø1);
                    var chunkWidthø1 = (heightmap.resolution - 1) / chunksø1;
                    return function () {
                        var G__8ø1 = chunksø1;
                        return function () {
                            var G__9ø1 = G__8ø1;
                            return function loop() {
                                var recur = loop;
                                var xchunkø1 = 0;
                                do {
                                    recur = xchunkø1 < G__9ø1 ? (function () {
                                        (function () {
                                            var G__10ø1 = G__8ø1;
                                            return function loop() {
                                                var recur = loop;
                                                var ychunkø1 = 0;
                                                do {
                                                    recur = ychunkø1 < G__10ø1 ? (function () {
                                                        (function () {
                                                            var leftXø1 = chunkWidthø1 * xchunkø1;
                                                            var rightXø1 = leftXø1 + chunkWidthø1;
                                                            var bottomYø1 = chunkWidthø1 * ychunkø1;
                                                            var topYø1 = bottomYø1 + chunkWidthø1;
                                                            return mpdDisplace(heightmap, leftXø1, rightXø1, bottomYø1, topYø1, spreadø1);
                                                        }.call(this));
                                                        return loop[0] = 1 + ychunkø1, loop;
                                                    })() : void 0;
                                                } while (ychunkø1 = loop[0], recur === loop);
                                                return recur;
                                            }.call(this);
                                        }.call(this));
                                        return loop[0] = 1 + xchunkø1, loop;
                                    })() : void 0;
                                } while (xchunkø1 = loop[0], recur === loop);
                                return recur;
                            }.call(this);
                        }.call(this);
                    }.call(this);
                }.call(this));
                return loop[0] = 1 + iterø1, loop[1] = spreadø1 * (0 + $('#input-spread-reduction').val()), loop;
            })() : void 0;
        } while (iterø1 = loop[0], spreadø1 = loop[1], recur === loop);
        return recur;
    }.call(this));
    return normalize(heightmap);
};
var mpdDisplaceD2 = exports.mpdDisplaceD2 = function mpdDisplaceD2(heightmap, lx, rx, by, ty, spread) {
    return function () {
        var cxø1 = midpoint(lx, rx);
        var cyø1 = midpoint(by, ty);
        var bottomLeftø1 = heightmap[by * heightmap.resolution + lx];
        var bottomRightø1 = heightmap[by * heightmap.resolution + rx];
        var topLeftø1 = heightmap[ty * heightmap.resolution + lx];
        var topRightø1 = heightmap[ty * heightmap.resolution + rx];
        var topø1 = average2(topLeftø1, topRightø1);
        var leftø1 = average2(bottomLeftø1, topLeftø1);
        var bottomø1 = average2(bottomLeftø1, bottomRightø1);
        var rightø1 = average2(bottomRightø1, topRightø1);
        heightmap[by * heightmap.resolution + cxø1] = jitter(bottomø1, spread);
        heightmap[ty * heightmap.resolution + cxø1] = jitter(topø1, spread);
        heightmap[cyø1 * heightmap.resolution + lx] = jitter(leftø1, spread);
        return heightmap[cyø1 * heightmap.resolution + rx] = jitter(rightø1, spread);
    }.call(this);
};
var midpointDisplacementD1 = exports.midpointDisplacementD1 = function midpointDisplacementD1(heightmap) {
    return mpdInitCorners(heightmap);
};
var midpointDisplacementD2 = exports.midpointDisplacementD2 = function midpointDisplacementD2(heightmap) {
    mpdInitCorners(heightmap);
    return mpdDisplaceD2(heightmap, 0, heightmap.last, 0, heightmap.last, 0.1);
};
var midpointDisplacementD3 = exports.midpointDisplacementD3 = function midpointDisplacementD3(heightmap) {
    mpdInitCorners(heightmap);
    return mpdDisplace(heightmap, 0, heightmap.last, 0, heightmap.last, 0.1);
};
var makeDirectionalLight = exports.makeDirectionalLight = function makeDirectionalLight() {
    return function () {
        var lightø1 = new THREE.DirectionalLight(16777215, 1);
        lightø1.position.set(100, 0, 150);
        return lightø1;
    }.call(this);
};
var makeCamera = exports.makeCamera = function makeCamera() {
    return function () {
        var cameraø1 = new THREE.PerspectiveCamera(55, width / height, 0.1, 1000);
        cameraø1.position.set(0, -100, 150);
        return cameraø1;
    }.call(this);
};
var makeRenderer = exports.makeRenderer = function makeRenderer() {
    return function () {
        var rendererø1 = new THREE.WebGLRenderer({ 'antialias': false });
        rendererø1.setClearColor(16777215);
        rendererø1.setSize(width, height);
        rendererø1.setPixelRatio(2);
        return rendererø1;
    }.call(this);
};
var makeGeometry = exports.makeGeometry = function makeGeometry(heightmap) {
    return function () {
        var geometryø1 = new THREE.PlaneGeometry(terrainSize, terrainSize, heightmap.resolution - 1, heightmap.resolution - 1);
        geometryø1.dynamic = true;
        return geometryø1;
    }.call(this);
};
var makeControls = exports.makeControls = function makeControls(camera, renderer) {
    return function () {
        var controlsø1 = new THREE.TrackballControls(camera, renderer.domElement);
        controlsø1.rotateSpeed = 1.4;
        controlsø1.zoomSpeed = 0.5;
        controlsø1.staticMoving = true;
        controlsø1.dynamicDampingFactor = 0.3;
        return controlsø1;
    }.call(this);
};
var makePlane = exports.makePlane = function makePlane(geometry) {
    return function () {
        var materialø1 = new THREE.MeshLambertMaterial({
            'wireframe': wireframe,
            'wireframeLinewidth': wireframeWidth,
            'color': 47872
        });
        return new THREE.Mesh(geometry, materialø1);
    }.call(this);
};
var attachToDom = exports.attachToDom = function attachToDom(renderer, elName, refreshFn) {
    return function () {
        var containerø1 = document.getElementById(elName);
        var settingsø1 = document.createElement('div');
        var refreshButtonø1 = document.createElement('button');
        var buttonTextø1 = document.createTextNode('Refresh');
        var cancelScrollø1 = function (e) {
            return e.preventDefault();
        };
        refreshButtonø1.onclick = refreshFn;
        renderer.domElement.onmousewheel = cancelScrollø1;
        renderer.domElement.addEventListener('MozMousePixelScroll', cancelScrollø1, false);
        refreshButtonø1.appendChild(buttonTextø1);
        containerø1.appendChild(renderer.domElement);
        containerø1.appendChild(settingsø1);
        return settingsø1.appendChild(refreshButtonø1);
    }.call(this);
};
var updateGeometry = exports.updateGeometry = function updateGeometry(geometry, heightmap) {
    (function () {
        var G__11ø1 = geometry.vertices.length;
        return function loop() {
            var recur = loop;
            var iø1 = 0;
            do {
                recur = iø1 < G__11ø1 ? (function () {
                    geometry.vertices[iø1].z = terrainHeight * heightmap[iø1];
                    return loop[0] = 1 + iø1, loop;
                })() : void 0;
            } while (iø1 = loop[0], recur === loop);
            return recur;
        }.call(this);
    }.call(this));
    geometry.verticesNeedUpdate = true;
    geometry.computeFaceNormals();
    geometry.computeVertexNormals();
    geometry.computeMorphNormals();
    return geometry;
};
var makeDemo = exports.makeDemo = function makeDemo(elementId, algorithm, size) {
    var scene = new THREE.Scene();
    scene.add(new THREE.AxisHelper(100));
    var clock = new THREE.Clock();
    var camera = makeCamera();
    var renderer = makeRenderer();
    var geometry = makeGeometry(makeHeightmap(size));
    scene.add(makeDirectionalLight());
    scene.add(new THREE.AmbientLight(16777215, 0.05));
    scene.add(makePlane(geometry));
    var refresh = function refresh() {
        l('Refreshing ========================================');
        return function () {
            var heightmapø1 = makeHeightmap(size);
            l('Generating terrain...');
            (function () {
                var G__12ø1 = new Date().getTime();
                var G__14ø1 = (function () {
                    return algorithm(heightmapø1);
                })();
                var G__13ø1 = new Date().getTime();
                l('Elapsed time: ' + (G__13ø1 - G__12ø1) + 'ms.');
                return G__14ø1;
            }.call(this));
            l('Refreshing geometry...');
            (function () {
                var G__15ø1 = new Date().getTime();
                var G__17ø1 = (function () {
                    return updateGeometry(geometry, heightmapø1);
                })();
                var G__16ø1 = new Date().getTime();
                l('Elapsed time: ' + (G__16ø1 - G__15ø1) + 'ms.');
                return G__17ø1;
            }.call(this));
            return l('Done!');
        }.call(this);
    };
    attachToDom(renderer, elementId, refresh);
    var controls = makeControls(camera, renderer);
    var render = function render() {
        return function () {
            var deltaø1 = clock.getDelta();
            requestAnimationFrame(render);
            controls.update(deltaø1);
            return renderer.render(scene, camera);
        }.call(this);
    };
    render();
    return void 0;
};
var makeFinal = exports.makeFinal = function makeFinal(elementId) {
    var scene = new THREE.Scene();
    scene.add(new THREE.AxisHelper(100));
    var clock = new THREE.Clock();
    var camera = makeCamera();
    var renderer = makeRenderer();
    var heightmap = makeHeightmap($('#input-exponent').val());
    var geometry = makeGeometry(heightmap);
    var plane = makePlane(geometry);
    scene.add(makeDirectionalLight());
    scene.add(new THREE.AmbientLight(16777215, 0.05));
    scene.add(plane);
    var refresh = function refresh() {
        l('Refreshing ========================================');
        scene.remove(plane);
        heightmap = makeHeightmap($('#input-exponent').val());
        geometry = makeGeometry(heightmap);
        plane = makePlane(geometry);
        scene.add(plane);
        l('Generating terrain...');
        (function () {
            var G__18ø1 = new Date().getTime();
            var G__20ø1 = (function () {
                return midpointDisplacementFinal(heightmap);
            })();
            var G__19ø1 = new Date().getTime();
            l('Elapsed time: ' + (G__19ø1 - G__18ø1) + 'ms.');
            return G__20ø1;
        }.call(this));
        l('Refreshing geometry...');
        (function () {
            var G__21ø1 = new Date().getTime();
            var G__23ø1 = (function () {
                return updateGeometry(geometry, heightmap);
            })();
            var G__22ø1 = new Date().getTime();
            l('Elapsed time: ' + (G__22ø1 - G__21ø1) + 'ms.');
            return G__23ø1;
        }.call(this));
        return l('Done!');
    };
    attachToDom(renderer, elementId, refresh);
    var controls = makeControls(camera, renderer);
    var render = function render() {
        return function () {
            var deltaø1 = clock.getDelta();
            requestAnimationFrame(render);
            controls.update(deltaø1);
            return renderer.render(scene, camera);
        }.call(this);
    };
    render();
    return void 0;
};
var run = exports.run = function run() {
    makeDemo('demo-random', randomNoise, 7);
    makeDemo('demo-mpd-1', midpointDisplacementD1, 2);
    makeDemo('demo-mpd-2', midpointDisplacementD2, 2);
    makeDemo('demo-mpd-3', midpointDisplacementD3, 2);
    makeDemo('demo-mpd-4', midpointDisplacement, 3);
    return makeFinal('demo-final');
};
$(run);


},{}]},{},[1]);