--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile Sun Feb 28 11:51:50 2016 +0000
@@ -0,0 +1,26 @@
+.PHONY: all clean generate regen serve deploy
+
+wisps := $(shell ffind --literal '.wisp')
+javascripts := $(subst .wisp,.js,$(wisps))
+
+all: media/js/terrain1.js
+
+media/js/wisp/%.js: media/js/wisp/%.wisp
+ cat $< | wisp > $@
+
+media/js/terrain1.js: $(javascripts)
+ browserify media/js/wisp/terrain1.js -o $@
+
+clean:
+ rm -rf ./deploy
+
+generate: all
+ hyde -g -s .
+
+serve:
+ hyde -w -s . -k
+
+regen: clean generate
+
+deploy: generate
+ rsync -avz ./deploy/ sl:/var/www/stevelosh.com
--- a/content/blog/2016/02/midpoint-displacement.html Fri Feb 19 19:48:12 2016 +0000
+++ b/content/blog/2016/02/midpoint-displacement.html Sun Feb 28 11:51:50 2016 +0000
@@ -13,10 +13,6 @@
<script data-cfasync="false" src="/media/js/TrackballControls.js"></script>
<script data-cfasync="false" src="/media/js/terrain1.js"></script>
-
- <script type="text/javascript">
- $(function () { run(); });
- </script>
{% endblock extra_js %}
{% block article %}
--- a/fabfile.py Fri Feb 19 19:48:12 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-from fabric.api import *
-import os
-import fabric.contrib.project as project
-
-PROD = 'sl'
-DEST_PATH = '/var/www/stevelosh.com/'
-ROOT_PATH = os.path.abspath(os.path.dirname(__file__))
-DEPLOY_PATH = os.path.join(ROOT_PATH, 'deploy')
-
-def clean():
- local('rm -rf ./deploy')
-
-def generate():
- local('hyde -g -s .')
-
-def regen():
- clean()
- generate()
-
-def serve():
- local('hyde -w -s . -k')
-
-def reserve():
- regen()
- serve()
-
-def smush():
- local('smusher ./media/images')
-
-@hosts(PROD)
-def publish():
- regen()
- project.rsync_project(
- remote_dir=DEST_PATH,
- local_dir=DEPLOY_PATH.rstrip('/') + '/',
- delete=True
- )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/media/js/terrain1.js Sun Feb 28 11:51:50 2016 +0000
@@ -0,0 +1,523 @@
+(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]);
--- a/media/js/terrain1.wisp Fri Feb 19 19:48:12 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,391 +0,0 @@
-; Constants -------------------------------------------------------------------
-(set! exports {}) ; fuck off wisp
-(def width 610)
-(def height 400)
-(def wireframe true)
-(def wireframe-width 1.2)
-(def terrain-height 50)
-(def terrain-size 100)
-
-; General Utilities -----------------------------------------------------------
-(defmacro when [condition & body]
- `(if ~condition
- (do ~@body)))
-
-(defmacro do-times [varname limit & body]
- (let [end (gensym)]
- `(let [~end ~limit]
- (loop [~varname 0]
- (when (< ~varname ~end)
- ~@body
- (recur (+ 1 ~varname)))))))
-
-(defmacro do-nested [xname yname width & body]
- (let [iterations (gensym)]
- `(let [~iterations ~width]
- (do-times ~xname ~iterations
- (do-times ~yname ~iterations
- ~@body)))))
-
-(defmacro inc! [place]
- `(set! ~place (+ ~place 1)))
-
-(defmacro add! [place amount]
- `(set! ~place (+ ~place ~amount)))
-
-(defmacro time [& body]
- (let [start (gensym)
- end (gensym)
- result (gensym)]
- `(let [~start (.getTime (new Date))
- ~result (do ~@body)
- ~end (.getTime (new Date))]
- (l (+ "Elapsed time: " (- ~end ~start) "ms."))
- ~result)))
-
-(defn l [v]
- (console.log v))
-
-
-(defn midpoint [a b]
- (/ (+ a b) 2))
-
-(defn average2 [a b]
- (/ (+ a b) 2))
-
-(defn average4 [a b c d]
- (/ (+ a b c d) 4))
-
-(defn safe-average [a b c d]
- (let [total 0 count 0]
- (when a (add! total a) (inc! count))
- (when b (add! total b) (inc! count))
- (when c (add! total c) (inc! count))
- (when d (add! total d) (inc! count))
- (/ total count)))
-
-
-(defn rand []
- (Math.random))
-
-(defn rand-around-zero [spread]
- (- (* spread (rand) 2) spread))
-
-
-(defn jitter [value spread]
- (+ value (rand-around-zero spread)))
-
-
-; Heightmap Helpers -----------------------------------------------------------
-(defmacro heightmap-get [hm x y]
- `(aget ~hm (+ (* ~y (.-resolution ~hm)) ~x)))
-
-(defn heightmap-get-safe [hm x y]
- (when (and (<= 0 x hm.last)
- (<= 0 y hm.last))
- (heightmap-get hm x y)))
-
-(defmacro heightmap-set! [hm x y val]
- `(set! (heightmap-get ~hm ~x ~y) ~val))
-
-
-(defn normalize [hm]
- (let [max (- Infinity)
- min Infinity]
- (do-times i hm.length
- (let [el (aget hm i)]
- (when (< max el) (set! max el))
- (when (> min el) (set! min el))))
- (let [span (- max min)]
- (do-times i hm.length
- (set! (aget hm i)
- (/ (- (aget hm i) min)
- span))))))
-
-(defn zero-heightmap [heightmap]
- (do-times i heightmap.length
- (set! (aget heightmap i) 0.0))
- heightmap)
-
-(defn make-heightmap [exponent]
- (let [resolution (+ 1 (Math.pow 2 exponent))]
- (l (+ "Creating " resolution " by " resolution " heightmap..."))
- (def heightmap
- (new Array (* resolution resolution)))
- (set! heightmap.resolution resolution)
- (set! heightmap.exponent exponent)
- (set! heightmap.last (- resolution 1))
- (zero-heightmap heightmap)))
-
-
-; Random Noise ----------------------------------------------------------------
-(defn random-noise [heightmap]
- (do-times i heightmap.length
- (set! (aget heightmap i) (rand))))
-
-
-; Midpoint Displacement -------------------------------------------------------
-(defn mpd-init-corners [heightmap]
- (heightmap-set! heightmap 0 0 (rand))
- (heightmap-set! heightmap 0 heightmap.last (rand))
- (heightmap-set! heightmap heightmap.last 0 (rand))
- (heightmap-set! heightmap heightmap.last heightmap.last (rand)))
-
-(defn mpd-displace [heightmap lx rx by ty spread]
- (let [cx (midpoint lx rx)
- cy (midpoint by ty)
-
- bottom-left (heightmap-get heightmap lx by)
- bottom-right (heightmap-get heightmap rx by)
- top-left (heightmap-get heightmap lx ty)
- top-right (heightmap-get heightmap rx ty)
-
- top (average2 top-left top-right)
- left (average2 bottom-left top-left)
- bottom (average2 bottom-left bottom-right)
- right (average2 bottom-right top-right)
- center (average4 top left bottom right)]
- (heightmap-set! heightmap cx by (jitter bottom spread))
- (heightmap-set! heightmap cx ty (jitter top spread))
- (heightmap-set! heightmap lx cy (jitter left spread))
- (heightmap-set! heightmap rx cy (jitter right spread))
- (heightmap-set! heightmap cx cy (jitter center spread))))
-
-(defn midpoint-displacement [heightmap]
- (mpd-init-corners heightmap)
- ; (mpd-displace heightmap 0 heightmap.last 0 heightmap.last 0.1)
- (loop [iter 0
- spread 0.3]
- (when (< iter heightmap.exponent)
- (let [chunks (Math.pow 2 iter)
- chunk-width (/ (- heightmap.resolution 1) chunks)]
- (do-nested xchunk ychunk chunks
- (let [left-x (* chunk-width xchunk)
- right-x (+ left-x chunk-width)
- bottom-y (* chunk-width ychunk)
- top-y (+ bottom-y chunk-width)]
- (mpd-displace heightmap left-x right-x bottom-y top-y spread))))
- (recur (+ 1 iter) (* spread 0.5))))
- (normalize heightmap))
-
-
-(defn midpoint-displacement-final [heightmap]
- (mpd-init-corners heightmap)
- ; (let [spread ])
- (loop [iter 0
- spread (+ 0 (.val ($ "#input-starting-spread")))]
- (when (< iter heightmap.exponent)
- (let [chunks (Math.pow 2 iter)
- chunk-width (/ (- heightmap.resolution 1) chunks)]
- (do-nested xchunk ychunk chunks
- (let [left-x (* chunk-width xchunk)
- right-x (+ left-x chunk-width)
- bottom-y (* chunk-width ychunk)
- top-y (+ bottom-y chunk-width)]
- (mpd-displace heightmap left-x right-x bottom-y top-y spread))))
- (recur (+ 1 iter) (* spread
- (+ 0 (.val ($ "#input-spread-reduction")))))))
- (normalize heightmap))
-
-
-(defn mpd-displace-d2 [heightmap lx rx by ty spread]
- (let [cx (midpoint lx rx)
- cy (midpoint by ty)
-
- bottom-left (heightmap-get heightmap lx by)
- bottom-right (heightmap-get heightmap rx by)
- top-left (heightmap-get heightmap lx ty)
- top-right (heightmap-get heightmap rx ty)
-
- top (average2 top-left top-right)
- left (average2 bottom-left top-left)
- bottom (average2 bottom-left bottom-right)
- right (average2 bottom-right top-right)]
- (heightmap-set! heightmap cx by (jitter bottom spread))
- (heightmap-set! heightmap cx ty (jitter top spread))
- (heightmap-set! heightmap lx cy (jitter left spread))
- (heightmap-set! heightmap rx cy (jitter right spread))))
-
-(defn midpoint-displacement-d1 [heightmap]
- (mpd-init-corners heightmap))
-
-(defn midpoint-displacement-d2 [heightmap]
- (mpd-init-corners heightmap)
- (mpd-displace-d2 heightmap
- 0 heightmap.last
- 0 heightmap.last
- 0.1))
-
-(defn midpoint-displacement-d3 [heightmap]
- (mpd-init-corners heightmap)
- (mpd-displace heightmap
- 0 heightmap.last
- 0 heightmap.last
- 0.1))
-
-
-
-; Three.js Helpers ------------------------------------------------------------
-(defn make-directional-light []
- (let [light (new THREE.DirectionalLight 0xffffff 1)]
- (light.position.set 100 0 150)
- light))
-
-(defn make-camera []
- (let [camera (new THREE.PerspectiveCamera
- 55,
- (/ width height)
- 0.1,
- 1000)]
- (camera.position.set 0 -100 150)
- camera))
-
-(defn make-renderer []
- (let [renderer (new THREE.WebGLRenderer {:antialias false})]
- (renderer.setClearColor 0xffffff)
- (renderer.setSize width height)
- (renderer.setPixelRatio 2)
- renderer))
-
-(defn make-geometry [heightmap]
- (let [geometry (new THREE.PlaneGeometry
- terrain-size
- terrain-size
- (- heightmap.resolution 1)
- (- heightmap.resolution 1))]
- (set! geometry.dynamic true)
- geometry))
-
-(defn make-controls [camera renderer]
- (let [controls (new THREE.TrackballControls camera renderer.domElement)]
- (set! controls.rotateSpeed 1.4)
- (set! controls.zoomSpeed 0.5)
- (set! controls.staticMoving true)
- (set! controls.dynamicDampingFactor 0.3)
- controls))
-
-(defn make-plane [geometry]
- (let [material (new THREE.MeshLambertMaterial
- {:wireframe wireframe
- :wireframeLinewidth wireframe-width
- :color 0x00bb00})]
- (new THREE.Mesh geometry material)))
-
-
-(defn attach-to-dom [renderer el-name refresh-fn]
- (let [container (document.getElementById el-name)
- settings (document.createElement "div")
- refresh-button (document.createElement "button")
- button-text (document.createTextNode "Refresh")
- cancel-scroll (fn [e] (.preventDefault e))]
- (set! refresh-button.onclick refresh-fn)
- (set! renderer.domElement.onmousewheel cancel-scroll)
- (renderer.domElement.addEventListener "MozMousePixelScroll" cancel-scroll false)
- (.appendChild refresh-button button-text)
- (.appendChild container renderer.domElement)
- (.appendChild container settings)
- (.appendChild settings refresh-button)))
-
-(defn update-geometry [geometry heightmap]
- (do-times i geometry.vertices.length
- (set! (.-z (aget geometry.vertices i))
- (* terrain-height (aget heightmap i))))
- (set! geometry.verticesNeedUpdate true)
- (geometry.computeFaceNormals)
- (geometry.computeVertexNormals)
- (geometry.computeMorphNormals)
- geometry)
-
-
-; Main ------------------------------------------------------------------------
-(defn make-demo [element-id algorithm size]
- (def scene (new THREE.Scene))
- (scene.add (new THREE.AxisHelper 100))
-
- (def clock (new THREE.Clock))
- (def camera (make-camera))
- (def renderer (make-renderer))
- (def geometry (make-geometry (make-heightmap size)))
-
- (scene.add (make-directional-light))
- (scene.add (new THREE.AmbientLight 0xffffff 0.05))
- (scene.add (make-plane geometry))
-
- (defn refresh []
- (l "Refreshing ========================================")
- (let [heightmap (make-heightmap size)]
- (l "Generating terrain...")
- (time (algorithm heightmap))
- (l "Refreshing geometry...")
- (time (update-geometry geometry heightmap))
- (l "Done!")))
-
- (attach-to-dom renderer element-id refresh)
- (def controls (make-controls camera renderer))
-
- (defn render []
- (let [delta (clock.getDelta)]
- (requestAnimationFrame render)
- (.update controls delta)
- (renderer.render scene camera)))
-
- (render)
-
- nil)
-
-(defn make-final [element-id]
- (def scene (new THREE.Scene))
- (scene.add (new THREE.AxisHelper 100))
-
- (def clock (new THREE.Clock))
- (def camera (make-camera))
- (def renderer (make-renderer))
- (def heightmap (make-heightmap (.val ($ "#input-exponent"))))
- (def geometry (make-geometry heightmap))
- (def plane (make-plane geometry))
-
- (scene.add (make-directional-light))
- (scene.add (new THREE.AmbientLight 0xffffff 0.05))
- (scene.add plane)
-
- (defn refresh []
- (l "Refreshing ========================================")
- (scene.remove plane)
- (set! heightmap (make-heightmap (.val ($ "#input-exponent"))))
- (set! geometry (make-geometry heightmap))
- (set! plane (make-plane geometry))
- (scene.add plane)
- (l "Generating terrain...")
- (time (midpoint-displacement-final heightmap))
- (l "Refreshing geometry...")
- (time (update-geometry geometry heightmap))
- (l "Done!"))
-
- (attach-to-dom renderer element-id refresh)
- (def controls (make-controls camera renderer))
-
- (defn render []
- (let [delta (clock.getDelta)]
- (requestAnimationFrame render)
- (.update controls delta)
- (renderer.render scene camera)))
-
- (render)
-
- nil)
-
-
-(defn run []
- (make-demo "demo-random" random-noise 7)
- (make-demo "demo-mpd-1" midpoint-displacement-d1 2)
- (make-demo "demo-mpd-2" midpoint-displacement-d2 2)
- (make-demo "demo-mpd-3" midpoint-displacement-d3 2)
- (make-demo "demo-mpd-4" midpoint-displacement 3)
- (make-final "demo-final")
- ; (make-demo "demo-midpoint" midpoint-displacement)
- ; (make-demo "demo-diamond" diamond-square)
-
- )
-
-
-; vim: lw+=do-times lw+=do-nested :
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/media/js/wisp/terrain1.js Sun Feb 28 11:51:50 2016 +0000
@@ -0,0 +1,520 @@
+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);
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImFub255bW91cy53aXNwIl0sIm5hbWVzIjpbIndpZHRoIiwiZXhwb3J0cyIsImhlaWdodCIsIndpcmVmcmFtZSIsIndpcmVmcmFtZVdpZHRoIiwidGVycmFpbkhlaWdodCIsInRlcnJhaW5TaXplIiwibCIsInYiLCJjb25zb2xlIiwibG9nIiwibWlkcG9pbnQiLCJhIiwiYiIsImF2ZXJhZ2UyIiwiYXZlcmFnZTQiLCJjIiwiZCIsInNhZmVBdmVyYWdlIiwidG90YWzDuDEiLCJjb3VudMO4MSIsInJhbmQiLCJNYXRoIiwicmFuZG9tIiwicmFuZEFyb3VuZFplcm8iLCJzcHJlYWQiLCJqaXR0ZXIiLCJ2YWx1ZSIsImhlaWdodG1hcEdldFNhZmUiLCJobSIsIngiLCJ5IiwibGFzdCIsIm5vcm1hbGl6ZSIsIm1heMO4MSIsIkluZmluaXR5IiwibWluw7gxIiwibGVuZ3RoIiwiacO4MSIsImVsw7gxIiwic3BhbsO4MSIsInplcm9IZWlnaHRtYXAiLCJoZWlnaHRtYXAiLCJtYWtlSGVpZ2h0bWFwIiwiZXhwb25lbnQiLCJyZXNvbHV0aW9uw7gxIiwicG93IiwiQXJyYXkiLCJyZXNvbHV0aW9uIiwicmFuZG9tTm9pc2UiLCJtcGRJbml0Q29ybmVycyIsIm1wZERpc3BsYWNlIiwibHgiLCJyeCIsImJ5IiwidHkiLCJjeMO4MSIsImN5w7gxIiwiYm90dG9tTGVmdMO4MSIsImJvdHRvbVJpZ2h0w7gxIiwidG9wTGVmdMO4MSIsInRvcFJpZ2h0w7gxIiwidG9ww7gxIiwibGVmdMO4MSIsImJvdHRvbcO4MSIsInJpZ2h0w7gxIiwiY2VudGVyw7gxIiwibWlkcG9pbnREaXNwbGFjZW1lbnQiLCJpdGVyw7gxIiwic3ByZWFkw7gxIiwiY2h1bmtzw7gxIiwiY2h1bmtXaWR0aMO4MSIsInhjaHVua8O4MSIsInljaHVua8O4MSIsImxlZnRYw7gxIiwicmlnaHRYw7gxIiwiYm90dG9tWcO4MSIsInRvcFnDuDEiLCJtaWRwb2ludERpc3BsYWNlbWVudEZpbmFsIiwiJCIsInZhbCIsIm1wZERpc3BsYWNlRDIiLCJtaWRwb2ludERpc3BsYWNlbWVudEQxIiwibWlkcG9pbnREaXNwbGFjZW1lbnREMiIsIm1pZHBvaW50RGlzcGxhY2VtZW50RDMiLCJtYWtlRGlyZWN0aW9uYWxMaWdodCIsImxpZ2h0w7gxIiwiVEhSRUUiLCJEaXJlY3Rpb25hbExpZ2h0IiwicG9zaXRpb24uc2V0IiwibWFrZUNhbWVyYSIsImNhbWVyYcO4MSIsIlBlcnNwZWN0aXZlQ2FtZXJhIiwibWFrZVJlbmRlcmVyIiwicmVuZGVyZXLDuDEiLCJXZWJHTFJlbmRlcmVyIiwic2V0Q2xlYXJDb2xvciIsInNldFNpemUiLCJzZXRQaXhlbFJhdGlvIiwibWFrZUdlb21ldHJ5IiwiZ2VvbWV0cnnDuDEiLCJQbGFuZUdlb21ldHJ5IiwiZHluYW1pYyIsIm1ha2VDb250cm9scyIsImNhbWVyYSIsInJlbmRlcmVyIiwiY29udHJvbHPDuDEiLCJUcmFja2JhbGxDb250cm9scyIsImRvbUVsZW1lbnQiLCJyb3RhdGVTcGVlZCIsInpvb21TcGVlZCIsInN0YXRpY01vdmluZyIsImR5bmFtaWNEYW1waW5nRmFjdG9yIiwibWFrZVBsYW5lIiwiZ2VvbWV0cnkiLCJtYXRlcmlhbMO4MSIsIk1lc2hMYW1iZXJ0TWF0ZXJpYWwiLCJNZXNoIiwiYXR0YWNoVG9Eb20iLCJlbE5hbWUiLCJyZWZyZXNoRm4iLCJjb250YWluZXLDuDEiLCJkb2N1bWVudCIsImdldEVsZW1lbnRCeUlkIiwic2V0dGluZ3PDuDEiLCJjcmVhdGVFbGVtZW50IiwicmVmcmVzaEJ1dHRvbsO4MSIsImJ1dHRvblRleHTDuDEiLCJjcmVhdGVUZXh0Tm9kZSIsImNhbmNlbFNjcm9sbMO4MSIsImUiLCJwcmV2ZW50RGVmYXVsdCIsIm9uY2xpY2siLCJkb21FbGVtZW50Lm9ubW91c2V3aGVlbCIsImRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lciIsImFwcGVuZENoaWxkIiwidXBkYXRlR2VvbWV0cnkiLCJ2ZXJ0aWNlcy5sZW5ndGgiLCJ2ZXJ0aWNlcyIsInoiLCJ2ZXJ0aWNlc05lZWRVcGRhdGUiLCJjb21wdXRlRmFjZU5vcm1hbHMiLCJjb21wdXRlVmVydGV4Tm9ybWFscyIsImNvbXB1dGVNb3JwaE5vcm1hbHMiLCJtYWtlRGVtbyIsImVsZW1lbnRJZCIsImFsZ29yaXRobSIsInNpemUiLCJzY2VuZSIsIlNjZW5lIiwiYWRkIiwiQXhpc0hlbHBlciIsImNsb2NrIiwiQ2xvY2siLCJBbWJpZW50TGlnaHQiLCJyZWZyZXNoIiwiaGVpZ2h0bWFww7gxIiwiY29udHJvbHMiLCJyZW5kZXIiLCJkZWx0YcO4MSIsImdldERlbHRhIiwicmVxdWVzdEFuaW1hdGlvbkZyYW1lIiwidXBkYXRlIiwibWFrZUZpbmFsIiwicGxhbmUiLCJyZW1vdmUiLCJydW4iXSwibWFwcGluZ3MiOiJBQUNBLElBQUtBLEtBQUEsR0FBQUMsT0FBQSxDQUFBRCxLQUFBLEdBQU0sR0FBWDtBQUNBLElBQUtFLE1BQUEsR0FBQUQsT0FBQSxDQUFBQyxNQUFBLEdBQU8sR0FBWixDQURBO0FBRUEsSUFBS0MsU0FBQSxHQUFBRixPQUFBLENBQUFFLFNBQUEsRyxJQUFMLENBRkE7QUFHQSxJQUFLQyxjQUFBLEdBQUFILE9BQUEsQ0FBQUcsY0FBQSxHQUFnQixHQUFyQixDQUhBO0FBSUEsSUFBS0MsYUFBQSxHQUFBSixPQUFBLENBQUFJLGFBQUEsR0FBZSxFQUFwQixDQUpBO0FBS0EsSUFBS0MsV0FBQSxHQUFBTCxPQUFBLENBQUFLLFdBQUEsR0FBYSxHQUFsQixDQUxBO09BQUE7T0FBQTtPQUFBO09BQUE7T0FBQTtPQUFBO0FBMkNBLElBQU1DLENBQUEsR0FBQU4sT0FBQSxDQUFBTSxDQUFBLEdBQU4sU0FBTUEsQ0FBTixDQUFTQyxDQUFULEVBQ0U7QUFBQSxXQUFDQyxPQUFBLENBQVFDLEdBQVQsQ0FBYUYsQ0FBYjtBQUFBLENBREYsQ0EzQ0E7QUErQ0EsSUFBTUcsUUFBQSxHQUFBVixPQUFBLENBQUFVLFFBQUEsR0FBTixTQUFNQSxRQUFOLENBQWdCQyxDQUFoQixFQUFrQkMsQ0FBbEIsRUFDRTtBQUFBLFdB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QVcsWUFBWCxFQUF3QjdFLG9CQUF4QixFQUE4QyxDQUE5QyxFQUpBO0FBQUEsSUFLQSxPQUFDZ0csU0FBRCxDQUFZLFlBQVosRUFMQTtBQUFBLENBREYsQ0F2WEE7QUFtWUNwRixDQUFELENBQUd1RixHQUFIIiwic291cmNlc0NvbnRlbnQiOlsiOyBDb25zdGFudHMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuKGRlZiB3aWR0aCA2MTApXG4oZGVmIGhlaWdodCA0MDApXG4oZGVmIHdpcmVmcmFtZSB0cnVlKVxuKGRlZiB3aXJlZnJhbWUtd2lkdGggMS4yKVxuKGRlZiB0ZXJyYWluLWhlaWdodCA1MClcbihkZWYgdGVycmFpbi1zaXplIDEwMClcblxuOyBHZW5lcmFsIFV0aWxpdGllcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuKGRlZm1hY3JvIHdoZW4gW2NvbmRpdGlvbiAmIGJvZHldXG4gIGAoaWYgfmNvbmRpdGlvblxuICAgICAoZG8gfkBib2R5KSkpXG5cbihkZWZtYWNybyBkby10aW1lcyBbdmFybmFtZSBsaW1pdCAmIGJvZHldXG4gIChsZXQgW2VuZCAoZ2Vuc3ltKV1cbiAgICBgKGxldCBbfmVuZCB+bGltaXRdXG4gICAgICAgKGxvb3AgW352YXJuYW1lIDBdXG4gICAgICAgICAod2hlbiAoPCB+dmFybmFtZSB+ZW5kKVxuICAgICAgICAgICB+QGJvZHlcbiAgICAgICAgICAgKHJlY3VyICgrIDEgfnZhcm5hbWUpKSkpKSkpXG5cbihkZWZtYWNybyBkby1uZXN0ZWQgW3huYW1lIHluYW1lIHdpZHRoICYgYm9keV1cbiAgKGxldCBbaXRlcmF0aW9ucyAoZ2Vuc3ltKV1cbiAgICBgKGxldCBbfml0ZXJhdGlvbnMgfndpZHRoXVxuICAgICAgIChkby10aW1lcyB+eG5hbWUgfml0ZXJhdGlvbnNcbiAgICAgICAgIChkby10aW1lcyB+eW5hbWUgfml0ZXJhdGlvbnNcbiAgICAgICAgICAgfkBib2R5KSkpKSlcblxuKGRlZm1hY3JvIGluYyEgW3BsYWNlXVxuICBgKHNldCEgfnBsYWNlICgrIH5wbGFjZSAxKSkpXG5cbihkZWZtYWNybyBhZGQhIFtwbGFjZSBhbW91bnRdXG4gIGAoc2V0ISB+cGxhY2UgKCsgfnBsYWNlIH5hbW91bnQpKSlcblxuKGRlZm1hY3JvIHRpbWUgWyYgYm9keV1cbiAgKGxldCBbc3RhcnQgKGdlbnN5bSlcbiAgICAgICAgZW5kIChnZW5zeW0pXG4gICAgICAgIHJlc3VsdCAoZ2Vuc3ltKV1cbiAgICBgKGxldCBbfnN0YXJ0ICguZ2V0VGltZSAobmV3IERhdGUpKVxuICAgICAgICAgICB+cmVzdWx0IChkbyB+QGJvZHkpXG4gICAgICAgICAgIH5lbmQgKC5nZXRUaW1lIChuZXcgRGF0ZSkpXVxuICAgICAgIChsICgrIFwiRWxhcHNlZCB0aW1lOiBcIiAoLSB+ZW5kIH5zdGFydCkgXCJtcy5cIikpXG4gICAgICAgfnJlc3VsdCkpKVxuXG4oZGVmbiBsIFt2XVxuICAoY29uc29sZS5sb2cgdikpXG5cblxuKGRlZm4gbWlkcG9pbnQgW2EgYl1cbiAgKC8gKCsgYSBiKSAyKSlcblxuKGRlZm4gYXZlcmFnZTIgW2EgYl1cbiAgKC8gKCsgYSBiKSAyKSlcblxuKGRlZm4gYXZlcmFnZTQgW2EgYiBjIGRdXG4gICgvICgrIGEgYiBjIGQpIDQpKVxuXG4oZGVmbiBzYWZlLWF2ZXJhZ2UgW2EgYiBjIGRdXG4gIChsZXQgW3RvdGFsIDAgY291bnQgMF1cbiAgICAod2hlbiBhIChhZGQhIHRvdGFsIGEpIChpbmMhIGNvdW50KSlcbiAgICAod2hlbiBiIChhZGQhIHRvdGFsIGIpIChpbmMhIGNvdW50KSlcbiAgICAod2hlbiBjIChhZGQhIHRvdGFsIGMpIChpbmMhIGNvdW50KSlcbiAgICAod2hlbiBkIChhZGQhIHRvdGFsIGQpIChpbmMhIGNvdW50KSlcbiAgICAoLyB0b3RhbCBjb3VudCkpKVxuXG5cbihkZWZuIHJhbmQgW11cbiAgKE1hdGgucmFuZG9tKSlcblxuKGRlZm4gcmFuZC1hcm91bmQtemVybyBbc3ByZWFkXVxuICAoLSAoKiBzcHJlYWQgKHJhbmQpIDIpIHNwcmVhZCkpXG5cblxuKGRlZm4gaml0dGVyIFt2YWx1ZSBzcHJlYWRdXG4gICgrIHZhbHVlIChyYW5kLWFyb3VuZC16ZXJvIHNwcmVhZCkpKVxuXG5cbjsgSGVpZ2h0bWFwIEhlbHBlcnMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbihkZWZtYWNybyBoZWlnaHRtYXAtZ2V0IFtobSB4IHldXG4gIGAoYWdldCB+aG0gKCsgKCogfnkgKC4tcmVzb2x1dGlvbiB+aG0pKSB+eCkpKVxuXG4oZGVmbiBoZWlnaHRtYXAtZ2V0LXNhZmUgW2htIHggeV1cbiAgKHdoZW4gKGFuZCAoPD0gMCB4IGhtLmxhc3QpXG4gICAgICAgICAgICAgKDw9IDAgeSBobS5sYXN0KSlcbiAgICAoaGVpZ2h0bWFwLWdldCBobSB4IHkpKSlcblxuKGRlZm1hY3JvIGhlaWdodG1hcC1zZXQhIFtobSB4IHkgdmFsXVxuICBgKHNldCEgKGhlaWdodG1hcC1nZXQgfmhtIH54IH55KSB+dmFsKSlcblxuXG4oZGVmbiBub3JtYWxpemUgW2htXVxuICAobGV0IFttYXggKC0gSW5maW5pdHkpXG4gICAgICAgIG1pbiBJbmZpbml0eV1cbiAgICAoZG8tdGltZXMgaSBobS5sZW5ndGhcbiAgICAgIChsZXQgW2VsIChhZ2V0IGhtIGkpXVxuICAgICAgICAod2hlbiAoPCBtYXggZWwpIChzZXQhIG1heCBlbCkpXG4gICAgICAgICh3aGVuICg+IG1pbiBlbCkgKHNldCEgbWluIGVsKSkpKVxuICAgIChsZXQgW3NwYW4gKC0gbWF4IG1pbildXG4gICAgICAoZG8tdGltZXMgaSBobS5sZW5ndGhcbiAgICAgICAgKHNldCEgKGFnZXQgaG0gaSlcbiAgICAgICAgICAoLyAoLSAoYWdldCBobSBpKSBtaW4pXG4gICAgICAgICAgICAgc3BhbikpKSkpKVxuXG4oZGVmbiB6ZXJvLWhlaWdodG1hcCBbaGVpZ2h0bWFwXVxuICAoZG8tdGltZXMgaSBoZWlnaHRtYXAubGVuZ3RoXG4gICAgKHNldCEgKGFnZXQgaGVpZ2h0bWFwIGkpIDAuMCkpXG4gIGhlaWdodG1hcClcblxuKGRlZm4gbWFrZS1oZWlnaHRtYXAgW2V4cG9uZW50XVxuICAobGV0IFtyZXNvbHV0aW9uICgrIDEgKE1hdGgucG93IDIgZXhwb25lbnQpKV1cbiAgICAobCAoKyBcIkNyZWF0aW5nIFwiIHJlc29sdXRpb24gXCIgYnkgXCIgcmVzb2x1dGlvbiBcIiBoZWlnaHRtYXAuLi5cIikpXG4gICAgKGRlZiBoZWlnaHRtYXBcbiAgICAgIChuZXcgQXJyYXkgKCogcmVzb2x1dGlvbiByZXNvbHV0aW9uKSkpXG4gICAgKHNldCEgaGVpZ2h0bWFwLnJlc29sdXRpb24gcmVzb2x1dGlvbilcbiAgICAoc2V0ISBoZWlnaHRtYXAuZXhwb25lbnQgZXhwb25lbnQpXG4gICAgKHNldCEgaGVpZ2h0bWFwLmxhc3QgKC0gcmVzb2x1dGlvbiAxKSlcbiAgICAoemVyby1oZWlnaHRtYXAgaGVpZ2h0bWFwKSkpXG5cblxuOyBSYW5kb20gTm9pc2UgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuKGRlZm4gcmFuZG9tLW5vaXNlIFtoZWlnaHRtYXBdXG4gIChkby10aW1lcyBpIGhlaWdodG1hcC5sZW5ndGhcbiAgICAoc2V0ISAoYWdldCBoZWlnaHRtYXAgaSkgKHJhbmQpKSkpXG5cblxuOyBNaWRwb2ludCBEaXNwbGFjZW1lbnQgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuKGRlZm4gbXBkLWluaXQtY29ybmVycyBbaGVpZ2h0bWFwXVxuICAoaGVpZ2h0bWFwLXNldCEgaGVpZ2h0bWFwIDAgMCAocmFuZCkpXG4gIChoZWlnaHRtYXAtc2V0ISBoZWlnaHRtYXAgMCBoZWlnaHRtYXAubGFzdCAocmFuZCkpXG4gIChoZWlnaHRtYXAtc2V0ISBoZWlnaHRtYXAgaGVpZ2h0bWFwLmxhc3QgMCAocmFuZCkpXG4gIChoZWlnaHRtYXAtc2V0ISBoZWlnaHRtYXAgaGVpZ2h0bWFwLmxhc3QgaGVpZ2h0bWFwLmxhc3QgKHJhbmQpKSlcblxuKGRlZm4gbXBkLWRpc3BsYWNlIFtoZWlnaHRtYXAgbHggcnggYnkgdHkgc3ByZWFkXVxuICAobGV0IFtjeCAobWlkcG9pbnQgbHggcngpXG4gICAgICAgIGN5IChtaWRwb2ludCBieSB0eSlcblxuICAgICAgICBib3R0b20tbGVmdCAoaGVpZ2h0bWFwLWdldCBoZWlnaHRtYXAgbHggYnkpXG4gICAgICAgIGJvdHRvbS1yaWdodCAoaGVpZ2h0bWFwLWdldCBoZWlnaHRtYXAgcnggYnkpXG4gICAgICAgIHRvcC1sZWZ0IChoZWlnaHRtYXAtZ2V0IGhlaWdodG1hcCBseCB0eSlcbiAgICAgICAgdG9wLXJpZ2h0IChoZWlnaHRtYXAtZ2V0IGhlaWdodG1hcCByeCB0eSlcblxuICAgICAgICB0b3AgKGF2ZXJhZ2UyIHRvcC1sZWZ0IHRvcC1yaWdodClcbiAgICAgICAgbGVmdCAoYXZlcmFnZTIgYm90dG9tLWxlZnQgdG9wLWxlZnQpXG4gICAgICAgIGJvdHRvbSAoYXZlcmFnZTIgYm90dG9tLWxlZnQgYm90dG9tLXJpZ2h0KVxuICAgICAgICByaWdodCAoYXZlcmFnZTIgYm90dG9tLXJpZ2h0IHRvcC1yaWdodClcbiAgICAgICAgY2VudGVyIChhdmVyYWdlNCB0b3AgbGVmdCBib3R0b20gcmlnaHQpXVxuICAgIChoZWlnaHRtYXAtc2V0ISBoZWlnaHRtYXAgY3ggYnkgKGppdHRlciBib3R0b20gc3ByZWFkKSlcbiAgICAoaGVpZ2h0bWFwLXNldCEgaGVpZ2h0bWFwIGN4IHR5IChqaXR0ZXIgdG9wIHNwcmVhZCkpXG4gICAgKGhlaWdodG1hcC1zZXQhIGhlaWdodG1hcCBseCBjeSAoaml0dGVyIGxlZnQgc3ByZWFkKSlcbiAgICAoaGVpZ2h0bWFwLXNldCEgaGVpZ2h0bWFwIHJ4IGN5IChqaXR0ZXIgcmlnaHQgc3ByZWFkKSlcbiAgICAoaGVpZ2h0bWFwLXNldCEgaGVpZ2h0bWFwIGN4IGN5IChqaXR0ZXIgY2VudGVyIHNwcmVhZCkpKSlcblxuKGRlZm4gbWlkcG9pbnQtZGlzcGxhY2VtZW50IFtoZWlnaHRtYXBdXG4gIChtcGQtaW5pdC1jb3JuZXJzIGhlaWdodG1hcClcbiAgOyAobXBkLWRpc3BsYWNlIGhlaWdodG1hcCAwIGhlaWdodG1hcC5sYXN0IDAgaGVpZ2h0bWFwLmxhc3QgMC4xKVxuICAobG9vcCBbaXRlciAwXG4gICAgICAgICBzcHJlYWQgMC4zXVxuICAgICh3aGVuICg8IGl0ZXIgaGVpZ2h0bWFwLmV4cG9uZW50KVxuICAgICAgKGxldCBbY2h1bmtzIChNYXRoLnBvdyAyIGl0ZXIpXG4gICAgICAgICAgICBjaHVuay13aWR0aCAoLyAoLSBoZWlnaHRtYXAucmVzb2x1dGlvbiAxKSBjaHVua3MpXVxuICAgICAgICAoZG8tbmVzdGVkIHhjaHVuayB5Y2h1bmsgY2h1bmtzXG4gICAgICAgICAgKGxldCBbbGVmdC14ICgqIGNodW5rLXdpZHRoIHhjaHVuaylcbiAgICAgICAgICAgICAgICByaWdodC14ICgrIGxlZnQteCBjaHVuay13aWR0aClcbiAgICAgICAgICAgICAgICBib3R0b20teSAoKiBjaHVuay13aWR0aCB5Y2h1bmspXG4gICAgICAgICAgICAgICAgdG9wLXkgKCsgYm90dG9tLXkgY2h1bmstd2lkdGgpXVxuICAgICAgICAgICAgKG1wZC1kaXNwbGFjZSBoZWlnaHRtYXAgbGVmdC14IHJpZ2h0LXggYm90dG9tLXkgdG9wLXkgc3ByZWFkKSkpKVxuICAgICAgKHJlY3VyICgrIDEgaXRlcikgKCogc3ByZWFkIDAuNSkpKSlcbiAgKG5vcm1hbGl6ZSBoZWlnaHRtYXApKVxuXG5cbihkZWZuIG1pZHBvaW50LWRpc3BsYWNlbWVudC1maW5hbCBbaGVpZ2h0bWFwXVxuICAobXBkLWluaXQtY29ybmVycyBoZWlnaHRtYXApXG4gIDsgKGxldCBbc3ByZWFkIF0pXG4gIChsb29wIFtpdGVyIDBcbiAgICAgICAgIHNwcmVhZCAoKyAwICgudmFsICgkIFwiI2lucHV0LXN0YXJ0aW5nLXNwcmVhZFwiKSkpXVxuICAgICh3aGVuICg8IGl0ZXIgaGVpZ2h0bWFwLmV4cG9uZW50KVxuICAgICAgKGxldCBbY2h1bmtzIChNYXRoLnBvdyAyIGl0ZXIpXG4gICAgICAgICAgICBjaHVuay13aWR0aCAoLyAoLSBoZWlnaHRtYXAucmVzb2x1dGlvbiAxKSBjaHVua3MpXVxuICAgICAgICAoZG8tbmVzdGVkIHhjaHVuayB5Y2h1bmsgY2h1bmtzXG4gICAgICAgICAgKGxldCBbbGVmdC14ICgqIGNodW5rLXdpZHRoIHhjaHVuaylcbiAgICAgICAgICAgICAgICByaWdodC14ICgrIGxlZnQteCBjaHVuay13aWR0aClcbiAgICAgICAgICAgICAgICBib3R0b20teSAoKiBjaHVuay13aWR0aCB5Y2h1bmspXG4gICAgICAgICAgICAgICAgdG9wLXkgKCsgYm90dG9tLXkgY2h1bmstd2lkdGgpXVxuICAgICAgICAgICAgKG1wZC1kaXNwbGFjZSBoZWlnaHRtYXAgbGVmdC14IHJpZ2h0LXggYm90dG9tLXkgdG9wLXkgc3ByZWFkKSkpKVxuICAgICAgKHJlY3VyICgrIDEgaXRlcikgKCogc3ByZWFkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAoKyAwICgudmFsICgkIFwiI2lucHV0LXNwcmVhZC1yZWR1Y3Rpb25cIikpKSkpKSlcbiAgKG5vcm1hbGl6ZSBoZWlnaHRtYXApKVxuXG5cbihkZWZuIG1wZC1kaXNwbGFjZS1kMiBbaGVpZ2h0bWFwIGx4IHJ4IGJ5IHR5IHNwcmVhZF1cbiAgKGxldCBbY3ggKG1pZHBvaW50IGx4IHJ4KVxuICAgICAgICBjeSAobWlkcG9pbnQgYnkgdHkpXG5cbiAgICAgICAgYm90dG9tLWxlZnQgKGhlaWdodG1hcC1nZXQgaGVpZ2h0bWFwIGx4IGJ5KVxuICAgICAgICBib3R0b20tcmlnaHQgKGhlaWdodG1hcC1nZXQgaGVpZ2h0bWFwIHJ4IGJ5KVxuICAgICAgICB0b3AtbGVmdCAoaGVpZ2h0bWFwLWdldCBoZWlnaHRtYXAgbHggdHkpXG4gICAgICAgIHRvcC1yaWdodCAoaGVpZ2h0bWFwLWdldCBoZWlnaHRtYXAgcnggdHkpXG5cbiAgICAgICAgdG9wIChhdmVyYWdlMiB0b3AtbGVmdCB0b3AtcmlnaHQpXG4gICAgICAgIGxlZnQgKGF2ZXJhZ2UyIGJvdHRvbS1sZWZ0IHRvcC1sZWZ0KVxuICAgICAgICBib3R0b20gKGF2ZXJhZ2UyIGJvdHRvbS1sZWZ0IGJvdHRvbS1yaWdodClcbiAgICAgICAgcmlnaHQgKGF2ZXJhZ2UyIGJvdHRvbS1yaWdodCB0b3AtcmlnaHQpXVxuICAgIChoZWlnaHRtYXAtc2V0ISBoZWlnaHRtYXAgY3ggYnkgKGppdHRlciBib3R0b20gc3ByZWFkKSlcbiAgICAoaGVpZ2h0bWFwLXNldCEgaGVpZ2h0bWFwIGN4IHR5IChqaXR0ZXIgdG9wIHNwcmVhZCkpXG4gICAgKGhlaWdodG1hcC1zZXQhIGhlaWdodG1hcCBseCBjeSAoaml0dGVyIGxlZnQgc3ByZWFkKSlcbiAgICAoaGVpZ2h0bWFwLXNldCEgaGVpZ2h0bWFwIHJ4IGN5IChqaXR0ZXIgcmlnaHQgc3ByZWFkKSkpKVxuXG4oZGVmbiBtaWRwb2ludC1kaXNwbGFjZW1lbnQtZDEgW2hlaWdodG1hcF1cbiAgKG1wZC1pbml0LWNvcm5lcnMgaGVpZ2h0bWFwKSlcblxuKGRlZm4gbWlkcG9pbnQtZGlzcGxhY2VtZW50LWQyIFtoZWlnaHRtYXBdXG4gIChtcGQtaW5pdC1jb3JuZXJzIGhlaWdodG1hcClcbiAgKG1wZC1kaXNwbGFjZS1kMiBoZWlnaHRtYXBcbiAgICAgICAgICAgICAgICAgICAwIGhlaWdodG1hcC5sYXN0XG4gICAgICAgICAgICAgICAgICAgMCBoZWlnaHRtYXAubGFzdFxuICAgICAgICAgICAgICAgICAgIDAuMSkpXG5cbihkZWZuIG1pZHBvaW50LWRpc3BsYWNlbWVudC1kMyBbaGVpZ2h0bWFwXVxuICAobXBkLWluaXQtY29ybmVycyBoZWlnaHRtYXApXG4gIChtcGQtZGlzcGxhY2UgaGVpZ2h0bWFwXG4gICAgICAgICAgICAgICAgMCBoZWlnaHRtYXAubGFzdFxuICAgICAgICAgICAgICAgIDAgaGVpZ2h0bWFwLmxhc3RcbiAgICAgICAgICAgICAgICAwLjEpKVxuXG5cblxuOyBUaHJlZS5qcyBIZWxwZXJzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuKGRlZm4gbWFrZS1kaXJlY3Rpb25hbC1saWdodCBbXVxuICAobGV0IFtsaWdodCAobmV3IFRIUkVFLkRpcmVjdGlvbmFsTGlnaHQgMHhmZmZmZmYgMSldXG4gICAgKGxpZ2h0LnBvc2l0aW9uLnNldCAxMDAgMCAxNTApXG4gICAgbGlnaHQpKVxuXG4oZGVmbiBtYWtlLWNhbWVyYSBbXVxuICAobGV0IFtjYW1lcmEgKG5ldyBUSFJFRS5QZXJzcGVjdGl2ZUNhbWVyYVxuICAgICAgICAgICAgICAgICAgICA1NSxcbiAgICAgICAgICAgICAgICAgICAgKC8gd2lkdGggaGVpZ2h0KVxuICAgICAgICAgICAgICAgICAgICAwLjEsXG4gICAgICAgICAgICAgICAgICAgIDEwMDApXVxuICAgIChjYW1lcmEucG9zaXRpb24uc2V0IDAgLTEwMCAxNTApXG4gICAgY2FtZXJhKSlcblxuKGRlZm4gbWFrZS1yZW5kZXJlciBbXVxuICAobGV0IFtyZW5kZXJlciAobmV3IFRIUkVFLldlYkdMUmVuZGVyZXIgezphbnRpYWxpYXMgZmFsc2V9KV1cbiAgICAocmVuZGVyZXIuc2V0Q2xlYXJDb2xvciAweGZmZmZmZilcbiAgICAocmVuZGVyZXIuc2V0U2l6ZSB3aWR0aCBoZWlnaHQpXG4gICAgKHJlbmRlcmVyLnNldFBpeGVsUmF0aW8gMilcbiAgICByZW5kZXJlcikpXG5cbihkZWZuIG1ha2UtZ2VvbWV0cnkgW2hlaWdodG1hcF1cbiAgKGxldCBbZ2VvbWV0cnkgKG5ldyBUSFJFRS5QbGFuZUdlb21ldHJ5XG4gICAgICAgICAgICAgICAgICAgICAgdGVycmFpbi1zaXplXG4gICAgICAgICAgICAgICAgICAgICAgdGVycmFpbi1zaXplXG4gICAgICAgICAgICAgICAgICAgICAgKC0gaGVpZ2h0bWFwLnJlc29sdXRpb24gMSlcbiAgICAgICAgICAgICAgICAgICAgICAoLSBoZWlnaHRtYXAucmVzb2x1dGlvbiAxKSldXG4gICAgKHNldCEgZ2VvbWV0cnkuZHluYW1pYyB0cnVlKVxuICAgIGdlb21ldHJ5KSlcblxuKGRlZm4gbWFrZS1jb250cm9scyBbY2FtZXJhIHJlbmRlcmVyXVxuICAobGV0IFtjb250cm9scyAobmV3IFRIUkVFLlRyYWNrYmFsbENvbnRyb2xzIGNhbWVyYSByZW5kZXJlci5kb21FbGVtZW50KV1cbiAgICAoc2V0ISBjb250cm9scy5yb3RhdGVTcGVlZCAxLjQpXG4gICAgKHNldCEgY29udHJvbHMuem9vbVNwZWVkIDAuNSlcbiAgICAoc2V0ISBjb250cm9scy5zdGF0aWNNb3ZpbmcgdHJ1ZSlcbiAgICAoc2V0ISBjb250cm9scy5keW5hbWljRGFtcGluZ0ZhY3RvciAwLjMpXG4gICAgY29udHJvbHMpKVxuXG4oZGVmbiBtYWtlLXBsYW5lIFtnZW9tZXRyeV1cbiAgKGxldCBbbWF0ZXJpYWwgKG5ldyBUSFJFRS5NZXNoTGFtYmVydE1hdGVyaWFsXG4gICAgICAgICAgICAgICAgICAgICAgezp3aXJlZnJhbWUgd2lyZWZyYW1lXG4gICAgICAgICAgICAgICAgICAgICAgIDp3aXJlZnJhbWVMaW5ld2lkdGggd2lyZWZyYW1lLXdpZHRoXG4gICAgICAgICAgICAgICAgICAgICAgIDpjb2xvciAweDAwYmIwMH0pXVxuICAgIChuZXcgVEhSRUUuTWVzaCBnZW9tZXRyeSBtYXRlcmlhbCkpKVxuXG5cbihkZWZuIGF0dGFjaC10by1kb20gW3JlbmRlcmVyIGVsLW5hbWUgcmVmcmVzaC1mbl1cbiAgKGxldCBbY29udGFpbmVyIChkb2N1bWVudC5nZXRFbGVtZW50QnlJZCBlbC1uYW1lKVxuICAgICAgICBzZXR0aW5ncyAoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCBcImRpdlwiKVxuICAgICAgICByZWZyZXNoLWJ1dHRvbiAoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCBcImJ1dHRvblwiKVxuICAgICAgICBidXR0b24tdGV4dCAoZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUgXCJSZWZyZXNoXCIpXG4gICAgICAgIGNhbmNlbC1zY3JvbGwgKGZuIFtlXSAoLnByZXZlbnREZWZhdWx0IGUpKV1cbiAgICAoc2V0ISByZWZyZXNoLWJ1dHRvbi5vbmNsaWNrIHJlZnJlc2gtZm4pXG4gICAgKHNldCEgcmVuZGVyZXIuZG9tRWxlbWVudC5vbm1vdXNld2hlZWwgY2FuY2VsLXNjcm9sbClcbiAgICAocmVuZGVyZXIuZG9tRWxlbWVudC5hZGRFdmVudExpc3RlbmVyIFwiTW96TW91c2VQaXhlbFNjcm9sbFwiIGNhbmNlbC1zY3JvbGwgZmFsc2UpXG4gICAgKC5hcHBlbmRDaGlsZCByZWZyZXNoLWJ1dHRvbiBidXR0b24tdGV4dClcbiAgICAoLmFwcGVuZENoaWxkIGNvbnRhaW5lciByZW5kZXJlci5kb21FbGVtZW50KVxuICAgICguYXBwZW5kQ2hpbGQgY29udGFpbmVyIHNldHRpbmdzKVxuICAgICguYXBwZW5kQ2hpbGQgc2V0dGluZ3MgcmVmcmVzaC1idXR0b24pKSlcblxuKGRlZm4gdXBkYXRlLWdlb21ldHJ5IFtnZW9tZXRyeSBoZWlnaHRtYXBdXG4gIChkby10aW1lcyBpIGdlb21ldHJ5LnZlcnRpY2VzLmxlbmd0aFxuICAgIChzZXQhICguLXogKGFnZXQgZ2VvbWV0cnkudmVydGljZXMgaSkpXG4gICAgICAoKiB0ZXJyYWluLWhlaWdodCAoYWdldCBoZWlnaHRtYXAgaSkpKSlcbiAgKHNldCEgZ2VvbWV0cnkudmVydGljZXNOZWVkVXBkYXRlIHRydWUpXG4gIChnZW9tZXRyeS5jb21wdXRlRmFjZU5vcm1hbHMpXG4gIChnZW9tZXRyeS5jb21wdXRlVmVydGV4Tm9ybWFscylcbiAgKGdlb21ldHJ5LmNvbXB1dGVNb3JwaE5vcm1hbHMpXG4gIGdlb21ldHJ5KVxuXG5cbjsgTWFpbiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbihkZWZuIG1ha2UtZGVtbyBbZWxlbWVudC1pZCBhbGdvcml0aG0gc2l6ZV1cbiAgKGRlZiBzY2VuZSAobmV3IFRIUkVFLlNjZW5lKSlcbiAgKHNjZW5lLmFkZCAobmV3IFRIUkVFLkF4aXNIZWxwZXIgMTAwKSlcblxuICAoZGVmIGNsb2NrIChuZXcgVEhSRUUuQ2xvY2spKVxuICAoZGVmIGNhbWVyYSAobWFrZS1jYW1lcmEpKVxuICAoZGVmIHJlbmRlcmVyIChtYWtlLXJlbmRlcmVyKSlcbiAgKGRlZiBnZW9tZXRyeSAobWFrZS1nZW9tZXRyeSAobWFrZS1oZWlnaHRtYXAgc2l6ZSkpKVxuXG4gIChzY2VuZS5hZGQgKG1ha2UtZGlyZWN0aW9uYWwtbGlnaHQpKVxuICAoc2NlbmUuYWRkIChuZXcgVEhSRUUuQW1iaWVudExpZ2h0IDB4ZmZmZmZmIDAuMDUpKVxuICAoc2NlbmUuYWRkIChtYWtlLXBsYW5lIGdlb21ldHJ5KSlcblxuICAoZGVmbiByZWZyZXNoIFtdXG4gICAgKGwgXCJSZWZyZXNoaW5nID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cIilcbiAgICAobGV0IFtoZWlnaHRtYXAgKG1ha2UtaGVpZ2h0bWFwIHNpemUpXVxuICAgICAgKGwgXCJHZW5lcmF0aW5nIHRlcnJhaW4uLi5cIilcbiAgICAgICh0aW1lIChhbGdvcml0aG0gaGVpZ2h0bWFwKSlcbiAgICAgIChsIFwiUmVmcmVzaGluZyBnZW9tZXRyeS4uLlwiKVxuICAgICAgKHRpbWUgKHVwZGF0ZS1nZW9tZXRyeSBnZW9tZXRyeSBoZWlnaHRtYXApKVxuICAgICAgKGwgXCJEb25lIVwiKSkpXG5cbiAgKGF0dGFjaC10by1kb20gcmVuZGVyZXIgZWxlbWVudC1pZCByZWZyZXNoKVxuICAoZGVmIGNvbnRyb2xzIChtYWtlLWNvbnRyb2xzIGNhbWVyYSByZW5kZXJlcikpXG5cbiAgKGRlZm4gcmVuZGVyIFtdXG4gICAgKGxldCBbZGVsdGEgKGNsb2NrLmdldERlbHRhKV1cbiAgICAgIChyZXF1ZXN0QW5pbWF0aW9uRnJhbWUgcmVuZGVyKVxuICAgICAgKC51cGRhdGUgY29udHJvbHMgZGVsdGEpXG4gICAgICAocmVuZGVyZXIucmVuZGVyIHNjZW5lIGNhbWVyYSkpKVxuXG4gIChyZW5kZXIpXG5cbiAgbmlsKVxuXG4oZGVmbiBtYWtlLWZpbmFsIFtlbGVtZW50LWlkXVxuICAoZGVmIHNjZW5lIChuZXcgVEhSRUUuU2NlbmUpKVxuICAoc2NlbmUuYWRkIChuZXcgVEhSRUUuQXhpc0hlbHBlciAxMDApKVxuXG4gIChkZWYgY2xvY2sgKG5ldyBUSFJFRS5DbG9jaykpXG4gIChkZWYgY2FtZXJhIChtYWtlLWNhbWVyYSkpXG4gIChkZWYgcmVuZGVyZXIgKG1ha2UtcmVuZGVyZXIpKVxuICAoZGVmIGhlaWdodG1hcCAobWFrZS1oZWlnaHRtYXAgKC52YWwgKCQgXCIjaW5wdXQtZXhwb25lbnRcIikpKSlcbiAgKGRlZiBnZW9tZXRyeSAobWFrZS1nZW9tZXRyeSBoZWlnaHRtYXApKVxuICAoZGVmIHBsYW5lIChtYWtlLXBsYW5lIGdlb21ldHJ5KSlcblxuICAoc2NlbmUuYWRkIChtYWtlLWRpcmVjdGlvbmFsLWxpZ2h0KSlcbiAgKHNjZW5lLmFkZCAobmV3IFRIUkVFLkFtYmllbnRMaWdodCAweGZmZmZmZiAwLjA1KSlcbiAgKHNjZW5lLmFkZCBwbGFuZSlcblxuICAoZGVmbiByZWZyZXNoIFtdXG4gICAgKGwgXCJSZWZyZXNoaW5nID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cIilcbiAgICAoc2NlbmUucmVtb3ZlIHBsYW5lKVxuICAgIChzZXQhIGhlaWdodG1hcCAobWFrZS1oZWlnaHRtYXAgKC52YWwgKCQgXCIjaW5wdXQtZXhwb25lbnRcIikpKSlcbiAgICAoc2V0ISBnZW9tZXRyeSAobWFrZS1nZW9tZXRyeSBoZWlnaHRtYXApKVxuICAgIChzZXQhIHBsYW5lIChtYWtlLXBsYW5lIGdlb21ldHJ5KSlcbiAgICAoc2NlbmUuYWRkIHBsYW5lKVxuICAgIChsIFwiR2VuZXJhdGluZyB0ZXJyYWluLi4uXCIpXG4gICAgKHRpbWUgKG1pZHBvaW50LWRpc3BsYWNlbWVudC1maW5hbCBoZWlnaHRtYXApKVxuICAgIChsIFwiUmVmcmVzaGluZyBnZW9tZXRyeS4uLlwiKVxuICAgICh0aW1lICh1cGRhdGUtZ2VvbWV0cnkgZ2VvbWV0cnkgaGVpZ2h0bWFwKSlcbiAgICAobCBcIkRvbmUhXCIpKVxuXG4gIChhdHRhY2gtdG8tZG9tIHJlbmRlcmVyIGVsZW1lbnQtaWQgcmVmcmVzaClcbiAgKGRlZiBjb250cm9scyAobWFrZS1jb250cm9scyBjYW1lcmEgcmVuZGVyZXIpKVxuXG4gIChkZWZuIHJlbmRlciBbXVxuICAgIChsZXQgW2RlbHRhIChjbG9jay5nZXREZWx0YSldXG4gICAgICAocmVxdWVzdEFuaW1hdGlvbkZyYW1lIHJlbmRlcilcbiAgICAgICgudXBkYXRlIGNvbnRyb2xzIGRlbHRhKVxuICAgICAgKHJlbmRlcmVyLnJlbmRlciBzY2VuZSBjYW1lcmEpKSlcblxuICAocmVuZGVyKVxuXG4gIG5pbClcblxuXG4oZGVmbiBydW4gW11cbiAgKG1ha2UtZGVtbyBcImRlbW8tcmFuZG9tXCIgcmFuZG9tLW5vaXNlIDcpXG4gIChtYWtlLWRlbW8gXCJkZW1vLW1wZC0xXCIgbWlkcG9pbnQtZGlzcGxhY2VtZW50LWQxIDIpXG4gIChtYWtlLWRlbW8gXCJkZW1vLW1wZC0yXCIgbWlkcG9pbnQtZGlzcGxhY2VtZW50LWQyIDIpXG4gIChtYWtlLWRlbW8gXCJkZW1vLW1wZC0zXCIgbWlkcG9pbnQtZGlzcGxhY2VtZW50LWQzIDIpXG4gIChtYWtlLWRlbW8gXCJkZW1vLW1wZC00XCIgbWlkcG9pbnQtZGlzcGxhY2VtZW50IDMpXG4gIChtYWtlLWZpbmFsIFwiZGVtby1maW5hbFwiKVxuICA7IChtYWtlLWRlbW8gXCJkZW1vLW1pZHBvaW50XCIgbWlkcG9pbnQtZGlzcGxhY2VtZW50KVxuICA7IChtYWtlLWRlbW8gXCJkZW1vLWRpYW1vbmRcIiBkaWFtb25kLXNxdWFyZSlcblxuICApXG5cbigkIHJ1bilcblxuXG47IHZpbTogbHcrPWRvLXRpbWVzIGx3Kz1kby1uZXN0ZWQgOlxuIl19
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/media/js/wisp/terrain1.wisp Sun Feb 28 11:51:50 2016 +0000
@@ -0,0 +1,392 @@
+; Constants -------------------------------------------------------------------
+(def width 610)
+(def height 400)
+(def wireframe true)
+(def wireframe-width 1.2)
+(def terrain-height 50)
+(def terrain-size 100)
+
+; General Utilities -----------------------------------------------------------
+(defmacro when [condition & body]
+ `(if ~condition
+ (do ~@body)))
+
+(defmacro do-times [varname limit & body]
+ (let [end (gensym)]
+ `(let [~end ~limit]
+ (loop [~varname 0]
+ (when (< ~varname ~end)
+ ~@body
+ (recur (+ 1 ~varname)))))))
+
+(defmacro do-nested [xname yname width & body]
+ (let [iterations (gensym)]
+ `(let [~iterations ~width]
+ (do-times ~xname ~iterations
+ (do-times ~yname ~iterations
+ ~@body)))))
+
+(defmacro inc! [place]
+ `(set! ~place (+ ~place 1)))
+
+(defmacro add! [place amount]
+ `(set! ~place (+ ~place ~amount)))
+
+(defmacro time [& body]
+ (let [start (gensym)
+ end (gensym)
+ result (gensym)]
+ `(let [~start (.getTime (new Date))
+ ~result (do ~@body)
+ ~end (.getTime (new Date))]
+ (l (+ "Elapsed time: " (- ~end ~start) "ms."))
+ ~result)))
+
+(defn l [v]
+ (console.log v))
+
+
+(defn midpoint [a b]
+ (/ (+ a b) 2))
+
+(defn average2 [a b]
+ (/ (+ a b) 2))
+
+(defn average4 [a b c d]
+ (/ (+ a b c d) 4))
+
+(defn safe-average [a b c d]
+ (let [total 0 count 0]
+ (when a (add! total a) (inc! count))
+ (when b (add! total b) (inc! count))
+ (when c (add! total c) (inc! count))
+ (when d (add! total d) (inc! count))
+ (/ total count)))
+
+
+(defn rand []
+ (Math.random))
+
+(defn rand-around-zero [spread]
+ (- (* spread (rand) 2) spread))
+
+
+(defn jitter [value spread]
+ (+ value (rand-around-zero spread)))
+
+
+; Heightmap Helpers -----------------------------------------------------------
+(defmacro heightmap-get [hm x y]
+ `(aget ~hm (+ (* ~y (.-resolution ~hm)) ~x)))
+
+(defn heightmap-get-safe [hm x y]
+ (when (and (<= 0 x hm.last)
+ (<= 0 y hm.last))
+ (heightmap-get hm x y)))
+
+(defmacro heightmap-set! [hm x y val]
+ `(set! (heightmap-get ~hm ~x ~y) ~val))
+
+
+(defn normalize [hm]
+ (let [max (- Infinity)
+ min Infinity]
+ (do-times i hm.length
+ (let [el (aget hm i)]
+ (when (< max el) (set! max el))
+ (when (> min el) (set! min el))))
+ (let [span (- max min)]
+ (do-times i hm.length
+ (set! (aget hm i)
+ (/ (- (aget hm i) min)
+ span))))))
+
+(defn zero-heightmap [heightmap]
+ (do-times i heightmap.length
+ (set! (aget heightmap i) 0.0))
+ heightmap)
+
+(defn make-heightmap [exponent]
+ (let [resolution (+ 1 (Math.pow 2 exponent))]
+ (l (+ "Creating " resolution " by " resolution " heightmap..."))
+ (def heightmap
+ (new Array (* resolution resolution)))
+ (set! heightmap.resolution resolution)
+ (set! heightmap.exponent exponent)
+ (set! heightmap.last (- resolution 1))
+ (zero-heightmap heightmap)))
+
+
+; Random Noise ----------------------------------------------------------------
+(defn random-noise [heightmap]
+ (do-times i heightmap.length
+ (set! (aget heightmap i) (rand))))
+
+
+; Midpoint Displacement -------------------------------------------------------
+(defn mpd-init-corners [heightmap]
+ (heightmap-set! heightmap 0 0 (rand))
+ (heightmap-set! heightmap 0 heightmap.last (rand))
+ (heightmap-set! heightmap heightmap.last 0 (rand))
+ (heightmap-set! heightmap heightmap.last heightmap.last (rand)))
+
+(defn mpd-displace [heightmap lx rx by ty spread]
+ (let [cx (midpoint lx rx)
+ cy (midpoint by ty)
+
+ bottom-left (heightmap-get heightmap lx by)
+ bottom-right (heightmap-get heightmap rx by)
+ top-left (heightmap-get heightmap lx ty)
+ top-right (heightmap-get heightmap rx ty)
+
+ top (average2 top-left top-right)
+ left (average2 bottom-left top-left)
+ bottom (average2 bottom-left bottom-right)
+ right (average2 bottom-right top-right)
+ center (average4 top left bottom right)]
+ (heightmap-set! heightmap cx by (jitter bottom spread))
+ (heightmap-set! heightmap cx ty (jitter top spread))
+ (heightmap-set! heightmap lx cy (jitter left spread))
+ (heightmap-set! heightmap rx cy (jitter right spread))
+ (heightmap-set! heightmap cx cy (jitter center spread))))
+
+(defn midpoint-displacement [heightmap]
+ (mpd-init-corners heightmap)
+ ; (mpd-displace heightmap 0 heightmap.last 0 heightmap.last 0.1)
+ (loop [iter 0
+ spread 0.3]
+ (when (< iter heightmap.exponent)
+ (let [chunks (Math.pow 2 iter)
+ chunk-width (/ (- heightmap.resolution 1) chunks)]
+ (do-nested xchunk ychunk chunks
+ (let [left-x (* chunk-width xchunk)
+ right-x (+ left-x chunk-width)
+ bottom-y (* chunk-width ychunk)
+ top-y (+ bottom-y chunk-width)]
+ (mpd-displace heightmap left-x right-x bottom-y top-y spread))))
+ (recur (+ 1 iter) (* spread 0.5))))
+ (normalize heightmap))
+
+
+(defn midpoint-displacement-final [heightmap]
+ (mpd-init-corners heightmap)
+ ; (let [spread ])
+ (loop [iter 0
+ spread (+ 0 (.val ($ "#input-starting-spread")))]
+ (when (< iter heightmap.exponent)
+ (let [chunks (Math.pow 2 iter)
+ chunk-width (/ (- heightmap.resolution 1) chunks)]
+ (do-nested xchunk ychunk chunks
+ (let [left-x (* chunk-width xchunk)
+ right-x (+ left-x chunk-width)
+ bottom-y (* chunk-width ychunk)
+ top-y (+ bottom-y chunk-width)]
+ (mpd-displace heightmap left-x right-x bottom-y top-y spread))))
+ (recur (+ 1 iter) (* spread
+ (+ 0 (.val ($ "#input-spread-reduction")))))))
+ (normalize heightmap))
+
+
+(defn mpd-displace-d2 [heightmap lx rx by ty spread]
+ (let [cx (midpoint lx rx)
+ cy (midpoint by ty)
+
+ bottom-left (heightmap-get heightmap lx by)
+ bottom-right (heightmap-get heightmap rx by)
+ top-left (heightmap-get heightmap lx ty)
+ top-right (heightmap-get heightmap rx ty)
+
+ top (average2 top-left top-right)
+ left (average2 bottom-left top-left)
+ bottom (average2 bottom-left bottom-right)
+ right (average2 bottom-right top-right)]
+ (heightmap-set! heightmap cx by (jitter bottom spread))
+ (heightmap-set! heightmap cx ty (jitter top spread))
+ (heightmap-set! heightmap lx cy (jitter left spread))
+ (heightmap-set! heightmap rx cy (jitter right spread))))
+
+(defn midpoint-displacement-d1 [heightmap]
+ (mpd-init-corners heightmap))
+
+(defn midpoint-displacement-d2 [heightmap]
+ (mpd-init-corners heightmap)
+ (mpd-displace-d2 heightmap
+ 0 heightmap.last
+ 0 heightmap.last
+ 0.1))
+
+(defn midpoint-displacement-d3 [heightmap]
+ (mpd-init-corners heightmap)
+ (mpd-displace heightmap
+ 0 heightmap.last
+ 0 heightmap.last
+ 0.1))
+
+
+
+; Three.js Helpers ------------------------------------------------------------
+(defn make-directional-light []
+ (let [light (new THREE.DirectionalLight 0xffffff 1)]
+ (light.position.set 100 0 150)
+ light))
+
+(defn make-camera []
+ (let [camera (new THREE.PerspectiveCamera
+ 55,
+ (/ width height)
+ 0.1,
+ 1000)]
+ (camera.position.set 0 -100 150)
+ camera))
+
+(defn make-renderer []
+ (let [renderer (new THREE.WebGLRenderer {:antialias false})]
+ (renderer.setClearColor 0xffffff)
+ (renderer.setSize width height)
+ (renderer.setPixelRatio 2)
+ renderer))
+
+(defn make-geometry [heightmap]
+ (let [geometry (new THREE.PlaneGeometry
+ terrain-size
+ terrain-size
+ (- heightmap.resolution 1)
+ (- heightmap.resolution 1))]
+ (set! geometry.dynamic true)
+ geometry))
+
+(defn make-controls [camera renderer]
+ (let [controls (new THREE.TrackballControls camera renderer.domElement)]
+ (set! controls.rotateSpeed 1.4)
+ (set! controls.zoomSpeed 0.5)
+ (set! controls.staticMoving true)
+ (set! controls.dynamicDampingFactor 0.3)
+ controls))
+
+(defn make-plane [geometry]
+ (let [material (new THREE.MeshLambertMaterial
+ {:wireframe wireframe
+ :wireframeLinewidth wireframe-width
+ :color 0x00bb00})]
+ (new THREE.Mesh geometry material)))
+
+
+(defn attach-to-dom [renderer el-name refresh-fn]
+ (let [container (document.getElementById el-name)
+ settings (document.createElement "div")
+ refresh-button (document.createElement "button")
+ button-text (document.createTextNode "Refresh")
+ cancel-scroll (fn [e] (.preventDefault e))]
+ (set! refresh-button.onclick refresh-fn)
+ (set! renderer.domElement.onmousewheel cancel-scroll)
+ (renderer.domElement.addEventListener "MozMousePixelScroll" cancel-scroll false)
+ (.appendChild refresh-button button-text)
+ (.appendChild container renderer.domElement)
+ (.appendChild container settings)
+ (.appendChild settings refresh-button)))
+
+(defn update-geometry [geometry heightmap]
+ (do-times i geometry.vertices.length
+ (set! (.-z (aget geometry.vertices i))
+ (* terrain-height (aget heightmap i))))
+ (set! geometry.verticesNeedUpdate true)
+ (geometry.computeFaceNormals)
+ (geometry.computeVertexNormals)
+ (geometry.computeMorphNormals)
+ geometry)
+
+
+; Main ------------------------------------------------------------------------
+(defn make-demo [element-id algorithm size]
+ (def scene (new THREE.Scene))
+ (scene.add (new THREE.AxisHelper 100))
+
+ (def clock (new THREE.Clock))
+ (def camera (make-camera))
+ (def renderer (make-renderer))
+ (def geometry (make-geometry (make-heightmap size)))
+
+ (scene.add (make-directional-light))
+ (scene.add (new THREE.AmbientLight 0xffffff 0.05))
+ (scene.add (make-plane geometry))
+
+ (defn refresh []
+ (l "Refreshing ========================================")
+ (let [heightmap (make-heightmap size)]
+ (l "Generating terrain...")
+ (time (algorithm heightmap))
+ (l "Refreshing geometry...")
+ (time (update-geometry geometry heightmap))
+ (l "Done!")))
+
+ (attach-to-dom renderer element-id refresh)
+ (def controls (make-controls camera renderer))
+
+ (defn render []
+ (let [delta (clock.getDelta)]
+ (requestAnimationFrame render)
+ (.update controls delta)
+ (renderer.render scene camera)))
+
+ (render)
+
+ nil)
+
+(defn make-final [element-id]
+ (def scene (new THREE.Scene))
+ (scene.add (new THREE.AxisHelper 100))
+
+ (def clock (new THREE.Clock))
+ (def camera (make-camera))
+ (def renderer (make-renderer))
+ (def heightmap (make-heightmap (.val ($ "#input-exponent"))))
+ (def geometry (make-geometry heightmap))
+ (def plane (make-plane geometry))
+
+ (scene.add (make-directional-light))
+ (scene.add (new THREE.AmbientLight 0xffffff 0.05))
+ (scene.add plane)
+
+ (defn refresh []
+ (l "Refreshing ========================================")
+ (scene.remove plane)
+ (set! heightmap (make-heightmap (.val ($ "#input-exponent"))))
+ (set! geometry (make-geometry heightmap))
+ (set! plane (make-plane geometry))
+ (scene.add plane)
+ (l "Generating terrain...")
+ (time (midpoint-displacement-final heightmap))
+ (l "Refreshing geometry...")
+ (time (update-geometry geometry heightmap))
+ (l "Done!"))
+
+ (attach-to-dom renderer element-id refresh)
+ (def controls (make-controls camera renderer))
+
+ (defn render []
+ (let [delta (clock.getDelta)]
+ (requestAnimationFrame render)
+ (.update controls delta)
+ (renderer.render scene camera)))
+
+ (render)
+
+ nil)
+
+
+(defn run []
+ (make-demo "demo-random" random-noise 7)
+ (make-demo "demo-mpd-1" midpoint-displacement-d1 2)
+ (make-demo "demo-mpd-2" midpoint-displacement-d2 2)
+ (make-demo "demo-mpd-3" midpoint-displacement-d3 2)
+ (make-demo "demo-mpd-4" midpoint-displacement 3)
+ (make-final "demo-final")
+ ; (make-demo "demo-midpoint" midpoint-displacement)
+ ; (make-demo "demo-diamond" diamond-square)
+
+ )
+
+($ run)
+
+
+; vim: lw+=do-times lw+=do-nested :
--- a/requirements.txt Fri Feb 19 19:48:12 2016 +0000
+++ b/requirements.txt Sun Feb 28 11:51:50 2016 +0000
@@ -1,5 +1,4 @@
-e git://github.com/django/django.git@stable/1.1.x#egg=django
--e git://github.com/fabric/fabric.git@0.9rc2#egg=fabric
-e svn+http://typogrify.googlecode.com/svn/trunk/#egg=typogrify
-e hg+http://bitbucket.org/cherrypy/cherrypy@cherrypy-3.2.0rc1#egg=cherrypy
-e git://github.com/waylan/python-markdown.git#egg=markdown
--- a/settings.py Fri Feb 19 19:48:12 2016 +0000
+++ b/settings.py Sun Feb 28 11:51:50 2016 +0000
@@ -46,9 +46,6 @@
'.png': ('hydeengine.media_processors.Thumbnail',),
'.jpg': ('hydeengine.media_processors.Thumbnail',),
},
- 'js/': {
- '.wisp': ('custom.processors.Wisp',),
- },
}
CONTENT_PROCESSORS = {}